1 /* $NetBSD: sfbplus.c,v 1.14 2002/03/17 19:41:03 atatat Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2000, 2001 Tohru Nishimura. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Tohru Nishimura 17 * for the NetBSD Project. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: sfbplus.c,v 1.14 2002/03/17 19:41:03 atatat Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/device.h> 40 #include <sys/malloc.h> 41 #include <sys/buf.h> 42 #include <sys/ioctl.h> 43 44 #include <machine/bus.h> 45 #include <machine/intr.h> 46 47 #include <dev/wscons/wsconsio.h> 48 #include <dev/wscons/wsdisplayvar.h> 49 50 #include <dev/rasops/rasops.h> 51 #include <dev/wsfont/wsfont.h> 52 53 #include <dev/tc/tcvar.h> 54 #include <dev/ic/bt459reg.h> 55 #include <dev/ic/bt463reg.h> 56 #include <dev/tc/sfbreg.h> 57 #include <dev/pci/tgareg.h> 58 59 #include <uvm/uvm_extern.h> 60 61 #if defined(pmax) 62 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x)) 63 #endif 64 65 #if defined(alpha) 66 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x)) 67 #endif 68 69 /* Bt459/Bt463 hardware registers */ 70 #define bt_lo 0 71 #define bt_hi 1 72 #define bt_reg 2 73 #define bt_cmap 3 74 75 #define REG(base, index) *((u_int32_t *)(base) + (index)) 76 #define SELECT(vdac, regno) do { \ 77 REG(vdac, bt_lo) = ((regno) & 0x00ff); \ 78 REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \ 79 tc_wmb(); \ 80 } while (0) 81 82 struct hwcmap256 { 83 #define CMAP_SIZE 256 /* 256 R/G/B entries */ 84 u_int8_t r[CMAP_SIZE]; 85 u_int8_t g[CMAP_SIZE]; 86 u_int8_t b[CMAP_SIZE]; 87 }; 88 89 struct hwcursor64 { 90 struct wsdisplay_curpos cc_pos; 91 struct wsdisplay_curpos cc_hot; 92 struct wsdisplay_curpos cc_size; 93 struct wsdisplay_curpos cc_magic; 94 #define CURSOR_MAX_SIZE 64 95 u_int8_t cc_color[6]; 96 u_int64_t cc_image[64 + 64]; 97 }; 98 99 struct hwops { 100 void (*setlut) __P((caddr_t, struct hwcmap256 *)); 101 void (*getlut) __P((caddr_t, struct hwcmap256 *)); 102 void (*visible) __P((caddr_t, int)); 103 void (*locate) __P((caddr_t, struct hwcursor64 *)); 104 void (*shape) __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *)); 105 void (*color) __P((caddr_t, u_int8_t *)); 106 }; 107 108 struct sfbp_softc { 109 struct device sc_dev; 110 vaddr_t sc_vaddr; 111 size_t sc_size; 112 struct rasops_info *sc_ri; 113 struct hwcmap256 sc_cmap; /* software copy of colormap */ 114 struct hwcursor64 sc_cursor; /* software copy of cursor */ 115 int sc_blanked; 116 int sc_curenb; /* cursor sprite enabled */ 117 int sc_changed; /* need update of hardware */ 118 #define WSDISPLAY_CMAP_DOLUT 0x20 119 int nscreens; 120 struct hwops sc_hwops; 121 }; 122 123 #define HX_MAGIC_X 368 124 #define HX_MAGIC_Y 38 125 126 static int sfbpmatch __P((struct device *, struct cfdata *, void *)); 127 static void sfbpattach __P((struct device *, struct device *, void *)); 128 129 const struct cfattach sfbp_ca = { 130 sizeof(struct sfbp_softc), sfbpmatch, sfbpattach, 131 }; 132 133 static void sfbp_common_init __P((struct rasops_info *)); 134 static struct rasops_info sfbp_console_ri; 135 static tc_addr_t sfbp_consaddr; 136 137 static struct wsscreen_descr sfbp_stdscreen = { 138 "std", 0, 0, 139 NULL, /* textops */ 140 0, 0, 141 WSSCREEN_REVERSE 142 }; 143 144 static const struct wsscreen_descr *_sfb_scrlist[] = { 145 &sfbp_stdscreen, 146 }; 147 148 static const struct wsscreen_list sfb_screenlist = { 149 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist 150 }; 151 152 static int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *)); 153 static paddr_t sfbmmap __P((void *, off_t, int)); 154 155 static int sfb_alloc_screen __P((void *, const struct wsscreen_descr *, 156 void **, int *, int *, long *)); 157 static void sfb_free_screen __P((void *, void *)); 158 static int sfb_show_screen __P((void *, void *, int, 159 void (*) (void *, int, int), void *)); 160 static void sfbp_putchar __P((void *, int, int, u_int, long)); 161 static void sfbp_erasecols __P((void *, int, int, int, long)); 162 static void sfbp_eraserows __P((void *, int, int, long)); 163 static void sfbp_copyrows __P((void *, int, int, int)); 164 165 static const struct wsdisplay_accessops sfb_accessops = { 166 sfbioctl, 167 sfbmmap, 168 sfb_alloc_screen, 169 sfb_free_screen, 170 sfb_show_screen, 171 0 /* load_font */ 172 }; 173 174 static void bt459init __P((caddr_t)); 175 static void bt459visible __P((caddr_t, int)); 176 static void bt459locate __P((caddr_t, struct hwcursor64 *)); 177 static void bt459shape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *)); 178 static void bt459color __P((caddr_t, u_int8_t *)); 179 static void bt459setlut __P((caddr_t, struct hwcmap256 *)); 180 181 static void sfbpvisible __P((caddr_t, int)); 182 static void sfbplocate __P((caddr_t, struct hwcursor64 *)); 183 static void sfbpshape __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *)); 184 static void bt463init __P((caddr_t)); 185 static void bt463color __P((caddr_t, u_int8_t *)); 186 static void noplut __P((caddr_t, struct hwcmap256 *)); 187 188 /* EXPORT */ int sfbp_cnattach __P((tc_addr_t)); 189 static int sfbpintr __P((void *)); 190 191 static int get_cmap __P((struct sfbp_softc *, struct wsdisplay_cmap *)); 192 static int set_cmap __P((struct sfbp_softc *, struct wsdisplay_cmap *)); 193 static int set_cursor __P((struct sfbp_softc *, struct wsdisplay_cursor *)); 194 static int get_cursor __P((struct sfbp_softc *, struct wsdisplay_cursor *)); 195 static void set_curpos __P((struct sfbp_softc *, struct wsdisplay_curpos *)); 196 197 /* 198 * Compose 2 bit/pixel cursor image. Bit order will be reversed. 199 * M M M M I I I I M I M I M I M I 200 * [ before ] [ after ] 201 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3 202 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7 203 */ 204 static const u_int8_t shuffle[256] = { 205 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 206 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 207 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4, 208 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5, 209 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74, 210 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75, 211 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4, 212 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5, 213 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c, 214 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d, 215 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc, 216 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd, 217 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c, 218 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d, 219 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc, 220 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd, 221 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56, 222 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57, 223 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6, 224 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7, 225 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76, 226 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77, 227 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6, 228 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7, 229 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e, 230 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f, 231 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde, 232 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf, 233 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e, 234 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f, 235 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe, 236 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff, 237 }; 238 239 static int 240 sfbpmatch(parent, match, aux) 241 struct device *parent; 242 struct cfdata *match; 243 void *aux; 244 { 245 struct tc_attach_args *ta = aux; 246 247 if (strncmp("PMAGD ", ta->ta_modname, TC_ROM_LLEN) != 0) 248 return (0); 249 250 return (1); 251 } 252 253 static void 254 sfbpattach(parent, self, aux) 255 struct device *parent, *self; 256 void *aux; 257 { 258 struct sfbp_softc *sc = (struct sfbp_softc *)self; 259 struct tc_attach_args *ta = aux; 260 struct rasops_info *ri; 261 struct wsemuldisplaydev_attach_args waa; 262 caddr_t asic; 263 int console; 264 265 console = (ta->ta_addr == sfbp_consaddr); 266 if (console) { 267 sc->sc_ri = ri = &sfbp_console_ri; 268 sc->nscreens = 1; 269 } 270 else { 271 MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info), 272 M_DEVBUF, M_NOWAIT); 273 if (ri == NULL) { 274 printf(": can't alloc memory\n"); 275 return; 276 } 277 memset(ri, 0, sizeof(struct rasops_info)); 278 279 ri->ri_hw = (void *)ta->ta_addr; 280 sfbp_common_init(ri); 281 sc->sc_ri = ri; 282 } 283 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, 284 (ri->ri_depth != 32) ? 8 : 24); 285 286 sc->sc_vaddr = ta->ta_addr; 287 sc->sc_cursor.cc_magic.x = HX_MAGIC_X; 288 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y; 289 sc->sc_blanked = sc->sc_curenb = 0; 290 291 if (ri->ri_depth == 8) { 292 struct hwcmap256 *cm; 293 const u_int8_t *p; 294 int index; 295 296 sc->sc_hwops.visible = bt459visible; 297 sc->sc_hwops.locate = bt459locate; 298 sc->sc_hwops.shape = bt459shape; 299 sc->sc_hwops.color = bt459color; 300 sc->sc_hwops.setlut = bt459setlut; 301 sc->sc_hwops.getlut = noplut; 302 cm = &sc->sc_cmap; 303 p = rasops_cmap; 304 for (index = 0; index < CMAP_SIZE; index++, p += 3) { 305 cm->r[index] = p[0]; 306 cm->g[index] = p[1]; 307 cm->b[index] = p[2]; 308 } 309 } 310 else { 311 sc->sc_hwops.visible = sfbpvisible; 312 sc->sc_hwops.locate = sfbplocate; 313 sc->sc_hwops.shape = sfbpshape; 314 sc->sc_hwops.color = bt463color; 315 sc->sc_hwops.setlut = noplut; 316 sc->sc_hwops.getlut = noplut; 317 } 318 319 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc); 320 321 asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 322 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 323 *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; 324 325 waa.console = console; 326 waa.scrdata = &sfb_screenlist; 327 waa.accessops = &sfb_accessops; 328 waa.accesscookie = sc; 329 330 config_found(self, &waa, wsemuldisplaydevprint); 331 } 332 333 static void 334 sfbp_common_init(ri) 335 struct rasops_info *ri; 336 { 337 caddr_t base, asic; 338 int i, depth, hsetup, vsetup, vbase, cookie; 339 340 base = (caddr_t)ri->ri_hw; 341 asic = base + SFB_ASIC_OFFSET; 342 hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP); 343 vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP); 344 i = *(u_int32_t *)(asic + SFB_ASIC_DEEP); 345 depth = (i & 01) ? 32 : 8; 346 347 /* 348 * - neglect 0,1 cases of hsetup register. 349 * - observed 804x600?, 644x480? values. 350 */ 351 352 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1; 353 vbase *= (i & 0x20) ? 2048 : 4096; /* VRAM chip size */ 354 if (i & 1) vbase *= 4; /* bytes per pixel */ 355 356 *(u_int32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0; 357 *(u_int32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0; 358 *(u_int32_t *)(asic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */ 359 *(u_int32_t *)(asic + SFB_ASIC_ROP) = 3; /* ROP_COPY */ 360 361 /* initialize colormap and cursor hardware */ 362 if (depth != 32) { 363 *(u_int32_t *)(asic + 0x180000) = 0; /* Bt459 reset */ 364 bt459init(base + SFB_RAMDAC_OFFSET); 365 } 366 else { 367 bt463init(base + SFB_RAMDAC_OFFSET); 368 } 369 370 ri->ri_flg = RI_CENTER; 371 ri->ri_flg = 0; /* XXX 32bpp RI_CENTER fails XXX */ 372 ri->ri_depth = depth; 373 ri->ri_width = (hsetup & 0x1ff) << 2; 374 ri->ri_height = (vsetup & 0x7ff); 375 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8); 376 ri->ri_bits = base + 0x800000 + vbase; 377 378 if (depth == 32) { 379 ri->ri_rnum = 8; 380 ri->ri_gnum = 8; 381 ri->ri_bnum = 8; 382 ri->ri_rpos = 16; 383 ri->ri_gpos = 8; 384 ri->ri_bpos = 0; 385 } 386 387 /* clear the screen */ 388 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 389 390 wsfont_init(); 391 /* prefer 12 pixel wide font */ 392 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L, 393 WSDISPLAY_FONTORDER_L2R); 394 if (cookie <= 0) 395 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, 396 WSDISPLAY_FONTORDER_L2R); 397 if (cookie <= 0) { 398 printf("sfbp: font table is empty\n"); 399 return; 400 } 401 402 /* the accelerated sfbp_putchar() needs LSbit left */ 403 if (wsfont_lock(cookie, &ri->ri_font)) { 404 printf("sfb: couldn't lock font\n"); 405 return; 406 } 407 ri->ri_wsfcookie = cookie; 408 409 rasops_init(ri, 34, 80); 410 411 /* add our accelerated functions */ 412 ri->ri_ops.putchar = sfbp_putchar; 413 ri->ri_ops.erasecols = sfbp_erasecols; 414 ri->ri_ops.copyrows = sfbp_copyrows; 415 ri->ri_ops.eraserows = sfbp_eraserows; 416 417 /* XXX shouldn't be global */ 418 sfbp_stdscreen.nrows = ri->ri_rows; 419 sfbp_stdscreen.ncols = ri->ri_cols; 420 sfbp_stdscreen.textops = &ri->ri_ops; 421 sfbp_stdscreen.capabilities = ri->ri_caps; 422 /* our accelerated putchar can't underline */ 423 sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE; 424 } 425 426 static int 427 sfbioctl(v, cmd, data, flag, p) 428 void *v; 429 u_long cmd; 430 caddr_t data; 431 int flag; 432 struct proc *p; 433 { 434 struct sfbp_softc *sc = v; 435 struct rasops_info *ri = sc->sc_ri; 436 int turnoff; 437 438 switch (cmd) { 439 case WSDISPLAYIO_GTYPE: 440 *(u_int *)data = WSDISPLAY_TYPE_SFBP; 441 return (0); 442 443 case WSDISPLAYIO_GINFO: 444 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 445 wsd_fbip->height = ri->ri_height; 446 wsd_fbip->width = ri->ri_width; 447 wsd_fbip->depth = ri->ri_depth; 448 wsd_fbip->cmsize = CMAP_SIZE; /* XXX */ 449 #undef fbt 450 return (0); 451 452 case WSDISPLAYIO_GETCMAP: 453 return get_cmap(sc, (struct wsdisplay_cmap *)data); 454 455 case WSDISPLAYIO_PUTCMAP: 456 return set_cmap(sc, (struct wsdisplay_cmap *)data); 457 458 case WSDISPLAYIO_SVIDEO: 459 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 460 if ((sc->sc_blanked == 0) ^ turnoff) { 461 sc->sc_blanked = turnoff; 462 #if 0 /* XXX later XXX */ 463 Low order 3bit control visibilities of screen and builtin cursor. 464 #endif /* XXX XXX XXX */ 465 } 466 return (0); 467 468 case WSDISPLAYIO_GVIDEO: 469 *(u_int *)data = sc->sc_blanked ? 470 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 471 return (0); 472 473 case WSDISPLAYIO_GCURPOS: 474 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 475 return (0); 476 477 case WSDISPLAYIO_SCURPOS: 478 set_curpos(sc, (struct wsdisplay_curpos *)data); 479 sc->sc_changed = WSDISPLAY_CURSOR_DOPOS; 480 return (0); 481 482 case WSDISPLAYIO_GCURMAX: 483 ((struct wsdisplay_curpos *)data)->x = 484 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 485 return (0); 486 487 case WSDISPLAYIO_GCURSOR: 488 return get_cursor(sc, (struct wsdisplay_cursor *)data); 489 490 case WSDISPLAYIO_SCURSOR: 491 return set_cursor(sc, (struct wsdisplay_cursor *)data); 492 } 493 return (EPASSTHROUGH); 494 } 495 496 paddr_t 497 sfbmmap(v, offset, prot) 498 void *v; 499 off_t offset; 500 int prot; 501 { 502 struct sfbp_softc *sc = v; 503 504 if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */ 505 return (-1); 506 return machine_btop(sc->sc_vaddr + offset); 507 } 508 509 static int 510 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 511 void *v; 512 const struct wsscreen_descr *type; 513 void **cookiep; 514 int *curxp, *curyp; 515 long *attrp; 516 { 517 struct sfbp_softc *sc = v; 518 struct rasops_info *ri = sc->sc_ri; 519 long defattr; 520 521 if (sc->nscreens > 0) 522 return (ENOMEM); 523 524 *cookiep = ri; /* one and only for now */ 525 *curxp = 0; 526 *curyp = 0; 527 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 528 *attrp = defattr; 529 sc->nscreens++; 530 return (0); 531 } 532 533 void 534 sfb_free_screen(v, cookie) 535 void *v; 536 void *cookie; 537 { 538 struct sfbp_softc *sc = v; 539 540 if (sc->sc_ri == &sfbp_console_ri) 541 panic("sfb_free_screen: console"); 542 543 sc->nscreens--; 544 } 545 546 static int 547 sfb_show_screen(v, cookie, waitok, cb, cbarg) 548 void *v; 549 void *cookie; 550 int waitok; 551 void (*cb) __P((void *, int, int)); 552 void *cbarg; 553 { 554 555 return (0); 556 } 557 558 int 559 sfbp_cnattach(addr) 560 tc_addr_t addr; 561 { 562 struct rasops_info *ri; 563 long defattr; 564 565 ri = &sfbp_console_ri; 566 ri->ri_hw = (void *)addr; 567 sfbp_common_init(ri); 568 (*ri->ri_ops.alloc_attr)(&ri, 0, 0, 0, &defattr); 569 wsdisplay_cnattach(&sfbp_stdscreen, ri, 0, 0, defattr); 570 sfbp_consaddr = addr; 571 return (0); 572 } 573 574 static int 575 sfbpintr(arg) 576 void *arg; 577 { 578 #define cc (&sc->sc_cursor) 579 struct sfbp_softc *sc = arg; 580 caddr_t base, asic; 581 u_int32_t sisr; 582 int v; 583 584 base = (caddr_t)sc->sc_ri->ri_hw; 585 asic = base + SFB_ASIC_OFFSET; 586 sisr = *((u_int32_t *)asic + TGA_REG_SISR); 587 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 588 589 if (sc->sc_changed == 0) 590 goto done; 591 592 v = sc->sc_changed; 593 if (v & WSDISPLAY_CURSOR_DOCUR) 594 (*sc->sc_hwops.visible)(base, sc->sc_curenb); 595 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) 596 (*sc->sc_hwops.locate)(base, cc); 597 if (v & WSDISPLAY_CURSOR_DOCMAP) 598 (*sc->sc_hwops.color)(base, cc->cc_color); 599 if (v & WSDISPLAY_CURSOR_DOSHAPE) 600 (*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image); 601 if (v & WSDISPLAY_CMAP_DOLUT) 602 (*sc->sc_hwops.setlut)(base, &sc->sc_cmap); 603 sc->sc_changed = 0; 604 done: 605 *((u_int32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb(); 606 return (1); 607 #undef cc 608 } 609 610 static void 611 bt459init(vdac) 612 caddr_t vdac; 613 { 614 const u_int8_t *p; 615 int i; 616 617 SELECT(vdac, BT459_IREG_COMMAND_0); 618 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb(); 619 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb(); 620 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb(); 621 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb(); 622 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb(); 623 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb(); 624 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb(); 625 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb(); 626 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb(); 627 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb(); 628 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb(); 629 630 SELECT(vdac, BT459_IREG_CCR); 631 REG(vdac, bt_reg) = 0x0; tc_wmb(); 632 REG(vdac, bt_reg) = 0x0; tc_wmb(); 633 REG(vdac, bt_reg) = 0x0; tc_wmb(); 634 REG(vdac, bt_reg) = 0x0; tc_wmb(); 635 REG(vdac, bt_reg) = 0x0; tc_wmb(); 636 REG(vdac, bt_reg) = 0x0; tc_wmb(); 637 REG(vdac, bt_reg) = 0x0; tc_wmb(); 638 REG(vdac, bt_reg) = 0x0; tc_wmb(); 639 REG(vdac, bt_reg) = 0x0; tc_wmb(); 640 REG(vdac, bt_reg) = 0x0; tc_wmb(); 641 REG(vdac, bt_reg) = 0x0; tc_wmb(); 642 REG(vdac, bt_reg) = 0x0; tc_wmb(); 643 REG(vdac, bt_reg) = 0x0; tc_wmb(); 644 645 /* build sane colormap */ 646 SELECT(vdac, 0); 647 p = rasops_cmap; 648 for (i = 0; i < CMAP_SIZE; i++, p += 3) { 649 REG(vdac, bt_cmap) = p[0]; tc_wmb(); 650 REG(vdac, bt_cmap) = p[1]; tc_wmb(); 651 REG(vdac, bt_cmap) = p[2]; tc_wmb(); 652 } 653 654 /* clear out cursor image */ 655 SELECT(vdac, BT459_IREG_CRAM_BASE); 656 for (i = 0; i < 1024; i++) 657 REG(vdac, bt_reg) = 0xff; tc_wmb(); 658 659 /* 660 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 661 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 662 * image color. CCOLOR_1 will be never used. 663 */ 664 SELECT(vdac, BT459_IREG_CCOLOR_1); 665 REG(vdac, bt_reg) = 0xff; tc_wmb(); 666 REG(vdac, bt_reg) = 0xff; tc_wmb(); 667 REG(vdac, bt_reg) = 0xff; tc_wmb(); 668 669 REG(vdac, bt_reg) = 0; tc_wmb(); 670 REG(vdac, bt_reg) = 0; tc_wmb(); 671 REG(vdac, bt_reg) = 0; tc_wmb(); 672 673 REG(vdac, bt_reg) = 0xff; tc_wmb(); 674 REG(vdac, bt_reg) = 0xff; tc_wmb(); 675 REG(vdac, bt_reg) = 0xff; tc_wmb(); 676 } 677 678 static void 679 bt463init(vdac) 680 caddr_t vdac; 681 { 682 int i; 683 684 SELECT(vdac, BT463_IREG_COMMAND_0); 685 REG(vdac, bt_reg) = 0x40; tc_wmb(); /* CMD 0 */ 686 REG(vdac, bt_reg) = 0x48; tc_wmb(); /* CMD 1 */ 687 REG(vdac, bt_reg) = 0xc0; tc_wmb(); /* CMD 2 */ 688 REG(vdac, bt_reg) = 0; tc_wmb(); /* !? 204 !? */ 689 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 0:7 */ 690 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 8:15 */ 691 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 16:23 */ 692 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 24:27 */ 693 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 0:7 */ 694 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 8:15 */ 695 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 16:23 */ 696 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 24:27 */ 697 REG(vdac, bt_reg) = 0x00; tc_wmb(); 698 699 SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE); 700 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) { 701 REG(vdac, bt_reg) = 0x00; /* 0:7 */ 702 REG(vdac, bt_reg) = 0xe1; /* 8:15 */ 703 REG(vdac, bt_reg) = 0x81; /* 16:23 */ 704 } 705 } 706 707 static int 708 get_cmap(sc, p) 709 struct sfbp_softc *sc; 710 struct wsdisplay_cmap *p; 711 { 712 u_int index = p->index, count = p->count; 713 714 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 715 return (EINVAL); 716 717 if (!uvm_useracc(p->red, count, B_WRITE) || 718 !uvm_useracc(p->green, count, B_WRITE) || 719 !uvm_useracc(p->blue, count, B_WRITE)) 720 return (EFAULT); 721 722 copyout(&sc->sc_cmap.r[index], p->red, count); 723 copyout(&sc->sc_cmap.g[index], p->green, count); 724 copyout(&sc->sc_cmap.b[index], p->blue, count); 725 726 return (0); 727 } 728 729 static int 730 set_cmap(sc, p) 731 struct sfbp_softc *sc; 732 struct wsdisplay_cmap *p; 733 { 734 u_int index = p->index, count = p->count; 735 736 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 737 return (EINVAL); 738 739 if (!uvm_useracc(p->red, count, B_READ) || 740 !uvm_useracc(p->green, count, B_READ) || 741 !uvm_useracc(p->blue, count, B_READ)) 742 return (EFAULT); 743 744 copyin(p->red, &sc->sc_cmap.r[index], count); 745 copyin(p->green, &sc->sc_cmap.g[index], count); 746 copyin(p->blue, &sc->sc_cmap.b[index], count); 747 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 748 return (0); 749 } 750 751 static int 752 set_cursor(sc, p) 753 struct sfbp_softc *sc; 754 struct wsdisplay_cursor *p; 755 { 756 #define cc (&sc->sc_cursor) 757 u_int v, index, count, icount; 758 759 v = p->which; 760 if (v & WSDISPLAY_CURSOR_DOCMAP) { 761 index = p->cmap.index; 762 count = p->cmap.count; 763 if (index >= 2 || (index + count) > 2) 764 return (EINVAL); 765 if (!uvm_useracc(p->cmap.red, count, B_READ) || 766 !uvm_useracc(p->cmap.green, count, B_READ) || 767 !uvm_useracc(p->cmap.blue, count, B_READ)) 768 return (EFAULT); 769 } 770 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 771 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 772 return (EINVAL); 773 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 774 if (!uvm_useracc(p->image, icount, B_READ) || 775 !uvm_useracc(p->mask, icount, B_READ)) 776 return (EFAULT); 777 } 778 779 if (v & WSDISPLAY_CURSOR_DOCUR) 780 sc->sc_curenb = p->enable; 781 if (v & WSDISPLAY_CURSOR_DOPOS) 782 set_curpos(sc, &p->pos); 783 if (v & WSDISPLAY_CURSOR_DOHOT) 784 cc->cc_hot = p->hot; 785 if (v & WSDISPLAY_CURSOR_DOCMAP) { 786 copyin(p->cmap.red, &cc->cc_color[index], count); 787 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 788 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 789 } 790 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 791 cc->cc_size = p->size; 792 memset(cc->cc_image, 0, sizeof cc->cc_image); 793 copyin(p->image, cc->cc_image, icount); 794 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount); 795 } 796 sc->sc_changed = v; 797 798 return (0); 799 #undef cc 800 } 801 802 static int 803 get_cursor(sc, p) 804 struct sfbp_softc *sc; 805 struct wsdisplay_cursor *p; 806 { 807 return (EPASSTHROUGH); /* XXX */ 808 } 809 810 static void 811 set_curpos(sc, curpos) 812 struct sfbp_softc *sc; 813 struct wsdisplay_curpos *curpos; 814 { 815 struct rasops_info *ri = sc->sc_ri; 816 int x = curpos->x, y = curpos->y; 817 818 if (y < 0) 819 y = 0; 820 else if (y > ri->ri_height) 821 y = ri->ri_height; 822 if (x < 0) 823 x = 0; 824 else if (x > ri->ri_width) 825 x = ri->ri_width; 826 sc->sc_cursor.cc_pos.x = x; 827 sc->sc_cursor.cc_pos.y = y; 828 } 829 830 static void 831 bt459visible(hw, on) 832 caddr_t hw; 833 int on; 834 { 835 hw += SFB_RAMDAC_OFFSET; 836 SELECT(hw, BT459_IREG_CCR); 837 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00; 838 tc_wmb(); 839 } 840 841 static void 842 sfbpvisible(hw, on) 843 caddr_t hw; 844 int on; 845 { 846 /* XXX use SFBplus ASIC XX */ 847 } 848 849 static void 850 bt459locate(hw, cc) 851 caddr_t hw; 852 struct hwcursor64 *cc; 853 { 854 int x, y, s; 855 856 x = cc->cc_pos.x - cc->cc_hot.x; 857 y = cc->cc_pos.y - cc->cc_hot.y; 858 x += cc->cc_magic.x; 859 y += cc->cc_magic.y; 860 861 hw += SFB_RAMDAC_OFFSET; 862 863 s = spltty(); 864 SELECT(hw, BT459_IREG_CURSOR_X_LOW); 865 REG(hw, bt_reg) = x; tc_wmb(); 866 REG(hw, bt_reg) = x >> 8; tc_wmb(); 867 REG(hw, bt_reg) = y; tc_wmb(); 868 REG(hw, bt_reg) = y >> 8; tc_wmb(); 869 splx(s); 870 } 871 872 static void 873 sfbplocate(hw, cc) 874 caddr_t hw; 875 struct hwcursor64 *cc; 876 { 877 int x, y; 878 879 x = cc->cc_pos.x - cc->cc_hot.x; 880 y = cc->cc_pos.y - cc->cc_hot.y; 881 882 hw += SFB_ASIC_OFFSET; 883 *((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff); 884 tc_wmb(); 885 } 886 887 static void 888 bt459color(hw, cp) 889 caddr_t hw; 890 u_int8_t *cp; 891 { 892 893 hw += SFB_RAMDAC_OFFSET; 894 895 SELECT(hw, BT459_IREG_CCOLOR_2); 896 REG(hw, bt_reg) = cp[1]; tc_wmb(); 897 REG(hw, bt_reg) = cp[3]; tc_wmb(); 898 REG(hw, bt_reg) = cp[5]; tc_wmb(); 899 900 REG(hw, bt_reg) = cp[0]; tc_wmb(); 901 REG(hw, bt_reg) = cp[2]; tc_wmb(); 902 REG(hw, bt_reg) = cp[4]; tc_wmb(); 903 } 904 905 static void 906 bt463color(hw, cp) 907 caddr_t hw; 908 u_int8_t *cp; 909 { 910 } 911 912 static void 913 bt459shape(hw, size, image) 914 caddr_t hw; 915 struct wsdisplay_curpos *size; 916 u_int64_t *image; 917 { 918 u_int8_t *ip, *mp, img, msk; 919 u_int8_t u; 920 int bcnt; 921 922 hw += SFB_RAMDAC_OFFSET; 923 ip = (u_int8_t *)image; 924 mp = (u_int8_t *)(image + CURSOR_MAX_SIZE); 925 926 bcnt = 0; 927 SELECT(hw, BT459_IREG_CRAM_BASE+0); 928 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 929 while (bcnt < size->y * 16) { 930 /* pad right half 32 pixel when smaller than 33 */ 931 if ((bcnt & 0x8) && size->x < 33) { 932 REG(hw, bt_reg) = 0; tc_wmb(); 933 REG(hw, bt_reg) = 0; tc_wmb(); 934 } 935 else { 936 img = *ip++; 937 msk = *mp++; 938 img &= msk; /* cookie off image */ 939 u = (msk & 0x0f) << 4 | (img & 0x0f); 940 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 941 u = (msk & 0xf0) | (img & 0xf0) >> 4; 942 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 943 } 944 bcnt += 2; 945 } 946 /* pad unoccupied scan lines */ 947 while (bcnt < CURSOR_MAX_SIZE * 16) { 948 REG(hw, bt_reg) = 0; tc_wmb(); 949 REG(hw, bt_reg) = 0; tc_wmb(); 950 bcnt += 2; 951 } 952 } 953 954 static void 955 sfbpshape(hw, size, image) 956 caddr_t hw; 957 struct wsdisplay_curpos *size; 958 u_int64_t *image; 959 { 960 /* XXX use SFBplus ASIC XXX */ 961 } 962 963 static void 964 bt459setlut(hw, cm) 965 caddr_t hw; 966 struct hwcmap256 *cm; 967 { 968 int index; 969 970 hw += SFB_RAMDAC_OFFSET; 971 SELECT(hw, 0); 972 for (index = 0; index < CMAP_SIZE; index++) { 973 REG(hw, bt_cmap) = cm->r[index]; tc_wmb(); 974 REG(hw, bt_cmap) = cm->g[index]; tc_wmb(); 975 REG(hw, bt_cmap) = cm->b[index]; tc_wmb(); 976 } 977 } 978 979 static void 980 noplut(hw, cm) 981 caddr_t hw; 982 struct hwcmap256 *cm; 983 { 984 } 985 986 #define SFBBPP 32 987 988 #define MODE_SIMPLE 0 989 #define MODE_OPAQUESTIPPLE 1 990 #define MODE_OPAQUELINE 2 991 #define MODE_TRANSPARENTSTIPPLE 5 992 #define MODE_TRANSPARENTLINE 6 993 #define MODE_COPY 7 994 995 #if SFBBPP == 8 996 /* parameters for 8bpp configuration */ 997 #define SFBALIGNMASK 0x7 998 #define SFBPIXELBYTES 1 999 #define SFBSTIPPLEALL1 0xffffffff 1000 #define SFBSTIPPLEBITS 32 1001 #define SFBSTIPPLEBITMASK 0x1f 1002 #define SFBSTIPPLEBYTESDONE 32 1003 #define SFBCOPYALL1 0xffffffff 1004 #define SFBCOPYBITS 32 1005 #define SFBCOPYBITMASK 0x1f 1006 #define SFBCOPYBYTESDONE 32 1007 1008 #elif SFBBPP == 32 1009 /* parameters for 32bpp configuration */ 1010 #define SFBALIGNMASK 0x7 1011 #define SFBPIXELBYTES 4 1012 #define SFBSTIPPLEALL1 0x0000ffff 1013 #define SFBSTIPPLEBITS 16 1014 #define SFBSTIPPLEBITMASK 0xf 1015 #define SFBSTIPPLEBYTESDONE 32 1016 #define SFBCOPYALL1 0x000000ff 1017 #define SFBCOPYBITS 8 1018 #define SFBCOPYBITMASK 0x3 1019 #define SFBCOPYBYTESDONE 32 1020 #endif 1021 1022 #ifdef pmax 1023 #define WRITE_MB() 1024 #define BUMP(p) (p) 1025 #endif 1026 1027 #ifdef alpha 1028 #define WRITE_MB() tc_wmb() 1029 /* registers is replicated in 1KB stride; rap round 4th iteration */ 1030 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000)) 1031 #endif 1032 1033 #define SFBMODE(p, v) \ 1034 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v)) 1035 #define SFBROP(p, v) \ 1036 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v)) 1037 #define SFBPLANEMASK(p, v) \ 1038 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v)) 1039 #define SFBPIXELMASK(p, v) \ 1040 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v)) 1041 #define SFBADDRESS(p, v) \ 1042 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v)) 1043 #define SFBSTART(p, v) \ 1044 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v)) 1045 #define SFBPIXELSHIFT(p, v) \ 1046 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v)) 1047 #define SFBFG(p, v) \ 1048 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v)) 1049 #define SFBBG(p, v) \ 1050 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v)) 1051 #define SFBBCONT(p, v) \ 1052 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v)) 1053 1054 #define SFBDATA(p, v) \ 1055 (*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v)) 1056 1057 #define SFBCOPY64BYTESDONE 8 1058 #define SFBCOPY64BITS 64 1059 #define SFBCOPY64SRC(p, v) \ 1060 (*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v)) 1061 #define SFBCOPY64DST(p, v) \ 1062 (*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v)) 1063 1064 /* 1065 * Actually write a string to the frame buffer. 1066 */ 1067 static void 1068 sfbp_putchar(id, row, col, uc, attr) 1069 void *id; 1070 int row, col; 1071 u_int uc; 1072 long attr; 1073 { 1074 struct rasops_info *ri = id; 1075 caddr_t sfb, p; 1076 int scanspan, height, width, align, x, y; 1077 u_int32_t lmask, rmask, glyph; 1078 u_int8_t *g; 1079 1080 x = col * ri->ri_font->fontwidth; 1081 y = row * ri->ri_font->fontheight; 1082 scanspan = ri->ri_stride; 1083 height = ri->ri_font->fontheight; 1084 uc -= ri->ri_font->firstchar; 1085 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 1086 1087 p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES; 1088 align = (long)p & SFBALIGNMASK; 1089 p -= align; 1090 align /= SFBPIXELBYTES; 1091 width = ri->ri_font->fontwidth + align; 1092 lmask = SFBSTIPPLEALL1 << align; 1093 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1094 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1095 1096 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 1097 SFBPLANEMASK(sfb, ~0); 1098 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]); 1099 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 1100 SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */ 1101 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask; 1102 1103 /* XXX 2B stride fonts only XXX */ 1104 while (height > 0) { 1105 glyph = *(u_int16_t *)g; /* XXX */ 1106 *(u_int32_t *)p = glyph << align; 1107 p += scanspan; 1108 g += 2; /* XXX */ 1109 height--; 1110 } 1111 SFBMODE(sfb, MODE_SIMPLE); 1112 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0; 1113 } 1114 1115 #undef SFBSTIPPLEALL1 1116 #undef SFBSTIPPLEBITS 1117 #undef SFBSTIPPLEBITMASK 1118 #define SFBSTIPPLEALL1 SFBCOPYALL1 1119 #define SFBSTIPPLEBITS SFBCOPYBITS 1120 #define SFBSTIPPLEBITMASK SFBCOPYBITMASK 1121 1122 /* 1123 * Clear characters in a line. 1124 */ 1125 static void 1126 sfbp_erasecols(id, row, startcol, ncols, attr) 1127 void *id; 1128 int row, startcol, ncols; 1129 long attr; 1130 { 1131 struct rasops_info *ri = id; 1132 caddr_t sfb, p; 1133 int scanspan, startx, height, width, align, w, y; 1134 u_int32_t lmask, rmask; 1135 1136 scanspan = ri->ri_stride; 1137 y = row * ri->ri_font->fontheight; 1138 startx = startcol * ri->ri_font->fontwidth; 1139 height = ri->ri_font->fontheight; 1140 w = ri->ri_font->fontwidth * ncols; 1141 1142 p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES; 1143 align = (long)p & SFBALIGNMASK; 1144 align /= SFBPIXELBYTES; 1145 p -= align; 1146 width = w + align; 1147 lmask = SFBSTIPPLEALL1 << align; 1148 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1149 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1150 1151 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1152 SFBPLANEMASK(sfb, ~0); 1153 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1154 if (width <= SFBSTIPPLEBITS) { 1155 lmask = lmask & rmask; 1156 while (height > 0) { 1157 *(u_int32_t *)p = lmask; 1158 p += scanspan; 1159 height--; 1160 } 1161 } 1162 else { 1163 caddr_t q = p; 1164 while (height > 0) { 1165 *(u_int32_t *)p = lmask; 1166 WRITE_MB(); 1167 width -= 2 * SFBSTIPPLEBITS; 1168 while (width > 0) { 1169 p += SFBSTIPPLEBYTESDONE; 1170 *(u_int32_t *)p = SFBSTIPPLEALL1; 1171 WRITE_MB(); 1172 width -= SFBSTIPPLEBITS; 1173 } 1174 p += SFBSTIPPLEBYTESDONE; 1175 *(u_int32_t *)p = rmask; 1176 WRITE_MB(); 1177 1178 p = (q += scanspan); 1179 width = w + align; 1180 height--; 1181 } 1182 } 1183 SFBMODE(sfb, MODE_SIMPLE); 1184 } 1185 1186 #if 1 1187 /* 1188 * Copy lines. 1189 */ 1190 static void 1191 sfbp_copyrows(id, srcrow, dstrow, nrows) 1192 void *id; 1193 int srcrow, dstrow, nrows; 1194 { 1195 struct rasops_info *ri = id; 1196 caddr_t sfb, p; 1197 int scanspan, offset, srcy, height, width, align, w; 1198 u_int32_t lmask, rmask; 1199 1200 scanspan = ri->ri_stride; 1201 height = ri->ri_font->fontheight * nrows; 1202 offset = (dstrow - srcrow) * ri->ri_yscale; 1203 srcy = ri->ri_font->fontheight * srcrow; 1204 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1205 scanspan = -scanspan; 1206 srcy += height; 1207 } 1208 1209 p = ri->ri_bits + srcy * ri->ri_stride; 1210 align = (long)p & SFBALIGNMASK; 1211 p -= align; 1212 align /= SFBPIXELBYTES; 1213 w = ri->ri_emuwidth; 1214 width = w + align; 1215 lmask = SFBCOPYALL1 << align; 1216 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1217 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1218 1219 SFBMODE(sfb, MODE_COPY); 1220 SFBPLANEMASK(sfb, ~0); 1221 SFBPIXELSHIFT(sfb, 0); 1222 if (width <= SFBCOPYBITS) { 1223 /* never happens */; 1224 } 1225 else { 1226 caddr_t q = p; 1227 while (height > 0) { 1228 *(u_int32_t *)p = lmask; 1229 *(u_int32_t *)(p + offset) = lmask; 1230 width -= 2 * SFBCOPYBITS; 1231 while (width > 0) { 1232 p += SFBCOPYBYTESDONE; 1233 *(u_int32_t *)p = SFBCOPYALL1; 1234 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1235 width -= SFBCOPYBITS; 1236 } 1237 p += SFBCOPYBYTESDONE; 1238 *(u_int32_t *)p = rmask; 1239 *(u_int32_t *)(p + offset) = rmask; 1240 1241 p = (q += scanspan); 1242 width = w + align; 1243 height--; 1244 } 1245 } 1246 SFBMODE(sfb, MODE_SIMPLE); 1247 } 1248 1249 #else 1250 1251 1252 static void 1253 sfbp_copyrows(id, srcrow, dstrow, nrows) 1254 void *id; 1255 int srcrow, dstrow, nrows; 1256 { 1257 struct rasops_info *ri = id; 1258 caddr_t sfb, p, q; 1259 int scanspan, offset, srcy, height, width, w, align; 1260 u_int32_t rmask, lmask; 1261 1262 scanspan = ri->ri_stride; 1263 height = ri->ri_font->fontheight * nrows; 1264 offset = (dstrow - srcrow) * ri->ri_yscale; 1265 srcy = ri->ri_font->fontheight * srcrow; 1266 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1267 scanspan = -scanspan; 1268 srcy += height; 1269 } 1270 1271 p = ri->ri_bits + srcy * ri->ri_stride; 1272 align = (long)p & SFBALIGNMASK; 1273 w = ri->ri_emuwidth; 1274 width = w + align; 1275 lmask = SFBCOPYALL1 << align; 1276 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1277 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1278 q = p; 1279 1280 SFBMODE(sfb, MODE_COPY); 1281 SFBPLANEMASK(sfb, ~0); 1282 SFBPIXELSHIFT(sfb, 0); 1283 1284 if (width <= SFBCOPYBITS) 1285 ; /* never happens */ 1286 else if (width < SFBCOPY64BITS) { 1287 ; /* unlikely happens */ 1288 1289 } 1290 else { 1291 while (height > 0) { 1292 while (width >= SFBCOPY64BITS) { 1293 SFBCOPY64SRC(sfb, p); 1294 SFBCOPY64DST(sfb, p + offset); 1295 p += SFBCOPY64BYTESDONE; 1296 width -= SFBCOPY64BITS; 1297 } 1298 if (width >= SFBCOPYBITS) { 1299 *(u_int32_t *)p = SFBCOPYALL1; 1300 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1301 p += SFBCOPYBYTESDONE; 1302 width -= SFBCOPYBITS; 1303 } 1304 if (width > 0) { 1305 *(u_int32_t *)p = rmask; 1306 *(u_int32_t *)(p + offset) = rmask; 1307 } 1308 1309 p = (q += scanspan); 1310 width = w; 1311 height--; 1312 } 1313 } 1314 SFBMODE(sfb, MODE_SIMPLE); 1315 } 1316 #endif 1317 1318 /* 1319 * Erase lines. 1320 */ 1321 static void 1322 sfbp_eraserows(id, startrow, nrows, attr) 1323 void *id; 1324 int startrow, nrows; 1325 long attr; 1326 { 1327 struct rasops_info *ri = id; 1328 caddr_t sfb, p; 1329 int scanspan, starty, height, width, align, w; 1330 u_int32_t lmask, rmask; 1331 1332 scanspan = ri->ri_stride; 1333 starty = ri->ri_font->fontheight * startrow; 1334 height = ri->ri_font->fontheight * nrows; 1335 1336 p = ri->ri_bits + starty * scanspan; 1337 align = (long)p & SFBALIGNMASK; 1338 p -= align; 1339 align /= SFBPIXELBYTES; 1340 w = ri->ri_emuwidth * SFBPIXELBYTES; 1341 width = w + align; 1342 lmask = SFBSTIPPLEALL1 << align; 1343 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1344 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1345 1346 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1347 SFBPLANEMASK(sfb, ~0); 1348 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 1349 if (width <= SFBSTIPPLEBITS) { 1350 /* never happens */; 1351 } 1352 else { 1353 caddr_t q = p; 1354 while (height > 0) { 1355 *(u_int32_t *)p = lmask; 1356 WRITE_MB(); 1357 width -= 2 * SFBSTIPPLEBITS; 1358 while (width > 0) { 1359 p += SFBSTIPPLEBYTESDONE; 1360 *(u_int32_t *)p = SFBSTIPPLEALL1; 1361 WRITE_MB(); 1362 width -= SFBSTIPPLEBITS; 1363 } 1364 p += SFBSTIPPLEBYTESDONE; 1365 *(u_int32_t *)p = rmask; 1366 WRITE_MB(); 1367 1368 p = (q += scanspan); 1369 width = w + align; 1370 height--; 1371 } 1372 } 1373 SFBMODE(sfb, MODE_SIMPLE); 1374 } 1375