1 /* $NetBSD: sfb.c,v 1.37 2000/06/28 17:05:23 mrg 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.37 2000/06/28 17:05:23 mrg 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 caddr_t sfbasic; 356 int console; 357 358 console = (ta->ta_addr == sfb_consaddr); 359 if (console) { 360 sc->sc_dc = &sfb_console_dc; 361 sc->nscreens = 1; 362 } 363 else { 364 sc->sc_dc = (struct fb_devconfig *) 365 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK); 366 memset(sc->sc_dc, 0, sizeof(struct fb_devconfig)); 367 sfb_getdevconfig(ta->ta_addr, sc->sc_dc); 368 } 369 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, 370 sc->sc_dc->dc_depth); 371 372 memcpy(&sc->sc_cmap, rasops_cmap, sizeof(struct hwcmap256)); 373 374 sc->sc_cursor.cc_magic.x = HX_MAGIC_X; 375 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y; 376 377 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc); 378 379 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET); 380 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0; 381 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; 382 383 waa.console = console; 384 waa.scrdata = &sfb_screenlist; 385 waa.accessops = &sfb_accessops; 386 waa.accesscookie = sc; 387 388 config_found(self, &waa, wsemuldisplaydevprint); 389 } 390 391 static int 392 sfbioctl(v, cmd, data, flag, p) 393 void *v; 394 u_long cmd; 395 caddr_t data; 396 int flag; 397 struct proc *p; 398 { 399 struct sfb_softc *sc = v; 400 struct fb_devconfig *dc = sc->sc_dc; 401 int turnoff; 402 403 switch (cmd) { 404 case WSDISPLAYIO_GTYPE: 405 *(u_int *)data = WSDISPLAY_TYPE_SFB; 406 return (0); 407 408 case WSDISPLAYIO_GINFO: 409 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 410 wsd_fbip->height = sc->sc_dc->dc_ht; 411 wsd_fbip->width = sc->sc_dc->dc_wid; 412 wsd_fbip->depth = sc->sc_dc->dc_depth; 413 wsd_fbip->cmsize = CMAP_SIZE; 414 #undef fbt 415 return (0); 416 417 case WSDISPLAYIO_GETCMAP: 418 return get_cmap(sc, (struct wsdisplay_cmap *)data); 419 420 case WSDISPLAYIO_PUTCMAP: 421 return set_cmap(sc, (struct wsdisplay_cmap *)data); 422 423 case WSDISPLAYIO_SVIDEO: 424 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 425 if ((dc->dc_blanked == 0) ^ turnoff) { 426 dc->dc_blanked = turnoff; 427 #if 0 /* XXX later XXX */ 428 To turn off, assign value 0 in ASIC_VIDEO_VALID register. 429 #endif /* XXX XXX XXX */ 430 } 431 return (0); 432 433 case WSDISPLAYIO_GVIDEO: 434 *(u_int *)data = dc->dc_blanked ? 435 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 436 return (0); 437 438 case WSDISPLAYIO_GCURPOS: 439 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 440 return (0); 441 442 case WSDISPLAYIO_SCURPOS: 443 set_curpos(sc, (struct wsdisplay_curpos *)data); 444 bt459_set_curpos(sc); 445 return (0); 446 447 case WSDISPLAYIO_GCURMAX: 448 ((struct wsdisplay_curpos *)data)->x = 449 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 450 return (0); 451 452 case WSDISPLAYIO_GCURSOR: 453 return get_cursor(sc, (struct wsdisplay_cursor *)data); 454 455 case WSDISPLAYIO_SCURSOR: 456 return set_cursor(sc, (struct wsdisplay_cursor *)data); 457 } 458 return ENOTTY; 459 } 460 461 static paddr_t 462 sfbmmap(v, offset, prot) 463 void *v; 464 off_t offset; 465 int prot; 466 { 467 struct sfb_softc *sc = v; 468 469 if (offset >= SFB_SIZE || offset < 0) 470 return (-1); 471 return machine_btop(sc->sc_dc->dc_paddr + offset); 472 } 473 474 static int 475 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 476 void *v; 477 const struct wsscreen_descr *type; 478 void **cookiep; 479 int *curxp, *curyp; 480 long *attrp; 481 { 482 struct sfb_softc *sc = v; 483 long defattr; 484 485 if (sc->nscreens > 0) 486 return (ENOMEM); 487 488 *cookiep = &sc->sc_dc->rinfo; /* one and only for now */ 489 *curxp = 0; 490 *curyp = 0; 491 (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr); 492 *attrp = defattr; 493 sc->nscreens++; 494 return (0); 495 } 496 497 static void 498 sfb_free_screen(v, cookie) 499 void *v; 500 void *cookie; 501 { 502 struct sfb_softc *sc = v; 503 504 if (sc->sc_dc == &sfb_console_dc) 505 panic("sfb_free_screen: console"); 506 507 sc->nscreens--; 508 } 509 510 static int 511 sfb_show_screen(v, cookie, waitok, cb, cbarg) 512 void *v; 513 void *cookie; 514 int waitok; 515 void (*cb) __P((void *, int, int)); 516 void *cbarg; 517 { 518 519 return (0); 520 } 521 522 /* EXPORT */ int 523 sfb_cnattach(addr) 524 tc_addr_t addr; 525 { 526 struct fb_devconfig *dcp = &sfb_console_dc; 527 long defattr; 528 529 sfb_getdevconfig(addr, dcp); 530 531 (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr); 532 533 wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr); 534 sfb_consaddr = addr; 535 return(0); 536 } 537 538 static int 539 sfbintr(arg) 540 void *arg; 541 { 542 struct sfb_softc *sc = arg; 543 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr; 544 caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET; 545 caddr_t vdac; 546 int v; 547 548 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0; 549 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */ 550 551 if (sc->sc_changed == 0) 552 return (1); 553 554 vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET); 555 v = sc->sc_changed; 556 sc->sc_changed = 0; 557 558 if (v & DATA_ENB_CHANGED) { 559 SELECT(vdac, BT459_IREG_CCR); 560 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00; 561 } 562 if (v & DATA_CURCMAP_CHANGED) { 563 u_int8_t *cp = sc->sc_cursor.cc_color; 564 565 SELECT(vdac, BT459_IREG_CCOLOR_2); 566 REG(vdac, bt_reg) = cp[1]; tc_wmb(); 567 REG(vdac, bt_reg) = cp[3]; tc_wmb(); 568 REG(vdac, bt_reg) = cp[5]; tc_wmb(); 569 570 REG(vdac, bt_reg) = cp[0]; tc_wmb(); 571 REG(vdac, bt_reg) = cp[2]; tc_wmb(); 572 REG(vdac, bt_reg) = cp[4]; tc_wmb(); 573 } 574 if (v & DATA_CURSHAPE_CHANGED) { 575 u_int8_t *ip, *mp, img, msk; 576 u_int8_t u; 577 int bcnt; 578 579 ip = (u_int8_t *)sc->sc_cursor.cc_image; 580 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE); 581 582 bcnt = 0; 583 SELECT(vdac, BT459_IREG_CRAM_BASE+0); 584 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 585 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 586 /* pad right half 32 pixel when smaller than 33 */ 587 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 588 REG(vdac, bt_reg) = 0; tc_wmb(); 589 REG(vdac, bt_reg) = 0; tc_wmb(); 590 } 591 else { 592 img = *ip++; 593 msk = *mp++; 594 img &= msk; /* cookie off image */ 595 u = (msk & 0x0f) << 4 | (img & 0x0f); 596 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 597 u = (msk & 0xf0) | (img & 0xf0) >> 4; 598 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 599 } 600 bcnt += 2; 601 } 602 /* pad unoccupied scan lines */ 603 while (bcnt < CURSOR_MAX_SIZE * 16) { 604 REG(vdac, bt_reg) = 0; tc_wmb(); 605 REG(vdac, bt_reg) = 0; tc_wmb(); 606 bcnt += 2; 607 } 608 } 609 if (v & DATA_CMAP_CHANGED) { 610 struct hwcmap256 *cm = &sc->sc_cmap; 611 int index; 612 613 SELECT(vdac, 0); 614 for (index = 0; index < CMAP_SIZE; index++) { 615 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb(); 616 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb(); 617 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb(); 618 } 619 } 620 return (1); 621 } 622 623 static void 624 sfbinit(dc) 625 struct fb_devconfig *dc; 626 { 627 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET); 628 caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET); 629 int i; 630 631 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0; 632 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0; 633 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */ 634 *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3; /* ROP_COPY */ 635 636 *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */ 637 638 SELECT(vdac, BT459_IREG_COMMAND_0); 639 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb(); 640 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb(); 641 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb(); 642 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb(); 643 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb(); 644 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb(); 645 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb(); 646 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb(); 647 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb(); 648 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb(); 649 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb(); 650 651 SELECT(vdac, BT459_IREG_CCR); 652 REG(vdac, bt_reg) = 0x0; tc_wmb(); 653 REG(vdac, bt_reg) = 0x0; tc_wmb(); 654 REG(vdac, bt_reg) = 0x0; tc_wmb(); 655 REG(vdac, bt_reg) = 0x0; tc_wmb(); 656 REG(vdac, bt_reg) = 0x0; tc_wmb(); 657 REG(vdac, bt_reg) = 0x0; tc_wmb(); 658 REG(vdac, bt_reg) = 0x0; tc_wmb(); 659 REG(vdac, bt_reg) = 0x0; tc_wmb(); 660 REG(vdac, bt_reg) = 0x0; tc_wmb(); 661 REG(vdac, bt_reg) = 0x0; tc_wmb(); 662 REG(vdac, bt_reg) = 0x0; tc_wmb(); 663 REG(vdac, bt_reg) = 0x0; tc_wmb(); 664 REG(vdac, bt_reg) = 0x0; tc_wmb(); 665 666 /* build sane colormap */ 667 SELECT(vdac, 0); 668 for (i = 0; i < CMAP_SIZE; i++) { 669 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 0]; 670 tc_wmb(); 671 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 1]; 672 tc_wmb(); 673 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 2]; 674 tc_wmb(); 675 } 676 677 /* clear out cursor image */ 678 SELECT(vdac, BT459_IREG_CRAM_BASE); 679 for (i = 0; i < 1024; i++) 680 REG(vdac, bt_reg) = 0xff; tc_wmb(); 681 682 /* 683 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 684 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 685 * image color. CCOLOR_1 will be never used. 686 */ 687 SELECT(vdac, BT459_IREG_CCOLOR_1); 688 REG(vdac, bt_reg) = 0xff; tc_wmb(); 689 REG(vdac, bt_reg) = 0xff; tc_wmb(); 690 REG(vdac, bt_reg) = 0xff; tc_wmb(); 691 692 REG(vdac, bt_reg) = 0; tc_wmb(); 693 REG(vdac, bt_reg) = 0; tc_wmb(); 694 REG(vdac, bt_reg) = 0; tc_wmb(); 695 696 REG(vdac, bt_reg) = 0xff; tc_wmb(); 697 REG(vdac, bt_reg) = 0xff; tc_wmb(); 698 REG(vdac, bt_reg) = 0xff; tc_wmb(); 699 } 700 701 static int 702 get_cmap(sc, p) 703 struct sfb_softc *sc; 704 struct wsdisplay_cmap *p; 705 { 706 u_int index = p->index, count = p->count; 707 708 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 709 return (EINVAL); 710 711 if (!uvm_useracc(p->red, count, B_WRITE) || 712 !uvm_useracc(p->green, count, B_WRITE) || 713 !uvm_useracc(p->blue, count, B_WRITE)) 714 return (EFAULT); 715 716 copyout(&sc->sc_cmap.r[index], p->red, count); 717 copyout(&sc->sc_cmap.g[index], p->green, count); 718 copyout(&sc->sc_cmap.b[index], p->blue, count); 719 720 return (0); 721 } 722 723 static int 724 set_cmap(sc, p) 725 struct sfb_softc *sc; 726 struct wsdisplay_cmap *p; 727 { 728 u_int index = p->index, count = p->count; 729 730 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 731 return (EINVAL); 732 733 if (!uvm_useracc(p->red, count, B_READ) || 734 !uvm_useracc(p->green, count, B_READ) || 735 !uvm_useracc(p->blue, count, B_READ)) 736 return (EFAULT); 737 738 copyin(p->red, &sc->sc_cmap.r[index], count); 739 copyin(p->green, &sc->sc_cmap.g[index], count); 740 copyin(p->blue, &sc->sc_cmap.b[index], count); 741 742 sc->sc_changed |= DATA_CMAP_CHANGED; 743 744 return (0); 745 } 746 747 748 static int 749 set_cursor(sc, p) 750 struct sfb_softc *sc; 751 struct wsdisplay_cursor *p; 752 { 753 #define cc (&sc->sc_cursor) 754 int v, index, count, icount; 755 756 v = p->which; 757 if (v & WSDISPLAY_CURSOR_DOCMAP) { 758 index = p->cmap.index; 759 count = p->cmap.count; 760 if (index >= 2 || (index + count) > 2) 761 return (EINVAL); 762 if (!uvm_useracc(p->cmap.red, count, B_READ) || 763 !uvm_useracc(p->cmap.green, count, B_READ) || 764 !uvm_useracc(p->cmap.blue, count, B_READ)) 765 return (EFAULT); 766 } 767 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 768 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 769 return (EINVAL); 770 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 771 if (!uvm_useracc(p->image, icount, B_READ) || 772 !uvm_useracc(p->mask, icount, B_READ)) 773 return (EFAULT); 774 } 775 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) { 776 if (v & WSDISPLAY_CURSOR_DOCUR) 777 cc->cc_hot = p->hot; 778 if (v & WSDISPLAY_CURSOR_DOPOS) 779 set_curpos(sc, &p->pos); 780 bt459_set_curpos(sc); 781 } 782 783 sc->sc_changed = 0; 784 if (v & WSDISPLAY_CURSOR_DOCUR) { 785 sc->sc_curenb = p->enable; 786 sc->sc_changed |= DATA_ENB_CHANGED; 787 } 788 if (v & WSDISPLAY_CURSOR_DOCMAP) { 789 copyin(p->cmap.red, &cc->cc_color[index], count); 790 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 791 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 792 sc->sc_changed |= DATA_CURCMAP_CHANGED; 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 sc->sc_changed |= DATA_CURSHAPE_CHANGED; 800 } 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 static void 836 bt459_set_curpos(sc) 837 struct sfb_softc *sc; 838 { 839 caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET; 840 int x, y, s; 841 842 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 843 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 844 845 x += sc->sc_cursor.cc_magic.x; 846 y += sc->sc_cursor.cc_magic.y; 847 848 s = spltty(); 849 850 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 851 REG(vdac, bt_reg) = x; tc_wmb(); 852 REG(vdac, bt_reg) = x >> 8; tc_wmb(); 853 REG(vdac, bt_reg) = y; tc_wmb(); 854 REG(vdac, bt_reg) = y >> 8; tc_wmb(); 855 856 splx(s); 857 } 858 859 #define MODE_SIMPLE 0 860 #define MODE_OPAQUESTIPPLE 1 861 #define MODE_OPAQUELINE 2 862 #define MODE_TRANSPARENTSTIPPLE 5 863 #define MODE_TRANSPARENTLINE 6 864 #define MODE_COPY 7 865 866 /* parameters for 8bpp configuration */ 867 #define SFBALIGNMASK 0x7 868 #define SFBSTIPPLEALL1 0xffffffff 869 #define SFBSTIPPLEBITS 32 870 #define SFBSTIPPLEBITMASK 0x1f 871 #define SFBSTIPPLEBYTESDONE 32 872 #define SFBCOPYALL1 0xffffffff 873 #define SFBCOPYBITS 32 874 #define SFBCOPYBITMASK 0x1f 875 #define SFBCOPYBYTESDONE 32 876 877 #if defined(pmax) 878 #define WRITE_MB() 879 #define BUMP(p) (p) 880 #endif 881 882 #if defined(alpha) 883 #define WRITE_MB() tc_wmb() 884 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400)) 885 #endif 886 887 #define SFBMODE(p, v) \ 888 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v)) 889 #define SFBROP(p, v) \ 890 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v)) 891 #define SFBPLANEMASK(p, v) \ 892 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v)) 893 #define SFBPIXELMASK(p, v) \ 894 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v)) 895 #define SFBADDRESS(p, v) \ 896 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v)) 897 #define SFBSTART(p, v) \ 898 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v)) 899 #define SFBPIXELSHIFT(p, v) \ 900 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v)) 901 #define SFBFG(p, v) \ 902 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v)) 903 #define SFBBG(p, v) \ 904 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v)) 905 906 907 #if 0 908 /* 909 * Paint (or unpaint) the cursor. 910 */ 911 static void 912 sfb_cursor(id, on, row, col) 913 void *id; 914 int on, row, col; 915 { 916 struct rasops_info *ri = id; 917 caddr_t sfb, p; 918 int scanspan, height, width, align, x, y; 919 u_int32_t lmask, rmask; 920 int fg, bg; 921 922 /* turn the cursor off */ 923 if (!on) { 924 /* make sure it's on */ 925 if ((rc->rc_bits & RC_CURSOR) == 0) 926 return; 927 928 row = *rc->rc_crowp; 929 col = *rc->rc_ccolp; 930 } else { 931 /* unpaint the old copy. */ 932 *rc->rc_crowp = row; 933 *rc->rc_ccolp = col; 934 } 935 936 x = col * ri->ri_font->fontwidth; 937 y = row * ri->ri_font->fontheight; 938 scanspan = ri->ri_stride; 939 height = ri->ri_font->fontheight; 940 941 p = ri->ri_bits + y * scanspan + x; 942 align = (long)p & SFBALIGNMASK; 943 p -= align; 944 width = ri->ri_font->fontwidth + align; 945 lmask = SFBSTIPPLEALL1 << align; 946 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 947 sfb = ri->ri_hw; 948 949 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 950 SFBPLANEMASK(sfb, ~0); 951 SFBROP(sfb, 6); /* ROP_XOR */ 952 rasops_unpack_attr(attr, &fg, &bg, 0); 953 fg ^= bg; /* (fg ^ bg) to swap fg/bg */ 954 fg |= fg << 8; 955 fg |= fg << 16; 956 SFBFG(sfb, fg); 957 if (width <= SFBSTIPPLEBITS) { 958 lmask = lmask & rmask; 959 while (height > 0) { 960 SFBADDRESS(sfb, (long)p); 961 SFBSTART(sfb, lmask); 962 p += scanspan; 963 height--; 964 } 965 } 966 else { 967 caddr_t q = p; 968 while (height > 0) { 969 *(u_int32_t *)p = lmask; 970 WRITE_MB(); 971 p += SFBSTIPPLEBYTESDONE; 972 *(u_int32_t *)p = rmask; 973 WRITE_MB(); 974 975 p = (q += scanspan); 976 height--; 977 } 978 } 979 SFBMODE(sfb, MODE_SIMPLE); 980 SFBROP(sfb, 3); /* ROP_COPY */ 981 982 rc->rc_bits ^= RC_CURSOR; 983 } 984 #endif 985 986 /* 987 * Actually write a string to the frame buffer. 988 */ 989 static void 990 sfb_putchar(id, row, col, uc, attr) 991 void *id; 992 int row, col; 993 u_int uc; 994 long attr; 995 { 996 struct rasops_info *ri = id; 997 caddr_t sfb, p; 998 int scanspan, height, width, align, x, y; 999 u_int32_t lmask, rmask, glyph; 1000 u_int8_t *g; 1001 int fg, bg; 1002 1003 x = col * ri->ri_font->fontwidth; 1004 y = row * ri->ri_font->fontheight; 1005 scanspan = ri->ri_stride; 1006 height = ri->ri_font->fontheight; 1007 uc -= ri->ri_font->firstchar; 1008 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 1009 1010 p = ri->ri_bits + y * scanspan + x; 1011 align = (long)p & SFBALIGNMASK; 1012 p -= align; 1013 width = ri->ri_font->fontwidth + align; 1014 lmask = SFBSTIPPLEALL1 << align; 1015 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1016 sfb = ri->ri_hw; 1017 1018 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 1019 SFBPLANEMASK(sfb, ~0); 1020 rasops_unpack_attr(attr, &fg, &bg, 0); 1021 fg |= fg << 8; 1022 fg |= fg << 16; 1023 bg |= bg << 8; 1024 bg |= bg << 16; 1025 SFBFG(sfb, fg); 1026 SFBBG(sfb, bg); 1027 if (1 /* width <= SFBSTIPPLEBITS */) { 1028 lmask = lmask & rmask; 1029 while (height > 0) { 1030 glyph = *(u_int16_t *)g; /* XXX */ 1031 SFBPIXELMASK(sfb, lmask); 1032 SFBADDRESS(sfb, (long)p); 1033 SFBSTART(sfb, glyph << align); 1034 p += scanspan; 1035 g += 2; /* XXX */ 1036 height--; 1037 } 1038 } 1039 #if supportlargerfonts 1040 else { 1041 caddr_t q = p; 1042 while (height > 0) { 1043 glyph = *(u_int16_t *)g; /* XXX */ 1044 SFBPIXELMASK(sfb, lmask); 1045 WRITE_MB(); 1046 *(u_int32_t *)p = glyph << align; 1047 WRITE_MB(); 1048 p += SFBSTIPPLEBYTESDONE; 1049 SFBPIXELMASK(sfb, rmask); 1050 WRITE_MB(); 1051 *(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK); 1052 WRITE_MB(); 1053 1054 p = (q += scanspan); 1055 g += 2; /* XXX */ 1056 height--; 1057 } 1058 } 1059 #endif 1060 SFBMODE(sfb, MODE_SIMPLE); 1061 SFBPIXELMASK(sfb, ~0); /* entire pixel */ 1062 } 1063 1064 #if 0 1065 /* 1066 * Copy characters in a line. 1067 */ 1068 static void 1069 sfb_copycols(id, row, srccol, dstcol, ncols) 1070 void *id; 1071 int row, srccol, dstcol, ncols; 1072 { 1073 struct rasops_info *ri = id; 1074 caddr_t sp, dp, basex, sfb; 1075 int scanspan, height, width, aligns, alignd, shift, w, y; 1076 u_int32_t lmasks, rmasks, lmaskd, rmaskd; 1077 1078 scanspan = ri->ri_stride; 1079 y = row * ri->ri_font->fontheight; 1080 basex = (caddr_t)rap->pixels + y * scanspan; 1081 height = ri->ri_font->fontheight; 1082 w = ri->ri_font->fontwidth * ncols; 1083 1084 sp = basex + ri->ri_font->fontwidth * srccol; 1085 aligns = (long)sp & SFBALIGNMASK; 1086 dp = basex + ri->ri_font->fontwidth * dstcol; 1087 alignd = (long)dp & SFBALIGNMASK; 1088 sfb = ri->ri_hw; 1089 1090 SFBMODE(sfb, MODE_COPY); 1091 SFBPLANEMASK(sfb, ~0); 1092 1093 /* copy forward (left-to-right) */ 1094 if (dstcol < srccol || srccol + ncols < dstcol) { 1095 caddr_t sq, dq; 1096 1097 shift = alignd - aligns; 1098 if (shift < 0) { 1099 shift = 8 + shift; /* enforce right rotate */ 1100 alignd += 8; /* bearing on left edge */ 1101 w += 8; /* enlarge to left */ 1102 } 1103 width = aligns + w; 1104 1105 sp -= aligns; 1106 dp -= alignd; 1107 lmasks = SFBCOPYALL1 << aligns; 1108 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1109 lmaskd = SFBCOPYALL1 << alignd; 1110 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK); 1111 1112 if (w + alignd <= SFBCOPYBITS) 1113 goto singlewrite; 1114 1115 SFBPIXELSHIFT(sfb, shift); 1116 w = width; 1117 sq = sp; 1118 dq = dp; 1119 while (height > 0) { 1120 *(u_int32_t *)sp = lmasks; 1121 WRITE_MB(); 1122 *(u_int32_t *)dp = lmaskd; 1123 WRITE_MB(); 1124 width -= 2 * SFBCOPYBITS; 1125 while (width > 0) { 1126 sp += SFBCOPYBYTESDONE; 1127 dp += SFBCOPYBYTESDONE; 1128 *(u_int32_t *)sp = SFBCOPYALL1; 1129 WRITE_MB(); 1130 *(u_int32_t *)dp = SFBCOPYALL1; 1131 WRITE_MB(); 1132 width -= SFBCOPYBITS; 1133 } 1134 sp += SFBCOPYBYTESDONE; 1135 dp += SFBCOPYBYTESDONE; 1136 *(u_int32_t *)sp = rmasks; 1137 WRITE_MB(); 1138 *(u_int32_t *)dp = rmaskd; 1139 WRITE_MB(); 1140 1141 sp = (sq += scanspan); 1142 dp = (dq += scanspan); 1143 width = w; 1144 height--; 1145 } 1146 } 1147 /* copy backward (right-to-left) */ 1148 else { 1149 caddr_t sq, dq; 1150 1151 shift = alignd - aligns; 1152 if (shift > 0) { 1153 shift = shift - 8; /* force left rotate */ 1154 aligns += 8; /* flush edge at left end */ 1155 } 1156 width = aligns + w; 1157 1158 sp -= aligns; 1159 dp -= alignd; 1160 lmasks = SFBCOPYALL1 << aligns; 1161 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1162 lmaskd = SFBCOPYALL1 << alignd; 1163 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK); 1164 1165 if (w + alignd <= SFBCOPYBITS) 1166 goto singlewrite; 1167 1168 SFBPIXELSHIFT(sfb, shift); 1169 w = width; 1170 sq = sp += ((width - 1) & ~31); 1171 dq = dp += (((w + alignd) - 1) & ~31); 1172 while (height > 0) { 1173 *(u_int32_t *)sp = rmasks; 1174 WRITE_MB(); 1175 *(u_int32_t *)dp = rmaskd; 1176 WRITE_MB(); 1177 width -= 2 * SFBCOPYBITS; 1178 while (width > 0) { 1179 sp -= SFBCOPYBYTESDONE; 1180 dp -= SFBCOPYBYTESDONE; 1181 *(u_int32_t *)sp = SFBCOPYALL1; 1182 WRITE_MB(); 1183 *(u_int32_t *)dp = SFBCOPYALL1; 1184 WRITE_MB(); 1185 width -= SFBCOPYBITS; 1186 } 1187 sp -= SFBCOPYBYTESDONE; 1188 dp -= SFBCOPYBYTESDONE; 1189 *(u_int32_t *)sp = lmasks; 1190 WRITE_MB(); 1191 *(u_int32_t *)dp = lmaskd; 1192 WRITE_MB(); 1193 1194 sp = (sq += scanspan); 1195 dp = (dq += scanspan); 1196 width = w; 1197 height--; 1198 } 1199 } 1200 SFBMODE(sfb, MODE_SIMPLE); 1201 SFBPIXELSHIFT(sfb, 0); 1202 return; 1203 1204 singlewrite: 1205 SFBPIXELSHIFT(sfb, shift); 1206 lmasks = lmasks & rmasks; 1207 lmaskd = lmaskd & rmaskd; 1208 while (height > 0) { 1209 *(u_int32_t *)sp = lmasks; 1210 WRITE_MB(); 1211 *(u_int32_t *)dp = lmaskd; 1212 WRITE_MB(); 1213 sp += scanspan; 1214 dp += scanspan; 1215 height--; 1216 } 1217 SFBMODE(sfb, MODE_SIMPLE); 1218 SFBPIXELSHIFT(sfb, 0); 1219 } 1220 #endif 1221 1222 /* 1223 * Clear characters in a line. 1224 */ 1225 static void 1226 sfb_erasecols(id, row, startcol, ncols, attr) 1227 void *id; 1228 int row, startcol, ncols; 1229 long attr; 1230 { 1231 struct rasops_info *ri = id; 1232 caddr_t sfb, p; 1233 int scanspan, startx, height, width, align, w, y; 1234 u_int32_t lmask, rmask; 1235 int fg, bg; 1236 1237 scanspan = ri->ri_stride; 1238 y = row * ri->ri_font->fontheight; 1239 startx = startcol * ri->ri_font->fontwidth; 1240 height = ri->ri_font->fontheight; 1241 w = ri->ri_font->fontwidth * ncols; 1242 1243 p = ri->ri_bits + y * scanspan + startx; 1244 align = (long)p & SFBALIGNMASK; 1245 p -= align; 1246 width = w + align; 1247 lmask = SFBSTIPPLEALL1 << align; 1248 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1249 sfb = ri->ri_hw; 1250 1251 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1252 SFBPLANEMASK(sfb, ~0); 1253 rasops_unpack_attr(attr, &fg, &bg, 0); 1254 bg |= bg << 8; 1255 bg |= bg << 16; 1256 SFBFG(sfb, bg); /* fill with bg color */ 1257 if (width <= SFBSTIPPLEBITS) { 1258 lmask = lmask & rmask; 1259 while (height > 0) { 1260 SFBADDRESS(sfb, (long)p); 1261 SFBSTART(sfb, lmask); 1262 p += scanspan; 1263 height--; 1264 } 1265 } 1266 else { 1267 caddr_t q = p; 1268 while (height > 0) { 1269 *(u_int32_t *)p = lmask; 1270 WRITE_MB(); 1271 width -= 2 * SFBSTIPPLEBITS; 1272 while (width > 0) { 1273 p += SFBSTIPPLEBYTESDONE; 1274 *(u_int32_t *)p = SFBSTIPPLEALL1; 1275 WRITE_MB(); 1276 width -= SFBSTIPPLEBITS; 1277 } 1278 p += SFBSTIPPLEBYTESDONE; 1279 *(u_int32_t *)p = rmask; 1280 WRITE_MB(); 1281 1282 p = (q += scanspan); 1283 width = w + align; 1284 height--; 1285 } 1286 } 1287 SFBMODE(sfb, MODE_SIMPLE); 1288 } 1289 1290 /* 1291 * Copy lines. 1292 */ 1293 static void 1294 sfb_copyrows(id, srcrow, dstrow, nrows) 1295 void *id; 1296 int srcrow, dstrow, nrows; 1297 { 1298 struct rasops_info *ri = id; 1299 caddr_t sfb, p; 1300 int scanspan, offset, srcy, height, width, align, w; 1301 u_int32_t lmask, rmask; 1302 1303 scanspan = ri->ri_stride; 1304 height = ri->ri_font->fontheight * nrows; 1305 offset = (dstrow - srcrow) * ri->ri_yscale; 1306 srcy = ri->ri_font->fontheight * srcrow; 1307 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1308 scanspan = -scanspan; 1309 srcy += height; 1310 } 1311 1312 p = ri->ri_bits + srcy * ri->ri_stride; 1313 align = (long)p & SFBALIGNMASK; 1314 p -= align; 1315 w = ri->ri_emuwidth; 1316 width = w + align; 1317 lmask = SFBCOPYALL1 << align; 1318 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1319 sfb = ri->ri_hw; 1320 1321 SFBMODE(sfb, MODE_COPY); 1322 SFBPLANEMASK(sfb, ~0); 1323 SFBPIXELSHIFT(sfb, 0); 1324 if (width <= SFBCOPYBITS) { 1325 /* never happens */; 1326 } 1327 else { 1328 caddr_t q = p; 1329 while (height > 0) { 1330 *(u_int32_t *)p = lmask; 1331 *(u_int32_t *)(p + offset) = lmask; 1332 width -= 2 * SFBCOPYBITS; 1333 while (width > 0) { 1334 p += SFBCOPYBYTESDONE; 1335 *(u_int32_t *)p = SFBCOPYALL1; 1336 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1337 width -= SFBCOPYBITS; 1338 } 1339 p += SFBCOPYBYTESDONE; 1340 *(u_int32_t *)p = rmask; 1341 *(u_int32_t *)(p + offset) = rmask; 1342 1343 p = (q += scanspan); 1344 width = w + align; 1345 height--; 1346 } 1347 } 1348 SFBMODE(sfb, MODE_SIMPLE); 1349 } 1350 1351 /* 1352 * Erase lines. 1353 */ 1354 void 1355 sfb_eraserows(id, startrow, nrows, attr) 1356 void *id; 1357 int startrow, nrows; 1358 long attr; 1359 { 1360 struct rasops_info *ri = id; 1361 caddr_t sfb, p; 1362 int scanspan, starty, height, width, align, w; 1363 u_int32_t lmask, rmask; 1364 int fg, bg; 1365 1366 scanspan = ri->ri_stride; 1367 starty = ri->ri_font->fontheight * startrow; 1368 height = ri->ri_font->fontheight * nrows; 1369 1370 p = ri->ri_bits + starty * scanspan; 1371 align = (long)p & SFBALIGNMASK; 1372 p -= align; 1373 w = ri->ri_emuwidth; 1374 width = w + align; 1375 lmask = SFBSTIPPLEALL1 << align; 1376 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1377 sfb = ri->ri_hw; 1378 1379 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1380 SFBPLANEMASK(sfb, ~0); 1381 rasops_unpack_attr(attr, &fg, &bg, 0); 1382 bg |= bg << 8; 1383 bg |= bg << 16; 1384 SFBFG(sfb, bg); /* fill with bg color */ 1385 if (width <= SFBSTIPPLEBITS) { 1386 /* never happens */; 1387 } 1388 else { 1389 caddr_t q = p; 1390 while (height > 0) { 1391 *(u_int32_t *)p = lmask; 1392 WRITE_MB(); 1393 width -= 2 * SFBSTIPPLEBITS; 1394 while (width > 0) { 1395 p += SFBSTIPPLEBYTESDONE; 1396 *(u_int32_t *)p = SFBSTIPPLEALL1; 1397 WRITE_MB(); 1398 width -= SFBSTIPPLEBITS; 1399 } 1400 p += SFBSTIPPLEBYTESDONE; 1401 *(u_int32_t *)p = rmask; 1402 WRITE_MB(); 1403 1404 p = (q += scanspan); 1405 width = w + align; 1406 height--; 1407 } 1408 } 1409 SFBMODE(sfb, MODE_SIMPLE); 1410 } 1411