1 1.29 macallan /* $NetBSD: gftfb.c,v 1.29 2025/03/11 06:04:19 macallan Exp $ */ 2 1.1 macallan 3 1.1 macallan /* $OpenBSD: sti_pci.c,v 1.7 2009/02/06 22:51:04 miod Exp $ */ 4 1.1 macallan 5 1.1 macallan /* 6 1.1 macallan * Copyright (c) 2006, 2007 Miodrag Vallat. 7 1.6 macallan ^ 2024 Michael Lorenz 8 1.1 macallan * 9 1.1 macallan * Permission to use, copy, modify, and distribute this software for any 10 1.1 macallan * purpose with or without fee is hereby granted, provided that the above 11 1.1 macallan * copyright notice, this permission notice, and the disclaimer below 12 1.1 macallan * appear in all copies. 13 1.1 macallan * 14 1.1 macallan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15 1.1 macallan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16 1.1 macallan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 17 1.1 macallan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 1.1 macallan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19 1.1 macallan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 20 1.1 macallan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 1.1 macallan */ 22 1.1 macallan 23 1.6 macallan /* 24 1.6 macallan * a native driver for HP Visualize EG PCI graphics cards 25 1.6 macallan * STI portions are from Miodrag Vallat's sti_pci.c 26 1.6 macallan */ 27 1.6 macallan 28 1.1 macallan #include <sys/param.h> 29 1.1 macallan #include <sys/systm.h> 30 1.1 macallan #include <sys/kmem.h> 31 1.1 macallan #include <sys/device.h> 32 1.7 macallan #include <sys/mutex.h> 33 1.1 macallan 34 1.1 macallan #include <dev/pci/pcivar.h> 35 1.1 macallan #include <dev/pci/pcireg.h> 36 1.1 macallan #include <dev/pci/pcidevs.h> 37 1.1 macallan #include <dev/pci/pciio.h> 38 1.1 macallan 39 1.1 macallan #include <dev/wscons/wsdisplayvar.h> 40 1.1 macallan #include <dev/wscons/wsconsio.h> 41 1.1 macallan #include <dev/wsfont/wsfont.h> 42 1.1 macallan #include <dev/rasops/rasops.h> 43 1.1 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 44 1.1 macallan #include <dev/pci/wsdisplay_pci.h> 45 1.1 macallan #include <dev/wscons/wsdisplay_glyphcachevar.h> 46 1.1 macallan 47 1.1 macallan #include <dev/ic/stireg.h> 48 1.1 macallan #include <dev/ic/stivar.h> 49 1.1 macallan 50 1.15 macallan #include "opt_gftfb.h" 51 1.1 macallan 52 1.15 macallan #ifdef GFTFB_DEBUG 53 1.15 macallan #define DPRINTF(s) printf(s) 54 1.1 macallan #else 55 1.15 macallan #define DPRINTF(s) /* */ 56 1.1 macallan #endif 57 1.1 macallan 58 1.1 macallan int gftfb_match(device_t, cfdata_t, void *); 59 1.1 macallan void gftfb_attach(device_t, device_t, void *); 60 1.1 macallan 61 1.1 macallan struct gftfb_softc { 62 1.1 macallan device_t sc_dev; 63 1.1 macallan pci_chipset_tag_t sc_pc; 64 1.1 macallan pcitag_t sc_tag; 65 1.1 macallan 66 1.1 macallan /* stuff we need in order to use the STI ROM */ 67 1.1 macallan struct sti_softc sc_base; 68 1.1 macallan struct sti_screen sc_scr; 69 1.1 macallan bus_space_handle_t sc_romh; 70 1.1 macallan 71 1.1 macallan int sc_width, sc_height; 72 1.1 macallan int sc_locked; 73 1.1 macallan struct vcons_screen sc_console_screen; 74 1.1 macallan struct wsscreen_descr sc_defaultscreen_descr; 75 1.1 macallan const struct wsscreen_descr *sc_screens[1]; 76 1.1 macallan struct wsscreen_list sc_screenlist; 77 1.1 macallan struct vcons_data vd; 78 1.1 macallan int sc_mode; 79 1.2 macallan void (*sc_putchar)(void *, int, int, u_int, long); 80 1.1 macallan u_char sc_cmap_red[256]; 81 1.1 macallan u_char sc_cmap_green[256]; 82 1.1 macallan u_char sc_cmap_blue[256]; 83 1.7 macallan kmutex_t sc_hwlock; 84 1.5 macallan uint32_t sc_hwmode; 85 1.5 macallan #define HW_FB 0 86 1.5 macallan #define HW_FILL 1 87 1.5 macallan #define HW_BLIT 2 88 1.7 macallan /* cursor stuff */ 89 1.7 macallan int sc_cursor_x, sc_cursor_y; 90 1.7 macallan int sc_hot_x, sc_hot_y, sc_enabled; 91 1.8 macallan int sc_video_on; 92 1.1 macallan glyphcache sc_gc; 93 1.1 macallan }; 94 1.1 macallan 95 1.1 macallan CFATTACH_DECL_NEW(gftfb, sizeof(struct gftfb_softc), 96 1.1 macallan gftfb_match, gftfb_attach, NULL, NULL); 97 1.1 macallan 98 1.1 macallan int gftfb_readbar(struct sti_softc *, struct pci_attach_args *, u_int, int); 99 1.1 macallan int gftfb_check_rom(struct gftfb_softc *, struct pci_attach_args *); 100 1.1 macallan void gftfb_enable_rom(struct sti_softc *); 101 1.1 macallan void gftfb_disable_rom(struct sti_softc *); 102 1.1 macallan void gftfb_enable_rom_internal(struct gftfb_softc *); 103 1.1 macallan void gftfb_disable_rom_internal(struct gftfb_softc *); 104 1.1 macallan 105 1.1 macallan void gftfb_setup(struct gftfb_softc *); 106 1.1 macallan 107 1.1 macallan #define ngle_bt458_write(memt, memh, r, v) \ 108 1.1 macallan bus_space_write_stream_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24) 109 1.1 macallan 110 1.1 macallan 111 1.3 macallan /* XXX these really need to go into their own header */ 112 1.1 macallan int sti_pci_is_console(struct pci_attach_args *, bus_addr_t *); 113 1.1 macallan int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t, 114 1.1 macallan bus_space_handle_t, bus_addr_t *, u_int); 115 1.1 macallan int sti_screen_setup(struct sti_screen *, int); 116 1.1 macallan void sti_describe_screen(struct sti_softc *, struct sti_screen *); 117 1.1 macallan 118 1.1 macallan #define PCI_ROM_SIZE(mr) \ 119 1.1 macallan (PCI_MAPREG_ROM_ADDR(mr) & -PCI_MAPREG_ROM_ADDR(mr)) 120 1.1 macallan 121 1.1 macallan /* wsdisplay stuff */ 122 1.1 macallan static int gftfb_ioctl(void *, void *, u_long, void *, int, 123 1.1 macallan struct lwp *); 124 1.1 macallan static paddr_t gftfb_mmap(void *, void *, off_t, int); 125 1.1 macallan static void gftfb_init_screen(void *, struct vcons_screen *, int, long *); 126 1.1 macallan 127 1.1 macallan static int gftfb_putcmap(struct gftfb_softc *, struct wsdisplay_cmap *); 128 1.1 macallan static int gftfb_getcmap(struct gftfb_softc *, struct wsdisplay_cmap *); 129 1.1 macallan static void gftfb_restore_palette(struct gftfb_softc *); 130 1.1 macallan static int gftfb_putpalreg(struct gftfb_softc *, uint8_t, uint8_t, 131 1.1 macallan uint8_t, uint8_t); 132 1.1 macallan 133 1.1 macallan static void gftfb_rectfill(struct gftfb_softc *, int, int, int, int, 134 1.1 macallan uint32_t); 135 1.1 macallan static void gftfb_bitblt(void *, int, int, int, int, int, 136 1.1 macallan int, int); 137 1.1 macallan 138 1.1 macallan static void gftfb_cursor(void *, int, int, int); 139 1.1 macallan static void gftfb_putchar(void *, int, int, u_int, long); 140 1.22 macallan static void gftfb_putchar_aa(void *, int, int, u_int, long); 141 1.1 macallan static void gftfb_copycols(void *, int, int, int, int); 142 1.1 macallan static void gftfb_erasecols(void *, int, int, int, long); 143 1.1 macallan static void gftfb_copyrows(void *, int, int, int); 144 1.1 macallan static void gftfb_eraserows(void *, int, int, long); 145 1.1 macallan 146 1.7 macallan static void gftfb_move_cursor(struct gftfb_softc *, int, int); 147 1.7 macallan static int gftfb_do_cursor(struct gftfb_softc *, struct wsdisplay_cursor *); 148 1.7 macallan 149 1.8 macallan static void gftfb_set_video(struct gftfb_softc *, int); 150 1.8 macallan 151 1.1 macallan struct wsdisplay_accessops gftfb_accessops = { 152 1.1 macallan gftfb_ioctl, 153 1.1 macallan gftfb_mmap, 154 1.1 macallan NULL, /* alloc_screen */ 155 1.1 macallan NULL, /* free_screen */ 156 1.1 macallan NULL, /* show_screen */ 157 1.1 macallan NULL, /* load_font */ 158 1.1 macallan NULL, /* pollc */ 159 1.1 macallan NULL /* scroll */ 160 1.1 macallan }; 161 1.1 macallan 162 1.7 macallan static inline void gftfb_wait_fifo(struct gftfb_softc *, uint32_t); 163 1.7 macallan 164 1.1 macallan int 165 1.1 macallan gftfb_match(device_t parent, cfdata_t cf, void *aux) 166 1.1 macallan { 167 1.1 macallan struct pci_attach_args *paa = aux; 168 1.1 macallan 169 1.1 macallan if (PCI_VENDOR(paa->pa_id) != PCI_VENDOR_HP) 170 1.1 macallan return 0; 171 1.1 macallan 172 1.1 macallan if (PCI_PRODUCT(paa->pa_id) == PCI_PRODUCT_HP_VISUALIZE_EG) 173 1.1 macallan return 10; /* beat out sti at pci */ 174 1.1 macallan 175 1.1 macallan return 0; 176 1.1 macallan } 177 1.1 macallan 178 1.21 macallan static inline uint32_t 179 1.21 macallan gftfb_read4(struct gftfb_softc *sc, uint32_t offset) 180 1.21 macallan { 181 1.21 macallan struct sti_rom *rom = sc->sc_base.sc_rom; 182 1.21 macallan bus_space_tag_t memt = rom->memt; 183 1.21 macallan bus_space_handle_t memh = rom->regh[2]; 184 1.21 macallan return bus_space_read_stream_4(memt, memh, offset); 185 1.21 macallan } 186 1.21 macallan 187 1.21 macallan static inline void 188 1.21 macallan gftfb_write4(struct gftfb_softc *sc, uint32_t offset, uint32_t val) 189 1.21 macallan { 190 1.21 macallan struct sti_rom *rom = sc->sc_base.sc_rom; 191 1.21 macallan bus_space_tag_t memt = rom->memt; 192 1.21 macallan bus_space_handle_t memh = rom->regh[2]; 193 1.21 macallan bus_space_write_stream_4(memt, memh, offset, val); 194 1.21 macallan } 195 1.21 macallan 196 1.21 macallan static inline uint8_t 197 1.21 macallan gftfb_read1(struct gftfb_softc *sc, uint32_t offset) 198 1.21 macallan { 199 1.21 macallan struct sti_rom *rom = sc->sc_base.sc_rom; 200 1.21 macallan bus_space_tag_t memt = rom->memt; 201 1.21 macallan bus_space_handle_t memh = rom->regh[2]; 202 1.21 macallan return bus_space_read_1(memt, memh, offset); 203 1.21 macallan } 204 1.21 macallan 205 1.21 macallan static inline void 206 1.21 macallan gftfb_write1(struct gftfb_softc *sc, uint32_t offset, uint8_t val) 207 1.21 macallan { 208 1.21 macallan struct sti_rom *rom = sc->sc_base.sc_rom; 209 1.21 macallan bus_space_tag_t memt = rom->memt; 210 1.21 macallan bus_space_handle_t memh = rom->regh[2]; 211 1.21 macallan bus_space_write_1(memt, memh, offset, val); 212 1.21 macallan } 213 1.21 macallan 214 1.1 macallan void 215 1.1 macallan gftfb_attach(device_t parent, device_t self, void *aux) 216 1.1 macallan { 217 1.1 macallan struct gftfb_softc *sc = device_private(self); 218 1.1 macallan struct pci_attach_args *paa = aux; 219 1.1 macallan struct sti_rom *rom; 220 1.1 macallan struct rasops_info *ri; 221 1.1 macallan struct wsemuldisplaydev_attach_args aa; 222 1.3 macallan unsigned long defattr = 0; 223 1.13 macallan int ret, is_console = 0; 224 1.1 macallan 225 1.1 macallan sc->sc_dev = self; 226 1.1 macallan 227 1.1 macallan sc->sc_pc = paa->pa_pc; 228 1.1 macallan sc->sc_tag = paa->pa_tag; 229 1.1 macallan sc->sc_base.sc_dev = self; 230 1.1 macallan sc->sc_base.sc_enable_rom = gftfb_enable_rom; 231 1.1 macallan sc->sc_base.sc_disable_rom = gftfb_disable_rom; 232 1.1 macallan 233 1.7 macallan /* we can *not* be interrupted when doing colour map accesses */ 234 1.7 macallan mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH); 235 1.7 macallan 236 1.1 macallan aprint_normal("\n"); 237 1.1 macallan 238 1.1 macallan if (gftfb_check_rom(sc, paa) != 0) 239 1.1 macallan return; 240 1.1 macallan 241 1.1 macallan ret = sti_pci_is_console(paa, sc->sc_base. bases); 242 1.1 macallan if (ret != 0) { 243 1.1 macallan sc->sc_base.sc_flags |= STI_CONSOLE; 244 1.1 macallan is_console = 1; 245 1.1 macallan } 246 1.1 macallan rom = (struct sti_rom *)kmem_zalloc(sizeof(*rom), KM_SLEEP); 247 1.1 macallan rom->rom_softc = &sc->sc_base; 248 1.14 macallan ret = sti_rom_setup(rom, paa->pa_iot, paa->pa_memt, sc->sc_romh, 249 1.14 macallan sc->sc_base.bases, STI_CODEBASE_MAIN); 250 1.1 macallan if (ret != 0) { 251 1.1 macallan kmem_free(rom, sizeof(*rom)); 252 1.1 macallan return; 253 1.1 macallan } 254 1.1 macallan 255 1.1 macallan sc->sc_base.sc_rom = rom; 256 1.1 macallan 257 1.1 macallan sc->sc_scr.scr_rom = sc->sc_base.sc_rom; 258 1.1 macallan ret = sti_screen_setup(&sc->sc_scr, STI_FBMODE); 259 1.1 macallan 260 1.1 macallan sc->sc_width = sc->sc_scr.scr_cfg.scr_width; 261 1.1 macallan sc->sc_height = sc->sc_scr.scr_cfg.scr_height; 262 1.12 macallan 263 1.26 riastrad aprint_normal_dev(sc->sc_dev, "%s at %dx%d\n", sc->sc_scr.name, 264 1.1 macallan sc->sc_width, sc->sc_height); 265 1.1 macallan gftfb_setup(sc); 266 1.1 macallan 267 1.21 macallan #ifdef GFTFB_DEBUG 268 1.21 macallan sc->sc_height -= 200; 269 1.21 macallan #endif 270 1.21 macallan 271 1.1 macallan sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 272 1.1 macallan "default", 273 1.1 macallan 0, 0, 274 1.1 macallan NULL, 275 1.1 macallan 8, 16, 276 1.1 macallan WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 277 1.1 macallan WSSCREEN_RESIZE, 278 1.1 macallan NULL 279 1.1 macallan }; 280 1.1 macallan 281 1.1 macallan sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 282 1.1 macallan sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 283 1.1 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 284 1.1 macallan sc->sc_locked = 0; 285 1.1 macallan 286 1.1 macallan vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 287 1.1 macallan &gftfb_accessops); 288 1.1 macallan sc->vd.init_screen = gftfb_init_screen; 289 1.1 macallan sc->vd.show_screen_cookie = &sc->sc_gc; 290 1.1 macallan sc->vd.show_screen_cb = glyphcache_adapt; 291 1.1 macallan 292 1.1 macallan ri = &sc->sc_console_screen.scr_ri; 293 1.1 macallan 294 1.1 macallan sc->sc_gc.gc_bitblt = gftfb_bitblt; 295 1.1 macallan sc->sc_gc.gc_blitcookie = sc; 296 1.3 macallan sc->sc_gc.gc_rop = RopSrc; 297 1.3 macallan 298 1.27 macallan vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); 299 1.27 macallan sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 300 1.27 macallan 301 1.27 macallan sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 302 1.27 macallan sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 303 1.27 macallan sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 304 1.27 macallan sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 305 1.27 macallan 306 1.27 macallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 307 1.27 macallan sc->sc_scr.fbheight - sc->sc_height - 5, 308 1.27 macallan sc->sc_scr.fbwidth, 309 1.27 macallan ri->ri_font->fontwidth, 310 1.27 macallan ri->ri_font->fontheight, 311 1.27 macallan defattr); 312 1.27 macallan 313 1.27 macallan gftfb_restore_palette(sc); 314 1.27 macallan gftfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 315 1.27 macallan ri->ri_devcmap[(defattr >> 16) & 0xff]); 316 1.27 macallan 317 1.1 macallan if (is_console) { 318 1.1 macallan wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 319 1.1 macallan defattr); 320 1.2 macallan 321 1.1 macallan vcons_replay_msgbuf(&sc->sc_console_screen); 322 1.1 macallan } 323 1.1 macallan 324 1.1 macallan /* no suspend/resume support yet */ 325 1.1 macallan if (!pmf_device_register(sc->sc_dev, NULL, NULL)) 326 1.1 macallan aprint_error_dev(sc->sc_dev, 327 1.1 macallan "couldn't establish power handler\n"); 328 1.1 macallan 329 1.1 macallan aa.console = is_console; 330 1.1 macallan aa.scrdata = &sc->sc_screenlist; 331 1.1 macallan aa.accessops = &gftfb_accessops; 332 1.1 macallan aa.accesscookie = &sc->vd; 333 1.1 macallan 334 1.1 macallan config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 335 1.1 macallan } 336 1.1 macallan 337 1.1 macallan /* 338 1.1 macallan * Grovel the STI ROM image. 339 1.1 macallan */ 340 1.1 macallan int 341 1.1 macallan gftfb_check_rom(struct gftfb_softc *spc, struct pci_attach_args *pa) 342 1.1 macallan { 343 1.1 macallan struct sti_softc *sc = &spc->sc_base; 344 1.1 macallan pcireg_t address, mask; 345 1.1 macallan bus_space_handle_t romh; 346 1.1 macallan bus_size_t romsize, subsize, stiromsize; 347 1.1 macallan bus_addr_t selected, offs, suboffs; 348 1.1 macallan uint32_t tmp; 349 1.1 macallan int i; 350 1.1 macallan int rc; 351 1.1 macallan 352 1.1 macallan /* sort of inline sti_pci_enable_rom(sc) */ 353 1.1 macallan address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM); 354 1.1 macallan pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, 355 1.1 macallan ~PCI_MAPREG_ROM_ENABLE); 356 1.1 macallan mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM); 357 1.1 macallan address |= PCI_MAPREG_ROM_ENABLE; 358 1.1 macallan pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, address); 359 1.1 macallan sc->sc_flags |= STI_ROM_ENABLED; 360 1.1 macallan /* 361 1.1 macallan * Map the complete ROM for now. 362 1.1 macallan */ 363 1.1 macallan 364 1.1 macallan romsize = PCI_ROM_SIZE(mask); 365 1.1 macallan DPRINTF(("%s: mapping rom @ %lx for %lx\n", __func__, 366 1.1 macallan (long)PCI_MAPREG_ROM_ADDR(address), (long)romsize)); 367 1.1 macallan 368 1.1 macallan rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address), romsize, 369 1.1 macallan 0, &romh); 370 1.1 macallan if (rc != 0) { 371 1.1 macallan aprint_error_dev(sc->sc_dev, "can't map PCI ROM (%d)\n", rc); 372 1.1 macallan goto fail2; 373 1.1 macallan } 374 1.1 macallan 375 1.1 macallan gftfb_disable_rom_internal(spc); 376 1.1 macallan /* 377 1.1 macallan * Iterate over the ROM images, pick the best candidate. 378 1.1 macallan */ 379 1.1 macallan 380 1.1 macallan selected = (bus_addr_t)-1; 381 1.1 macallan for (offs = 0; offs < romsize; offs += subsize) { 382 1.1 macallan gftfb_enable_rom_internal(spc); 383 1.1 macallan /* 384 1.1 macallan * Check for a valid ROM header. 385 1.1 macallan */ 386 1.1 macallan tmp = bus_space_read_4(pa->pa_memt, romh, offs + 0); 387 1.1 macallan tmp = le32toh(tmp); 388 1.1 macallan if (tmp != 0x55aa0000) { 389 1.1 macallan gftfb_disable_rom_internal(spc); 390 1.1 macallan if (offs == 0) { 391 1.1 macallan aprint_error_dev(sc->sc_dev, 392 1.1 macallan "invalid PCI ROM header signature (%08x)\n", 393 1.1 macallan tmp); 394 1.1 macallan rc = EINVAL; 395 1.1 macallan } 396 1.1 macallan break; 397 1.1 macallan } 398 1.1 macallan 399 1.1 macallan /* 400 1.1 macallan * Check ROM type. 401 1.1 macallan */ 402 1.1 macallan tmp = bus_space_read_4(pa->pa_memt, romh, offs + 4); 403 1.1 macallan tmp = le32toh(tmp); 404 1.1 macallan if (tmp != 0x00000001) { /* 1 == STI ROM */ 405 1.1 macallan gftfb_disable_rom_internal(spc); 406 1.1 macallan if (offs == 0) { 407 1.1 macallan aprint_error_dev(sc->sc_dev, 408 1.1 macallan "invalid PCI ROM type (%08x)\n", tmp); 409 1.1 macallan rc = EINVAL; 410 1.1 macallan } 411 1.1 macallan break; 412 1.1 macallan } 413 1.1 macallan 414 1.1 macallan subsize = (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, 415 1.1 macallan offs + 0x0c); 416 1.1 macallan subsize <<= 9; 417 1.1 macallan 418 1.15 macallan #ifdef GFTFB_DEBUG 419 1.1 macallan gftfb_disable_rom_internal(spc); 420 1.1 macallan DPRINTF(("ROM offset %08x size %08x type %08x", 421 1.1 macallan (u_int)offs, (u_int)subsize, tmp)); 422 1.1 macallan gftfb_enable_rom_internal(spc); 423 1.1 macallan #endif 424 1.1 macallan 425 1.1 macallan /* 426 1.1 macallan * Check for a valid ROM data structure. 427 1.1 macallan * We do not need it except to know what architecture the ROM 428 1.1 macallan * code is for. 429 1.1 macallan */ 430 1.1 macallan 431 1.1 macallan suboffs = offs +(bus_addr_t)bus_space_read_2(pa->pa_memt, romh, 432 1.1 macallan offs + 0x18); 433 1.1 macallan tmp = bus_space_read_4(pa->pa_memt, romh, suboffs + 0); 434 1.1 macallan tmp = le32toh(tmp); 435 1.1 macallan if (tmp != 0x50434952) { /* PCIR */ 436 1.1 macallan gftfb_disable_rom_internal(spc); 437 1.1 macallan if (offs == 0) { 438 1.1 macallan aprint_error_dev(sc->sc_dev, "invalid PCI data" 439 1.1 macallan " signature (%08x)\n", tmp); 440 1.1 macallan rc = EINVAL; 441 1.1 macallan } else { 442 1.1 macallan DPRINTF((" invalid PCI data signature %08x\n", 443 1.1 macallan tmp)); 444 1.1 macallan continue; 445 1.1 macallan } 446 1.1 macallan } 447 1.1 macallan 448 1.1 macallan tmp = bus_space_read_1(pa->pa_memt, romh, suboffs + 0x14); 449 1.1 macallan gftfb_disable_rom_internal(spc); 450 1.1 macallan DPRINTF((" code %02x", tmp)); 451 1.1 macallan 452 1.1 macallan switch (tmp) { 453 1.1 macallan #ifdef __hppa__ 454 1.1 macallan case 0x10: 455 1.1 macallan if (selected == (bus_addr_t)-1) 456 1.1 macallan selected = offs; 457 1.1 macallan break; 458 1.1 macallan #endif 459 1.1 macallan #ifdef __i386__ 460 1.1 macallan case 0x00: 461 1.1 macallan if (selected == (bus_addr_t)-1) 462 1.1 macallan selected = offs; 463 1.1 macallan break; 464 1.1 macallan #endif 465 1.1 macallan default: 466 1.1 macallan DPRINTF((" (wrong architecture)")); 467 1.1 macallan break; 468 1.1 macallan } 469 1.1 macallan DPRINTF(("%s\n", selected == offs ? " -> SELECTED" : "")); 470 1.1 macallan } 471 1.1 macallan 472 1.1 macallan if (selected == (bus_addr_t)-1) { 473 1.1 macallan if (rc == 0) { 474 1.1 macallan aprint_error_dev(sc->sc_dev, "found no ROM with " 475 1.1 macallan "correct microcode architecture\n"); 476 1.1 macallan rc = ENOEXEC; 477 1.1 macallan } 478 1.1 macallan goto fail; 479 1.1 macallan } 480 1.1 macallan 481 1.1 macallan /* 482 1.1 macallan * Read the STI region BAR assignments. 483 1.1 macallan */ 484 1.1 macallan 485 1.1 macallan gftfb_enable_rom_internal(spc); 486 1.1 macallan offs = selected + 487 1.1 macallan (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, selected + 0x0e); 488 1.1 macallan for (i = 0; i < STI_REGION_MAX; i++) { 489 1.1 macallan rc = gftfb_readbar(sc, pa, i, 490 1.1 macallan bus_space_read_1(pa->pa_memt, romh, offs + i)); 491 1.1 macallan if (rc != 0) 492 1.1 macallan goto fail; 493 1.1 macallan } 494 1.1 macallan 495 1.1 macallan /* 496 1.1 macallan * Find out where the STI ROM itself lies, and its size. 497 1.1 macallan */ 498 1.1 macallan 499 1.1 macallan offs = selected + 500 1.1 macallan (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, selected + 0x08); 501 1.1 macallan stiromsize = (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, 502 1.1 macallan offs + 0x18); 503 1.1 macallan stiromsize = le32toh(stiromsize); 504 1.1 macallan gftfb_disable_rom_internal(spc); 505 1.1 macallan 506 1.1 macallan /* 507 1.1 macallan * Replace our mapping with a smaller mapping of only the area 508 1.1 macallan * we are interested in. 509 1.1 macallan */ 510 1.1 macallan 511 1.1 macallan DPRINTF(("remapping rom @ %lx for %lx\n", 512 1.1 macallan (long)(PCI_MAPREG_ROM_ADDR(address) + offs), (long)stiromsize)); 513 1.1 macallan bus_space_unmap(pa->pa_memt, romh, romsize); 514 1.1 macallan rc = bus_space_map(pa->pa_memt, PCI_MAPREG_ROM_ADDR(address) + offs, 515 1.1 macallan stiromsize, 0, &spc->sc_romh); 516 1.1 macallan if (rc != 0) { 517 1.1 macallan aprint_error_dev(sc->sc_dev, "can't map STI ROM (%d)\n", 518 1.1 macallan rc); 519 1.1 macallan goto fail2; 520 1.1 macallan } 521 1.1 macallan gftfb_disable_rom_internal(spc); 522 1.1 macallan sc->sc_flags &= ~STI_ROM_ENABLED; 523 1.1 macallan 524 1.1 macallan return 0; 525 1.1 macallan 526 1.1 macallan fail: 527 1.1 macallan bus_space_unmap(pa->pa_memt, romh, romsize); 528 1.1 macallan fail2: 529 1.1 macallan gftfb_disable_rom_internal(spc); 530 1.1 macallan 531 1.1 macallan return rc; 532 1.1 macallan } 533 1.1 macallan 534 1.1 macallan /* 535 1.1 macallan * Decode a BAR register. 536 1.1 macallan */ 537 1.1 macallan int 538 1.1 macallan gftfb_readbar(struct sti_softc *sc, struct pci_attach_args *pa, u_int region, 539 1.1 macallan int bar) 540 1.1 macallan { 541 1.1 macallan bus_addr_t addr; 542 1.1 macallan bus_size_t size; 543 1.1 macallan uint32_t cf; 544 1.1 macallan int rc; 545 1.1 macallan 546 1.1 macallan if (bar == 0) { 547 1.1 macallan sc->bases[region] = 0; 548 1.1 macallan return (0); 549 1.1 macallan } 550 1.1 macallan 551 1.1 macallan #ifdef DIAGNOSTIC 552 1.1 macallan if (bar < PCI_MAPREG_START || bar > PCI_MAPREG_PPB_END) { 553 1.1 macallan gftfb_disable_rom(sc); 554 1.1 macallan printf("%s: unexpected bar %02x for region %d\n", 555 1.1 macallan device_xname(sc->sc_dev), bar, region); 556 1.1 macallan gftfb_enable_rom(sc); 557 1.1 macallan } 558 1.1 macallan #endif 559 1.1 macallan 560 1.1 macallan cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar); 561 1.1 macallan 562 1.1 macallan rc = pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar, PCI_MAPREG_TYPE(cf), 563 1.1 macallan &addr, &size, NULL); 564 1.1 macallan 565 1.1 macallan if (rc != 0) { 566 1.1 macallan gftfb_disable_rom(sc); 567 1.1 macallan aprint_error_dev(sc->sc_dev, "invalid bar %02x for region %d\n", 568 1.1 macallan bar, region); 569 1.1 macallan gftfb_enable_rom(sc); 570 1.1 macallan return (rc); 571 1.1 macallan } 572 1.1 macallan 573 1.1 macallan sc->bases[region] = addr; 574 1.1 macallan return (0); 575 1.1 macallan } 576 1.1 macallan 577 1.1 macallan /* 578 1.1 macallan * Enable PCI ROM. 579 1.1 macallan */ 580 1.1 macallan void 581 1.1 macallan gftfb_enable_rom_internal(struct gftfb_softc *spc) 582 1.1 macallan { 583 1.1 macallan pcireg_t address; 584 1.1 macallan 585 1.1 macallan KASSERT(spc != NULL); 586 1.1 macallan 587 1.1 macallan address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM); 588 1.1 macallan address |= PCI_MAPREG_ROM_ENABLE; 589 1.1 macallan pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address); 590 1.1 macallan } 591 1.1 macallan 592 1.1 macallan void 593 1.1 macallan gftfb_enable_rom(struct sti_softc *sc) 594 1.1 macallan { 595 1.1 macallan struct gftfb_softc *spc = device_private(sc->sc_dev); 596 1.1 macallan 597 1.1 macallan if (!ISSET(sc->sc_flags, STI_ROM_ENABLED)) { 598 1.1 macallan gftfb_enable_rom_internal(spc); 599 1.1 macallan } 600 1.1 macallan SET(sc->sc_flags, STI_ROM_ENABLED); 601 1.1 macallan } 602 1.1 macallan 603 1.1 macallan /* 604 1.1 macallan * Disable PCI ROM. 605 1.1 macallan */ 606 1.1 macallan void 607 1.1 macallan gftfb_disable_rom_internal(struct gftfb_softc *spc) 608 1.1 macallan { 609 1.1 macallan pcireg_t address; 610 1.1 macallan 611 1.1 macallan KASSERT(spc != NULL); 612 1.1 macallan 613 1.1 macallan address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM); 614 1.1 macallan address &= ~PCI_MAPREG_ROM_ENABLE; 615 1.1 macallan pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_MAPREG_ROM, address); 616 1.1 macallan } 617 1.1 macallan 618 1.1 macallan void 619 1.1 macallan gftfb_disable_rom(struct sti_softc *sc) 620 1.1 macallan { 621 1.1 macallan struct gftfb_softc *spc = device_private(sc->sc_dev); 622 1.1 macallan 623 1.1 macallan if (ISSET(sc->sc_flags, STI_ROM_ENABLED)) { 624 1.1 macallan gftfb_disable_rom_internal(spc); 625 1.1 macallan } 626 1.1 macallan CLR(sc->sc_flags, STI_ROM_ENABLED); 627 1.1 macallan } 628 1.1 macallan 629 1.3 macallan static inline void 630 1.1 macallan gftfb_wait(struct gftfb_softc *sc) 631 1.1 macallan { 632 1.1 macallan uint8_t stat; 633 1.1 macallan 634 1.1 macallan do { 635 1.21 macallan stat = gftfb_read1(sc, NGLE_REG_15b0); 636 1.1 macallan if (stat == 0) 637 1.21 macallan stat = gftfb_read1(sc, NGLE_REG_15b0); 638 1.1 macallan } while (stat != 0); 639 1.1 macallan } 640 1.1 macallan 641 1.3 macallan static inline void 642 1.1 macallan gftfb_setup_fb(struct gftfb_softc *sc) 643 1.1 macallan { 644 1.1 macallan gftfb_wait(sc); 645 1.24 macallan gftfb_write4(sc, NGLE_REG_10, 646 1.24 macallan BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINapp0I, 0)); 647 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x83000300); 648 1.1 macallan gftfb_wait(sc); 649 1.21 macallan gftfb_write1(sc, NGLE_REG_16b1, 1); 650 1.5 macallan sc->sc_hwmode = HW_FB; 651 1.1 macallan } 652 1.1 macallan 653 1.1 macallan void 654 1.1 macallan gftfb_setup(struct gftfb_softc *sc) 655 1.1 macallan { 656 1.1 macallan struct sti_rom *rom = sc->sc_base.sc_rom; 657 1.1 macallan bus_space_tag_t memt = rom->memt; 658 1.1 macallan bus_space_handle_t memh = rom->regh[2]; 659 1.26 riastrad int i; 660 1.1 macallan 661 1.5 macallan sc->sc_hwmode = HW_FB; 662 1.7 macallan sc->sc_hot_x = 0; 663 1.7 macallan sc->sc_hot_y = 0; 664 1.7 macallan sc->sc_enabled = 0; 665 1.8 macallan sc->sc_video_on = 1; 666 1.3 macallan 667 1.12 macallan 668 1.1 macallan /* set Bt458 read mask register to all planes */ 669 1.1 macallan gftfb_wait(sc); 670 1.1 macallan ngle_bt458_write(memt, memh, 0x08, 0x04); 671 1.1 macallan ngle_bt458_write(memt, memh, 0x0a, 0xff); 672 1.1 macallan 673 1.1 macallan gftfb_setup_fb(sc); 674 1.1 macallan 675 1.1 macallan /* attr. planes */ 676 1.1 macallan gftfb_wait(sc); 677 1.21 macallan gftfb_write4(sc, NGLE_REG_11, 0x2ea0d000); 678 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x23000302); 679 1.21 macallan gftfb_write4(sc, NGLE_REG_12, NGLE_ARTIST_CMAP0); 680 1.21 macallan gftfb_write4(sc, NGLE_REG_8, 0xffffffff); 681 1.1 macallan 682 1.1 macallan gftfb_wait(sc); 683 1.21 macallan gftfb_write4(sc, NGLE_REG_6, 0x00000000); 684 1.21 macallan gftfb_write4(sc, NGLE_REG_9, 685 1.1 macallan (sc->sc_scr.scr_cfg.scr_width << 16) | sc->sc_scr.scr_cfg.scr_height); 686 1.5 macallan /* 687 1.26 riastrad * blit into offscreen memory to force flush previous - apparently 688 1.5 macallan * some chips have a bug this works around 689 1.5 macallan */ 690 1.21 macallan gftfb_write4(sc, NGLE_REG_6, 0x05000000); 691 1.21 macallan gftfb_write4(sc, NGLE_REG_9, 0x00040001); 692 1.1 macallan 693 1.1 macallan gftfb_wait(sc); 694 1.21 macallan gftfb_write4(sc, NGLE_REG_12, 0x00000000); 695 1.1 macallan 696 1.1 macallan gftfb_setup_fb(sc); 697 1.1 macallan 698 1.5 macallan /* make sure video output is enabled */ 699 1.1 macallan gftfb_wait(sc); 700 1.21 macallan gftfb_write4(sc, NGLE_REG_21, 701 1.21 macallan gftfb_read4(sc, NGLE_REG_21) | 0x0a000000); 702 1.21 macallan gftfb_write4(sc, NGLE_REG_27, 703 1.21 macallan gftfb_read4(sc, NGLE_REG_27) | 0x00800000); 704 1.7 macallan 705 1.7 macallan /* initialize cursor sprite */ 706 1.7 macallan gftfb_wait(sc); 707 1.26 riastrad 708 1.7 macallan /* cursor mask */ 709 1.7 macallan gftfb_wait(sc); 710 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x300); 711 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 712 1.25 macallan gftfb_write4(sc, NGLE_REG_11, 713 1.25 macallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcmask, 0)); 714 1.21 macallan gftfb_write4(sc, NGLE_REG_3, 0); 715 1.7 macallan for (i = 0; i < 64; i++) { 716 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0xffffffff); 717 1.21 macallan gftfb_write4(sc, NGLE_REG_5, 0xffffffff); 718 1.7 macallan } 719 1.7 macallan 720 1.7 macallan /* cursor image */ 721 1.7 macallan gftfb_wait(sc); 722 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x300); 723 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 724 1.25 macallan gftfb_write4(sc, NGLE_REG_11, 725 1.25 macallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcursor, 0)); 726 1.21 macallan gftfb_write4(sc, NGLE_REG_3, 0); 727 1.7 macallan for (i = 0; i < 64; i++) { 728 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0xff00ff00); 729 1.21 macallan gftfb_write4(sc, NGLE_REG_5, 0xff00ff00); 730 1.7 macallan } 731 1.7 macallan 732 1.7 macallan /* colour map */ 733 1.7 macallan gftfb_wait(sc); 734 1.26 riastrad gftfb_write4(sc, NGLE_REG_10, 735 1.25 macallan BA(FractDcd, Otc24, Ots08, Addr24, 0, BINcmap, 0)); 736 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x03000300); 737 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 738 1.7 macallan gftfb_wait(sc); 739 1.21 macallan gftfb_write4(sc, NGLE_REG_3, 0); 740 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0); 741 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0); 742 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0x000000ff); /* BG */ 743 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0x00ff0000); /* FG */ 744 1.7 macallan gftfb_wait(sc); 745 1.21 macallan gftfb_write4(sc, NGLE_REG_2, 0); 746 1.21 macallan gftfb_write4(sc, NGLE_REG_26, 0x80008004); 747 1.26 riastrad gftfb_setup_fb(sc); 748 1.7 macallan 749 1.7 macallan gftfb_move_cursor(sc, 100, 100); 750 1.7 macallan 751 1.1 macallan } 752 1.1 macallan 753 1.1 macallan static int 754 1.1 macallan gftfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 755 1.1 macallan struct lwp *l) 756 1.1 macallan { 757 1.1 macallan struct vcons_data *vd = v; 758 1.1 macallan struct gftfb_softc *sc = vd->cookie; 759 1.1 macallan struct wsdisplay_fbinfo *wdf; 760 1.1 macallan struct vcons_screen *ms = vd->active; 761 1.1 macallan 762 1.1 macallan switch (cmd) { 763 1.1 macallan case WSDISPLAYIO_GTYPE: 764 1.10 macallan *(u_int *)data = WSDISPLAY_TYPE_STI; 765 1.1 macallan return 0; 766 1.1 macallan 767 1.18 macallan case GCID: 768 1.18 macallan *(u_int *)data = STI_DD_EG; 769 1.18 macallan return 0; 770 1.18 macallan 771 1.1 macallan /* PCI config read/write passthrough. */ 772 1.1 macallan case PCI_IOC_CFGREAD: 773 1.1 macallan case PCI_IOC_CFGWRITE: 774 1.1 macallan return pci_devioctl(sc->sc_pc, sc->sc_tag, 775 1.1 macallan cmd, data, flag, l); 776 1.1 macallan 777 1.1 macallan case WSDISPLAYIO_GET_BUSID: 778 1.26 riastrad return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 779 1.1 macallan sc->sc_tag, data); 780 1.1 macallan 781 1.1 macallan case WSDISPLAYIO_GINFO: 782 1.1 macallan if (ms == NULL) 783 1.1 macallan return ENODEV; 784 1.1 macallan wdf = (void *)data; 785 1.1 macallan wdf->height = ms->scr_ri.ri_height; 786 1.1 macallan wdf->width = ms->scr_ri.ri_width; 787 1.1 macallan wdf->depth = ms->scr_ri.ri_depth; 788 1.1 macallan wdf->cmsize = 256; 789 1.1 macallan return 0; 790 1.1 macallan 791 1.1 macallan case WSDISPLAYIO_GETCMAP: 792 1.1 macallan return gftfb_getcmap(sc, 793 1.1 macallan (struct wsdisplay_cmap *)data); 794 1.1 macallan 795 1.1 macallan case WSDISPLAYIO_PUTCMAP: 796 1.1 macallan return gftfb_putcmap(sc, 797 1.1 macallan (struct wsdisplay_cmap *)data); 798 1.1 macallan 799 1.1 macallan case WSDISPLAYIO_LINEBYTES: 800 1.1 macallan *(u_int *)data = 2048; 801 1.1 macallan return 0; 802 1.1 macallan 803 1.1 macallan case WSDISPLAYIO_SMODE: { 804 1.1 macallan int new_mode = *(int*)data; 805 1.1 macallan if (new_mode != sc->sc_mode) { 806 1.1 macallan sc->sc_mode = new_mode; 807 1.1 macallan if(new_mode == WSDISPLAYIO_MODE_EMUL) { 808 1.2 macallan gftfb_setup(sc); 809 1.5 macallan gftfb_restore_palette(sc); 810 1.3 macallan glyphcache_wipe(&sc->sc_gc); 811 1.2 macallan gftfb_rectfill(sc, 0, 0, sc->sc_width, 812 1.2 macallan sc->sc_height, ms->scr_ri.ri_devcmap[ 813 1.2 macallan (ms->scr_defattr >> 16) & 0xff]); 814 1.1 macallan vcons_redraw_screen(ms); 815 1.8 macallan gftfb_set_video(sc, 1); 816 1.1 macallan } 817 1.1 macallan } 818 1.1 macallan } 819 1.1 macallan return 0; 820 1.1 macallan 821 1.1 macallan case WSDISPLAYIO_GET_FBINFO: 822 1.10 macallan { 823 1.1 macallan struct wsdisplayio_fbinfo *fbi = data; 824 1.10 macallan int ret; 825 1.1 macallan 826 1.10 macallan ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 827 1.10 macallan fbi->fbi_fbsize = sc->sc_scr.fbheight * 2048; 828 1.10 macallan return ret; 829 1.10 macallan } 830 1.7 macallan 831 1.7 macallan case WSDISPLAYIO_GCURPOS: 832 1.7 macallan { 833 1.7 macallan struct wsdisplay_curpos *cp = (void *)data; 834 1.7 macallan 835 1.7 macallan cp->x = sc->sc_cursor_x; 836 1.7 macallan cp->y = sc->sc_cursor_y; 837 1.7 macallan } 838 1.7 macallan return 0; 839 1.7 macallan 840 1.7 macallan case WSDISPLAYIO_SCURPOS: 841 1.7 macallan { 842 1.7 macallan struct wsdisplay_curpos *cp = (void *)data; 843 1.7 macallan 844 1.7 macallan gftfb_move_cursor(sc, cp->x, cp->y); 845 1.7 macallan } 846 1.7 macallan return 0; 847 1.7 macallan 848 1.7 macallan case WSDISPLAYIO_GCURMAX: 849 1.7 macallan { 850 1.7 macallan struct wsdisplay_curpos *cp = (void *)data; 851 1.7 macallan 852 1.7 macallan cp->x = 64; 853 1.7 macallan cp->y = 64; 854 1.7 macallan } 855 1.7 macallan return 0; 856 1.7 macallan 857 1.7 macallan case WSDISPLAYIO_SCURSOR: 858 1.7 macallan { 859 1.7 macallan struct wsdisplay_cursor *cursor = (void *)data; 860 1.7 macallan 861 1.7 macallan return gftfb_do_cursor(sc, cursor); 862 1.7 macallan } 863 1.8 macallan 864 1.8 macallan case WSDISPLAYIO_SVIDEO: 865 1.8 macallan gftfb_set_video(sc, *(int *)data); 866 1.8 macallan return 0; 867 1.8 macallan case WSDISPLAYIO_GVIDEO: 868 1.19 macallan *(u_int *)data = sc->sc_video_on ? 869 1.8 macallan WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 870 1.19 macallan return 0; 871 1.1 macallan } 872 1.1 macallan return EPASSTHROUGH; 873 1.1 macallan } 874 1.1 macallan 875 1.1 macallan static paddr_t 876 1.1 macallan gftfb_mmap(void *v, void *vs, off_t offset, int prot) 877 1.1 macallan { 878 1.1 macallan struct vcons_data *vd = v; 879 1.1 macallan struct gftfb_softc *sc = vd->cookie; 880 1.2 macallan struct sti_rom *rom = sc->sc_base.sc_rom; 881 1.14 macallan paddr_t pa = -1; 882 1.2 macallan 883 1.14 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 884 1.2 macallan return -1; 885 1.2 macallan 886 1.17 macallan if (offset >= 0 && offset < sc->sc_scr.fblen) { 887 1.14 macallan /* framebuffer */ 888 1.14 macallan pa = bus_space_mmap(rom->memt, sc->sc_scr.fbaddr, offset, 889 1.14 macallan prot, BUS_SPACE_MAP_LINEAR); 890 1.23 macallan } else if (offset >= 0x80000000 && offset < 0x80400000) { 891 1.14 macallan /* blitter registers etc. */ 892 1.14 macallan pa = bus_space_mmap(rom->memt, rom->regh[2], 893 1.14 macallan offset - 0x80000000, prot, BUS_SPACE_MAP_LINEAR); 894 1.14 macallan } 895 1.2 macallan 896 1.2 macallan return pa; 897 1.1 macallan } 898 1.1 macallan 899 1.1 macallan static void 900 1.1 macallan gftfb_init_screen(void *cookie, struct vcons_screen *scr, 901 1.1 macallan int existing, long *defattr) 902 1.1 macallan { 903 1.1 macallan struct gftfb_softc *sc = cookie; 904 1.1 macallan struct rasops_info *ri = &scr->scr_ri; 905 1.1 macallan 906 1.1 macallan ri->ri_depth = 8; 907 1.1 macallan ri->ri_width = sc->sc_width; 908 1.1 macallan ri->ri_height = sc->sc_height; 909 1.1 macallan ri->ri_stride = 2048; 910 1.26 riastrad ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB | 911 1.3 macallan RI_ENABLE_ALPHA | RI_PREFER_ALPHA; 912 1.3 macallan 913 1.1 macallan ri->ri_bits = (void *)sc->sc_scr.fbaddr; 914 1.1 macallan rasops_init(ri, 0, 0); 915 1.1 macallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 916 1.1 macallan WSSCREEN_RESIZE; 917 1.1 macallan scr->scr_flags |= VCONS_LOADFONT; 918 1.1 macallan 919 1.1 macallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 920 1.1 macallan sc->sc_width / ri->ri_font->fontwidth); 921 1.1 macallan 922 1.1 macallan ri->ri_hw = scr; 923 1.2 macallan sc->sc_putchar = ri->ri_ops.putchar; 924 1.1 macallan ri->ri_ops.copyrows = gftfb_copyrows; 925 1.1 macallan ri->ri_ops.copycols = gftfb_copycols; 926 1.1 macallan ri->ri_ops.eraserows = gftfb_eraserows; 927 1.1 macallan ri->ri_ops.erasecols = gftfb_erasecols; 928 1.1 macallan ri->ri_ops.cursor = gftfb_cursor; 929 1.22 macallan if (FONT_IS_ALPHA(ri->ri_font)) { 930 1.22 macallan ri->ri_ops.putchar = gftfb_putchar_aa; 931 1.26 riastrad } else 932 1.22 macallan ri->ri_ops.putchar = gftfb_putchar; 933 1.1 macallan } 934 1.1 macallan 935 1.1 macallan static int 936 1.1 macallan gftfb_putcmap(struct gftfb_softc *sc, struct wsdisplay_cmap *cm) 937 1.1 macallan { 938 1.1 macallan u_char *r, *g, *b; 939 1.1 macallan u_int index = cm->index; 940 1.1 macallan u_int count = cm->count; 941 1.1 macallan int i, error; 942 1.1 macallan u_char rbuf[256], gbuf[256], bbuf[256]; 943 1.1 macallan 944 1.1 macallan if (cm->index >= 256 || cm->count > 256 || 945 1.1 macallan (cm->index + cm->count) > 256) 946 1.1 macallan return EINVAL; 947 1.1 macallan error = copyin(cm->red, &rbuf[index], count); 948 1.1 macallan if (error) 949 1.1 macallan return error; 950 1.1 macallan error = copyin(cm->green, &gbuf[index], count); 951 1.1 macallan if (error) 952 1.1 macallan return error; 953 1.1 macallan error = copyin(cm->blue, &bbuf[index], count); 954 1.1 macallan if (error) 955 1.1 macallan return error; 956 1.1 macallan 957 1.1 macallan memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 958 1.1 macallan memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 959 1.1 macallan memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 960 1.1 macallan 961 1.1 macallan r = &sc->sc_cmap_red[index]; 962 1.1 macallan g = &sc->sc_cmap_green[index]; 963 1.1 macallan b = &sc->sc_cmap_blue[index]; 964 1.1 macallan 965 1.1 macallan for (i = 0; i < count; i++) { 966 1.1 macallan gftfb_putpalreg(sc, index, *r, *g, *b); 967 1.1 macallan index++; 968 1.1 macallan r++, g++, b++; 969 1.1 macallan } 970 1.1 macallan return 0; 971 1.1 macallan } 972 1.1 macallan 973 1.1 macallan static int 974 1.1 macallan gftfb_getcmap(struct gftfb_softc *sc, struct wsdisplay_cmap *cm) 975 1.1 macallan { 976 1.1 macallan u_int index = cm->index; 977 1.1 macallan u_int count = cm->count; 978 1.1 macallan int error; 979 1.1 macallan 980 1.1 macallan if (index >= 255 || count > 256 || index + count > 256) 981 1.1 macallan return EINVAL; 982 1.1 macallan 983 1.1 macallan error = copyout(&sc->sc_cmap_red[index], cm->red, count); 984 1.1 macallan if (error) 985 1.1 macallan return error; 986 1.1 macallan error = copyout(&sc->sc_cmap_green[index], cm->green, count); 987 1.1 macallan if (error) 988 1.1 macallan return error; 989 1.1 macallan error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 990 1.1 macallan if (error) 991 1.1 macallan return error; 992 1.1 macallan 993 1.1 macallan return 0; 994 1.1 macallan } 995 1.1 macallan 996 1.1 macallan static void 997 1.1 macallan gftfb_restore_palette(struct gftfb_softc *sc) 998 1.1 macallan { 999 1.13 macallan uint8_t cmap[768]; 1000 1.13 macallan int i, j; 1001 1.1 macallan 1002 1.13 macallan j = 0; 1003 1.13 macallan rasops_get_cmap(&sc->sc_console_screen.scr_ri, cmap, sizeof(cmap)); 1004 1.1 macallan for (i = 0; i < 256; i++) { 1005 1.13 macallan sc->sc_cmap_red[i] = cmap[j]; 1006 1.13 macallan sc->sc_cmap_green[i] = cmap[j + 1]; 1007 1.13 macallan sc->sc_cmap_blue[i] = cmap[j + 2]; 1008 1.13 macallan gftfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); 1009 1.13 macallan j += 3; 1010 1.1 macallan } 1011 1.1 macallan } 1012 1.1 macallan 1013 1.1 macallan static int 1014 1.1 macallan gftfb_putpalreg(struct gftfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, 1015 1.1 macallan uint8_t b) 1016 1.1 macallan { 1017 1.7 macallan mutex_enter(&sc->sc_hwlock); 1018 1.1 macallan gftfb_wait(sc); 1019 1.25 macallan gftfb_write4(sc, NGLE_REG_10, 1020 1.25 macallan BA(FractDcd, Otc24, Ots08, Addr24, 0, BINcmap, 0)); 1021 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x03000300); 1022 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 1023 1.1 macallan 1024 1.1 macallan gftfb_wait(sc); 1025 1.21 macallan gftfb_write4(sc, NGLE_REG_3, 0x400 | (idx << 2)); 1026 1.21 macallan gftfb_write4(sc, NGLE_REG_4, (r << 16) | (g << 8) | b); 1027 1.1 macallan 1028 1.21 macallan gftfb_write4(sc, NGLE_REG_2, 0x400); 1029 1.21 macallan gftfb_write4(sc, NGLE_REG_26, 0x80000100); 1030 1.1 macallan gftfb_setup_fb(sc); 1031 1.7 macallan mutex_exit(&sc->sc_hwlock); 1032 1.1 macallan return 0; 1033 1.1 macallan } 1034 1.2 macallan 1035 1.3 macallan static inline void 1036 1.2 macallan gftfb_wait_fifo(struct gftfb_softc *sc, uint32_t slots) 1037 1.2 macallan { 1038 1.2 macallan uint32_t reg; 1039 1.2 macallan 1040 1.2 macallan do { 1041 1.21 macallan reg = gftfb_read4(sc, NGLE_REG_34); 1042 1.2 macallan } while (reg < slots); 1043 1.2 macallan } 1044 1.2 macallan 1045 1.28 macallan static inline void 1046 1.28 macallan gftfb_fillmode(struct gftfb_softc *sc) 1047 1.2 macallan { 1048 1.5 macallan if (sc->sc_hwmode != HW_FILL) { 1049 1.20 macallan gftfb_wait_fifo(sc, 3); 1050 1.5 macallan /* plane mask */ 1051 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xff); 1052 1.5 macallan /* bitmap op */ 1053 1.26 riastrad gftfb_write4(sc, NGLE_REG_14, 1054 1.28 macallan IBOvals(RopSrc, 0, BitmapExtent08, 1, DataDynamic, 0, 1055 1.28 macallan 0, 0)); 1056 1.5 macallan /* dst bitmap access */ 1057 1.21 macallan gftfb_write4(sc, NGLE_REG_11, 1058 1.28 macallan BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 1059 1.28 macallan 0)); 1060 1.5 macallan sc->sc_hwmode = HW_FILL; 1061 1.5 macallan } 1062 1.28 macallan } 1063 1.28 macallan 1064 1.28 macallan static void 1065 1.28 macallan gftfb_rectfill(struct gftfb_softc *sc, int x, int y, int wi, int he, 1066 1.28 macallan uint32_t bg) 1067 1.28 macallan { 1068 1.28 macallan gftfb_fillmode(sc); 1069 1.28 macallan 1070 1.20 macallan gftfb_wait_fifo(sc, 4); 1071 1.20 macallan 1072 1.20 macallan /* transfer data */ 1073 1.28 macallan gftfb_write4(sc, NGLE_REG_8, 0xffffffff); 1074 1.21 macallan gftfb_write4(sc, NGLE_REG_35, bg); 1075 1.2 macallan /* dst XY */ 1076 1.21 macallan gftfb_write4(sc, NGLE_REG_6, (x << 16) | y); 1077 1.2 macallan /* len XY start */ 1078 1.21 macallan gftfb_write4(sc, NGLE_REG_9, (wi << 16) | he); 1079 1.2 macallan 1080 1.2 macallan } 1081 1.2 macallan 1082 1.12 macallan static void 1083 1.2 macallan gftfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi, 1084 1.2 macallan int he, int rop) 1085 1.2 macallan { 1086 1.2 macallan struct gftfb_softc *sc = cookie; 1087 1.2 macallan 1088 1.6 macallan if (sc->sc_hwmode != HW_BLIT) { 1089 1.6 macallan gftfb_wait(sc); 1090 1.24 macallan gftfb_write4(sc, NGLE_REG_10, 1091 1.24 macallan BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINapp0I, 0)); 1092 1.6 macallan sc->sc_hwmode = HW_BLIT; 1093 1.6 macallan } 1094 1.2 macallan gftfb_wait_fifo(sc, 5); 1095 1.24 macallan gftfb_write4(sc, NGLE_REG_14, 1096 1.24 macallan IBOvals(rop, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0)); 1097 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xff); 1098 1.21 macallan gftfb_write4(sc, NGLE_REG_24, (xs << 16) | ys); 1099 1.21 macallan gftfb_write4(sc, NGLE_REG_7, (wi << 16) | he); 1100 1.21 macallan gftfb_write4(sc, NGLE_REG_25, (xd << 16) | yd); 1101 1.2 macallan } 1102 1.2 macallan 1103 1.2 macallan static void 1104 1.4 macallan gftfb_nuke_cursor(struct rasops_info *ri) 1105 1.4 macallan { 1106 1.4 macallan struct vcons_screen *scr = ri->ri_hw; 1107 1.4 macallan struct gftfb_softc *sc = scr->scr_cookie; 1108 1.4 macallan int wi, he, x, y; 1109 1.26 riastrad 1110 1.4 macallan if (ri->ri_flg & RI_CURSOR) { 1111 1.4 macallan wi = ri->ri_font->fontwidth; 1112 1.4 macallan he = ri->ri_font->fontheight; 1113 1.4 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 1114 1.4 macallan y = ri->ri_crow * he + ri->ri_yorigin; 1115 1.4 macallan gftfb_bitblt(sc, x, y, x, y, wi, he, RopInv); 1116 1.4 macallan ri->ri_flg &= ~RI_CURSOR; 1117 1.4 macallan } 1118 1.4 macallan } 1119 1.4 macallan 1120 1.4 macallan static void 1121 1.2 macallan gftfb_cursor(void *cookie, int on, int row, int col) 1122 1.2 macallan { 1123 1.2 macallan struct rasops_info *ri = cookie; 1124 1.2 macallan struct vcons_screen *scr = ri->ri_hw; 1125 1.2 macallan struct gftfb_softc *sc = scr->scr_cookie; 1126 1.2 macallan int x, y, wi, he; 1127 1.26 riastrad 1128 1.2 macallan wi = ri->ri_font->fontwidth; 1129 1.2 macallan he = ri->ri_font->fontheight; 1130 1.26 riastrad 1131 1.2 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1132 1.4 macallan if (on) { 1133 1.4 macallan if (ri->ri_flg & RI_CURSOR) { 1134 1.4 macallan gftfb_nuke_cursor(ri); 1135 1.4 macallan } 1136 1.4 macallan x = col * wi + ri->ri_xorigin; 1137 1.4 macallan y = row * he + ri->ri_yorigin; 1138 1.2 macallan gftfb_bitblt(sc, x, y, x, y, wi, he, RopInv); 1139 1.4 macallan ri->ri_flg |= RI_CURSOR; 1140 1.2 macallan } 1141 1.2 macallan ri->ri_crow = row; 1142 1.2 macallan ri->ri_ccol = col; 1143 1.4 macallan } else 1144 1.4 macallan { 1145 1.4 macallan ri->ri_crow = row; 1146 1.4 macallan ri->ri_ccol = col; 1147 1.4 macallan ri->ri_flg &= ~RI_CURSOR; 1148 1.2 macallan } 1149 1.2 macallan 1150 1.2 macallan } 1151 1.2 macallan 1152 1.2 macallan static void 1153 1.2 macallan gftfb_putchar(void *cookie, int row, int col, u_int c, long attr) 1154 1.2 macallan { 1155 1.2 macallan struct rasops_info *ri = cookie; 1156 1.2 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1157 1.2 macallan struct vcons_screen *scr = ri->ri_hw; 1158 1.2 macallan struct gftfb_softc *sc = scr->scr_cookie; 1159 1.22 macallan void *data; 1160 1.22 macallan int i, x, y, wi, he, rv = GC_NOPE; 1161 1.22 macallan uint32_t bg, fg, mask; 1162 1.22 macallan 1163 1.22 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1164 1.22 macallan return; 1165 1.22 macallan 1166 1.22 macallan if (!CHAR_IN_FONT(c, font)) 1167 1.22 macallan return; 1168 1.22 macallan 1169 1.22 macallan if (row == ri->ri_crow && col == ri->ri_ccol) { 1170 1.22 macallan ri->ri_flg &= ~RI_CURSOR; 1171 1.22 macallan } 1172 1.22 macallan 1173 1.22 macallan wi = font->fontwidth; 1174 1.22 macallan he = font->fontheight; 1175 1.22 macallan 1176 1.22 macallan x = ri->ri_xorigin + col * wi; 1177 1.22 macallan y = ri->ri_yorigin + row * he; 1178 1.22 macallan 1179 1.22 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1180 1.22 macallan 1181 1.22 macallan /* if we're drawing a space we're done here */ 1182 1.22 macallan if (c == 0x20) { 1183 1.22 macallan gftfb_rectfill(sc, x, y, wi, he, bg); 1184 1.22 macallan return; 1185 1.22 macallan } 1186 1.22 macallan 1187 1.22 macallan 1188 1.22 macallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1189 1.22 macallan if (rv == GC_OK) 1190 1.22 macallan return; 1191 1.22 macallan 1192 1.22 macallan data = WSFONT_GLYPH(c, font); 1193 1.28 macallan fg = ri->ri_devcmap[(attr >> 24) & 0x0f]; 1194 1.22 macallan 1195 1.28 macallan gftfb_fillmode(sc); 1196 1.28 macallan gftfb_wait_fifo(sc, 3); 1197 1.22 macallan 1198 1.22 macallan /* character colour */ 1199 1.22 macallan gftfb_write4(sc, NGLE_REG_35, fg); 1200 1.28 macallan gftfb_write4(sc, NGLE_REG_36, bg); 1201 1.22 macallan /* dst XY */ 1202 1.22 macallan gftfb_write4(sc, NGLE_REG_6, (x << 16) | y); 1203 1.22 macallan 1204 1.22 macallan if (ri->ri_font->stride == 1) { 1205 1.22 macallan uint8_t *data8 = data; 1206 1.22 macallan for (i = 0; i < he; i++) { 1207 1.22 macallan gftfb_wait_fifo(sc, 2); 1208 1.22 macallan mask = *data8; 1209 1.26 riastrad gftfb_write4(sc, NGLE_REG_8, mask << 24); 1210 1.22 macallan gftfb_write4(sc, NGLE_REG_9, (wi << 16) | 1); 1211 1.22 macallan data8++; 1212 1.22 macallan } 1213 1.22 macallan } else { 1214 1.22 macallan uint16_t *data16 = data; 1215 1.22 macallan for (i = 0; i < he; i++) { 1216 1.22 macallan gftfb_wait_fifo(sc, 2); 1217 1.22 macallan mask = *data16; 1218 1.26 riastrad gftfb_write4(sc, NGLE_REG_8, mask << 16); 1219 1.22 macallan gftfb_write4(sc, NGLE_REG_9, (wi << 16) | 1); 1220 1.22 macallan data16++; 1221 1.22 macallan } 1222 1.22 macallan } 1223 1.22 macallan 1224 1.22 macallan if (rv == GC_ADD) 1225 1.22 macallan glyphcache_add(&sc->sc_gc, c, x, y); 1226 1.22 macallan } 1227 1.22 macallan 1228 1.22 macallan static void 1229 1.22 macallan gftfb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1230 1.22 macallan { 1231 1.22 macallan struct rasops_info *ri = cookie; 1232 1.22 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1233 1.22 macallan struct vcons_screen *scr = ri->ri_hw; 1234 1.22 macallan struct gftfb_softc *sc = scr->scr_cookie; 1235 1.3 macallan int x, y, wi, he, rv = GC_NOPE; 1236 1.3 macallan uint32_t bg; 1237 1.12 macallan 1238 1.3 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1239 1.3 macallan return; 1240 1.2 macallan 1241 1.3 macallan if (!CHAR_IN_FONT(c, font)) 1242 1.2 macallan return; 1243 1.2 macallan 1244 1.4 macallan if (row == ri->ri_crow && col == ri->ri_ccol) { 1245 1.4 macallan ri->ri_flg &= ~RI_CURSOR; 1246 1.4 macallan } 1247 1.4 macallan 1248 1.3 macallan wi = font->fontwidth; 1249 1.3 macallan he = font->fontheight; 1250 1.3 macallan 1251 1.3 macallan x = ri->ri_xorigin + col * wi; 1252 1.3 macallan y = ri->ri_yorigin + row * he; 1253 1.12 macallan 1254 1.3 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1255 1.3 macallan 1256 1.3 macallan if (c == 0x20) { 1257 1.3 macallan gftfb_rectfill(sc, x, y, wi, he, bg); 1258 1.3 macallan return; 1259 1.3 macallan } 1260 1.12 macallan 1261 1.3 macallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1262 1.3 macallan if (rv == GC_OK) 1263 1.2 macallan return; 1264 1.3 macallan 1265 1.5 macallan if (sc->sc_hwmode != HW_FB) gftfb_setup_fb(sc); 1266 1.2 macallan sc->sc_putchar(cookie, row, col, c, attr); 1267 1.3 macallan 1268 1.3 macallan if (rv == GC_ADD) 1269 1.3 macallan glyphcache_add(&sc->sc_gc, c, x, y); 1270 1.2 macallan } 1271 1.2 macallan 1272 1.2 macallan static void 1273 1.2 macallan gftfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1274 1.2 macallan { 1275 1.2 macallan struct rasops_info *ri = cookie; 1276 1.2 macallan struct vcons_screen *scr = ri->ri_hw; 1277 1.2 macallan struct gftfb_softc *sc = scr->scr_cookie; 1278 1.2 macallan int32_t xs, xd, y, width, height; 1279 1.26 riastrad 1280 1.2 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1281 1.26 riastrad if (ri->ri_crow == row && 1282 1.4 macallan (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) && 1283 1.4 macallan (ri->ri_flg & RI_CURSOR)) { 1284 1.4 macallan gftfb_nuke_cursor(ri); 1285 1.4 macallan } 1286 1.4 macallan 1287 1.2 macallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1288 1.2 macallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1289 1.2 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1290 1.2 macallan width = ri->ri_font->fontwidth * ncols; 1291 1.2 macallan height = ri->ri_font->fontheight; 1292 1.2 macallan gftfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc); 1293 1.26 riastrad if (ri->ri_crow == row && 1294 1.4 macallan (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols))) 1295 1.4 macallan ri->ri_flg &= ~RI_CURSOR; 1296 1.2 macallan } 1297 1.2 macallan } 1298 1.2 macallan 1299 1.2 macallan static void 1300 1.2 macallan gftfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1301 1.2 macallan { 1302 1.2 macallan struct rasops_info *ri = cookie; 1303 1.2 macallan struct vcons_screen *scr = ri->ri_hw; 1304 1.2 macallan struct gftfb_softc *sc = scr->scr_cookie; 1305 1.2 macallan int32_t x, y, width, height, fg, bg, ul; 1306 1.26 riastrad 1307 1.2 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1308 1.2 macallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1309 1.2 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1310 1.2 macallan width = ri->ri_font->fontwidth * ncols; 1311 1.2 macallan height = ri->ri_font->fontheight; 1312 1.2 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1313 1.2 macallan 1314 1.2 macallan gftfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1315 1.26 riastrad if (ri->ri_crow == row && 1316 1.4 macallan (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols))) 1317 1.4 macallan ri->ri_flg &= ~RI_CURSOR; 1318 1.2 macallan } 1319 1.2 macallan } 1320 1.2 macallan 1321 1.2 macallan static void 1322 1.2 macallan gftfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1323 1.2 macallan { 1324 1.2 macallan struct rasops_info *ri = cookie; 1325 1.2 macallan struct vcons_screen *scr = ri->ri_hw; 1326 1.2 macallan struct gftfb_softc *sc = scr->scr_cookie; 1327 1.2 macallan int32_t x, ys, yd, width, height; 1328 1.2 macallan 1329 1.2 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1330 1.4 macallan if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) && 1331 1.4 macallan (ri->ri_flg & RI_CURSOR)) { 1332 1.4 macallan gftfb_nuke_cursor(ri); 1333 1.4 macallan } 1334 1.2 macallan x = ri->ri_xorigin; 1335 1.2 macallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1336 1.2 macallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1337 1.2 macallan width = ri->ri_emuwidth; 1338 1.2 macallan height = ri->ri_font->fontheight * nrows; 1339 1.2 macallan gftfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc); 1340 1.4 macallan if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows)) 1341 1.4 macallan ri->ri_flg &= ~RI_CURSOR; 1342 1.2 macallan } 1343 1.2 macallan } 1344 1.2 macallan 1345 1.2 macallan static void 1346 1.2 macallan gftfb_eraserows(void *cookie, int row, int nrows, long fillattr) 1347 1.2 macallan { 1348 1.2 macallan struct rasops_info *ri = cookie; 1349 1.2 macallan struct vcons_screen *scr = ri->ri_hw; 1350 1.2 macallan struct gftfb_softc *sc = scr->scr_cookie; 1351 1.2 macallan int32_t x, y, width, height, fg, bg, ul; 1352 1.26 riastrad 1353 1.2 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1354 1.2 macallan x = ri->ri_xorigin; 1355 1.2 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1356 1.2 macallan width = ri->ri_emuwidth; 1357 1.2 macallan height = ri->ri_font->fontheight * nrows; 1358 1.2 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1359 1.2 macallan 1360 1.2 macallan gftfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1361 1.4 macallan 1362 1.4 macallan if (ri->ri_crow >= row && ri->ri_crow < (row + nrows)) 1363 1.4 macallan ri->ri_flg &= ~RI_CURSOR; 1364 1.2 macallan } 1365 1.2 macallan } 1366 1.7 macallan 1367 1.7 macallan /* 1368 1.7 macallan * cursor sprite handling 1369 1.7 macallan * like most hw info, xf86 3.3 -> nglehdw.h was used as documentation 1370 1.7 macallan * problem is, the PCI EG doesn't quite behave like an S9000_ID_ARTIST 1371 1.28 macallan * the cursor position register behaves like the one on HCRX while using 1372 1.7 macallan * the same address as Artist, incuding the enable bit and weird handling 1373 1.7 macallan * of negative coordinates. The rest of it, colour map, sprite image etc., 1374 1.7 macallan * behave like Artist. 1375 1.7 macallan */ 1376 1.26 riastrad 1377 1.7 macallan static void 1378 1.7 macallan gftfb_move_cursor(struct gftfb_softc *sc, int x, int y) 1379 1.7 macallan { 1380 1.7 macallan uint32_t pos; 1381 1.7 macallan 1382 1.7 macallan sc->sc_cursor_x = x; 1383 1.7 macallan x -= sc->sc_hot_x; 1384 1.7 macallan sc->sc_cursor_y = y; 1385 1.7 macallan y -= sc->sc_hot_y; 1386 1.7 macallan 1387 1.7 macallan if (x < 0) x = 0x1000 - x; 1388 1.7 macallan if (y < 0) y = 0x1000 - y; 1389 1.7 macallan pos = (x << 16) | y; 1390 1.7 macallan if (sc->sc_enabled) pos |= 0x80000000; 1391 1.29 macallan gftfb_wait_fifo(sc, 2); 1392 1.21 macallan gftfb_write4(sc, NGLE_REG_17, pos); 1393 1.7 macallan } 1394 1.7 macallan 1395 1.7 macallan static int 1396 1.7 macallan gftfb_do_cursor(struct gftfb_softc *sc, struct wsdisplay_cursor *cur) 1397 1.7 macallan { 1398 1.7 macallan if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1399 1.7 macallan 1400 1.7 macallan sc->sc_enabled = cur->enable; 1401 1.7 macallan cur->which |= WSDISPLAY_CURSOR_DOPOS; 1402 1.7 macallan } 1403 1.7 macallan if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1404 1.7 macallan 1405 1.7 macallan sc->sc_hot_x = cur->hot.x; 1406 1.7 macallan sc->sc_hot_y = cur->hot.y; 1407 1.7 macallan cur->which |= WSDISPLAY_CURSOR_DOPOS; 1408 1.7 macallan } 1409 1.7 macallan if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1410 1.7 macallan 1411 1.7 macallan gftfb_move_cursor(sc, cur->pos.x, cur->pos.y); 1412 1.7 macallan } 1413 1.7 macallan if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1414 1.7 macallan uint32_t rgb; 1415 1.7 macallan uint8_t r[2], g[2], b[2]; 1416 1.7 macallan 1417 1.7 macallan copyin(cur->cmap.blue, b, 2); 1418 1.7 macallan copyin(cur->cmap.green, g, 2); 1419 1.7 macallan copyin(cur->cmap.red, r, 2); 1420 1.7 macallan mutex_enter(&sc->sc_hwlock); 1421 1.7 macallan gftfb_wait(sc); 1422 1.25 macallan gftfb_write4(sc, NGLE_REG_10, 1423 1.25 macallan BA(FractDcd, Otc24, Ots08, Addr24, 0, BINcmap, 0)); 1424 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x03000300); 1425 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 1426 1.7 macallan gftfb_wait(sc); 1427 1.21 macallan gftfb_write4(sc, NGLE_REG_3, 0); 1428 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0); 1429 1.21 macallan gftfb_write4(sc, NGLE_REG_4, 0); 1430 1.7 macallan rgb = (r[0] << 16) | (g[0] << 8) | b[0]; 1431 1.21 macallan gftfb_write4(sc, NGLE_REG_4, rgb); /* BG */ 1432 1.7 macallan rgb = (r[1] << 16) | (g[1] << 8) | b[1]; 1433 1.21 macallan gftfb_write4(sc, NGLE_REG_4, rgb); /* FG */ 1434 1.21 macallan gftfb_write4(sc, NGLE_REG_2, 0); 1435 1.21 macallan gftfb_write4(sc, NGLE_REG_26, 0x80008004); 1436 1.26 riastrad gftfb_setup_fb(sc); 1437 1.7 macallan mutex_exit(&sc->sc_hwlock); 1438 1.7 macallan 1439 1.7 macallan } 1440 1.7 macallan if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1441 1.7 macallan uint32_t buffer[128], latch, tmp; 1442 1.7 macallan int i; 1443 1.7 macallan 1444 1.7 macallan copyin(cur->mask, buffer, 512); 1445 1.7 macallan gftfb_wait(sc); 1446 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x300); 1447 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 1448 1.25 macallan gftfb_write4(sc, NGLE_REG_11, 1449 1.25 macallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcmask, 0)); 1450 1.21 macallan gftfb_write4(sc, NGLE_REG_3, 0); 1451 1.7 macallan for (i = 0; i < 128; i += 2) { 1452 1.7 macallan latch = 0; 1453 1.7 macallan tmp = buffer[i] & 0x80808080; 1454 1.7 macallan latch |= tmp >> 7; 1455 1.7 macallan tmp = buffer[i] & 0x40404040; 1456 1.7 macallan latch |= tmp >> 5; 1457 1.7 macallan tmp = buffer[i] & 0x20202020; 1458 1.7 macallan latch |= tmp >> 3; 1459 1.7 macallan tmp = buffer[i] & 0x10101010; 1460 1.7 macallan latch |= tmp >> 1; 1461 1.7 macallan tmp = buffer[i] & 0x08080808; 1462 1.7 macallan latch |= tmp << 1; 1463 1.7 macallan tmp = buffer[i] & 0x04040404; 1464 1.7 macallan latch |= tmp << 3; 1465 1.7 macallan tmp = buffer[i] & 0x02020202; 1466 1.7 macallan latch |= tmp << 5; 1467 1.7 macallan tmp = buffer[i] & 0x01010101; 1468 1.7 macallan latch |= tmp << 7; 1469 1.21 macallan gftfb_write4(sc, NGLE_REG_4, latch); 1470 1.7 macallan latch = 0; 1471 1.7 macallan tmp = buffer[i + 1] & 0x80808080; 1472 1.7 macallan latch |= tmp >> 7; 1473 1.7 macallan tmp = buffer[i + 1] & 0x40404040; 1474 1.7 macallan latch |= tmp >> 5; 1475 1.7 macallan tmp = buffer[i + 1] & 0x20202020; 1476 1.7 macallan latch |= tmp >> 3; 1477 1.7 macallan tmp = buffer[i + 1] & 0x10101010; 1478 1.7 macallan latch |= tmp >> 1; 1479 1.7 macallan tmp = buffer[i + 1] & 0x08080808; 1480 1.7 macallan latch |= tmp << 1; 1481 1.7 macallan tmp = buffer[i + 1] & 0x04040404; 1482 1.7 macallan latch |= tmp << 3; 1483 1.7 macallan tmp = buffer[i + 1] & 0x02020202; 1484 1.7 macallan latch |= tmp << 5; 1485 1.7 macallan tmp = buffer[i + 1] & 0x01010101; 1486 1.7 macallan latch |= tmp << 7; 1487 1.21 macallan gftfb_write4(sc, NGLE_REG_5, latch); 1488 1.7 macallan } 1489 1.7 macallan 1490 1.7 macallan copyin(cur->image, buffer, 512); 1491 1.7 macallan gftfb_wait(sc); 1492 1.21 macallan gftfb_write4(sc, NGLE_REG_14, 0x300); 1493 1.21 macallan gftfb_write4(sc, NGLE_REG_13, 0xffffffff); 1494 1.25 macallan gftfb_write4(sc, NGLE_REG_11, 1495 1.25 macallan BA(IndexedDcd, Otc32, 0, AddrLong, 0, BINcursor, 0)); 1496 1.21 macallan gftfb_write4(sc, NGLE_REG_3, 0); 1497 1.7 macallan for (i = 0; i < 128; i += 2) { 1498 1.7 macallan latch = 0; 1499 1.7 macallan tmp = buffer[i] & 0x80808080; 1500 1.7 macallan latch |= tmp >> 7; 1501 1.7 macallan tmp = buffer[i] & 0x40404040; 1502 1.7 macallan latch |= tmp >> 5; 1503 1.7 macallan tmp = buffer[i] & 0x20202020; 1504 1.7 macallan latch |= tmp >> 3; 1505 1.7 macallan tmp = buffer[i] & 0x10101010; 1506 1.7 macallan latch |= tmp >> 1; 1507 1.7 macallan tmp = buffer[i] & 0x08080808; 1508 1.7 macallan latch |= tmp << 1; 1509 1.7 macallan tmp = buffer[i] & 0x04040404; 1510 1.7 macallan latch |= tmp << 3; 1511 1.7 macallan tmp = buffer[i] & 0x02020202; 1512 1.7 macallan latch |= tmp << 5; 1513 1.7 macallan tmp = buffer[i] & 0x01010101; 1514 1.7 macallan latch |= tmp << 7; 1515 1.21 macallan gftfb_write4(sc, NGLE_REG_4, latch); 1516 1.7 macallan latch = 0; 1517 1.7 macallan tmp = buffer[i + 1] & 0x80808080; 1518 1.7 macallan latch |= tmp >> 7; 1519 1.7 macallan tmp = buffer[i + 1] & 0x40404040; 1520 1.7 macallan latch |= tmp >> 5; 1521 1.7 macallan tmp = buffer[i + 1] & 0x20202020; 1522 1.7 macallan latch |= tmp >> 3; 1523 1.7 macallan tmp = buffer[i + 1] & 0x10101010; 1524 1.7 macallan latch |= tmp >> 1; 1525 1.7 macallan tmp = buffer[i + 1] & 0x08080808; 1526 1.7 macallan latch |= tmp << 1; 1527 1.7 macallan tmp = buffer[i + 1] & 0x04040404; 1528 1.7 macallan latch |= tmp << 3; 1529 1.7 macallan tmp = buffer[i + 1] & 0x02020202; 1530 1.7 macallan latch |= tmp << 5; 1531 1.7 macallan tmp = buffer[i + 1] & 0x01010101; 1532 1.7 macallan latch |= tmp << 7; 1533 1.21 macallan gftfb_write4(sc, NGLE_REG_5, latch); 1534 1.7 macallan } 1535 1.7 macallan gftfb_setup_fb(sc); 1536 1.7 macallan } 1537 1.7 macallan 1538 1.7 macallan return 0; 1539 1.7 macallan } 1540 1.8 macallan 1541 1.8 macallan static void 1542 1.8 macallan gftfb_set_video(struct gftfb_softc *sc, int on) 1543 1.8 macallan { 1544 1.8 macallan if (sc->sc_video_on == on) 1545 1.8 macallan return; 1546 1.26 riastrad 1547 1.8 macallan sc->sc_video_on = on; 1548 1.8 macallan 1549 1.8 macallan gftfb_wait(sc); 1550 1.8 macallan if (on) { 1551 1.21 macallan gftfb_write4(sc, NGLE_REG_21, 1552 1.21 macallan gftfb_read4(sc, NGLE_REG_21) | 0x0a000000); 1553 1.21 macallan gftfb_write4(sc, NGLE_REG_27, 1554 1.21 macallan gftfb_read4(sc, NGLE_REG_27) | 0x00800000); 1555 1.8 macallan } else { 1556 1.21 macallan gftfb_write4(sc, NGLE_REG_21, 1557 1.21 macallan gftfb_read4(sc, NGLE_REG_21) & ~0x0a000000); 1558 1.21 macallan gftfb_write4(sc, NGLE_REG_27, 1559 1.21 macallan gftfb_read4(sc, NGLE_REG_27) & ~0x00800000); 1560 1.8 macallan } 1561 1.8 macallan } 1562