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