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