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