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