1 /* $NetBSD: tga.c,v 1.15 1999/12/06 19:25:59 drochner Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/device.h> 34 #include <sys/conf.h> 35 #include <sys/malloc.h> 36 #include <sys/buf.h> 37 #include <sys/ioctl.h> 38 39 #include <vm/vm.h> 40 41 #include <machine/bus.h> 42 #include <machine/intr.h> 43 44 #include <dev/pci/pcireg.h> 45 #include <dev/pci/pcivar.h> 46 #include <dev/pci/pcidevs.h> 47 #include <dev/pci/tgareg.h> 48 #include <dev/pci/tgavar.h> 49 #include <dev/ic/bt485reg.h> 50 51 #include <dev/rcons/raster.h> 52 #include <dev/wscons/wsconsio.h> 53 #include <dev/wscons/wscons_raster.h> 54 #include <dev/wscons/wsdisplayvar.h> 55 56 #ifdef __alpha__ 57 #include <machine/pte.h> 58 #endif 59 60 int tgamatch __P((struct device *, struct cfdata *, void *)); 61 void tgaattach __P((struct device *, struct device *, void *)); 62 int tgaprint __P((void *, const char *)); 63 64 struct cfattach tga_ca = { 65 sizeof(struct tga_softc), tgamatch, tgaattach, 66 }; 67 68 int tga_identify __P((tga_reg_t *)); 69 const struct tga_conf *tga_getconf __P((int)); 70 void tga_getdevconfig __P((bus_space_tag_t memt, pci_chipset_tag_t pc, 71 pcitag_t tag, struct tga_devconfig *dc)); 72 73 struct tga_devconfig tga_console_dc; 74 75 int tga_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 76 int tga_mmap __P((void *, off_t, int)); 77 static void tga_copyrows __P((void *, int, int, int)); 78 static void tga_copycols __P((void *, int, int, int, int)); 79 static int tga_alloc_screen __P((void *, const struct wsscreen_descr *, 80 void **, int *, int *, long *)); 81 static void tga_free_screen __P((void *, void *)); 82 static int tga_show_screen __P((void *, void *, int, 83 void (*) (void *, int, int), void *)); 84 static int tga_rop __P((struct raster *, int, int, int, int, int, 85 struct raster *, int, int)); 86 static int tga_rop_nosrc __P((struct raster *, int, int, int, int, int)); 87 static int tga_rop_htov __P((struct raster *, int, int, int, int, 88 int, struct raster *, int, int )); 89 static int tga_rop_vtov __P((struct raster *, int, int, int, int, 90 int, struct raster *, int, int )); 91 92 struct wsdisplay_emulops tga_emulops = { 93 rcons_cursor, /* could use hardware cursor; punt */ 94 rcons_mapchar, 95 rcons_putchar, 96 tga_copycols, 97 rcons_erasecols, 98 tga_copyrows, 99 rcons_eraserows, 100 rcons_alloc_attr 101 }; 102 103 struct wsscreen_descr tga_stdscreen = { 104 "std", 105 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 106 &tga_emulops, 107 0, 0, 108 WSSCREEN_REVERSE 109 }; 110 111 const struct wsscreen_descr *_tga_scrlist[] = { 112 &tga_stdscreen, 113 /* XXX other formats, graphics screen? */ 114 }; 115 116 struct wsscreen_list tga_screenlist = { 117 sizeof(_tga_scrlist) / sizeof(struct wsscreen_descr *), _tga_scrlist 118 }; 119 120 struct wsdisplay_accessops tga_accessops = { 121 tga_ioctl, 122 tga_mmap, 123 tga_alloc_screen, 124 tga_free_screen, 125 tga_show_screen, 126 0 /* load_font */ 127 }; 128 129 void tga_blank __P((struct tga_devconfig *)); 130 void tga_unblank __P((struct tga_devconfig *)); 131 132 int 133 tgamatch(parent, match, aux) 134 struct device *parent; 135 struct cfdata *match; 136 void *aux; 137 { 138 struct pci_attach_args *pa = aux; 139 140 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_DEC || 141 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_DEC_21030) 142 return (0); 143 144 return (10); 145 } 146 147 void 148 tga_getdevconfig(memt, pc, tag, dc) 149 bus_space_tag_t memt; 150 pci_chipset_tag_t pc; 151 pcitag_t tag; 152 struct tga_devconfig *dc; 153 { 154 const struct tga_conf *tgac; 155 const struct tga_ramdac_conf *tgar; 156 struct raster *rap; 157 struct rcons *rcp; 158 bus_size_t pcisize; 159 int i, flags; 160 161 dc->dc_memt = memt; 162 dc->dc_pc = pc; 163 164 dc->dc_pcitag = tag; 165 166 /* XXX magic number */ 167 if (pci_mapreg_info(pc, tag, 0x10, 168 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 169 &dc->dc_pcipaddr, &pcisize, &flags)) 170 return; 171 if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) /* XXX */ 172 panic("tga memory not cacheable"); 173 174 if (bus_space_map(memt, dc->dc_pcipaddr, pcisize, 175 BUS_SPACE_MAP_CACHEABLE | BUS_SPACE_MAP_LINEAR, &dc->dc_vaddr)) 176 return; 177 #ifdef __alpha__ 178 dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr); /* XXX */ 179 #endif 180 181 dc->dc_regs = (tga_reg_t *)(dc->dc_vaddr + TGA_MEM_CREGS); 182 dc->dc_tga_type = tga_identify(dc->dc_regs); 183 tgac = dc->dc_tgaconf = tga_getconf(dc->dc_tga_type); 184 if (tgac == NULL) 185 return; 186 187 #if 0 188 /* XXX on the Alpha, pcisize = 4 * cspace_size. */ 189 if (tgac->tgac_cspace_size != pcisize) /* sanity */ 190 panic("tga_getdevconfig: memory size mismatch?"); 191 #endif 192 193 tgar = tgac->tgac_ramdac; 194 195 switch (dc->dc_regs[TGA_REG_VHCR] & 0x1ff) { /* XXX */ 196 case 0: 197 dc->dc_wid = 8192; 198 break; 199 200 case 1: 201 dc->dc_wid = 8196; 202 break; 203 204 default: 205 dc->dc_wid = (dc->dc_regs[TGA_REG_VHCR] & 0x1ff) * 4; /* XXX */ 206 break; 207 } 208 209 dc->dc_rowbytes = dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8); 210 211 if ((dc->dc_regs[TGA_REG_VHCR] & 0x00000001) != 0 && /* XXX */ 212 (dc->dc_regs[TGA_REG_VHCR] & 0x80000000) != 0) { /* XXX */ 213 dc->dc_wid -= 4; 214 /* 215 * XXX XXX turning off 'odd' shouldn't be necesssary, 216 * XXX XXX but i can't make X work with the weird size. 217 */ 218 dc->dc_regs[TGA_REG_VHCR] &= ~0x80000001; 219 dc->dc_rowbytes = 220 dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8); 221 } 222 223 dc->dc_ht = (dc->dc_regs[TGA_REG_VVCR] & 0x7ff); /* XXX */ 224 225 /* XXX this seems to be what DEC does */ 226 dc->dc_regs[TGA_REG_CCBR] = 0; 227 dc->dc_regs[TGA_REG_VVBR] = 1; 228 dc->dc_videobase = dc->dc_vaddr + tgac->tgac_dbuf[0] + 229 1 * tgac->tgac_vvbr_units; 230 dc->dc_blanked = 1; 231 tga_unblank(dc); 232 233 /* 234 * Set all bits in the pixel mask, to enable writes to all pixels. 235 * It seems that the console firmware clears some of them 236 * under some circumstances, which causes cute vertical stripes. 237 */ 238 dc->dc_regs[TGA_REG_GPXR_P] = 0xffffffff; 239 240 /* clear the screen */ 241 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t)) 242 *(u_int32_t *)(dc->dc_videobase + i) = 0; 243 244 /* initialize the raster */ 245 rap = &dc->dc_raster; 246 rap->width = dc->dc_wid; 247 rap->height = dc->dc_ht; 248 rap->depth = tgac->tgac_phys_depth; 249 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t); 250 rap->pixels = (u_int32_t *)dc->dc_videobase; 251 rap->data = (caddr_t)dc; 252 253 /* initialize the raster console blitter */ 254 rcp = &dc->dc_rcons; 255 rcp->rc_sp = rap; 256 rcp->rc_crow = rcp->rc_ccol = -1; 257 rcp->rc_crowp = &rcp->rc_crow; 258 rcp->rc_ccolp = &rcp->rc_ccol; 259 rcons_init(rcp, 34, 80); 260 261 tga_stdscreen.nrows = dc->dc_rcons.rc_maxrow; 262 tga_stdscreen.ncols = dc->dc_rcons.rc_maxcol; 263 } 264 265 void 266 tgaattach(parent, self, aux) 267 struct device *parent, *self; 268 void *aux; 269 { 270 struct pci_attach_args *pa = aux; 271 struct tga_softc *sc = (struct tga_softc *)self; 272 struct wsemuldisplaydev_attach_args aa; 273 pci_intr_handle_t intrh; 274 const char *intrstr; 275 u_int8_t rev; 276 int console; 277 278 #ifdef __alpha__ 279 console = (pa->pa_tag == tga_console_dc.dc_pcitag); 280 #else 281 console = 0; 282 #endif 283 if (console) { 284 sc->sc_dc = &tga_console_dc; 285 sc->nscreens = 1; 286 } else { 287 sc->sc_dc = (struct tga_devconfig *) 288 malloc(sizeof(struct tga_devconfig), M_DEVBUF, M_WAITOK); 289 bzero(sc->sc_dc, sizeof(struct tga_devconfig)); 290 tga_getdevconfig(pa->pa_memt, pa->pa_pc, pa->pa_tag, sc->sc_dc); 291 } 292 if (sc->sc_dc->dc_vaddr == NULL) { 293 printf(": couldn't map memory space; punt!\n"); 294 return; 295 } 296 297 /* XXX say what's going on. */ 298 intrstr = NULL; 299 if (sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_intr != NULL) { 300 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 301 pa->pa_intrline, &intrh)) { 302 printf(": couldn't map interrupt"); 303 return; 304 } 305 intrstr = pci_intr_string(pa->pa_pc, intrh); 306 sc->sc_intr = pci_intr_establish(pa->pa_pc, intrh, IPL_TTY, 307 sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_intr, sc->sc_dc); 308 if (sc->sc_intr == NULL) { 309 printf(": couldn't establish interrupt"); 310 if (intrstr != NULL) 311 printf("at %s", intrstr); 312 printf("\n"); 313 return; 314 } 315 } 316 317 /* 318 * Initialize the RAMDAC and allocate any private storage it needs. 319 * Initialization includes disabling cursor, setting a sane 320 * colormap, etc. 321 */ 322 (*sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_init)(sc->sc_dc, 1); 323 324 printf(": DC21030 "); 325 rev = PCI_REVISION(pa->pa_class); 326 switch (rev) { 327 case 1: case 2: case 3: 328 printf("step %c", 'A' + rev - 1); 329 break; 330 331 default: 332 printf("unknown stepping (0x%x)", rev); 333 break; 334 } 335 printf(", "); 336 337 if (sc->sc_dc->dc_tgaconf == NULL) { 338 printf("unknown board configuration\n"); 339 return; 340 } 341 printf("board type %s\n", sc->sc_dc->dc_tgaconf->tgac_name); 342 printf("%s: %d x %d, %dbpp, %s RAMDAC\n", sc->sc_dev.dv_xname, 343 sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, 344 sc->sc_dc->dc_tgaconf->tgac_phys_depth, 345 sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_name); 346 347 if (intrstr != NULL) 348 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, 349 intrstr); 350 351 aa.console = console; 352 aa.scrdata = &tga_screenlist; 353 aa.accessops = &tga_accessops; 354 aa.accesscookie = sc; 355 356 config_found(self, &aa, wsemuldisplaydevprint); 357 } 358 359 int 360 tga_ioctl(v, cmd, data, flag, p) 361 void *v; 362 u_long cmd; 363 caddr_t data; 364 int flag; 365 struct proc *p; 366 { 367 struct tga_softc *sc = v; 368 struct tga_devconfig *dc = sc->sc_dc; 369 const struct tga_ramdac_conf *tgar = dc->dc_tgaconf->tgac_ramdac; 370 371 switch (cmd) { 372 case WSDISPLAYIO_GTYPE: 373 *(u_int *)data = WSDISPLAY_TYPE_TGA; 374 return (0); 375 376 case WSDISPLAYIO_GINFO: 377 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 378 wsd_fbip->height = sc->sc_dc->dc_ht; 379 wsd_fbip->width = sc->sc_dc->dc_wid; 380 wsd_fbip->depth = sc->sc_dc->dc_tgaconf->tgac_phys_depth; 381 wsd_fbip->cmsize = 256; /* XXX ??? */ 382 #undef wsd_fbip 383 return (0); 384 385 case WSDISPLAYIO_GETCMAP: 386 return (*tgar->tgar_get_cmap)(dc, 387 (struct wsdisplay_cmap *)data); 388 389 case WSDISPLAYIO_PUTCMAP: 390 return (*tgar->tgar_set_cmap)(dc, 391 (struct wsdisplay_cmap *)data); 392 393 case WSDISPLAYIO_SVIDEO: 394 if (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF) 395 tga_blank(sc->sc_dc); 396 else 397 tga_unblank(sc->sc_dc); 398 return (0); 399 400 case WSDISPLAYIO_GVIDEO: 401 *(u_int *)data = dc->dc_blanked ? 402 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 403 return (0); 404 405 case WSDISPLAYIO_GCURPOS: 406 return (*tgar->tgar_get_curpos)(dc, 407 (struct wsdisplay_curpos *)data); 408 409 case WSDISPLAYIO_SCURPOS: 410 return (*tgar->tgar_set_curpos)(dc, 411 (struct wsdisplay_curpos *)data); 412 413 case WSDISPLAYIO_GCURMAX: 414 return (*tgar->tgar_get_curmax)(dc, 415 (struct wsdisplay_curpos *)data); 416 417 case WSDISPLAYIO_GCURSOR: 418 return (*tgar->tgar_get_cursor)(dc, 419 (struct wsdisplay_cursor *)data); 420 421 case WSDISPLAYIO_SCURSOR: 422 return (*tgar->tgar_set_cursor)(dc, 423 (struct wsdisplay_cursor *)data); 424 } 425 return (-1); 426 } 427 428 int 429 tga_mmap(v, offset, prot) 430 void *v; 431 off_t offset; 432 int prot; 433 { 434 435 /* XXX NEW MAPPING CODE... */ 436 437 #ifdef __alpha__ 438 struct tga_softc *sc = v; 439 440 if (offset >= sc->sc_dc->dc_tgaconf->tgac_cspace_size || offset < 0) 441 return -1; 442 return alpha_btop(sc->sc_dc->dc_paddr + offset); 443 #else 444 return (-1); 445 #endif 446 } 447 448 int 449 tga_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 450 void *v; 451 const struct wsscreen_descr *type; 452 void **cookiep; 453 int *curxp, *curyp; 454 long *attrp; 455 { 456 struct tga_softc *sc = v; 457 long defattr; 458 459 if (sc->nscreens > 0) 460 return (ENOMEM); 461 462 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */ 463 *curxp = 0; 464 *curyp = 0; 465 rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr); 466 *attrp = defattr; 467 sc->nscreens++; 468 return (0); 469 } 470 471 void 472 tga_free_screen(v, cookie) 473 void *v; 474 void *cookie; 475 { 476 struct tga_softc *sc = v; 477 478 if (sc->sc_dc == &tga_console_dc) 479 panic("tga_free_screen: console"); 480 481 sc->nscreens--; 482 } 483 484 int 485 tga_show_screen(v, cookie, waitok, cb, cbarg) 486 void *v; 487 void *cookie; 488 int waitok; 489 void (*cb) __P((void *, int, int)); 490 void *cbarg; 491 { 492 493 return (0); 494 } 495 496 int 497 tga_cnattach(iot, memt, pc, bus, device, function) 498 bus_space_tag_t iot, memt; 499 pci_chipset_tag_t pc; 500 int bus, device, function; 501 { 502 struct tga_devconfig *dcp = &tga_console_dc; 503 long defattr; 504 505 tga_getdevconfig(memt, pc, 506 pci_make_tag(pc, bus, device, function), dcp); 507 508 /* sanity checks */ 509 if (dcp->dc_vaddr == NULL) 510 panic("tga_console(%d, %d): couldn't map memory space", 511 device, function); 512 if (dcp->dc_tgaconf == NULL) 513 panic("tga_console(%d, %d): unknown board configuration", 514 device, function); 515 516 /* 517 * Initialize the RAMDAC but DO NOT allocate any private storage. 518 * Initialization includes disabling cursor, setting a sane 519 * colormap, etc. It will be reinitialized in tgaattach(). 520 */ 521 (*dcp->dc_tgaconf->tgac_ramdac->tgar_init)(dcp, 0); 522 523 rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr); 524 525 wsdisplay_cnattach(&tga_stdscreen, &dcp->dc_rcons, 526 0, 0, defattr); 527 528 return(0); 529 } 530 531 /* 532 * Functions to blank and unblank the display. 533 */ 534 void 535 tga_blank(dc) 536 struct tga_devconfig *dc; 537 { 538 539 if (!dc->dc_blanked) { 540 dc->dc_blanked = 1; 541 dc->dc_regs[TGA_REG_VVVR] |= VVR_BLANK; /* XXX */ 542 } 543 } 544 545 void 546 tga_unblank(dc) 547 struct tga_devconfig *dc; 548 { 549 550 if (dc->dc_blanked) { 551 dc->dc_blanked = 0; 552 dc->dc_regs[TGA_REG_VVVR] &= ~VVR_BLANK; /* XXX */ 553 } 554 } 555 556 /* 557 * Functions to manipulate the built-in cursor handing hardware. 558 */ 559 int 560 tga_builtin_set_cursor(dc, cursorp) 561 struct tga_devconfig *dc; 562 struct wsdisplay_cursor *cursorp; 563 { 564 int count, error, v; 565 566 v = cursorp->which; 567 if (v & WSDISPLAY_CURSOR_DOCMAP) { 568 error = (*dc->dc_tgaconf->tgac_ramdac->tgar_check_curcmap)(dc, 569 cursorp); 570 if (error) 571 return (error); 572 } 573 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 574 if ((u_int)cursorp->size.x != 64 || 575 (u_int)cursorp->size.y > 64) 576 return (EINVAL); 577 /* The cursor is 2 bits deep, and there is no mask */ 578 count = (cursorp->size.y * 64 * 2) / NBBY; 579 if (!uvm_useracc(cursorp->image, count, B_READ)) 580 return (EFAULT); 581 } 582 if (v & WSDISPLAY_CURSOR_DOHOT) /* not supported */ 583 return EINVAL; 584 585 /* parameters are OK; do it */ 586 if (v & WSDISPLAY_CURSOR_DOCUR) { 587 if (cursorp->enable) 588 dc->dc_regs[TGA_REG_VVVR] |= 0x04; /* XXX */ 589 else 590 dc->dc_regs[TGA_REG_VVVR] &= ~0x04; /* XXX */ 591 } 592 if (v & WSDISPLAY_CURSOR_DOPOS) { 593 dc->dc_regs[TGA_REG_CXYR] = ((cursorp->pos.y & 0xfff) << 12) | 594 (cursorp->pos.x & 0xfff); 595 } 596 if (v & WSDISPLAY_CURSOR_DOCMAP) { 597 /* can't fail. */ 598 (*dc->dc_tgaconf->tgac_ramdac->tgar_set_curcmap)(dc, cursorp); 599 } 600 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 601 count = ((64 * 2) / NBBY) * cursorp->size.y; 602 dc->dc_regs[TGA_REG_CCBR] = 603 (dc->dc_regs[TGA_REG_CCBR] & ~0xfc00) | 604 (cursorp->size.y << 10); 605 copyin(cursorp->image, (char *)(dc->dc_vaddr + 606 (dc->dc_regs[TGA_REG_CCBR] & 0x3ff)), 607 count); /* can't fail. */ 608 } 609 return (0); 610 } 611 612 int 613 tga_builtin_get_cursor(dc, cursorp) 614 struct tga_devconfig *dc; 615 struct wsdisplay_cursor *cursorp; 616 { 617 int count, error; 618 619 cursorp->which = WSDISPLAY_CURSOR_DOALL & 620 ~(WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOCMAP); 621 cursorp->enable = (dc->dc_regs[TGA_REG_VVVR] & 0x04) != 0; 622 cursorp->pos.x = dc->dc_regs[TGA_REG_CXYR] & 0xfff; 623 cursorp->pos.y = (dc->dc_regs[TGA_REG_CXYR] >> 12) & 0xfff; 624 cursorp->size.x = 64; 625 cursorp->size.y = (dc->dc_regs[TGA_REG_CCBR] >> 10) & 0x3f; 626 627 if (cursorp->image != NULL) { 628 count = (cursorp->size.y * 64 * 2) / NBBY; 629 error = copyout((char *)(dc->dc_vaddr + 630 (dc->dc_regs[TGA_REG_CCBR] & 0x3ff)), 631 cursorp->image, count); 632 if (error) 633 return (error); 634 /* No mask */ 635 } 636 error = (*dc->dc_tgaconf->tgac_ramdac->tgar_get_curcmap)(dc, cursorp); 637 return (error); 638 } 639 640 int 641 tga_builtin_set_curpos(dc, curposp) 642 struct tga_devconfig *dc; 643 struct wsdisplay_curpos *curposp; 644 { 645 646 dc->dc_regs[TGA_REG_CXYR] = 647 ((curposp->y & 0xfff) << 12) | (curposp->x & 0xfff); 648 return (0); 649 } 650 651 int 652 tga_builtin_get_curpos(dc, curposp) 653 struct tga_devconfig *dc; 654 struct wsdisplay_curpos *curposp; 655 { 656 657 curposp->x = dc->dc_regs[TGA_REG_CXYR] & 0xfff; 658 curposp->y = (dc->dc_regs[TGA_REG_CXYR] >> 12) & 0xfff; 659 return (0); 660 } 661 662 int 663 tga_builtin_get_curmax(dc, curposp) 664 struct tga_devconfig *dc; 665 struct wsdisplay_curpos *curposp; 666 { 667 668 curposp->x = curposp->y = 64; 669 return (0); 670 } 671 672 /* 673 * Copy columns (characters) in a row (line). 674 */ 675 void 676 tga_copycols(id, row, srccol, dstcol, ncols) 677 void *id; 678 int row, srccol, dstcol, ncols; 679 { 680 struct rcons *rc = id; 681 int y, srcx, dstx, nx; 682 683 y = rc->rc_yorigin + rc->rc_font->height * row; 684 srcx = rc->rc_xorigin + rc->rc_font->width * srccol; 685 dstx = rc->rc_xorigin + rc->rc_font->width * dstcol; 686 nx = rc->rc_font->width * ncols; 687 688 tga_rop(rc->rc_sp, dstx, y, 689 nx, rc->rc_font->height, RAS_SRC, 690 rc->rc_sp, srcx, y); 691 } 692 693 /* 694 * Copy rows (lines). 695 */ 696 void 697 tga_copyrows(id, srcrow, dstrow, nrows) 698 void *id; 699 int srcrow, dstrow, nrows; 700 { 701 struct rcons *rc = id; 702 int srcy, dsty, ny; 703 704 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow; 705 dsty = rc->rc_yorigin + rc->rc_font->height * dstrow; 706 ny = rc->rc_font->height * nrows; 707 708 tga_rop(rc->rc_sp, rc->rc_xorigin, dsty, 709 rc->rc_raswidth, ny, RAS_SRC, 710 rc->rc_sp, rc->rc_xorigin, srcy); 711 } 712 713 /* Do we need the src? */ 714 static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 }; 715 716 /* A mapping between our API and the TGA card */ 717 static int map_rop[16] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 718 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf 719 }; 720 721 /* 722 * Generic TGA raster op. 723 * This covers all possible raster ops, and 724 * clips the sizes and all of that. 725 */ 726 static int 727 tga_rop(dst, dx, dy, w, h, rop, src, sx, sy) 728 struct raster *dst; 729 int dx, dy, w, h, rop; 730 struct raster *src; 731 int sx, sy; 732 { 733 if (!dst) 734 return -1; 735 if (dst->data == NULL) 736 return -1; /* we should be writing to a screen */ 737 if (needsrc[RAS_GETOP(rop)]) { 738 if (src == (struct raster *) 0) 739 return -1; /* We want a src */ 740 /* Clip against src */ 741 if (sx < 0) { 742 w += sx; 743 sx = 0; 744 } 745 if (sy < 0) { 746 h += sy; 747 sy = 0; 748 } 749 if (sx + w > src->width) 750 w = src->width - sx; 751 if (sy + h > src->height) 752 h = src->height - sy; 753 } else { 754 if (src != (struct raster *) 0) 755 return -1; /* We need no src */ 756 } 757 /* Clip against dst. We modify src regardless of using it, 758 * since it really doesn't matter. 759 */ 760 if (dx < 0) { 761 w += dx; 762 sx -= dx; 763 dx = 0; 764 } 765 if (dy < 0) { 766 h += dy; 767 sy -= dy; 768 dy = 0; 769 } 770 if (dx + w > dst->width) 771 w = dst->width - dx; 772 if (dy + h > dst->height) 773 h = dst->height - dy; 774 if (w <= 0 || h <= 0) 775 return 0; /* Vacuously true; */ 776 if (!src) 777 return tga_rop_nosrc(dst, dx, dy, w, h, rop); 778 if (src->data == NULL) 779 return tga_rop_htov(dst, dx, dy, w, h, rop, src, sx, sy); 780 else 781 return tga_rop_vtov(dst, dx, dy, w, h, rop, src, sx, sy); 782 } 783 784 /* 785 * No source raster ops. 786 * This function deals with all raster ops that don't require a src. 787 */ 788 static int 789 tga_rop_nosrc(dst, dx, dy, w, h, rop) 790 struct raster *dst; 791 int dx, dy, w, h, rop; 792 { 793 return raster_op(dst, dx, dy, w, h, rop, NULL, 0, 0); 794 } 795 796 /* 797 * Host to Video raster ops. 798 * This function deals with all raster ops that have a src that is host memory. 799 */ 800 static int 801 tga_rop_htov(dst, dx, dy, w, h, rop, src, sx, sy) 802 struct raster *dst; 803 int dx, dy, w, h, rop; 804 struct raster *src; 805 int sx, sy; 806 { 807 return raster_op(dst, dx, dy, w, h, rop, src, sx, sy); 808 } 809 810 /* 811 * Video to Video raster ops. 812 * This function deals with all raster ops that have a src and dst 813 * that are on the card. 814 */ 815 static int 816 tga_rop_vtov(dst, dx, dy, w, h, rop, src, sx, sy) 817 struct raster *dst; 818 int dx, dy, w, h, rop; 819 struct raster *src; 820 int sx, sy; 821 { 822 struct tga_devconfig *dc = (struct tga_devconfig *)dst->data; 823 tga_reg_t *regs0 = dc->dc_regs; 824 tga_reg_t *regs1 = regs0 + 16 * 1024; /* register alias 1 */ 825 tga_reg_t *regs2 = regs1 + 16 * 1024; /* register alias 2 */ 826 tga_reg_t *regs3 = regs2 + 16 * 1024; /* register alias 3 */ 827 int srcb, dstb; 828 int x, y; 829 int xstart, xend, xdir, xinc; 830 int ystart, yend, ydir, yinc; 831 int offset = 1 * dc->dc_tgaconf->tgac_vvbr_units; 832 833 /* 834 * I don't yet want to deal with unaligned guys, really. And we don't 835 * deal with copies from one card to another. 836 */ 837 if (dx % 8 != 0 || sx % 8 != 0 || src != dst) 838 return raster_op(dst, dx, dy, w, h, rop, src, sx, sy); 839 840 if (sy >= dy) { 841 ystart = 0; 842 yend = h; 843 ydir = 1; 844 } else { 845 ystart = h; 846 yend = 0; 847 ydir = -1; 848 } 849 if (sx >= dx) { 850 xstart = 0; 851 xend = w * (dst->depth / 8); 852 xdir = 1; 853 } else { 854 xstart = w * (dst->depth / 8); 855 xend = 0; 856 xdir = -1; 857 } 858 xinc = xdir * 4 * 64; 859 yinc = ydir * dst->linelongs * 4; 860 ystart *= dst->linelongs * 4; 861 yend *= dst->linelongs * 4; 862 srcb = offset + sy * src->linelongs * 4 + sx; 863 dstb = offset + dy * dst->linelongs * 4 + dx; 864 regs3[TGA_REG_GMOR] = 0x0007; /* Copy mode */ 865 regs3[TGA_REG_GOPR] = map_rop[rop]; /* Set up the op */ 866 for (y = ystart; (ydir * y) < (ydir * yend); y += yinc) { 867 for (x = xstart; (xdir * x) < (xdir * xend); x += xinc) { 868 regs0[TGA_REG_GCSR] = srcb + y + x + 3 * 64; 869 regs0[TGA_REG_GCDR] = dstb + y + x + 3 * 64; 870 regs1[TGA_REG_GCSR] = srcb + y + x + 2 * 64; 871 regs1[TGA_REG_GCDR] = dstb + y + x + 2 * 64; 872 regs2[TGA_REG_GCSR] = srcb + y + x + 1 * 64; 873 regs2[TGA_REG_GCDR] = dstb + y + x + 1 * 64; 874 regs3[TGA_REG_GCSR] = srcb + y + x + 0 * 64; 875 regs3[TGA_REG_GCDR] = dstb + y + x + 0 * 64; 876 } 877 } 878 regs0[TGA_REG_GOPR] = 0x0003; /* op -> dst = src */ 879 regs0[TGA_REG_GMOR] = 0x0000; /* Simple mode */ 880 return 0; 881 } 882