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