1 /* $NetBSD: cgsix.c,v 1.67 2016/04/21 18:06:06 macallan Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This software was developed by the Computer Systems Engineering group 37 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 38 * contributed to Berkeley. 39 * 40 * All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Lawrence Berkeley Laboratory. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 * @(#)cgsix.c 8.4 (Berkeley) 1/21/94 70 */ 71 72 /* 73 * color display (cgsix) driver. 74 * 75 * Does not handle interrupts, even though they can occur. 76 * 77 * XXX should defer colormap updates to vertical retrace interrupts 78 */ 79 80 #include <sys/cdefs.h> 81 __KERNEL_RCSID(0, "$NetBSD: cgsix.c,v 1.67 2016/04/21 18:06:06 macallan Exp $"); 82 83 #include <sys/param.h> 84 #include <sys/systm.h> 85 #include <sys/buf.h> 86 #include <sys/device.h> 87 #include <sys/ioctl.h> 88 #include <sys/malloc.h> 89 #include <sys/mman.h> 90 #include <sys/tty.h> 91 #include <sys/conf.h> 92 93 #ifdef DEBUG 94 #include <sys/proc.h> 95 #include <sys/syslog.h> 96 #endif 97 98 #include <sys/bus.h> 99 100 #include <dev/sun/fbio.h> 101 #include <dev/sun/fbvar.h> 102 103 #include <dev/sun/btreg.h> 104 #include <dev/sun/btvar.h> 105 #include <dev/sun/pfourreg.h> 106 107 #include <dev/wscons/wsconsio.h> 108 #include <dev/wsfont/wsfont.h> 109 #include <dev/rasops/rasops.h> 110 111 #include "opt_wsemul.h" 112 #include "rasops_glue.h" 113 114 #include <dev/sun/cgsixreg.h> 115 #include <dev/sun/cgsixvar.h> 116 117 #include "ioconf.h" 118 119 static void cg6_unblank(device_t); 120 static void cg6_blank(struct cgsix_softc *, int); 121 122 dev_type_open(cgsixopen); 123 dev_type_close(cgsixclose); 124 dev_type_ioctl(cgsixioctl); 125 dev_type_mmap(cgsixmmap); 126 127 const struct cdevsw cgsix_cdevsw = { 128 .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, /* capabilities */ 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 566 if(isconsole) { 567 /* we mess with cg6_console_screen only once */ 568 vcons_init_screen(&sc->vd, &cg6_console_screen, 1, 569 &defattr); 570 sc->sc_bg = (defattr >> 16) & 0xf; /* yes, this is an index into devcmap */ 571 572 /* 573 * XXX 574 * Is this actually necessary? We're going to use the blitter later on anyway. 575 */ 576 /* We need unaccelerated initial screen clear on old revisions */ 577 if (sc->sc_fhcrev < 2) { 578 memset(sc->sc_fb.fb_pixels, ri->ri_devcmap[sc->sc_bg], 579 sc->sc_stride * sc->sc_height); 580 } else 581 cgsix_clearscreen(sc); 582 583 cg6_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 584 585 cgsix_defaultscreen.textops = &ri->ri_ops; 586 cgsix_defaultscreen.capabilities = ri->ri_caps; 587 cgsix_defaultscreen.nrows = ri->ri_rows; 588 cgsix_defaultscreen.ncols = ri->ri_cols; 589 SCREEN_VISIBLE(&cg6_console_screen); 590 sc->vd.active = &cg6_console_screen; 591 wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr); 592 if (ri->ri_flg & RI_ENABLE_ALPHA) { 593 glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 594 (sc->sc_ramsize / sc->sc_stride) - 595 sc->sc_height - 5, 596 sc->sc_width, 597 ri->ri_font->fontwidth, 598 ri->ri_font->fontheight, 599 defattr); 600 } 601 vcons_replay_msgbuf(&cg6_console_screen); 602 } else { 603 /* 604 * since we're not the console we can postpone the rest 605 * until someone actually allocates a screen for us 606 */ 607 if (cg6_console_screen.scr_ri.ri_rows == 0) { 608 /* do some minimal setup to avoid weirdnesses later */ 609 vcons_init_screen(&sc->vd, &cg6_console_screen, 1, 610 &defattr); 611 } else 612 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 613 sc->sc_bg = (defattr >> 16) & 0xf; 614 if (ri->ri_flg & RI_ENABLE_ALPHA) { 615 glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 616 (sc->sc_ramsize / sc->sc_stride) - 617 sc->sc_height - 5, 618 sc->sc_width, 619 ri->ri_font->fontwidth, 620 ri->ri_font->fontheight, 621 defattr); 622 } 623 } 624 cg6_setup_palette(sc); 625 626 aa.scrdata = &cgsix_screenlist; 627 aa.console = isconsole; 628 aa.accessops = &cgsix_accessops; 629 aa.accesscookie = &sc->vd; 630 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); 631 } 632 633 634 int 635 cgsixopen(dev_t dev, int flags, int mode, struct lwp *l) 636 { 637 device_t dv = device_lookup(&cgsix_cd, minor(dev)); 638 struct cgsix_softc *sc = device_private(dv); 639 640 if (dv == NULL) 641 return ENXIO; 642 sc->sc_fb_is_open = TRUE; 643 644 return 0; 645 } 646 647 int 648 cgsixclose(dev_t dev, int flags, int mode, struct lwp *l) 649 { 650 device_t dv = device_lookup(&cgsix_cd, minor(dev)); 651 struct cgsix_softc *sc = device_private(dv); 652 653 cg6_reset(sc); 654 sc->sc_fb_is_open = FALSE; 655 656 if (IS_IN_EMUL_MODE(sc)) { 657 struct vcons_screen *ms = sc->vd.active; 658 659 cg6_ras_init(sc); 660 cg6_setup_palette(sc); 661 glyphcache_wipe(&sc->sc_gc); 662 663 /* we don't know if the screen exists */ 664 if (ms != NULL) 665 vcons_redraw_screen(ms); 666 } 667 return 0; 668 } 669 670 int 671 cgsixioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 672 { 673 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 674 union cursor_cmap tcm; 675 uint32_t image[32], mask[32]; 676 u_int count; 677 int v, error; 678 679 #ifdef CGSIX_DEBUG 680 printf("cgsixioctl(%lx)\n",cmd); 681 #endif 682 683 switch (cmd) { 684 685 case FBIOGTYPE: 686 *(struct fbtype *)data = sc->sc_fb.fb_type; 687 break; 688 689 case FBIOGATTR: 690 #define fba ((struct fbgattr *)data) 691 fba->real_type = sc->sc_fb.fb_type.fb_type; 692 fba->owner = 0; /* XXX ??? */ 693 fba->fbtype = sc->sc_fb.fb_type; 694 fba->sattr.flags = 0; 695 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 696 fba->sattr.dev_specific[0] = -1; 697 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 698 fba->emu_types[1] = -1; 699 #undef fba 700 break; 701 702 case FBIOGETCMAP: 703 #define p ((struct fbcmap *)data) 704 return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); 705 706 case FBIOPUTCMAP: 707 /* copy to software map */ 708 error = bt_putcmap(p, &sc->sc_cmap, 256, 1); 709 if (error) 710 return error; 711 /* now blast them into the chip */ 712 /* XXX should use retrace interrupt */ 713 cg6_loadcmap(sc, p->index, p->count); 714 #undef p 715 break; 716 717 case FBIOGVIDEO: 718 *(int *)data = sc->sc_blanked; 719 break; 720 721 case FBIOSVIDEO: 722 cg6_blank(sc, !(*(int *)data)); 723 break; 724 725 /* these are for both FBIOSCURSOR and FBIOGCURSOR */ 726 #define p ((struct fbcursor *)data) 727 #define cc (&sc->sc_cursor) 728 729 case FBIOGCURSOR: 730 /* do not quite want everything here... */ 731 p->set = FB_CUR_SETALL; /* close enough, anyway */ 732 p->enable = cc->cc_enable; 733 p->pos = cc->cc_pos; 734 p->hot = cc->cc_hot; 735 p->size = cc->cc_size; 736 737 /* begin ugh ... can we lose some of this crap?? */ 738 if (p->image != NULL) { 739 count = cc->cc_size.y * 32 / NBBY; 740 error = copyout(cc->cc_bits[1], p->image, count); 741 if (error) 742 return error; 743 error = copyout(cc->cc_bits[0], p->mask, count); 744 if (error) 745 return error; 746 } 747 if (p->cmap.red != NULL) { 748 error = bt_getcmap(&p->cmap, 749 (union bt_cmap *)&cc->cc_color, 2, 1); 750 if (error) 751 return error; 752 } else { 753 p->cmap.index = 0; 754 p->cmap.count = 2; 755 } 756 /* end ugh */ 757 break; 758 759 case FBIOSCURSOR: 760 /* 761 * For setcmap and setshape, verify parameters, so that 762 * we do not get halfway through an update and then crap 763 * out with the software state screwed up. 764 */ 765 v = p->set; 766 if (v & FB_CUR_SETCMAP) { 767 /* 768 * This use of a temporary copy of the cursor 769 * colormap is not terribly efficient, but these 770 * copies are small (8 bytes)... 771 */ 772 tcm = cc->cc_color; 773 error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2, 774 1); 775 if (error) 776 return error; 777 } 778 if (v & FB_CUR_SETSHAPE) { 779 if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32) 780 return EINVAL; 781 count = p->size.y * 32 / NBBY; 782 error = copyin(p->image, image, count); 783 if (error) 784 return error; 785 error = copyin(p->mask, mask, count); 786 if (error) 787 return error; 788 } 789 790 /* parameters are OK; do it */ 791 if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { 792 if (v & FB_CUR_SETCUR) 793 cc->cc_enable = p->enable; 794 if (v & FB_CUR_SETPOS) 795 cc->cc_pos = p->pos; 796 if (v & FB_CUR_SETHOT) 797 cc->cc_hot = p->hot; 798 cg6_setcursor(sc); 799 } 800 if (v & FB_CUR_SETCMAP) { 801 cc->cc_color = tcm; 802 cg6_loadomap(sc); /* XXX defer to vertical retrace */ 803 } 804 if (v & FB_CUR_SETSHAPE) { 805 cc->cc_size = p->size; 806 count = p->size.y * 32 / NBBY; 807 memset(cc->cc_bits, 0, sizeof cc->cc_bits); 808 memcpy(cc->cc_bits[1], image, count); 809 memcpy(cc->cc_bits[0], mask, count); 810 cg6_loadcursor(sc); 811 } 812 break; 813 814 #undef p 815 #undef cc 816 817 case FBIOGCURPOS: 818 *(struct fbcurpos *)data = sc->sc_cursor.cc_pos; 819 break; 820 821 case FBIOSCURPOS: 822 sc->sc_cursor.cc_pos = *(struct fbcurpos *)data; 823 cg6_setcursor(sc); 824 break; 825 826 case FBIOGCURMAX: 827 /* max cursor size is 32x32 */ 828 ((struct fbcurpos *)data)->x = 32; 829 ((struct fbcurpos *)data)->y = 32; 830 break; 831 832 default: 833 #ifdef DEBUG 834 log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd, 835 l->l_proc->p_comm, l->l_proc->p_pid); 836 #endif 837 return ENOTTY; 838 } 839 return 0; 840 } 841 842 /* 843 * Clean up hardware state (e.g., after bootup or after X crashes). 844 */ 845 static void 846 cg6_reset(struct cgsix_softc *sc) 847 { 848 volatile struct cg6_tec_xxx *tec; 849 int fhc; 850 volatile struct bt_regs *bt; 851 852 /* hide the cursor, just in case */ 853 sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF; 854 855 /* turn off frobs in transform engine (makes X11 work) */ 856 tec = sc->sc_tec; 857 tec->tec_mv = 0; 858 tec->tec_clip = 0; 859 tec->tec_vdc = 0; 860 861 /* take care of hardware bugs in old revisions */ 862 if (sc->sc_fhcrev < 5) { 863 /* 864 * Keep current resolution; set CPU to 68020, set test 865 * window (size 1Kx1K), and for rev 1, disable dest cache. 866 */ 867 fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 | 868 FHC_TEST | 869 (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT); 870 if (sc->sc_fhcrev < 2) 871 fhc |= FHC_DST_DISABLE; 872 *sc->sc_fhc = fhc; 873 } 874 875 /* Enable cursor in Brooktree DAC. */ 876 bt = sc->sc_bt; 877 bt->bt_addr = 0x06 << 24; 878 bt->bt_ctrl |= 0x03 << 24; 879 } 880 881 static void 882 cg6_setcursor(struct cgsix_softc *sc) 883 { 884 885 /* we need to subtract the hot-spot value here */ 886 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f) 887 sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ? 888 ((COORD(x) << 16) | (COORD(y) & 0xffff)) : 889 (THC_CURSOFF << 16) | THC_CURSOFF; 890 #undef COORD 891 } 892 893 static void 894 cg6_loadcursor(struct cgsix_softc *sc) 895 { 896 volatile struct cg6_thc *thc; 897 u_int edgemask, m; 898 int i; 899 900 /* 901 * Keep the top size.x bits. Here we *throw out* the top 902 * size.x bits from an all-one-bits word, introducing zeros in 903 * the top size.x bits, then invert all the bits to get what 904 * we really wanted as our mask. But this fails if size.x is 905 * 32---a sparc uses only the low 5 bits of the shift count--- 906 * so we have to special case that. 907 */ 908 edgemask = ~0; 909 if (sc->sc_cursor.cc_size.x < 32) 910 edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x); 911 thc = sc->sc_thc; 912 for (i = 0; i < 32; i++) { 913 m = sc->sc_cursor.cc_bits[0][i] & edgemask; 914 thc->thc_cursmask[i] = m; 915 thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i]; 916 } 917 } 918 919 /* 920 * Load a subset of the current (new) colormap into the color DAC. 921 */ 922 static void 923 cg6_loadcmap(struct cgsix_softc *sc, int start, int ncolors) 924 { 925 volatile struct bt_regs *bt; 926 u_int *ip, i; 927 int count; 928 929 ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ 930 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; 931 bt = sc->sc_bt; 932 bt->bt_addr = BT_D4M4(start) << 24; 933 while (--count >= 0) { 934 i = *ip++; 935 /* hardware that makes one want to pound boards with hammers */ 936 bt->bt_cmap = i; 937 bt->bt_cmap = i << 8; 938 bt->bt_cmap = i << 16; 939 bt->bt_cmap = i << 24; 940 } 941 } 942 943 /* 944 * Load the cursor (overlay `foreground' and `background') colors. 945 */ 946 static void 947 cg6_loadomap(struct cgsix_softc *sc) 948 { 949 volatile struct bt_regs *bt; 950 u_int i; 951 952 bt = sc->sc_bt; 953 bt->bt_addr = 0x01 << 24; /* set background color */ 954 i = sc->sc_cursor.cc_color.cm_chip[0]; 955 bt->bt_omap = i; /* R */ 956 bt->bt_omap = i << 8; /* G */ 957 bt->bt_omap = i << 16; /* B */ 958 959 bt->bt_addr = 0x03 << 24; /* set foreground color */ 960 bt->bt_omap = i << 24; /* R */ 961 i = sc->sc_cursor.cc_color.cm_chip[1]; 962 bt->bt_omap = i; /* G */ 963 bt->bt_omap = i << 8; /* B */ 964 } 965 966 /* blank or unblank the screen */ 967 static void 968 cg6_blank(struct cgsix_softc *sc, int flag) 969 { 970 971 if (sc->sc_blanked != flag) { 972 sc->sc_blanked = flag; 973 if (flag) { 974 sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN; 975 } else { 976 sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 977 } 978 } 979 } 980 981 /* 982 * this is called on panic or ddb entry - force the console to the front, reset 983 * the colour map and enable drawing so we actually see the message even when X 984 * is running 985 */ 986 static void 987 cg6_unblank(device_t dev) 988 { 989 struct cgsix_softc *sc = device_private(dev); 990 991 cg6_blank(sc, 0); 992 } 993 994 /* XXX the following should be moved to a "user interface" header */ 995 /* 996 * Base addresses at which users can mmap() the various pieces of a cg6. 997 * Note that although the Brooktree color registers do not occupy 8K, 998 * the X server dies if we do not allow it to map 8K there (it just maps 999 * from 0x70000000 forwards, as a contiguous chunk). 1000 */ 1001 #define CG6_USER_FBC 0x70000000 1002 #define CG6_USER_TEC 0x70001000 1003 #define CG6_USER_BTREGS 0x70002000 1004 #define CG6_USER_FHC 0x70004000 1005 #define CG6_USER_THC 0x70005000 1006 #define CG6_USER_ROM 0x70006000 1007 #define CG6_USER_RAM 0x70016000 1008 #define CG6_USER_DHC 0x80000000 1009 1010 struct mmo { 1011 u_long mo_uaddr; /* user (virtual) address */ 1012 u_long mo_size; /* size, or 0 for video ram size */ 1013 u_long mo_physoff; /* offset from sc_physadr */ 1014 }; 1015 1016 /* 1017 * Return the address that would map the given device at the given 1018 * offset, allowing for the given protection, or return -1 for error. 1019 * 1020 * XXX needs testing against `demanding' applications (e.g., aviator) 1021 */ 1022 paddr_t 1023 cgsixmmap(dev_t dev, off_t off, int prot) 1024 { 1025 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 1026 struct mmo *mo; 1027 u_int u, sz; 1028 static struct mmo mmo[] = { 1029 { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET }, 1030 1031 /* do not actually know how big most of these are! */ 1032 { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET }, 1033 { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET }, 1034 { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET }, 1035 { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET }, 1036 { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET }, 1037 { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET }, 1038 { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET }, 1039 }; 1040 #define NMMO (sizeof mmo / sizeof *mmo) 1041 1042 if (off & PGOFSET) 1043 panic("cgsixmmap"); 1044 1045 /* 1046 * Entries with size 0 map video RAM (i.e., the size in fb data). 1047 * 1048 * Since we work in pages, the fact that the map offset table's 1049 * sizes are sometimes bizarre (e.g., 1) is effectively ignored: 1050 * one byte is as good as one page. 1051 */ 1052 for (mo = mmo; mo < &mmo[NMMO]; mo++) { 1053 if ((u_long)off < mo->mo_uaddr) 1054 continue; 1055 u = off - mo->mo_uaddr; 1056 sz = mo->mo_size ? mo->mo_size : 1057 sc->sc_ramsize; 1058 if (u < sz) { 1059 return (bus_space_mmap(sc->sc_bustag, 1060 sc->sc_paddr, u+mo->mo_physoff, 1061 prot, BUS_SPACE_MAP_LINEAR)); 1062 } 1063 } 1064 1065 #ifdef DEBUG 1066 { 1067 struct proc *p = curlwp->l_proc; /* XXX */ 1068 log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n", 1069 (long long)off, p->p_comm, p->p_pid); 1070 } 1071 #endif 1072 return -1; /* not a user-map offset */ 1073 } 1074 1075 static void 1076 cg6_setup_palette(struct cgsix_softc *sc) 1077 { 1078 int i, j; 1079 1080 rasops_get_cmap(&cg6_console_screen.scr_ri, sc->sc_default_cmap, 1081 sizeof(sc->sc_default_cmap)); 1082 j = 0; 1083 for (i = 0; i < 256; i++) { 1084 sc->sc_cmap.cm_map[i][0] = sc->sc_default_cmap[j]; 1085 j++; 1086 sc->sc_cmap.cm_map[i][1] = sc->sc_default_cmap[j]; 1087 j++; 1088 sc->sc_cmap.cm_map[i][2] = sc->sc_default_cmap[j]; 1089 j++; 1090 } 1091 cg6_loadcmap(sc, 0, 256); 1092 } 1093 1094 int 1095 cgsix_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 1096 struct lwp *l) 1097 { 1098 /* we'll probably need to add more stuff here */ 1099 struct vcons_data *vd = v; 1100 struct cgsix_softc *sc = vd->cookie; 1101 struct wsdisplay_fbinfo *wdf; 1102 struct vcons_screen *ms = sc->vd.active; 1103 1104 #ifdef CGSIX_DEBUG 1105 printf("cgsix_ioctl(%lx)\n",cmd); 1106 #endif 1107 switch (cmd) { 1108 case WSDISPLAYIO_GTYPE: 1109 *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; 1110 return 0; 1111 case WSDISPLAYIO_GINFO: 1112 wdf = (void *)data; 1113 wdf->height = sc->sc_height; 1114 wdf->width = sc->sc_width; 1115 wdf->depth = 8; 1116 wdf->cmsize = 256; 1117 return 0; 1118 1119 case WSDISPLAYIO_GETCMAP: 1120 return cgsix_getcmap(sc, 1121 (struct wsdisplay_cmap *)data); 1122 case WSDISPLAYIO_PUTCMAP: 1123 return cgsix_putcmap(sc, 1124 (struct wsdisplay_cmap *)data); 1125 1126 case WSDISPLAYIO_LINEBYTES: 1127 *(u_int *)data = sc->sc_stride; 1128 return 0; 1129 1130 case WSDISPLAYIO_SMODE: 1131 { 1132 int new_mode = *(int*)data; 1133 1134 if (new_mode != sc->sc_mode) { 1135 sc->sc_mode = new_mode; 1136 if (IS_IN_EMUL_MODE(sc)) { 1137 cg6_reset(sc); 1138 cg6_ras_init(sc); 1139 cg6_setup_palette(sc); 1140 glyphcache_wipe(&sc->sc_gc); 1141 vcons_redraw_screen(ms); 1142 } 1143 } 1144 } 1145 return 0; 1146 case WSDISPLAYIO_GET_FBINFO: 1147 { 1148 struct wsdisplayio_fbinfo *fbi = data; 1149 1150 return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 1151 } 1152 } 1153 return EPASSTHROUGH; 1154 } 1155 1156 paddr_t 1157 cgsix_mmap(void *v, void *vs, off_t offset, int prot) 1158 { 1159 struct vcons_data *vd = v; 1160 struct cgsix_softc *sc = vd->cookie; 1161 1162 if (offset < sc->sc_ramsize) { 1163 return bus_space_mmap(sc->sc_bustag, sc->sc_paddr, 1164 CGSIX_RAM_OFFSET + offset, prot, BUS_SPACE_MAP_LINEAR); 1165 } 1166 return -1; 1167 } 1168 1169 int 1170 cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1171 { 1172 u_int index = cm->index; 1173 u_int count = cm->count; 1174 int error, i; 1175 1176 if (index >= 256 || count > 256 || index + count > 256) 1177 return EINVAL; 1178 1179 for (i = 0; i < count; i++) 1180 { 1181 error = copyin(&cm->red[i], 1182 &sc->sc_cmap.cm_map[index + i][0], 1); 1183 if (error) 1184 return error; 1185 error = copyin(&cm->green[i], 1186 &sc->sc_cmap.cm_map[index + i][1], 1187 1); 1188 if (error) 1189 return error; 1190 error = copyin(&cm->blue[i], 1191 &sc->sc_cmap.cm_map[index + i][2], 1); 1192 if (error) 1193 return error; 1194 } 1195 cg6_loadcmap(sc, index, count); 1196 1197 return 0; 1198 } 1199 1200 int 1201 cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1202 { 1203 u_int index = cm->index; 1204 u_int count = cm->count; 1205 int error,i; 1206 1207 if (index >= 256 || count > 256 || index + count > 256) 1208 return EINVAL; 1209 1210 for (i = 0; i < count; i++) 1211 { 1212 error = copyout(&sc->sc_cmap.cm_map[index + i][0], 1213 &cm->red[i], 1); 1214 if (error) 1215 return error; 1216 error = copyout(&sc->sc_cmap.cm_map[index + i][1], 1217 &cm->green[i], 1); 1218 if (error) 1219 return error; 1220 error = copyout(&sc->sc_cmap.cm_map[index + i][2], 1221 &cm->blue[i], 1); 1222 if (error) 1223 return error; 1224 } 1225 1226 return 0; 1227 } 1228 1229 void 1230 cgsix_init_screen(void *cookie, struct vcons_screen *scr, 1231 int existing, long *defattr) 1232 { 1233 struct cgsix_softc *sc = cookie; 1234 struct rasops_info *ri = &scr->scr_ri; 1235 int av; 1236 1237 ri->ri_depth = 8; 1238 ri->ri_width = sc->sc_width; 1239 ri->ri_height = sc->sc_height; 1240 ri->ri_stride = sc->sc_stride; 1241 av = sc->sc_ramsize - (sc->sc_height * sc->sc_stride); 1242 ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB; 1243 if (av > (128 * 1024)) { 1244 ri->ri_flg |= RI_ENABLE_ALPHA; 1245 } 1246 ri->ri_bits = sc->sc_fb.fb_pixels; 1247 1248 rasops_init(ri, 0, 0); 1249 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 1250 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 1251 sc->sc_width / ri->ri_font->fontwidth); 1252 1253 /* enable acceleration */ 1254 ri->ri_hw = scr; 1255 ri->ri_ops.copyrows = cg6_ras_copyrows; 1256 ri->ri_ops.copycols = cg6_ras_copycols; 1257 ri->ri_ops.eraserows = cg6_ras_eraserows; 1258 ri->ri_ops.erasecols = cg6_ras_erasecols; 1259 ri->ri_ops.cursor = cgsix_cursor; 1260 if (FONT_IS_ALPHA(ri->ri_font)) { 1261 ri->ri_ops.putchar = cgsix_putchar_aa; 1262 } else 1263 ri->ri_ops.putchar = cgsix_putchar; 1264 } 1265 1266 void 1267 cgsix_rectfill(struct cgsix_softc *sc, int xs, int ys, int wi, int he, 1268 uint32_t col) 1269 { 1270 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1271 1272 CG6_WAIT_READY(fbc); 1273 1274 fbc->fbc_alu = CG6_ALU_FILL; 1275 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1276 1277 fbc->fbc_fg = col; 1278 fbc->fbc_arecty = ys; 1279 fbc->fbc_arectx = xs; 1280 fbc->fbc_arecty = ys + he - 1; 1281 fbc->fbc_arectx = xs + wi - 1; 1282 CG6_DRAW(fbc); 1283 } 1284 1285 void 1286 cgsix_bitblt(void *cookie, int xs, int ys, int xd, int yd, 1287 int wi, int he, int rop) 1288 { 1289 struct cgsix_softc *sc = cookie; 1290 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1291 CG6_WAIT_READY(fbc); 1292 1293 fbc->fbc_alu = rop; 1294 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1295 1296 fbc->fbc_x0 = xs; 1297 fbc->fbc_y0 = ys; 1298 fbc->fbc_x1 = xs + wi - 1; 1299 fbc->fbc_y1 = ys + he - 1; 1300 fbc->fbc_x2 = xd; 1301 fbc->fbc_y2 = yd; 1302 fbc->fbc_x3 = xd + wi - 1; 1303 fbc->fbc_y3 = yd + he - 1; 1304 CG6_BLIT(fbc); 1305 } 1306 1307 void 1308 cgsix_setup_mono(struct cgsix_softc *sc, int x, int y, int wi, int he, 1309 uint32_t fg, uint32_t bg) 1310 { 1311 volatile struct cg6_fbc *fbc=sc->sc_fbc; 1312 1313 CG6_WAIT_READY(fbc); 1314 1315 fbc->fbc_x0 = x; 1316 fbc->fbc_x1 = x + wi - 1; 1317 fbc->fbc_y0 = y; 1318 fbc->fbc_incx = 0; 1319 fbc->fbc_incy = 1; 1320 fbc->fbc_fg = fg; 1321 fbc->fbc_bg = bg; 1322 fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR1; 1323 fbc->fbc_alu = GX_PATTERN_ONES | ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET); 1324 sc->sc_mono_width = wi; 1325 /* now feed the data into the chip */ 1326 } 1327 1328 void 1329 cgsix_feed_line(struct cgsix_softc *sc, int count, uint8_t *data) 1330 { 1331 int i; 1332 uint32_t latch, res = 0, shift; 1333 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1334 1335 if (sc->sc_mono_width > 32) { 1336 /* ARGH! */ 1337 } else 1338 { 1339 shift = 24; 1340 for (i = 0; i < count; i++) { 1341 latch = data[i]; 1342 res |= latch << shift; 1343 shift -= 8; 1344 } 1345 fbc->fbc_font = res; 1346 } 1347 } 1348 1349 void 1350 cgsix_putchar(void *cookie, int row, int col, u_int c, long attr) 1351 { 1352 struct rasops_info *ri = cookie; 1353 struct wsdisplay_font *font = PICK_FONT(ri, c); 1354 struct vcons_screen *scr = ri->ri_hw; 1355 struct cgsix_softc *sc = scr->scr_cookie; 1356 int inv; 1357 1358 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) && 1359 (col < ri->ri_cols)) { 1360 1361 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1362 1363 int fg, bg, uc, i; 1364 uint8_t *data; 1365 int x, y, wi, he; 1366 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1367 1368 wi = font->fontwidth; 1369 he = font->fontheight; 1370 1371 if (!CHAR_IN_FONT(c, font)) 1372 return; 1373 inv = ((attr >> 8) & WSATTR_REVERSE); 1374 if (inv) { 1375 fg = (u_char)ri->ri_devcmap[(attr >> 16) & 1376 0xff]; 1377 bg = (u_char)ri->ri_devcmap[(attr >> 24) & 1378 0xff]; 1379 } else { 1380 bg = (u_char)ri->ri_devcmap[(attr >> 16) & 1381 0xff]; 1382 fg = (u_char)ri->ri_devcmap[(attr >> 24) & 1383 0xff]; 1384 } 1385 1386 x = ri->ri_xorigin + col * wi; 1387 y = ri->ri_yorigin + row * he; 1388 1389 if (c == 0x20) { 1390 cgsix_rectfill(sc, x, y, wi, he, bg); 1391 } else { 1392 uc = c - font->firstchar; 1393 data = (uint8_t *)font->data + uc * 1394 ri->ri_fontscale; 1395 1396 cgsix_setup_mono(sc, x, y, wi, 1, fg, bg); 1397 for (i = 0; i < he; i++) { 1398 cgsix_feed_line(sc, font->stride, 1399 data); 1400 data += font->stride; 1401 } 1402 /* put the chip back to normal */ 1403 fbc->fbc_incy = 0; 1404 } 1405 } 1406 } 1407 } 1408 1409 void 1410 cgsix_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1411 { 1412 struct rasops_info *ri = cookie; 1413 struct wsdisplay_font *font = PICK_FONT(ri, c); 1414 struct vcons_screen *scr = ri->ri_hw; 1415 struct cgsix_softc *sc = scr->scr_cookie; 1416 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1417 1418 uint32_t bg, latch = 0, bg8, fg8, pixel; 1419 int i, j, shift, x, y, wi, he, r, g, b, aval; 1420 int r1, g1, b1, r0, g0, b0, fgo, bgo; 1421 uint8_t *data8; 1422 int rv; 1423 1424 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1425 return; 1426 1427 if (!CHAR_IN_FONT(c, font)) 1428 return; 1429 1430 wi = font->fontwidth; 1431 he = font->fontheight; 1432 1433 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1434 x = ri->ri_xorigin + col * wi; 1435 y = ri->ri_yorigin + row * he; 1436 if (c == 0x20) { 1437 cgsix_rectfill(sc, x, y, wi, he, bg); 1438 return; 1439 } 1440 1441 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1442 if (rv == GC_OK) 1443 return; 1444 1445 data8 = WSFONT_GLYPH(c, font); 1446 1447 CG6_WAIT_READY(sc->sc_fbc); 1448 fbc->fbc_incx = 4; 1449 fbc->fbc_incy = 0; 1450 fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR8; 1451 fbc->fbc_alu = CG6_ALU_COPY; 1452 fbc->fbc_clipmaxx = x + wi - 1; 1453 1454 /* 1455 * we need the RGB colours here, so get offsets into rasops_cmap 1456 */ 1457 fgo = ((attr >> 24) & 0xf) * 3; 1458 bgo = ((attr >> 16) & 0xf) * 3; 1459 1460 r0 = rasops_cmap[bgo]; 1461 r1 = rasops_cmap[fgo]; 1462 g0 = rasops_cmap[bgo + 1]; 1463 g1 = rasops_cmap[fgo + 1]; 1464 b0 = rasops_cmap[bgo + 2]; 1465 b1 = rasops_cmap[fgo + 2]; 1466 #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 1467 bg8 = R3G3B2(r0, g0, b0); 1468 fg8 = R3G3B2(r1, g1, b1); 1469 1470 for (i = 0; i < he; i++) { 1471 1472 CG6_WAIT_READY(fbc); 1473 fbc->fbc_x0 = x; 1474 fbc->fbc_x1 = x + 3; 1475 fbc->fbc_y0 = y + i; 1476 1477 shift = 24; 1478 for (j = 0; j < wi; j++) { 1479 aval = *data8; 1480 if (aval == 0) { 1481 pixel = bg8; 1482 } else if (aval == 255) { 1483 pixel = fg8; 1484 } else { 1485 r = aval * r1 + (255 - aval) * r0; 1486 g = aval * g1 + (255 - aval) * g0; 1487 b = aval * b1 + (255 - aval) * b0; 1488 pixel = ((r & 0xe000) >> 8) | 1489 ((g & 0xe000) >> 11) | 1490 ((b & 0xc000) >> 14); 1491 } 1492 data8++; 1493 1494 latch |= pixel << shift; 1495 if (shift == 0) { 1496 fbc->fbc_font = latch; 1497 latch = 0; 1498 shift = 24; 1499 } else 1500 shift -= 8; 1501 } 1502 if (shift != 24) 1503 fbc->fbc_font = latch; 1504 } 1505 fbc->fbc_clipmaxx = 0x3fff; 1506 1507 if (rv == GC_ADD) { 1508 glyphcache_add(&sc->sc_gc, c, x, y); 1509 } 1510 } 1511 1512 void 1513 cgsix_cursor(void *cookie, int on, int row, int col) 1514 { 1515 struct rasops_info *ri = cookie; 1516 struct vcons_screen *scr = ri->ri_hw; 1517 struct cgsix_softc *sc = scr->scr_cookie; 1518 int x, y, wi, he; 1519 1520 wi = ri->ri_font->fontwidth; 1521 he = ri->ri_font->fontheight; 1522 1523 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1524 x = ri->ri_ccol * wi + ri->ri_xorigin; 1525 y = ri->ri_crow * he + ri->ri_yorigin; 1526 if (ri->ri_flg & RI_CURSOR) { 1527 cg6_invert(sc, x, y, wi, he); 1528 ri->ri_flg &= ~RI_CURSOR; 1529 } 1530 ri->ri_crow = row; 1531 ri->ri_ccol = col; 1532 if (on) 1533 { 1534 x = ri->ri_ccol * wi + ri->ri_xorigin; 1535 y = ri->ri_crow * he + ri->ri_yorigin; 1536 cg6_invert(sc, x, y, wi, he); 1537 ri->ri_flg |= RI_CURSOR; 1538 } 1539 } else 1540 { 1541 ri->ri_crow = row; 1542 ri->ri_ccol = col; 1543 ri->ri_flg &= ~RI_CURSOR; 1544 } 1545 } 1546 1547 void 1548 cgsix_clearscreen(struct cgsix_softc *sc) 1549 { 1550 struct rasops_info *ri = &cg6_console_screen.scr_ri; 1551 1552 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1553 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1554 1555 CG6_WAIT_READY(fbc); 1556 1557 fbc->fbc_alu = CG6_ALU_FILL; 1558 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1559 1560 fbc->fbc_fg = ri->ri_devcmap[sc->sc_bg]; 1561 fbc->fbc_arectx = 0; 1562 fbc->fbc_arecty = 0; 1563 fbc->fbc_arectx = ri->ri_width - 1; 1564 fbc->fbc_arecty = ri->ri_height - 1; 1565 CG6_DRAW(fbc); 1566 } 1567 } 1568 1569 void 1570 cg6_invert(struct cgsix_softc *sc, int x, int y, int wi, int he) 1571 { 1572 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1573 1574 CG6_WAIT_READY(fbc); 1575 1576 fbc->fbc_alu = CG6_ALU_FLIP; 1577 fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1578 fbc->fbc_arecty = y; 1579 fbc->fbc_arectx = x; 1580 fbc->fbc_arecty = y + he - 1; 1581 fbc->fbc_arectx = x + wi - 1; 1582 CG6_DRAW(fbc); 1583 } 1584 1585