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