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