1 /* $NetBSD: topcat.c,v 1.5 2021/04/15 14:43:19 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 153 static struct wsdisplay_accessops topcat_accessops = { 154 topcat_ioctl, 155 diofb_mmap, 156 diofb_alloc_screen, 157 diofb_free_screen, 158 diofb_show_screen, 159 NULL, /* load_font */ 160 }; 161 162 /* 163 * Attachment glue 164 */ 165 166 int 167 topcat_intio_match(device_t parent, cfdata_t cf, void *aux) 168 { 169 struct intio_attach_args *ia = aux; 170 struct diofbreg *fbr; 171 172 if (strcmp("fb", ia->ia_modname) != 0) 173 return 0; 174 175 fbr = (struct diofbreg *)ia->ia_addr; 176 177 if (badaddr((void *)fbr)) 178 return 0; 179 180 if (fbr->id == GRFHWID) { 181 switch (fbr->fbid) { 182 case GID_TOPCAT: 183 case GID_LRCATSEYE: 184 case GID_HRCCATSEYE: 185 case GID_HRMCATSEYE: 186 #if 0 187 case GID_XXXCATSEYE: 188 #endif 189 return 1; 190 } 191 } 192 193 return 0; 194 } 195 196 void 197 topcat_intio_attach(device_t parent, device_t self, void *aux) 198 { 199 struct topcat_softc *sc = device_private(self); 200 struct intio_attach_args *ia = aux; 201 struct diofbreg *fbr; 202 203 sc->sc_dev = self; 204 fbr = (struct diofbreg *)ia->ia_addr; 205 sc->sc_scode = CONSCODE_INTERNAL; 206 207 if (sc->sc_scode == conscode) { 208 sc->sc_fb = &diofb_cn; 209 } else { 210 sc->sc_fb = &sc->sc_fb_store; 211 topcat_reset(sc->sc_fb, sc->sc_scode, fbr); 212 } 213 214 topcat_end_attach(sc, fbr->fbid); 215 } 216 217 int 218 topcat_dio_match(device_t parent, cfdata_t cf, void *aux) 219 { 220 struct dio_attach_args *da = aux; 221 222 if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER) { 223 switch (da->da_secid) { 224 case DIO_DEVICE_SECID_TOPCAT: 225 case DIO_DEVICE_SECID_LRCATSEYE: 226 case DIO_DEVICE_SECID_HRCCATSEYE: 227 case DIO_DEVICE_SECID_HRMCATSEYE: 228 #if 0 229 case DIO_DEVICE_SECID_XXXCATSEYE: 230 #endif 231 return 1; 232 } 233 } 234 235 return 0; 236 } 237 238 void 239 topcat_dio_attach(device_t parent, device_t self, void *aux) 240 { 241 struct topcat_softc *sc = device_private(self); 242 struct dio_attach_args *da = aux; 243 bus_space_handle_t bsh; 244 struct diofbreg *fbr; 245 246 sc->sc_dev = self; 247 sc->sc_scode = da->da_scode; 248 if (sc->sc_scode == conscode) { 249 fbr = (struct diofbreg *)conaddr; /* already mapped */ 250 sc->sc_fb = &diofb_cn; 251 } else { 252 sc->sc_fb = &sc->sc_fb_store; 253 if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0, 254 &bsh)) { 255 aprint_error(": can't map framebuffer\n"); 256 return; 257 } 258 fbr = bus_space_vaddr(da->da_bst, bsh); 259 if (topcat_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) { 260 aprint_error(": can't reset framebuffer\n"); 261 return; 262 } 263 } 264 265 topcat_end_attach(sc, fbr->fbid); 266 } 267 268 void 269 topcat_end_attach(struct topcat_softc *sc, uint8_t id) 270 { 271 const char *fbname = "unknown"; 272 273 switch (id) { 274 case GID_TOPCAT: 275 switch (sc->sc_fb->planes) { 276 case 1: 277 if (sc->sc_fb->dheight == 400) 278 fbname = "HP98542 topcat"; 279 else 280 fbname = "HP98544 topcat"; 281 break; 282 case 4: 283 if (sc->sc_fb->dheight == 400) 284 fbname = "HP98543 topcat"; 285 else 286 fbname = "HP98545 topcat"; 287 break; 288 case 6: 289 fbname = "HP98547 topcat"; 290 break; 291 } 292 break; 293 case GID_HRCCATSEYE: 294 fbname = "HP98550 catseye"; /* also A1416 kathmandu */ 295 break; 296 case GID_LRCATSEYE: 297 fbname = "HP98549 catseye"; 298 break; 299 case GID_HRMCATSEYE: 300 fbname = "HP98548 catseye"; 301 break; 302 } 303 304 diofb_end_attach(sc->sc_dev, &topcat_accessops, sc->sc_fb, 305 sc->sc_scode == conscode, fbname); 306 } 307 308 /* 309 * Initialize hardware and display routines. 310 */ 311 int 312 topcat_reset(struct diofb *fb, int scode, struct diofbreg *fbr) 313 { 314 volatile struct tcboxfb *tc = (struct tcboxfb *)fbr; 315 int rc; 316 u_int i; 317 318 if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0) 319 return rc; 320 321 /* 322 * If we could not get a valid number of planes, determine it 323 * by writing to the first frame buffer display location, 324 * then reading it back. 325 */ 326 if (fb->planes == 0) { 327 volatile uint8_t *fbp; 328 uint8_t save; 329 330 fbp = (uint8_t *)fb->fbkva; 331 tc->fben = ~0; 332 tc->wen = ~0; 333 tc->ren = ~0; 334 tc->prr = RR_COPY; 335 save = *fbp; 336 *fbp = 0xff; 337 fb->planemask = *fbp; 338 *fbp = save; 339 340 for (fb->planes = 1; fb->planemask >= (1 << fb->planes); 341 fb->planes++); 342 if (fb->planes > 8) 343 fb->planes = 8; 344 fb->planemask = (1 << fb->planes) - 1; 345 } 346 347 fb->bmv = topcat_windowmove; 348 topcat_restore(fb); 349 diofb_fbsetup(fb); 350 for (i = 0; i <= fb->planemask; i++) 351 topcat_setcolor(fb, i); 352 353 return 0; 354 } 355 356 void 357 topcat_restore(struct diofb *fb) 358 { 359 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 360 361 /* 362 * Catseye looks a lot like a topcat, but not completely. 363 * So, we set some bits to make it work. 364 */ 365 if (tc->regs.fbid != GID_TOPCAT) { 366 while ((tc->catseye_status & 1)) 367 ; 368 tc->catseye_status = 0x0; 369 tc->vb_select = 0x0; 370 tc->tcntrl = 0x0; 371 tc->acntrl = 0x0; 372 tc->pncntrl = 0x0; 373 tc->rug_cmdstat = 0x90; 374 } 375 376 /* 377 * Enable reading/writing of all the planes. 378 */ 379 tc->fben = fb->planemask; 380 tc->wen = fb->planemask; 381 tc->ren = fb->planemask; 382 tc->prr = RR_COPY; 383 384 /* Enable display */ 385 tc->nblank = 0xff; 386 } 387 388 int 389 topcat_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, 390 struct lwp *l) 391 { 392 struct diofb *fb = v; 393 struct wsdisplay_fbinfo *wdf; 394 u_int i; 395 396 switch (cmd) { 397 case WSDISPLAYIO_GTYPE: 398 *(u_int *)data = WSDISPLAY_TYPE_TOPCAT; 399 return 0; 400 case WSDISPLAYIO_SMODE: 401 fb->mapmode = *(u_int *)data; 402 if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) { 403 topcat_restore(fb); 404 for (i = 0; i <= fb->planemask; i++) 405 topcat_setcolor(fb, i); 406 } 407 return 0; 408 case WSDISPLAYIO_GINFO: 409 wdf = (void *)data; 410 wdf->width = fb->ri.ri_width; 411 wdf->height = fb->ri.ri_height; 412 wdf->depth = fb->ri.ri_depth; 413 wdf->cmsize = 1 << fb->planes; 414 return 0; 415 case WSDISPLAYIO_LINEBYTES: 416 *(u_int *)data = fb->ri.ri_stride; 417 return 0; 418 case WSDISPLAYIO_GETCMAP: 419 if (fb->planemask == 1) 420 return EPASSTHROUGH; 421 return diofb_getcmap(fb, (struct wsdisplay_cmap *)data); 422 case WSDISPLAYIO_PUTCMAP: 423 if (fb->planemask == 1) 424 return EPASSTHROUGH; 425 return topcat_setcmap(fb, (struct wsdisplay_cmap *)data); 426 case WSDISPLAYIO_GVIDEO: 427 case WSDISPLAYIO_SVIDEO: 428 return EPASSTHROUGH; 429 } 430 431 return EPASSTHROUGH; 432 } 433 434 void 435 topcat_setcolor(struct diofb *fb, u_int index) 436 { 437 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 438 439 /* No color map registers on monochrome framebuffers. */ 440 if (fb->planemask == 1) 441 return; 442 443 if (tc->regs.fbid != GID_TOPCAT) { 444 tccm_waitbusy(tc); 445 tc->plane_mask = 0xff; 446 tc->cindex = ~index; 447 tc->rdata = fb->cmap.r[index]; 448 tc->gdata = fb->cmap.g[index]; 449 tc->bdata = fb->cmap.b[index]; 450 tc->strobe = 0xff; 451 452 tccm_waitbusy(tc); 453 tc->cindex = 0; 454 } else { 455 tccm_waitbusy(tc); 456 tc->plane_mask = 0xff; 457 tc->rdata = fb->cmap.r[index]; 458 tc->gdata = fb->cmap.g[index]; 459 tc->bdata = fb->cmap.b[index]; 460 tc->cindex = ~index; 461 tc->strobe = 0xff; 462 463 tccm_waitbusy(tc); 464 tc->rdata = 0; 465 tc->gdata = 0; 466 tc->bdata = 0; 467 tc->cindex = 0; 468 } 469 } 470 471 int 472 topcat_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm) 473 { 474 uint8_t r[256], g[256], b[256]; 475 u_int index = cm->index, count = cm->count; 476 u_int colcount = 1 << fb->planes; 477 int error; 478 479 if (index >= colcount || count > colcount - index) 480 return EINVAL; 481 482 if ((error = copyin(cm->red, r, count)) != 0) 483 return error; 484 if ((error = copyin(cm->green, g, count)) != 0) 485 return error; 486 if ((error = copyin(cm->blue, b, count)) != 0) 487 return error; 488 489 memcpy(fb->cmap.r + index, r, count); 490 memcpy(fb->cmap.g + index, g, count); 491 memcpy(fb->cmap.b + index, b, count); 492 493 while (count-- != 0) 494 topcat_setcolor(fb, index++); 495 496 return 0; 497 } 498 499 /* 500 * Accelerated routines 501 */ 502 503 int 504 topcat_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy, 505 uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop, 506 int16_t planemask) 507 { 508 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 509 510 tc_waitbusy(tc, fb->planemask); 511 512 tc->wen = planemask; 513 tc->wmrr = rop; 514 if (planemask != 0xff) { 515 tc->wen = planemask ^ 0xff; 516 tc->wmrr = rop ^ 0x0f; 517 tc->wen = fb->planemask; 518 } 519 tc->source_y = sy; 520 tc->source_x = sx; 521 tc->dest_y = dy; 522 tc->dest_x = dx; 523 tc->wheight = cy; 524 tc->wwidth = cx; 525 tc->wmove = fb->planemask; 526 527 tc_waitbusy(tc, fb->planemask); 528 529 return 0; 530 } 531 532 533 /* 534 * Topcat/catseye console attachment 535 */ 536 537 int 538 topcatcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 539 { 540 bus_space_handle_t bsh; 541 void *va; 542 struct diofbreg *fbr; 543 struct diofb *fb = &diofb_cn; 544 int size; 545 546 if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh)) 547 return 1; 548 va = bus_space_vaddr(bst, bsh); 549 fbr = va; 550 551 if (badaddr(va) || fbr->id != GRFHWID) { 552 bus_space_unmap(bst, bsh, PAGE_SIZE); 553 return 1; 554 } 555 556 switch (fbr->fbid) { 557 case GID_TOPCAT: 558 case GID_LRCATSEYE: 559 case GID_HRCCATSEYE: 560 case GID_HRMCATSEYE: 561 break; 562 563 default: 564 bus_space_unmap(bst, bsh, PAGE_SIZE); 565 return 1; 566 } 567 568 size = DIO_SIZE(scode, va); 569 570 bus_space_unmap(bst, bsh, PAGE_SIZE); 571 if (bus_space_map(bst, addr, size, 0, &bsh)) 572 return 1; 573 va = bus_space_vaddr(bst, bsh); 574 575 /* 576 * Initialize the framebuffer hardware. 577 */ 578 conscode = scode; 579 conaddr = va; 580 topcat_reset(fb, conscode, (struct diofbreg *)conaddr); 581 582 /* 583 * Initialize the terminal emulator. 584 */ 585 diofb_cnattach(fb); 586 return 0; 587 } 588