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