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