1 /* $NetBSD: sfb.c,v 1.49 2001/11/13 06:26:10 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 1999 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: sfb.c,v 1.49 2001/11/13 06:26:10 lukem 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/tc/sfbreg.h> 56 57 #include <uvm/uvm_extern.h> 58 59 #if defined(pmax) 60 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x)) 61 #endif 62 63 #if defined(alpha) 64 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x)) 65 #endif 66 67 /* 68 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have 69 * obscure register layout such as 2nd and 3rd Bt459 registers are 70 * adjacent each other in a word, i.e., 71 * struct bt459triplet { 72 * struct { 73 * u_int8_t u0; 74 * u_int8_t u1; 75 * u_int8_t u2; 76 * unsigned :8; 77 * } bt_lo; 78 * 79 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble. 80 * struct bt459reg { 81 * u_int32_t bt_lo; 82 * u_int32_t bt_hi; 83 * u_int32_t bt_reg; 84 * u_int32_t bt_cmap; 85 * }; 86 */ 87 88 /* Bt459 hardware registers */ 89 #define bt_lo 0 90 #define bt_hi 1 91 #define bt_reg 2 92 #define bt_cmap 3 93 94 #define REG(base, index) *((u_int32_t *)(base) + (index)) 95 #define SELECT(vdac, regno) do { \ 96 REG(vdac, bt_lo) = ((regno) & 0x00ff); \ 97 REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \ 98 tc_wmb(); \ 99 } while (0) 100 101 struct hwcmap256 { 102 #define CMAP_SIZE 256 /* 256 R/G/B entries */ 103 u_int8_t r[CMAP_SIZE]; 104 u_int8_t g[CMAP_SIZE]; 105 u_int8_t b[CMAP_SIZE]; 106 }; 107 108 struct hwcursor64 { 109 struct wsdisplay_curpos cc_pos; 110 struct wsdisplay_curpos cc_hot; 111 struct wsdisplay_curpos cc_size; 112 struct wsdisplay_curpos cc_magic; 113 #define CURSOR_MAX_SIZE 64 114 u_int8_t cc_color[6]; 115 u_int64_t cc_image[64 + 64]; 116 }; 117 118 struct sfb_softc { 119 struct device sc_dev; 120 vaddr_t sc_vaddr; 121 size_t sc_size; 122 struct rasops_info *sc_ri; 123 struct hwcmap256 sc_cmap; /* software copy of colormap */ 124 struct hwcursor64 sc_cursor; /* software copy of cursor */ 125 int sc_blanked; /* video visibility disabled */ 126 int sc_curenb; /* cursor sprite enabled */ 127 int sc_changed; /* need update of hardware */ 128 #define WSDISPLAY_CMAP_DOLUT 0x20 129 int nscreens; 130 }; 131 132 #define HX_MAGIC_X 368 133 #define HX_MAGIC_Y 38 134 135 static int sfbmatch __P((struct device *, struct cfdata *, void *)); 136 static void sfbattach __P((struct device *, struct device *, void *)); 137 138 const struct cfattach sfb_ca = { 139 sizeof(struct sfb_softc), sfbmatch, sfbattach, 140 }; 141 142 static void sfb_common_init __P((struct rasops_info *)); 143 static struct rasops_info sfb_console_ri; 144 static tc_addr_t sfb_consaddr; 145 146 static void sfb_putchar __P((void *, int, int, u_int, long)); 147 static void sfb_erasecols __P((void *, int, int, int, long)); 148 static void sfb_eraserows __P((void *, int, int, long)); 149 static void sfb_copyrows __P((void *, int, int, int)); 150 static void sfb_do_cursor __P((struct rasops_info *)); 151 #if 0 152 static void sfb_copycols __P((void *, int, int, int, int)); 153 #endif 154 155 static struct wsscreen_descr sfb_stdscreen = { 156 "std", 0, 0, 157 0, /* textops */ 158 0, 0, 159 WSSCREEN_REVERSE 160 }; 161 162 static const struct wsscreen_descr *_sfb_scrlist[] = { 163 &sfb_stdscreen, 164 }; 165 166 static const struct wsscreen_list sfb_screenlist = { 167 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist 168 }; 169 170 static int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *)); 171 static paddr_t sfbmmap __P((void *, off_t, int)); 172 173 static int sfb_alloc_screen __P((void *, const struct wsscreen_descr *, 174 void **, int *, int *, long *)); 175 static void sfb_free_screen __P((void *, void *)); 176 static int sfb_show_screen __P((void *, void *, int, 177 void (*) (void *, int, int), void *)); 178 179 static const struct wsdisplay_accessops sfb_accessops = { 180 sfbioctl, 181 sfbmmap, 182 sfb_alloc_screen, 183 sfb_free_screen, 184 sfb_show_screen, 185 0 /* load_font */ 186 }; 187 188 int sfb_cnattach __P((tc_addr_t)); 189 static int sfbintr __P((void *)); 190 static void sfbhwinit __P((caddr_t)); 191 192 static int get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *)); 193 static int set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *)); 194 static int set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *)); 195 static int get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *)); 196 static void set_curpos __P((struct sfb_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 sfbmatch(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("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0) 249 return (0); 250 return (1); 251 } 252 253 static void 254 sfbattach(parent, self, aux) 255 struct device *parent, *self; 256 void *aux; 257 { 258 struct sfb_softc *sc = (struct sfb_softc *)self; 259 struct tc_attach_args *ta = aux; 260 struct rasops_info *ri; 261 struct wsemuldisplaydev_attach_args waa; 262 struct hwcmap256 *cm; 263 const u_int8_t *p; 264 caddr_t asic; 265 int console, index; 266 267 console = (ta->ta_addr == sfb_consaddr); 268 if (console) { 269 sc->sc_ri = ri = &sfb_console_ri; 270 sc->nscreens = 1; 271 } 272 else { 273 MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info), 274 M_DEVBUF, M_NOWAIT); 275 if (ri == NULL) { 276 printf(": can't alloc memory\n"); 277 return; 278 } 279 memset(ri, 0, sizeof(struct rasops_info)); 280 281 ri->ri_hw = (void *)ta->ta_addr; 282 sfb_common_init(ri); 283 sc->sc_ri = ri; 284 } 285 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth); 286 287 cm = &sc->sc_cmap; 288 p = rasops_cmap; 289 for (index = 0; index < CMAP_SIZE; index++, p += 3) { 290 cm->r[index] = p[0]; 291 cm->g[index] = p[1]; 292 cm->b[index] = p[2]; 293 } 294 295 sc->sc_vaddr = ta->ta_addr; 296 sc->sc_cursor.cc_magic.x = HX_MAGIC_X; 297 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y; 298 sc->sc_blanked = sc->sc_curenb = 0; 299 300 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc); 301 302 asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 303 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 304 *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; 305 306 waa.console = console; 307 waa.scrdata = &sfb_screenlist; 308 waa.accessops = &sfb_accessops; 309 waa.accesscookie = sc; 310 311 config_found(self, &waa, wsemuldisplaydevprint); 312 } 313 314 static void 315 sfb_common_init(ri) 316 struct rasops_info *ri; 317 { 318 caddr_t base, asic; 319 int hsetup, vsetup, vbase, cookie; 320 321 base = (caddr_t)ri->ri_hw; 322 asic = base + SFB_ASIC_OFFSET; 323 hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP); 324 vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP); 325 326 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1; 327 *(u_int32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0; 328 *(u_int32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0; 329 *(u_int32_t *)(asic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */ 330 *(u_int32_t *)(asic + SFB_ASIC_ROP) = 3; /* ROP_COPY */ 331 *(u_int32_t *)(asic + 0x180000) = 0; /* Bt459 reset */ 332 333 /* initialize colormap and cursor hardware */ 334 sfbhwinit(base); 335 336 ri->ri_flg = RI_CENTER; 337 ri->ri_depth = 8; 338 ri->ri_width = (hsetup & 0x1ff) << 2; 339 ri->ri_height = (vsetup & 0x7ff); 340 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8); 341 ri->ri_bits = base + SFB_FB_OFFSET + vbase * 4096; 342 343 /* clear the screen */ 344 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 345 346 wsfont_init(); 347 /* prefer 12 pixel wide font */ 348 if ((cookie = wsfont_find(NULL, 12, 0, 0)) <= 0) 349 cookie = wsfont_find(NULL, 0, 0, 0); 350 if (cookie <= 0) { 351 printf("sfb: font table is empty\n"); 352 return; 353 } 354 355 /* the accelerated sfb_putchar() needs LSbit left */ 356 if (wsfont_lock(cookie, &ri->ri_font, 357 WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) { 358 printf("sfb: couldn't lock font\n"); 359 return; 360 } 361 ri->ri_wsfcookie = cookie; 362 363 rasops_init(ri, 34, 80); 364 365 /* add our accelerated functions */ 366 ri->ri_ops.putchar = sfb_putchar; 367 ri->ri_ops.erasecols = sfb_erasecols; 368 ri->ri_ops.copyrows = sfb_copyrows; 369 ri->ri_ops.eraserows = sfb_eraserows; 370 ri->ri_do_cursor = sfb_do_cursor; 371 372 /* XXX shouldn't be global */ 373 sfb_stdscreen.nrows = ri->ri_rows; 374 sfb_stdscreen.ncols = ri->ri_cols; 375 sfb_stdscreen.textops = &ri->ri_ops; 376 sfb_stdscreen.capabilities = ri->ri_caps; 377 } 378 379 static int 380 sfbioctl(v, cmd, data, flag, p) 381 void *v; 382 u_long cmd; 383 caddr_t data; 384 int flag; 385 struct proc *p; 386 { 387 struct sfb_softc *sc = v; 388 struct rasops_info *ri = sc->sc_ri; 389 int turnoff; 390 391 switch (cmd) { 392 case WSDISPLAYIO_GTYPE: 393 *(u_int *)data = WSDISPLAY_TYPE_SFB; 394 return (0); 395 396 case WSDISPLAYIO_GINFO: 397 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 398 wsd_fbip->height = ri->ri_height; 399 wsd_fbip->width = ri->ri_width; 400 wsd_fbip->depth = ri->ri_depth; 401 wsd_fbip->cmsize = CMAP_SIZE; 402 #undef fbt 403 return (0); 404 405 case WSDISPLAYIO_GETCMAP: 406 return get_cmap(sc, (struct wsdisplay_cmap *)data); 407 408 case WSDISPLAYIO_PUTCMAP: 409 return set_cmap(sc, (struct wsdisplay_cmap *)data); 410 411 case WSDISPLAYIO_SVIDEO: 412 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 413 if (sc->sc_blanked ^ turnoff) { 414 caddr_t asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 415 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VALID) 416 = !turnoff; 417 tc_wmb(); 418 sc->sc_blanked = turnoff; 419 } 420 return (0); 421 422 case WSDISPLAYIO_GVIDEO: 423 *(u_int *)data = sc->sc_blanked ? 424 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 425 return (0); 426 427 case WSDISPLAYIO_GCURPOS: 428 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 429 return (0); 430 431 case WSDISPLAYIO_SCURPOS: 432 set_curpos(sc, (struct wsdisplay_curpos *)data); 433 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 434 return (0); 435 436 case WSDISPLAYIO_GCURMAX: 437 ((struct wsdisplay_curpos *)data)->x = 438 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 439 return (0); 440 441 case WSDISPLAYIO_GCURSOR: 442 return get_cursor(sc, (struct wsdisplay_cursor *)data); 443 444 case WSDISPLAYIO_SCURSOR: 445 return set_cursor(sc, (struct wsdisplay_cursor *)data); 446 } 447 return (ENOTTY); 448 } 449 450 static paddr_t 451 sfbmmap(v, offset, prot) 452 void *v; 453 off_t offset; 454 int prot; 455 { 456 struct sfb_softc *sc = v; 457 458 if (offset >= SFB_SIZE || offset < 0) 459 return (-1); 460 return machine_btop(sc->sc_vaddr + offset); 461 } 462 463 static int 464 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 465 void *v; 466 const struct wsscreen_descr *type; 467 void **cookiep; 468 int *curxp, *curyp; 469 long *attrp; 470 { 471 struct sfb_softc *sc = v; 472 struct rasops_info *ri = sc->sc_ri; 473 long defattr; 474 475 if (sc->nscreens > 0) 476 return (ENOMEM); 477 478 *cookiep = ri; /* one and only for now */ 479 *curxp = 0; 480 *curyp = 0; 481 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 482 *attrp = defattr; 483 sc->nscreens++; 484 return (0); 485 } 486 487 static void 488 sfb_free_screen(v, cookie) 489 void *v; 490 void *cookie; 491 { 492 struct sfb_softc *sc = v; 493 494 if (sc->sc_ri == &sfb_console_ri) 495 panic("sfb_free_screen: console"); 496 497 sc->nscreens--; 498 } 499 500 static int 501 sfb_show_screen(v, cookie, waitok, cb, cbarg) 502 void *v; 503 void *cookie; 504 int waitok; 505 void (*cb) __P((void *, int, int)); 506 void *cbarg; 507 { 508 509 return (0); 510 } 511 512 /* EXPORT */ int 513 sfb_cnattach(addr) 514 tc_addr_t addr; 515 { 516 struct rasops_info *ri; 517 long defattr; 518 519 ri = &sfb_console_ri; 520 ri->ri_hw = (void *)addr; 521 sfb_common_init(ri); 522 (*ri->ri_ops.alloc_attr)(&ri, 0, 0, 0, &defattr); 523 wsdisplay_cnattach(&sfb_stdscreen, ri, 0, 0, defattr); 524 sfb_consaddr = addr; 525 return (0); 526 } 527 528 static int 529 sfbintr(arg) 530 void *arg; 531 { 532 struct sfb_softc *sc = arg; 533 caddr_t base, asic, vdac; 534 int v; 535 536 base = (caddr_t)sc->sc_ri->ri_hw; 537 asic = base + SFB_ASIC_OFFSET; 538 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 539 /* *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; */ 540 541 if (sc->sc_changed == 0) 542 goto done; 543 544 vdac = base + SFB_RAMDAC_OFFSET; 545 v = sc->sc_changed; 546 if (v & WSDISPLAY_CURSOR_DOCUR) { 547 SELECT(vdac, BT459_IREG_CCR); 548 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00; 549 } 550 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 551 int x, y; 552 553 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 554 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 555 x += sc->sc_cursor.cc_magic.x; 556 y += sc->sc_cursor.cc_magic.y; 557 558 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 559 REG(vdac, bt_reg) = x; tc_wmb(); 560 REG(vdac, bt_reg) = x >> 8; tc_wmb(); 561 REG(vdac, bt_reg) = y; tc_wmb(); 562 REG(vdac, bt_reg) = y >> 8; tc_wmb(); 563 } 564 if (v & WSDISPLAY_CURSOR_DOCMAP) { 565 u_int8_t *cp = sc->sc_cursor.cc_color; 566 567 SELECT(vdac, BT459_IREG_CCOLOR_2); 568 REG(vdac, bt_reg) = cp[1]; tc_wmb(); 569 REG(vdac, bt_reg) = cp[3]; tc_wmb(); 570 REG(vdac, bt_reg) = cp[5]; tc_wmb(); 571 572 REG(vdac, bt_reg) = cp[0]; tc_wmb(); 573 REG(vdac, bt_reg) = cp[2]; tc_wmb(); 574 REG(vdac, bt_reg) = cp[4]; tc_wmb(); 575 } 576 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 577 u_int8_t *ip, *mp, img, msk; 578 u_int8_t u; 579 int bcnt; 580 581 ip = (u_int8_t *)sc->sc_cursor.cc_image; 582 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE); 583 584 bcnt = 0; 585 SELECT(vdac, BT459_IREG_CRAM_BASE+0); 586 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 587 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 588 /* pad right half 32 pixel when smaller than 33 */ 589 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 590 REG(vdac, bt_reg) = 0; tc_wmb(); 591 REG(vdac, bt_reg) = 0; tc_wmb(); 592 } 593 else { 594 img = *ip++; 595 msk = *mp++; 596 img &= msk; /* cookie off image */ 597 u = (msk & 0x0f) << 4 | (img & 0x0f); 598 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 599 u = (msk & 0xf0) | (img & 0xf0) >> 4; 600 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 601 } 602 bcnt += 2; 603 } 604 /* pad unoccupied scan lines */ 605 while (bcnt < CURSOR_MAX_SIZE * 16) { 606 REG(vdac, bt_reg) = 0; tc_wmb(); 607 REG(vdac, bt_reg) = 0; tc_wmb(); 608 bcnt += 2; 609 } 610 } 611 if (v & WSDISPLAY_CMAP_DOLUT) { 612 struct hwcmap256 *cm = &sc->sc_cmap; 613 int index; 614 615 SELECT(vdac, 0); 616 for (index = 0; index < CMAP_SIZE; index++) { 617 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb(); 618 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb(); 619 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb(); 620 } 621 } 622 sc->sc_changed = 0; 623 done: 624 return (1); 625 } 626 627 static void 628 sfbhwinit(base) 629 caddr_t base; 630 { 631 caddr_t vdac = base + SFB_RAMDAC_OFFSET; 632 const u_int8_t *p; 633 int i; 634 635 SELECT(vdac, BT459_IREG_COMMAND_0); 636 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb(); 637 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb(); 638 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb(); 639 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb(); 640 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb(); 641 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb(); 642 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb(); 643 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb(); 644 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb(); 645 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb(); 646 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb(); 647 648 SELECT(vdac, BT459_IREG_CCR); 649 REG(vdac, bt_reg) = 0x0; tc_wmb(); 650 REG(vdac, bt_reg) = 0x0; tc_wmb(); 651 REG(vdac, bt_reg) = 0x0; tc_wmb(); 652 REG(vdac, bt_reg) = 0x0; tc_wmb(); 653 REG(vdac, bt_reg) = 0x0; tc_wmb(); 654 REG(vdac, bt_reg) = 0x0; tc_wmb(); 655 REG(vdac, bt_reg) = 0x0; tc_wmb(); 656 REG(vdac, bt_reg) = 0x0; tc_wmb(); 657 REG(vdac, bt_reg) = 0x0; tc_wmb(); 658 REG(vdac, bt_reg) = 0x0; tc_wmb(); 659 REG(vdac, bt_reg) = 0x0; tc_wmb(); 660 REG(vdac, bt_reg) = 0x0; tc_wmb(); 661 REG(vdac, bt_reg) = 0x0; tc_wmb(); 662 663 /* build sane colormap */ 664 SELECT(vdac, 0); 665 p = rasops_cmap; 666 for (i = 0; i < CMAP_SIZE; i++, p += 3) { 667 REG(vdac, bt_cmap) = p[0]; tc_wmb(); 668 REG(vdac, bt_cmap) = p[1]; tc_wmb(); 669 REG(vdac, bt_cmap) = p[2]; tc_wmb(); 670 } 671 672 /* clear out cursor image */ 673 SELECT(vdac, BT459_IREG_CRAM_BASE); 674 for (i = 0; i < 1024; i++) 675 REG(vdac, bt_reg) = 0xff; tc_wmb(); 676 677 /* 678 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 679 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 680 * image color. CCOLOR_1 will be never used. 681 */ 682 SELECT(vdac, BT459_IREG_CCOLOR_1); 683 REG(vdac, bt_reg) = 0xff; tc_wmb(); 684 REG(vdac, bt_reg) = 0xff; tc_wmb(); 685 REG(vdac, bt_reg) = 0xff; tc_wmb(); 686 687 REG(vdac, bt_reg) = 0; tc_wmb(); 688 REG(vdac, bt_reg) = 0; tc_wmb(); 689 REG(vdac, bt_reg) = 0; tc_wmb(); 690 691 REG(vdac, bt_reg) = 0xff; tc_wmb(); 692 REG(vdac, bt_reg) = 0xff; tc_wmb(); 693 REG(vdac, bt_reg) = 0xff; tc_wmb(); 694 } 695 696 static int 697 get_cmap(sc, p) 698 struct sfb_softc *sc; 699 struct wsdisplay_cmap *p; 700 { 701 u_int index = p->index, count = p->count; 702 703 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 704 return (EINVAL); 705 706 if (!uvm_useracc(p->red, count, B_WRITE) || 707 !uvm_useracc(p->green, count, B_WRITE) || 708 !uvm_useracc(p->blue, count, B_WRITE)) 709 return (EFAULT); 710 711 copyout(&sc->sc_cmap.r[index], p->red, count); 712 copyout(&sc->sc_cmap.g[index], p->green, count); 713 copyout(&sc->sc_cmap.b[index], p->blue, count); 714 715 return (0); 716 } 717 718 static int 719 set_cmap(sc, p) 720 struct sfb_softc *sc; 721 struct wsdisplay_cmap *p; 722 { 723 u_int index = p->index, count = p->count; 724 725 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 726 return (EINVAL); 727 728 if (!uvm_useracc(p->red, count, B_READ) || 729 !uvm_useracc(p->green, count, B_READ) || 730 !uvm_useracc(p->blue, count, B_READ)) 731 return (EFAULT); 732 733 copyin(p->red, &sc->sc_cmap.r[index], count); 734 copyin(p->green, &sc->sc_cmap.g[index], count); 735 copyin(p->blue, &sc->sc_cmap.b[index], count); 736 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 737 return (0); 738 } 739 740 static int 741 set_cursor(sc, p) 742 struct sfb_softc *sc; 743 struct wsdisplay_cursor *p; 744 { 745 #define cc (&sc->sc_cursor) 746 u_int v, index, count, icount; 747 748 v = p->which; 749 if (v & WSDISPLAY_CURSOR_DOCMAP) { 750 index = p->cmap.index; 751 count = p->cmap.count; 752 if (index >= 2 || (index + count) > 2) 753 return (EINVAL); 754 if (!uvm_useracc(p->cmap.red, count, B_READ) || 755 !uvm_useracc(p->cmap.green, count, B_READ) || 756 !uvm_useracc(p->cmap.blue, count, B_READ)) 757 return (EFAULT); 758 } 759 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 760 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 761 return (EINVAL); 762 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 763 if (!uvm_useracc(p->image, icount, B_READ) || 764 !uvm_useracc(p->mask, icount, B_READ)) 765 return (EFAULT); 766 } 767 768 if (v & WSDISPLAY_CURSOR_DOCUR) 769 sc->sc_curenb = p->enable; 770 if (v & WSDISPLAY_CURSOR_DOPOS) 771 set_curpos(sc, &p->pos); 772 if (v & WSDISPLAY_CURSOR_DOHOT) 773 cc->cc_hot = p->hot; 774 if (v & WSDISPLAY_CURSOR_DOCMAP) { 775 copyin(p->cmap.red, &cc->cc_color[index], count); 776 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 777 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 778 } 779 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 780 cc->cc_size = p->size; 781 memset(cc->cc_image, 0, sizeof cc->cc_image); 782 copyin(p->image, cc->cc_image, icount); 783 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount); 784 } 785 sc->sc_changed |= v; 786 787 return (0); 788 #undef cc 789 } 790 791 static int 792 get_cursor(sc, p) 793 struct sfb_softc *sc; 794 struct wsdisplay_cursor *p; 795 { 796 797 return (ENOTTY); /* XXX */ 798 } 799 800 static void 801 set_curpos(sc, curpos) 802 struct sfb_softc *sc; 803 struct wsdisplay_curpos *curpos; 804 { 805 struct rasops_info *ri = sc->sc_ri; 806 int x = curpos->x, y = curpos->y; 807 808 if (y < 0) 809 y = 0; 810 else if (y > ri->ri_height); 811 y = ri->ri_height; 812 if (x < 0) 813 x = 0; 814 else if (x > ri->ri_width); 815 x = ri->ri_width; 816 sc->sc_cursor.cc_pos.x = x; 817 sc->sc_cursor.cc_pos.y = y; 818 } 819 820 #define MODE_SIMPLE 0 821 #define MODE_OPAQUESTIPPLE 1 822 #define MODE_OPAQUELINE 2 823 #define MODE_TRANSPARENTSTIPPLE 5 824 #define MODE_TRANSPARENTLINE 6 825 #define MODE_COPY 7 826 827 /* parameters for 8bpp configuration */ 828 #define SFBALIGNMASK 0x7 829 #define SFBSTIPPLEALL1 0xffffffff 830 #define SFBSTIPPLEBITS 32 831 #define SFBSTIPPLEBITMASK 0x1f 832 #define SFBSTIPPLEBYTESDONE 32 833 #define SFBCOPYALL1 0xffffffff 834 #define SFBCOPYBITS 32 835 #define SFBCOPYBITMASK 0x1f 836 #define SFBCOPYBYTESDONE 32 837 838 #if defined(pmax) 839 #define WRITE_MB() 840 #define BUMP(p) (p) 841 #endif 842 843 #if defined(alpha) 844 #define WRITE_MB() tc_wmb() 845 /* SFB registers replicated in 128B stride; cycle after eight iterations */ 846 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x80) & ~0x400)) 847 #endif 848 849 #define SFBMODE(p, v) \ 850 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v)) 851 #define SFBROP(p, v) \ 852 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v)) 853 #define SFBPLANEMASK(p, v) \ 854 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v)) 855 #define SFBPIXELMASK(p, v) \ 856 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v)) 857 #define SFBADDRESS(p, v) \ 858 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v)) 859 #define SFBSTART(p, v) \ 860 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v)) 861 #define SFBPIXELSHIFT(p, v) \ 862 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v)) 863 #define SFBFG(p, v) \ 864 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v)) 865 #define SFBBG(p, v) \ 866 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v)) 867 868 /* 869 * Paint the cursor. 870 */ 871 static void 872 sfb_do_cursor(ri) 873 struct rasops_info *ri; 874 { 875 caddr_t sfb, p; 876 int scanspan, height, width, align, x, y; 877 u_int32_t lmask, rmask; 878 879 x = ri->ri_ccol * ri->ri_font->fontwidth; 880 y = ri->ri_crow * ri->ri_font->fontheight; 881 scanspan = ri->ri_stride; 882 height = ri->ri_font->fontheight; 883 884 p = ri->ri_bits + y * scanspan + x; 885 align = (long)p & SFBALIGNMASK; 886 p -= align; 887 width = ri->ri_font->fontwidth + align; 888 lmask = SFBSTIPPLEALL1 << align; 889 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 890 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 891 892 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 893 SFBPLANEMASK(sfb, ~0); 894 SFBROP(sfb, 6); /* ROP_XOR */ 895 SFBFG(sfb, ~0); 896 897 lmask = lmask & rmask; 898 while (height > 0) { 899 SFBADDRESS(sfb, (long)p); 900 SFBSTART(sfb, lmask); 901 p += scanspan; 902 height--; 903 } 904 SFBMODE(sfb, MODE_SIMPLE); 905 SFBROP(sfb, 3); /* ROP_COPY */ 906 } 907 908 /* 909 * Paint a character. 910 */ 911 static void 912 sfb_putchar(id, row, col, uc, attr) 913 void *id; 914 int row, col; 915 u_int uc; 916 long attr; 917 { 918 struct rasops_info *ri = id; 919 caddr_t sfb, p; 920 int scanspan, height, width, align, x, y; 921 u_int32_t lmask, rmask, glyph; 922 u_int8_t *g; 923 924 x = col * ri->ri_font->fontwidth; 925 y = row * ri->ri_font->fontheight; 926 scanspan = ri->ri_stride; 927 height = ri->ri_font->fontheight; 928 uc -= ri->ri_font->firstchar; 929 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 930 931 p = ri->ri_bits + y * scanspan + x; 932 align = (long)p & SFBALIGNMASK; 933 p -= align; 934 width = ri->ri_font->fontwidth + align; 935 lmask = SFBSTIPPLEALL1 << align; 936 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 937 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 938 939 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 940 SFBPLANEMASK(sfb, ~0); 941 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]); 942 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 943 944 /* XXX 2B stride fonts only XXX */ 945 lmask = lmask & rmask; 946 while (height > 0) { 947 glyph = *(u_int16_t *)g; /* XXX */ 948 SFBPIXELMASK(sfb, lmask); 949 SFBADDRESS(sfb, (long)p); 950 SFBSTART(sfb, glyph << align); 951 p += scanspan; 952 g += 2; /* XXX */ 953 height--; 954 } 955 if (attr & 1 /* UNDERLINE */) { 956 p -= scanspan * 2; 957 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 958 SFBADDRESS(sfb, (long)p); 959 SFBSTART(sfb, lmask); 960 } 961 962 SFBMODE(sfb, MODE_SIMPLE); 963 SFBPIXELMASK(sfb, ~0); /* entire pixel */ 964 } 965 966 #if 0 967 /* 968 * Copy characters in a line. 969 */ 970 static void 971 sfb_copycols(id, row, srccol, dstcol, ncols) 972 void *id; 973 int row, srccol, dstcol, ncols; 974 { 975 struct rasops_info *ri = id; 976 caddr_t sp, dp, basex, sfb; 977 int scanspan, height, width, aligns, alignd, shift, w, y; 978 u_int32_t lmaskd, rmaskd; 979 980 scanspan = ri->ri_stride; 981 y = row * ri->ri_font->fontheight; 982 basex = ri->ri_bits + y * scanspan; 983 height = ri->ri_font->fontheight; 984 w = ri->ri_font->fontwidth * ncols; 985 986 sp = basex + ri->ri_font->fontwidth * srccol; 987 aligns = (long)sp & SFBALIGNMASK; 988 dp = basex + ri->ri_font->fontwidth * dstcol; 989 alignd = (long)dp & SFBALIGNMASK; 990 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 991 992 SFBMODE(sfb, MODE_COPY); 993 SFBPLANEMASK(sfb, ~0); 994 /* small enough to fit in a single 32bit */ 995 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) { 996 SFBPIXELSHIFT(sfb, alignd - aligns); 997 lmaskd = SFBCOPYALL1 << alignd; 998 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK); 999 lmaskd = lmaskd & rmaskd; 1000 sp -= aligns; 1001 dp -= alignd; 1002 while (height > 0) { 1003 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1004 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1005 sp += scanspan; 1006 dp += scanspan; 1007 height--; 1008 } 1009 } 1010 /* copy forward (left-to-right) */ 1011 else if (dstcol < srccol || srccol + ncols < dstcol) { 1012 caddr_t sq, dq; 1013 1014 shift = alignd - aligns; 1015 if (shift < 0) { 1016 shift = 8 + shift; /* enforce right rotate */ 1017 alignd += 8; /* bearing on left edge */ 1018 } 1019 width = alignd + w; 1020 lmaskd = SFBCOPYALL1 << alignd; 1021 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1022 sp -= aligns; 1023 dp -= alignd; 1024 1025 SFBPIXELSHIFT(sfb, shift); 1026 w = width; 1027 sq = sp; 1028 dq = dp; 1029 while (height > 0) { 1030 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1031 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1032 width -= 2 * SFBCOPYBITS; 1033 while (width > 0) { 1034 sp += SFBCOPYBYTESDONE; 1035 dp += SFBCOPYBYTESDONE; 1036 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1037 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB(); 1038 width -= SFBCOPYBITS; 1039 } 1040 sp += SFBCOPYBYTESDONE; 1041 dp += SFBCOPYBYTESDONE; 1042 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1043 *(u_int32_t *)dp = rmaskd; WRITE_MB(); 1044 sp = (sq += scanspan); 1045 dp = (dq += scanspan); 1046 width = w; 1047 height--; 1048 } 1049 } 1050 /* copy backward (right-to-left) */ 1051 else { 1052 caddr_t sq, dq; 1053 1054 shift = alignd - aligns; 1055 if (shift > 0) { 1056 shift = shift - 8; /* force left rotate */ 1057 alignd += 24; 1058 } 1059 width = alignd + w; 1060 lmaskd = SFBCOPYALL1 << alignd; 1061 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1062 sp -= aligns; 1063 dp -= alignd; 1064 1065 SFBPIXELSHIFT(sfb, shift); 1066 w = width; 1067 sq = sp += (((aligns + w) - 1) & ~31); 1068 dq = dp += (((alignd + w) - 1) & ~31); 1069 while (height > 0) { 1070 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1071 *(u_int32_t *)dp = rmaskd; WRITE_MB(); 1072 width -= 2 * SFBCOPYBITS; 1073 while (width > 0) { 1074 sp -= SFBCOPYBYTESDONE; 1075 dp -= SFBCOPYBYTESDONE; 1076 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1077 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB(); 1078 width -= SFBCOPYBITS; 1079 } 1080 sp -= SFBCOPYBYTESDONE; 1081 dp -= SFBCOPYBYTESDONE; 1082 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1083 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1084 1085 sp = (sq += scanspan); 1086 dp = (dq += scanspan); 1087 width = w; 1088 height--; 1089 } 1090 } 1091 SFBMODE(sfb, MODE_SIMPLE); 1092 SFBPIXELSHIFT(sfb, 0); 1093 } 1094 #endif 1095 1096 /* 1097 * Clear characters in a line. 1098 */ 1099 static void 1100 sfb_erasecols(id, row, startcol, ncols, attr) 1101 void *id; 1102 int row, startcol, ncols; 1103 long attr; 1104 { 1105 struct rasops_info *ri = id; 1106 caddr_t sfb, p; 1107 int scanspan, startx, height, width, align, w, y; 1108 u_int32_t lmask, rmask; 1109 1110 scanspan = ri->ri_stride; 1111 y = row * ri->ri_font->fontheight; 1112 startx = startcol * ri->ri_font->fontwidth; 1113 height = ri->ri_font->fontheight; 1114 w = ri->ri_font->fontwidth * ncols; 1115 1116 p = ri->ri_bits + y * scanspan + startx; 1117 align = (long)p & SFBALIGNMASK; 1118 p -= align; 1119 width = w + align; 1120 lmask = SFBSTIPPLEALL1 << align; 1121 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1122 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1123 1124 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1125 SFBPLANEMASK(sfb, ~0); 1126 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1127 if (width <= SFBSTIPPLEBITS) { 1128 lmask = lmask & rmask; 1129 while (height > 0) { 1130 SFBADDRESS(sfb, (long)p); 1131 SFBSTART(sfb, lmask); 1132 p += scanspan; 1133 height--; 1134 } 1135 } 1136 else { 1137 caddr_t q = p; 1138 while (height > 0) { 1139 *(u_int32_t *)p = lmask; 1140 WRITE_MB(); 1141 width -= 2 * SFBSTIPPLEBITS; 1142 while (width > 0) { 1143 p += SFBSTIPPLEBYTESDONE; 1144 *(u_int32_t *)p = SFBSTIPPLEALL1; 1145 WRITE_MB(); 1146 width -= SFBSTIPPLEBITS; 1147 } 1148 p += SFBSTIPPLEBYTESDONE; 1149 *(u_int32_t *)p = rmask; 1150 WRITE_MB(); 1151 1152 p = (q += scanspan); 1153 width = w + align; 1154 height--; 1155 } 1156 } 1157 SFBMODE(sfb, MODE_SIMPLE); 1158 } 1159 1160 /* 1161 * Copy lines. 1162 */ 1163 static void 1164 sfb_copyrows(id, srcrow, dstrow, nrows) 1165 void *id; 1166 int srcrow, dstrow, nrows; 1167 { 1168 struct rasops_info *ri = id; 1169 caddr_t sfb, p; 1170 int scanspan, offset, srcy, height, width, align, w; 1171 u_int32_t lmask, rmask; 1172 1173 scanspan = ri->ri_stride; 1174 height = ri->ri_font->fontheight * nrows; 1175 offset = (dstrow - srcrow) * ri->ri_yscale; 1176 srcy = ri->ri_font->fontheight * srcrow; 1177 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1178 scanspan = -scanspan; 1179 srcy += height; 1180 } 1181 1182 p = ri->ri_bits + srcy * ri->ri_stride; 1183 align = (long)p & SFBALIGNMASK; 1184 p -= align; 1185 w = ri->ri_emuwidth; 1186 width = w + align; 1187 lmask = SFBCOPYALL1 << align; 1188 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1189 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1190 1191 SFBMODE(sfb, MODE_COPY); 1192 SFBPLANEMASK(sfb, ~0); 1193 SFBPIXELSHIFT(sfb, 0); 1194 if (width <= SFBCOPYBITS) { 1195 /* never happens */; 1196 } 1197 else { 1198 caddr_t q = p; 1199 while (height > 0) { 1200 *(u_int32_t *)p = lmask; 1201 *(u_int32_t *)(p + offset) = lmask; 1202 width -= 2 * SFBCOPYBITS; 1203 while (width > 0) { 1204 p += SFBCOPYBYTESDONE; 1205 *(u_int32_t *)p = SFBCOPYALL1; 1206 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1207 width -= SFBCOPYBITS; 1208 } 1209 p += SFBCOPYBYTESDONE; 1210 *(u_int32_t *)p = rmask; 1211 *(u_int32_t *)(p + offset) = rmask; 1212 1213 p = (q += scanspan); 1214 width = w + align; 1215 height--; 1216 } 1217 } 1218 SFBMODE(sfb, MODE_SIMPLE); 1219 } 1220 1221 /* 1222 * Erase lines. 1223 */ 1224 void 1225 sfb_eraserows(id, startrow, nrows, attr) 1226 void *id; 1227 int startrow, nrows; 1228 long attr; 1229 { 1230 struct rasops_info *ri = id; 1231 caddr_t sfb, p; 1232 int scanspan, starty, height, width, align, w; 1233 u_int32_t lmask, rmask; 1234 1235 scanspan = ri->ri_stride; 1236 starty = ri->ri_font->fontheight * startrow; 1237 height = ri->ri_font->fontheight * nrows; 1238 1239 p = ri->ri_bits + starty * scanspan; 1240 align = (long)p & SFBALIGNMASK; 1241 p -= align; 1242 w = ri->ri_emuwidth; 1243 width = w + align; 1244 lmask = SFBSTIPPLEALL1 << align; 1245 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1246 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1247 1248 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1249 SFBPLANEMASK(sfb, ~0); 1250 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1251 if (width <= SFBSTIPPLEBITS) { 1252 /* never happens */; 1253 } 1254 else { 1255 caddr_t q = p; 1256 while (height > 0) { 1257 *(u_int32_t *)p = lmask; 1258 WRITE_MB(); 1259 width -= 2 * SFBSTIPPLEBITS; 1260 while (width > 0) { 1261 p += SFBSTIPPLEBYTESDONE; 1262 *(u_int32_t *)p = SFBSTIPPLEALL1; 1263 WRITE_MB(); 1264 width -= SFBSTIPPLEBITS; 1265 } 1266 p += SFBSTIPPLEBYTESDONE; 1267 *(u_int32_t *)p = rmask; 1268 WRITE_MB(); 1269 1270 p = (q += scanspan); 1271 width = w + align; 1272 height--; 1273 } 1274 } 1275 SFBMODE(sfb, MODE_SIMPLE); 1276 } 1277