1 /* $NetBSD: cgsix.c,v 1.63 2013/12/03 17:01:04 macallan Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This software was developed by the Computer Systems Engineering group 37 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 38 * contributed to Berkeley. 39 * 40 * All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Lawrence Berkeley Laboratory. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 * @(#)cgsix.c 8.4 (Berkeley) 1/21/94 70 */ 71 72 /* 73 * color display (cgsix) driver. 74 * 75 * Does not handle interrupts, even though they can occur. 76 * 77 * XXX should defer colormap updates to vertical retrace interrupts 78 */ 79 80 #include <sys/cdefs.h> 81 __KERNEL_RCSID(0, "$NetBSD: cgsix.c,v 1.63 2013/12/03 17:01:04 macallan Exp $"); 82 83 #include <sys/param.h> 84 #include <sys/systm.h> 85 #include <sys/buf.h> 86 #include <sys/device.h> 87 #include <sys/ioctl.h> 88 #include <sys/malloc.h> 89 #include <sys/mman.h> 90 #include <sys/tty.h> 91 #include <sys/conf.h> 92 93 #ifdef DEBUG 94 #include <sys/proc.h> 95 #include <sys/syslog.h> 96 #endif 97 98 #include <sys/bus.h> 99 100 #include <dev/sun/fbio.h> 101 #include <dev/sun/fbvar.h> 102 103 #include <dev/sun/btreg.h> 104 #include <dev/sun/btvar.h> 105 #include <dev/sun/pfourreg.h> 106 107 #include <dev/wscons/wsconsio.h> 108 #include <dev/wsfont/wsfont.h> 109 #include <dev/rasops/rasops.h> 110 111 #include "opt_wsemul.h" 112 #include "rasops_glue.h" 113 114 #include <dev/sun/cgsixreg.h> 115 #include <dev/sun/cgsixvar.h> 116 117 #include "ioconf.h" 118 119 static void cg6_unblank(device_t); 120 static void cg6_blank(struct cgsix_softc *, int); 121 122 dev_type_open(cgsixopen); 123 dev_type_close(cgsixclose); 124 dev_type_ioctl(cgsixioctl); 125 dev_type_mmap(cgsixmmap); 126 127 const struct cdevsw cgsix_cdevsw = { 128 cgsixopen, cgsixclose, noread, nowrite, cgsixioctl, 129 nostop, notty, nopoll, cgsixmmap, nokqfilter, D_OTHER 130 }; 131 132 /* frame buffer generic driver */ 133 static struct fbdriver cg6_fbdriver = { 134 cg6_unblank, cgsixopen, cgsixclose, cgsixioctl, nopoll, cgsixmmap, 135 nokqfilter 136 }; 137 138 static void cg6_reset (struct cgsix_softc *); 139 static void cg6_loadcmap (struct cgsix_softc *, int, int); 140 static void cg6_loadomap (struct cgsix_softc *); 141 static void cg6_setcursor (struct cgsix_softc *);/* set position */ 142 static void cg6_loadcursor (struct cgsix_softc *);/* set shape */ 143 144 #if NWSDISPLAY > 0 145 #ifdef RASTERCONSOLE 146 #error RASTERCONSOLE and wsdisplay are mutually exclusive 147 #endif 148 149 static void cg6_setup_palette(struct cgsix_softc *); 150 151 struct wsscreen_descr cgsix_defaultscreen = { 152 "std", 153 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 154 NULL, /* textops */ 155 8, 16, /* font width/height */ 156 WSSCREEN_WSCOLORS, /* capabilities */ 157 NULL /* modecookie */ 158 }; 159 160 static int cgsix_ioctl(void *, void *, u_long, void *, int, struct lwp *); 161 static paddr_t cgsix_mmap(void *, void *, off_t, int); 162 static void cgsix_init_screen(void *, struct vcons_screen *, int, long *); 163 164 static void cgsix_clearscreen(struct cgsix_softc *); 165 166 void cgsix_setup_mono(struct cgsix_softc *, int, int, int, int, uint32_t, 167 uint32_t); 168 void cgsix_feed_line(struct cgsix_softc *, int, uint8_t *); 169 void cgsix_rectfill(struct cgsix_softc *, int, int, int, int, uint32_t); 170 void cgsix_bitblt(void *, int, int, int, int, int, int, int); 171 172 int cgsix_putcmap(struct cgsix_softc *, struct wsdisplay_cmap *); 173 int cgsix_getcmap(struct cgsix_softc *, struct wsdisplay_cmap *); 174 void cgsix_putchar(void *, int, int, u_int, long); 175 void cgsix_putchar_aa(void *, int, int, u_int, long); 176 void cgsix_cursor(void *, int, int, int); 177 178 struct wsdisplay_accessops cgsix_accessops = { 179 cgsix_ioctl, 180 cgsix_mmap, 181 NULL, /* alloc_screen */ 182 NULL, /* free_screen */ 183 NULL, /* show_screen */ 184 NULL, /* load_font */ 185 NULL, /* pollc */ 186 NULL /* scroll */ 187 }; 188 189 const struct wsscreen_descr *_cgsix_scrlist[] = { 190 &cgsix_defaultscreen 191 }; 192 193 struct wsscreen_list cgsix_screenlist = { 194 sizeof(_cgsix_scrlist) / sizeof(struct wsscreen_descr *), 195 _cgsix_scrlist 196 }; 197 198 199 extern const u_char rasops_cmap[768]; 200 201 #endif /* NWSDISPLAY > 0 */ 202 203 #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE) 204 void cg6_invert(struct cgsix_softc *, int, int, int, int); 205 206 /* need this for both cases because ri_hw points to it */ 207 static struct vcons_screen cg6_console_screen; 208 #endif 209 210 #ifdef RASTERCONSOLE 211 int cgsix_use_rasterconsole = 1; 212 #endif 213 214 /* 215 * cg6 accelerated console routines. 216 * 217 * Note that buried in this code in several places is the assumption 218 * that pixels are exactly one byte wide. Since this is cg6-specific 219 * code, this seems safe. This assumption resides in things like the 220 * use of ri_emuwidth without messing around with ri_pelbytes, or the 221 * assumption that ri_font->fontwidth is the right thing to multiply 222 * character-cell counts by to get byte counts. 223 */ 224 225 /* 226 * Magic values for blitter 227 */ 228 229 /* Values for the mode register */ 230 #define CG6_MODE ( \ 231 0x00200000 /* GX_BLIT_SRC */ \ 232 | 0x00020000 /* GX_MODE_COLOR8 */ \ 233 | 0x00008000 /* GX_DRAW_RENDER */ \ 234 | 0x00002000 /* GX_BWRITE0_ENABLE */ \ 235 | 0x00001000 /* GX_BWRITE1_DISABLE */ \ 236 | 0x00000200 /* GX_BREAD_0 */ \ 237 | 0x00000080 /* GX_BDISP_0 */ \ 238 ) 239 #define CG6_MODE_MASK ( \ 240 0x00300000 /* GX_BLIT_ALL */ \ 241 | 0x00060000 /* GX_MODE_ALL */ \ 242 | 0x00018000 /* GX_DRAW_ALL */ \ 243 | 0x00006000 /* GX_BWRITE0_ALL */ \ 244 | 0x00001800 /* GX_BWRITE1_ALL */ \ 245 | 0x00000600 /* GX_BREAD_ALL */ \ 246 | 0x00000180 /* GX_BDISP_ALL */ \ 247 ) 248 249 /* Value for the alu register for screen-to-screen copies */ 250 #define CG6_ALU_COPY ( \ 251 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 252 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 253 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 254 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 255 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 256 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 257 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 258 | 0x0000cccc /* ALU = src */ \ 259 ) 260 261 /* Value for the alu register for region fills */ 262 #define CG6_ALU_FILL ( \ 263 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 264 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 265 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 266 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 267 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 268 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 269 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 270 | 0x0000ff00 /* ALU = fg color */ \ 271 ) 272 273 /* Value for the alu register for toggling an area */ 274 #define CG6_ALU_FLIP ( \ 275 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 276 | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 277 | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 278 | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 279 | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 280 | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 281 | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 282 | 0x00005555 /* ALU = ~dst */ \ 283 ) 284 285 /* 286 * Run a blitter command 287 */ 288 #define CG6_BLIT(f) { (void)f->fbc_blit; } 289 290 /* 291 * Run a drawing command 292 */ 293 #define CG6_DRAW(f) { (void)f->fbc_draw; } 294 295 /* 296 * Wait for the whole engine to go idle. This may not matter in our case; 297 * I'm not sure whether blits are actually queued or not. It more likely 298 * is intended for lines and such that do get queued. 299 * 0x10000000 bit: GX_INPROGRESS 300 */ 301 #define CG6_DRAIN(fbc) do { \ 302 while ((fbc)->fbc_s & GX_INPROGRESS) \ 303 /*EMPTY*/; \ 304 } while (0) 305 306 /* 307 * something is missing here 308 * Waiting for GX_FULL to clear should be enough to send another command 309 * but some CG6 ( LX onboard for example ) lock up if we do that while 310 * it works fine on others ( a 4MB TGX+ I've got here ) 311 * So, until I figure out what's going on we wait for the blitter to go 312 * fully idle. 313 */ 314 #define CG6_WAIT_READY(fbc) do { \ 315 while (((fbc)->fbc_s & GX_INPROGRESS/*GX_FULL*/) != 0) \ 316 /*EMPTY*/; \ 317 } while (0) 318 319 #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE) 320 static void cg6_ras_init(struct cgsix_softc *); 321 static void cg6_ras_copyrows(void *, int, int, int); 322 static void cg6_ras_copycols(void *, int, int, int, int); 323 static void cg6_ras_erasecols(void *, int, int, int, long int); 324 static void cg6_ras_eraserows(void *, int, int, long int); 325 #if defined(RASTERCONSOLE) && defined(CG6_BLIT_CURSOR) 326 static void cg6_ras_do_cursor(struct rasops_info *); 327 #endif 328 329 static void 330 cg6_ras_init(struct cgsix_softc *sc) 331 { 332 volatile struct cg6_fbc *fbc = sc->sc_fbc; 333 334 CG6_DRAIN(fbc); 335 fbc->fbc_mode &= ~CG6_MODE_MASK; 336 fbc->fbc_mode |= CG6_MODE; 337 338 /* set some common drawing engine parameters */ 339 fbc->fbc_clip = 0; 340 fbc->fbc_s = 0; 341 fbc->fbc_offx = 0; 342 fbc->fbc_offy = 0; 343 fbc->fbc_clipminx = 0; 344 fbc->fbc_clipminy = 0; 345 fbc->fbc_clipmaxx = 0x3fff; 346 fbc->fbc_clipmaxy = 0x3fff; 347 } 348 349 static void 350 cg6_ras_copyrows(void *cookie, int src, int dst, int n) 351 { 352 struct rasops_info *ri = cookie; 353 struct vcons_screen *scr = ri->ri_hw; 354 struct cgsix_softc *sc = scr->scr_cookie; 355 volatile struct cg6_fbc *fbc = sc->sc_fbc; 356 357 if (dst == src) 358 return; 359 if (src < 0) { 360 n += src; 361 src = 0; 362 } 363 if (src+n > ri->ri_rows) 364 n = ri->ri_rows - src; 365 if (dst < 0) { 366 n += dst; 367 dst = 0; 368 } 369 if (dst+n > ri->ri_rows) 370 n = ri->ri_rows - dst; 371 if (n <= 0) 372 return; 373 n *= ri->ri_font->fontheight; 374 src *= ri->ri_font->fontheight; 375 dst *= ri->ri_font->fontheight; 376 377 CG6_WAIT_READY(fbc); 378 379 fbc->fbc_alu = CG6_ALU_COPY; 380 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 381 382 fbc->fbc_x0 = ri->ri_xorigin; 383 fbc->fbc_y0 = ri->ri_yorigin + src; 384 fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1; 385 fbc->fbc_y1 = ri->ri_yorigin + src + n - 1; 386 fbc->fbc_x2 = ri->ri_xorigin; 387 fbc->fbc_y2 = ri->ri_yorigin + dst; 388 fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1; 389 fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1; 390 CG6_BLIT(fbc); 391 } 392 393 static void 394 cg6_ras_copycols(void *cookie, int row, int src, int dst, int n) 395 { 396 struct rasops_info *ri = cookie; 397 struct vcons_screen *scr = ri->ri_hw; 398 struct cgsix_softc *sc = scr->scr_cookie; 399 volatile struct cg6_fbc *fbc = sc->sc_fbc; 400 401 if (dst == src) 402 return; 403 if ((row < 0) || (row >= ri->ri_rows)) 404 return; 405 if (src < 0) { 406 n += src; 407 src = 0; 408 } 409 if (src+n > ri->ri_cols) 410 n = ri->ri_cols - src; 411 if (dst < 0) { 412 n += dst; 413 dst = 0; 414 } 415 if (dst+n > ri->ri_cols) 416 n = ri->ri_cols - dst; 417 if (n <= 0) 418 return; 419 n *= ri->ri_font->fontwidth; 420 src *= ri->ri_font->fontwidth; 421 dst *= ri->ri_font->fontwidth; 422 row *= ri->ri_font->fontheight; 423 424 CG6_WAIT_READY(fbc); 425 426 fbc->fbc_alu = CG6_ALU_COPY; 427 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 428 429 fbc->fbc_x0 = ri->ri_xorigin + src; 430 fbc->fbc_y0 = ri->ri_yorigin + row; 431 fbc->fbc_x1 = ri->ri_xorigin + src + n - 1; 432 fbc->fbc_y1 = ri->ri_yorigin + row + 433 ri->ri_font->fontheight - 1; 434 fbc->fbc_x2 = ri->ri_xorigin + dst; 435 fbc->fbc_y2 = ri->ri_yorigin + row; 436 fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1; 437 fbc->fbc_y3 = ri->ri_yorigin + row + 438 ri->ri_font->fontheight - 1; 439 CG6_BLIT(fbc); 440 } 441 442 static void 443 cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr) 444 { 445 struct rasops_info *ri = cookie; 446 struct vcons_screen *scr = ri->ri_hw; 447 struct cgsix_softc *sc = scr->scr_cookie; 448 volatile struct cg6_fbc *fbc = sc->sc_fbc; 449 450 if ((row < 0) || (row >= ri->ri_rows)) 451 return; 452 if (col < 0) { 453 n += col; 454 col = 0; 455 } 456 if (col+n > ri->ri_cols) 457 n = ri->ri_cols - col; 458 if (n <= 0) 459 return; 460 n *= ri->ri_font->fontwidth; 461 col *= ri->ri_font->fontwidth; 462 row *= ri->ri_font->fontheight; 463 464 CG6_WAIT_READY(fbc); 465 fbc->fbc_alu = CG6_ALU_FILL; 466 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 467 468 fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff]; 469 fbc->fbc_arecty = ri->ri_yorigin + row; 470 fbc->fbc_arectx = ri->ri_xorigin + col; 471 fbc->fbc_arecty = ri->ri_yorigin + row + 472 ri->ri_font->fontheight - 1; 473 fbc->fbc_arectx = ri->ri_xorigin + col + n - 1; 474 CG6_DRAW(fbc); 475 } 476 477 static void 478 cg6_ras_eraserows(void *cookie, int row, int n, long int attr) 479 { 480 struct rasops_info *ri = cookie; 481 struct vcons_screen *scr = ri->ri_hw; 482 struct cgsix_softc *sc = scr->scr_cookie; 483 volatile struct cg6_fbc *fbc = sc->sc_fbc; 484 485 if (row < 0) { 486 n += row; 487 row = 0; 488 } 489 if (row+n > ri->ri_rows) 490 n = ri->ri_rows - row; 491 if (n <= 0) 492 return; 493 494 CG6_WAIT_READY(fbc); 495 fbc->fbc_alu = CG6_ALU_FILL; 496 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 497 498 fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff]; 499 if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) { 500 fbc->fbc_arecty = 0; 501 fbc->fbc_arectx = 0; 502 fbc->fbc_arecty = ri->ri_height - 1; 503 fbc->fbc_arectx = ri->ri_width - 1; 504 } else { 505 row *= ri->ri_font->fontheight; 506 fbc->fbc_arecty = ri->ri_yorigin + row; 507 fbc->fbc_arectx = ri->ri_xorigin; 508 fbc->fbc_arecty = ri->ri_yorigin + row + 509 (n * ri->ri_font->fontheight) - 1; 510 fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1; 511 } 512 CG6_DRAW(fbc); 513 } 514 515 #if defined(RASTERCONSOLE) && defined(CG6_BLIT_CURSOR) 516 /* 517 * Really want something more like fg^bg here, but that would be more 518 * or less impossible to migrate to colors. So we hope there's 519 * something not too inappropriate in the colormap...besides, it's what 520 * the non-accelerated code did. :-) 521 */ 522 static void 523 cg6_ras_do_cursor(struct rasops_info *ri) 524 { 525 struct vcons_screen *scr = ri->ri_hw; 526 struct cgsix_softc *sc = scr->cookie; 527 int row, col; 528 529 row = ri->ri_crow * ri->ri_font->fontheight; 530 col = ri->ri_ccol * ri->ri_font->fontwidth; 531 cg6_invert(sc, ri->ri_xorigin + col,ri->ri_yorigin + 532 row, ri->ri_font->fontwidth, ri->ri_font->fontheight); 533 } 534 #endif /* RASTERCONSOLE */ 535 536 #endif /* (NWSDISPLAY > 0) || defined(RASTERCONSOLE) */ 537 538 void 539 cg6attach(struct cgsix_softc *sc, const char *name, int isconsole) 540 { 541 struct fbdevice *fb = &sc->sc_fb; 542 #if NWSDISPLAY > 0 543 struct wsemuldisplaydev_attach_args aa; 544 struct rasops_info *ri = &cg6_console_screen.scr_ri; 545 unsigned long defattr; 546 #endif 547 548 fb->fb_driver = &cg6_fbdriver; 549 550 /* Don't have to map the pfour register on the cgsix. */ 551 fb->fb_pfour = NULL; 552 553 fb->fb_type.fb_cmsize = 256; 554 fb->fb_type.fb_size = sc->sc_ramsize; 555 556 printf(": %s, %d x %d", name, 557 fb->fb_type.fb_width, fb->fb_type.fb_height); 558 if(sc->sc_fhc) { 559 sc->sc_fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) & 560 (FHC_REV_MASK >> FHC_REV_SHIFT); 561 } else 562 sc->sc_fhcrev=-1; 563 printf(", rev %d", sc->sc_fhcrev); 564 565 /* reset cursor & frame buffer controls */ 566 cg6_reset(sc); 567 568 /* enable video */ 569 sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 570 571 if (isconsole) { 572 printf(" (console)"); 573 574 /* this is the old console attachment stuff - sparc still needs it */ 575 #ifdef RASTERCONSOLE 576 if (cgsix_use_rasterconsole) { 577 fbrcons_init(&sc->sc_fb); 578 /* 579 * we don't use the screen struct but keep it here to 580 * avoid ugliness in the cg6_ras_* functions 581 */ 582 cg6_console_screen.scr_cookie = sc; 583 sc->sc_fb.fb_rinfo.ri_hw = &cg6_console_screen; 584 sc->sc_fb.fb_rinfo.ri_ops.copyrows = cg6_ras_copyrows; 585 sc->sc_fb.fb_rinfo.ri_ops.copycols = cg6_ras_copycols; 586 sc->sc_fb.fb_rinfo.ri_ops.erasecols = cg6_ras_erasecols; 587 sc->sc_fb.fb_rinfo.ri_ops.eraserows = cg6_ras_eraserows; 588 #ifdef CG6_BLIT_CURSOR 589 sc->sc_fb.fb_rinfo.ri_do_cursor = cg6_ras_do_cursor; 590 #endif 591 cg6_ras_init(sc); 592 } 593 #endif 594 } 595 printf("\n"); 596 597 fb_attach(&sc->sc_fb, isconsole); 598 sc->sc_width = fb->fb_type.fb_width; 599 sc->sc_stride = fb->fb_type.fb_width; 600 sc->sc_height = fb->fb_type.fb_height; 601 602 printf("%s: framebuffer size: %d MB\n", device_xname(sc->sc_dev), 603 sc->sc_ramsize >> 20); 604 605 #if NWSDISPLAY 606 /* setup rasops and so on for wsdisplay */ 607 memcpy(sc->sc_default_cmap, rasops_cmap, 768); 608 wsfont_init(); 609 cg6_ras_init(sc); 610 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 611 sc->sc_bg = WS_DEFAULT_BG; 612 sc->sc_fb_is_open = FALSE; 613 614 vcons_init(&sc->vd, sc, &cgsix_defaultscreen, &cgsix_accessops); 615 sc->vd.init_screen = cgsix_init_screen; 616 617 sc->sc_gc.gc_bitblt = cgsix_bitblt; 618 sc->sc_gc.gc_blitcookie = sc; 619 sc->sc_gc.gc_rop = CG6_ALU_COPY; 620 621 if(isconsole) { 622 /* we mess with cg6_console_screen only once */ 623 vcons_init_screen(&sc->vd, &cg6_console_screen, 1, 624 &defattr); 625 sc->sc_bg = (defattr >> 16) & 0xf; /* yes, this is an index into devcmap */ 626 627 /* 628 * XXX 629 * Is this actually necessary? We're going to use the blitter later on anyway. 630 */ 631 /* We need unaccelerated initial screen clear on old revisions */ 632 if (sc->sc_fhcrev < 2) { 633 memset(sc->sc_fb.fb_pixels, ri->ri_devcmap[sc->sc_bg], 634 sc->sc_stride * sc->sc_height); 635 } else 636 cgsix_clearscreen(sc); 637 638 cg6_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 639 640 cgsix_defaultscreen.textops = &ri->ri_ops; 641 cgsix_defaultscreen.capabilities = ri->ri_caps; 642 cgsix_defaultscreen.nrows = ri->ri_rows; 643 cgsix_defaultscreen.ncols = ri->ri_cols; 644 SCREEN_VISIBLE(&cg6_console_screen); 645 sc->vd.active = &cg6_console_screen; 646 wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr); 647 if (ri->ri_flg & RI_ENABLE_ALPHA) { 648 glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 649 (sc->sc_ramsize / sc->sc_stride) - 650 sc->sc_height - 5, 651 sc->sc_width, 652 ri->ri_font->fontwidth, 653 ri->ri_font->fontheight, 654 defattr); 655 } 656 vcons_replay_msgbuf(&cg6_console_screen); 657 } else { 658 /* 659 * since we're not the console we can postpone the rest 660 * until someone actually allocates a screen for us 661 */ 662 if (cg6_console_screen.scr_ri.ri_rows == 0) { 663 /* do some minimal setup to avoid weirdnesses later */ 664 vcons_init_screen(&sc->vd, &cg6_console_screen, 1, 665 &defattr); 666 } else 667 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 668 sc->sc_bg = (defattr >> 16) & 0xf; 669 if (ri->ri_flg & RI_ENABLE_ALPHA) { 670 glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 671 (sc->sc_ramsize / sc->sc_stride) - 672 sc->sc_height - 5, 673 sc->sc_width, 674 ri->ri_font->fontwidth, 675 ri->ri_font->fontheight, 676 defattr); 677 } 678 } 679 cg6_setup_palette(sc); 680 681 aa.scrdata = &cgsix_screenlist; 682 aa.console = isconsole; 683 aa.accessops = &cgsix_accessops; 684 aa.accesscookie = &sc->vd; 685 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); 686 #else 687 bt_initcmap(&sc->sc_cmap, 256); 688 cg6_loadcmap(sc, 0, 256); 689 690 #endif 691 } 692 693 694 int 695 cgsixopen(dev_t dev, int flags, int mode, struct lwp *l) 696 { 697 device_t dv = device_lookup(&cgsix_cd, minor(dev)); 698 struct cgsix_softc *sc = device_private(dv); 699 700 if (dv == NULL) 701 return ENXIO; 702 sc->sc_fb_is_open = TRUE; 703 704 return 0; 705 } 706 707 int 708 cgsixclose(dev_t dev, int flags, int mode, struct lwp *l) 709 { 710 device_t dv = device_lookup(&cgsix_cd, minor(dev)); 711 struct cgsix_softc *sc = device_private(dv); 712 713 cg6_reset(sc); 714 sc->sc_fb_is_open = FALSE; 715 716 #if NWSDISPLAY > 0 717 if (IS_IN_EMUL_MODE(sc)) { 718 struct vcons_screen *ms = sc->vd.active; 719 720 cg6_ras_init(sc); 721 cg6_setup_palette(sc); 722 glyphcache_wipe(&sc->sc_gc); 723 724 /* we don't know if the screen exists */ 725 if (ms != NULL) 726 vcons_redraw_screen(ms); 727 } 728 #else 729 /* (re-)initialize the default color map */ 730 bt_initcmap(&sc->sc_cmap, 256); 731 732 cg6_loadcmap(sc, 0, 256); 733 #endif 734 return 0; 735 } 736 737 int 738 cgsixioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 739 { 740 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 741 union cursor_cmap tcm; 742 uint32_t image[32], mask[32]; 743 u_int count; 744 int v, error; 745 746 #ifdef CGSIX_DEBUG 747 printf("cgsixioctl(%lx)\n",cmd); 748 #endif 749 750 switch (cmd) { 751 752 case FBIOGTYPE: 753 *(struct fbtype *)data = sc->sc_fb.fb_type; 754 break; 755 756 case FBIOGATTR: 757 #define fba ((struct fbgattr *)data) 758 fba->real_type = sc->sc_fb.fb_type.fb_type; 759 fba->owner = 0; /* XXX ??? */ 760 fba->fbtype = sc->sc_fb.fb_type; 761 fba->sattr.flags = 0; 762 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 763 fba->sattr.dev_specific[0] = -1; 764 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 765 fba->emu_types[1] = -1; 766 #undef fba 767 break; 768 769 case FBIOGETCMAP: 770 #define p ((struct fbcmap *)data) 771 return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); 772 773 case FBIOPUTCMAP: 774 /* copy to software map */ 775 error = bt_putcmap(p, &sc->sc_cmap, 256, 1); 776 if (error) 777 return error; 778 /* now blast them into the chip */ 779 /* XXX should use retrace interrupt */ 780 cg6_loadcmap(sc, p->index, p->count); 781 #undef p 782 break; 783 784 case FBIOGVIDEO: 785 *(int *)data = sc->sc_blanked; 786 break; 787 788 case FBIOSVIDEO: 789 cg6_blank(sc, !(*(int *)data)); 790 break; 791 792 /* these are for both FBIOSCURSOR and FBIOGCURSOR */ 793 #define p ((struct fbcursor *)data) 794 #define cc (&sc->sc_cursor) 795 796 case FBIOGCURSOR: 797 /* do not quite want everything here... */ 798 p->set = FB_CUR_SETALL; /* close enough, anyway */ 799 p->enable = cc->cc_enable; 800 p->pos = cc->cc_pos; 801 p->hot = cc->cc_hot; 802 p->size = cc->cc_size; 803 804 /* begin ugh ... can we lose some of this crap?? */ 805 if (p->image != NULL) { 806 count = cc->cc_size.y * 32 / NBBY; 807 error = copyout(cc->cc_bits[1], p->image, count); 808 if (error) 809 return error; 810 error = copyout(cc->cc_bits[0], p->mask, count); 811 if (error) 812 return error; 813 } 814 if (p->cmap.red != NULL) { 815 error = bt_getcmap(&p->cmap, 816 (union bt_cmap *)&cc->cc_color, 2, 1); 817 if (error) 818 return error; 819 } else { 820 p->cmap.index = 0; 821 p->cmap.count = 2; 822 } 823 /* end ugh */ 824 break; 825 826 case FBIOSCURSOR: 827 /* 828 * For setcmap and setshape, verify parameters, so that 829 * we do not get halfway through an update and then crap 830 * out with the software state screwed up. 831 */ 832 v = p->set; 833 if (v & FB_CUR_SETCMAP) { 834 /* 835 * This use of a temporary copy of the cursor 836 * colormap is not terribly efficient, but these 837 * copies are small (8 bytes)... 838 */ 839 tcm = cc->cc_color; 840 error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2, 841 1); 842 if (error) 843 return error; 844 } 845 if (v & FB_CUR_SETSHAPE) { 846 if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32) 847 return EINVAL; 848 count = p->size.y * 32 / NBBY; 849 error = copyin(p->image, image, count); 850 if (error) 851 return error; 852 error = copyin(p->mask, mask, count); 853 if (error) 854 return error; 855 } 856 857 /* parameters are OK; do it */ 858 if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { 859 if (v & FB_CUR_SETCUR) 860 cc->cc_enable = p->enable; 861 if (v & FB_CUR_SETPOS) 862 cc->cc_pos = p->pos; 863 if (v & FB_CUR_SETHOT) 864 cc->cc_hot = p->hot; 865 cg6_setcursor(sc); 866 } 867 if (v & FB_CUR_SETCMAP) { 868 cc->cc_color = tcm; 869 cg6_loadomap(sc); /* XXX defer to vertical retrace */ 870 } 871 if (v & FB_CUR_SETSHAPE) { 872 cc->cc_size = p->size; 873 count = p->size.y * 32 / NBBY; 874 memset(cc->cc_bits, 0, sizeof cc->cc_bits); 875 memcpy(cc->cc_bits[1], image, count); 876 memcpy(cc->cc_bits[0], mask, count); 877 cg6_loadcursor(sc); 878 } 879 break; 880 881 #undef p 882 #undef cc 883 884 case FBIOGCURPOS: 885 *(struct fbcurpos *)data = sc->sc_cursor.cc_pos; 886 break; 887 888 case FBIOSCURPOS: 889 sc->sc_cursor.cc_pos = *(struct fbcurpos *)data; 890 cg6_setcursor(sc); 891 break; 892 893 case FBIOGCURMAX: 894 /* max cursor size is 32x32 */ 895 ((struct fbcurpos *)data)->x = 32; 896 ((struct fbcurpos *)data)->y = 32; 897 break; 898 899 default: 900 #ifdef DEBUG 901 log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd, 902 l->l_proc->p_comm, l->l_proc->p_pid); 903 #endif 904 return ENOTTY; 905 } 906 return 0; 907 } 908 909 /* 910 * Clean up hardware state (e.g., after bootup or after X crashes). 911 */ 912 static void 913 cg6_reset(struct cgsix_softc *sc) 914 { 915 volatile struct cg6_tec_xxx *tec; 916 int fhc; 917 volatile struct bt_regs *bt; 918 919 /* hide the cursor, just in case */ 920 sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF; 921 922 /* turn off frobs in transform engine (makes X11 work) */ 923 tec = sc->sc_tec; 924 tec->tec_mv = 0; 925 tec->tec_clip = 0; 926 tec->tec_vdc = 0; 927 928 /* take care of hardware bugs in old revisions */ 929 if (sc->sc_fhcrev < 5) { 930 /* 931 * Keep current resolution; set CPU to 68020, set test 932 * window (size 1Kx1K), and for rev 1, disable dest cache. 933 */ 934 fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 | 935 FHC_TEST | 936 (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT); 937 if (sc->sc_fhcrev < 2) 938 fhc |= FHC_DST_DISABLE; 939 *sc->sc_fhc = fhc; 940 } 941 942 /* Enable cursor in Brooktree DAC. */ 943 bt = sc->sc_bt; 944 bt->bt_addr = 0x06 << 24; 945 bt->bt_ctrl |= 0x03 << 24; 946 } 947 948 static void 949 cg6_setcursor(struct cgsix_softc *sc) 950 { 951 952 /* we need to subtract the hot-spot value here */ 953 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f) 954 sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ? 955 ((COORD(x) << 16) | (COORD(y) & 0xffff)) : 956 (THC_CURSOFF << 16) | THC_CURSOFF; 957 #undef COORD 958 } 959 960 static void 961 cg6_loadcursor(struct cgsix_softc *sc) 962 { 963 volatile struct cg6_thc *thc; 964 u_int edgemask, m; 965 int i; 966 967 /* 968 * Keep the top size.x bits. Here we *throw out* the top 969 * size.x bits from an all-one-bits word, introducing zeros in 970 * the top size.x bits, then invert all the bits to get what 971 * we really wanted as our mask. But this fails if size.x is 972 * 32---a sparc uses only the low 5 bits of the shift count--- 973 * so we have to special case that. 974 */ 975 edgemask = ~0; 976 if (sc->sc_cursor.cc_size.x < 32) 977 edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x); 978 thc = sc->sc_thc; 979 for (i = 0; i < 32; i++) { 980 m = sc->sc_cursor.cc_bits[0][i] & edgemask; 981 thc->thc_cursmask[i] = m; 982 thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i]; 983 } 984 } 985 986 /* 987 * Load a subset of the current (new) colormap into the color DAC. 988 */ 989 static void 990 cg6_loadcmap(struct cgsix_softc *sc, int start, int ncolors) 991 { 992 volatile struct bt_regs *bt; 993 u_int *ip, i; 994 int count; 995 996 ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ 997 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; 998 bt = sc->sc_bt; 999 bt->bt_addr = BT_D4M4(start) << 24; 1000 while (--count >= 0) { 1001 i = *ip++; 1002 /* hardware that makes one want to pound boards with hammers */ 1003 bt->bt_cmap = i; 1004 bt->bt_cmap = i << 8; 1005 bt->bt_cmap = i << 16; 1006 bt->bt_cmap = i << 24; 1007 } 1008 } 1009 1010 /* 1011 * Load the cursor (overlay `foreground' and `background') colors. 1012 */ 1013 static void 1014 cg6_loadomap(struct cgsix_softc *sc) 1015 { 1016 volatile struct bt_regs *bt; 1017 u_int i; 1018 1019 bt = sc->sc_bt; 1020 bt->bt_addr = 0x01 << 24; /* set background color */ 1021 i = sc->sc_cursor.cc_color.cm_chip[0]; 1022 bt->bt_omap = i; /* R */ 1023 bt->bt_omap = i << 8; /* G */ 1024 bt->bt_omap = i << 16; /* B */ 1025 1026 bt->bt_addr = 0x03 << 24; /* set foreground color */ 1027 bt->bt_omap = i << 24; /* R */ 1028 i = sc->sc_cursor.cc_color.cm_chip[1]; 1029 bt->bt_omap = i; /* G */ 1030 bt->bt_omap = i << 8; /* B */ 1031 } 1032 1033 /* blank or unblank the screen */ 1034 static void 1035 cg6_blank(struct cgsix_softc *sc, int flag) 1036 { 1037 1038 if (sc->sc_blanked != flag) { 1039 sc->sc_blanked = flag; 1040 if (flag) { 1041 sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN; 1042 } else { 1043 sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 1044 } 1045 } 1046 } 1047 1048 /* 1049 * this is called on panic or ddb entry - force the console to the front, reset 1050 * the colour map and enable drawing so we actually see the message even when X 1051 * is running 1052 */ 1053 static void 1054 cg6_unblank(device_t dev) 1055 { 1056 struct cgsix_softc *sc = device_private(dev); 1057 1058 cg6_blank(sc, 0); 1059 } 1060 1061 /* XXX the following should be moved to a "user interface" header */ 1062 /* 1063 * Base addresses at which users can mmap() the various pieces of a cg6. 1064 * Note that although the Brooktree color registers do not occupy 8K, 1065 * the X server dies if we do not allow it to map 8K there (it just maps 1066 * from 0x70000000 forwards, as a contiguous chunk). 1067 */ 1068 #define CG6_USER_FBC 0x70000000 1069 #define CG6_USER_TEC 0x70001000 1070 #define CG6_USER_BTREGS 0x70002000 1071 #define CG6_USER_FHC 0x70004000 1072 #define CG6_USER_THC 0x70005000 1073 #define CG6_USER_ROM 0x70006000 1074 #define CG6_USER_RAM 0x70016000 1075 #define CG6_USER_DHC 0x80000000 1076 1077 struct mmo { 1078 u_long mo_uaddr; /* user (virtual) address */ 1079 u_long mo_size; /* size, or 0 for video ram size */ 1080 u_long mo_physoff; /* offset from sc_physadr */ 1081 }; 1082 1083 /* 1084 * Return the address that would map the given device at the given 1085 * offset, allowing for the given protection, or return -1 for error. 1086 * 1087 * XXX needs testing against `demanding' applications (e.g., aviator) 1088 */ 1089 paddr_t 1090 cgsixmmap(dev_t dev, off_t off, int prot) 1091 { 1092 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 1093 struct mmo *mo; 1094 u_int u, sz; 1095 static struct mmo mmo[] = { 1096 { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET }, 1097 1098 /* do not actually know how big most of these are! */ 1099 { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET }, 1100 { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET }, 1101 { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET }, 1102 { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET }, 1103 { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET }, 1104 { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET }, 1105 { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET }, 1106 }; 1107 #define NMMO (sizeof mmo / sizeof *mmo) 1108 1109 if (off & PGOFSET) 1110 panic("cgsixmmap"); 1111 1112 /* 1113 * Entries with size 0 map video RAM (i.e., the size in fb data). 1114 * 1115 * Since we work in pages, the fact that the map offset table's 1116 * sizes are sometimes bizarre (e.g., 1) is effectively ignored: 1117 * one byte is as good as one page. 1118 */ 1119 for (mo = mmo; mo < &mmo[NMMO]; mo++) { 1120 if ((u_long)off < mo->mo_uaddr) 1121 continue; 1122 u = off - mo->mo_uaddr; 1123 sz = mo->mo_size ? mo->mo_size : 1124 sc->sc_ramsize; 1125 if (u < sz) { 1126 return (bus_space_mmap(sc->sc_bustag, 1127 sc->sc_paddr, u+mo->mo_physoff, 1128 prot, BUS_SPACE_MAP_LINEAR)); 1129 } 1130 } 1131 1132 #ifdef DEBUG 1133 { 1134 struct proc *p = curlwp->l_proc; /* XXX */ 1135 log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n", 1136 (long long)off, p->p_comm, p->p_pid); 1137 } 1138 #endif 1139 return -1; /* not a user-map offset */ 1140 } 1141 1142 #if NWSDISPLAY > 0 1143 1144 static void 1145 cg6_setup_palette(struct cgsix_softc *sc) 1146 { 1147 int i, j; 1148 1149 rasops_get_cmap(&cg6_console_screen.scr_ri, sc->sc_default_cmap, 1150 sizeof(sc->sc_default_cmap)); 1151 j = 0; 1152 for (i = 0; i < 256; i++) { 1153 sc->sc_cmap.cm_map[i][0] = sc->sc_default_cmap[j]; 1154 j++; 1155 sc->sc_cmap.cm_map[i][1] = sc->sc_default_cmap[j]; 1156 j++; 1157 sc->sc_cmap.cm_map[i][2] = sc->sc_default_cmap[j]; 1158 j++; 1159 } 1160 cg6_loadcmap(sc, 0, 256); 1161 } 1162 1163 int 1164 cgsix_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 1165 struct lwp *l) 1166 { 1167 /* we'll probably need to add more stuff here */ 1168 struct vcons_data *vd = v; 1169 struct cgsix_softc *sc = vd->cookie; 1170 struct wsdisplay_fbinfo *wdf; 1171 struct rasops_info *ri = &sc->sc_fb.fb_rinfo; 1172 struct vcons_screen *ms = sc->vd.active; 1173 1174 #ifdef CGSIX_DEBUG 1175 printf("cgsix_ioctl(%lx)\n",cmd); 1176 #endif 1177 switch (cmd) { 1178 case WSDISPLAYIO_GTYPE: 1179 *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; 1180 return 0; 1181 case WSDISPLAYIO_GINFO: 1182 wdf = (void *)data; 1183 wdf->height = ri->ri_height; 1184 wdf->width = ri->ri_width; 1185 wdf->depth = ri->ri_depth; 1186 wdf->cmsize = 256; 1187 return 0; 1188 1189 case WSDISPLAYIO_GETCMAP: 1190 return cgsix_getcmap(sc, 1191 (struct wsdisplay_cmap *)data); 1192 case WSDISPLAYIO_PUTCMAP: 1193 return cgsix_putcmap(sc, 1194 (struct wsdisplay_cmap *)data); 1195 1196 case WSDISPLAYIO_LINEBYTES: 1197 *(u_int *)data = sc->sc_stride; 1198 return 0; 1199 1200 case WSDISPLAYIO_SMODE: 1201 { 1202 int new_mode = *(int*)data; 1203 1204 if (new_mode != sc->sc_mode) { 1205 sc->sc_mode = new_mode; 1206 if (IS_IN_EMUL_MODE(sc)) { 1207 cg6_reset(sc); 1208 cg6_ras_init(sc); 1209 cg6_setup_palette(sc); 1210 glyphcache_wipe(&sc->sc_gc); 1211 vcons_redraw_screen(ms); 1212 } 1213 } 1214 } 1215 } 1216 return EPASSTHROUGH; 1217 } 1218 1219 paddr_t 1220 cgsix_mmap(void *v, void *vs, off_t offset, int prot) 1221 { 1222 struct vcons_data *vd = v; 1223 struct cgsix_softc *sc = vd->cookie; 1224 1225 if (offset < sc->sc_ramsize) { 1226 return bus_space_mmap(sc->sc_bustag, sc->sc_paddr, 1227 CGSIX_RAM_OFFSET + offset, prot, BUS_SPACE_MAP_LINEAR); 1228 } 1229 return -1; 1230 } 1231 1232 int 1233 cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1234 { 1235 u_int index = cm->index; 1236 u_int count = cm->count; 1237 int error, i; 1238 1239 if (index >= 256 || count > 256 || index + count > 256) 1240 return EINVAL; 1241 1242 for (i = 0; i < count; i++) 1243 { 1244 error = copyin(&cm->red[i], 1245 &sc->sc_cmap.cm_map[index + i][0], 1); 1246 if (error) 1247 return error; 1248 error = copyin(&cm->green[i], 1249 &sc->sc_cmap.cm_map[index + i][1], 1250 1); 1251 if (error) 1252 return error; 1253 error = copyin(&cm->blue[i], 1254 &sc->sc_cmap.cm_map[index + i][2], 1); 1255 if (error) 1256 return error; 1257 } 1258 cg6_loadcmap(sc, index, count); 1259 1260 return 0; 1261 } 1262 1263 int 1264 cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1265 { 1266 u_int index = cm->index; 1267 u_int count = cm->count; 1268 int error,i; 1269 1270 if (index >= 256 || count > 256 || index + count > 256) 1271 return EINVAL; 1272 1273 for (i = 0; i < count; i++) 1274 { 1275 error = copyout(&sc->sc_cmap.cm_map[index + i][0], 1276 &cm->red[i], 1); 1277 if (error) 1278 return error; 1279 error = copyout(&sc->sc_cmap.cm_map[index + i][1], 1280 &cm->green[i], 1); 1281 if (error) 1282 return error; 1283 error = copyout(&sc->sc_cmap.cm_map[index + i][2], 1284 &cm->blue[i], 1); 1285 if (error) 1286 return error; 1287 } 1288 1289 return 0; 1290 } 1291 1292 void 1293 cgsix_init_screen(void *cookie, struct vcons_screen *scr, 1294 int existing, long *defattr) 1295 { 1296 struct cgsix_softc *sc = cookie; 1297 struct rasops_info *ri = &scr->scr_ri; 1298 int av; 1299 1300 ri->ri_depth = 8; 1301 ri->ri_width = sc->sc_width; 1302 ri->ri_height = sc->sc_height; 1303 ri->ri_stride = sc->sc_stride; 1304 av = sc->sc_ramsize - (sc->sc_height * sc->sc_stride); 1305 ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB; 1306 if (av > (128 * 1024)) { 1307 ri->ri_flg |= RI_ENABLE_ALPHA; 1308 } 1309 ri->ri_bits = sc->sc_fb.fb_pixels; 1310 1311 rasops_init(ri, 0, 0); 1312 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 1313 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 1314 sc->sc_width / ri->ri_font->fontwidth); 1315 1316 /* enable acceleration */ 1317 ri->ri_hw = scr; 1318 ri->ri_ops.copyrows = cg6_ras_copyrows; 1319 ri->ri_ops.copycols = cg6_ras_copycols; 1320 ri->ri_ops.eraserows = cg6_ras_eraserows; 1321 ri->ri_ops.erasecols = cg6_ras_erasecols; 1322 ri->ri_ops.cursor = cgsix_cursor; 1323 if (FONT_IS_ALPHA(ri->ri_font)) { 1324 ri->ri_ops.putchar = cgsix_putchar_aa; 1325 } else 1326 ri->ri_ops.putchar = cgsix_putchar; 1327 } 1328 1329 void 1330 cgsix_rectfill(struct cgsix_softc *sc, int xs, int ys, int wi, int he, 1331 uint32_t col) 1332 { 1333 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1334 1335 CG6_WAIT_READY(fbc); 1336 1337 fbc->fbc_alu = CG6_ALU_FILL; 1338 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1339 1340 fbc->fbc_fg = col; 1341 fbc->fbc_arecty = ys; 1342 fbc->fbc_arectx = xs; 1343 fbc->fbc_arecty = ys + he - 1; 1344 fbc->fbc_arectx = xs + wi - 1; 1345 CG6_DRAW(fbc); 1346 } 1347 1348 void 1349 cgsix_bitblt(void *cookie, int xs, int ys, int xd, int yd, 1350 int wi, int he, int rop) 1351 { 1352 struct cgsix_softc *sc = cookie; 1353 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1354 CG6_WAIT_READY(fbc); 1355 1356 fbc->fbc_alu = rop; 1357 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1358 1359 fbc->fbc_x0 = xs; 1360 fbc->fbc_y0 = ys; 1361 fbc->fbc_x1 = xs + wi - 1; 1362 fbc->fbc_y1 = ys + he - 1; 1363 fbc->fbc_x2 = xd; 1364 fbc->fbc_y2 = yd; 1365 fbc->fbc_x3 = xd + wi - 1; 1366 fbc->fbc_y3 = yd + he - 1; 1367 CG6_BLIT(fbc); 1368 } 1369 1370 void 1371 cgsix_setup_mono(struct cgsix_softc *sc, int x, int y, int wi, int he, 1372 uint32_t fg, uint32_t bg) 1373 { 1374 volatile struct cg6_fbc *fbc=sc->sc_fbc; 1375 1376 CG6_WAIT_READY(fbc); 1377 1378 fbc->fbc_x0 = x; 1379 fbc->fbc_x1 = x + wi - 1; 1380 fbc->fbc_y0 = y; 1381 fbc->fbc_incx = 0; 1382 fbc->fbc_incy = 1; 1383 fbc->fbc_fg = fg; 1384 fbc->fbc_bg = bg; 1385 fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR1; 1386 fbc->fbc_alu = GX_PATTERN_ONES | ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET); 1387 sc->sc_mono_width = wi; 1388 /* now feed the data into the chip */ 1389 } 1390 1391 void 1392 cgsix_feed_line(struct cgsix_softc *sc, int count, uint8_t *data) 1393 { 1394 int i; 1395 uint32_t latch, res = 0, shift; 1396 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1397 1398 if (sc->sc_mono_width > 32) { 1399 /* ARGH! */ 1400 } else 1401 { 1402 shift = 24; 1403 for (i = 0; i < count; i++) { 1404 latch = data[i]; 1405 res |= latch << shift; 1406 shift -= 8; 1407 } 1408 fbc->fbc_font = res; 1409 } 1410 } 1411 1412 void 1413 cgsix_putchar(void *cookie, int row, int col, u_int c, long attr) 1414 { 1415 struct rasops_info *ri = cookie; 1416 struct wsdisplay_font *font = PICK_FONT(ri, c); 1417 struct vcons_screen *scr = ri->ri_hw; 1418 struct cgsix_softc *sc = scr->scr_cookie; 1419 int inv; 1420 1421 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) && 1422 (col < ri->ri_cols)) { 1423 1424 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1425 1426 int fg, bg, uc, i; 1427 uint8_t *data; 1428 int x, y, wi, he; 1429 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1430 1431 wi = font->fontwidth; 1432 he = font->fontheight; 1433 1434 if (!CHAR_IN_FONT(c, font)) 1435 return; 1436 inv = ((attr >> 8) & WSATTR_REVERSE); 1437 if (inv) { 1438 fg = (u_char)ri->ri_devcmap[(attr >> 16) & 1439 0xff]; 1440 bg = (u_char)ri->ri_devcmap[(attr >> 24) & 1441 0xff]; 1442 } else { 1443 bg = (u_char)ri->ri_devcmap[(attr >> 16) & 1444 0xff]; 1445 fg = (u_char)ri->ri_devcmap[(attr >> 24) & 1446 0xff]; 1447 } 1448 1449 x = ri->ri_xorigin + col * wi; 1450 y = ri->ri_yorigin + row * he; 1451 1452 if (c == 0x20) { 1453 cgsix_rectfill(sc, x, y, wi, he, bg); 1454 } else { 1455 uc = c - font->firstchar; 1456 data = (uint8_t *)font->data + uc * 1457 ri->ri_fontscale; 1458 1459 cgsix_setup_mono(sc, x, y, wi, 1, fg, bg); 1460 for (i = 0; i < he; i++) { 1461 cgsix_feed_line(sc, font->stride, 1462 data); 1463 data += font->stride; 1464 } 1465 /* put the chip back to normal */ 1466 fbc->fbc_incy = 0; 1467 } 1468 } 1469 } 1470 } 1471 1472 void 1473 cgsix_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1474 { 1475 struct rasops_info *ri = cookie; 1476 struct wsdisplay_font *font = PICK_FONT(ri, c); 1477 struct vcons_screen *scr = ri->ri_hw; 1478 struct cgsix_softc *sc = scr->scr_cookie; 1479 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1480 1481 uint32_t bg, latch = 0, bg8, fg8, pixel; 1482 int i, j, shift, x, y, wi, he, r, g, b, aval; 1483 int r1, g1, b1, r0, g0, b0, fgo, bgo; 1484 uint8_t *data8; 1485 int rv; 1486 1487 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1488 return; 1489 1490 if (!CHAR_IN_FONT(c, font)) 1491 return; 1492 1493 wi = font->fontwidth; 1494 he = font->fontheight; 1495 1496 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1497 x = ri->ri_xorigin + col * wi; 1498 y = ri->ri_yorigin + row * he; 1499 if (c == 0x20) { 1500 cgsix_rectfill(sc, x, y, wi, he, bg); 1501 return; 1502 } 1503 1504 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1505 if (rv == GC_OK) 1506 return; 1507 1508 data8 = WSFONT_GLYPH(c, font); 1509 1510 CG6_WAIT_READY(sc->sc_fbc); 1511 fbc->fbc_incx = 4; 1512 fbc->fbc_incy = 0; 1513 fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR8; 1514 fbc->fbc_alu = CG6_ALU_COPY; 1515 fbc->fbc_clipmaxx = x + wi - 1; 1516 1517 /* 1518 * we need the RGB colours here, so get offsets into rasops_cmap 1519 */ 1520 fgo = ((attr >> 24) & 0xf) * 3; 1521 bgo = ((attr >> 16) & 0xf) * 3; 1522 1523 r0 = rasops_cmap[bgo]; 1524 r1 = rasops_cmap[fgo]; 1525 g0 = rasops_cmap[bgo + 1]; 1526 g1 = rasops_cmap[fgo + 1]; 1527 b0 = rasops_cmap[bgo + 2]; 1528 b1 = rasops_cmap[fgo + 2]; 1529 #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 1530 bg8 = R3G3B2(r0, g0, b0); 1531 fg8 = R3G3B2(r1, g1, b1); 1532 1533 for (i = 0; i < he; i++) { 1534 1535 CG6_WAIT_READY(fbc); 1536 fbc->fbc_x0 = x; 1537 fbc->fbc_x1 = x + 3; 1538 fbc->fbc_y0 = y + i; 1539 1540 shift = 24; 1541 for (j = 0; j < wi; j++) { 1542 aval = *data8; 1543 if (aval == 0) { 1544 pixel = bg8; 1545 } else if (aval == 255) { 1546 pixel = fg8; 1547 } else { 1548 r = aval * r1 + (255 - aval) * r0; 1549 g = aval * g1 + (255 - aval) * g0; 1550 b = aval * b1 + (255 - aval) * b0; 1551 pixel = ((r & 0xe000) >> 8) | 1552 ((g & 0xe000) >> 11) | 1553 ((b & 0xc000) >> 14); 1554 } 1555 data8++; 1556 1557 latch |= pixel << shift; 1558 if (shift == 0) { 1559 fbc->fbc_font = latch; 1560 latch = 0; 1561 shift = 24; 1562 } else 1563 shift -= 8; 1564 } 1565 if (shift != 24) 1566 fbc->fbc_font = latch; 1567 } 1568 fbc->fbc_clipmaxx = 0x3fff; 1569 1570 if (rv == GC_ADD) { 1571 glyphcache_add(&sc->sc_gc, c, x, y); 1572 } 1573 } 1574 1575 void 1576 cgsix_cursor(void *cookie, int on, int row, int col) 1577 { 1578 struct rasops_info *ri = cookie; 1579 struct vcons_screen *scr = ri->ri_hw; 1580 struct cgsix_softc *sc = scr->scr_cookie; 1581 int x, y, wi, he; 1582 1583 wi = ri->ri_font->fontwidth; 1584 he = ri->ri_font->fontheight; 1585 1586 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1587 x = ri->ri_ccol * wi + ri->ri_xorigin; 1588 y = ri->ri_crow * he + ri->ri_yorigin; 1589 if (ri->ri_flg & RI_CURSOR) { 1590 cg6_invert(sc, x, y, wi, he); 1591 ri->ri_flg &= ~RI_CURSOR; 1592 } 1593 ri->ri_crow = row; 1594 ri->ri_ccol = col; 1595 if (on) 1596 { 1597 x = ri->ri_ccol * wi + ri->ri_xorigin; 1598 y = ri->ri_crow * he + ri->ri_yorigin; 1599 cg6_invert(sc, x, y, wi, he); 1600 ri->ri_flg |= RI_CURSOR; 1601 } 1602 } else 1603 { 1604 ri->ri_crow = row; 1605 ri->ri_ccol = col; 1606 ri->ri_flg &= ~RI_CURSOR; 1607 } 1608 } 1609 1610 void 1611 cgsix_clearscreen(struct cgsix_softc *sc) 1612 { 1613 struct rasops_info *ri = &cg6_console_screen.scr_ri; 1614 1615 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1616 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1617 1618 CG6_WAIT_READY(fbc); 1619 1620 fbc->fbc_alu = CG6_ALU_FILL; 1621 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1622 1623 fbc->fbc_fg = ri->ri_devcmap[sc->sc_bg]; 1624 fbc->fbc_arectx = 0; 1625 fbc->fbc_arecty = 0; 1626 fbc->fbc_arectx = ri->ri_width - 1; 1627 fbc->fbc_arecty = ri->ri_height - 1; 1628 CG6_DRAW(fbc); 1629 } 1630 } 1631 1632 #endif /* NWSDISPLAY > 0 */ 1633 1634 #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE) 1635 void 1636 cg6_invert(struct cgsix_softc *sc, int x, int y, int wi, int he) 1637 { 1638 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1639 1640 CG6_WAIT_READY(fbc); 1641 1642 fbc->fbc_alu = CG6_ALU_FLIP; 1643 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1644 fbc->fbc_arecty = y; 1645 fbc->fbc_arectx = x; 1646 fbc->fbc_arecty = y + he - 1; 1647 fbc->fbc_arectx = x + wi - 1; 1648 CG6_DRAW(fbc); 1649 } 1650 1651 #endif 1652 1653