1 /* $NetBSD: topcat.c,v 1.4 2011/02/18 19:15:43 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 fbname = "HP98544 topcat"; 278 break; 279 case 4: 280 if (sc->sc_fb->dheight == 400) 281 fbname = "HP98543 topcat"; 282 else 283 fbname = "HP98545 topcat"; 284 break; 285 case 6: 286 fbname = "HP98547 topcat"; 287 break; 288 } 289 break; 290 case GID_HRCCATSEYE: 291 fbname = "HP98550 catseye"; /* also A1416 kathmandu */ 292 break; 293 case GID_LRCATSEYE: 294 fbname = "HP98549 catseye"; 295 break; 296 case GID_HRMCATSEYE: 297 fbname = "HP98548 catseye"; 298 break; 299 } 300 301 diofb_end_attach(sc->sc_dev, &topcat_accessops, sc->sc_fb, 302 sc->sc_scode == conscode, fbname); 303 } 304 305 /* 306 * Initialize hardware and display routines. 307 */ 308 int 309 topcat_reset(struct diofb *fb, int scode, struct diofbreg *fbr) 310 { 311 volatile struct tcboxfb *tc = (struct tcboxfb *)fbr; 312 int rc; 313 u_int i; 314 315 if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0) 316 return rc; 317 318 /* 319 * If we could not get a valid number of planes, determine it 320 * by writing to the first frame buffer display location, 321 * then reading it back. 322 */ 323 if (fb->planes == 0) { 324 volatile uint8_t *fbp; 325 uint8_t save; 326 327 fbp = (uint8_t *)fb->fbkva; 328 tc->fben = ~0; 329 tc->wen = ~0; 330 tc->ren = ~0; 331 tc->prr = RR_COPY; 332 save = *fbp; 333 *fbp = 0xff; 334 fb->planemask = *fbp; 335 *fbp = save; 336 337 for (fb->planes = 1; fb->planemask >= (1 << fb->planes); 338 fb->planes++); 339 if (fb->planes > 8) 340 fb->planes = 8; 341 fb->planemask = (1 << fb->planes) - 1; 342 } 343 344 fb->bmv = topcat_windowmove; 345 topcat_restore(fb); 346 diofb_fbsetup(fb); 347 for (i = 0; i <= fb->planemask; i++) 348 topcat_setcolor(fb, i); 349 350 return 0; 351 } 352 353 void 354 topcat_restore(struct diofb *fb) 355 { 356 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 357 358 /* 359 * Catseye looks a lot like a topcat, but not completely. 360 * So, we set some bits to make it work. 361 */ 362 if (tc->regs.fbid != GID_TOPCAT) { 363 while ((tc->catseye_status & 1)) 364 ; 365 tc->catseye_status = 0x0; 366 tc->vb_select = 0x0; 367 tc->tcntrl = 0x0; 368 tc->acntrl = 0x0; 369 tc->pncntrl = 0x0; 370 tc->rug_cmdstat = 0x90; 371 } 372 373 /* 374 * Enable reading/writing of all the planes. 375 */ 376 tc->fben = fb->planemask; 377 tc->wen = fb->planemask; 378 tc->ren = fb->planemask; 379 tc->prr = RR_COPY; 380 381 /* Enable display */ 382 tc->nblank = 0xff; 383 } 384 385 int 386 topcat_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, 387 struct lwp *l) 388 { 389 struct diofb *fb = v; 390 struct wsdisplay_fbinfo *wdf; 391 u_int i; 392 393 switch (cmd) { 394 case WSDISPLAYIO_GTYPE: 395 *(u_int *)data = WSDISPLAY_TYPE_TOPCAT; 396 return 0; 397 case WSDISPLAYIO_SMODE: 398 fb->mapmode = *(u_int *)data; 399 if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) { 400 topcat_restore(fb); 401 for (i = 0; i <= fb->planemask; i++) 402 topcat_setcolor(fb, i); 403 } 404 return 0; 405 case WSDISPLAYIO_GINFO: 406 wdf = (void *)data; 407 wdf->width = fb->ri.ri_width; 408 wdf->height = fb->ri.ri_height; 409 wdf->depth = fb->ri.ri_depth; 410 wdf->cmsize = 1 << fb->planes; 411 return 0; 412 case WSDISPLAYIO_LINEBYTES: 413 *(u_int *)data = fb->ri.ri_stride; 414 return 0; 415 case WSDISPLAYIO_GETCMAP: 416 return diofb_getcmap(fb, (struct wsdisplay_cmap *)data); 417 case WSDISPLAYIO_PUTCMAP: 418 return topcat_setcmap(fb, (struct wsdisplay_cmap *)data); 419 case WSDISPLAYIO_GVIDEO: 420 case WSDISPLAYIO_SVIDEO: 421 return EPASSTHROUGH; 422 } 423 424 return EPASSTHROUGH; 425 } 426 427 void 428 topcat_setcolor(struct diofb *fb, u_int index) 429 { 430 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 431 432 if (tc->regs.fbid != GID_TOPCAT) { 433 tccm_waitbusy(tc); 434 tc->plane_mask = 0xff; 435 tc->cindex = ~index; 436 tc->rdata = fb->cmap.r[index]; 437 tc->gdata = fb->cmap.g[index]; 438 tc->bdata = fb->cmap.b[index]; 439 tc->strobe = 0xff; 440 441 tccm_waitbusy(tc); 442 tc->cindex = 0; 443 } else { 444 tccm_waitbusy(tc); 445 tc->plane_mask = 0xff; 446 tc->rdata = fb->cmap.r[index]; 447 tc->gdata = fb->cmap.g[index]; 448 tc->bdata = fb->cmap.b[index]; 449 tc->cindex = ~index; 450 tc->strobe = 0xff; 451 452 tccm_waitbusy(tc); 453 tc->rdata = 0; 454 tc->gdata = 0; 455 tc->bdata = 0; 456 tc->cindex = 0; 457 } 458 } 459 460 int 461 topcat_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm) 462 { 463 uint8_t r[256], g[256], b[256]; 464 u_int index = cm->index, count = cm->count; 465 u_int colcount = 1 << fb->planes; 466 int error; 467 468 if (index >= colcount || count > colcount - index) 469 return EINVAL; 470 471 if ((error = copyin(cm->red, r, count)) != 0) 472 return error; 473 if ((error = copyin(cm->green, g, count)) != 0) 474 return error; 475 if ((error = copyin(cm->blue, b, count)) != 0) 476 return error; 477 478 memcpy(fb->cmap.r + index, r, count); 479 memcpy(fb->cmap.g + index, g, count); 480 memcpy(fb->cmap.b + index, b, count); 481 482 while (count-- != 0) 483 topcat_setcolor(fb, index++); 484 485 return 0; 486 } 487 488 /* 489 * Accelerated routines 490 */ 491 492 int 493 topcat_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy, 494 uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop, 495 int16_t planemask) 496 { 497 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 498 499 tc_waitbusy(tc, fb->planemask); 500 501 tc->wen = planemask; 502 tc->wmrr = rop; 503 if (planemask != 0xff) { 504 tc->wen = planemask ^ 0xff; 505 tc->wmrr = rop ^ 0x0f; 506 tc->wen = fb->planemask; 507 } 508 tc->source_y = sy; 509 tc->source_x = sx; 510 tc->dest_y = dy; 511 tc->dest_x = dx; 512 tc->wheight = cy; 513 tc->wwidth = cx; 514 tc->wmove = fb->planemask; 515 516 tc_waitbusy(tc, fb->planemask); 517 518 return 0; 519 } 520 521 522 /* 523 * Topcat/catseye console attachment 524 */ 525 526 int 527 topcatcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 528 { 529 bus_space_handle_t bsh; 530 void *va; 531 struct diofbreg *fbr; 532 struct diofb *fb = &diofb_cn; 533 int size; 534 535 if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh)) 536 return 1; 537 va = bus_space_vaddr(bst, bsh); 538 fbr = va; 539 540 if (badaddr(va) || fbr->id != GRFHWID) { 541 bus_space_unmap(bst, bsh, PAGE_SIZE); 542 return 1; 543 } 544 545 switch (fbr->fbid) { 546 case GID_TOPCAT: 547 case GID_LRCATSEYE: 548 case GID_HRCCATSEYE: 549 case GID_HRMCATSEYE: 550 break; 551 552 default: 553 bus_space_unmap(bst, bsh, PAGE_SIZE); 554 return 1; 555 } 556 557 size = DIO_SIZE(scode, va); 558 559 bus_space_unmap(bst, bsh, PAGE_SIZE); 560 if (bus_space_map(bst, addr, size, 0, &bsh)) 561 return 1; 562 va = bus_space_vaddr(bst, bsh); 563 564 /* 565 * Initialize the framebuffer hardware. 566 */ 567 conscode = scode; 568 conaddr = va; 569 topcat_reset(fb, conscode, (struct diofbreg *)conaddr); 570 571 /* 572 * Initialize the terminal emulator. 573 */ 574 diofb_cnattach(fb); 575 return 0; 576 } 577