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