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