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