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