1 /* $NetBSD: sfb.c,v 1.51 2002/03/17 19:41:02 atatat 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.51 2002/03/17 19:41:02 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/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 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L, 349 WSDISPLAY_FONTORDER_L2R); 350 if (cookie <= 0) 351 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, 352 WSDISPLAY_FONTORDER_L2R); 353 if (cookie <= 0) { 354 printf("sfb: font table is empty\n"); 355 return; 356 } 357 358 /* the accelerated sfb_putchar() needs LSbit left */ 359 if (wsfont_lock(cookie, &ri->ri_font)) { 360 printf("sfb: couldn't lock font\n"); 361 return; 362 } 363 ri->ri_wsfcookie = cookie; 364 365 rasops_init(ri, 34, 80); 366 367 /* add our accelerated functions */ 368 ri->ri_ops.putchar = sfb_putchar; 369 ri->ri_ops.erasecols = sfb_erasecols; 370 ri->ri_ops.copyrows = sfb_copyrows; 371 ri->ri_ops.eraserows = sfb_eraserows; 372 ri->ri_do_cursor = sfb_do_cursor; 373 374 /* XXX shouldn't be global */ 375 sfb_stdscreen.nrows = ri->ri_rows; 376 sfb_stdscreen.ncols = ri->ri_cols; 377 sfb_stdscreen.textops = &ri->ri_ops; 378 sfb_stdscreen.capabilities = ri->ri_caps; 379 } 380 381 static int 382 sfbioctl(v, cmd, data, flag, p) 383 void *v; 384 u_long cmd; 385 caddr_t data; 386 int flag; 387 struct proc *p; 388 { 389 struct sfb_softc *sc = v; 390 struct rasops_info *ri = sc->sc_ri; 391 int turnoff; 392 393 switch (cmd) { 394 case WSDISPLAYIO_GTYPE: 395 *(u_int *)data = WSDISPLAY_TYPE_SFB; 396 return (0); 397 398 case WSDISPLAYIO_GINFO: 399 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 400 wsd_fbip->height = ri->ri_height; 401 wsd_fbip->width = ri->ri_width; 402 wsd_fbip->depth = ri->ri_depth; 403 wsd_fbip->cmsize = CMAP_SIZE; 404 #undef fbt 405 return (0); 406 407 case WSDISPLAYIO_GETCMAP: 408 return get_cmap(sc, (struct wsdisplay_cmap *)data); 409 410 case WSDISPLAYIO_PUTCMAP: 411 return set_cmap(sc, (struct wsdisplay_cmap *)data); 412 413 case WSDISPLAYIO_SVIDEO: 414 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 415 if (sc->sc_blanked ^ turnoff) { 416 caddr_t asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 417 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VALID) 418 = !turnoff; 419 tc_wmb(); 420 sc->sc_blanked = turnoff; 421 } 422 return (0); 423 424 case WSDISPLAYIO_GVIDEO: 425 *(u_int *)data = sc->sc_blanked ? 426 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 427 return (0); 428 429 case WSDISPLAYIO_GCURPOS: 430 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 431 return (0); 432 433 case WSDISPLAYIO_SCURPOS: 434 set_curpos(sc, (struct wsdisplay_curpos *)data); 435 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 436 return (0); 437 438 case WSDISPLAYIO_GCURMAX: 439 ((struct wsdisplay_curpos *)data)->x = 440 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 441 return (0); 442 443 case WSDISPLAYIO_GCURSOR: 444 return get_cursor(sc, (struct wsdisplay_cursor *)data); 445 446 case WSDISPLAYIO_SCURSOR: 447 return set_cursor(sc, (struct wsdisplay_cursor *)data); 448 } 449 return (EPASSTHROUGH); 450 } 451 452 static paddr_t 453 sfbmmap(v, offset, prot) 454 void *v; 455 off_t offset; 456 int prot; 457 { 458 struct sfb_softc *sc = v; 459 460 if (offset >= SFB_SIZE || offset < 0) 461 return (-1); 462 return machine_btop(sc->sc_vaddr + offset); 463 } 464 465 static int 466 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 467 void *v; 468 const struct wsscreen_descr *type; 469 void **cookiep; 470 int *curxp, *curyp; 471 long *attrp; 472 { 473 struct sfb_softc *sc = v; 474 struct rasops_info *ri = sc->sc_ri; 475 long defattr; 476 477 if (sc->nscreens > 0) 478 return (ENOMEM); 479 480 *cookiep = ri; /* one and only for now */ 481 *curxp = 0; 482 *curyp = 0; 483 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 484 *attrp = defattr; 485 sc->nscreens++; 486 return (0); 487 } 488 489 static void 490 sfb_free_screen(v, cookie) 491 void *v; 492 void *cookie; 493 { 494 struct sfb_softc *sc = v; 495 496 if (sc->sc_ri == &sfb_console_ri) 497 panic("sfb_free_screen: console"); 498 499 sc->nscreens--; 500 } 501 502 static int 503 sfb_show_screen(v, cookie, waitok, cb, cbarg) 504 void *v; 505 void *cookie; 506 int waitok; 507 void (*cb) __P((void *, int, int)); 508 void *cbarg; 509 { 510 511 return (0); 512 } 513 514 /* EXPORT */ int 515 sfb_cnattach(addr) 516 tc_addr_t addr; 517 { 518 struct rasops_info *ri; 519 long defattr; 520 521 ri = &sfb_console_ri; 522 ri->ri_hw = (void *)addr; 523 sfb_common_init(ri); 524 (*ri->ri_ops.alloc_attr)(&ri, 0, 0, 0, &defattr); 525 wsdisplay_cnattach(&sfb_stdscreen, ri, 0, 0, defattr); 526 sfb_consaddr = addr; 527 return (0); 528 } 529 530 static int 531 sfbintr(arg) 532 void *arg; 533 { 534 struct sfb_softc *sc = arg; 535 caddr_t base, asic, vdac; 536 int v; 537 538 base = (caddr_t)sc->sc_ri->ri_hw; 539 asic = base + SFB_ASIC_OFFSET; 540 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 541 /* *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; */ 542 543 if (sc->sc_changed == 0) 544 goto done; 545 546 vdac = base + SFB_RAMDAC_OFFSET; 547 v = sc->sc_changed; 548 if (v & WSDISPLAY_CURSOR_DOCUR) { 549 SELECT(vdac, BT459_IREG_CCR); 550 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00; 551 } 552 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 553 int x, y; 554 555 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 556 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 557 x += sc->sc_cursor.cc_magic.x; 558 y += sc->sc_cursor.cc_magic.y; 559 560 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 561 REG(vdac, bt_reg) = x; tc_wmb(); 562 REG(vdac, bt_reg) = x >> 8; tc_wmb(); 563 REG(vdac, bt_reg) = y; tc_wmb(); 564 REG(vdac, bt_reg) = y >> 8; tc_wmb(); 565 } 566 if (v & WSDISPLAY_CURSOR_DOCMAP) { 567 u_int8_t *cp = sc->sc_cursor.cc_color; 568 569 SELECT(vdac, BT459_IREG_CCOLOR_2); 570 REG(vdac, bt_reg) = cp[1]; tc_wmb(); 571 REG(vdac, bt_reg) = cp[3]; tc_wmb(); 572 REG(vdac, bt_reg) = cp[5]; tc_wmb(); 573 574 REG(vdac, bt_reg) = cp[0]; tc_wmb(); 575 REG(vdac, bt_reg) = cp[2]; tc_wmb(); 576 REG(vdac, bt_reg) = cp[4]; tc_wmb(); 577 } 578 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 579 u_int8_t *ip, *mp, img, msk; 580 u_int8_t u; 581 int bcnt; 582 583 ip = (u_int8_t *)sc->sc_cursor.cc_image; 584 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE); 585 586 bcnt = 0; 587 SELECT(vdac, BT459_IREG_CRAM_BASE+0); 588 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 589 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 590 /* pad right half 32 pixel when smaller than 33 */ 591 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 592 REG(vdac, bt_reg) = 0; tc_wmb(); 593 REG(vdac, bt_reg) = 0; tc_wmb(); 594 } 595 else { 596 img = *ip++; 597 msk = *mp++; 598 img &= msk; /* cookie off image */ 599 u = (msk & 0x0f) << 4 | (img & 0x0f); 600 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 601 u = (msk & 0xf0) | (img & 0xf0) >> 4; 602 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 603 } 604 bcnt += 2; 605 } 606 /* pad unoccupied scan lines */ 607 while (bcnt < CURSOR_MAX_SIZE * 16) { 608 REG(vdac, bt_reg) = 0; tc_wmb(); 609 REG(vdac, bt_reg) = 0; tc_wmb(); 610 bcnt += 2; 611 } 612 } 613 if (v & WSDISPLAY_CMAP_DOLUT) { 614 struct hwcmap256 *cm = &sc->sc_cmap; 615 int index; 616 617 SELECT(vdac, 0); 618 for (index = 0; index < CMAP_SIZE; index++) { 619 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb(); 620 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb(); 621 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb(); 622 } 623 } 624 sc->sc_changed = 0; 625 done: 626 return (1); 627 } 628 629 static void 630 sfbhwinit(base) 631 caddr_t base; 632 { 633 caddr_t vdac = base + SFB_RAMDAC_OFFSET; 634 const u_int8_t *p; 635 int i; 636 637 SELECT(vdac, BT459_IREG_COMMAND_0); 638 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb(); 639 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb(); 640 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb(); 641 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb(); 642 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb(); 643 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb(); 644 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb(); 645 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb(); 646 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb(); 647 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb(); 648 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb(); 649 650 SELECT(vdac, BT459_IREG_CCR); 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 REG(vdac, bt_reg) = 0x0; tc_wmb(); 663 REG(vdac, bt_reg) = 0x0; tc_wmb(); 664 665 /* build sane colormap */ 666 SELECT(vdac, 0); 667 p = rasops_cmap; 668 for (i = 0; i < CMAP_SIZE; i++, p += 3) { 669 REG(vdac, bt_cmap) = p[0]; tc_wmb(); 670 REG(vdac, bt_cmap) = p[1]; tc_wmb(); 671 REG(vdac, bt_cmap) = p[2]; tc_wmb(); 672 } 673 674 /* clear out cursor image */ 675 SELECT(vdac, BT459_IREG_CRAM_BASE); 676 for (i = 0; i < 1024; i++) 677 REG(vdac, bt_reg) = 0xff; tc_wmb(); 678 679 /* 680 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 681 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 682 * image color. CCOLOR_1 will be never used. 683 */ 684 SELECT(vdac, BT459_IREG_CCOLOR_1); 685 REG(vdac, bt_reg) = 0xff; tc_wmb(); 686 REG(vdac, bt_reg) = 0xff; tc_wmb(); 687 REG(vdac, bt_reg) = 0xff; tc_wmb(); 688 689 REG(vdac, bt_reg) = 0; tc_wmb(); 690 REG(vdac, bt_reg) = 0; tc_wmb(); 691 REG(vdac, bt_reg) = 0; tc_wmb(); 692 693 REG(vdac, bt_reg) = 0xff; tc_wmb(); 694 REG(vdac, bt_reg) = 0xff; tc_wmb(); 695 REG(vdac, bt_reg) = 0xff; tc_wmb(); 696 } 697 698 static int 699 get_cmap(sc, p) 700 struct sfb_softc *sc; 701 struct wsdisplay_cmap *p; 702 { 703 u_int index = p->index, count = p->count; 704 705 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 706 return (EINVAL); 707 708 if (!uvm_useracc(p->red, count, B_WRITE) || 709 !uvm_useracc(p->green, count, B_WRITE) || 710 !uvm_useracc(p->blue, count, B_WRITE)) 711 return (EFAULT); 712 713 copyout(&sc->sc_cmap.r[index], p->red, count); 714 copyout(&sc->sc_cmap.g[index], p->green, count); 715 copyout(&sc->sc_cmap.b[index], p->blue, count); 716 717 return (0); 718 } 719 720 static int 721 set_cmap(sc, p) 722 struct sfb_softc *sc; 723 struct wsdisplay_cmap *p; 724 { 725 u_int index = p->index, count = p->count; 726 727 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 728 return (EINVAL); 729 730 if (!uvm_useracc(p->red, count, B_READ) || 731 !uvm_useracc(p->green, count, B_READ) || 732 !uvm_useracc(p->blue, count, B_READ)) 733 return (EFAULT); 734 735 copyin(p->red, &sc->sc_cmap.r[index], count); 736 copyin(p->green, &sc->sc_cmap.g[index], count); 737 copyin(p->blue, &sc->sc_cmap.b[index], count); 738 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 739 return (0); 740 } 741 742 static int 743 set_cursor(sc, p) 744 struct sfb_softc *sc; 745 struct wsdisplay_cursor *p; 746 { 747 #define cc (&sc->sc_cursor) 748 u_int v, index, count, icount; 749 750 v = p->which; 751 if (v & WSDISPLAY_CURSOR_DOCMAP) { 752 index = p->cmap.index; 753 count = p->cmap.count; 754 if (index >= 2 || (index + count) > 2) 755 return (EINVAL); 756 if (!uvm_useracc(p->cmap.red, count, B_READ) || 757 !uvm_useracc(p->cmap.green, count, B_READ) || 758 !uvm_useracc(p->cmap.blue, count, B_READ)) 759 return (EFAULT); 760 } 761 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 762 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 763 return (EINVAL); 764 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 765 if (!uvm_useracc(p->image, icount, B_READ) || 766 !uvm_useracc(p->mask, icount, B_READ)) 767 return (EFAULT); 768 } 769 770 if (v & WSDISPLAY_CURSOR_DOCUR) 771 sc->sc_curenb = p->enable; 772 if (v & WSDISPLAY_CURSOR_DOPOS) 773 set_curpos(sc, &p->pos); 774 if (v & WSDISPLAY_CURSOR_DOHOT) 775 cc->cc_hot = p->hot; 776 if (v & WSDISPLAY_CURSOR_DOCMAP) { 777 copyin(p->cmap.red, &cc->cc_color[index], count); 778 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 779 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 780 } 781 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 782 cc->cc_size = p->size; 783 memset(cc->cc_image, 0, sizeof cc->cc_image); 784 copyin(p->image, cc->cc_image, icount); 785 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount); 786 } 787 sc->sc_changed |= v; 788 789 return (0); 790 #undef cc 791 } 792 793 static int 794 get_cursor(sc, p) 795 struct sfb_softc *sc; 796 struct wsdisplay_cursor *p; 797 { 798 799 return (EPASSTHROUGH); /* XXX */ 800 } 801 802 static void 803 set_curpos(sc, curpos) 804 struct sfb_softc *sc; 805 struct wsdisplay_curpos *curpos; 806 { 807 struct rasops_info *ri = sc->sc_ri; 808 int x = curpos->x, y = curpos->y; 809 810 if (y < 0) 811 y = 0; 812 else if (y > ri->ri_height); 813 y = ri->ri_height; 814 if (x < 0) 815 x = 0; 816 else if (x > ri->ri_width); 817 x = ri->ri_width; 818 sc->sc_cursor.cc_pos.x = x; 819 sc->sc_cursor.cc_pos.y = y; 820 } 821 822 #define MODE_SIMPLE 0 823 #define MODE_OPAQUESTIPPLE 1 824 #define MODE_OPAQUELINE 2 825 #define MODE_TRANSPARENTSTIPPLE 5 826 #define MODE_TRANSPARENTLINE 6 827 #define MODE_COPY 7 828 829 /* parameters for 8bpp configuration */ 830 #define SFBALIGNMASK 0x7 831 #define SFBSTIPPLEALL1 0xffffffff 832 #define SFBSTIPPLEBITS 32 833 #define SFBSTIPPLEBITMASK 0x1f 834 #define SFBSTIPPLEBYTESDONE 32 835 #define SFBCOPYALL1 0xffffffff 836 #define SFBCOPYBITS 32 837 #define SFBCOPYBITMASK 0x1f 838 #define SFBCOPYBYTESDONE 32 839 840 #if defined(pmax) 841 #define WRITE_MB() 842 #define BUMP(p) (p) 843 #endif 844 845 #if defined(alpha) 846 #define WRITE_MB() tc_wmb() 847 /* SFB registers replicated in 128B stride; cycle after eight iterations */ 848 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x80) & ~0x400)) 849 #endif 850 851 #define SFBMODE(p, v) \ 852 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v)) 853 #define SFBROP(p, v) \ 854 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v)) 855 #define SFBPLANEMASK(p, v) \ 856 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v)) 857 #define SFBPIXELMASK(p, v) \ 858 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v)) 859 #define SFBADDRESS(p, v) \ 860 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v)) 861 #define SFBSTART(p, v) \ 862 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v)) 863 #define SFBPIXELSHIFT(p, v) \ 864 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v)) 865 #define SFBFG(p, v) \ 866 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v)) 867 #define SFBBG(p, v) \ 868 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v)) 869 870 /* 871 * Paint the cursor. 872 */ 873 static void 874 sfb_do_cursor(ri) 875 struct rasops_info *ri; 876 { 877 caddr_t sfb, p; 878 int scanspan, height, width, align, x, y; 879 u_int32_t lmask, rmask; 880 881 x = ri->ri_ccol * ri->ri_font->fontwidth; 882 y = ri->ri_crow * ri->ri_font->fontheight; 883 scanspan = ri->ri_stride; 884 height = ri->ri_font->fontheight; 885 886 p = ri->ri_bits + y * scanspan + x; 887 align = (long)p & SFBALIGNMASK; 888 p -= align; 889 width = ri->ri_font->fontwidth + align; 890 lmask = SFBSTIPPLEALL1 << align; 891 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 892 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 893 894 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 895 SFBPLANEMASK(sfb, ~0); 896 SFBROP(sfb, 6); /* ROP_XOR */ 897 SFBFG(sfb, ~0); 898 899 lmask = lmask & rmask; 900 while (height > 0) { 901 SFBADDRESS(sfb, (long)p); 902 SFBSTART(sfb, lmask); 903 p += scanspan; 904 height--; 905 } 906 SFBMODE(sfb, MODE_SIMPLE); 907 SFBROP(sfb, 3); /* ROP_COPY */ 908 } 909 910 /* 911 * Paint a character. 912 */ 913 static void 914 sfb_putchar(id, row, col, uc, attr) 915 void *id; 916 int row, col; 917 u_int uc; 918 long attr; 919 { 920 struct rasops_info *ri = id; 921 caddr_t sfb, p; 922 int scanspan, height, width, align, x, y; 923 u_int32_t lmask, rmask, glyph; 924 u_int8_t *g; 925 926 x = col * ri->ri_font->fontwidth; 927 y = row * ri->ri_font->fontheight; 928 scanspan = ri->ri_stride; 929 height = ri->ri_font->fontheight; 930 uc -= ri->ri_font->firstchar; 931 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 932 933 p = ri->ri_bits + y * scanspan + x; 934 align = (long)p & SFBALIGNMASK; 935 p -= align; 936 width = ri->ri_font->fontwidth + align; 937 lmask = SFBSTIPPLEALL1 << align; 938 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 939 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 940 941 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 942 SFBPLANEMASK(sfb, ~0); 943 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]); 944 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 945 946 /* XXX 2B stride fonts only XXX */ 947 lmask = lmask & rmask; 948 while (height > 0) { 949 glyph = *(u_int16_t *)g; /* XXX */ 950 SFBPIXELMASK(sfb, lmask); 951 SFBADDRESS(sfb, (long)p); 952 SFBSTART(sfb, glyph << align); 953 p += scanspan; 954 g += 2; /* XXX */ 955 height--; 956 } 957 if (attr & 1 /* UNDERLINE */) { 958 p -= scanspan * 2; 959 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 960 SFBADDRESS(sfb, (long)p); 961 SFBSTART(sfb, lmask); 962 } 963 964 SFBMODE(sfb, MODE_SIMPLE); 965 SFBPIXELMASK(sfb, ~0); /* entire pixel */ 966 } 967 968 #if 0 969 /* 970 * Copy characters in a line. 971 */ 972 static void 973 sfb_copycols(id, row, srccol, dstcol, ncols) 974 void *id; 975 int row, srccol, dstcol, ncols; 976 { 977 struct rasops_info *ri = id; 978 caddr_t sp, dp, basex, sfb; 979 int scanspan, height, width, aligns, alignd, shift, w, y; 980 u_int32_t lmaskd, rmaskd; 981 982 scanspan = ri->ri_stride; 983 y = row * ri->ri_font->fontheight; 984 basex = ri->ri_bits + y * scanspan; 985 height = ri->ri_font->fontheight; 986 w = ri->ri_font->fontwidth * ncols; 987 988 sp = basex + ri->ri_font->fontwidth * srccol; 989 aligns = (long)sp & SFBALIGNMASK; 990 dp = basex + ri->ri_font->fontwidth * dstcol; 991 alignd = (long)dp & SFBALIGNMASK; 992 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 993 994 SFBMODE(sfb, MODE_COPY); 995 SFBPLANEMASK(sfb, ~0); 996 /* small enough to fit in a single 32bit */ 997 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) { 998 SFBPIXELSHIFT(sfb, alignd - aligns); 999 lmaskd = SFBCOPYALL1 << alignd; 1000 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK); 1001 lmaskd = lmaskd & rmaskd; 1002 sp -= aligns; 1003 dp -= alignd; 1004 while (height > 0) { 1005 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1006 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1007 sp += scanspan; 1008 dp += scanspan; 1009 height--; 1010 } 1011 } 1012 /* copy forward (left-to-right) */ 1013 else if (dstcol < srccol || srccol + ncols < dstcol) { 1014 caddr_t sq, dq; 1015 1016 shift = alignd - aligns; 1017 if (shift < 0) { 1018 shift = 8 + shift; /* enforce right rotate */ 1019 alignd += 8; /* bearing on left edge */ 1020 } 1021 width = alignd + w; 1022 lmaskd = SFBCOPYALL1 << alignd; 1023 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1024 sp -= aligns; 1025 dp -= alignd; 1026 1027 SFBPIXELSHIFT(sfb, shift); 1028 w = width; 1029 sq = sp; 1030 dq = dp; 1031 while (height > 0) { 1032 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1033 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1034 width -= 2 * SFBCOPYBITS; 1035 while (width > 0) { 1036 sp += SFBCOPYBYTESDONE; 1037 dp += SFBCOPYBYTESDONE; 1038 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1039 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB(); 1040 width -= SFBCOPYBITS; 1041 } 1042 sp += SFBCOPYBYTESDONE; 1043 dp += SFBCOPYBYTESDONE; 1044 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1045 *(u_int32_t *)dp = rmaskd; WRITE_MB(); 1046 sp = (sq += scanspan); 1047 dp = (dq += scanspan); 1048 width = w; 1049 height--; 1050 } 1051 } 1052 /* copy backward (right-to-left) */ 1053 else { 1054 caddr_t sq, dq; 1055 1056 shift = alignd - aligns; 1057 if (shift > 0) { 1058 shift = shift - 8; /* force left rotate */ 1059 alignd += 24; 1060 } 1061 width = alignd + w; 1062 lmaskd = SFBCOPYALL1 << alignd; 1063 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1064 sp -= aligns; 1065 dp -= alignd; 1066 1067 SFBPIXELSHIFT(sfb, shift); 1068 w = width; 1069 sq = sp += (((aligns + w) - 1) & ~31); 1070 dq = dp += (((alignd + w) - 1) & ~31); 1071 while (height > 0) { 1072 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1073 *(u_int32_t *)dp = rmaskd; WRITE_MB(); 1074 width -= 2 * SFBCOPYBITS; 1075 while (width > 0) { 1076 sp -= SFBCOPYBYTESDONE; 1077 dp -= SFBCOPYBYTESDONE; 1078 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1079 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB(); 1080 width -= SFBCOPYBITS; 1081 } 1082 sp -= SFBCOPYBYTESDONE; 1083 dp -= SFBCOPYBYTESDONE; 1084 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1085 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1086 1087 sp = (sq += scanspan); 1088 dp = (dq += scanspan); 1089 width = w; 1090 height--; 1091 } 1092 } 1093 SFBMODE(sfb, MODE_SIMPLE); 1094 SFBPIXELSHIFT(sfb, 0); 1095 } 1096 #endif 1097 1098 /* 1099 * Clear characters in a line. 1100 */ 1101 static void 1102 sfb_erasecols(id, row, startcol, ncols, attr) 1103 void *id; 1104 int row, startcol, ncols; 1105 long attr; 1106 { 1107 struct rasops_info *ri = id; 1108 caddr_t sfb, p; 1109 int scanspan, startx, height, width, align, w, y; 1110 u_int32_t lmask, rmask; 1111 1112 scanspan = ri->ri_stride; 1113 y = row * ri->ri_font->fontheight; 1114 startx = startcol * ri->ri_font->fontwidth; 1115 height = ri->ri_font->fontheight; 1116 w = ri->ri_font->fontwidth * ncols; 1117 1118 p = ri->ri_bits + y * scanspan + startx; 1119 align = (long)p & SFBALIGNMASK; 1120 p -= align; 1121 width = w + align; 1122 lmask = SFBSTIPPLEALL1 << align; 1123 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1124 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1125 1126 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1127 SFBPLANEMASK(sfb, ~0); 1128 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1129 if (width <= SFBSTIPPLEBITS) { 1130 lmask = lmask & rmask; 1131 while (height > 0) { 1132 SFBADDRESS(sfb, (long)p); 1133 SFBSTART(sfb, lmask); 1134 p += scanspan; 1135 height--; 1136 } 1137 } 1138 else { 1139 caddr_t q = p; 1140 while (height > 0) { 1141 *(u_int32_t *)p = lmask; 1142 WRITE_MB(); 1143 width -= 2 * SFBSTIPPLEBITS; 1144 while (width > 0) { 1145 p += SFBSTIPPLEBYTESDONE; 1146 *(u_int32_t *)p = SFBSTIPPLEALL1; 1147 WRITE_MB(); 1148 width -= SFBSTIPPLEBITS; 1149 } 1150 p += SFBSTIPPLEBYTESDONE; 1151 *(u_int32_t *)p = rmask; 1152 WRITE_MB(); 1153 1154 p = (q += scanspan); 1155 width = w + align; 1156 height--; 1157 } 1158 } 1159 SFBMODE(sfb, MODE_SIMPLE); 1160 } 1161 1162 /* 1163 * Copy lines. 1164 */ 1165 static void 1166 sfb_copyrows(id, srcrow, dstrow, nrows) 1167 void *id; 1168 int srcrow, dstrow, nrows; 1169 { 1170 struct rasops_info *ri = id; 1171 caddr_t sfb, p; 1172 int scanspan, offset, srcy, height, width, align, w; 1173 u_int32_t lmask, rmask; 1174 1175 scanspan = ri->ri_stride; 1176 height = ri->ri_font->fontheight * nrows; 1177 offset = (dstrow - srcrow) * ri->ri_yscale; 1178 srcy = ri->ri_font->fontheight * srcrow; 1179 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1180 scanspan = -scanspan; 1181 srcy += height; 1182 } 1183 1184 p = ri->ri_bits + srcy * ri->ri_stride; 1185 align = (long)p & SFBALIGNMASK; 1186 p -= align; 1187 w = ri->ri_emuwidth; 1188 width = w + align; 1189 lmask = SFBCOPYALL1 << align; 1190 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1191 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1192 1193 SFBMODE(sfb, MODE_COPY); 1194 SFBPLANEMASK(sfb, ~0); 1195 SFBPIXELSHIFT(sfb, 0); 1196 if (width <= SFBCOPYBITS) { 1197 /* never happens */; 1198 } 1199 else { 1200 caddr_t q = p; 1201 while (height > 0) { 1202 *(u_int32_t *)p = lmask; 1203 *(u_int32_t *)(p + offset) = lmask; 1204 width -= 2 * SFBCOPYBITS; 1205 while (width > 0) { 1206 p += SFBCOPYBYTESDONE; 1207 *(u_int32_t *)p = SFBCOPYALL1; 1208 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1209 width -= SFBCOPYBITS; 1210 } 1211 p += SFBCOPYBYTESDONE; 1212 *(u_int32_t *)p = rmask; 1213 *(u_int32_t *)(p + offset) = rmask; 1214 1215 p = (q += scanspan); 1216 width = w + align; 1217 height--; 1218 } 1219 } 1220 SFBMODE(sfb, MODE_SIMPLE); 1221 } 1222 1223 /* 1224 * Erase lines. 1225 */ 1226 void 1227 sfb_eraserows(id, startrow, nrows, attr) 1228 void *id; 1229 int startrow, nrows; 1230 long attr; 1231 { 1232 struct rasops_info *ri = id; 1233 caddr_t sfb, p; 1234 int scanspan, starty, height, width, align, w; 1235 u_int32_t lmask, rmask; 1236 1237 scanspan = ri->ri_stride; 1238 starty = ri->ri_font->fontheight * startrow; 1239 height = ri->ri_font->fontheight * nrows; 1240 1241 p = ri->ri_bits + starty * scanspan; 1242 align = (long)p & SFBALIGNMASK; 1243 p -= align; 1244 w = ri->ri_emuwidth; 1245 width = w + align; 1246 lmask = SFBSTIPPLEALL1 << align; 1247 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1248 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1249 1250 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1251 SFBPLANEMASK(sfb, ~0); 1252 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1253 if (width <= SFBSTIPPLEBITS) { 1254 /* never happens */; 1255 } 1256 else { 1257 caddr_t q = p; 1258 while (height > 0) { 1259 *(u_int32_t *)p = lmask; 1260 WRITE_MB(); 1261 width -= 2 * SFBSTIPPLEBITS; 1262 while (width > 0) { 1263 p += SFBSTIPPLEBYTESDONE; 1264 *(u_int32_t *)p = SFBSTIPPLEALL1; 1265 WRITE_MB(); 1266 width -= SFBSTIPPLEBITS; 1267 } 1268 p += SFBSTIPPLEBYTESDONE; 1269 *(u_int32_t *)p = rmask; 1270 WRITE_MB(); 1271 1272 p = (q += scanspan); 1273 width = w + align; 1274 height--; 1275 } 1276 } 1277 SFBMODE(sfb, MODE_SIMPLE); 1278 } 1279