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