1 /* $NetBSD: gffb.c,v 1.27 2025/08/30 09:29:14 macallan Exp $ */ 2 3 /* 4 * Copyright (c) 2013 Michael Lorenz 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * A console driver for nvidia geforce graphics controllers 30 * tested on macppc only so far, should work on other hardware as long as 31 * something sets up a usable graphics mode and sets the right device properties 32 * This driver should work with all NV1x hardware but so far it's been tested 33 * only on NV11 / GeForce2 MX. Needs testing with more hardware and if 34 * successful, PCI IDs need to be added to gffb_match() 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: gffb.c,v 1.27 2025/08/30 09:29:14 macallan Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/device.h> 44 #include <sys/lwp.h> 45 #include <sys/kauth.h> 46 #include <sys/atomic.h> 47 48 #include <dev/pci/pcivar.h> 49 #include <dev/pci/pcireg.h> 50 #include <dev/pci/pcidevs.h> 51 #include <dev/pci/pciio.h> 52 #include <dev/pci/gffbreg.h> 53 54 #include <dev/wscons/wsdisplayvar.h> 55 #include <dev/wscons/wsconsio.h> 56 #include <dev/wsfont/wsfont.h> 57 #include <dev/rasops/rasops.h> 58 #include <dev/wscons/wsdisplay_vconsvar.h> 59 #include <dev/pci/wsdisplay_pci.h> 60 #include <dev/wscons/wsdisplay_glyphcachevar.h> 61 62 #include "opt_gffb.h" 63 #include "opt_vcons.h" 64 65 #ifdef GFFB_DEBUG 66 #define DPRINTF printf 67 #else 68 #define DPRINTF while(0) printf 69 #endif 70 71 struct gffb_softc { 72 device_t sc_dev; 73 74 pci_chipset_tag_t sc_pc; 75 pcitag_t sc_pcitag; 76 77 bus_space_tag_t sc_memt; 78 bus_space_tag_t sc_iot; 79 80 bus_space_handle_t sc_regh, sc_fbh; 81 bus_addr_t sc_fb, sc_reg; 82 bus_size_t sc_fbsize, sc_regsize; 83 uint8_t *sc_fbaddr; 84 size_t sc_vramsize; 85 uint32_t sc_fboffset; 86 87 int sc_width, sc_height, sc_depth, sc_stride; 88 int sc_locked, sc_accel, sc_mobile, sc_video; 89 struct vcons_screen sc_console_screen; 90 struct wsscreen_descr sc_defaultscreen_descr; 91 const struct wsscreen_descr *sc_screens[1]; 92 struct wsscreen_list sc_screenlist; 93 struct vcons_data vd; 94 int sc_mode, sc_arch; 95 u_char sc_cmap_red[256]; 96 u_char sc_cmap_green[256]; 97 u_char sc_cmap_blue[256]; 98 int sc_put, sc_current, sc_free; 99 uint32_t sc_rop; 100 void (*sc_putchar)(void *, int, int, u_int, long); 101 kmutex_t sc_lock; 102 glyphcache sc_gc; 103 }; 104 105 static int gffb_match(device_t, cfdata_t, void *); 106 static void gffb_attach(device_t, device_t, void *); 107 108 CFATTACH_DECL_NEW(gffb, sizeof(struct gffb_softc), 109 gffb_match, gffb_attach, NULL, NULL); 110 111 static int gffb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 112 static paddr_t gffb_mmap(void *, void *, off_t, int); 113 static void gffb_init_screen(void *, struct vcons_screen *, int, long *); 114 115 static int gffb_putcmap(struct gffb_softc *, struct wsdisplay_cmap *); 116 static int gffb_getcmap(struct gffb_softc *, struct wsdisplay_cmap *); 117 static void gffb_restore_palette(struct gffb_softc *); 118 static int gffb_putpalreg(struct gffb_softc *, uint8_t, uint8_t, 119 uint8_t, uint8_t); 120 static void gffb_setvideo(struct gffb_softc *, int); 121 122 static void gffb_init(struct gffb_softc *); 123 124 static void gffb_make_room(struct gffb_softc *, int); 125 static void gffb_sync(struct gffb_softc *); 126 127 static void gffb_rectfill(struct gffb_softc *, int, int, int, int, 128 uint32_t); 129 static void gffb_bitblt(void *, int, int, int, int, int, int, int); 130 static void gffb_rop(struct gffb_softc *, int); 131 132 static void gffb_cursor(void *, int, int, int); 133 static void gffb_putchar(void *, int, int, u_int, long); 134 static void gffb_copycols(void *, int, int, int, int); 135 static void gffb_erasecols(void *, int, int, int, long); 136 static void gffb_copyrows(void *, int, int, int); 137 static void gffb_eraserows(void *, int, int, long); 138 139 #define GFFB_READ_4(o) bus_space_read_stream_4(sc->sc_memt, sc->sc_regh, (o)) 140 #define GFFB_READ_1(o) bus_space_read_1(sc->sc_memt, sc->sc_regh, (o)) 141 #define GFFB_WRITE_4(o, v) bus_space_write_stream_4(sc->sc_memt, sc->sc_regh, (o), (v)) 142 #define GFFB_WRITE_1(o, v) bus_space_write_1(sc->sc_memt, sc->sc_regh, (o), (v)) 143 144 struct wsdisplay_accessops gffb_accessops = { 145 gffb_ioctl, 146 gffb_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 void 156 gffb_write_crtc(struct gffb_softc *sc, int head, uint8_t reg, uint8_t val) 157 { 158 if (head == 0) { 159 GFFB_WRITE_1(GFFB_PCIO0 + 0x3d4, reg); 160 GFFB_WRITE_1(GFFB_PCIO0 + 0x3d5, val); 161 } else { 162 GFFB_WRITE_1(GFFB_PCIO1 + 0x3d4, reg); 163 GFFB_WRITE_1(GFFB_PCIO1 + 0x3d5, val); 164 } 165 } 166 167 static uint8_t 168 gffb_read_crtc(struct gffb_softc *sc, int head, uint8_t reg) 169 { 170 if (head == 0) { 171 GFFB_WRITE_1(GFFB_PCIO0 + 0x3d4, reg); 172 return GFFB_READ_1(GFFB_PCIO0 + 0x3d5); 173 } else { 174 GFFB_WRITE_1(GFFB_PCIO1 + 0x3d4, reg); 175 return GFFB_READ_1(GFFB_PCIO1 + 0x3d5); 176 } 177 } 178 179 static int 180 gffb_match(device_t parent, cfdata_t match, void *aux) 181 { 182 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 183 184 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) 185 return 0; 186 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_NVIDIA) 187 return 0; 188 189 /* only cards tested on so far - likely needs a list */ 190 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NVIDIA_GEFORCE2MX) 191 return 100; 192 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NVIDIA_GEFORCE_6800U) 193 return 100; 194 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NVIDIA_GF_FXGO5200) 195 return 100; 196 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NVIDIA_GF_FX5200U) 197 return 100; 198 return (0); 199 } 200 201 static void 202 gffb_attach(device_t parent, device_t self, void *aux) 203 { 204 struct gffb_softc *sc = device_private(self); 205 struct pci_attach_args *pa = aux; 206 struct rasops_info *ri; 207 bus_space_tag_t tag; 208 struct wsemuldisplaydev_attach_args aa; 209 prop_dictionary_t dict; 210 unsigned long defattr; 211 pcireg_t reg; 212 bool is_console = FALSE; 213 uint32_t addr; 214 int i, j, f; 215 uint8_t cmap[768]; 216 217 sc->sc_pc = pa->pa_pc; 218 sc->sc_pcitag = pa->pa_tag; 219 sc->sc_memt = pa->pa_memt; 220 sc->sc_iot = pa->pa_iot; 221 sc->sc_dev = self; 222 223 sc->sc_mobile = 0; 224 sc->sc_video = 0; 225 226 /* first, see what kind of chip we've got */ 227 reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_ID_REG); 228 switch (PCI_PRODUCT(reg)) { 229 case PCI_PRODUCT_NVIDIA_GEFORCE2MX: 230 sc->sc_accel = true; 231 sc->sc_arch = 10; 232 break; 233 case PCI_PRODUCT_NVIDIA_GEFORCE_6800U: 234 sc->sc_accel = false; 235 sc->sc_arch = 40; 236 break; 237 case PCI_PRODUCT_NVIDIA_GF_FXGO5200: 238 sc->sc_mobile = 1; 239 /* FALLTHROUGH */ 240 case PCI_PRODUCT_NVIDIA_GF_FX5200U: 241 sc->sc_accel = true; 242 sc->sc_arch = 30; 243 break; 244 default: 245 sc->sc_accel = false; 246 sc->sc_arch = 0; 247 } 248 249 pci_aprint_devinfo(pa, NULL); 250 DPRINTF("%s accel %d arch %d\n", __func__, sc->sc_accel, sc->sc_arch); 251 /* fill in parameters from properties */ 252 dict = device_properties(self); 253 if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) { 254 aprint_error("%s: no width property\n", device_xname(self)); 255 return; 256 } 257 if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) { 258 aprint_error("%s: no height property\n", device_xname(self)); 259 return; 260 } 261 262 #ifdef GLYPHCACHE_DEBUG 263 /* leave some visible VRAM unused so we can see the glyph cache */ 264 sc->sc_height -= 300; 265 #endif 266 267 if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) { 268 aprint_error("%s: no depth property\n", device_xname(self)); 269 return; 270 } 271 if (!prop_dictionary_get_uint32(dict, "linebytes", &sc->sc_stride)) { 272 aprint_error("%s: no linebytes property\n", 273 device_xname(self)); 274 return; 275 } 276 277 /* 278 * on !2MX we need to use the firmware's offset - for some reason 279 * register writes to anything other than the DACs go wrong 280 */ 281 sc->sc_fboffset = 0; 282 if (prop_dictionary_get_uint32(dict, "address", &addr)) { 283 sc->sc_fboffset = addr & 0x000fffff; /* XXX */ 284 } 285 DPRINTF("%s: fboffset %8x\n", __func__, sc->sc_fboffset); 286 prop_dictionary_get_bool(dict, "is_console", &is_console); 287 288 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, 0, 289 &tag, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) { 290 aprint_error("%s: failed to map registers.\n", 291 device_xname(sc->sc_dev)); 292 } 293 /* 294 * first thing we need to make sure register access uses host byte order 295 * so we can recycle as much of xf86-video-nv as possible 296 */ 297 #if BYTE_ORDER == BIG_ENDIAN 298 uint32_t mreg = GFFB_READ_4(GFFB_PMC + 4); 299 if ((mreg & 0x01000001) == 0) { 300 GFFB_WRITE_4(GFFB_PMC + 4, 0x01000001); 301 } 302 #endif 303 sc->sc_vramsize = GFFB_READ_4(GFFB_VRAM) & 0xfff00000; 304 305 /* don't map more VRAM than we actually have */ 306 if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, 307 0x14, PCI_MAPREG_TYPE_MEM, &sc->sc_fb, &sc->sc_fbsize, &f)) { 308 aprint_error("%s: can't find the framebuffer?!\n", 309 device_xname(sc->sc_dev)); 310 } 311 if (sc->sc_vramsize == 0) sc->sc_vramsize = sc->sc_fbsize; 312 313 /* don't map (much) more than we actually need */ 314 if (bus_space_map(sc->sc_memt, sc->sc_fb, 0x1000000, 315 BUS_SPACE_MAP_PREFETCHABLE | BUS_SPACE_MAP_LINEAR, 316 &sc->sc_fbh)) { 317 aprint_error("%s: failed to map the framebuffer.\n", 318 device_xname(sc->sc_dev)); 319 } 320 sc->sc_fbaddr = bus_space_vaddr(tag, sc->sc_fbh); 321 322 aprint_normal("%s: %d MB aperture at 0x%08x\n", device_xname(self), 323 (int)(sc->sc_fbsize >> 20), (uint32_t)sc->sc_fb); 324 aprint_normal_dev(sc->sc_dev, "%d MB video memory\n", 325 (int)(sc->sc_vramsize >> 20)); 326 327 sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 328 "default", 329 0, 0, 330 NULL, 331 8, 16, 332 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_RESIZE, 333 NULL 334 }; 335 sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 336 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 337 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 338 sc->sc_locked = 0; 339 340 #ifdef GFFB_DEBUG 341 printf("put: %08x\n", GFFB_READ_4(GFFB_FIFO_PUT)); 342 printf("get: %08x\n", GFFB_READ_4(GFFB_FIFO_GET)); 343 #endif 344 345 /* 346 * we don't have hardware synchronization so we need a lock to serialize 347 * access to the DMA buffer between normal and kernel output 348 * actually it might be enough to use atomic ops on sc_current, sc_free 349 * etc. but for now we'll play it safe 350 * XXX we will probably deadlock if we take an interrupt while sc_lock 351 * is held and then try to printf() 352 */ 353 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 354 355 /* init engine here */ 356 gffb_init(sc); 357 gffb_setvideo(sc, 1); 358 359 #ifdef GFFB_DEBUG 360 printf("put: %08x\n", GFFB_READ_4(GFFB_FIFO_PUT)); 361 printf("get: %08x\n", GFFB_READ_4(GFFB_FIFO_GET)); 362 #endif 363 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 364 &gffb_accessops); 365 sc->vd.init_screen = gffb_init_screen; 366 367 368 ri = &sc->sc_console_screen.scr_ri; 369 370 if (sc->sc_accel) { 371 sc->sc_gc.gc_bitblt = gffb_bitblt; 372 sc->sc_gc.gc_blitcookie = sc; 373 sc->sc_gc.gc_rop = 0xcc; 374 sc->vd.show_screen_cookie = &sc->sc_gc; 375 sc->vd.show_screen_cb = glyphcache_adapt; 376 } 377 378 if (is_console) { 379 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 380 &defattr); 381 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 382 383 if (sc->sc_accel) { 384 gffb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 385 ri->ri_devcmap[(defattr >> 16) & 0xf]); 386 } else { 387 memset(sc->sc_fbaddr + sc->sc_fboffset, 388 ri->ri_devcmap[(defattr >> 16) & 0xf], 389 sc->sc_stride * sc->sc_height); 390 } 391 sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 392 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 393 sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 394 sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 395 396 if (sc->sc_accel) 397 glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 398 (0x800000 / sc->sc_stride) - sc->sc_height - 5, 399 sc->sc_width, 400 ri->ri_font->fontwidth, 401 ri->ri_font->fontheight, 402 defattr); 403 404 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 405 defattr); 406 vcons_replay_msgbuf(&sc->sc_console_screen); 407 } else { 408 /* 409 * since we're not the console we can postpone the rest 410 * until someone actually allocates a screen for us 411 */ 412 if (sc->sc_console_screen.scr_ri.ri_rows == 0) { 413 /* do some minimal setup to avoid weirdnesses later */ 414 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 415 &defattr); 416 } else 417 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 418 419 if (sc->sc_accel) 420 glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 421 (0x800000 / sc->sc_stride) - sc->sc_height - 5, 422 sc->sc_width, 423 ri->ri_font->fontwidth, 424 ri->ri_font->fontheight, 425 defattr); 426 } 427 428 j = 0; 429 rasops_get_cmap(ri, cmap, sizeof(cmap)); 430 for (i = 0; i < 256; i++) { 431 sc->sc_cmap_red[i] = cmap[j]; 432 sc->sc_cmap_green[i] = cmap[j + 1]; 433 sc->sc_cmap_blue[i] = cmap[j + 2]; 434 gffb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); 435 j += 3; 436 } 437 438 /* no suspend/resume support yet */ 439 if (!pmf_device_register(sc->sc_dev, NULL, NULL)) 440 aprint_error_dev(sc->sc_dev, 441 "couldn't establish power handler\n"); 442 443 aa.console = is_console; 444 aa.scrdata = &sc->sc_screenlist; 445 aa.accessops = &gffb_accessops; 446 aa.accesscookie = &sc->vd; 447 448 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 449 } 450 451 static int 452 gffb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 453 { 454 struct vcons_data *vd = v; 455 struct gffb_softc *sc = vd->cookie; 456 struct wsdisplay_fbinfo *wdf; 457 struct vcons_screen *ms = vd->active; 458 struct wsdisplay_param *param; 459 460 switch (cmd) { 461 case WSDISPLAYIO_GTYPE: 462 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 463 return 0; 464 465 /* PCI config read/write passthrough. */ 466 case PCI_IOC_CFGREAD: 467 case PCI_IOC_CFGWRITE: 468 return pci_devioctl(sc->sc_pc, sc->sc_pcitag, 469 cmd, data, flag, l); 470 471 case WSDISPLAYIO_GET_BUSID: 472 return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 473 sc->sc_pcitag, data); 474 475 case WSDISPLAYIO_GINFO: 476 if (ms == NULL) 477 return ENODEV; 478 wdf = (void *)data; 479 wdf->height = ms->scr_ri.ri_height; 480 wdf->width = ms->scr_ri.ri_width; 481 wdf->depth = ms->scr_ri.ri_depth; 482 wdf->cmsize = 256; 483 return 0; 484 485 case WSDISPLAYIO_GETCMAP: 486 return gffb_getcmap(sc, 487 (struct wsdisplay_cmap *)data); 488 489 case WSDISPLAYIO_PUTCMAP: 490 return gffb_putcmap(sc, 491 (struct wsdisplay_cmap *)data); 492 493 case WSDISPLAYIO_LINEBYTES: 494 *(u_int *)data = sc->sc_stride; 495 return 0; 496 497 case WSDISPLAYIO_SMODE: { 498 int new_mode = *(int*)data; 499 if (new_mode != sc->sc_mode) { 500 sc->sc_mode = new_mode; 501 if(new_mode == WSDISPLAYIO_MODE_EMUL) { 502 gffb_init(sc); 503 gffb_restore_palette(sc); 504 if (sc->sc_accel) { 505 glyphcache_wipe(&sc->sc_gc); 506 gffb_rectfill(sc, 0, 0, sc->sc_width, 507 sc->sc_height, ms->scr_ri.ri_devcmap[ 508 (ms->scr_defattr >> 16) & 0xf]); 509 } else { 510 memset(sc->sc_fbaddr + sc->sc_fboffset, 511 ms->scr_ri.ri_devcmap[ 512 (ms->scr_defattr >> 16) & 0xf], 513 sc->sc_stride * sc->sc_height); 514 } 515 vcons_redraw_screen(ms); 516 } 517 } 518 } 519 return 0; 520 521 case WSDISPLAYIO_GET_EDID: { 522 struct wsdisplayio_edid_info *d = data; 523 return wsdisplayio_get_edid(sc->sc_dev, d); 524 } 525 526 case WSDISPLAYIO_GET_FBINFO: { 527 struct wsdisplayio_fbinfo *fbi = data; 528 return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 529 } 530 531 case WSDISPLAYIO_GETPARAM: 532 param = (struct wsdisplay_param *)data; 533 if (sc->sc_mobile == 0) 534 return EPASSTHROUGH; 535 switch (param->param) { 536 #if 0 537 case WSDISPLAYIO_PARAM_BRIGHTNESS: 538 param->min = 0; 539 param->max = 255; 540 param->curval = sc->sc_bl_level; 541 return 0; 542 #endif 543 case WSDISPLAYIO_PARAM_BACKLIGHT: 544 param->min = 0; 545 param->max = 1; 546 param->curval = sc->sc_video; 547 return 0; 548 } 549 return EPASSTHROUGH; 550 551 case WSDISPLAYIO_SETPARAM: 552 param = (struct wsdisplay_param *)data; 553 if (sc->sc_mobile == 0) 554 return EPASSTHROUGH; 555 switch (param->param) { 556 #if 0 557 case WSDISPLAYIO_PARAM_BRIGHTNESS: 558 gffb_set_backlight(sc, param->curval); 559 return 0; 560 #endif 561 case WSDISPLAYIO_PARAM_BACKLIGHT: 562 gffb_setvideo(sc, param->curval); 563 return 0; 564 } 565 return EPASSTHROUGH; 566 567 case WSDISPLAYIO_GVIDEO: 568 if (sc->sc_video) 569 *(int *)data = WSDISPLAYIO_VIDEO_ON; 570 else 571 *(int *)data = WSDISPLAYIO_VIDEO_OFF; 572 return 0; 573 574 case WSDISPLAYIO_SVIDEO: 575 gffb_setvideo(sc, *(int *)data == WSDISPLAYIO_VIDEO_ON); 576 return 0; 577 } 578 return EPASSTHROUGH; 579 } 580 581 static paddr_t 582 gffb_mmap(void *v, void *vs, off_t offset, int prot) 583 { 584 struct vcons_data *vd = v; 585 struct gffb_softc *sc = vd->cookie; 586 paddr_t pa; 587 588 /* 'regular' framebuffer mmap()ing */ 589 if (offset < sc->sc_vramsize) { 590 pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset + 0x2000, 591 0, prot, BUS_SPACE_MAP_LINEAR); 592 return pa; 593 } 594 595 /* 596 * restrict all other mappings to processes with superuser privileges 597 * or the kernel itself 598 */ 599 if (kauth_authorize_machdep(kauth_cred_get(), 600 KAUTH_MACHDEP_UNMANAGEDMEM, 601 NULL, NULL, NULL, NULL) != 0) { 602 aprint_normal("%s: mmap() rejected.\n", 603 device_xname(sc->sc_dev)); 604 return -1; 605 } 606 607 if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) { 608 pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 609 BUS_SPACE_MAP_LINEAR); 610 return pa; 611 } 612 613 if ((offset >= sc->sc_reg) && 614 (offset < (sc->sc_reg + sc->sc_regsize))) { 615 pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 616 BUS_SPACE_MAP_LINEAR); 617 return pa; 618 } 619 620 #ifdef PCI_MAGIC_IO_RANGE 621 /* allow mapping of IO space */ 622 if ((offset >= PCI_MAGIC_IO_RANGE) && 623 (offset < PCI_MAGIC_IO_RANGE + 0x10000)) { 624 pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE, 625 0, prot, BUS_SPACE_MAP_LINEAR); 626 return pa; 627 } 628 #endif 629 630 return -1; 631 } 632 633 static void 634 gffb_init_screen(void *cookie, struct vcons_screen *scr, 635 int existing, long *defattr) 636 { 637 struct gffb_softc *sc = cookie; 638 struct rasops_info *ri = &scr->scr_ri; 639 640 ri->ri_depth = sc->sc_depth; 641 ri->ri_width = sc->sc_width; 642 ri->ri_height = sc->sc_height; 643 ri->ri_stride = sc->sc_stride; 644 if (sc->sc_depth == 8) 645 ri->ri_bits = sc->sc_fbaddr + sc->sc_fboffset; 646 ri->ri_flg = RI_CENTER; 647 ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA; 648 649 rasops_init(ri, 0, 0); 650 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_RESIZE; 651 scr->scr_flags |= VCONS_LOADFONT; 652 653 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 654 sc->sc_width / ri->ri_font->fontwidth); 655 656 ri->ri_hw = scr; 657 658 if (sc->sc_accel) { 659 sc->sc_putchar = ri->ri_ops.putchar; 660 ri->ri_ops.copyrows = gffb_copyrows; 661 ri->ri_ops.copycols = gffb_copycols; 662 ri->ri_ops.eraserows = gffb_eraserows; 663 ri->ri_ops.erasecols = gffb_erasecols; 664 ri->ri_ops.cursor = gffb_cursor; 665 ri->ri_ops.putchar = gffb_putchar; 666 } else { 667 scr->scr_flags |= VCONS_DONT_READ; 668 } 669 } 670 671 static int 672 gffb_putcmap(struct gffb_softc *sc, struct wsdisplay_cmap *cm) 673 { 674 u_char *r, *g, *b; 675 u_int index = cm->index; 676 u_int count = cm->count; 677 int i, error; 678 u_char rbuf[256], gbuf[256], bbuf[256]; 679 680 #ifdef GFFB_DEBUG 681 aprint_debug("putcmap: %d %d\n",index, count); 682 #endif 683 if (cm->index >= 256 || cm->count > 256 || 684 (cm->index + cm->count) > 256) 685 return EINVAL; 686 error = copyin(cm->red, &rbuf[index], count); 687 if (error) 688 return error; 689 error = copyin(cm->green, &gbuf[index], count); 690 if (error) 691 return error; 692 error = copyin(cm->blue, &bbuf[index], count); 693 if (error) 694 return error; 695 696 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 697 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 698 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 699 700 r = &sc->sc_cmap_red[index]; 701 g = &sc->sc_cmap_green[index]; 702 b = &sc->sc_cmap_blue[index]; 703 704 for (i = 0; i < count; i++) { 705 gffb_putpalreg(sc, index, *r, *g, *b); 706 index++; 707 r++, g++, b++; 708 } 709 return 0; 710 } 711 712 static int 713 gffb_getcmap(struct gffb_softc *sc, struct wsdisplay_cmap *cm) 714 { 715 u_int index = cm->index; 716 u_int count = cm->count; 717 int error; 718 719 if (index >= 255 || count > 256 || index + count > 256) 720 return EINVAL; 721 722 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 723 if (error) 724 return error; 725 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 726 if (error) 727 return error; 728 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 729 if (error) 730 return error; 731 732 return 0; 733 } 734 735 static void 736 gffb_restore_palette(struct gffb_softc *sc) 737 { 738 int i; 739 740 for (i = 0; i < (1 << sc->sc_depth); i++) { 741 gffb_putpalreg(sc, i, sc->sc_cmap_red[i], 742 sc->sc_cmap_green[i], sc->sc_cmap_blue[i]); 743 } 744 } 745 746 static int 747 gffb_putpalreg(struct gffb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, 748 uint8_t b) 749 { 750 /* port 0 */ 751 GFFB_WRITE_1(GFFB_PDIO0 + GFFB_PEL_IW, idx); 752 GFFB_WRITE_1(GFFB_PDIO0 + GFFB_PEL_D, r); 753 GFFB_WRITE_1(GFFB_PDIO0 + GFFB_PEL_D, g); 754 GFFB_WRITE_1(GFFB_PDIO0 + GFFB_PEL_D, b); 755 756 /* port 1 */ 757 GFFB_WRITE_1(GFFB_PDIO1 + GFFB_PEL_IW, idx); 758 GFFB_WRITE_1(GFFB_PDIO1 + GFFB_PEL_D, r); 759 GFFB_WRITE_1(GFFB_PDIO1 + GFFB_PEL_D, g); 760 GFFB_WRITE_1(GFFB_PDIO1 + GFFB_PEL_D, b); 761 762 return 0; 763 } 764 765 static void 766 gffb_setvideo(struct gffb_softc *sc, int on) 767 { 768 uint8_t reg0, reg1; 769 770 if (sc->sc_video == on) 771 return; 772 773 reg0 = gffb_read_crtc(sc, 0, 0x1a) & 0x3f; 774 reg1 = gffb_read_crtc(sc, 1, 0x1a) & 0x3f; 775 776 if (!on) { 777 reg0 |= 0xc0; 778 reg1 |= 0xc0; 779 } 780 781 gffb_write_crtc(sc, 0, 0x1a, reg0); 782 gffb_write_crtc(sc, 1, 0x1a, reg1); 783 784 if(sc->sc_mobile) { 785 uint32_t tmp_pmc, tmp_pcrt; 786 tmp_pmc = GFFB_READ_4(GFFB_PMC + 0x10F0) & 0x7FFFFFFF; 787 tmp_pcrt = GFFB_READ_4(GFFB_CRTC0 + 0x081C) & 0xFFFFFFFC; 788 if (on) { 789 tmp_pmc |= (1 << 31); 790 tmp_pcrt |= 0x1; 791 } 792 GFFB_WRITE_4(GFFB_PMC + 0x10F0, tmp_pmc); 793 GFFB_WRITE_4(GFFB_CRTC0 + 0x081C, tmp_pcrt); 794 } 795 sc->sc_video = on; 796 } 797 798 static void 799 gffb_dma_kickoff(struct gffb_softc *sc) 800 { 801 volatile uint32_t junk; 802 if (sc->sc_current != sc->sc_put) { 803 sc->sc_put = sc->sc_current; 804 bus_space_barrier(sc->sc_memt, sc->sc_fbh, 0, 0x1000000, 805 BUS_SPACE_BARRIER_WRITE); 806 junk = *sc->sc_fbaddr; 807 __USE(junk); 808 GFFB_WRITE_4(GFFB_FIFO_PUT, sc->sc_put); 809 bus_space_barrier(sc->sc_memt, sc->sc_regh, GFFB_FIFO_PUT, 4, 810 BUS_SPACE_BARRIER_WRITE); 811 } 812 } 813 814 static void 815 gffb_dmanext(struct gffb_softc *sc, uint32_t data) 816 { 817 bus_space_write_stream_4(sc->sc_memt, sc->sc_fbh, sc->sc_current, data); 818 sc->sc_current += 4; 819 } 820 821 static void 822 gffb_dmastart(struct gffb_softc *sc, uint32_t tag, int size) 823 { 824 if(sc->sc_free <= (size << 2)) 825 gffb_make_room(sc, size); 826 gffb_dmanext(sc, ((size) << 18) | (tag)); 827 sc->sc_free -= ((size + 1) << 2); 828 } 829 830 /* 831 * from xf86_video_nv/nv_xaa.c: 832 * There is a HW race condition with videoram command buffers. 833 * You can't jump to the location of your put offset. We write put 834 * at the jump offset + SKIPS dwords with noop padding in between 835 * to solve this problem 836 */ 837 838 #define SKIPS 8 839 840 static void 841 gffb_make_room(struct gffb_softc *sc, int size) 842 { 843 uint32_t get; 844 845 size = (size + 1) << 2; /* slots -> offset */ 846 847 while (sc->sc_free < size) { 848 get = GFFB_READ_4(GFFB_FIFO_GET); 849 850 if (sc->sc_put >= get) { 851 sc->sc_free = 0x2000 - sc->sc_current; 852 if (sc->sc_free < size) { 853 gffb_dmanext(sc, 0x20000000); 854 if(get <= (SKIPS << 2)) { 855 if (sc->sc_put <= (SKIPS << 2)) { 856 /* corner case - will be idle */ 857 GFFB_WRITE_4(GFFB_FIFO_PUT, 858 (SKIPS + 1) << 2); 859 } 860 do { 861 get =GFFB_READ_4(GFFB_FIFO_GET); 862 } while (get <= (SKIPS << 2)); 863 } 864 GFFB_WRITE_4(GFFB_FIFO_PUT, SKIPS << 2); 865 sc->sc_current = sc->sc_put = (SKIPS << 2); 866 sc->sc_free = get - ((SKIPS + 1) << 2); 867 } 868 } else 869 sc->sc_free = get - sc->sc_current - 4; 870 } 871 } 872 873 static void 874 gffb_sync(struct gffb_softc *sc) 875 { 876 int bail; 877 int i; 878 879 /* 880 * if there are commands in the buffer make sure the chip is actually 881 * trying to run them 882 */ 883 gffb_dma_kickoff(sc); 884 885 /* now wait for the command buffer to drain... */ 886 bail = 100000000; 887 while ((GFFB_READ_4(GFFB_FIFO_GET) != sc->sc_put) && (bail > 0)) { 888 bail--; 889 } 890 if (bail == 0) { 891 printf("FIFO isn't moving\n"); 892 goto crap; 893 } 894 895 /* ... and for the engine to go idle */ 896 bail = 100000000; 897 while((GFFB_READ_4(GFFB_BUSY) != 0) && (bail > 0)) { 898 bail--; 899 } 900 if (bail == 0) goto crap; 901 return; 902 crap: 903 /* if we time out fill the buffer with NOPs and cross fingers */ 904 DPRINTF("GET %08x\n", GFFB_READ_4(GFFB_FIFO_GET)); 905 sc->sc_put = 0; 906 sc->sc_current = 0; 907 for (i = 0; i < 0x2000; i += 4) 908 bus_space_write_stream_4(sc->sc_memt, sc->sc_fbh, i, 0); 909 aprint_error_dev(sc->sc_dev, "DMA lockup\n"); 910 } 911 912 void 913 gffb_init(struct gffb_softc *sc) 914 { 915 int i; 916 uint32_t foo; 917 918 if (!sc->sc_accel) return; 919 DPRINTF("%s offset %08x %08x\n", __func__, 920 GFFB_READ_4(GFFB_CRTC0 + GFFB_DISPLAYSTART), 921 GFFB_READ_4(GFFB_CRTC1 + GFFB_DISPLAYSTART)); 922 923 sc->sc_fboffset = 0x2000; 924 925 /* init display start */ 926 GFFB_WRITE_4(GFFB_CRTC0 + GFFB_DISPLAYSTART, sc->sc_fboffset); 927 GFFB_WRITE_4(GFFB_CRTC1 + GFFB_DISPLAYSTART, sc->sc_fboffset); 928 929 /* make sure we do 8bit per channel */ 930 GFFB_WRITE_1(GFFB_PDIO0 + GFFB_PEL_MASK, 0xff); 931 GFFB_WRITE_1(GFFB_PDIO1 + GFFB_PEL_MASK, 0xff); 932 933 /* DMA stuff. A whole lot of magic number voodoo from xf86-video-nv */ 934 GFFB_WRITE_4(GFFB_PMC + 0x140, 0); 935 GFFB_WRITE_4(GFFB_PMC + 0x200, 0xffff00ff); 936 GFFB_WRITE_4(GFFB_PMC + 0x200, 0xffffffff); 937 GFFB_WRITE_4(GFFB_PTIMER + 0x800, 8); 938 GFFB_WRITE_4(GFFB_PTIMER + 0x840, 3); 939 GFFB_WRITE_4(GFFB_PTIMER + 0x500, 0); 940 GFFB_WRITE_4(GFFB_PTIMER + 0x400, 0xffffffff); 941 for (i = 0; i < 8; i++) { 942 GFFB_WRITE_4(GFFB_PFB + 0x0240 + (i * 0x10), 0); 943 GFFB_WRITE_4(GFFB_PFB + 0x0244 + (i * 0x10), 944 sc->sc_vramsize - 1); 945 } 946 947 GFFB_WRITE_4(GFFB_PRAMIN, 0x80000010); 948 GFFB_WRITE_4(GFFB_PRAMIN + 0x04, 0x80011201); 949 GFFB_WRITE_4(GFFB_PRAMIN + 0x08, 0x80000011); 950 GFFB_WRITE_4(GFFB_PRAMIN + 0x0c, 0x80011202); 951 GFFB_WRITE_4(GFFB_PRAMIN + 0x10, 0x80000012); 952 GFFB_WRITE_4(GFFB_PRAMIN + 0x14, 0x80011203); 953 GFFB_WRITE_4(GFFB_PRAMIN + 0x18, 0x80000013); 954 GFFB_WRITE_4(GFFB_PRAMIN + 0x1c, 0x80011204); 955 GFFB_WRITE_4(GFFB_PRAMIN + 0x20, 0x80000014); 956 GFFB_WRITE_4(GFFB_PRAMIN + 0x24, 0x80011205); 957 GFFB_WRITE_4(GFFB_PRAMIN + 0x28, 0x80000015); 958 GFFB_WRITE_4(GFFB_PRAMIN + 0x2c, 0x80011206); 959 GFFB_WRITE_4(GFFB_PRAMIN + 0x30, 0x80000016); 960 GFFB_WRITE_4(GFFB_PRAMIN + 0x34, 0x80011207); 961 GFFB_WRITE_4(GFFB_PRAMIN + 0x38, 0x80000017); 962 GFFB_WRITE_4(GFFB_PRAMIN + 0x3c, 0x80011208); 963 GFFB_WRITE_4(GFFB_PRAMIN + 0x2000, 0x00003000); 964 GFFB_WRITE_4(GFFB_PRAMIN + 0x2004, sc->sc_vramsize - 1); 965 GFFB_WRITE_4(GFFB_PRAMIN + 0x2008, 0x00000002); 966 GFFB_WRITE_4(GFFB_PRAMIN + 0x200c, 0x00000002); 967 GFFB_WRITE_4(GFFB_PRAMIN + 0x2010, 0x01008062); /* nv10+ */ 968 GFFB_WRITE_4(GFFB_PRAMIN + 0x2014, 0); 969 GFFB_WRITE_4(GFFB_PRAMIN + 0x2018, 0x12001200); 970 GFFB_WRITE_4(GFFB_PRAMIN + 0x201c, 0); 971 GFFB_WRITE_4(GFFB_PRAMIN + 0x2020, 0x01008043); 972 GFFB_WRITE_4(GFFB_PRAMIN + 0x2024, 0); 973 GFFB_WRITE_4(GFFB_PRAMIN + 0x2028, 0); 974 GFFB_WRITE_4(GFFB_PRAMIN + 0x202c, 0); 975 GFFB_WRITE_4(GFFB_PRAMIN + 0x2030, 0x01008044); 976 GFFB_WRITE_4(GFFB_PRAMIN + 0x2034, 0x00000002); 977 GFFB_WRITE_4(GFFB_PRAMIN + 0x2038, 0); 978 GFFB_WRITE_4(GFFB_PRAMIN + 0x203c, 0); 979 GFFB_WRITE_4(GFFB_PRAMIN + 0x2040, 0x01008019); 980 GFFB_WRITE_4(GFFB_PRAMIN + 0x2044, 0); 981 GFFB_WRITE_4(GFFB_PRAMIN + 0x2048, 0); 982 GFFB_WRITE_4(GFFB_PRAMIN + 0x204c, 0); 983 GFFB_WRITE_4(GFFB_PRAMIN + 0x2050, 0x0100a05c); 984 GFFB_WRITE_4(GFFB_PRAMIN + 0x2054, 0); 985 GFFB_WRITE_4(GFFB_PRAMIN + 0x2058, 0); 986 GFFB_WRITE_4(GFFB_PRAMIN + 0x205c, 0); 987 /* XXX 0x0100805f if !WaitVSynvPossible */ 988 GFFB_WRITE_4(GFFB_PRAMIN + 0x2060, 0x0100805f); 989 GFFB_WRITE_4(GFFB_PRAMIN + 0x2064, 0); 990 GFFB_WRITE_4(GFFB_PRAMIN + 0x2068, 0x12001200); 991 GFFB_WRITE_4(GFFB_PRAMIN + 0x206c, 0); 992 GFFB_WRITE_4(GFFB_PRAMIN + 0x2070, 0x0100804a); 993 GFFB_WRITE_4(GFFB_PRAMIN + 0x2074, 0x00000002); 994 GFFB_WRITE_4(GFFB_PRAMIN + 0x2078, 0); 995 GFFB_WRITE_4(GFFB_PRAMIN + 0x207c, 0); 996 GFFB_WRITE_4(GFFB_PRAMIN + 0x2080, 0x01018077); 997 GFFB_WRITE_4(GFFB_PRAMIN + 0x2084, 0); 998 GFFB_WRITE_4(GFFB_PRAMIN + 0x2088, 0x12001200); 999 GFFB_WRITE_4(GFFB_PRAMIN + 0x208c, 0); 1000 GFFB_WRITE_4(GFFB_PRAMIN + 0x2090, 0x00003002); 1001 GFFB_WRITE_4(GFFB_PRAMIN + 0x2094, 0x00007fff); 1002 /* command buffer start with some flag in the lower bits */ 1003 GFFB_WRITE_4(GFFB_PRAMIN + 0x2098, sc->sc_vramsize | 0x00000002); 1004 GFFB_WRITE_4(GFFB_PRAMIN + 0x209c, 0x00000002); 1005 #if BYTE_ORDER == BIG_ENDIAN 1006 GFFB_WRITE_4(GFFB_PRAMIN + 0x2010, 0x01088062); 1007 GFFB_WRITE_4(GFFB_PRAMIN + 0x2020, 0x01088043); 1008 GFFB_WRITE_4(GFFB_PRAMIN + 0x2030, 0x01088044); 1009 GFFB_WRITE_4(GFFB_PRAMIN + 0x2040, 0x01088019); 1010 GFFB_WRITE_4(GFFB_PRAMIN + 0x2050, 0x0108a05c); 1011 GFFB_WRITE_4(GFFB_PRAMIN + 0x2060, 0x0108805f); 1012 GFFB_WRITE_4(GFFB_PRAMIN + 0x2070, 0x0108804a); 1013 GFFB_WRITE_4(GFFB_PRAMIN + 0x2080, 0x01098077); 1014 GFFB_WRITE_4(GFFB_PRAMIN + 0x2034, 0x00000001); 1015 GFFB_WRITE_4(GFFB_PRAMIN + 0x2074, 0x00000001); 1016 #endif 1017 /* PGRAPH setup */ 1018 GFFB_WRITE_4(GFFB_PGRAPH + 0x0080, 0xFFFFFFFF); 1019 GFFB_WRITE_4(GFFB_PGRAPH + 0x0080, 0x00000000); 1020 1021 GFFB_WRITE_4(GFFB_PGRAPH + 0x0140, 0x00000000); 1022 GFFB_WRITE_4(GFFB_PGRAPH + 0x0100, 0xFFFFFFFF); 1023 GFFB_WRITE_4(GFFB_PGRAPH + 0x0144, 0x10010100); 1024 GFFB_WRITE_4(GFFB_PGRAPH + 0x0714, 0xFFFFFFFF); 1025 GFFB_WRITE_4(GFFB_PGRAPH + 0x0720, 0x00000001); 1026 /* 1027 * xf86_video_nv does this in two writes, 1028 * not sure if they can be combined 1029 */ 1030 foo = GFFB_READ_4(GFFB_PGRAPH + 0x0710); 1031 foo &= 0x0007ff00; 1032 foo |= 0x00020100; 1033 GFFB_WRITE_4(GFFB_PGRAPH + 0x0710, foo); 1034 1035 /* NV_ARCH_10 */ 1036 if(sc->sc_arch == 10) { 1037 GFFB_WRITE_4(GFFB_PGRAPH + 0x0084, 0x00118700); 1038 GFFB_WRITE_4(GFFB_PGRAPH + 0x0088, 0x24E00810); 1039 GFFB_WRITE_4(GFFB_PGRAPH + 0x008C, 0x55DE0030); 1040 1041 for(i = 0; i < 128; i += 4) { 1042 GFFB_WRITE_4(GFFB_PGRAPH + 0x0B00 + i, 1043 GFFB_READ_4(GFFB_PFB + 0x0240 + i)); 1044 } 1045 1046 GFFB_WRITE_4(GFFB_PGRAPH + 0x640, 0); 1047 GFFB_WRITE_4(GFFB_PGRAPH + 0x644, 0); 1048 GFFB_WRITE_4(GFFB_PGRAPH + 0x684, sc->sc_vramsize - 1); 1049 GFFB_WRITE_4(GFFB_PGRAPH + 0x688, sc->sc_vramsize - 1); 1050 1051 GFFB_WRITE_4(GFFB_PGRAPH + 0x0810, 0x00000000); 1052 GFFB_WRITE_4(GFFB_PGRAPH + 0x0608, 0xFFFFFFFF); 1053 } else { 1054 /* nv30 */ 1055 GFFB_WRITE_4(GFFB_PGRAPH + 0x0084, 0x40108700); 1056 GFFB_WRITE_4(GFFB_PGRAPH + 0x0890, 0x00140000); 1057 GFFB_WRITE_4(GFFB_PGRAPH + 0x008C, 0xf00e0431); 1058 GFFB_WRITE_4(GFFB_PGRAPH + 0x0090, 0x00008000); 1059 GFFB_WRITE_4(GFFB_PGRAPH + 0x0610, 0xf04b1f36); 1060 GFFB_WRITE_4(GFFB_PGRAPH + 0x0B80, 0x1002d888); 1061 GFFB_WRITE_4(GFFB_PGRAPH + 0x0B88, 0x62ff007f); 1062 1063 for (i = 0; i < 128; i += 4) { 1064 GFFB_WRITE_4(GFFB_PGRAPH + 0x0900 + i, 1065 GFFB_READ_4(GFFB_PFB + 0x0240 + i)); 1066 GFFB_WRITE_4(GFFB_PGRAPH + 0x6900 + i, 1067 GFFB_READ_4(GFFB_PFB + 0x0240 + i)); 1068 } 1069 1070 GFFB_WRITE_4(GFFB_PGRAPH + 0x09A4, 1071 GFFB_READ_4(GFFB_PFB + 0x0200)); 1072 GFFB_WRITE_4(GFFB_PGRAPH + 0x09A8, 1073 GFFB_READ_4(GFFB_PFB + 0x0204)); 1074 GFFB_WRITE_4(GFFB_PGRAPH + 0x0750, 0x00EA0000); 1075 GFFB_WRITE_4(GFFB_PGRAPH + 0x0754, 1076 GFFB_READ_4(GFFB_PFB + 0x0200)); 1077 GFFB_WRITE_4(GFFB_PGRAPH + 0x0750, 0x00EA0004); 1078 GFFB_WRITE_4(GFFB_PGRAPH + 0x0754, 1079 GFFB_READ_4(GFFB_PFB + 0x0204)); 1080 1081 GFFB_WRITE_4(GFFB_PGRAPH + 0x0820, 0); 1082 GFFB_WRITE_4(GFFB_PGRAPH + 0x0824, 0); 1083 GFFB_WRITE_4(GFFB_PGRAPH + 0x0864, sc->sc_vramsize - 1); 1084 GFFB_WRITE_4(GFFB_PGRAPH + 0x0868, sc->sc_vramsize - 1); 1085 1086 GFFB_WRITE_4(GFFB_PGRAPH + 0x0B20, 0x00000000); 1087 GFFB_WRITE_4(GFFB_PGRAPH + 0x0B04, 0xFFFFFFFF); 1088 } 1089 1090 /* PFIFO setup */ 1091 GFFB_WRITE_4(GFFB_PGRAPH + 0x053C, 0); 1092 GFFB_WRITE_4(GFFB_PGRAPH + 0x0540, 0); 1093 GFFB_WRITE_4(GFFB_PGRAPH + 0x0544, 0x00007FFF); 1094 GFFB_WRITE_4(GFFB_PGRAPH + 0x0548, 0x00007FFF); 1095 1096 GFFB_WRITE_4(GFFB_PFIFO + 0x0500, 0); 1097 GFFB_WRITE_4(GFFB_PFIFO + 0x0504, 0x00000001); 1098 GFFB_WRITE_4(GFFB_PFIFO + 0x1200, 0); 1099 GFFB_WRITE_4(GFFB_PFIFO + 0x1250, 0); 1100 GFFB_WRITE_4(GFFB_PFIFO + 0x1204, 0x00000100); /* different on nv40 */ 1101 GFFB_WRITE_4(GFFB_PFIFO + 0x1240, 0); 1102 GFFB_WRITE_4(GFFB_PFIFO + 0x1244, 0); 1103 GFFB_WRITE_4(GFFB_PFIFO + 0x122c, 0x00001209); /* different on nv40 */ 1104 GFFB_WRITE_4(GFFB_PFIFO + 0x1000, 0); 1105 GFFB_WRITE_4(GFFB_PFIFO + 0x1050, 0); 1106 GFFB_WRITE_4(GFFB_PFIFO + 0x0210, 0x03000100); 1107 GFFB_WRITE_4(GFFB_PFIFO + 0x0214, 0x00000110); 1108 GFFB_WRITE_4(GFFB_PFIFO + 0x0218, 0x00000112); 1109 GFFB_WRITE_4(GFFB_PFIFO + 0x050c, 0x0000ffff); 1110 GFFB_WRITE_4(GFFB_PFIFO + 0x1258, 0x0000ffff); 1111 GFFB_WRITE_4(GFFB_PFIFO + 0x0140, 0); 1112 GFFB_WRITE_4(GFFB_PFIFO + 0x0100, 0xffffffff); 1113 GFFB_WRITE_4(GFFB_PFIFO + 0x1054, 0x00000001); 1114 GFFB_WRITE_4(GFFB_PFIFO + 0x1230, 0); 1115 GFFB_WRITE_4(GFFB_PFIFO + 0x1280, 0); 1116 #if BYTE_ORDER == BIG_ENDIAN 1117 GFFB_WRITE_4(GFFB_PFIFO + 0x1224, 0x800f0078); 1118 #else 1119 GFFB_WRITE_4(GFFB_PFIFO + 0x1224, 0x000f0078); 1120 #endif 1121 GFFB_WRITE_4(GFFB_PFIFO + 0x1220, 0x00000001); 1122 GFFB_WRITE_4(GFFB_PFIFO + 0x1200, 0x00000001); 1123 GFFB_WRITE_4(GFFB_PFIFO + 0x1250, 0x00000001); 1124 GFFB_WRITE_4(GFFB_PFIFO + 0x1254, 0x00000001); 1125 GFFB_WRITE_4(GFFB_PFIFO + 0x0500, 0x00000001); 1126 1127 GFFB_WRITE_4(GFFB_PMC + 0x8704, 1); 1128 GFFB_WRITE_4(GFFB_PMC + 0x8140, 0); 1129 GFFB_WRITE_4(GFFB_PMC + 0x8920, 0); 1130 GFFB_WRITE_4(GFFB_PMC + 0x8924, 0); 1131 GFFB_WRITE_4(GFFB_PMC + 0x8908, sc->sc_vramsize - 1); 1132 GFFB_WRITE_4(GFFB_PMC + 0x890C, sc->sc_vramsize - 1); 1133 GFFB_WRITE_4(GFFB_PMC + 0x1588, 0); 1134 1135 __asm("eieio; sync;"); 1136 GFFB_WRITE_4(GFFB_FIFO_GET, 0); 1137 GFFB_WRITE_4(GFFB_CMDSTART, 0x00000002); 1138 sc->sc_put = 0; 1139 sc->sc_current = 0; 1140 sc->sc_free = 0x2000; 1141 1142 for(i = 0; i < SKIPS; i++) 1143 gffb_dmanext(sc, 0); 1144 1145 gffb_dmanext(sc, 0x00040000); 1146 gffb_dmanext(sc, 0x80000010); 1147 gffb_dmanext(sc, 0x00042000); 1148 gffb_dmanext(sc, 0x80000011); 1149 gffb_dmanext(sc, 0x00044000); 1150 gffb_dmanext(sc, 0x80000012); 1151 gffb_dmanext(sc, 0x00046000); 1152 gffb_dmanext(sc, 0x80000013); 1153 gffb_dmanext(sc, 0x00048000); 1154 gffb_dmanext(sc, 0x80000014); 1155 gffb_dmanext(sc, 0x0004A000); 1156 gffb_dmanext(sc, 0x80000015); 1157 gffb_dmanext(sc, 0x0004C000); 1158 gffb_dmanext(sc, 0x80000016); 1159 gffb_dmanext(sc, 0x0004E000); 1160 gffb_dmanext(sc, 0x80000017); 1161 sc->sc_free = 0x2000 - sc->sc_current; 1162 1163 gffb_dmastart(sc, SURFACE_FORMAT, 4); 1164 gffb_dmanext(sc, SURFACE_FORMAT_DEPTH8); 1165 gffb_dmanext(sc, sc->sc_stride | (sc->sc_stride << 16)); 1166 gffb_dmanext(sc, sc->sc_fboffset); /* src offset */ 1167 gffb_dmanext(sc, sc->sc_fboffset); /* dst offset */ 1168 1169 gffb_dmastart(sc, RECT_FORMAT, 1); 1170 gffb_dmanext(sc, RECT_FORMAT_DEPTH8); 1171 1172 gffb_dmastart(sc, PATTERN_FORMAT, 1); 1173 gffb_dmanext(sc, PATTERN_FORMAT_DEPTH8); 1174 1175 gffb_dmastart(sc, PATTERN_COLOR_0, 4); 1176 gffb_dmanext(sc, 0xffffffff); 1177 gffb_dmanext(sc, 0xffffffff); 1178 gffb_dmanext(sc, 0xffffffff); 1179 gffb_dmanext(sc, 0xffffffff); 1180 1181 gffb_dmastart(sc, ROP_SET, 1); 1182 gffb_dmanext(sc, 0xcc); 1183 sc->sc_rop = 0xcc; 1184 DPRINTF("put %x current %x\n", sc->sc_put, sc->sc_current); 1185 1186 gffb_dma_kickoff(sc); 1187 DPRINTF("put %x current %x\n", sc->sc_put, sc->sc_current); 1188 #ifdef GFFB_DEBUG 1189 printf("put: %08x\n", GFFB_READ_4(GFFB_FIFO_PUT)); 1190 printf("get: %08x\n", GFFB_READ_4(GFFB_FIFO_GET)); 1191 #endif 1192 gffb_sync(sc); 1193 DPRINTF("put %x current %x\n", sc->sc_put, sc->sc_current); 1194 } 1195 1196 static void 1197 gffb_rop(struct gffb_softc *sc, int rop) 1198 { 1199 if (rop == sc->sc_rop) 1200 return; 1201 sc->sc_rop = rop; 1202 gffb_dmastart(sc, ROP_SET, 1); 1203 gffb_dmanext(sc, rop); 1204 } 1205 1206 static void 1207 gffb_rectfill(struct gffb_softc *sc, int x, int y, int wi, int he, 1208 uint32_t colour) 1209 { 1210 if (!sc->sc_accel) return; 1211 mutex_enter(&sc->sc_lock); 1212 gffb_rop(sc, 0xcc); 1213 1214 gffb_dmastart(sc, RECT_SOLID_COLOR, 1); 1215 gffb_dmanext(sc, colour); 1216 1217 gffb_dmastart(sc, RECT_SOLID_RECTS(0), 2); 1218 gffb_dmanext(sc, (x << 16) | y); 1219 gffb_dmanext(sc, (wi << 16) | he); 1220 gffb_dma_kickoff(sc); 1221 mutex_exit(&sc->sc_lock); 1222 } 1223 1224 static void 1225 gffb_bitblt(void *cookie, int xs, int ys, int xd, int yd, 1226 int wi, int he, int rop) 1227 { 1228 struct gffb_softc *sc = cookie; 1229 1230 if (!sc->sc_accel) return; 1231 mutex_enter(&sc->sc_lock); 1232 1233 gffb_rop(sc, rop); 1234 1235 gffb_dmastart(sc, BLIT_POINT_SRC, 3); 1236 gffb_dmanext(sc, (ys << 16) | xs); 1237 gffb_dmanext(sc, (yd << 16) | xd); 1238 gffb_dmanext(sc, (he << 16) | wi); 1239 gffb_dma_kickoff(sc); 1240 mutex_exit(&sc->sc_lock); 1241 } 1242 1243 static void 1244 gffb_cursor(void *cookie, int on, int row, int col) 1245 { 1246 struct rasops_info *ri = cookie; 1247 struct vcons_screen *scr = ri->ri_hw; 1248 struct gffb_softc *sc = scr->scr_cookie; 1249 int x, y, wi, he; 1250 1251 wi = ri->ri_font->fontwidth; 1252 he = ri->ri_font->fontheight; 1253 1254 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1255 x = ri->ri_ccol * wi + ri->ri_xorigin; 1256 y = ri->ri_crow * he + ri->ri_yorigin; 1257 if (ri->ri_flg & RI_CURSOR) { 1258 gffb_bitblt(sc, x, y, x, y, wi, he, 0x33); 1259 ri->ri_flg &= ~RI_CURSOR; 1260 } 1261 ri->ri_crow = row; 1262 ri->ri_ccol = col; 1263 if (on) { 1264 x = ri->ri_ccol * wi + ri->ri_xorigin; 1265 y = ri->ri_crow * he + ri->ri_yorigin; 1266 gffb_bitblt(sc, x, y, x, y, wi, he, 0x33); 1267 ri->ri_flg |= RI_CURSOR; 1268 } 1269 } else { 1270 scr->scr_ri.ri_crow = row; 1271 scr->scr_ri.ri_ccol = col; 1272 scr->scr_ri.ri_flg &= ~RI_CURSOR; 1273 } 1274 1275 } 1276 1277 static void 1278 gffb_putchar(void *cookie, int row, int col, u_int c, long attr) 1279 { 1280 struct rasops_info *ri = cookie; 1281 struct wsdisplay_font *font = PICK_FONT(ri, c); 1282 struct vcons_screen *scr = ri->ri_hw; 1283 struct gffb_softc *sc = scr->scr_cookie; 1284 int x, y, wi, he, rv = GC_NOPE; 1285 uint32_t bg; 1286 1287 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1288 return; 1289 1290 if (!CHAR_IN_FONT(c, font)) 1291 return; 1292 1293 wi = font->fontwidth; 1294 he = font->fontheight; 1295 1296 x = ri->ri_xorigin + col * wi; 1297 y = ri->ri_yorigin + row * he; 1298 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1299 1300 if (c == 0x20) { 1301 gffb_rectfill(sc, x, y, wi, he, bg); 1302 return; 1303 } 1304 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1305 if (rv == GC_OK) 1306 return; 1307 1308 /* 1309 * Use gffb_sync to wait for the engine to become idle before 1310 * we start scribbling into VRAM -- we wouldn't want to stomp on 1311 * a scroll in progress or a prior glyphcache_add that hasn't 1312 * completed yet on the GPU. 1313 */ 1314 mutex_enter(&sc->sc_lock); 1315 gffb_sync(sc); 1316 sc->sc_putchar(cookie, row, col, c, attr); 1317 mutex_exit(&sc->sc_lock); 1318 1319 /* 1320 * If glyphcache_try asked us to, cache the newly written 1321 * character. This will issue a gffb_bitblt which will wait 1322 * for our CPU writes to the framebuffer in VRAM to complete 1323 * before triggering GPU reads from the framebuffer in VRAM. 1324 */ 1325 if (rv == GC_ADD) { 1326 glyphcache_add(&sc->sc_gc, c, x, y); 1327 } 1328 } 1329 1330 static void 1331 gffb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1332 { 1333 struct rasops_info *ri = cookie; 1334 struct vcons_screen *scr = ri->ri_hw; 1335 struct gffb_softc *sc = scr->scr_cookie; 1336 int32_t xs, xd, y, width, height; 1337 1338 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1339 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1340 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1341 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1342 width = ri->ri_font->fontwidth * ncols; 1343 height = ri->ri_font->fontheight; 1344 gffb_bitblt(sc, xs, y, xd, y, width, height, 0xcc); 1345 } 1346 } 1347 1348 static void 1349 gffb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1350 { 1351 struct rasops_info *ri = cookie; 1352 struct vcons_screen *scr = ri->ri_hw; 1353 struct gffb_softc *sc = scr->scr_cookie; 1354 int32_t x, y, width, height, fg, bg, ul; 1355 1356 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1357 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1358 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1359 width = ri->ri_font->fontwidth * ncols; 1360 height = ri->ri_font->fontheight; 1361 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1362 1363 gffb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1364 } 1365 } 1366 1367 static void 1368 gffb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1369 { 1370 struct rasops_info *ri = cookie; 1371 struct vcons_screen *scr = ri->ri_hw; 1372 struct gffb_softc *sc = scr->scr_cookie; 1373 int32_t x, ys, yd, width, height; 1374 1375 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1376 x = ri->ri_xorigin; 1377 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1378 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1379 width = ri->ri_emuwidth; 1380 height = ri->ri_font->fontheight * nrows; 1381 gffb_bitblt(sc, x, ys, x, yd, width, height, 0xcc); 1382 } 1383 } 1384 1385 static void 1386 gffb_eraserows(void *cookie, int row, int nrows, long fillattr) 1387 { 1388 struct rasops_info *ri = cookie; 1389 struct vcons_screen *scr = ri->ri_hw; 1390 struct gffb_softc *sc = scr->scr_cookie; 1391 int32_t x, y, width, height, fg, bg, ul; 1392 1393 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1394 x = ri->ri_xorigin; 1395 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1396 width = ri->ri_emuwidth; 1397 height = ri->ri_font->fontheight * nrows; 1398 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1399 1400 gffb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1401 } 1402 } 1403