1 /* $NetBSD: sfb.c,v 1.57 2002/10/02 16:53:05 thorpej 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.57 2002/10/02 16:53:05 thorpej 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 CFATTACH_DECL(sfb, sizeof(struct sfb_softc), 139 sfbmatch, sfbattach, NULL, NULL); 140 141 static void sfb_common_init __P((struct rasops_info *)); 142 static struct rasops_info sfb_console_ri; 143 static tc_addr_t sfb_consaddr; 144 145 static void sfb_putchar __P((void *, int, int, u_int, long)); 146 static void sfb_erasecols __P((void *, int, int, int, long)); 147 static void sfb_eraserows __P((void *, int, int, long)); 148 static void sfb_copyrows __P((void *, int, int, int)); 149 static void sfb_do_cursor __P((struct rasops_info *)); 150 #if 0 151 static void sfb_copycols __P((void *, int, int, int, int)); 152 #endif 153 154 static struct wsscreen_descr sfb_stdscreen = { 155 "std", 0, 0, 156 0, /* textops */ 157 0, 0, 158 WSSCREEN_REVERSE 159 }; 160 161 static const struct wsscreen_descr *_sfb_scrlist[] = { 162 &sfb_stdscreen, 163 }; 164 165 static const struct wsscreen_list sfb_screenlist = { 166 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist 167 }; 168 169 static int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *)); 170 static paddr_t sfbmmap __P((void *, off_t, int)); 171 172 static int sfb_alloc_screen __P((void *, const struct wsscreen_descr *, 173 void **, int *, int *, long *)); 174 static void sfb_free_screen __P((void *, void *)); 175 static int sfb_show_screen __P((void *, void *, int, 176 void (*) (void *, int, int), void *)); 177 178 static const struct wsdisplay_accessops sfb_accessops = { 179 sfbioctl, 180 sfbmmap, 181 sfb_alloc_screen, 182 sfb_free_screen, 183 sfb_show_screen, 184 0 /* load_font */ 185 }; 186 187 int sfb_cnattach __P((tc_addr_t)); 188 static int sfbintr __P((void *)); 189 static void sfbhwinit __P((caddr_t)); 190 191 static int get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *)); 192 static int set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *)); 193 static int set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *)); 194 static int get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *)); 195 static void set_curpos __P((struct sfb_softc *, struct wsdisplay_curpos *)); 196 197 /* 198 * Compose 2 bit/pixel cursor image. Bit order will be reversed. 199 * M M M M I I I I M I M I M I M I 200 * [ before ] [ after ] 201 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3 202 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7 203 */ 204 static const u_int8_t shuffle[256] = { 205 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 206 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 207 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4, 208 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5, 209 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74, 210 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75, 211 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4, 212 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5, 213 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c, 214 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d, 215 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc, 216 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd, 217 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c, 218 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d, 219 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc, 220 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd, 221 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56, 222 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57, 223 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6, 224 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7, 225 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76, 226 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77, 227 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6, 228 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7, 229 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e, 230 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f, 231 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde, 232 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf, 233 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e, 234 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f, 235 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe, 236 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff, 237 }; 238 239 static int 240 sfbmatch(parent, match, aux) 241 struct device *parent; 242 struct cfdata *match; 243 void *aux; 244 { 245 struct tc_attach_args *ta = aux; 246 247 if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0) 248 return (0); 249 return (1); 250 } 251 252 static void 253 sfbattach(parent, self, aux) 254 struct device *parent, *self; 255 void *aux; 256 { 257 struct sfb_softc *sc = (struct sfb_softc *)self; 258 struct tc_attach_args *ta = aux; 259 struct rasops_info *ri; 260 struct wsemuldisplaydev_attach_args waa; 261 struct hwcmap256 *cm; 262 const u_int8_t *p; 263 caddr_t asic; 264 int console, index; 265 266 console = (ta->ta_addr == sfb_consaddr); 267 if (console) { 268 sc->sc_ri = ri = &sfb_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 sfb_common_init(ri); 282 sc->sc_ri = ri; 283 } 284 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth); 285 286 cm = &sc->sc_cmap; 287 p = rasops_cmap; 288 for (index = 0; index < CMAP_SIZE; index++, p += 3) { 289 cm->r[index] = p[0]; 290 cm->g[index] = p[1]; 291 cm->b[index] = p[2]; 292 } 293 294 sc->sc_vaddr = ta->ta_addr; 295 sc->sc_cursor.cc_magic.x = HX_MAGIC_X; 296 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y; 297 sc->sc_blanked = sc->sc_curenb = 0; 298 299 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc); 300 301 asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 302 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 303 *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; 304 305 waa.console = console; 306 waa.scrdata = &sfb_screenlist; 307 waa.accessops = &sfb_accessops; 308 waa.accesscookie = sc; 309 310 config_found(self, &waa, wsemuldisplaydevprint); 311 } 312 313 static void 314 sfb_common_init(ri) 315 struct rasops_info *ri; 316 { 317 caddr_t base, asic; 318 int hsetup, vsetup, vbase, cookie; 319 320 base = (caddr_t)ri->ri_hw; 321 asic = base + SFB_ASIC_OFFSET; 322 hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP); 323 vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP); 324 325 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1; 326 *(u_int32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0; 327 *(u_int32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0; 328 *(u_int32_t *)(asic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */ 329 *(u_int32_t *)(asic + SFB_ASIC_ROP) = 3; /* ROP_COPY */ 330 *(u_int32_t *)(asic + 0x180000) = 0; /* Bt459 reset */ 331 332 /* initialize colormap and cursor hardware */ 333 sfbhwinit(base); 334 335 ri->ri_flg = RI_CENTER; 336 ri->ri_depth = 8; 337 ri->ri_width = (hsetup & 0x1ff) << 2; 338 ri->ri_height = (vsetup & 0x7ff); 339 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8); 340 ri->ri_bits = base + SFB_FB_OFFSET + vbase * 4096; 341 342 /* clear the screen */ 343 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 344 345 wsfont_init(); 346 /* prefer 12 pixel wide font */ 347 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L, 348 WSDISPLAY_FONTORDER_L2R); 349 if (cookie <= 0) 350 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, 351 WSDISPLAY_FONTORDER_L2R); 352 if (cookie <= 0) { 353 printf("sfb: font table is empty\n"); 354 return; 355 } 356 357 /* the accelerated sfb_putchar() needs LSbit left */ 358 if (wsfont_lock(cookie, &ri->ri_font)) { 359 printf("sfb: couldn't lock font\n"); 360 return; 361 } 362 ri->ri_wsfcookie = cookie; 363 364 rasops_init(ri, 34, 80); 365 366 /* add our accelerated functions */ 367 ri->ri_ops.putchar = sfb_putchar; 368 ri->ri_ops.erasecols = sfb_erasecols; 369 ri->ri_ops.copyrows = sfb_copyrows; 370 ri->ri_ops.eraserows = sfb_eraserows; 371 ri->ri_do_cursor = sfb_do_cursor; 372 373 /* XXX shouldn't be global */ 374 sfb_stdscreen.nrows = ri->ri_rows; 375 sfb_stdscreen.ncols = ri->ri_cols; 376 sfb_stdscreen.textops = &ri->ri_ops; 377 sfb_stdscreen.capabilities = ri->ri_caps; 378 } 379 380 static int 381 sfbioctl(v, cmd, data, flag, p) 382 void *v; 383 u_long cmd; 384 caddr_t data; 385 int flag; 386 struct proc *p; 387 { 388 struct sfb_softc *sc = v; 389 struct rasops_info *ri = sc->sc_ri; 390 int turnoff; 391 392 switch (cmd) { 393 case WSDISPLAYIO_GTYPE: 394 *(u_int *)data = WSDISPLAY_TYPE_SFB; 395 return (0); 396 397 case WSDISPLAYIO_GINFO: 398 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 399 wsd_fbip->height = ri->ri_height; 400 wsd_fbip->width = ri->ri_width; 401 wsd_fbip->depth = ri->ri_depth; 402 wsd_fbip->cmsize = CMAP_SIZE; 403 #undef fbt 404 return (0); 405 406 case WSDISPLAYIO_GETCMAP: 407 return get_cmap(sc, (struct wsdisplay_cmap *)data); 408 409 case WSDISPLAYIO_PUTCMAP: 410 return set_cmap(sc, (struct wsdisplay_cmap *)data); 411 412 case WSDISPLAYIO_SVIDEO: 413 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 414 if (sc->sc_blanked ^ turnoff) { 415 caddr_t asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 416 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VALID) 417 = !turnoff; 418 tc_wmb(); 419 sc->sc_blanked = turnoff; 420 } 421 return (0); 422 423 case WSDISPLAYIO_GVIDEO: 424 *(u_int *)data = sc->sc_blanked ? 425 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 426 return (0); 427 428 case WSDISPLAYIO_GCURPOS: 429 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 430 return (0); 431 432 case WSDISPLAYIO_SCURPOS: 433 set_curpos(sc, (struct wsdisplay_curpos *)data); 434 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 435 return (0); 436 437 case WSDISPLAYIO_GCURMAX: 438 ((struct wsdisplay_curpos *)data)->x = 439 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 440 return (0); 441 442 case WSDISPLAYIO_GCURSOR: 443 return get_cursor(sc, (struct wsdisplay_cursor *)data); 444 445 case WSDISPLAYIO_SCURSOR: 446 return set_cursor(sc, (struct wsdisplay_cursor *)data); 447 } 448 return (EPASSTHROUGH); 449 } 450 451 static paddr_t 452 sfbmmap(v, offset, prot) 453 void *v; 454 off_t offset; 455 int prot; 456 { 457 struct sfb_softc *sc = v; 458 459 if (offset >= SFB_SIZE || offset < 0) 460 return (-1); 461 return machine_btop(sc->sc_vaddr + offset); 462 } 463 464 static int 465 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 466 void *v; 467 const struct wsscreen_descr *type; 468 void **cookiep; 469 int *curxp, *curyp; 470 long *attrp; 471 { 472 struct sfb_softc *sc = v; 473 struct rasops_info *ri = sc->sc_ri; 474 long defattr; 475 476 if (sc->nscreens > 0) 477 return (ENOMEM); 478 479 *cookiep = ri; /* one and only for now */ 480 *curxp = 0; 481 *curyp = 0; 482 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 483 *attrp = defattr; 484 sc->nscreens++; 485 return (0); 486 } 487 488 static void 489 sfb_free_screen(v, cookie) 490 void *v; 491 void *cookie; 492 { 493 struct sfb_softc *sc = v; 494 495 if (sc->sc_ri == &sfb_console_ri) 496 panic("sfb_free_screen: console"); 497 498 sc->nscreens--; 499 } 500 501 static int 502 sfb_show_screen(v, cookie, waitok, cb, cbarg) 503 void *v; 504 void *cookie; 505 int waitok; 506 void (*cb) __P((void *, int, int)); 507 void *cbarg; 508 { 509 510 return (0); 511 } 512 513 /* EXPORT */ int 514 sfb_cnattach(addr) 515 tc_addr_t addr; 516 { 517 struct rasops_info *ri; 518 long defattr; 519 520 ri = &sfb_console_ri; 521 ri->ri_hw = (void *)addr; 522 sfb_common_init(ri); 523 (*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr); 524 wsdisplay_cnattach(&sfb_stdscreen, ri, 0, 0, defattr); 525 sfb_consaddr = addr; 526 return (0); 527 } 528 529 static int 530 sfbintr(arg) 531 void *arg; 532 { 533 struct sfb_softc *sc = arg; 534 caddr_t base, asic, vdac; 535 int v; 536 537 base = (caddr_t)sc->sc_ri->ri_hw; 538 asic = base + SFB_ASIC_OFFSET; 539 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 540 /* *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; */ 541 542 if (sc->sc_changed == 0) 543 goto done; 544 545 vdac = base + SFB_RAMDAC_OFFSET; 546 v = sc->sc_changed; 547 if (v & WSDISPLAY_CURSOR_DOCUR) { 548 SELECT(vdac, BT459_IREG_CCR); 549 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00; 550 } 551 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 552 int x, y; 553 554 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 555 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 556 x += sc->sc_cursor.cc_magic.x; 557 y += sc->sc_cursor.cc_magic.y; 558 559 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 560 REG(vdac, bt_reg) = x; tc_wmb(); 561 REG(vdac, bt_reg) = x >> 8; tc_wmb(); 562 REG(vdac, bt_reg) = y; tc_wmb(); 563 REG(vdac, bt_reg) = y >> 8; tc_wmb(); 564 } 565 if (v & WSDISPLAY_CURSOR_DOCMAP) { 566 u_int8_t *cp = sc->sc_cursor.cc_color; 567 568 SELECT(vdac, BT459_IREG_CCOLOR_2); 569 REG(vdac, bt_reg) = cp[1]; tc_wmb(); 570 REG(vdac, bt_reg) = cp[3]; tc_wmb(); 571 REG(vdac, bt_reg) = cp[5]; tc_wmb(); 572 573 REG(vdac, bt_reg) = cp[0]; tc_wmb(); 574 REG(vdac, bt_reg) = cp[2]; tc_wmb(); 575 REG(vdac, bt_reg) = cp[4]; tc_wmb(); 576 } 577 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 578 u_int8_t *ip, *mp, img, msk; 579 u_int8_t u; 580 int bcnt; 581 582 ip = (u_int8_t *)sc->sc_cursor.cc_image; 583 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE); 584 585 bcnt = 0; 586 SELECT(vdac, BT459_IREG_CRAM_BASE+0); 587 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 588 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 589 /* pad right half 32 pixel when smaller than 33 */ 590 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 591 REG(vdac, bt_reg) = 0; tc_wmb(); 592 REG(vdac, bt_reg) = 0; tc_wmb(); 593 } 594 else { 595 img = *ip++; 596 msk = *mp++; 597 img &= msk; /* cookie off image */ 598 u = (msk & 0x0f) << 4 | (img & 0x0f); 599 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 600 u = (msk & 0xf0) | (img & 0xf0) >> 4; 601 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 602 } 603 bcnt += 2; 604 } 605 /* pad unoccupied scan lines */ 606 while (bcnt < CURSOR_MAX_SIZE * 16) { 607 REG(vdac, bt_reg) = 0; tc_wmb(); 608 REG(vdac, bt_reg) = 0; tc_wmb(); 609 bcnt += 2; 610 } 611 } 612 if (v & WSDISPLAY_CMAP_DOLUT) { 613 struct hwcmap256 *cm = &sc->sc_cmap; 614 int index; 615 616 SELECT(vdac, 0); 617 for (index = 0; index < CMAP_SIZE; index++) { 618 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb(); 619 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb(); 620 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb(); 621 } 622 } 623 sc->sc_changed = 0; 624 done: 625 return (1); 626 } 627 628 static void 629 sfbhwinit(base) 630 caddr_t base; 631 { 632 caddr_t vdac = base + SFB_RAMDAC_OFFSET; 633 const u_int8_t *p; 634 int i; 635 636 SELECT(vdac, BT459_IREG_COMMAND_0); 637 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb(); 638 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb(); 639 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb(); 640 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb(); 641 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb(); 642 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb(); 643 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb(); 644 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb(); 645 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb(); 646 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb(); 647 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb(); 648 649 SELECT(vdac, BT459_IREG_CCR); 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 REG(vdac, bt_reg) = 0x0; tc_wmb(); 663 664 /* build sane colormap */ 665 SELECT(vdac, 0); 666 p = rasops_cmap; 667 for (i = 0; i < CMAP_SIZE; i++, p += 3) { 668 REG(vdac, bt_cmap) = p[0]; tc_wmb(); 669 REG(vdac, bt_cmap) = p[1]; tc_wmb(); 670 REG(vdac, bt_cmap) = p[2]; tc_wmb(); 671 } 672 673 /* clear out cursor image */ 674 SELECT(vdac, BT459_IREG_CRAM_BASE); 675 for (i = 0; i < 1024; i++) 676 REG(vdac, bt_reg) = 0xff; tc_wmb(); 677 678 /* 679 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 680 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 681 * image color. CCOLOR_1 will be never used. 682 */ 683 SELECT(vdac, BT459_IREG_CCOLOR_1); 684 REG(vdac, bt_reg) = 0xff; tc_wmb(); 685 REG(vdac, bt_reg) = 0xff; tc_wmb(); 686 REG(vdac, bt_reg) = 0xff; tc_wmb(); 687 688 REG(vdac, bt_reg) = 0; tc_wmb(); 689 REG(vdac, bt_reg) = 0; tc_wmb(); 690 REG(vdac, bt_reg) = 0; tc_wmb(); 691 692 REG(vdac, bt_reg) = 0xff; tc_wmb(); 693 REG(vdac, bt_reg) = 0xff; tc_wmb(); 694 REG(vdac, bt_reg) = 0xff; tc_wmb(); 695 } 696 697 static int 698 get_cmap(sc, p) 699 struct sfb_softc *sc; 700 struct wsdisplay_cmap *p; 701 { 702 u_int index = p->index, count = p->count; 703 704 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 705 return (EINVAL); 706 707 if (!uvm_useracc(p->red, count, B_WRITE) || 708 !uvm_useracc(p->green, count, B_WRITE) || 709 !uvm_useracc(p->blue, count, B_WRITE)) 710 return (EFAULT); 711 712 copyout(&sc->sc_cmap.r[index], p->red, count); 713 copyout(&sc->sc_cmap.g[index], p->green, count); 714 copyout(&sc->sc_cmap.b[index], p->blue, count); 715 716 return (0); 717 } 718 719 static int 720 set_cmap(sc, p) 721 struct sfb_softc *sc; 722 struct wsdisplay_cmap *p; 723 { 724 u_int index = p->index, count = p->count; 725 726 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 727 return (EINVAL); 728 729 if (!uvm_useracc(p->red, count, B_READ) || 730 !uvm_useracc(p->green, count, B_READ) || 731 !uvm_useracc(p->blue, count, B_READ)) 732 return (EFAULT); 733 734 copyin(p->red, &sc->sc_cmap.r[index], count); 735 copyin(p->green, &sc->sc_cmap.g[index], count); 736 copyin(p->blue, &sc->sc_cmap.b[index], count); 737 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 738 return (0); 739 } 740 741 static int 742 set_cursor(sc, p) 743 struct sfb_softc *sc; 744 struct wsdisplay_cursor *p; 745 { 746 #define cc (&sc->sc_cursor) 747 u_int v, index, count, icount; 748 749 v = p->which; 750 if (v & WSDISPLAY_CURSOR_DOCMAP) { 751 index = p->cmap.index; 752 count = p->cmap.count; 753 if (index >= 2 || (index + count) > 2) 754 return (EINVAL); 755 if (!uvm_useracc(p->cmap.red, count, B_READ) || 756 !uvm_useracc(p->cmap.green, count, B_READ) || 757 !uvm_useracc(p->cmap.blue, count, B_READ)) 758 return (EFAULT); 759 } 760 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 761 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 762 return (EINVAL); 763 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 764 if (!uvm_useracc(p->image, icount, B_READ) || 765 !uvm_useracc(p->mask, icount, B_READ)) 766 return (EFAULT); 767 } 768 769 if (v & WSDISPLAY_CURSOR_DOCUR) 770 sc->sc_curenb = p->enable; 771 if (v & WSDISPLAY_CURSOR_DOPOS) 772 set_curpos(sc, &p->pos); 773 if (v & WSDISPLAY_CURSOR_DOHOT) 774 cc->cc_hot = p->hot; 775 if (v & WSDISPLAY_CURSOR_DOCMAP) { 776 copyin(p->cmap.red, &cc->cc_color[index], count); 777 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 778 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 779 } 780 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 781 cc->cc_size = p->size; 782 memset(cc->cc_image, 0, sizeof cc->cc_image); 783 copyin(p->image, cc->cc_image, icount); 784 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount); 785 } 786 sc->sc_changed |= v; 787 788 return (0); 789 #undef cc 790 } 791 792 static int 793 get_cursor(sc, p) 794 struct sfb_softc *sc; 795 struct wsdisplay_cursor *p; 796 { 797 798 return (EPASSTHROUGH); /* XXX */ 799 } 800 801 static void 802 set_curpos(sc, curpos) 803 struct sfb_softc *sc; 804 struct wsdisplay_curpos *curpos; 805 { 806 struct rasops_info *ri = sc->sc_ri; 807 int x = curpos->x, y = curpos->y; 808 809 if (y < 0) 810 y = 0; 811 else if (y > ri->ri_height); 812 y = ri->ri_height; 813 if (x < 0) 814 x = 0; 815 else if (x > ri->ri_width); 816 x = ri->ri_width; 817 sc->sc_cursor.cc_pos.x = x; 818 sc->sc_cursor.cc_pos.y = y; 819 } 820 821 #define MODE_SIMPLE 0 822 #define MODE_OPAQUESTIPPLE 1 823 #define MODE_OPAQUELINE 2 824 #define MODE_TRANSPARENTSTIPPLE 5 825 #define MODE_TRANSPARENTLINE 6 826 #define MODE_COPY 7 827 828 /* parameters for 8bpp configuration */ 829 #define SFBALIGNMASK 0x7 830 #define SFBSTIPPLEALL1 0xffffffff 831 #define SFBSTIPPLEBITS 32 832 #define SFBSTIPPLEBITMASK 0x1f 833 #define SFBSTIPPLEBYTESDONE 32 834 #define SFBCOPYALL1 0xffffffff 835 #define SFBCOPYBITS 32 836 #define SFBCOPYBITMASK 0x1f 837 #define SFBCOPYBYTESDONE 32 838 839 #if defined(pmax) 840 #define WRITE_MB() 841 #define BUMP(p) (p) 842 #endif 843 844 #if defined(alpha) 845 #define WRITE_MB() tc_wmb() 846 /* SFB registers replicated in 128B stride; cycle after eight iterations */ 847 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x80) & ~0x400)) 848 #endif 849 850 #define SFBMODE(p, v) \ 851 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v)) 852 #define SFBROP(p, v) \ 853 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v)) 854 #define SFBPLANEMASK(p, v) \ 855 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v)) 856 #define SFBPIXELMASK(p, v) \ 857 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v)) 858 #define SFBADDRESS(p, v) \ 859 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v)) 860 #define SFBSTART(p, v) \ 861 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v)) 862 #define SFBPIXELSHIFT(p, v) \ 863 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v)) 864 #define SFBFG(p, v) \ 865 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v)) 866 #define SFBBG(p, v) \ 867 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v)) 868 869 /* 870 * Paint the cursor. 871 */ 872 static void 873 sfb_do_cursor(ri) 874 struct rasops_info *ri; 875 { 876 caddr_t sfb, p; 877 int scanspan, height, width, align, x, y; 878 u_int32_t lmask, rmask; 879 880 x = ri->ri_ccol * ri->ri_font->fontwidth; 881 y = ri->ri_crow * ri->ri_font->fontheight; 882 scanspan = ri->ri_stride; 883 height = ri->ri_font->fontheight; 884 885 p = ri->ri_bits + y * scanspan + x; 886 align = (long)p & SFBALIGNMASK; 887 p -= align; 888 width = ri->ri_font->fontwidth + align; 889 lmask = SFBSTIPPLEALL1 << align; 890 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 891 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 892 893 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 894 SFBPLANEMASK(sfb, ~0); 895 SFBROP(sfb, 6); /* ROP_XOR */ 896 SFBFG(sfb, ~0); 897 898 lmask = lmask & rmask; 899 while (height > 0) { 900 SFBADDRESS(sfb, (long)p); 901 SFBSTART(sfb, lmask); 902 p += scanspan; 903 height--; 904 } 905 SFBMODE(sfb, MODE_SIMPLE); 906 SFBROP(sfb, 3); /* ROP_COPY */ 907 } 908 909 /* 910 * Paint a character. 911 */ 912 static void 913 sfb_putchar(id, row, col, uc, attr) 914 void *id; 915 int row, col; 916 u_int uc; 917 long attr; 918 { 919 struct rasops_info *ri = id; 920 caddr_t sfb, p; 921 int scanspan, height, width, align, x, y; 922 u_int32_t lmask, rmask, glyph; 923 u_int8_t *g; 924 925 x = col * ri->ri_font->fontwidth; 926 y = row * ri->ri_font->fontheight; 927 scanspan = ri->ri_stride; 928 height = ri->ri_font->fontheight; 929 uc -= ri->ri_font->firstchar; 930 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 931 932 p = ri->ri_bits + y * scanspan + x; 933 align = (long)p & SFBALIGNMASK; 934 p -= align; 935 width = ri->ri_font->fontwidth + align; 936 lmask = SFBSTIPPLEALL1 << align; 937 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 938 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 939 940 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 941 SFBPLANEMASK(sfb, ~0); 942 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]); 943 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 944 945 /* XXX 2B stride fonts only XXX */ 946 lmask = lmask & rmask; 947 while (height > 0) { 948 glyph = *(u_int16_t *)g; /* XXX */ 949 SFBPIXELMASK(sfb, lmask); 950 SFBADDRESS(sfb, (long)p); 951 SFBSTART(sfb, glyph << align); 952 p += scanspan; 953 g += 2; /* XXX */ 954 height--; 955 } 956 if (attr & 1 /* UNDERLINE */) { 957 p -= scanspan * 2; 958 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 959 SFBADDRESS(sfb, (long)p); 960 SFBSTART(sfb, lmask); 961 } 962 963 SFBMODE(sfb, MODE_SIMPLE); 964 SFBPIXELMASK(sfb, ~0); /* entire pixel */ 965 } 966 967 #if 0 968 /* 969 * Copy characters in a line. 970 */ 971 static void 972 sfb_copycols(id, row, srccol, dstcol, ncols) 973 void *id; 974 int row, srccol, dstcol, ncols; 975 { 976 struct rasops_info *ri = id; 977 caddr_t sp, dp, basex, sfb; 978 int scanspan, height, width, aligns, alignd, shift, w, y; 979 u_int32_t lmaskd, rmaskd; 980 981 scanspan = ri->ri_stride; 982 y = row * ri->ri_font->fontheight; 983 basex = ri->ri_bits + y * scanspan; 984 height = ri->ri_font->fontheight; 985 w = ri->ri_font->fontwidth * ncols; 986 987 sp = basex + ri->ri_font->fontwidth * srccol; 988 aligns = (long)sp & SFBALIGNMASK; 989 dp = basex + ri->ri_font->fontwidth * dstcol; 990 alignd = (long)dp & SFBALIGNMASK; 991 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 992 993 SFBMODE(sfb, MODE_COPY); 994 SFBPLANEMASK(sfb, ~0); 995 /* small enough to fit in a single 32bit */ 996 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) { 997 SFBPIXELSHIFT(sfb, alignd - aligns); 998 lmaskd = SFBCOPYALL1 << alignd; 999 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK); 1000 lmaskd = lmaskd & rmaskd; 1001 sp -= aligns; 1002 dp -= alignd; 1003 while (height > 0) { 1004 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1005 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1006 sp += scanspan; 1007 dp += scanspan; 1008 height--; 1009 } 1010 } 1011 /* copy forward (left-to-right) */ 1012 else if (dstcol < srccol || srccol + ncols < dstcol) { 1013 caddr_t sq, dq; 1014 1015 shift = alignd - aligns; 1016 if (shift < 0) { 1017 shift = 8 + shift; /* enforce right rotate */ 1018 alignd += 8; /* bearing on left edge */ 1019 } 1020 width = alignd + w; 1021 lmaskd = SFBCOPYALL1 << alignd; 1022 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1023 sp -= aligns; 1024 dp -= alignd; 1025 1026 SFBPIXELSHIFT(sfb, shift); 1027 w = width; 1028 sq = sp; 1029 dq = dp; 1030 while (height > 0) { 1031 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1032 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1033 width -= 2 * SFBCOPYBITS; 1034 while (width > 0) { 1035 sp += SFBCOPYBYTESDONE; 1036 dp += SFBCOPYBYTESDONE; 1037 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1038 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB(); 1039 width -= SFBCOPYBITS; 1040 } 1041 sp += SFBCOPYBYTESDONE; 1042 dp += SFBCOPYBYTESDONE; 1043 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1044 *(u_int32_t *)dp = rmaskd; WRITE_MB(); 1045 sp = (sq += scanspan); 1046 dp = (dq += scanspan); 1047 width = w; 1048 height--; 1049 } 1050 } 1051 /* copy backward (right-to-left) */ 1052 else { 1053 caddr_t sq, dq; 1054 1055 shift = alignd - aligns; 1056 if (shift > 0) { 1057 shift = shift - 8; /* force left rotate */ 1058 alignd += 24; 1059 } 1060 width = alignd + w; 1061 lmaskd = SFBCOPYALL1 << alignd; 1062 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1063 sp -= aligns; 1064 dp -= alignd; 1065 1066 SFBPIXELSHIFT(sfb, shift); 1067 w = width; 1068 sq = sp += (((aligns + w) - 1) & ~31); 1069 dq = dp += (((alignd + w) - 1) & ~31); 1070 while (height > 0) { 1071 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1072 *(u_int32_t *)dp = rmaskd; WRITE_MB(); 1073 width -= 2 * SFBCOPYBITS; 1074 while (width > 0) { 1075 sp -= SFBCOPYBYTESDONE; 1076 dp -= SFBCOPYBYTESDONE; 1077 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1078 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB(); 1079 width -= SFBCOPYBITS; 1080 } 1081 sp -= SFBCOPYBYTESDONE; 1082 dp -= SFBCOPYBYTESDONE; 1083 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB(); 1084 *(u_int32_t *)dp = lmaskd; WRITE_MB(); 1085 1086 sp = (sq += scanspan); 1087 dp = (dq += scanspan); 1088 width = w; 1089 height--; 1090 } 1091 } 1092 SFBMODE(sfb, MODE_SIMPLE); 1093 SFBPIXELSHIFT(sfb, 0); 1094 } 1095 #endif 1096 1097 /* 1098 * Clear characters in a line. 1099 */ 1100 static void 1101 sfb_erasecols(id, row, startcol, ncols, attr) 1102 void *id; 1103 int row, startcol, ncols; 1104 long attr; 1105 { 1106 struct rasops_info *ri = id; 1107 caddr_t sfb, p; 1108 int scanspan, startx, height, width, align, w, y; 1109 u_int32_t lmask, rmask; 1110 1111 scanspan = ri->ri_stride; 1112 y = row * ri->ri_font->fontheight; 1113 startx = startcol * ri->ri_font->fontwidth; 1114 height = ri->ri_font->fontheight; 1115 w = ri->ri_font->fontwidth * ncols; 1116 1117 p = ri->ri_bits + y * scanspan + startx; 1118 align = (long)p & SFBALIGNMASK; 1119 p -= align; 1120 width = w + align; 1121 lmask = SFBSTIPPLEALL1 << align; 1122 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1123 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1124 1125 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1126 SFBPLANEMASK(sfb, ~0); 1127 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1128 if (width <= SFBSTIPPLEBITS) { 1129 lmask = lmask & rmask; 1130 while (height > 0) { 1131 SFBADDRESS(sfb, (long)p); 1132 SFBSTART(sfb, lmask); 1133 p += scanspan; 1134 height--; 1135 } 1136 } 1137 else { 1138 caddr_t q = p; 1139 while (height > 0) { 1140 *(u_int32_t *)p = lmask; 1141 WRITE_MB(); 1142 width -= 2 * SFBSTIPPLEBITS; 1143 while (width > 0) { 1144 p += SFBSTIPPLEBYTESDONE; 1145 *(u_int32_t *)p = SFBSTIPPLEALL1; 1146 WRITE_MB(); 1147 width -= SFBSTIPPLEBITS; 1148 } 1149 p += SFBSTIPPLEBYTESDONE; 1150 *(u_int32_t *)p = rmask; 1151 WRITE_MB(); 1152 1153 p = (q += scanspan); 1154 width = w + align; 1155 height--; 1156 } 1157 } 1158 SFBMODE(sfb, MODE_SIMPLE); 1159 } 1160 1161 /* 1162 * Copy lines. 1163 */ 1164 static void 1165 sfb_copyrows(id, srcrow, dstrow, nrows) 1166 void *id; 1167 int srcrow, dstrow, nrows; 1168 { 1169 struct rasops_info *ri = id; 1170 caddr_t sfb, p; 1171 int scanspan, offset, srcy, height, width, align, w; 1172 u_int32_t lmask, rmask; 1173 1174 scanspan = ri->ri_stride; 1175 height = ri->ri_font->fontheight * nrows; 1176 offset = (dstrow - srcrow) * ri->ri_yscale; 1177 srcy = ri->ri_font->fontheight * srcrow; 1178 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1179 scanspan = -scanspan; 1180 srcy += height; 1181 } 1182 1183 p = ri->ri_bits + srcy * ri->ri_stride; 1184 align = (long)p & SFBALIGNMASK; 1185 p -= align; 1186 w = ri->ri_emuwidth; 1187 width = w + align; 1188 lmask = SFBCOPYALL1 << align; 1189 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1190 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1191 1192 SFBMODE(sfb, MODE_COPY); 1193 SFBPLANEMASK(sfb, ~0); 1194 SFBPIXELSHIFT(sfb, 0); 1195 if (width <= SFBCOPYBITS) { 1196 /* never happens */; 1197 } 1198 else { 1199 caddr_t q = p; 1200 while (height > 0) { 1201 *(u_int32_t *)p = lmask; 1202 *(u_int32_t *)(p + offset) = lmask; 1203 width -= 2 * SFBCOPYBITS; 1204 while (width > 0) { 1205 p += SFBCOPYBYTESDONE; 1206 *(u_int32_t *)p = SFBCOPYALL1; 1207 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1208 width -= SFBCOPYBITS; 1209 } 1210 p += SFBCOPYBYTESDONE; 1211 *(u_int32_t *)p = rmask; 1212 *(u_int32_t *)(p + offset) = rmask; 1213 1214 p = (q += scanspan); 1215 width = w + align; 1216 height--; 1217 } 1218 } 1219 SFBMODE(sfb, MODE_SIMPLE); 1220 } 1221 1222 /* 1223 * Erase lines. 1224 */ 1225 void 1226 sfb_eraserows(id, startrow, nrows, attr) 1227 void *id; 1228 int startrow, nrows; 1229 long attr; 1230 { 1231 struct rasops_info *ri = id; 1232 caddr_t sfb, p; 1233 int scanspan, starty, height, width, align, w; 1234 u_int32_t lmask, rmask; 1235 1236 scanspan = ri->ri_stride; 1237 starty = ri->ri_font->fontheight * startrow; 1238 height = ri->ri_font->fontheight * nrows; 1239 1240 p = ri->ri_bits + starty * scanspan; 1241 align = (long)p & SFBALIGNMASK; 1242 p -= align; 1243 w = ri->ri_emuwidth; 1244 width = w + align; 1245 lmask = SFBSTIPPLEALL1 << align; 1246 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1247 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET; 1248 1249 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1250 SFBPLANEMASK(sfb, ~0); 1251 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1252 if (width <= SFBSTIPPLEBITS) { 1253 /* never happens */; 1254 } 1255 else { 1256 caddr_t q = p; 1257 while (height > 0) { 1258 *(u_int32_t *)p = lmask; 1259 WRITE_MB(); 1260 width -= 2 * SFBSTIPPLEBITS; 1261 while (width > 0) { 1262 p += SFBSTIPPLEBYTESDONE; 1263 *(u_int32_t *)p = SFBSTIPPLEALL1; 1264 WRITE_MB(); 1265 width -= SFBSTIPPLEBITS; 1266 } 1267 p += SFBSTIPPLEBYTESDONE; 1268 *(u_int32_t *)p = rmask; 1269 WRITE_MB(); 1270 1271 p = (q += scanspan); 1272 width = w + align; 1273 height--; 1274 } 1275 } 1276 SFBMODE(sfb, MODE_SIMPLE); 1277 } 1278