1 /* $NetBSD: topcat.c,v 1.13 2024/12/20 22:42:57 tsutsui Exp $ */ 2 /* $OpenBSD: topcat.c,v 1.15 2006/08/11 18:33:13 miod Exp $ */ 3 4 /* 5 * Copyright (c) 2005, Miodrag Vallat. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 */ 30 /*- 31 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 32 * All rights reserved. 33 * 34 * This code is derived from software contributed to The NetBSD Foundation 35 * by Jason R. Thorpe. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 56 * POSSIBILITY OF SUCH DAMAGE. 57 */ 58 59 /* 60 * Copyright (c) 1988 University of Utah. 61 * Copyright (c) 1990, 1993 62 * The Regents of the University of California. All rights reserved. 63 * 64 * This code is derived from software contributed to Berkeley by 65 * the Systems Programming Group of the University of Utah Computer 66 * Science Department. 67 * 68 * Redistribution and use in source and binary forms, with or without 69 * modification, are permitted provided that the following conditions 70 * are met: 71 * 1. Redistributions of source code must retain the above copyright 72 * notice, this list of conditions and the following disclaimer. 73 * 2. Redistributions in binary form must reproduce the above copyright 74 * notice, this list of conditions and the following disclaimer in the 75 * documentation and/or other materials provided with the distribution. 76 * 3. Neither the name of the University nor the names of its contributors 77 * may be used to endorse or promote products derived from this software 78 * without specific prior written permission. 79 * 80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 90 * SUCH DAMAGE. 91 * 92 * from: Utah $Hdr: grf_tc.c 1.20 93/08/13$ 93 * 94 * @(#)grf_tc.c 8.4 (Berkeley) 1/12/94 95 */ 96 97 /* 98 * Graphics routines for TOPCAT, CATSEYE and KATHMANDU frame buffers 99 */ 100 101 #include <sys/param.h> 102 #include <sys/systm.h> 103 #include <sys/conf.h> 104 #include <sys/device.h> 105 #include <sys/proc.h> 106 #include <sys/ioctl.h> 107 #include <sys/bus.h> 108 #include <sys/cpu.h> 109 110 #include <machine/autoconf.h> 111 112 #include <hp300/dev/dioreg.h> 113 #include <hp300/dev/diovar.h> 114 #include <hp300/dev/diodevs.h> 115 #include <hp300/dev/intiovar.h> 116 117 #include <dev/wscons/wsconsio.h> 118 #include <dev/wscons/wsdisplayvar.h> 119 #include <dev/rasops/rasops.h> 120 121 #include <hp300/dev/diofbreg.h> 122 #include <hp300/dev/diofbvar.h> 123 #include <hp300/dev/topcatreg.h> 124 125 struct topcat_softc { 126 device_t sc_dev; 127 struct diofb *sc_fb; 128 struct diofb sc_fb_store; 129 int sc_scode; 130 }; 131 132 static int topcat_dio_match(device_t, cfdata_t, void *); 133 static void topcat_dio_attach(device_t, device_t, void *); 134 static int topcat_intio_match(device_t, cfdata_t, void *); 135 static void topcat_intio_attach(device_t, device_t, void *); 136 137 CFATTACH_DECL_NEW(topcat_dio, sizeof(struct topcat_softc), 138 topcat_dio_match, topcat_dio_attach, NULL, NULL); 139 140 CFATTACH_DECL_NEW(topcat_intio, sizeof(struct topcat_softc), 141 topcat_intio_match, topcat_intio_attach, NULL, NULL); 142 143 static void topcat_end_attach(struct topcat_softc *, uint8_t); 144 static int topcat_reset(struct diofb *, int, struct diofbreg *); 145 static void topcat_restore(struct diofb *); 146 static int topcat_setcmap(struct diofb *, struct wsdisplay_cmap *); 147 static void topcat_setcolor(struct diofb *, u_int); 148 static int topcat_windowmove(struct diofb *, uint16_t, uint16_t, uint16_t, 149 uint16_t, uint16_t, uint16_t, int16_t, int16_t); 150 151 static int topcat_ioctl(void *, void *, u_long, void *, int, struct lwp *); 152 static void topcat_putchar8(void *, int, int, u_int, long); 153 static void topcat_putchar1_4(void *, int, int, u_int, long); 154 155 static struct wsdisplay_accessops topcat_accessops = { 156 topcat_ioctl, 157 diofb_mmap, 158 diofb_alloc_screen, 159 diofb_free_screen, 160 diofb_show_screen, 161 NULL, /* load_font */ 162 }; 163 164 /* 165 * Attachment glue 166 */ 167 168 int 169 topcat_intio_match(device_t parent, cfdata_t cf, void *aux) 170 { 171 struct intio_attach_args *ia = aux; 172 struct diofbreg *fbr; 173 174 if (strcmp("fb", ia->ia_modname) != 0) 175 return 0; 176 177 fbr = (struct diofbreg *)ia->ia_addr; 178 179 if (badaddr((void *)fbr)) 180 return 0; 181 182 if (fbr->id == GRFHWID) { 183 switch (fbr->fbid) { 184 case GID_TOPCAT: 185 case GID_LRCATSEYE: 186 case GID_HRCCATSEYE: 187 case GID_HRMCATSEYE: 188 #if 0 189 case GID_XXXCATSEYE: 190 #endif 191 return 1; 192 } 193 } 194 195 return 0; 196 } 197 198 void 199 topcat_intio_attach(device_t parent, device_t self, void *aux) 200 { 201 struct topcat_softc *sc = device_private(self); 202 struct intio_attach_args *ia = aux; 203 struct diofbreg *fbr; 204 205 sc->sc_dev = self; 206 fbr = (struct diofbreg *)ia->ia_addr; 207 sc->sc_scode = CONSCODE_INTERNAL; 208 209 if (sc->sc_scode == conscode) { 210 sc->sc_fb = &diofb_cn; 211 } else { 212 sc->sc_fb = &sc->sc_fb_store; 213 topcat_reset(sc->sc_fb, sc->sc_scode, fbr); 214 } 215 216 topcat_end_attach(sc, fbr->fbid); 217 } 218 219 int 220 topcat_dio_match(device_t parent, cfdata_t cf, void *aux) 221 { 222 struct dio_attach_args *da = aux; 223 224 if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER) { 225 switch (da->da_secid) { 226 case DIO_DEVICE_SECID_TOPCAT: 227 case DIO_DEVICE_SECID_LRCATSEYE: 228 case DIO_DEVICE_SECID_HRCCATSEYE: 229 case DIO_DEVICE_SECID_HRMCATSEYE: 230 #if 0 231 case DIO_DEVICE_SECID_XXXCATSEYE: 232 #endif 233 return 1; 234 } 235 } 236 237 return 0; 238 } 239 240 void 241 topcat_dio_attach(device_t parent, device_t self, void *aux) 242 { 243 struct topcat_softc *sc = device_private(self); 244 struct dio_attach_args *da = aux; 245 bus_space_handle_t bsh; 246 struct diofbreg *fbr; 247 248 sc->sc_dev = self; 249 sc->sc_scode = da->da_scode; 250 if (sc->sc_scode == conscode) { 251 fbr = (struct diofbreg *)conaddr; /* already mapped */ 252 sc->sc_fb = &diofb_cn; 253 } else { 254 sc->sc_fb = &sc->sc_fb_store; 255 if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0, 256 &bsh)) { 257 aprint_error(": can't map framebuffer\n"); 258 return; 259 } 260 fbr = bus_space_vaddr(da->da_bst, bsh); 261 if (topcat_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) { 262 aprint_error(": can't reset framebuffer\n"); 263 return; 264 } 265 } 266 267 topcat_end_attach(sc, fbr->fbid); 268 } 269 270 void 271 topcat_end_attach(struct topcat_softc *sc, uint8_t id) 272 { 273 const char *fbname = "unknown"; 274 275 switch (id) { 276 case GID_TOPCAT: 277 switch (sc->sc_fb->planes) { 278 case 1: 279 if (sc->sc_fb->dheight == 400) 280 fbname = "HP98542 topcat"; 281 else 282 fbname = "HP98544 topcat"; 283 break; 284 case 4: 285 if (sc->sc_fb->dheight == 400) 286 fbname = "HP98543 topcat"; 287 else 288 fbname = "HP98545 topcat"; 289 break; 290 case 6: 291 fbname = "HP98547 topcat"; 292 break; 293 } 294 break; 295 case GID_HRCCATSEYE: 296 fbname = "HP98550 catseye"; /* also A1416 kathmandu */ 297 break; 298 case GID_LRCATSEYE: 299 fbname = "HP98549 catseye"; 300 break; 301 case GID_HRMCATSEYE: 302 fbname = "HP98548 catseye"; 303 break; 304 } 305 306 diofb_end_attach(sc->sc_dev, &topcat_accessops, sc->sc_fb, 307 sc->sc_scode == conscode, fbname); 308 } 309 310 /* 311 * Initialize hardware and display routines. 312 */ 313 int 314 topcat_reset(struct diofb *fb, int scode, struct diofbreg *fbr) 315 { 316 volatile struct tcboxfb *tc = (struct tcboxfb *)fbr; 317 struct rasops_info *ri = &fb->ri; 318 int rc; 319 u_int i; 320 bool sparse = false; 321 322 if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0) 323 return rc; 324 325 /* 326 * If we could not get a valid number of planes, determine it 327 * by writing to the first frame buffer display location, 328 * then reading it back. 329 */ 330 if (fb->planes == 0) { 331 volatile uint8_t *fbp; 332 uint8_t save; 333 334 fbp = (uint8_t *)fb->fbkva; 335 tc->fben = ~0; 336 tc->wen = ~0; 337 tc->ren = ~0; 338 tc->prr = RR_COPY; 339 save = *fbp; 340 *fbp = 0xff; 341 fb->planemask = *fbp; 342 *fbp = save; 343 344 for (fb->planes = 1; fb->planemask >= (1 << fb->planes); 345 fb->planes++); 346 if (fb->planes > 8) 347 fb->planes = 8; 348 fb->planemask = (1 << fb->planes) - 1; 349 } 350 351 /* 352 * Some displays, such as the HP332 and HP340 internal video 353 * and HP98542/98543 appear to return a display width of 1024 354 * instead of 512. It looks these boards have actually have 355 * enough 64KB (1bpp) or 256KB (4bpp) VRAM and RAMDAC capabilities 356 * to display 1024x400 pixels. 357 * 358 * However HP's officlal "Service Information Manual" for 359 * "HP 900 Series 300 Computers Models 330/350" says: 360 * "The medium-resolution board uses eight memory chips per plane. 361 * This is enough to display 512 doubled pixels by 400 scan lines." 362 * 363 * This "512 doubled pixels" implies that the native HP-UX treated 364 * these 1024x400 framebuffers as pseudo 512x400 ones because 365 * ancient 1980s CRTs (such as 35741) didn't display such higher 366 * resolution. Furthermore, even modern LCDs can only handle 367 * upto 720 pixels in the "400 line" as VGA compatible mode. 368 * 369 * As mentioned above, we treat these 1024x400 1 bit or 4 bit 370 * framebuffers as "2 bytes per pixel" ones, so we have to handle 371 * 512 pixels per line with 1024 bytes per line. 372 */ 373 if (fb->planes <= 4 && fb->dwidth == 1024 && fb->dheight == 400) { 374 fb->dwidth = 512; 375 sparse = true; 376 } 377 378 fb->bmv = topcat_windowmove; 379 topcat_restore(fb); 380 diofb_fbsetup(fb); 381 if (!sparse) { 382 /* save original rasops putchar op */ 383 fb->wsputchar = ri->ri_ops.putchar; 384 ri->ri_ops.putchar = topcat_putchar8; 385 } else { 386 ri->ri_ops.putchar = topcat_putchar1_4; 387 /* copycols and erasecols ops require byte size of fontwidth */ 388 fb->wsd.fontwidth *= 2; 389 /* copyrows and eraserows ops require byte size per line */ 390 ri->ri_emuwidth *= 2; 391 } 392 for (i = 0; i <= fb->planemask; i++) 393 topcat_setcolor(fb, i); 394 395 return 0; 396 } 397 398 void 399 topcat_restore(struct diofb *fb) 400 { 401 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 402 403 /* 404 * Catseye looks a lot like a topcat, but not completely. 405 * So, we set some bits to make it work. 406 */ 407 if (tc->regs.fbid != GID_TOPCAT) { 408 while ((tc->catseye_status & 1)) 409 ; 410 tc->catseye_status = 0x0; 411 tc->vb_select = 0x0; 412 tc->tcntrl = 0x0; 413 tc->acntrl = 0x0; 414 tc->pncntrl = 0x0; 415 tc->rug_cmdstat = 0x90; 416 } 417 418 /* 419 * Enable reading/writing of all the planes. 420 */ 421 tc->fben = fb->planemask; 422 tc->wen = fb->planemask; 423 tc->ren = fb->planemask; 424 tc->prr = RR_COPY; 425 426 /* Enable display */ 427 tc->nblank = fb->planemask; 428 } 429 430 int 431 topcat_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, 432 struct lwp *l) 433 { 434 struct diofb *fb = v; 435 struct wsdisplay_fbinfo *wdf; 436 u_int i; 437 438 switch (cmd) { 439 case WSDISPLAYIO_GTYPE: 440 *(u_int *)data = WSDISPLAY_TYPE_TOPCAT; 441 return 0; 442 case WSDISPLAYIO_SMODE: 443 fb->mapmode = *(u_int *)data; 444 if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) { 445 topcat_restore(fb); 446 for (i = 0; i <= fb->planemask; i++) 447 topcat_setcolor(fb, i); 448 } 449 return 0; 450 case WSDISPLAYIO_GINFO: 451 wdf = (void *)data; 452 wdf->width = fb->ri.ri_width; 453 wdf->height = fb->ri.ri_height; 454 wdf->depth = fb->ri.ri_depth; 455 wdf->cmsize = 1 << fb->planes; 456 return 0; 457 case WSDISPLAYIO_LINEBYTES: 458 *(u_int *)data = fb->ri.ri_stride; 459 return 0; 460 case WSDISPLAYIO_GETCMAP: 461 if (fb->planemask == 1) 462 return EPASSTHROUGH; 463 return diofb_getcmap(fb, (struct wsdisplay_cmap *)data); 464 case WSDISPLAYIO_PUTCMAP: 465 if (fb->planemask == 1) 466 return EPASSTHROUGH; 467 return topcat_setcmap(fb, (struct wsdisplay_cmap *)data); 468 case WSDISPLAYIO_GVIDEO: 469 case WSDISPLAYIO_SVIDEO: 470 return EPASSTHROUGH; 471 } 472 473 return EPASSTHROUGH; 474 } 475 476 void 477 topcat_setcolor(struct diofb *fb, u_int index) 478 { 479 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 480 481 /* No color map registers on monochrome framebuffers. */ 482 if (fb->planemask == 1) 483 return; 484 485 tc_waitbusy(tc, fb->planemask); 486 487 if (tc->regs.fbid != GID_TOPCAT) { 488 tccm_waitbusy(tc); 489 tc->plane_mask = fb->planemask; 490 tc->cindex = ~index; 491 tc->rdata = fb->cmap.r[index]; 492 tc->gdata = fb->cmap.g[index]; 493 tc->bdata = fb->cmap.b[index]; 494 tc->strobe = 0xff; 495 /* XXX delay required on 68020/30 to avoid bus error */ 496 DELAY(100); 497 498 tccm_waitbusy(tc); 499 tc->cindex = 0; 500 } else { 501 tccm_waitbusy(tc); 502 tc->plane_mask = fb->planemask; 503 tc->rdata = fb->cmap.r[index]; 504 tc->gdata = fb->cmap.g[index]; 505 tc->bdata = fb->cmap.b[index]; 506 DELAY(1); /* necessary for at least old HP98543 */ 507 tc->cindex = ~index; 508 DELAY(1); /* necessary for at least old HP98543 */ 509 tc->strobe = 0xff; 510 /* XXX delay required on 68020/30 to avoid bus error */ 511 DELAY(100); 512 513 tccm_waitbusy(tc); 514 tc->rdata = 0; 515 tc->gdata = 0; 516 tc->bdata = 0; 517 tc->cindex = 0; 518 } 519 } 520 521 int 522 topcat_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm) 523 { 524 uint8_t r[256], g[256], b[256]; 525 u_int index = cm->index, count = cm->count; 526 u_int colcount = 1 << fb->planes; 527 int error; 528 529 if (index >= colcount || count > colcount - index) 530 return EINVAL; 531 532 if ((error = copyin(cm->red, r, count)) != 0) 533 return error; 534 if ((error = copyin(cm->green, g, count)) != 0) 535 return error; 536 if ((error = copyin(cm->blue, b, count)) != 0) 537 return error; 538 539 memcpy(fb->cmap.r + index, r, count); 540 memcpy(fb->cmap.g + index, g, count); 541 memcpy(fb->cmap.b + index, b, count); 542 543 while (count-- != 0) 544 topcat_setcolor(fb, index++); 545 546 return 0; 547 } 548 549 /* 550 * Accelerated routines 551 */ 552 553 int 554 topcat_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy, 555 uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop, 556 int16_t planemask) 557 { 558 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 559 560 tc_waitbusy(tc, fb->planemask); 561 562 if (planemask != 0xff) { 563 tc->wen = planemask ^ 0xff; 564 tc->wmrr = rop ^ 0x0f; 565 tc->wen = fb->planemask; 566 } else { 567 tc->wen = planemask; 568 tc->wmrr = rop; 569 } 570 tc->source_y = sy; 571 tc->source_x = sx; 572 tc->dest_y = dy; 573 tc->dest_x = dx; 574 tc->wheight = cy; 575 tc->wwidth = cx; 576 tc->wmove = fb->planemask; 577 578 return 0; 579 } 580 581 static void 582 topcat_putchar8(void *cookie, int row, int col, u_int uc, long attr) 583 { 584 struct rasops_info *ri = (struct rasops_info *)cookie; 585 struct diofb *diofb = ri->ri_hw; 586 volatile struct tcboxfb *tc = (struct tcboxfb *)diofb->regkva; 587 588 /* Wait windowmove ops complete before drawing a glyph */ 589 tc_waitbusy(tc, diofb->planemask); 590 591 /* Call the original rasops putchar */ 592 (*diofb->wsputchar)(cookie, row, col, uc, attr); 593 } 594 595 /* 596 * Put a single character on 1 bpp (98542) or 4 bpp (98543) variants 597 * with 1024x400 VRAM to treat them as a pseudo 512x400 bitmap. 598 */ 599 static void 600 topcat_putchar1_4(void *cookie, int row, int col, u_int uc, long attr) 601 { 602 int width, height, cnt, fs; 603 uint32_t fb; 604 uint8_t *fr, clr[2]; 605 uint8_t *dp, *rp; 606 struct rasops_info *ri; 607 struct diofb *diofb; 608 volatile struct tcboxfb *tc; 609 610 ri = (struct rasops_info *)cookie; 611 612 if (!CHAR_IN_FONT(uc, ri->ri_font)) 613 return; 614 615 rp = ri->ri_bits + (row * ri->ri_yscale) + 616 (col * ri->ri_xscale * 2); 617 618 height = ri->ri_font->fontheight; 619 width = ri->ri_font->fontwidth; 620 clr[0] = (uint8_t)ri->ri_devcmap[(attr >> 16) & 0xf]; 621 clr[1] = (uint8_t)ri->ri_devcmap[(attr >> 24) & 0xf]; 622 623 /* Wait windowmove ops complete before drawing a glyph */ 624 diofb = ri->ri_hw; 625 tc = (struct tcboxfb *)diofb->regkva; 626 tc_waitbusy(tc, diofb->planemask); 627 628 /* 629 * We have to put pixel data to both odd and even addresses 630 * to handle "doubled pixels" as noted above. 631 */ 632 if (uc == ' ') { 633 uint16_t c = clr[0]; 634 635 c = c << 8 | c; 636 while (height--) { 637 dp = rp; 638 rp += ri->ri_stride; 639 640 for (cnt = width; cnt; cnt--) { 641 *(uint16_t *)dp = c; 642 dp += 2; 643 } 644 } 645 } else { 646 uc -= ri->ri_font->firstchar; 647 fr = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale; 648 fs = ri->ri_font->stride; 649 650 while (height--) { 651 dp = rp; 652 fb = be32dec(fr); 653 fr += fs; 654 rp += ri->ri_stride; 655 656 for (cnt = width; cnt; cnt--) { 657 uint16_t c = clr[(fb >> 31) & 1]; 658 659 c = c << 8 | c; 660 *(uint16_t *)dp = c; 661 dp += 2; 662 fb <<= 1; 663 } 664 } 665 } 666 667 /* Do underline */ 668 if ((attr & WSATTR_UNDERLINE) != 0) { 669 uint16_t c = clr[1]; 670 671 c = c << 8 | c; 672 rp -= ri->ri_stride * ri->ri_ul.off; 673 674 while (width--) { 675 *(uint16_t *)rp = c; 676 rp += 2; 677 } 678 } 679 } 680 681 /* 682 * Topcat/catseye console attachment 683 */ 684 685 int 686 topcatcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 687 { 688 bus_space_handle_t bsh; 689 void *va; 690 struct diofbreg *fbr; 691 struct diofb *fb = &diofb_cn; 692 int size; 693 694 if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh)) 695 return 1; 696 va = bus_space_vaddr(bst, bsh); 697 fbr = va; 698 699 if (badaddr(va) || fbr->id != GRFHWID) { 700 bus_space_unmap(bst, bsh, PAGE_SIZE); 701 return 1; 702 } 703 704 switch (fbr->fbid) { 705 case GID_TOPCAT: 706 case GID_LRCATSEYE: 707 case GID_HRCCATSEYE: 708 case GID_HRMCATSEYE: 709 break; 710 711 default: 712 bus_space_unmap(bst, bsh, PAGE_SIZE); 713 return 1; 714 } 715 716 size = DIO_SIZE(scode, va); 717 718 bus_space_unmap(bst, bsh, PAGE_SIZE); 719 if (bus_space_map(bst, addr, size, 0, &bsh)) 720 return 1; 721 va = bus_space_vaddr(bst, bsh); 722 723 /* 724 * Initialize the framebuffer hardware. 725 */ 726 conscode = scode; 727 conaddr = va; 728 topcat_reset(fb, conscode, (struct diofbreg *)conaddr); 729 730 /* 731 * Initialize the terminal emulator. 732 */ 733 diofb_cnattach(fb); 734 return 0; 735 } 736