1 /* $NetBSD: cgsix.c,v 1.44 2009/02/20 22:55:26 martin 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.44 2009/02/20 22:55:26 martin 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 static void cg6_unblank(device_t); 120 static void cg6_blank(struct cgsix_softc *, int); 121 122 extern struct cfdriver cgsix_cd; 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 if(isconsole) { 619 /* we mess with cg6_console_screen only once */ 620 vcons_init_screen(&sc->vd, &cg6_console_screen, 1, 621 &defattr); 622 cg6_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 623 624 cgsix_defaultscreen.textops = &ri->ri_ops; 625 cgsix_defaultscreen.capabilities = ri->ri_caps; 626 cgsix_defaultscreen.nrows = ri->ri_rows; 627 cgsix_defaultscreen.ncols = ri->ri_cols; 628 SCREEN_VISIBLE(&cg6_console_screen); 629 sc->vd.active = &cg6_console_screen; 630 wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr); 631 } else { 632 /* 633 * we're not the console so we just clear the screen and don't 634 * set up any sort of text display 635 */ 636 if (cgsix_defaultscreen.textops == NULL) { 637 /* 638 * ugly, but... 639 * we want the console settings to win, so we only 640 * touch anything when we find an untouched screen 641 * definition. In this case we fill it from fb to 642 * avoid problems in case no cgsix is the console 643 */ 644 ri = &sc->sc_fb.fb_rinfo; 645 cgsix_defaultscreen.textops = &ri->ri_ops; 646 cgsix_defaultscreen.capabilities = ri->ri_caps; 647 cgsix_defaultscreen.nrows = ri->ri_rows; 648 cgsix_defaultscreen.ncols = ri->ri_cols; 649 } 650 } 651 652 cg6_setup_palette(sc); 653 cgsix_clearscreen(sc); 654 655 aa.scrdata = &cgsix_screenlist; 656 aa.console = isconsole; 657 aa.accessops = &cgsix_accessops; 658 aa.accesscookie = &sc->vd; 659 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); 660 #else 661 bt_initcmap(&sc->sc_cmap, 256); 662 cg6_loadcmap(sc, 0, 256); 663 664 #endif 665 } 666 667 668 int 669 cgsixopen(dev_t dev, int flags, int mode, struct lwp *l) 670 { 671 int unit = minor(dev); 672 673 if (device_lookup(&cgsix_cd, unit) == NULL) 674 return ENXIO; 675 return 0; 676 } 677 678 int 679 cgsixclose(dev_t dev, int flags, int mode, struct lwp *l) 680 { 681 device_t dv = device_lookup(&cgsix_cd, minor(dev)); 682 struct cgsix_softc *sc = device_private(dv); 683 684 cg6_reset(sc); 685 686 #if NWSDISPLAY > 0 687 cg6_setup_palette(sc); 688 #else 689 /* (re-)initialize the default color map */ 690 bt_initcmap(&sc->sc_cmap, 256); 691 692 cg6_loadcmap(sc, 0, 256); 693 #endif 694 return 0; 695 } 696 697 int 698 cgsixioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 699 { 700 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 701 union cursor_cmap tcm; 702 uint32_t image[32], mask[32]; 703 u_int count; 704 int v, error; 705 706 #ifdef CGSIX_DEBUG 707 printf("cgsixioctl(%ld)\n",cmd); 708 #endif 709 710 switch (cmd) { 711 712 case FBIOGTYPE: 713 *(struct fbtype *)data = sc->sc_fb.fb_type; 714 break; 715 716 case FBIOGATTR: 717 #define fba ((struct fbgattr *)data) 718 fba->real_type = sc->sc_fb.fb_type.fb_type; 719 fba->owner = 0; /* XXX ??? */ 720 fba->fbtype = sc->sc_fb.fb_type; 721 fba->sattr.flags = 0; 722 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 723 fba->sattr.dev_specific[0] = -1; 724 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 725 fba->emu_types[1] = -1; 726 #undef fba 727 break; 728 729 case FBIOGETCMAP: 730 #define p ((struct fbcmap *)data) 731 return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); 732 733 case FBIOPUTCMAP: 734 /* copy to software map */ 735 error = bt_putcmap(p, &sc->sc_cmap, 256, 1); 736 if (error) 737 return error; 738 /* now blast them into the chip */ 739 /* XXX should use retrace interrupt */ 740 cg6_loadcmap(sc, p->index, p->count); 741 #undef p 742 break; 743 744 case FBIOGVIDEO: 745 *(int *)data = sc->sc_blanked; 746 break; 747 748 case FBIOSVIDEO: 749 cg6_blank(sc, !(*(int *)data)); 750 break; 751 752 /* these are for both FBIOSCURSOR and FBIOGCURSOR */ 753 #define p ((struct fbcursor *)data) 754 #define cc (&sc->sc_cursor) 755 756 case FBIOGCURSOR: 757 /* do not quite want everything here... */ 758 p->set = FB_CUR_SETALL; /* close enough, anyway */ 759 p->enable = cc->cc_enable; 760 p->pos = cc->cc_pos; 761 p->hot = cc->cc_hot; 762 p->size = cc->cc_size; 763 764 /* begin ugh ... can we lose some of this crap?? */ 765 if (p->image != NULL) { 766 count = cc->cc_size.y * 32 / NBBY; 767 error = copyout(cc->cc_bits[1], p->image, count); 768 if (error) 769 return error; 770 error = copyout(cc->cc_bits[0], p->mask, count); 771 if (error) 772 return error; 773 } 774 if (p->cmap.red != NULL) { 775 error = bt_getcmap(&p->cmap, 776 (union bt_cmap *)&cc->cc_color, 2, 1); 777 if (error) 778 return error; 779 } else { 780 p->cmap.index = 0; 781 p->cmap.count = 2; 782 } 783 /* end ugh */ 784 break; 785 786 case FBIOSCURSOR: 787 /* 788 * For setcmap and setshape, verify parameters, so that 789 * we do not get halfway through an update and then crap 790 * out with the software state screwed up. 791 */ 792 v = p->set; 793 if (v & FB_CUR_SETCMAP) { 794 /* 795 * This use of a temporary copy of the cursor 796 * colormap is not terribly efficient, but these 797 * copies are small (8 bytes)... 798 */ 799 tcm = cc->cc_color; 800 error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2, 801 1); 802 if (error) 803 return error; 804 } 805 if (v & FB_CUR_SETSHAPE) { 806 if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32) 807 return EINVAL; 808 count = p->size.y * 32 / NBBY; 809 error = copyin(p->image, image, count); 810 if (error) 811 return error; 812 error = copyin(p->mask, mask, count); 813 if (error) 814 return error; 815 } 816 817 /* parameters are OK; do it */ 818 if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { 819 if (v & FB_CUR_SETCUR) 820 cc->cc_enable = p->enable; 821 if (v & FB_CUR_SETPOS) 822 cc->cc_pos = p->pos; 823 if (v & FB_CUR_SETHOT) 824 cc->cc_hot = p->hot; 825 cg6_setcursor(sc); 826 } 827 if (v & FB_CUR_SETCMAP) { 828 cc->cc_color = tcm; 829 cg6_loadomap(sc); /* XXX defer to vertical retrace */ 830 } 831 if (v & FB_CUR_SETSHAPE) { 832 cc->cc_size = p->size; 833 count = p->size.y * 32 / NBBY; 834 memset(cc->cc_bits, 0, sizeof cc->cc_bits); 835 memcpy(cc->cc_bits[1], image, count); 836 memcpy(cc->cc_bits[0], mask, count); 837 cg6_loadcursor(sc); 838 } 839 break; 840 841 #undef p 842 #undef cc 843 844 case FBIOGCURPOS: 845 *(struct fbcurpos *)data = sc->sc_cursor.cc_pos; 846 break; 847 848 case FBIOSCURPOS: 849 sc->sc_cursor.cc_pos = *(struct fbcurpos *)data; 850 cg6_setcursor(sc); 851 break; 852 853 case FBIOGCURMAX: 854 /* max cursor size is 32x32 */ 855 ((struct fbcurpos *)data)->x = 32; 856 ((struct fbcurpos *)data)->y = 32; 857 break; 858 859 default: 860 #ifdef DEBUG 861 log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd, 862 l->l_proc->p_comm, l->l_proc->p_pid); 863 #endif 864 return ENOTTY; 865 } 866 return 0; 867 } 868 869 /* 870 * Clean up hardware state (e.g., after bootup or after X crashes). 871 */ 872 static void 873 cg6_reset(struct cgsix_softc *sc) 874 { 875 volatile struct cg6_tec_xxx *tec; 876 int fhc; 877 volatile struct bt_regs *bt; 878 879 /* hide the cursor, just in case */ 880 sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF; 881 882 /* turn off frobs in transform engine (makes X11 work) */ 883 tec = sc->sc_tec; 884 tec->tec_mv = 0; 885 tec->tec_clip = 0; 886 tec->tec_vdc = 0; 887 888 /* take care of hardware bugs in old revisions */ 889 if (sc->sc_fhcrev < 5) { 890 /* 891 * Keep current resolution; set CPU to 68020, set test 892 * window (size 1Kx1K), and for rev 1, disable dest cache. 893 */ 894 fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 | 895 FHC_TEST | 896 (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT); 897 if (sc->sc_fhcrev < 2) 898 fhc |= FHC_DST_DISABLE; 899 *sc->sc_fhc = fhc; 900 } 901 902 /* Enable cursor in Brooktree DAC. */ 903 bt = sc->sc_bt; 904 bt->bt_addr = 0x06 << 24; 905 bt->bt_ctrl |= 0x03 << 24; 906 } 907 908 static void 909 cg6_setcursor(struct cgsix_softc *sc) 910 { 911 912 /* we need to subtract the hot-spot value here */ 913 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f) 914 sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ? 915 ((COORD(x) << 16) | (COORD(y) & 0xffff)) : 916 (THC_CURSOFF << 16) | THC_CURSOFF; 917 #undef COORD 918 } 919 920 static void 921 cg6_loadcursor(struct cgsix_softc *sc) 922 { 923 volatile struct cg6_thc *thc; 924 u_int edgemask, m; 925 int i; 926 927 /* 928 * Keep the top size.x bits. Here we *throw out* the top 929 * size.x bits from an all-one-bits word, introducing zeros in 930 * the top size.x bits, then invert all the bits to get what 931 * we really wanted as our mask. But this fails if size.x is 932 * 32---a sparc uses only the low 5 bits of the shift count--- 933 * so we have to special case that. 934 */ 935 edgemask = ~0; 936 if (sc->sc_cursor.cc_size.x < 32) 937 edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x); 938 thc = sc->sc_thc; 939 for (i = 0; i < 32; i++) { 940 m = sc->sc_cursor.cc_bits[0][i] & edgemask; 941 thc->thc_cursmask[i] = m; 942 thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i]; 943 } 944 } 945 946 /* 947 * Load a subset of the current (new) colormap into the color DAC. 948 */ 949 static void 950 cg6_loadcmap(struct cgsix_softc *sc, int start, int ncolors) 951 { 952 volatile struct bt_regs *bt; 953 u_int *ip, i; 954 int count; 955 956 ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ 957 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; 958 bt = sc->sc_bt; 959 bt->bt_addr = BT_D4M4(start) << 24; 960 while (--count >= 0) { 961 i = *ip++; 962 /* hardware that makes one want to pound boards with hammers */ 963 bt->bt_cmap = i; 964 bt->bt_cmap = i << 8; 965 bt->bt_cmap = i << 16; 966 bt->bt_cmap = i << 24; 967 } 968 } 969 970 /* 971 * Load the cursor (overlay `foreground' and `background') colors. 972 */ 973 static void 974 cg6_loadomap(struct cgsix_softc *sc) 975 { 976 volatile struct bt_regs *bt; 977 u_int i; 978 979 bt = sc->sc_bt; 980 bt->bt_addr = 0x01 << 24; /* set background color */ 981 i = sc->sc_cursor.cc_color.cm_chip[0]; 982 bt->bt_omap = i; /* R */ 983 bt->bt_omap = i << 8; /* G */ 984 bt->bt_omap = i << 16; /* B */ 985 986 bt->bt_addr = 0x03 << 24; /* set foreground color */ 987 bt->bt_omap = i << 24; /* R */ 988 i = sc->sc_cursor.cc_color.cm_chip[1]; 989 bt->bt_omap = i; /* G */ 990 bt->bt_omap = i << 8; /* B */ 991 } 992 993 /* blank or unblank the screen */ 994 static void 995 cg6_blank(struct cgsix_softc *sc, int flag) 996 { 997 998 if (sc->sc_blanked != flag) { 999 sc->sc_blanked = flag; 1000 if (flag) { 1001 sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN; 1002 } else { 1003 sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 1004 } 1005 } 1006 } 1007 1008 /* 1009 * this is called on panic or ddb entry - force the console to the front, reset 1010 * the colour map and enable drawing so we actually see the message even when X 1011 * is running 1012 */ 1013 static void 1014 cg6_unblank(device_t dev) 1015 { 1016 struct cgsix_softc *sc = device_private(dev); 1017 1018 cg6_blank(sc, 0); 1019 } 1020 1021 /* XXX the following should be moved to a "user interface" header */ 1022 /* 1023 * Base addresses at which users can mmap() the various pieces of a cg6. 1024 * Note that although the Brooktree color registers do not occupy 8K, 1025 * the X server dies if we do not allow it to map 8K there (it just maps 1026 * from 0x70000000 forwards, as a contiguous chunk). 1027 */ 1028 #define CG6_USER_FBC 0x70000000 1029 #define CG6_USER_TEC 0x70001000 1030 #define CG6_USER_BTREGS 0x70002000 1031 #define CG6_USER_FHC 0x70004000 1032 #define CG6_USER_THC 0x70005000 1033 #define CG6_USER_ROM 0x70006000 1034 #define CG6_USER_RAM 0x70016000 1035 #define CG6_USER_DHC 0x80000000 1036 1037 struct mmo { 1038 u_long mo_uaddr; /* user (virtual) address */ 1039 u_long mo_size; /* size, or 0 for video ram size */ 1040 u_long mo_physoff; /* offset from sc_physadr */ 1041 }; 1042 1043 /* 1044 * Return the address that would map the given device at the given 1045 * offset, allowing for the given protection, or return -1 for error. 1046 * 1047 * XXX needs testing against `demanding' applications (e.g., aviator) 1048 */ 1049 paddr_t 1050 cgsixmmap(dev_t dev, off_t off, int prot) 1051 { 1052 struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 1053 struct mmo *mo; 1054 u_int u, sz; 1055 static struct mmo mmo[] = { 1056 { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET }, 1057 1058 /* do not actually know how big most of these are! */ 1059 { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET }, 1060 { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET }, 1061 { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET }, 1062 { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET }, 1063 { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET }, 1064 { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET }, 1065 { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET }, 1066 }; 1067 #define NMMO (sizeof mmo / sizeof *mmo) 1068 1069 if (off & PGOFSET) 1070 panic("cgsixmmap"); 1071 1072 /* 1073 * Entries with size 0 map video RAM (i.e., the size in fb data). 1074 * 1075 * Since we work in pages, the fact that the map offset table's 1076 * sizes are sometimes bizarre (e.g., 1) is effectively ignored: 1077 * one byte is as good as one page. 1078 */ 1079 for (mo = mmo; mo < &mmo[NMMO]; mo++) { 1080 if ((u_long)off < mo->mo_uaddr) 1081 continue; 1082 u = off - mo->mo_uaddr; 1083 sz = mo->mo_size ? mo->mo_size : 1084 sc->sc_ramsize/*sc_fb.fb_type.fb_size*/; 1085 if (u < sz) { 1086 return (bus_space_mmap(sc->sc_bustag, 1087 sc->sc_paddr, u+mo->mo_physoff, 1088 prot, BUS_SPACE_MAP_LINEAR)); 1089 } 1090 } 1091 1092 #ifdef DEBUG 1093 { 1094 struct proc *p = curlwp->l_proc; /* XXX */ 1095 log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n", 1096 (long long)off, p->p_comm, p->p_pid); 1097 } 1098 #endif 1099 return -1; /* not a user-map offset */ 1100 } 1101 1102 #if NWSDISPLAY > 0 1103 1104 static void 1105 cg6_setup_palette(struct cgsix_softc *sc) 1106 { 1107 int i, j; 1108 1109 j = 0; 1110 for (i = 0; i < 256; i++) { 1111 sc->sc_cmap.cm_map[i][0] = sc->sc_default_cmap[j]; 1112 j++; 1113 sc->sc_cmap.cm_map[i][1] = sc->sc_default_cmap[j]; 1114 j++; 1115 sc->sc_cmap.cm_map[i][2] = sc->sc_default_cmap[j]; 1116 j++; 1117 } 1118 cg6_loadcmap(sc, 0, 256); 1119 } 1120 1121 int 1122 cgsix_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 1123 struct lwp *l) 1124 { 1125 /* we'll probably need to add more stuff here */ 1126 struct vcons_data *vd = v; 1127 struct cgsix_softc *sc = vd->cookie; 1128 struct wsdisplay_fbinfo *wdf; 1129 struct rasops_info *ri = &sc->sc_fb.fb_rinfo; 1130 struct vcons_screen *ms = sc->vd.active; 1131 #ifdef CGSIX_DEBUG 1132 printf("cgsix_ioctl(%ld)\n",cmd); 1133 #endif 1134 switch (cmd) { 1135 case WSDISPLAYIO_GTYPE: 1136 *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; 1137 return 0; 1138 case WSDISPLAYIO_GINFO: 1139 wdf = (void *)data; 1140 wdf->height = ri->ri_height; 1141 wdf->width = ri->ri_width; 1142 wdf->depth = ri->ri_depth; 1143 wdf->cmsize = 256; 1144 return 0; 1145 1146 case WSDISPLAYIO_GETCMAP: 1147 return cgsix_getcmap(sc, 1148 (struct wsdisplay_cmap *)data); 1149 case WSDISPLAYIO_PUTCMAP: 1150 return cgsix_putcmap(sc, 1151 (struct wsdisplay_cmap *)data); 1152 1153 case WSDISPLAYIO_SMODE: 1154 { 1155 int new_mode = *(int*)data; 1156 if (new_mode != sc->sc_mode) 1157 { 1158 sc->sc_mode = new_mode; 1159 if(new_mode == WSDISPLAYIO_MODE_EMUL) 1160 { 1161 cg6_reset(sc); 1162 cg6_ras_init(sc); 1163 cg6_setup_palette(sc); 1164 vcons_redraw_screen(ms); 1165 } 1166 } 1167 } 1168 } 1169 return EPASSTHROUGH; 1170 } 1171 1172 paddr_t 1173 cgsix_mmap(void *v, void *vs, off_t offset, int prot) 1174 { 1175 struct vcons_data *vd = v; 1176 struct cgsix_softc *sc = vd->cookie; 1177 1178 if(offset<sc->sc_ramsize) { 1179 return bus_space_mmap(sc->sc_bustag, sc->sc_paddr, 1180 CGSIX_RAM_OFFSET+offset, prot, BUS_SPACE_MAP_LINEAR); 1181 } 1182 /* I'm not at all sure this is the right thing to do */ 1183 return cgsixmmap(0, offset, prot); /* assume minor dev 0 for now */ 1184 } 1185 1186 int 1187 cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1188 { 1189 u_int index = cm->index; 1190 u_int count = cm->count; 1191 int error,i; 1192 if (index >= 256 || count > 256 || index + count > 256) 1193 return EINVAL; 1194 1195 for (i = 0; i < count; i++) 1196 { 1197 error = copyin(&cm->red[i], 1198 &sc->sc_cmap.cm_map[index + i][0], 1); 1199 if (error) 1200 return error; 1201 error = copyin(&cm->green[i], 1202 &sc->sc_cmap.cm_map[index + i][1], 1203 1); 1204 if (error) 1205 return error; 1206 error = copyin(&cm->blue[i], 1207 &sc->sc_cmap.cm_map[index + i][2], 1); 1208 if (error) 1209 return error; 1210 } 1211 cg6_loadcmap(sc, index, count); 1212 1213 return 0; 1214 } 1215 1216 int 1217 cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1218 { 1219 u_int index = cm->index; 1220 u_int count = cm->count; 1221 int error,i; 1222 1223 if (index >= 256 || count > 256 || index + count > 256) 1224 return EINVAL; 1225 1226 for (i = 0; i < count; i++) 1227 { 1228 error = copyout(&sc->sc_cmap.cm_map[index + i][0], 1229 &cm->red[i], 1); 1230 if (error) 1231 return error; 1232 error = copyout(&sc->sc_cmap.cm_map[index + i][1], 1233 &cm->green[i], 1); 1234 if (error) 1235 return error; 1236 error = copyout(&sc->sc_cmap.cm_map[index + i][2], 1237 &cm->blue[i], 1); 1238 if (error) 1239 return error; 1240 } 1241 1242 return 0; 1243 } 1244 1245 void 1246 cgsix_init_screen(void *cookie, struct vcons_screen *scr, 1247 int existing, long *defattr) 1248 { 1249 struct cgsix_softc *sc = cookie; 1250 struct rasops_info *ri = &scr->scr_ri; 1251 1252 ri->ri_depth = 8; 1253 ri->ri_width = sc->sc_width; 1254 ri->ri_height = sc->sc_height; 1255 ri->ri_stride = sc->sc_stride; 1256 ri->ri_flg = RI_CENTER; 1257 1258 ri->ri_bits = sc->sc_fb.fb_pixels; 1259 1260 /* We need unaccelerated initial screen clear on old revisions */ 1261 if (sc->sc_fhcrev < 2) 1262 memset(sc->sc_fb.fb_pixels, (*defattr >> 16) & 0xff, 1263 sc->sc_stride * sc->sc_height); 1264 rasops_init(ri, sc->sc_height/8, sc->sc_width/8); 1265 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 1266 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 1267 sc->sc_width / ri->ri_font->fontwidth); 1268 1269 /* enable acceleration */ 1270 ri->ri_hw = scr; 1271 ri->ri_ops.copyrows = cg6_ras_copyrows; 1272 ri->ri_ops.copycols = cg6_ras_copycols; 1273 ri->ri_ops.eraserows = cg6_ras_eraserows; 1274 ri->ri_ops.erasecols = cg6_ras_erasecols; 1275 ri->ri_ops.cursor = cgsix_cursor; 1276 ri->ri_ops.putchar = cgsix_putchar; 1277 } 1278 1279 void 1280 cgsix_rectfill(struct cgsix_softc *sc, int xs, int ys, int wi, int he, 1281 uint32_t col) 1282 { 1283 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1284 1285 CG6_DRAIN(fbc); 1286 fbc->fbc_clip = 0; 1287 fbc->fbc_s = 0; 1288 fbc->fbc_offx = 0; 1289 fbc->fbc_offy = 0; 1290 fbc->fbc_clipminx = 0; 1291 fbc->fbc_clipminy = 0; 1292 fbc->fbc_clipmaxx = sc->sc_width - 1; 1293 fbc->fbc_clipmaxy = sc->sc_height - 1; 1294 fbc->fbc_alu = CG6_ALU_FILL; 1295 fbc->fbc_fg = col; 1296 fbc->fbc_arecty = ys; 1297 fbc->fbc_arectx = xs; 1298 fbc->fbc_arecty = ys + he - 1; 1299 fbc->fbc_arectx = xs + wi - 1; 1300 CG6_DRAW_WAIT(fbc); 1301 } 1302 1303 void 1304 cgsix_setup_mono(struct cgsix_softc *sc, int x, int y, int wi, int he, 1305 uint32_t fg, uint32_t bg) 1306 { 1307 volatile struct cg6_fbc *fbc=sc->sc_fbc; 1308 CG6_DRAIN(fbc); 1309 fbc->fbc_x0 = x; 1310 fbc->fbc_x1 =x + wi - 1; 1311 fbc->fbc_y0 = y; 1312 fbc->fbc_incx = 0; 1313 fbc->fbc_incy = 1; 1314 fbc->fbc_fg = fg; 1315 fbc->fbc_bg = bg; 1316 fbc->fbc_mode = 0x00140000; /* nosrc, color1 */ 1317 fbc->fbc_alu = 0x0800fc30; /* colour expansion, solid bg */ 1318 sc->sc_mono_width = wi; 1319 /* now feed the data into the chip */ 1320 } 1321 1322 void 1323 cgsix_feed_line(struct cgsix_softc *sc, int count, uint8_t *data) 1324 { 1325 int i; 1326 uint32_t latch, res = 0, shift; 1327 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1328 1329 if (sc->sc_mono_width > 32) { 1330 /* ARGH! */ 1331 } else 1332 { 1333 shift = 24; 1334 for (i = 0; i < count; i++) { 1335 latch = data[i]; 1336 res |= latch << shift; 1337 shift -= 8; 1338 } 1339 fbc->fbc_font = res; 1340 } 1341 } 1342 1343 void 1344 cgsix_putchar(void *cookie, int row, int col, u_int c, long attr) 1345 { 1346 struct rasops_info *ri = cookie; 1347 struct vcons_screen *scr = ri->ri_hw; 1348 struct cgsix_softc *sc = scr->scr_cookie; 1349 int inv; 1350 1351 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) && 1352 (col < ri->ri_cols)) { 1353 1354 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1355 1356 int fg, bg, uc, i; 1357 uint8_t *data; 1358 int x, y, wi, he; 1359 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1360 1361 wi = ri->ri_font->fontwidth; 1362 he = ri->ri_font->fontheight; 1363 1364 if (!CHAR_IN_FONT(c, ri->ri_font)) 1365 return; 1366 inv = ((attr >> 8) & WSATTR_REVERSE); 1367 if (inv) { 1368 fg = (u_char)ri->ri_devcmap[(attr >> 16) & 1369 0xff]; 1370 bg = (u_char)ri->ri_devcmap[(attr >> 24) & 1371 0xff]; 1372 } else { 1373 bg = (u_char)ri->ri_devcmap[(attr >> 16) & 1374 0xff]; 1375 fg = (u_char)ri->ri_devcmap[(attr >> 24) & 1376 0xff]; 1377 } 1378 1379 x = ri->ri_xorigin + col * wi; 1380 y = ri->ri_yorigin + row * he; 1381 1382 if (c == 0x20) { 1383 cgsix_rectfill(sc, x, y, wi, he, bg); 1384 } else { 1385 uc = c-ri->ri_font->firstchar; 1386 data = (uint8_t *)ri->ri_font->data + uc * 1387 ri->ri_fontscale; 1388 1389 cgsix_setup_mono(sc, x, y, wi, 1, fg, bg); 1390 for (i = 0; i < he; i++) { 1391 cgsix_feed_line(sc, ri->ri_font->stride, 1392 data); 1393 data += ri->ri_font->stride; 1394 } 1395 /* put the chip back to normal */ 1396 fbc->fbc_incy = 0; 1397 /* nosrc, color8 */ 1398 fbc->fbc_mode = 0x00120000; 1399 /*fbc->fbc_mode &= ~CG6_MODE_MASK; 1400 fbc->fbc_mode |= CG6_MODE;*/ 1401 } 1402 } 1403 } 1404 } 1405 1406 void 1407 cgsix_cursor(void *cookie, int on, int row, int col) 1408 { 1409 struct rasops_info *ri = cookie; 1410 struct vcons_screen *scr = ri->ri_hw; 1411 struct cgsix_softc *sc = scr->scr_cookie; 1412 int x, y, wi, he; 1413 1414 wi = ri->ri_font->fontwidth; 1415 he = ri->ri_font->fontheight; 1416 1417 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1418 x = ri->ri_ccol * wi + ri->ri_xorigin; 1419 y = ri->ri_crow * he + ri->ri_yorigin; 1420 if (ri->ri_flg & RI_CURSOR) { 1421 cg6_invert(sc, x, y, wi, he); 1422 ri->ri_flg &= ~RI_CURSOR; 1423 } 1424 ri->ri_crow = row; 1425 ri->ri_ccol = col; 1426 if (on) 1427 { 1428 x = ri->ri_ccol * wi + ri->ri_xorigin; 1429 y = ri->ri_crow * he + ri->ri_yorigin; 1430 cg6_invert(sc, x, y, wi, he); 1431 ri->ri_flg |= RI_CURSOR; 1432 } 1433 } else 1434 { 1435 ri->ri_crow = row; 1436 ri->ri_ccol = col; 1437 ri->ri_flg &= ~RI_CURSOR; 1438 } 1439 } 1440 1441 void 1442 cgsix_clearscreen(struct cgsix_softc *sc) 1443 { 1444 struct rasops_info *ri = &cg6_console_screen.scr_ri; 1445 1446 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1447 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1448 1449 CG6_DRAIN(fbc); 1450 fbc->fbc_clip = 0; 1451 fbc->fbc_s = 0; 1452 fbc->fbc_offx = 0; 1453 fbc->fbc_offy = 0; 1454 fbc->fbc_clipminx = 0; 1455 fbc->fbc_clipminy = 0; 1456 fbc->fbc_clipmaxx = ri->ri_width - 1; 1457 fbc->fbc_clipmaxy = ri->ri_height - 1; 1458 fbc->fbc_alu = CG6_ALU_FILL; 1459 fbc->fbc_fg = ri->ri_devcmap[sc->sc_bg]; 1460 fbc->fbc_arectx = 0; 1461 fbc->fbc_arecty = 0; 1462 fbc->fbc_arectx = ri->ri_width - 1; 1463 fbc->fbc_arecty = ri->ri_height - 1; 1464 CG6_DRAW_WAIT(fbc); 1465 } 1466 } 1467 1468 #endif /* NWSDISPLAY > 0 */ 1469 1470 #if (NWSDISPLAY > 0) || defined(RASTERCONSOLE) 1471 void 1472 cg6_invert(struct cgsix_softc *sc, int x, int y, int wi, int he) 1473 { 1474 volatile struct cg6_fbc *fbc = sc->sc_fbc; 1475 struct rasops_info *ri = &cg6_console_screen.scr_ri; 1476 1477 CG6_DRAIN(fbc); 1478 fbc->fbc_clip = 0; 1479 fbc->fbc_s = 0; 1480 fbc->fbc_offx = 0; 1481 fbc->fbc_offy = 0; 1482 fbc->fbc_clipminx = 0; 1483 fbc->fbc_clipminy = 0; 1484 fbc->fbc_clipmaxx = ri->ri_width - 1; 1485 fbc->fbc_clipmaxy = ri->ri_height - 1; 1486 fbc->fbc_alu = CG6_ALU_FLIP; 1487 fbc->fbc_arecty = y; 1488 fbc->fbc_arectx = x; 1489 fbc->fbc_arecty = y + he - 1; 1490 fbc->fbc_arectx = x + wi - 1; 1491 CG6_DRAW_WAIT(fbc); 1492 } 1493 1494 #endif 1495 1496