1*64ffcac2Smacallan /* $NetBSD: gftfb.c,v 1.27 2024/11/13 08:21:16 macallan Exp $ */ 2bd04fd95Smacallan 3bd04fd95Smacallan /* $OpenBSD: sti_pci.c,v 1.7 2009/02/06 22:51:04 miod Exp $ */ 4bd04fd95Smacallan 5bd04fd95Smacallan /* 6bd04fd95Smacallan * Copyright (c) 2006, 2007 Miodrag Vallat. 7dafa96cfSmacallan ^ 2024 Michael Lorenz 8bd04fd95Smacallan * 9bd04fd95Smacallan * Permission to use, copy, modify, and distribute this software for any 10bd04fd95Smacallan * purpose with or without fee is hereby granted, provided that the above 11bd04fd95Smacallan * copyright notice, this permission notice, and the disclaimer below 12bd04fd95Smacallan * appear in all copies. 13bd04fd95Smacallan * 14bd04fd95Smacallan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15bd04fd95Smacallan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16bd04fd95Smacallan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 17bd04fd95Smacallan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18bd04fd95Smacallan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19bd04fd95Smacallan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 20bd04fd95Smacallan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21bd04fd95Smacallan */ 22bd04fd95Smacallan 23dafa96cfSmacallan /* 24dafa96cfSmacallan * a native driver for HP Visualize EG PCI graphics cards 25dafa96cfSmacallan * STI portions are from Miodrag Vallat's sti_pci.c 26dafa96cfSmacallan */ 27dafa96cfSmacallan 28bd04fd95Smacallan #include <sys/param.h> 29bd04fd95Smacallan #include <sys/systm.h> 30bd04fd95Smacallan #include <sys/kmem.h> 31bd04fd95Smacallan #include <sys/device.h> 32a75f9c4bSmacallan #include <sys/mutex.h> 33bd04fd95Smacallan 34bd04fd95Smacallan #include <dev/pci/pcivar.h> 35bd04fd95Smacallan #include <dev/pci/pcireg.h> 36bd04fd95Smacallan #include <dev/pci/pcidevs.h> 37bd04fd95Smacallan #include <dev/pci/pciio.h> 38bd04fd95Smacallan 39bd04fd95Smacallan #include <dev/wscons/wsdisplayvar.h> 40bd04fd95Smacallan #include <dev/wscons/wsconsio.h> 41bd04fd95Smacallan #include <dev/wsfont/wsfont.h> 42bd04fd95Smacallan #include <dev/rasops/rasops.h> 43bd04fd95Smacallan #include <dev/wscons/wsdisplay_vconsvar.h> 44bd04fd95Smacallan #include <dev/pci/wsdisplay_pci.h> 45bd04fd95Smacallan #include <dev/wscons/wsdisplay_glyphcachevar.h> 46bd04fd95Smacallan 47bd04fd95Smacallan #include <dev/ic/stireg.h> 48bd04fd95Smacallan #include <dev/ic/stivar.h> 49bd04fd95Smacallan 50fda0b806Smacallan #include "opt_gftfb.h" 51bd04fd95Smacallan 52fda0b806Smacallan #ifdef GFTFB_DEBUG 53fda0b806Smacallan #define DPRINTF(s) printf(s) 54bd04fd95Smacallan #else 55bd04fd95Smacallan #define DPRINTF(s) /* */ 56bd04fd95Smacallan #endif 57bd04fd95Smacallan 58bd04fd95Smacallan int gftfb_match(device_t, cfdata_t, void *); 59bd04fd95Smacallan void gftfb_attach(device_t, device_t, void *); 60bd04fd95Smacallan 61bd04fd95Smacallan struct gftfb_softc { 62bd04fd95Smacallan device_t sc_dev; 63bd04fd95Smacallan pci_chipset_tag_t sc_pc; 64bd04fd95Smacallan pcitag_t sc_tag; 65bd04fd95Smacallan 66bd04fd95Smacallan /* stuff we need in order to use the STI ROM */ 67bd04fd95Smacallan struct sti_softc sc_base; 68bd04fd95Smacallan struct sti_screen sc_scr; 69bd04fd95Smacallan bus_space_handle_t sc_romh; 70bd04fd95Smacallan 71bd04fd95Smacallan int sc_width, sc_height; 72bd04fd95Smacallan int sc_locked; 73bd04fd95Smacallan struct vcons_screen sc_console_screen; 74bd04fd95Smacallan struct wsscreen_descr sc_defaultscreen_descr; 75bd04fd95Smacallan const struct wsscreen_descr *sc_screens[1]; 76bd04fd95Smacallan struct wsscreen_list sc_screenlist; 77bd04fd95Smacallan struct vcons_data vd; 78bd04fd95Smacallan int sc_mode; 79949bc4d7Smacallan void (*sc_putchar)(void *, int, int, u_int, long); 80bd04fd95Smacallan u_char sc_cmap_red[256]; 81bd04fd95Smacallan u_char sc_cmap_green[256]; 82bd04fd95Smacallan u_char sc_cmap_blue[256]; 83a75f9c4bSmacallan kmutex_t sc_hwlock; 84e867efe1Smacallan uint32_t sc_hwmode; 85e867efe1Smacallan #define HW_FB 0 86e867efe1Smacallan #define HW_FILL 1 87e867efe1Smacallan #define HW_BLIT 2 88a75f9c4bSmacallan /* cursor stuff */ 89a75f9c4bSmacallan int sc_cursor_x, sc_cursor_y; 90a75f9c4bSmacallan int sc_hot_x, sc_hot_y, sc_enabled; 91278b8452Smacallan int sc_video_on; 92bd04fd95Smacallan glyphcache sc_gc; 93bd04fd95Smacallan }; 94bd04fd95Smacallan 95bd04fd95Smacallan CFATTACH_DECL_NEW(gftfb, sizeof(struct gftfb_softc), 96bd04fd95Smacallan gftfb_match, gftfb_attach, NULL, NULL); 97bd04fd95Smacallan 98bd04fd95Smacallan int gftfb_readbar(struct sti_softc *, struct pci_attach_args *, u_int, int); 99bd04fd95Smacallan int gftfb_check_rom(struct gftfb_softc *, struct pci_attach_args *); 100bd04fd95Smacallan void gftfb_enable_rom(struct sti_softc *); 101bd04fd95Smacallan void gftfb_disable_rom(struct sti_softc *); 102bd04fd95Smacallan void gftfb_enable_rom_internal(struct gftfb_softc *); 103bd04fd95Smacallan void gftfb_disable_rom_internal(struct gftfb_softc *); 104bd04fd95Smacallan 105bd04fd95Smacallan void gftfb_setup(struct gftfb_softc *); 106bd04fd95Smacallan 107bd04fd95Smacallan #define ngle_bt458_write(memt, memh, r, v) \ 108bd04fd95Smacallan bus_space_write_stream_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24) 109bd04fd95Smacallan 110bd04fd95Smacallan 11169fecadcSmacallan /* XXX these really need to go into their own header */ 112bd04fd95Smacallan int sti_pci_is_console(struct pci_attach_args *, bus_addr_t *); 113bd04fd95Smacallan int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t, 114bd04fd95Smacallan bus_space_handle_t, bus_addr_t *, u_int); 115bd04fd95Smacallan int sti_screen_setup(struct sti_screen *, int); 116bd04fd95Smacallan void sti_describe_screen(struct sti_softc *, struct sti_screen *); 117bd04fd95Smacallan 118bd04fd95Smacallan #define PCI_ROM_SIZE(mr) \ 119bd04fd95Smacallan (PCI_MAPREG_ROM_ADDR(mr) & -PCI_MAPREG_ROM_ADDR(mr)) 120bd04fd95Smacallan 121bd04fd95Smacallan /* wsdisplay stuff */ 122bd04fd95Smacallan static int gftfb_ioctl(void *, void *, u_long, void *, int, 123bd04fd95Smacallan struct lwp *); 124bd04fd95Smacallan static paddr_t gftfb_mmap(void *, void *, off_t, int); 125bd04fd95Smacallan static void gftfb_init_screen(void *, struct vcons_screen *, int, long *); 126bd04fd95Smacallan 127bd04fd95Smacallan static int gftfb_putcmap(struct gftfb_softc *, struct wsdisplay_cmap *); 128bd04fd95Smacallan static int gftfb_getcmap(struct gftfb_softc *, struct wsdisplay_cmap *); 129bd04fd95Smacallan static void gftfb_restore_palette(struct gftfb_softc *); 130bd04fd95Smacallan static int gftfb_putpalreg(struct gftfb_softc *, uint8_t, uint8_t, 131bd04fd95Smacallan uint8_t, uint8_t); 132bd04fd95Smacallan 133bd04fd95Smacallan static void gftfb_rectfill(struct gftfb_softc *, int, int, int, int, 134bd04fd95Smacallan uint32_t); 135bd04fd95Smacallan static void gftfb_bitblt(void *, int, int, int, int, int, 136bd04fd95Smacallan int, int); 137bd04fd95Smacallan 138bd04fd95Smacallan static void gftfb_cursor(void *, int, int, int); 139bd04fd95Smacallan static void gftfb_putchar(void *, int, int, u_int, long); 1408623c793Smacallan static void gftfb_putchar_aa(void *, int, int, u_int, long); 141bd04fd95Smacallan static void gftfb_copycols(void *, int, int, int, int); 142bd04fd95Smacallan static void gftfb_erasecols(void *, int, int, int, long); 143bd04fd95Smacallan static void gftfb_copyrows(void *, int, int, int); 144bd04fd95Smacallan static void gftfb_eraserows(void *, int, int, long); 145bd04fd95Smacallan 146a75f9c4bSmacallan static void gftfb_move_cursor(struct gftfb_softc *, int, int); 147a75f9c4bSmacallan static int gftfb_do_cursor(struct gftfb_softc *, struct wsdisplay_cursor *); 148a75f9c4bSmacallan 149278b8452Smacallan static void gftfb_set_video(struct gftfb_softc *, int); 150278b8452Smacallan 151bd04fd95Smacallan struct wsdisplay_accessops gftfb_accessops = { 152bd04fd95Smacallan gftfb_ioctl, 153bd04fd95Smacallan gftfb_mmap, 154bd04fd95Smacallan NULL, /* alloc_screen */ 155bd04fd95Smacallan NULL, /* free_screen */ 156bd04fd95Smacallan NULL, /* show_screen */ 157bd04fd95Smacallan NULL, /* load_font */ 158bd04fd95Smacallan NULL, /* pollc */ 159bd04fd95Smacallan NULL /* scroll */ 160bd04fd95Smacallan }; 161bd04fd95Smacallan 162a75f9c4bSmacallan static inline void gftfb_wait_fifo(struct gftfb_softc *, uint32_t); 163a75f9c4bSmacallan 164bd04fd95Smacallan int 165bd04fd95Smacallan gftfb_match(device_t parent, cfdata_t cf, void *aux) 166bd04fd95Smacallan { 167bd04fd95Smacallan struct pci_attach_args *paa = aux; 168bd04fd95Smacallan 169bd04fd95Smacallan if (PCI_VENDOR(paa->pa_id) != PCI_VENDOR_HP) 170bd04fd95Smacallan return 0; 171bd04fd95Smacallan 172bd04fd95Smacallan if (PCI_PRODUCT(paa->pa_id) == PCI_PRODUCT_HP_VISUALIZE_EG) 173bd04fd95Smacallan return 10; /* beat out sti at pci */ 174bd04fd95Smacallan 175bd04fd95Smacallan return 0; 176bd04fd95Smacallan } 177bd04fd95Smacallan 1781dfbd2d1Smacallan static inline uint32_t 1791dfbd2d1Smacallan gftfb_read4(struct gftfb_softc *sc, uint32_t offset) 1801dfbd2d1Smacallan { 1811dfbd2d1Smacallan struct sti_rom *rom = sc->sc_base.sc_rom; 1821dfbd2d1Smacallan bus_space_tag_t memt = rom->memt; 1831dfbd2d1Smacallan bus_space_handle_t memh = rom->regh[2]; 1841dfbd2d1Smacallan return bus_space_read_stream_4(memt, memh, offset); 1851dfbd2d1Smacallan } 1861dfbd2d1Smacallan 1871dfbd2d1Smacallan static inline void 1881dfbd2d1Smacallan gftfb_write4(struct gftfb_softc *sc, uint32_t offset, uint32_t val) 1891dfbd2d1Smacallan { 1901dfbd2d1Smacallan struct sti_rom *rom = sc->sc_base.sc_rom; 1911dfbd2d1Smacallan bus_space_tag_t memt = rom->memt; 1921dfbd2d1Smacallan bus_space_handle_t memh = rom->regh[2]; 1931dfbd2d1Smacallan bus_space_write_stream_4(memt, memh, offset, val); 1941dfbd2d1Smacallan } 1951dfbd2d1Smacallan 1961dfbd2d1Smacallan static inline uint8_t 1971dfbd2d1Smacallan gftfb_read1(struct gftfb_softc *sc, uint32_t offset) 1981dfbd2d1Smacallan { 1991dfbd2d1Smacallan struct sti_rom *rom = sc->sc_base.sc_rom; 2001dfbd2d1Smacallan bus_space_tag_t memt = rom->memt; 2011dfbd2d1Smacallan bus_space_handle_t memh = rom->regh[2]; 2021dfbd2d1Smacallan return bus_space_read_1(memt, memh, offset); 2031dfbd2d1Smacallan } 2041dfbd2d1Smacallan 2051dfbd2d1Smacallan static inline void 2061dfbd2d1Smacallan gftfb_write1(struct gftfb_softc *sc, uint32_t offset, uint8_t val) 2071dfbd2d1Smacallan { 2081dfbd2d1Smacallan struct sti_rom *rom = sc->sc_base.sc_rom; 2091dfbd2d1Smacallan bus_space_tag_t memt = rom->memt; 2101dfbd2d1Smacallan bus_space_handle_t memh = rom->regh[2]; 2111dfbd2d1Smacallan bus_space_write_1(memt, memh, offset, val); 2121dfbd2d1Smacallan } 2131dfbd2d1Smacallan 214bd04fd95Smacallan void 215bd04fd95Smacallan gftfb_attach(device_t parent, device_t self, void *aux) 216bd04fd95Smacallan { 217bd04fd95Smacallan struct gftfb_softc *sc = device_private(self); 218bd04fd95Smacallan struct pci_attach_args *paa = aux; 219bd04fd95Smacallan struct sti_rom *rom; 220bd04fd95Smacallan struct rasops_info *ri; 221bd04fd95Smacallan struct wsemuldisplaydev_attach_args aa; 22269fecadcSmacallan unsigned long defattr = 0; 223a78c8d27Smacallan int ret, is_console = 0; 224bd04fd95Smacallan 225bd04fd95Smacallan sc->sc_dev = self; 226bd04fd95Smacallan 227bd04fd95Smacallan sc->sc_pc = paa->pa_pc; 228bd04fd95Smacallan sc->sc_tag = paa->pa_tag; 229bd04fd95Smacallan sc->sc_base.sc_dev = self; 230bd04fd95Smacallan sc->sc_base.sc_enable_rom = gftfb_enable_rom; 231bd04fd95Smacallan sc->sc_base.sc_disable_rom = gftfb_disable_rom; 232bd04fd95Smacallan 233a75f9c4bSmacallan /* we can *not* be interrupted when doing colour map accesses */ 234a75f9c4bSmacallan mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH); 235a75f9c4bSmacallan 236bd04fd95Smacallan aprint_normal("\n"); 237bd04fd95Smacallan 238bd04fd95Smacallan if (gftfb_check_rom(sc, paa) != 0) 239bd04fd95Smacallan return; 240bd04fd95Smacallan 241bd04fd95Smacallan ret = sti_pci_is_console(paa, sc->sc_base. bases); 242bd04fd95Smacallan if (ret != 0) { 243bd04fd95Smacallan sc->sc_base.sc_flags |= STI_CONSOLE; 244bd04fd95Smacallan is_console = 1; 245bd04fd95Smacallan } 246bd04fd95Smacallan rom = (struct sti_rom *)kmem_zalloc(sizeof(*rom), KM_SLEEP); 247bd04fd95Smacallan rom->rom_softc = &sc->sc_base; 248de3a34d3Smacallan ret = sti_rom_setup(rom, paa->pa_iot, paa->pa_memt, sc->sc_romh, 249de3a34d3Smacallan sc->sc_base.bases, STI_CODEBASE_MAIN); 250bd04fd95Smacallan if (ret != 0) { 251bd04fd95Smacallan kmem_free(rom, sizeof(*rom)); 252bd04fd95Smacallan return; 253bd04fd95Smacallan } 254bd04fd95Smacallan 255bd04fd95Smacallan sc->sc_base.sc_rom = rom; 256bd04fd95Smacallan 257bd04fd95Smacallan sc->sc_scr.scr_rom = sc->sc_base.sc_rom; 258bd04fd95Smacallan ret = sti_screen_setup(&sc->sc_scr, STI_FBMODE); 259bd04fd95Smacallan 260bd04fd95Smacallan sc->sc_width = sc->sc_scr.scr_cfg.scr_width; 261bd04fd95Smacallan sc->sc_height = sc->sc_scr.scr_cfg.scr_height; 262bd04fd95Smacallan 263bd04fd95Smacallan aprint_normal_dev(sc->sc_dev, "%s at %dx%d\n", sc->sc_scr.name, 264bd04fd95Smacallan sc->sc_width, sc->sc_height); 265bd04fd95Smacallan gftfb_setup(sc); 266bd04fd95Smacallan 2671dfbd2d1Smacallan #ifdef GFTFB_DEBUG 2681dfbd2d1Smacallan sc->sc_height -= 200; 2691dfbd2d1Smacallan #endif 2701dfbd2d1Smacallan 271bd04fd95Smacallan sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 272bd04fd95Smacallan "default", 273bd04fd95Smacallan 0, 0, 274bd04fd95Smacallan NULL, 275bd04fd95Smacallan 8, 16, 276bd04fd95Smacallan WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 277bd04fd95Smacallan WSSCREEN_RESIZE, 278bd04fd95Smacallan NULL 279bd04fd95Smacallan }; 280bd04fd95Smacallan 281bd04fd95Smacallan sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 282bd04fd95Smacallan sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 283bd04fd95Smacallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 284bd04fd95Smacallan sc->sc_locked = 0; 285bd04fd95Smacallan 286bd04fd95Smacallan vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 287bd04fd95Smacallan &gftfb_accessops); 288bd04fd95Smacallan sc->vd.init_screen = gftfb_init_screen; 289bd04fd95Smacallan sc->vd.show_screen_cookie = &sc->sc_gc; 290bd04fd95Smacallan sc->vd.show_screen_cb = glyphcache_adapt; 291bd04fd95Smacallan 292bd04fd95Smacallan ri = &sc->sc_console_screen.scr_ri; 293bd04fd95Smacallan 294bd04fd95Smacallan sc->sc_gc.gc_bitblt = gftfb_bitblt; 295bd04fd95Smacallan sc->sc_gc.gc_blitcookie = sc; 29669fecadcSmacallan sc->sc_gc.gc_rop = RopSrc; 29769fecadcSmacallan 298*64ffcac2Smacallan vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); 299bd04fd95Smacallan sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 300bd04fd95Smacallan 301bd04fd95Smacallan sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 302bd04fd95Smacallan sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 303bd04fd95Smacallan sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 304bd04fd95Smacallan sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 30569fecadcSmacallan 306bd04fd95Smacallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 30769fecadcSmacallan sc->sc_scr.fbheight - sc->sc_height - 5, 308711ef3cdSmacallan sc->sc_scr.fbwidth, 309bd04fd95Smacallan ri->ri_font->fontwidth, 310bd04fd95Smacallan ri->ri_font->fontheight, 311bd04fd95Smacallan defattr); 31269fecadcSmacallan 313*64ffcac2Smacallan gftfb_restore_palette(sc); 314949bc4d7Smacallan gftfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 315949bc4d7Smacallan ri->ri_devcmap[(defattr >> 16) & 0xff]); 316949bc4d7Smacallan 317*64ffcac2Smacallan if (is_console) { 318*64ffcac2Smacallan wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 319bd04fd95Smacallan defattr); 320bd04fd95Smacallan 321*64ffcac2Smacallan vcons_replay_msgbuf(&sc->sc_console_screen); 322*64ffcac2Smacallan } 323bd04fd95Smacallan 324bd04fd95Smacallan /* no suspend/resume support yet */ 325bd04fd95Smacallan if (!pmf_device_register(sc->sc_dev, NULL, NULL)) 326bd04fd95Smacallan aprint_error_dev(sc->sc_dev, 327bd04fd95Smacallan "couldn't establish power handler\n"); 328bd04fd95Smacallan 329bd04fd95Smacallan aa.console = is_console; 330bd04fd95Smacallan aa.scrdata = &sc->sc_screenlist; 331bd04fd95Smacallan aa.accessops = &gftfb_accessops; 332bd04fd95Smacallan aa.accesscookie = &sc->vd; 333bd04fd95Smacallan 334bd04fd95Smacallan config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 335bd04fd95Smacallan } 336bd04fd95Smacallan 337bd04fd95Smacallan /* 338bd04fd95Smacallan * Grovel the STI ROM image. 339bd04fd95Smacallan */ 340bd04fd95Smacallan int 341bd04fd95Smacallan gftfb_check_rom(struct gftfb_softc *spc, struct pci_attach_args *pa) 342bd04fd95Smacallan { 343bd04fd95Smacallan struct sti_softc *sc = &spc->sc_base; 344bd04fd95Smacallan pcireg_t address, mask; 345bd04fd95Smacallan bus_space_handle_t romh; 346bd04fd95Smacallan bus_size_t romsize, subsize, stiromsize; 347bd04fd95Smacallan bus_addr_t selected, offs, suboffs; 348bd04fd95Smacallan uint32_t tmp; 349bd04fd95Smacallan int i; 350bd04fd95Smacallan int rc; 351bd04fd95Smacallan 352bd04fd95Smacallan /* sort of inline sti_pci_enable_rom(sc) */ 353bd04fd95Smacallan address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM); 354bd04fd95Smacallan pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, 355bd04fd95Smacallan ~PCI_MAPREG_ROM_ENABLE); 356bd04fd95Smacallan mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM); 357bd04fd95Smacallan address |= PCI_MAPREG_ROM_ENABLE; 358bd04fd95Smacallan pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, address); 359bd04fd95Smacallan sc->sc_flags |= STI_ROM_ENABLED; 360bd04fd95Smacallan /* 361bd04fd95Smacallan * Map the complete ROM for now. 362bd04fd95Smacallan */ 363bd04fd95Smacallan 364bd04fd95Smacallan romsize = PCI_ROM_SIZE(mask); 365bd04fd95Smacallan DPRINTF(("%s: mapping rom @ %lx for %lx\n", __func__, 366bd04fd95Smacallan (long)PCI_MAPREG_ROM_ADDR(address), (long)romsize)); 367bd04fd95Smacallan 368bd04fd95Smacallan rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address), romsize, 369bd04fd95Smacallan 0, &romh); 370bd04fd95Smacallan if (rc != 0) { 371bd04fd95Smacallan aprint_error_dev(sc->sc_dev, "can't map PCI ROM (%d)\n", rc); 372bd04fd95Smacallan goto fail2; 373bd04fd95Smacallan } 374bd04fd95Smacallan 375bd04fd95Smacallan gftfb_disable_rom_internal(spc); 376bd04fd95Smacallan /* 377bd04fd95Smacallan * Iterate over the ROM images, pick the best candidate. 378bd04fd95Smacallan */ 379bd04fd95Smacallan 380bd04fd95Smacallan selected = (bus_addr_t)-1; 381bd04fd95Smacallan for (offs = 0; offs < romsize; offs += subsize) { 382bd04fd95Smacallan gftfb_enable_rom_internal(spc); 383bd04fd95Smacallan /* 384bd04fd95Smacallan * Check for a valid ROM header. 385bd04fd95Smacallan */ 386bd04fd95Smacallan tmp = bus_space_read_4(pa->pa_memt, romh, offs + 0); 387bd04fd95Smacallan tmp = le32toh(tmp); 388bd04fd95Smacallan if (tmp != 0x55aa0000) { 389bd04fd95Smacallan gftfb_disable_rom_internal(spc); 390bd04fd95Smacallan if (offs == 0) { 391bd04fd95Smacallan aprint_error_dev(sc->sc_dev, 392bd04fd95Smacallan "invalid PCI ROM header signature (%08x)\n", 393bd04fd95Smacallan tmp); 394bd04fd95Smacallan rc = EINVAL; 395bd04fd95Smacallan } 396bd04fd95Smacallan break; 397bd04fd95Smacallan } 398bd04fd95Smacallan 399bd04fd95Smacallan /* 400bd04fd95Smacallan * Check ROM type. 401bd04fd95Smacallan */ 402bd04fd95Smacallan tmp = bus_space_read_4(pa->pa_memt, romh, offs + 4); 403bd04fd95Smacallan tmp = le32toh(tmp); 404bd04fd95Smacallan if (tmp != 0x00000001) { /* 1 == STI ROM */ 405bd04fd95Smacallan gftfb_disable_rom_internal(spc); 406bd04fd95Smacallan if (offs == 0) { 407bd04fd95Smacallan aprint_error_dev(sc->sc_dev, 408bd04fd95Smacallan "invalid PCI ROM type (%08x)\n", tmp); 409bd04fd95Smacallan rc = EINVAL; 410bd04fd95Smacallan } 411bd04fd95Smacallan break; 412bd04fd95Smacallan } 413bd04fd95Smacallan 414bd04fd95Smacallan subsize = (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, 415bd04fd95Smacallan offs + 0x0c); 416bd04fd95Smacallan subsize <<= 9; 417bd04fd95Smacallan 418fda0b806Smacallan #ifdef GFTFB_DEBUG 419bd04fd95Smacallan gftfb_disable_rom_internal(spc); 420bd04fd95Smacallan DPRINTF(("ROM offset %08x size %08x type %08x", 421bd04fd95Smacallan (u_int)offs, (u_int)subsize, tmp)); 422bd04fd95Smacallan gftfb_enable_rom_internal(spc); 423bd04fd95Smacallan #endif 424bd04fd95Smacallan 425bd04fd95Smacallan /* 426bd04fd95Smacallan * Check for a valid ROM data structure. 427bd04fd95Smacallan * We do not need it except to know what architecture the ROM 428bd04fd95Smacallan * code is for. 429bd04fd95Smacallan */ 430bd04fd95Smacallan 431bd04fd95Smacallan suboffs = offs +(bus_addr_t)bus_space_read_2(pa->pa_memt, romh, 432bd04fd95Smacallan offs + 0x18); 433bd04fd95Smacallan tmp = bus_space_read_4(pa->pa_memt, romh, suboffs + 0); 434bd04fd95Smacallan tmp = le32toh(tmp); 435bd04fd95Smacallan if (tmp != 0x50434952) { /* PCIR */ 436bd04fd95Smacallan gftfb_disable_rom_internal(spc); 437bd04fd95Smacallan if (offs == 0) { 438bd04fd95Smacallan aprint_error_dev(sc->sc_dev, "invalid PCI data" 439bd04fd95Smacallan " signature (%08x)\n", tmp); 440bd04fd95Smacallan rc = EINVAL; 441bd04fd95Smacallan } else { 442bd04fd95Smacallan DPRINTF((" invalid PCI data signature %08x\n", 443bd04fd95Smacallan tmp)); 444bd04fd95Smacallan continue; 445bd04fd95Smacallan } 446bd04fd95Smacallan } 447bd04fd95Smacallan 448bd04fd95Smacallan tmp = bus_space_read_1(pa->pa_memt, romh, suboffs + 0x14); 449bd04fd95Smacallan gftfb_disable_rom_internal(spc); 450bd04fd95Smacallan DPRINTF((" code %02x", tmp)); 451bd04fd95Smacallan 452bd04fd95Smacallan switch (tmp) { 453bd04fd95Smacallan #ifdef __hppa__ 454bd04fd95Smacallan case 0x10: 455bd04fd95Smacallan if (selected == (bus_addr_t)-1) 456bd04fd95Smacallan selected = offs; 457bd04fd95Smacallan break; 458bd04fd95Smacallan #endif 459bd04fd95Smacallan #ifdef __i386__ 460bd04fd95Smacallan case 0x00: 461bd04fd95Smacallan if (selected == (bus_addr_t)-1) 462bd04fd95Smacallan selected = offs; 463bd04fd95Smacallan break; 464bd04fd95Smacallan #endif 465bd04fd95Smacallan default: 466bd04fd95Smacallan DPRINTF((" (wrong architecture)")); 467bd04fd95Smacallan break; 468bd04fd95Smacallan } 469bd04fd95Smacallan DPRINTF(("%s\n", selected == offs ? " -> SELECTED" : "")); 470bd04fd95Smacallan } 471bd04fd95Smacallan 472bd04fd95Smacallan if (selected == (bus_addr_t)-1) { 473bd04fd95Smacallan if (rc == 0) { 474bd04fd95Smacallan aprint_error_dev(sc->sc_dev, "found no ROM with " 475bd04fd95Smacallan "correct microcode architecture\n"); 476bd04fd95Smacallan rc = ENOEXEC; 477bd04fd95Smacallan } 478bd04fd95Smacallan goto fail; 479bd04fd95Smacallan } 480bd04fd95Smacallan 481bd04fd95Smacallan /* 482bd04fd95Smacallan * Read the STI region BAR assignments. 483bd04fd95Smacallan */ 484bd04fd95Smacallan 485bd04fd95Smacallan gftfb_enable_rom_internal(spc); 486bd04fd95Smacallan offs = selected + 487bd04fd95Smacallan (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, selected + 0x0e); 488bd04fd95Smacallan for (i = 0; i < STI_REGION_MAX; i++) { 489bd04fd95Smacallan rc = gftfb_readbar(sc, pa, i, 490bd04fd95Smacallan bus_space_read_1(pa->pa_memt, romh, offs + i)); 491bd04fd95Smacallan if (rc != 0) 492bd04fd95Smacallan goto fail; 493bd04fd95Smacallan } 494bd04fd95Smacallan 495bd04fd95Smacallan /* 496bd04fd95Smacallan * Find out where the STI ROM itself lies, and its size. 497bd04fd95Smacallan */ 498bd04fd95Smacallan 499bd04fd95Smacallan offs = selected + 500bd04fd95Smacallan (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, selected + 0x08); 501bd04fd95Smacallan stiromsize = (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, 502bd04fd95Smacallan offs + 0x18); 503bd04fd95Smacallan stiromsize = le32toh(stiromsize); 504bd04fd95Smacallan gftfb_disable_rom_internal(spc); 505bd04fd95Smacallan 506bd04fd95Smacallan /* 507bd04fd95Smacallan * Replace our mapping with a smaller mapping of only the area 508bd04fd95Smacallan * we are interested in. 509bd04fd95Smacallan */ 510bd04fd95Smacallan 511bd04fd95Smacallan DPRINTF(("remapping rom @ %lx for %lx\n", 512bd04fd95Smacallan (long)(PCI_MAPREG_ROM_ADDR(address) + offs), (long)stiromsize)); 513bd04fd95Smacallan bus_space_unmap(pa->pa_memt, romh, romsize); 514bd04fd95Smacallan rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address) + offs, 515bd04fd95Smacallan stiromsize, 0, &spc->sc_romh); 516bd04fd95Smacallan if (rc != 0) { 517bd04fd95Smacallan aprint_error_dev(sc->sc_dev, "can't map STI ROM (%d)\n", 518bd04fd95Smacallan rc); 519bd04fd95Smacallan goto fail2; 520bd04fd95Smacallan } 521bd04fd95Smacallan gftfb_disable_rom_internal(spc); 522bd04fd95Smacallan sc->sc_flags &= ~STI_ROM_ENABLED; 523bd04fd95Smacallan 524bd04fd95Smacallan return 0; 525bd04fd95Smacallan 526bd04fd95Smacallan fail: 527bd04fd95Smacallan bus_space_unmap(pa->pa_memt, romh, romsize); 528bd04fd95Smacallan fail2: 529bd04fd95Smacallan gftfb_disable_rom_internal(spc); 530bd04fd95Smacallan 531bd04fd95Smacallan return rc; 532bd04fd95Smacallan } 533bd04fd95Smacallan 534bd04fd95Smacallan /* 535bd04fd95Smacallan * Decode a BAR register. 536bd04fd95Smacallan */ 537bd04fd95Smacallan int 538bd04fd95Smacallan gftfb_readbar(struct sti_softc *sc, struct pci_attach_args *pa, u_int region, 539bd04fd95Smacallan int bar) 540bd04fd95Smacallan { 541bd04fd95Smacallan bus_addr_t addr; 542bd04fd95Smacallan bus_size_t size; 543bd04fd95Smacallan uint32_t cf; 544bd04fd95Smacallan int rc; 545bd04fd95Smacallan 546bd04fd95Smacallan if (bar == 0) { 547bd04fd95Smacallan sc->bases[region] = 0; 548bd04fd95Smacallan return (0); 549bd04fd95Smacallan } 550bd04fd95Smacallan 551bd04fd95Smacallan #ifdef DIAGNOSTIC 552bd04fd95Smacallan if (bar < PCI_MAPREG_START || bar > PCI_MAPREG_PPB_END) { 553bd04fd95Smacallan gftfb_disable_rom(sc); 554bd04fd95Smacallan printf("%s: unexpected bar %02x for region %d\n", 555bd04fd95Smacallan device_xname(sc->sc_dev), bar, region); 556bd04fd95Smacallan gftfb_enable_rom(sc); 557bd04fd95Smacallan } 558bd04fd95Smacallan #endif 559bd04fd95Smacallan 560bd04fd95Smacallan cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar); 561bd04fd95Smacallan 562bd04fd95Smacallan rc = pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar, PCI_MAPREG_TYPE(cf), 563bd04fd95Smacallan &addr, &size, NULL); 564bd04fd95Smacallan 565bd04fd95Smacallan if (rc != 0) { 566bd04fd95Smacallan gftfb_disable_rom(sc); 567bd04fd95Smacallan aprint_error_dev(sc->sc_dev, "invalid bar %02x for region %d\n", 568bd04fd95Smacallan bar, region); 569bd04fd95Smacallan gftfb_enable_rom(sc); 570bd04fd95Smacallan return (rc); 571bd04fd95Smacallan } 572bd04fd95Smacallan 573bd04fd95Smacallan sc->bases[region] = addr; 574bd04fd95Smacallan return (0); 575bd04fd95Smacallan } 576bd04fd95Smacallan 577bd04fd95Smacallan /* 578bd04fd95Smacallan * Enable PCI ROM. 579bd04fd95Smacallan */ 580bd04fd95Smacallan void 581bd04fd95Smacallan gftfb_enable_rom_internal(struct gftfb_softc *spc) 582bd04fd95Smacallan { 583bd04fd95Smacallan pcireg_t address; 584bd04fd95Smacallan 585bd04fd95Smacallan KASSERT(spc != NULL); 586bd04fd95Smacallan 587bd04fd95Smacallan address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM); 588bd04fd95Smacallan address |= PCI_MAPREG_ROM_ENABLE; 589bd04fd95Smacallan pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address); 590bd04fd95Smacallan } 591bd04fd95Smacallan 592bd04fd95Smacallan void 593bd04fd95Smacallan gftfb_enable_rom(struct sti_softc *sc) 594bd04fd95Smacallan { 595bd04fd95Smacallan struct gftfb_softc *spc = device_private(sc->sc_dev); 596bd04fd95Smacallan 597bd04fd95Smacallan if (!ISSET(sc->sc_flags, STI_ROM_ENABLED)) { 598bd04fd95Smacallan gftfb_enable_rom_internal(spc); 599bd04fd95Smacallan } 600bd04fd95Smacallan SET(sc->sc_flags, STI_ROM_ENABLED); 601bd04fd95Smacallan } 602bd04fd95Smacallan 603bd04fd95Smacallan /* 604bd04fd95Smacallan * Disable PCI ROM. 605bd04fd95Smacallan */ 606bd04fd95Smacallan void 607bd04fd95Smacallan gftfb_disable_rom_internal(struct gftfb_softc *spc) 608bd04fd95Smacallan { 609bd04fd95Smacallan pcireg_t address; 610bd04fd95Smacallan 611bd04fd95Smacallan KASSERT(spc != NULL); 612bd04fd95Smacallan 613bd04fd95Smacallan address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM); 614bd04fd95Smacallan address &= ~PCI_MAPREG_ROM_ENABLE; 615bd04fd95Smacallan pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address); 616bd04fd95Smacallan } 617bd04fd95Smacallan 618bd04fd95Smacallan void 619bd04fd95Smacallan gftfb_disable_rom(struct sti_softc *sc) 620bd04fd95Smacallan { 621bd04fd95Smacallan struct gftfb_softc *spc = device_private(sc->sc_dev); 622bd04fd95Smacallan 623bd04fd95Smacallan if (ISSET(sc->sc_flags, STI_ROM_ENABLED)) { 624bd04fd95Smacallan gftfb_disable_rom_internal(spc); 625bd04fd95Smacallan } 626bd04fd95Smacallan CLR(sc->sc_flags, STI_ROM_ENABLED); 627bd04fd95Smacallan } 628bd04fd95Smacallan 62969fecadcSmacallan static inline void 630bd04fd95Smacallan gftfb_wait(struct gftfb_softc *sc) 631bd04fd95Smacallan { 632bd04fd95Smacallan uint8_t stat; 633bd04fd95Smacallan 634bd04fd95Smacallan do { 6351dfbd2d1Smacallan stat = gftfb_read1(sc, NGLE_REG_15b0); 636bd04fd95Smacallan if (stat == 0) 6371dfbd2d1Smacallan stat = gftfb_read1(sc, NGLE_REG_15b0); 638bd04fd95Smacallan } while (stat != 0); 639bd04fd95Smacallan } 640bd04fd95Smacallan 64169fecadcSmacallan static inline void 642bd04fd95Smacallan gftfb_setup_fb(struct gftfb_softc *sc) 643bd04fd95Smacallan { 644bd04fd95Smacallan gftfb_wait(sc); 645bf57f384Smacallan gftfb_write4(sc, NGLE_REG_10, 646bf57f384Smacallan BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINapp0I, 0)); 6471dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x83000300); 648bd04fd95Smacallan gftfb_wait(sc); 6491dfbd2d1Smacallan gftfb_write1(sc, NGLE_REG_16b1, 1); 650e867efe1Smacallan sc->sc_hwmode = HW_FB; 651bd04fd95Smacallan } 652bd04fd95Smacallan 653bd04fd95Smacallan void 654bd04fd95Smacallan gftfb_setup(struct gftfb_softc *sc) 655bd04fd95Smacallan { 656bd04fd95Smacallan struct sti_rom *rom = sc->sc_base.sc_rom; 657bd04fd95Smacallan bus_space_tag_t memt = rom->memt; 658bd04fd95Smacallan bus_space_handle_t memh = rom->regh[2]; 659a75f9c4bSmacallan int i; 660bd04fd95Smacallan 661e867efe1Smacallan sc->sc_hwmode = HW_FB; 662a75f9c4bSmacallan sc->sc_hot_x = 0; 663a75f9c4bSmacallan sc->sc_hot_y = 0; 664a75f9c4bSmacallan sc->sc_enabled = 0; 665278b8452Smacallan sc->sc_video_on = 1; 66669fecadcSmacallan 6675a795c59Smacallan 668bd04fd95Smacallan /* set Bt458 read mask register to all planes */ 669bd04fd95Smacallan gftfb_wait(sc); 670bd04fd95Smacallan ngle_bt458_write(memt, memh, 0x08, 0x04); 671bd04fd95Smacallan ngle_bt458_write(memt, memh, 0x0a, 0xff); 672bd04fd95Smacallan 673bd04fd95Smacallan gftfb_setup_fb(sc); 674bd04fd95Smacallan 675bd04fd95Smacallan /* attr. planes */ 676bd04fd95Smacallan gftfb_wait(sc); 6771dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_11, 0x2ea0d000); 6781dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x23000302); 6791dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_12, NGLE_ARTIST_CMAP0); 6801dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_8, 0xffffffff); 681bd04fd95Smacallan 682bd04fd95Smacallan gftfb_wait(sc); 6831dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_6, 0x00000000); 6841dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_9, 685bd04fd95Smacallan (sc->sc_scr.scr_cfg.scr_width << 16) | sc->sc_scr.scr_cfg.scr_height); 686e867efe1Smacallan /* 687e867efe1Smacallan * blit into offscreen memory to force flush previous - apparently 688e867efe1Smacallan * some chips have a bug this works around 689e867efe1Smacallan */ 6901dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_6, 0x05000000); 6911dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_9, 0x00040001); 692bd04fd95Smacallan 693bd04fd95Smacallan gftfb_wait(sc); 6941dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_12, 0x00000000); 695bd04fd95Smacallan 696bd04fd95Smacallan gftfb_setup_fb(sc); 697bd04fd95Smacallan 698e867efe1Smacallan /* make sure video output is enabled */ 699bd04fd95Smacallan gftfb_wait(sc); 7001dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_21, 7011dfbd2d1Smacallan gftfb_read4(sc, NGLE_REG_21) | 0x0a000000); 7021dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_27, 7031dfbd2d1Smacallan gftfb_read4(sc, NGLE_REG_27) | 0x00800000); 704a75f9c4bSmacallan 705a75f9c4bSmacallan /* initialize cursor sprite */ 706a75f9c4bSmacallan gftfb_wait(sc); 707a75f9c4bSmacallan 708a75f9c4bSmacallan /* cursor mask */ 709a75f9c4bSmacallan gftfb_wait(sc); 7101dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x300); 7111dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 7127706e6e4Smacallan gftfb_write4(sc, NGLE_REG_11, 7137706e6e4Smacallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcmask, 0)); 7141dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_3, 0); 715a75f9c4bSmacallan for (i = 0; i < 64; i++) { 7161dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0xffffffff); 7171dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_5, 0xffffffff); 718a75f9c4bSmacallan } 719a75f9c4bSmacallan 720a75f9c4bSmacallan /* cursor image */ 721a75f9c4bSmacallan gftfb_wait(sc); 7221dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x300); 7231dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 7247706e6e4Smacallan gftfb_write4(sc, NGLE_REG_11, 7257706e6e4Smacallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcursor, 0)); 7261dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_3, 0); 727a75f9c4bSmacallan for (i = 0; i < 64; i++) { 7281dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0xff00ff00); 7291dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_5, 0xff00ff00); 730a75f9c4bSmacallan } 731a75f9c4bSmacallan 732a75f9c4bSmacallan /* colour map */ 733a75f9c4bSmacallan gftfb_wait(sc); 7347706e6e4Smacallan gftfb_write4(sc, NGLE_REG_10, 7357706e6e4Smacallan BA(FractDcd, Otc24, Ots08, Addr24, 0, BINcmap, 0)); 7361dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x03000300); 7371dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 738a75f9c4bSmacallan gftfb_wait(sc); 7391dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_3, 0); 7401dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0); 7411dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0); 7421dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0x000000ff); /* BG */ 7431dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0x00ff0000); /* FG */ 744a75f9c4bSmacallan gftfb_wait(sc); 7451dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_2, 0); 7461dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_26, 0x80008004); 747a75f9c4bSmacallan gftfb_setup_fb(sc); 748a75f9c4bSmacallan 749a75f9c4bSmacallan gftfb_move_cursor(sc, 100, 100); 750a75f9c4bSmacallan 751bd04fd95Smacallan } 752bd04fd95Smacallan 753bd04fd95Smacallan static int 754bd04fd95Smacallan gftfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 755bd04fd95Smacallan struct lwp *l) 756bd04fd95Smacallan { 757bd04fd95Smacallan struct vcons_data *vd = v; 758bd04fd95Smacallan struct gftfb_softc *sc = vd->cookie; 759bd04fd95Smacallan struct wsdisplay_fbinfo *wdf; 760bd04fd95Smacallan struct vcons_screen *ms = vd->active; 761bd04fd95Smacallan 762bd04fd95Smacallan switch (cmd) { 763bd04fd95Smacallan case WSDISPLAYIO_GTYPE: 7645e20e311Smacallan *(u_int *)data = WSDISPLAY_TYPE_STI; 765bd04fd95Smacallan return 0; 766bd04fd95Smacallan 7677f6c1850Smacallan case GCID: 7687f6c1850Smacallan *(u_int *)data = STI_DD_EG; 7697f6c1850Smacallan return 0; 7707f6c1850Smacallan 771bd04fd95Smacallan /* PCI config read/write passthrough. */ 772bd04fd95Smacallan case PCI_IOC_CFGREAD: 773bd04fd95Smacallan case PCI_IOC_CFGWRITE: 774bd04fd95Smacallan return pci_devioctl(sc->sc_pc, sc->sc_tag, 775bd04fd95Smacallan cmd, data, flag, l); 776bd04fd95Smacallan 777bd04fd95Smacallan case WSDISPLAYIO_GET_BUSID: 778bd04fd95Smacallan return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 779bd04fd95Smacallan sc->sc_tag, data); 780bd04fd95Smacallan 781bd04fd95Smacallan case WSDISPLAYIO_GINFO: 782bd04fd95Smacallan if (ms == NULL) 783bd04fd95Smacallan return ENODEV; 784bd04fd95Smacallan wdf = (void *)data; 785bd04fd95Smacallan wdf->height = ms->scr_ri.ri_height; 786bd04fd95Smacallan wdf->width = ms->scr_ri.ri_width; 787bd04fd95Smacallan wdf->depth = ms->scr_ri.ri_depth; 788bd04fd95Smacallan wdf->cmsize = 256; 789bd04fd95Smacallan return 0; 790bd04fd95Smacallan 791bd04fd95Smacallan case WSDISPLAYIO_GETCMAP: 792bd04fd95Smacallan return gftfb_getcmap(sc, 793bd04fd95Smacallan (struct wsdisplay_cmap *)data); 794bd04fd95Smacallan 795bd04fd95Smacallan case WSDISPLAYIO_PUTCMAP: 796bd04fd95Smacallan return gftfb_putcmap(sc, 797bd04fd95Smacallan (struct wsdisplay_cmap *)data); 798bd04fd95Smacallan 799bd04fd95Smacallan case WSDISPLAYIO_LINEBYTES: 800bd04fd95Smacallan *(u_int *)data = 2048; 801bd04fd95Smacallan return 0; 802bd04fd95Smacallan 803bd04fd95Smacallan case WSDISPLAYIO_SMODE: { 804bd04fd95Smacallan int new_mode = *(int*)data; 805bd04fd95Smacallan if (new_mode != sc->sc_mode) { 806bd04fd95Smacallan sc->sc_mode = new_mode; 807bd04fd95Smacallan if(new_mode == WSDISPLAYIO_MODE_EMUL) { 808949bc4d7Smacallan gftfb_setup(sc); 809e867efe1Smacallan gftfb_restore_palette(sc); 81069fecadcSmacallan glyphcache_wipe(&sc->sc_gc); 811949bc4d7Smacallan gftfb_rectfill(sc, 0, 0, sc->sc_width, 812949bc4d7Smacallan sc->sc_height, ms->scr_ri.ri_devcmap[ 813949bc4d7Smacallan (ms->scr_defattr >> 16) & 0xff]); 814bd04fd95Smacallan vcons_redraw_screen(ms); 815278b8452Smacallan gftfb_set_video(sc, 1); 816bd04fd95Smacallan } 817bd04fd95Smacallan } 818bd04fd95Smacallan } 819bd04fd95Smacallan return 0; 820bd04fd95Smacallan 821bd04fd95Smacallan case WSDISPLAYIO_GET_FBINFO: 822bd04fd95Smacallan { 823bd04fd95Smacallan struct wsdisplayio_fbinfo *fbi = data; 8245e20e311Smacallan int ret; 825bd04fd95Smacallan 8265e20e311Smacallan ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 8275e20e311Smacallan fbi->fbi_fbsize = sc->sc_scr.fbheight * 2048; 8285e20e311Smacallan return ret; 829bd04fd95Smacallan } 830a75f9c4bSmacallan 831a75f9c4bSmacallan case WSDISPLAYIO_GCURPOS: 832a75f9c4bSmacallan { 833a75f9c4bSmacallan struct wsdisplay_curpos *cp = (void *)data; 834a75f9c4bSmacallan 835a75f9c4bSmacallan cp->x = sc->sc_cursor_x; 836a75f9c4bSmacallan cp->y = sc->sc_cursor_y; 837bd04fd95Smacallan } 838a75f9c4bSmacallan return 0; 839a75f9c4bSmacallan 840a75f9c4bSmacallan case WSDISPLAYIO_SCURPOS: 841a75f9c4bSmacallan { 842a75f9c4bSmacallan struct wsdisplay_curpos *cp = (void *)data; 843a75f9c4bSmacallan 844a75f9c4bSmacallan gftfb_move_cursor(sc, cp->x, cp->y); 845a75f9c4bSmacallan } 846a75f9c4bSmacallan return 0; 847a75f9c4bSmacallan 848a75f9c4bSmacallan case WSDISPLAYIO_GCURMAX: 849a75f9c4bSmacallan { 850a75f9c4bSmacallan struct wsdisplay_curpos *cp = (void *)data; 851a75f9c4bSmacallan 852a75f9c4bSmacallan cp->x = 64; 853a75f9c4bSmacallan cp->y = 64; 854a75f9c4bSmacallan } 855a75f9c4bSmacallan return 0; 856a75f9c4bSmacallan 857a75f9c4bSmacallan case WSDISPLAYIO_SCURSOR: 858a75f9c4bSmacallan { 859a75f9c4bSmacallan struct wsdisplay_cursor *cursor = (void *)data; 860a75f9c4bSmacallan 861a75f9c4bSmacallan return gftfb_do_cursor(sc, cursor); 862a75f9c4bSmacallan } 863a75f9c4bSmacallan 864278b8452Smacallan case WSDISPLAYIO_SVIDEO: 865278b8452Smacallan gftfb_set_video(sc, *(int *)data); 866278b8452Smacallan return 0; 867278b8452Smacallan case WSDISPLAYIO_GVIDEO: 8681aa0b529Smacallan *(u_int *)data = sc->sc_video_on ? 869278b8452Smacallan WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 8701aa0b529Smacallan return 0; 871278b8452Smacallan } 872bd04fd95Smacallan return EPASSTHROUGH; 873bd04fd95Smacallan } 874bd04fd95Smacallan 875bd04fd95Smacallan static paddr_t 876bd04fd95Smacallan gftfb_mmap(void *v, void *vs, off_t offset, int prot) 877bd04fd95Smacallan { 878bd04fd95Smacallan struct vcons_data *vd = v; 879bd04fd95Smacallan struct gftfb_softc *sc = vd->cookie; 880949bc4d7Smacallan struct sti_rom *rom = sc->sc_base.sc_rom; 881de3a34d3Smacallan paddr_t pa = -1; 882949bc4d7Smacallan 883de3a34d3Smacallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 884bd04fd95Smacallan return -1; 885949bc4d7Smacallan 886e229c7a9Smacallan if (offset >= 0 && offset < sc->sc_scr.fblen) { 887de3a34d3Smacallan /* framebuffer */ 888de3a34d3Smacallan pa = bus_space_mmap(rom->memt, sc->sc_scr.fbaddr, offset, 889de3a34d3Smacallan prot, BUS_SPACE_MAP_LINEAR); 890f020d495Smacallan } else if (offset >= 0x80000000 && offset < 0x80400000) { 891de3a34d3Smacallan /* blitter registers etc. */ 892de3a34d3Smacallan pa = bus_space_mmap(rom->memt, rom->regh[2], 893de3a34d3Smacallan offset - 0x80000000, prot, BUS_SPACE_MAP_LINEAR); 894de3a34d3Smacallan } 895949bc4d7Smacallan 896949bc4d7Smacallan return pa; 897bd04fd95Smacallan } 898bd04fd95Smacallan 899bd04fd95Smacallan static void 900bd04fd95Smacallan gftfb_init_screen(void *cookie, struct vcons_screen *scr, 901bd04fd95Smacallan int existing, long *defattr) 902bd04fd95Smacallan { 903bd04fd95Smacallan struct gftfb_softc *sc = cookie; 904bd04fd95Smacallan struct rasops_info *ri = &scr->scr_ri; 905bd04fd95Smacallan 906bd04fd95Smacallan ri->ri_depth = 8; 907bd04fd95Smacallan ri->ri_width = sc->sc_width; 908bd04fd95Smacallan ri->ri_height = sc->sc_height; 909bd04fd95Smacallan ri->ri_stride = 2048; 91069fecadcSmacallan ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB | 91169fecadcSmacallan RI_ENABLE_ALPHA | RI_PREFER_ALPHA; 91269fecadcSmacallan 913bd04fd95Smacallan ri->ri_bits = (void *)sc->sc_scr.fbaddr; 914bd04fd95Smacallan rasops_init(ri, 0, 0); 915bd04fd95Smacallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 916bd04fd95Smacallan WSSCREEN_RESIZE; 917bd04fd95Smacallan scr->scr_flags |= VCONS_LOADFONT; 918bd04fd95Smacallan 919bd04fd95Smacallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 920bd04fd95Smacallan sc->sc_width / ri->ri_font->fontwidth); 921bd04fd95Smacallan 922bd04fd95Smacallan ri->ri_hw = scr; 923949bc4d7Smacallan sc->sc_putchar = ri->ri_ops.putchar; 924bd04fd95Smacallan ri->ri_ops.copyrows = gftfb_copyrows; 925bd04fd95Smacallan ri->ri_ops.copycols = gftfb_copycols; 926bd04fd95Smacallan ri->ri_ops.eraserows = gftfb_eraserows; 927bd04fd95Smacallan ri->ri_ops.erasecols = gftfb_erasecols; 928bd04fd95Smacallan ri->ri_ops.cursor = gftfb_cursor; 9298623c793Smacallan if (FONT_IS_ALPHA(ri->ri_font)) { 9308623c793Smacallan ri->ri_ops.putchar = gftfb_putchar_aa; 9318623c793Smacallan } else 932bd04fd95Smacallan ri->ri_ops.putchar = gftfb_putchar; 933bd04fd95Smacallan } 934bd04fd95Smacallan 935bd04fd95Smacallan static int 936bd04fd95Smacallan gftfb_putcmap(struct gftfb_softc *sc, struct wsdisplay_cmap *cm) 937bd04fd95Smacallan { 938bd04fd95Smacallan u_char *r, *g, *b; 939bd04fd95Smacallan u_int index = cm->index; 940bd04fd95Smacallan u_int count = cm->count; 941bd04fd95Smacallan int i, error; 942bd04fd95Smacallan u_char rbuf[256], gbuf[256], bbuf[256]; 943bd04fd95Smacallan 944bd04fd95Smacallan if (cm->index >= 256 || cm->count > 256 || 945bd04fd95Smacallan (cm->index + cm->count) > 256) 946bd04fd95Smacallan return EINVAL; 947bd04fd95Smacallan error = copyin(cm->red, &rbuf[index], count); 948bd04fd95Smacallan if (error) 949bd04fd95Smacallan return error; 950bd04fd95Smacallan error = copyin(cm->green, &gbuf[index], count); 951bd04fd95Smacallan if (error) 952bd04fd95Smacallan return error; 953bd04fd95Smacallan error = copyin(cm->blue, &bbuf[index], count); 954bd04fd95Smacallan if (error) 955bd04fd95Smacallan return error; 956bd04fd95Smacallan 957bd04fd95Smacallan memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 958bd04fd95Smacallan memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 959bd04fd95Smacallan memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 960bd04fd95Smacallan 961bd04fd95Smacallan r = &sc->sc_cmap_red[index]; 962bd04fd95Smacallan g = &sc->sc_cmap_green[index]; 963bd04fd95Smacallan b = &sc->sc_cmap_blue[index]; 964bd04fd95Smacallan 965bd04fd95Smacallan for (i = 0; i < count; i++) { 966bd04fd95Smacallan gftfb_putpalreg(sc, index, *r, *g, *b); 967bd04fd95Smacallan index++; 968bd04fd95Smacallan r++, g++, b++; 969bd04fd95Smacallan } 970bd04fd95Smacallan return 0; 971bd04fd95Smacallan } 972bd04fd95Smacallan 973bd04fd95Smacallan static int 974bd04fd95Smacallan gftfb_getcmap(struct gftfb_softc *sc, struct wsdisplay_cmap *cm) 975bd04fd95Smacallan { 976bd04fd95Smacallan u_int index = cm->index; 977bd04fd95Smacallan u_int count = cm->count; 978bd04fd95Smacallan int error; 979bd04fd95Smacallan 980bd04fd95Smacallan if (index >= 255 || count > 256 || index + count > 256) 981bd04fd95Smacallan return EINVAL; 982bd04fd95Smacallan 983bd04fd95Smacallan error = copyout(&sc->sc_cmap_red[index], cm->red, count); 984bd04fd95Smacallan if (error) 985bd04fd95Smacallan return error; 986bd04fd95Smacallan error = copyout(&sc->sc_cmap_green[index], cm->green, count); 987bd04fd95Smacallan if (error) 988bd04fd95Smacallan return error; 989bd04fd95Smacallan error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 990bd04fd95Smacallan if (error) 991bd04fd95Smacallan return error; 992bd04fd95Smacallan 993bd04fd95Smacallan return 0; 994bd04fd95Smacallan } 995bd04fd95Smacallan 996bd04fd95Smacallan static void 997bd04fd95Smacallan gftfb_restore_palette(struct gftfb_softc *sc) 998bd04fd95Smacallan { 999a78c8d27Smacallan uint8_t cmap[768]; 1000a78c8d27Smacallan int i, j; 1001bd04fd95Smacallan 1002a78c8d27Smacallan j = 0; 1003a78c8d27Smacallan rasops_get_cmap(&sc->sc_console_screen.scr_ri, cmap, sizeof(cmap)); 1004bd04fd95Smacallan for (i = 0; i < 256; i++) { 1005a78c8d27Smacallan sc->sc_cmap_red[i] = cmap[j]; 1006a78c8d27Smacallan sc->sc_cmap_green[i] = cmap[j + 1]; 1007a78c8d27Smacallan sc->sc_cmap_blue[i] = cmap[j + 2]; 1008a78c8d27Smacallan gftfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); 1009a78c8d27Smacallan j += 3; 1010bd04fd95Smacallan } 1011bd04fd95Smacallan } 1012bd04fd95Smacallan 1013bd04fd95Smacallan static int 1014bd04fd95Smacallan gftfb_putpalreg(struct gftfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, 1015bd04fd95Smacallan uint8_t b) 1016bd04fd95Smacallan { 1017a75f9c4bSmacallan mutex_enter(&sc->sc_hwlock); 1018bd04fd95Smacallan gftfb_wait(sc); 10197706e6e4Smacallan gftfb_write4(sc, NGLE_REG_10, 10207706e6e4Smacallan BA(FractDcd, Otc24, Ots08, Addr24, 0, BINcmap, 0)); 10211dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x03000300); 10221dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 1023bd04fd95Smacallan 1024bd04fd95Smacallan gftfb_wait(sc); 10251dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_3, 0x400 | (idx << 2)); 10261dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, (r << 16) | (g << 8) | b); 1027bd04fd95Smacallan 10281dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_2, 0x400); 10291dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_26, 0x80000100); 1030bd04fd95Smacallan gftfb_setup_fb(sc); 1031a75f9c4bSmacallan mutex_exit(&sc->sc_hwlock); 1032bd04fd95Smacallan return 0; 1033bd04fd95Smacallan } 1034949bc4d7Smacallan 103569fecadcSmacallan static inline void 1036949bc4d7Smacallan gftfb_wait_fifo(struct gftfb_softc *sc, uint32_t slots) 1037949bc4d7Smacallan { 1038949bc4d7Smacallan uint32_t reg; 1039949bc4d7Smacallan 1040949bc4d7Smacallan do { 10411dfbd2d1Smacallan reg = gftfb_read4(sc, NGLE_REG_34); 1042949bc4d7Smacallan } while (reg < slots); 1043949bc4d7Smacallan } 1044949bc4d7Smacallan 1045949bc4d7Smacallan static void 1046d5d7ec22Smacallan gftfb_rectfill(struct gftfb_softc *sc, int x, int y, int wi, int he, 1047949bc4d7Smacallan uint32_t bg) 1048949bc4d7Smacallan { 1049d5d7ec22Smacallan uint32_t mask = 0xffffffff; 1050949bc4d7Smacallan 1051e867efe1Smacallan if (sc->sc_hwmode != HW_FILL) { 1052d5d7ec22Smacallan gftfb_wait_fifo(sc, 3); 1053949bc4d7Smacallan /* plane mask */ 10541dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xff); 1055949bc4d7Smacallan /* bitmap op */ 10561dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 1057d5d7ec22Smacallan IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 1, 0)); 105869fecadcSmacallan /* dst bitmap access */ 10591dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_11, 1060949bc4d7Smacallan BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 0)); 1061e867efe1Smacallan sc->sc_hwmode = HW_FILL; 1062e867efe1Smacallan } 1063d5d7ec22Smacallan gftfb_wait_fifo(sc, 4); 1064d5d7ec22Smacallan 1065d5d7ec22Smacallan if (wi < 32) 1066d5d7ec22Smacallan mask = 0xffffffff << (32 - wi); 1067d5d7ec22Smacallan /* transfer data */ 10681dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_8, mask); 10691dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_35, bg); 1070949bc4d7Smacallan /* dst XY */ 10711dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_6, (x << 16) | y); 1072949bc4d7Smacallan /* len XY start */ 10731dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_9, (wi << 16) | he); 1074949bc4d7Smacallan 1075949bc4d7Smacallan } 1076949bc4d7Smacallan 10775a795c59Smacallan static void 1078949bc4d7Smacallan gftfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi, 1079949bc4d7Smacallan int he, int rop) 1080949bc4d7Smacallan { 1081949bc4d7Smacallan struct gftfb_softc *sc = cookie; 1082949bc4d7Smacallan 1083dafa96cfSmacallan if (sc->sc_hwmode != HW_BLIT) { 1084949bc4d7Smacallan gftfb_wait(sc); 1085bf57f384Smacallan gftfb_write4(sc, NGLE_REG_10, 1086bf57f384Smacallan BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINapp0I, 0)); 1087dafa96cfSmacallan sc->sc_hwmode = HW_BLIT; 1088dafa96cfSmacallan } 1089949bc4d7Smacallan gftfb_wait_fifo(sc, 5); 1090bf57f384Smacallan gftfb_write4(sc, NGLE_REG_14, 1091bf57f384Smacallan IBOvals(rop, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0)); 10921dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xff); 10931dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_24, (xs << 16) | ys); 10941dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_7, (wi << 16) | he); 10951dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_25, (xd << 16) | yd); 1096949bc4d7Smacallan } 1097949bc4d7Smacallan 1098949bc4d7Smacallan static void 1099755e92edSmacallan gftfb_nuke_cursor(struct rasops_info *ri) 1100755e92edSmacallan { 1101755e92edSmacallan struct vcons_screen *scr = ri->ri_hw; 1102755e92edSmacallan struct gftfb_softc *sc = scr->scr_cookie; 1103755e92edSmacallan int wi, he, x, y; 1104755e92edSmacallan 1105755e92edSmacallan if (ri->ri_flg & RI_CURSOR) { 1106755e92edSmacallan wi = ri->ri_font->fontwidth; 1107755e92edSmacallan he = ri->ri_font->fontheight; 1108755e92edSmacallan x = ri->ri_ccol * wi + ri->ri_xorigin; 1109755e92edSmacallan y = ri->ri_crow * he + ri->ri_yorigin; 1110755e92edSmacallan gftfb_bitblt(sc, x, y, x, y, wi, he, RopInv); 1111755e92edSmacallan ri->ri_flg &= ~RI_CURSOR; 1112755e92edSmacallan } 1113755e92edSmacallan } 1114755e92edSmacallan 1115755e92edSmacallan static void 1116949bc4d7Smacallan gftfb_cursor(void *cookie, int on, int row, int col) 1117949bc4d7Smacallan { 1118949bc4d7Smacallan struct rasops_info *ri = cookie; 1119949bc4d7Smacallan struct vcons_screen *scr = ri->ri_hw; 1120949bc4d7Smacallan struct gftfb_softc *sc = scr->scr_cookie; 1121949bc4d7Smacallan int x, y, wi, he; 1122949bc4d7Smacallan 1123949bc4d7Smacallan wi = ri->ri_font->fontwidth; 1124949bc4d7Smacallan he = ri->ri_font->fontheight; 1125949bc4d7Smacallan 1126949bc4d7Smacallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1127949bc4d7Smacallan if (on) { 1128755e92edSmacallan if (ri->ri_flg & RI_CURSOR) { 1129755e92edSmacallan gftfb_nuke_cursor(ri); 1130755e92edSmacallan } 1131755e92edSmacallan x = col * wi + ri->ri_xorigin; 1132755e92edSmacallan y = row * he + ri->ri_yorigin; 1133949bc4d7Smacallan gftfb_bitblt(sc, x, y, x, y, wi, he, RopInv); 1134949bc4d7Smacallan ri->ri_flg |= RI_CURSOR; 1135949bc4d7Smacallan } 1136755e92edSmacallan ri->ri_crow = row; 1137755e92edSmacallan ri->ri_ccol = col; 1138755e92edSmacallan } else 1139755e92edSmacallan { 1140755e92edSmacallan ri->ri_crow = row; 1141755e92edSmacallan ri->ri_ccol = col; 1142755e92edSmacallan ri->ri_flg &= ~RI_CURSOR; 1143949bc4d7Smacallan } 1144949bc4d7Smacallan 1145949bc4d7Smacallan } 1146949bc4d7Smacallan 1147949bc4d7Smacallan static void 1148949bc4d7Smacallan gftfb_putchar(void *cookie, int row, int col, u_int c, long attr) 1149949bc4d7Smacallan { 1150949bc4d7Smacallan struct rasops_info *ri = cookie; 1151949bc4d7Smacallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1152949bc4d7Smacallan struct vcons_screen *scr = ri->ri_hw; 1153949bc4d7Smacallan struct gftfb_softc *sc = scr->scr_cookie; 11548623c793Smacallan void *data; 11558623c793Smacallan int i, x, y, wi, he, rv = GC_NOPE; 11568623c793Smacallan uint32_t bg, fg, mask; 11578623c793Smacallan 11588623c793Smacallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 11598623c793Smacallan return; 11608623c793Smacallan 11618623c793Smacallan if (!CHAR_IN_FONT(c, font)) 11628623c793Smacallan return; 11638623c793Smacallan 11648623c793Smacallan if (row == ri->ri_crow && col == ri->ri_ccol) { 11658623c793Smacallan ri->ri_flg &= ~RI_CURSOR; 11668623c793Smacallan } 11678623c793Smacallan 11688623c793Smacallan wi = font->fontwidth; 11698623c793Smacallan he = font->fontheight; 11708623c793Smacallan 11718623c793Smacallan x = ri->ri_xorigin + col * wi; 11728623c793Smacallan y = ri->ri_yorigin + row * he; 11738623c793Smacallan 11748623c793Smacallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 11758623c793Smacallan 11768623c793Smacallan /* if we're drawing a space we're done here */ 11778623c793Smacallan if (c == 0x20) { 11788623c793Smacallan gftfb_rectfill(sc, x, y, wi, he, bg); 11798623c793Smacallan return; 11808623c793Smacallan } 11818623c793Smacallan 11828623c793Smacallan fg = ri->ri_devcmap[(attr >> 24) & 0x0f]; 11838623c793Smacallan 11848623c793Smacallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 11858623c793Smacallan if (rv == GC_OK) 11868623c793Smacallan return; 11878623c793Smacallan 11888623c793Smacallan /* clear the character cell */ 11898623c793Smacallan gftfb_rectfill(sc, x, y, wi, he, bg); 11908623c793Smacallan 11918623c793Smacallan data = WSFONT_GLYPH(c, font); 11928623c793Smacallan 11938623c793Smacallan /* 11948623c793Smacallan * we're in rectangle mode with transparency enabled from the call to 11958623c793Smacallan * gftfb_rectfill() above, so all we need to do is reset the starting 11968623c793Smacallan * cordinates, then hammer mask and size/start. Starting coordinates 11978623c793Smacallan * will automatically move down the y-axis 11988623c793Smacallan */ 11998623c793Smacallan gftfb_wait_fifo(sc, 2); 12008623c793Smacallan 12018623c793Smacallan /* character colour */ 12028623c793Smacallan gftfb_write4(sc, NGLE_REG_35, fg); 12038623c793Smacallan /* dst XY */ 12048623c793Smacallan gftfb_write4(sc, NGLE_REG_6, (x << 16) | y); 12058623c793Smacallan 12068623c793Smacallan if (ri->ri_font->stride == 1) { 12078623c793Smacallan uint8_t *data8 = data; 12088623c793Smacallan for (i = 0; i < he; i++) { 12098623c793Smacallan gftfb_wait_fifo(sc, 2); 12108623c793Smacallan mask = *data8; 12118623c793Smacallan gftfb_write4(sc, NGLE_REG_8, mask << 24); 12128623c793Smacallan gftfb_write4(sc, NGLE_REG_9, (wi << 16) | 1); 12138623c793Smacallan data8++; 12148623c793Smacallan } 12158623c793Smacallan } else { 12168623c793Smacallan uint16_t *data16 = data; 12178623c793Smacallan for (i = 0; i < he; i++) { 12188623c793Smacallan gftfb_wait_fifo(sc, 2); 12198623c793Smacallan mask = *data16; 12208623c793Smacallan gftfb_write4(sc, NGLE_REG_8, mask << 16); 12218623c793Smacallan gftfb_write4(sc, NGLE_REG_9, (wi << 16) | 1); 12228623c793Smacallan data16++; 12238623c793Smacallan } 12248623c793Smacallan } 12258623c793Smacallan 12268623c793Smacallan if (rv == GC_ADD) 12278623c793Smacallan glyphcache_add(&sc->sc_gc, c, x, y); 12288623c793Smacallan } 12298623c793Smacallan 12308623c793Smacallan static void 12318623c793Smacallan gftfb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 12328623c793Smacallan { 12338623c793Smacallan struct rasops_info *ri = cookie; 12348623c793Smacallan struct wsdisplay_font *font = PICK_FONT(ri, c); 12358623c793Smacallan struct vcons_screen *scr = ri->ri_hw; 12368623c793Smacallan struct gftfb_softc *sc = scr->scr_cookie; 123769fecadcSmacallan int x, y, wi, he, rv = GC_NOPE; 123869fecadcSmacallan uint32_t bg; 12395a795c59Smacallan 1240949bc4d7Smacallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1241949bc4d7Smacallan return; 1242949bc4d7Smacallan 1243949bc4d7Smacallan if (!CHAR_IN_FONT(c, font)) 1244949bc4d7Smacallan return; 124569fecadcSmacallan 1246755e92edSmacallan if (row == ri->ri_crow && col == ri->ri_ccol) { 1247755e92edSmacallan ri->ri_flg &= ~RI_CURSOR; 1248755e92edSmacallan } 1249755e92edSmacallan 125069fecadcSmacallan wi = font->fontwidth; 125169fecadcSmacallan he = font->fontheight; 125269fecadcSmacallan 125369fecadcSmacallan x = ri->ri_xorigin + col * wi; 125469fecadcSmacallan y = ri->ri_yorigin + row * he; 12555a795c59Smacallan 125669fecadcSmacallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 125769fecadcSmacallan 125869fecadcSmacallan if (c == 0x20) { 125969fecadcSmacallan gftfb_rectfill(sc, x, y, wi, he, bg); 126069fecadcSmacallan return; 126169fecadcSmacallan } 12625a795c59Smacallan 126369fecadcSmacallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 126469fecadcSmacallan if (rv == GC_OK) 126569fecadcSmacallan return; 126669fecadcSmacallan 1267e867efe1Smacallan if (sc->sc_hwmode != HW_FB) gftfb_setup_fb(sc); 1268949bc4d7Smacallan sc->sc_putchar(cookie, row, col, c, attr); 126969fecadcSmacallan 127069fecadcSmacallan if (rv == GC_ADD) 127169fecadcSmacallan glyphcache_add(&sc->sc_gc, c, x, y); 1272949bc4d7Smacallan } 1273949bc4d7Smacallan 1274949bc4d7Smacallan static void 1275949bc4d7Smacallan gftfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1276949bc4d7Smacallan { 1277949bc4d7Smacallan struct rasops_info *ri = cookie; 1278949bc4d7Smacallan struct vcons_screen *scr = ri->ri_hw; 1279949bc4d7Smacallan struct gftfb_softc *sc = scr->scr_cookie; 1280949bc4d7Smacallan int32_t xs, xd, y, width, height; 1281949bc4d7Smacallan 1282949bc4d7Smacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1283755e92edSmacallan if (ri->ri_crow == row && 1284755e92edSmacallan (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) && 1285755e92edSmacallan (ri->ri_flg & RI_CURSOR)) { 1286755e92edSmacallan gftfb_nuke_cursor(ri); 1287755e92edSmacallan } 1288755e92edSmacallan 1289949bc4d7Smacallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1290949bc4d7Smacallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1291949bc4d7Smacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1292949bc4d7Smacallan width = ri->ri_font->fontwidth * ncols; 1293949bc4d7Smacallan height = ri->ri_font->fontheight; 1294949bc4d7Smacallan gftfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc); 1295755e92edSmacallan if (ri->ri_crow == row && 1296755e92edSmacallan (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols))) 1297755e92edSmacallan ri->ri_flg &= ~RI_CURSOR; 1298949bc4d7Smacallan } 1299949bc4d7Smacallan } 1300949bc4d7Smacallan 1301949bc4d7Smacallan static void 1302949bc4d7Smacallan gftfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1303949bc4d7Smacallan { 1304949bc4d7Smacallan struct rasops_info *ri = cookie; 1305949bc4d7Smacallan struct vcons_screen *scr = ri->ri_hw; 1306949bc4d7Smacallan struct gftfb_softc *sc = scr->scr_cookie; 1307949bc4d7Smacallan int32_t x, y, width, height, fg, bg, ul; 1308949bc4d7Smacallan 1309949bc4d7Smacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1310949bc4d7Smacallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1311949bc4d7Smacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1312949bc4d7Smacallan width = ri->ri_font->fontwidth * ncols; 1313949bc4d7Smacallan height = ri->ri_font->fontheight; 1314949bc4d7Smacallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1315949bc4d7Smacallan 1316949bc4d7Smacallan gftfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1317755e92edSmacallan if (ri->ri_crow == row && 1318755e92edSmacallan (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols))) 1319755e92edSmacallan ri->ri_flg &= ~RI_CURSOR; 1320949bc4d7Smacallan } 1321949bc4d7Smacallan } 1322949bc4d7Smacallan 1323949bc4d7Smacallan static void 1324949bc4d7Smacallan gftfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1325949bc4d7Smacallan { 1326949bc4d7Smacallan struct rasops_info *ri = cookie; 1327949bc4d7Smacallan struct vcons_screen *scr = ri->ri_hw; 1328949bc4d7Smacallan struct gftfb_softc *sc = scr->scr_cookie; 1329949bc4d7Smacallan int32_t x, ys, yd, width, height; 1330949bc4d7Smacallan 1331949bc4d7Smacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1332755e92edSmacallan if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) && 1333755e92edSmacallan (ri->ri_flg & RI_CURSOR)) { 1334755e92edSmacallan gftfb_nuke_cursor(ri); 1335755e92edSmacallan } 1336949bc4d7Smacallan x = ri->ri_xorigin; 1337949bc4d7Smacallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1338949bc4d7Smacallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1339949bc4d7Smacallan width = ri->ri_emuwidth; 1340949bc4d7Smacallan height = ri->ri_font->fontheight * nrows; 1341949bc4d7Smacallan gftfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc); 1342755e92edSmacallan if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows)) 1343755e92edSmacallan ri->ri_flg &= ~RI_CURSOR; 1344949bc4d7Smacallan } 1345949bc4d7Smacallan } 1346949bc4d7Smacallan 1347949bc4d7Smacallan static void 1348949bc4d7Smacallan gftfb_eraserows(void *cookie, int row, int nrows, long fillattr) 1349949bc4d7Smacallan { 1350949bc4d7Smacallan struct rasops_info *ri = cookie; 1351949bc4d7Smacallan struct vcons_screen *scr = ri->ri_hw; 1352949bc4d7Smacallan struct gftfb_softc *sc = scr->scr_cookie; 1353949bc4d7Smacallan int32_t x, y, width, height, fg, bg, ul; 1354949bc4d7Smacallan 1355949bc4d7Smacallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1356949bc4d7Smacallan x = ri->ri_xorigin; 1357949bc4d7Smacallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1358949bc4d7Smacallan width = ri->ri_emuwidth; 1359949bc4d7Smacallan height = ri->ri_font->fontheight * nrows; 1360949bc4d7Smacallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1361949bc4d7Smacallan 1362949bc4d7Smacallan gftfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1363755e92edSmacallan 1364755e92edSmacallan if (ri->ri_crow >= row && ri->ri_crow < (row + nrows)) 1365755e92edSmacallan ri->ri_flg &= ~RI_CURSOR; 1366949bc4d7Smacallan } 1367949bc4d7Smacallan } 1368a75f9c4bSmacallan 1369a75f9c4bSmacallan /* 1370a75f9c4bSmacallan * cursor sprite handling 1371a75f9c4bSmacallan * like most hw info, xf86 3.3 -> nglehdw.h was used as documentation 1372a75f9c4bSmacallan * problem is, the PCI EG doesn't quite behave like an S9000_ID_ARTIST 1373a75f9c4bSmacallan * the cursor position register bahaves like the one on HCRX while using 1374a75f9c4bSmacallan * the same address as Artist, incuding the enable bit and weird handling 1375a75f9c4bSmacallan * of negative coordinates. The rest of it, colour map, sprite image etc., 1376a75f9c4bSmacallan * behave like Artist. 1377a75f9c4bSmacallan */ 1378a75f9c4bSmacallan 1379a75f9c4bSmacallan static void 1380a75f9c4bSmacallan gftfb_move_cursor(struct gftfb_softc *sc, int x, int y) 1381a75f9c4bSmacallan { 1382a75f9c4bSmacallan uint32_t pos; 1383a75f9c4bSmacallan 1384a75f9c4bSmacallan sc->sc_cursor_x = x; 1385a75f9c4bSmacallan x -= sc->sc_hot_x; 1386a75f9c4bSmacallan sc->sc_cursor_y = y; 1387a75f9c4bSmacallan y -= sc->sc_hot_y; 1388a75f9c4bSmacallan 1389a75f9c4bSmacallan if (x < 0) x = 0x1000 - x; 1390a75f9c4bSmacallan if (y < 0) y = 0x1000 - y; 1391a75f9c4bSmacallan pos = (x << 16) | y; 1392a75f9c4bSmacallan if (sc->sc_enabled) pos |= 0x80000000; 1393a75f9c4bSmacallan gftfb_wait(sc); 13941dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_17, pos); 13951dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_18, 0x80); 1396a75f9c4bSmacallan } 1397a75f9c4bSmacallan 1398a75f9c4bSmacallan static int 1399a75f9c4bSmacallan gftfb_do_cursor(struct gftfb_softc *sc, struct wsdisplay_cursor *cur) 1400a75f9c4bSmacallan { 1401a75f9c4bSmacallan if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1402a75f9c4bSmacallan 1403a75f9c4bSmacallan sc->sc_enabled = cur->enable; 1404a75f9c4bSmacallan cur->which |= WSDISPLAY_CURSOR_DOPOS; 1405a75f9c4bSmacallan } 1406a75f9c4bSmacallan if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1407a75f9c4bSmacallan 1408a75f9c4bSmacallan sc->sc_hot_x = cur->hot.x; 1409a75f9c4bSmacallan sc->sc_hot_y = cur->hot.y; 1410a75f9c4bSmacallan cur->which |= WSDISPLAY_CURSOR_DOPOS; 1411a75f9c4bSmacallan } 1412a75f9c4bSmacallan if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1413a75f9c4bSmacallan 1414a75f9c4bSmacallan gftfb_move_cursor(sc, cur->pos.x, cur->pos.y); 1415a75f9c4bSmacallan } 1416a75f9c4bSmacallan if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1417a75f9c4bSmacallan uint32_t rgb; 1418a75f9c4bSmacallan uint8_t r[2], g[2], b[2]; 1419a75f9c4bSmacallan 1420a75f9c4bSmacallan copyin(cur->cmap.blue, b, 2); 1421a75f9c4bSmacallan copyin(cur->cmap.green, g, 2); 1422a75f9c4bSmacallan copyin(cur->cmap.red, r, 2); 1423a75f9c4bSmacallan mutex_enter(&sc->sc_hwlock); 1424a75f9c4bSmacallan gftfb_wait(sc); 14257706e6e4Smacallan gftfb_write4(sc, NGLE_REG_10, 14267706e6e4Smacallan BA(FractDcd, Otc24, Ots08, Addr24, 0, BINcmap, 0)); 14271dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x03000300); 14281dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 1429a75f9c4bSmacallan gftfb_wait(sc); 14301dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_3, 0); 14311dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0); 14321dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, 0); 1433a75f9c4bSmacallan rgb = (r[0] << 16) | (g[0] << 8) | b[0]; 14341dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, rgb); /* BG */ 1435a75f9c4bSmacallan rgb = (r[1] << 16) | (g[1] << 8) | b[1]; 14361dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, rgb); /* FG */ 14371dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_2, 0); 14381dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_26, 0x80008004); 1439a75f9c4bSmacallan gftfb_setup_fb(sc); 1440a75f9c4bSmacallan mutex_exit(&sc->sc_hwlock); 1441a75f9c4bSmacallan 1442a75f9c4bSmacallan } 1443a75f9c4bSmacallan if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1444a75f9c4bSmacallan uint32_t buffer[128], latch, tmp; 1445a75f9c4bSmacallan int i; 1446a75f9c4bSmacallan 1447a75f9c4bSmacallan copyin(cur->mask, buffer, 512); 1448a75f9c4bSmacallan gftfb_wait(sc); 14491dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x300); 14501dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 14517706e6e4Smacallan gftfb_write4(sc, NGLE_REG_11, 14527706e6e4Smacallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcmask, 0)); 14531dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_3, 0); 1454a75f9c4bSmacallan for (i = 0; i < 128; i += 2) { 1455a75f9c4bSmacallan latch = 0; 1456a75f9c4bSmacallan tmp = buffer[i] & 0x80808080; 1457a75f9c4bSmacallan latch |= tmp >> 7; 1458a75f9c4bSmacallan tmp = buffer[i] & 0x40404040; 1459a75f9c4bSmacallan latch |= tmp >> 5; 1460a75f9c4bSmacallan tmp = buffer[i] & 0x20202020; 1461a75f9c4bSmacallan latch |= tmp >> 3; 1462a75f9c4bSmacallan tmp = buffer[i] & 0x10101010; 1463a75f9c4bSmacallan latch |= tmp >> 1; 1464a75f9c4bSmacallan tmp = buffer[i] & 0x08080808; 1465a75f9c4bSmacallan latch |= tmp << 1; 1466a75f9c4bSmacallan tmp = buffer[i] & 0x04040404; 1467a75f9c4bSmacallan latch |= tmp << 3; 1468a75f9c4bSmacallan tmp = buffer[i] & 0x02020202; 1469a75f9c4bSmacallan latch |= tmp << 5; 1470a75f9c4bSmacallan tmp = buffer[i] & 0x01010101; 1471a75f9c4bSmacallan latch |= tmp << 7; 14721dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, latch); 1473a75f9c4bSmacallan latch = 0; 1474a75f9c4bSmacallan tmp = buffer[i + 1] & 0x80808080; 1475a75f9c4bSmacallan latch |= tmp >> 7; 1476a75f9c4bSmacallan tmp = buffer[i + 1] & 0x40404040; 1477a75f9c4bSmacallan latch |= tmp >> 5; 1478a75f9c4bSmacallan tmp = buffer[i + 1] & 0x20202020; 1479a75f9c4bSmacallan latch |= tmp >> 3; 1480a75f9c4bSmacallan tmp = buffer[i + 1] & 0x10101010; 1481a75f9c4bSmacallan latch |= tmp >> 1; 1482a75f9c4bSmacallan tmp = buffer[i + 1] & 0x08080808; 1483a75f9c4bSmacallan latch |= tmp << 1; 1484a75f9c4bSmacallan tmp = buffer[i + 1] & 0x04040404; 1485a75f9c4bSmacallan latch |= tmp << 3; 1486a75f9c4bSmacallan tmp = buffer[i + 1] & 0x02020202; 1487a75f9c4bSmacallan latch |= tmp << 5; 1488a75f9c4bSmacallan tmp = buffer[i + 1] & 0x01010101; 1489a75f9c4bSmacallan latch |= tmp << 7; 14901dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_5, latch); 1491a75f9c4bSmacallan } 1492a75f9c4bSmacallan 1493a75f9c4bSmacallan copyin(cur->image, buffer, 512); 1494a75f9c4bSmacallan gftfb_wait(sc); 14951dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_14, 0x300); 14961dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 14977706e6e4Smacallan gftfb_write4(sc, NGLE_REG_11, 14987706e6e4Smacallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcursor, 0)); 14991dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_3, 0); 1500a75f9c4bSmacallan for (i = 0; i < 128; i += 2) { 1501a75f9c4bSmacallan latch = 0; 1502a75f9c4bSmacallan tmp = buffer[i] & 0x80808080; 1503a75f9c4bSmacallan latch |= tmp >> 7; 1504a75f9c4bSmacallan tmp = buffer[i] & 0x40404040; 1505a75f9c4bSmacallan latch |= tmp >> 5; 1506a75f9c4bSmacallan tmp = buffer[i] & 0x20202020; 1507a75f9c4bSmacallan latch |= tmp >> 3; 1508a75f9c4bSmacallan tmp = buffer[i] & 0x10101010; 1509a75f9c4bSmacallan latch |= tmp >> 1; 1510a75f9c4bSmacallan tmp = buffer[i] & 0x08080808; 1511a75f9c4bSmacallan latch |= tmp << 1; 1512a75f9c4bSmacallan tmp = buffer[i] & 0x04040404; 1513a75f9c4bSmacallan latch |= tmp << 3; 1514a75f9c4bSmacallan tmp = buffer[i] & 0x02020202; 1515a75f9c4bSmacallan latch |= tmp << 5; 1516a75f9c4bSmacallan tmp = buffer[i] & 0x01010101; 1517a75f9c4bSmacallan latch |= tmp << 7; 15181dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_4, latch); 1519a75f9c4bSmacallan latch = 0; 1520a75f9c4bSmacallan tmp = buffer[i + 1] & 0x80808080; 1521a75f9c4bSmacallan latch |= tmp >> 7; 1522a75f9c4bSmacallan tmp = buffer[i + 1] & 0x40404040; 1523a75f9c4bSmacallan latch |= tmp >> 5; 1524a75f9c4bSmacallan tmp = buffer[i + 1] & 0x20202020; 1525a75f9c4bSmacallan latch |= tmp >> 3; 1526a75f9c4bSmacallan tmp = buffer[i + 1] & 0x10101010; 1527a75f9c4bSmacallan latch |= tmp >> 1; 1528a75f9c4bSmacallan tmp = buffer[i + 1] & 0x08080808; 1529a75f9c4bSmacallan latch |= tmp << 1; 1530a75f9c4bSmacallan tmp = buffer[i + 1] & 0x04040404; 1531a75f9c4bSmacallan latch |= tmp << 3; 1532a75f9c4bSmacallan tmp = buffer[i + 1] & 0x02020202; 1533a75f9c4bSmacallan latch |= tmp << 5; 1534a75f9c4bSmacallan tmp = buffer[i + 1] & 0x01010101; 1535a75f9c4bSmacallan latch |= tmp << 7; 15361dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_5, latch); 1537a75f9c4bSmacallan } 1538a75f9c4bSmacallan gftfb_setup_fb(sc); 1539a75f9c4bSmacallan } 1540a75f9c4bSmacallan 1541a75f9c4bSmacallan return 0; 1542a75f9c4bSmacallan } 1543278b8452Smacallan 1544278b8452Smacallan static void 1545278b8452Smacallan gftfb_set_video(struct gftfb_softc *sc, int on) 1546278b8452Smacallan { 1547278b8452Smacallan if (sc->sc_video_on == on) 1548278b8452Smacallan return; 1549278b8452Smacallan 1550278b8452Smacallan sc->sc_video_on = on; 1551278b8452Smacallan 1552278b8452Smacallan gftfb_wait(sc); 1553278b8452Smacallan if (on) { 15541dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_21, 15551dfbd2d1Smacallan gftfb_read4(sc, NGLE_REG_21) | 0x0a000000); 15561dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_27, 15571dfbd2d1Smacallan gftfb_read4(sc, NGLE_REG_27) | 0x00800000); 1558278b8452Smacallan } else { 15591dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_21, 15601dfbd2d1Smacallan gftfb_read4(sc, NGLE_REG_21) & ~0x0a000000); 15611dfbd2d1Smacallan gftfb_write4(sc, NGLE_REG_27, 15621dfbd2d1Smacallan gftfb_read4(sc, NGLE_REG_27) & ~0x00800000); 1563278b8452Smacallan } 1564278b8452Smacallan } 1565