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