1 /* $NetBSD: sfb.c,v 1.86 2019/11/10 21:16:37 chs 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.86 2019/11/10 21:16:37 chs 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_WAITOK | M_ZERO); 275 ri->ri_hw = (void *)ta->ta_addr; 276 sfb_common_init(ri); 277 sc->sc_ri = ri; 278 } 279 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth); 280 281 sfb_cmap_init(sc); 282 283 sc->sc_vaddr = ta->ta_addr; 284 sc->sc_cursor.cc_magic.x = HX_MAGIC_X; 285 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y; 286 sc->sc_blanked = sc->sc_curenb = 0; 287 288 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc); 289 290 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 291 292 SFBWRITE32(asic, SFB_ASIC_CLEAR_INTR, 0); 293 SFBWRITE32(asic, SFB_ASIC_ENABLE_INTR, 1); 294 295 waa.console = console; 296 waa.scrdata = &sfb_screenlist; 297 waa.accessops = &sfb_accessops; 298 waa.accesscookie = sc; 299 300 config_found(self, &waa, wsemuldisplaydevprint); 301 } 302 303 static void 304 sfb_cmap_init(struct sfb_softc *sc) 305 { 306 struct hwcmap256 *cm; 307 const uint8_t *p; 308 int index; 309 310 cm = &sc->sc_cmap; 311 p = rasops_cmap; 312 for (index = 0; index < CMAP_SIZE; index++, p += 3) { 313 cm->r[index] = p[0]; 314 cm->g[index] = p[1]; 315 cm->b[index] = p[2]; 316 } 317 } 318 319 static void 320 sfb_common_init(struct rasops_info *ri) 321 { 322 char *base, *asic; 323 int hsetup, vsetup, vbase, cookie; 324 325 base = (void *)ri->ri_hw; 326 asic = base + SFB_ASIC_OFFSET; 327 hsetup = *(volatile uint32_t *)(asic + SFB_ASIC_VIDEO_HSETUP); 328 vsetup = *(volatile uint32_t *)(asic + SFB_ASIC_VIDEO_VSETUP); 329 330 vbase = 1; 331 SFBWRITE32(asic, SFB_ASIC_VIDEO_BASE, vbase); 332 SFBWRITE32(asic, SFB_ASIC_PLANEMASK, ~0); 333 SFBWRITE32(asic, SFB_ASIC_PIXELMASK, ~0); 334 SFBWRITE32(asic, SFB_ASIC_MODE, 0); /* MODE_SIMPLE */ 335 SFBWRITE32(asic, SFB_ASIC_ROP, 3); /* ROP_COPY */ 336 SFBWRITE32(asic, 0x180000, 0); /* Bt459 reset */ 337 338 /* initialize colormap and cursor hardware */ 339 sfbhwinit(base); 340 341 ri->ri_flg = RI_CENTER; 342 if (ri == &sfb_console_ri) 343 ri->ri_flg |= RI_NO_AUTO; 344 ri->ri_depth = 8; 345 ri->ri_width = (hsetup & 0x1ff) << 2; 346 ri->ri_height = (vsetup & 0x7ff); 347 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8); 348 ri->ri_bits = base + SFB_FB_OFFSET + vbase * 4096; 349 350 /* clear the screen */ 351 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 352 353 wsfont_init(); 354 /* prefer 12 pixel wide font */ 355 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L, 356 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP); 357 if (cookie <= 0) 358 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, 359 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP); 360 if (cookie <= 0) { 361 printf("sfb: font table is empty\n"); 362 return; 363 } 364 365 /* the accelerated sfb_putchar() needs LSbit left */ 366 if (wsfont_lock(cookie, &ri->ri_font)) { 367 printf("sfb: couldn't lock font\n"); 368 return; 369 } 370 ri->ri_wsfcookie = cookie; 371 372 rasops_init(ri, 34, 80); 373 374 /* add our accelerated functions */ 375 ri->ri_ops.putchar = sfb_putchar; 376 ri->ri_ops.erasecols = sfb_erasecols; 377 ri->ri_ops.copyrows = sfb_copyrows; 378 ri->ri_ops.eraserows = sfb_eraserows; 379 ri->ri_do_cursor = sfb_do_cursor; 380 381 /* XXX shouldn't be global */ 382 sfb_stdscreen.nrows = ri->ri_rows; 383 sfb_stdscreen.ncols = ri->ri_cols; 384 sfb_stdscreen.textops = &ri->ri_ops; 385 sfb_stdscreen.capabilities = ri->ri_caps; 386 } 387 388 static int 389 sfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 390 { 391 struct sfb_softc *sc = v; 392 struct rasops_info *ri = sc->sc_ri; 393 int turnoff, s; 394 395 switch (cmd) { 396 case WSDISPLAYIO_GTYPE: 397 *(u_int *)data = WSDISPLAY_TYPE_SFB; 398 return (0); 399 400 case WSDISPLAYIO_GINFO: 401 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 402 wsd_fbip->height = ri->ri_height; 403 wsd_fbip->width = ri->ri_width; 404 wsd_fbip->depth = ri->ri_depth; 405 wsd_fbip->cmsize = CMAP_SIZE; 406 #undef fbt 407 return (0); 408 409 case WSDISPLAYIO_GETCMAP: 410 return get_cmap(sc, (struct wsdisplay_cmap *)data); 411 412 case WSDISPLAYIO_PUTCMAP: 413 return set_cmap(sc, (struct wsdisplay_cmap *)data); 414 415 case WSDISPLAYIO_SVIDEO: 416 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 417 if (sc->sc_blanked != turnoff) { 418 sc->sc_blanked = turnoff; 419 sfb_screenblank(sc); 420 } 421 return (0); 422 423 case WSDISPLAYIO_GVIDEO: 424 *(u_int *)data = sc->sc_blanked ? 425 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 426 return (0); 427 428 case WSDISPLAYIO_GCURPOS: 429 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 430 return (0); 431 432 case WSDISPLAYIO_SCURPOS: 433 s = spltty(); 434 set_curpos(sc, (struct wsdisplay_curpos *)data); 435 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 436 splx(s); 437 return (0); 438 439 case WSDISPLAYIO_GCURMAX: 440 ((struct wsdisplay_curpos *)data)->x = 441 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 442 return (0); 443 444 case WSDISPLAYIO_GCURSOR: 445 return get_cursor(sc, (struct wsdisplay_cursor *)data); 446 447 case WSDISPLAYIO_SCURSOR: 448 return set_cursor(sc, (struct wsdisplay_cursor *)data); 449 450 case WSDISPLAYIO_SMODE: 451 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { 452 s = spltty(); 453 sfb_cmap_init(sc); 454 sc->sc_curenb = 0; 455 sc->sc_blanked = 0; 456 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR | 457 WSDISPLAY_CMAP_DOLUT); 458 splx(s); 459 sfb_screenblank(sc); 460 } 461 return (0); 462 } 463 return (EPASSTHROUGH); 464 } 465 466 static void 467 sfb_screenblank(struct sfb_softc *sc) 468 { 469 struct rasops_info *ri; 470 char *asic; 471 472 ri = sc->sc_ri; 473 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 474 SFBWRITE32(asic, SFB_ASIC_VIDEO_VALID, !sc->sc_blanked); 475 tc_wmb(); 476 } 477 478 static paddr_t 479 sfbmmap(void *v, void *vs, off_t offset, int prot) 480 { 481 struct sfb_softc *sc = v; 482 483 if (offset >= SFB_SIZE || offset < 0) 484 return (-1); 485 return machine_btop(sc->sc_vaddr + offset); 486 } 487 488 static int 489 sfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 490 int *curxp, int *curyp, long *attrp) 491 { 492 struct sfb_softc *sc = v; 493 struct rasops_info *ri = sc->sc_ri; 494 long defattr; 495 496 if (sc->nscreens > 0) 497 return (ENOMEM); 498 499 *cookiep = ri; /* one and only for now */ 500 *curxp = 0; 501 *curyp = 0; 502 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 503 *attrp = defattr; 504 sc->nscreens++; 505 return (0); 506 } 507 508 static void 509 sfb_free_screen(void *v, void *cookie) 510 { 511 struct sfb_softc *sc = v; 512 513 if (sc->sc_ri == &sfb_console_ri) 514 panic("sfb_free_screen: console"); 515 516 sc->nscreens--; 517 } 518 519 static int 520 sfb_show_screen(void *v, void *cookie, int waitok, 521 void (*cb)(void *, int, int), void *cbarg) 522 { 523 524 return (0); 525 } 526 527 /* EXPORT */ int 528 sfb_cnattach(tc_addr_t addr) 529 { 530 struct rasops_info *ri; 531 long defattr; 532 533 ri = &sfb_console_ri; 534 ri->ri_hw = (void *)addr; 535 sfb_common_init(ri); 536 (*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr); 537 wsdisplay_cnattach(&sfb_stdscreen, ri, 0, 0, defattr); 538 sfb_consaddr = addr; 539 return (0); 540 } 541 542 static int 543 sfbintr(void *arg) 544 { 545 struct sfb_softc *sc = arg; 546 char *base, *asic, *vdac; 547 int v; 548 549 base = (void *)sc->sc_ri->ri_hw; 550 asic = base + SFB_ASIC_OFFSET; 551 SFBWRITE32(asic, SFB_ASIC_CLEAR_INTR, 0); 552 /* SFBWRITE32(asic, SFB_ASIC_ENABLE_INTR, 1); */ 553 554 if (sc->sc_changed == 0) 555 goto done; 556 557 vdac = base + SFB_RAMDAC_OFFSET; 558 v = sc->sc_changed; 559 if (v & WSDISPLAY_CURSOR_DOCUR) { 560 int onoff; 561 562 onoff = (sc->sc_curenb) ? 0xc0 : 0x00; 563 VDACSELECT(vdac, BT459_IREG_CCR); 564 REGWRITE32(vdac, bt_reg, onoff); 565 } 566 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 567 int x, y; 568 569 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 570 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 571 x += sc->sc_cursor.cc_magic.x; 572 y += sc->sc_cursor.cc_magic.y; 573 574 VDACSELECT(vdac, BT459_IREG_CURSOR_X_LOW); 575 REGWRITE32(vdac, bt_reg, x); 576 REGWRITE32(vdac, bt_reg, x >> 8); 577 REGWRITE32(vdac, bt_reg, y); 578 REGWRITE32(vdac, bt_reg, y >> 8); 579 } 580 if (v & WSDISPLAY_CURSOR_DOCMAP) { 581 uint8_t *cp = sc->sc_cursor.cc_color; 582 583 VDACSELECT(vdac, BT459_IREG_CCOLOR_2); 584 REGWRITE32(vdac, bt_reg, cp[1]); 585 REGWRITE32(vdac, bt_reg, cp[3]); 586 REGWRITE32(vdac, bt_reg, cp[5]); 587 588 REGWRITE32(vdac, bt_reg, cp[0]); 589 REGWRITE32(vdac, bt_reg, cp[2]); 590 REGWRITE32(vdac, bt_reg, cp[4]); 591 } 592 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 593 uint8_t *ip, *mp, img, msk; 594 uint8_t u; 595 int bcnt; 596 597 ip = (uint8_t *)sc->sc_cursor.cc_image; 598 mp = (uint8_t *)sc->sc_cursor.cc_mask; 599 600 bcnt = 0; 601 VDACSELECT(vdac, BT459_IREG_CRAM_BASE+0); 602 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 603 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 604 /* pad right half 32 pixel when smaller than 33 */ 605 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 606 REGWRITE32(vdac, bt_reg, 0); 607 REGWRITE32(vdac, bt_reg, 0); 608 } 609 else { 610 img = *ip++; 611 msk = *mp++; 612 img &= msk; /* cookie off image */ 613 u = (msk & 0x0f) << 4 | (img & 0x0f); 614 REGWRITE32(vdac, bt_reg, shuffle[u]); 615 u = (msk & 0xf0) | (img & 0xf0) >> 4; 616 REGWRITE32(vdac, bt_reg, shuffle[u]); 617 } 618 bcnt += 2; 619 } 620 /* pad unoccupied scan lines */ 621 while (bcnt < CURSOR_MAX_SIZE * 16) { 622 REGWRITE32(vdac, bt_reg, 0); 623 REGWRITE32(vdac, bt_reg, 0); 624 bcnt += 2; 625 } 626 } 627 if (v & WSDISPLAY_CMAP_DOLUT) { 628 struct hwcmap256 *cm = &sc->sc_cmap; 629 int index; 630 631 VDACSELECT(vdac, 0); 632 for (index = 0; index < CMAP_SIZE; index++) { 633 REGWRITE32(vdac, bt_cmap, cm->r[index]); 634 REGWRITE32(vdac, bt_cmap, cm->g[index]); 635 REGWRITE32(vdac, bt_cmap, cm->b[index]); 636 } 637 } 638 sc->sc_changed = 0; 639 done: 640 return (1); 641 } 642 643 static void 644 sfbhwinit(void *base) 645 { 646 char *vdac = (char *)base + SFB_RAMDAC_OFFSET; 647 const uint8_t *p; 648 int i; 649 650 VDACSELECT(vdac, BT459_IREG_COMMAND_0); 651 REGWRITE32(vdac, bt_reg, 0x40); /* CMD0 */ 652 REGWRITE32(vdac, bt_reg, 0x0); /* CMD1 */ 653 REGWRITE32(vdac, bt_reg, 0xc0); /* CMD2 */ 654 REGWRITE32(vdac, bt_reg, 0xff); /* PRM */ 655 REGWRITE32(vdac, bt_reg, 0); /* 205 */ 656 REGWRITE32(vdac, bt_reg, 0x0); /* PBM */ 657 REGWRITE32(vdac, bt_reg, 0); /* 207 */ 658 REGWRITE32(vdac, bt_reg, 0x0); /* ORM */ 659 REGWRITE32(vdac, bt_reg, 0x0); /* OBM */ 660 REGWRITE32(vdac, bt_reg, 0x0); /* ILV */ 661 REGWRITE32(vdac, bt_reg, 0x0); /* TEST */ 662 663 VDACSELECT(vdac, BT459_IREG_CCR); 664 REGWRITE32(vdac, bt_reg, 0x0); 665 REGWRITE32(vdac, bt_reg, 0x0); 666 REGWRITE32(vdac, bt_reg, 0x0); 667 REGWRITE32(vdac, bt_reg, 0x0); 668 REGWRITE32(vdac, bt_reg, 0x0); 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 678 /* build sane colormap */ 679 VDACSELECT(vdac, 0); 680 p = rasops_cmap; 681 for (i = 0; i < CMAP_SIZE; i++, p += 3) { 682 REGWRITE32(vdac, bt_cmap, p[0]); 683 REGWRITE32(vdac, bt_cmap, p[1]); 684 REGWRITE32(vdac, bt_cmap, p[2]); 685 } 686 687 /* clear out cursor image */ 688 VDACSELECT(vdac, BT459_IREG_CRAM_BASE); 689 for (i = 0; i < 1024; i++) 690 REGWRITE32(vdac, bt_reg, 0xff); 691 692 /* 693 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 694 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 695 * image color. CCOLOR_1 will be never used. 696 */ 697 VDACSELECT(vdac, BT459_IREG_CCOLOR_1); 698 REGWRITE32(vdac, bt_reg, 0xff); 699 REGWRITE32(vdac, bt_reg, 0xff); 700 REGWRITE32(vdac, bt_reg, 0xff); 701 702 REGWRITE32(vdac, bt_reg, 0); 703 REGWRITE32(vdac, bt_reg, 0); 704 REGWRITE32(vdac, bt_reg, 0); 705 706 REGWRITE32(vdac, bt_reg, 0xff); 707 REGWRITE32(vdac, bt_reg, 0xff); 708 REGWRITE32(vdac, bt_reg, 0xff); 709 } 710 711 static int 712 get_cmap(struct sfb_softc *sc, struct wsdisplay_cmap *p) 713 { 714 u_int index = p->index, count = p->count; 715 int error; 716 717 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 718 return (EINVAL); 719 720 error = copyout(&sc->sc_cmap.r[index], p->red, count); 721 if (error) 722 return error; 723 error = copyout(&sc->sc_cmap.g[index], p->green, count); 724 if (error) 725 return error; 726 error = copyout(&sc->sc_cmap.b[index], p->blue, count); 727 return error; 728 } 729 730 static int 731 set_cmap(struct sfb_softc *sc, struct wsdisplay_cmap *p) 732 { 733 struct hwcmap256 cmap; 734 u_int index = p->index, count = p->count; 735 int error, s; 736 737 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 738 return (EINVAL); 739 740 error = copyin(p->red, &cmap.r[index], count); 741 if (error) 742 return error; 743 error = copyin(p->green, &cmap.g[index], count); 744 if (error) 745 return error; 746 error = copyin(p->blue, &cmap.b[index], count); 747 if (error) 748 return error; 749 750 s = spltty(); 751 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count); 752 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count); 753 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count); 754 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 755 splx(s); 756 return (0); 757 } 758 759 static int 760 set_cursor(struct sfb_softc *sc, struct wsdisplay_cursor *p) 761 { 762 #define cc (&sc->sc_cursor) 763 u_int v, index = 0, count = 0, icount = 0; 764 uint8_t r[2], g[2], b[2], image[512], mask[512]; 765 int error, s; 766 767 v = p->which; 768 if (v & WSDISPLAY_CURSOR_DOCMAP) { 769 index = p->cmap.index; 770 count = p->cmap.count; 771 if (index >= 2 || count > 2 - index) 772 return (EINVAL); 773 error = copyin(p->cmap.red, &r[index], count); 774 if (error) 775 return error; 776 error = copyin(p->cmap.green, &g[index], count); 777 if (error) 778 return error; 779 error = copyin(p->cmap.blue, &b[index], count); 780 if (error) 781 return error; 782 } 783 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 784 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 785 return (EINVAL); 786 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 787 error = copyin(p->image, image, icount); 788 if (error) 789 return error; 790 error = copyin(p->mask, mask, icount); 791 if (error) 792 return error; 793 } 794 795 s = spltty(); 796 if (v & WSDISPLAY_CURSOR_DOCUR) 797 sc->sc_curenb = p->enable; 798 if (v & WSDISPLAY_CURSOR_DOPOS) 799 set_curpos(sc, &p->pos); 800 if (v & WSDISPLAY_CURSOR_DOHOT) 801 cc->cc_hot = p->hot; 802 if (v & WSDISPLAY_CURSOR_DOCMAP) { 803 memcpy(&cc->cc_color[index], &r[index], count); 804 memcpy(&cc->cc_color[index + 2], &g[index], count); 805 memcpy(&cc->cc_color[index + 4], &b[index], count); 806 } 807 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 808 cc->cc_size = p->size; 809 memset(cc->cc_image, 0, sizeof cc->cc_image); 810 memcpy(cc->cc_image, image, icount); 811 memset(cc->cc_mask, 0, sizeof cc->cc_mask); 812 memcpy(cc->cc_mask, mask, icount); 813 } 814 sc->sc_changed |= v; 815 splx(s); 816 817 return (0); 818 #undef cc 819 } 820 821 static int 822 get_cursor(struct sfb_softc *sc, struct wsdisplay_cursor *p) 823 { 824 825 return (EPASSTHROUGH); /* XXX */ 826 } 827 828 static void 829 set_curpos(struct sfb_softc *sc, struct wsdisplay_curpos *curpos) 830 { 831 struct rasops_info *ri = sc->sc_ri; 832 int x = curpos->x, y = curpos->y; 833 834 if (y < 0) 835 y = 0; 836 else if (y > ri->ri_height) 837 y = ri->ri_height; 838 if (x < 0) 839 x = 0; 840 else if (x > ri->ri_width) 841 x = ri->ri_width; 842 sc->sc_cursor.cc_pos.x = x; 843 sc->sc_cursor.cc_pos.y = y; 844 } 845 846 #define MODE_SIMPLE 0 847 #define MODE_OPAQUESTIPPLE 1 848 #define MODE_OPAQUELINE 2 849 #define MODE_TRANSPARENTSTIPPLE 5 850 #define MODE_TRANSPARENTLINE 6 851 #define MODE_COPY 7 852 853 /* parameters for 8bpp configuration */ 854 #define SFBALIGNMASK 0x7 855 #define SFBSTIPPLEALL1 0xffffffff 856 #define SFBSTIPPLEBITS 32 857 #define SFBSTIPPLEBITMASK 0x1f 858 #define SFBSTIPPLEBYTESDONE 32 859 #define SFBCOPYALL1 0xffffffff 860 #define SFBCOPYBITS 32 861 #define SFBCOPYBITMASK 0x1f 862 #define SFBCOPYBYTESDONE 32 863 864 #if defined(pmax) 865 #define WRITE_MB() 866 #define BUMP(p) (p) 867 #endif 868 869 #if defined(alpha) 870 #define WRITE_MB() tc_wmb() 871 /* SFB registers replicated in 128B stride; cycle after eight iterations */ 872 #define BUMP(p) ((p) = (void *)(((long)(p) + 0x80) & ~0x400)) 873 #endif 874 875 #define SFBMODE(p, v) \ 876 SFBWRITE32(BUMP(p), SFB_ASIC_MODE, (v)) 877 #define SFBROP(p, v) \ 878 SFBWRITE32(BUMP(p), SFB_ASIC_ROP, (v)) 879 #define SFBPLANEMASK(p, v) \ 880 SFBWRITE32(BUMP(p), SFB_ASIC_PLANEMASK, (v)) 881 #define SFBPIXELMASK(p, v) \ 882 SFBWRITE32(BUMP(p), SFB_ASIC_PIXELMASK, (v)) 883 #define SFBADDRESS(p, v) \ 884 SFBWRITE32(BUMP(p), SFB_ASIC_ADDRESS, (v)) 885 #define SFBSTART(p, v) \ 886 SFBWRITE32(BUMP(p), SFB_ASIC_START, (v)) 887 #define SFBPIXELSHIFT(p, v) \ 888 SFBWRITE32(BUMP(p), SFB_ASIC_PIXELSHIFT, (v)) 889 #define SFBFG(p, v) \ 890 SFBWRITE32(BUMP(p), SFB_ASIC_FG, (v)) 891 #define SFBBG(p, v) \ 892 SFBWRITE32(BUMP(p), SFB_ASIC_BG, (v)) 893 894 /* 895 * Paint the cursor. 896 */ 897 static void 898 sfb_do_cursor(struct rasops_info *ri) 899 { 900 char *sfb, *p; 901 int scanspan, height, width, align, x, y; 902 uint32_t lmask, rmask; 903 904 x = ri->ri_ccol * ri->ri_font->fontwidth; 905 y = ri->ri_crow * ri->ri_font->fontheight; 906 scanspan = ri->ri_stride; 907 height = ri->ri_font->fontheight; 908 909 p = ri->ri_bits + y * scanspan + x; 910 align = (long)p & SFBALIGNMASK; 911 p -= align; 912 width = ri->ri_font->fontwidth + align; 913 lmask = SFBSTIPPLEALL1 << align; 914 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 915 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 916 917 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 918 SFBPLANEMASK(sfb, ~0); 919 SFBROP(sfb, 6); /* ROP_XOR */ 920 SFBFG(sfb, ~0); 921 922 lmask = lmask & rmask; 923 while (height > 0) { 924 SFBADDRESS(sfb, (long)p); 925 SFBSTART(sfb, lmask); 926 p += scanspan; 927 height--; 928 } 929 SFBMODE(sfb, MODE_SIMPLE); 930 SFBROP(sfb, 3); /* ROP_COPY */ 931 } 932 933 /* 934 * Paint a character. 935 */ 936 static void 937 sfb_putchar(void *id, int row, int col, u_int uc, long attr) 938 { 939 struct rasops_info *ri = id; 940 char *sfb, *p; 941 int scanspan, height, width, align, x, y; 942 uint32_t lmask, rmask, glyph; 943 uint8_t *g; 944 945 x = col * ri->ri_font->fontwidth; 946 y = row * ri->ri_font->fontheight; 947 scanspan = ri->ri_stride; 948 height = ri->ri_font->fontheight; 949 uc -= ri->ri_font->firstchar; 950 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 951 952 p = ri->ri_bits + y * scanspan + x; 953 align = (long)p & SFBALIGNMASK; 954 p -= align; 955 width = ri->ri_font->fontwidth + align; 956 lmask = SFBSTIPPLEALL1 << align; 957 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 958 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 959 960 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 961 SFBPLANEMASK(sfb, ~0); 962 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]); 963 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 964 965 /* XXX 2B stride fonts only XXX */ 966 lmask = lmask & rmask; 967 while (height > 0) { 968 glyph = *(uint16_t *)g; /* XXX */ 969 SFBPIXELMASK(sfb, lmask); 970 SFBADDRESS(sfb, (long)p); 971 SFBSTART(sfb, glyph << align); 972 p += scanspan; 973 g += 2; /* XXX */ 974 height--; 975 } 976 if (attr & 1 /* UNDERLINE */) { 977 p -= scanspan * 2; 978 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 979 SFBADDRESS(sfb, (long)p); 980 SFBSTART(sfb, lmask); 981 } 982 983 SFBMODE(sfb, MODE_SIMPLE); 984 SFBPIXELMASK(sfb, ~0); /* entire pixel */ 985 } 986 987 #if 0 988 /* 989 * Copy characters in a line. 990 */ 991 static void 992 sfb_copycols(void *id, int row, int srccol, int dstcol, int ncols) 993 { 994 struct rasops_info *ri = id; 995 void *sp, *dp, *basex, *sfb; 996 int scanspan, height, width, aligns, alignd, shift, w, y; 997 uint32_t lmaskd, rmaskd; 998 999 scanspan = ri->ri_stride; 1000 y = row * ri->ri_font->fontheight; 1001 basex = ri->ri_bits + y * scanspan; 1002 height = ri->ri_font->fontheight; 1003 w = ri->ri_font->fontwidth * ncols; 1004 1005 sp = basex + ri->ri_font->fontwidth * srccol; 1006 aligns = (long)sp & SFBALIGNMASK; 1007 dp = basex + ri->ri_font->fontwidth * dstcol; 1008 alignd = (long)dp & SFBALIGNMASK; 1009 sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET; 1010 1011 SFBMODE(sfb, MODE_COPY); 1012 SFBPLANEMASK(sfb, ~0); 1013 /* small enough to fit in a single 32bit */ 1014 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) { 1015 SFBPIXELSHIFT(sfb, alignd - aligns); 1016 lmaskd = SFBCOPYALL1 << alignd; 1017 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK); 1018 lmaskd = lmaskd & rmaskd; 1019 sp -= aligns; 1020 dp -= alignd; 1021 while (height > 0) { 1022 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB(); 1023 MEMWRITE32(dp, lmaskd); WRITE_MB(); 1024 sp += scanspan; 1025 dp += scanspan; 1026 height--; 1027 } 1028 } 1029 /* copy forward (left-to-right) */ 1030 else if (dstcol < srccol || srccol + ncols < dstcol) { 1031 void *sq, dq; 1032 1033 shift = alignd - aligns; 1034 if (shift < 0) { 1035 shift = 8 + shift; /* enforce right rotate */ 1036 alignd += 8; /* bearing on left edge */ 1037 } 1038 width = alignd + w; 1039 lmaskd = SFBCOPYALL1 << alignd; 1040 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1041 sp -= aligns; 1042 dp -= alignd; 1043 1044 SFBPIXELSHIFT(sfb, shift); 1045 w = width; 1046 sq = sp; 1047 dq = dp; 1048 while (height > 0) { 1049 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB(); 1050 MEMWRITE32(dp, lmaskd); WRITE_MB(); 1051 width -= 2 * SFBCOPYBITS; 1052 while (width > 0) { 1053 sp += SFBCOPYBYTESDONE; 1054 dp += SFBCOPYBYTESDONE; 1055 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB(); 1056 MEMWRITE32(dp, SFBCOPYALL1); WRITE_MB(); 1057 width -= SFBCOPYBITS; 1058 } 1059 sp += SFBCOPYBYTESDONE; 1060 dp += SFBCOPYBYTESDONE; 1061 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB(); 1062 MEMWRITE32(dp, rmaskd); WRITE_MB(); 1063 sp = (sq += scanspan); 1064 dp = (dq += scanspan); 1065 width = w; 1066 height--; 1067 } 1068 } 1069 /* copy backward (right-to-left) */ 1070 else { 1071 void *sq, dq; 1072 1073 shift = alignd - aligns; 1074 if (shift > 0) { 1075 shift = shift - 8; /* force left rotate */ 1076 alignd += 24; 1077 } 1078 width = alignd + w; 1079 lmaskd = SFBCOPYALL1 << alignd; 1080 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1081 sp -= aligns; 1082 dp -= alignd; 1083 1084 SFBPIXELSHIFT(sfb, shift); 1085 w = width; 1086 sq = sp += (((aligns + w) - 1) & ~31); 1087 dq = dp += (((alignd + w) - 1) & ~31); 1088 while (height > 0) { 1089 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB(); 1090 MEMWRITE32(dp, rmaskd); WRITE_MB(); 1091 width -= 2 * SFBCOPYBITS; 1092 while (width > 0) { 1093 sp -= SFBCOPYBYTESDONE; 1094 dp -= SFBCOPYBYTESDONE; 1095 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB(); 1096 MEMWRITE32(dp, SFBCOPYALL1); WRITE_MB(); 1097 width -= SFBCOPYBITS; 1098 } 1099 sp -= SFBCOPYBYTESDONE; 1100 dp -= SFBCOPYBYTESDONE; 1101 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB(); 1102 MEMWRITE32(dp, lmaskd); WRITE_MB(); 1103 1104 sp = (sq += scanspan); 1105 dp = (dq += scanspan); 1106 width = w; 1107 height--; 1108 } 1109 } 1110 SFBMODE(sfb, MODE_SIMPLE); 1111 SFBPIXELSHIFT(sfb, 0); 1112 } 1113 #endif 1114 1115 /* 1116 * Clear characters in a line. 1117 */ 1118 static void 1119 sfb_erasecols(void *id, int row, int startcol, int ncols, long attr) 1120 { 1121 struct rasops_info *ri = id; 1122 char *sfb, *p; 1123 int scanspan, startx, height, width, align, w, y; 1124 uint32_t lmask, rmask; 1125 1126 scanspan = ri->ri_stride; 1127 y = row * ri->ri_font->fontheight; 1128 startx = startcol * ri->ri_font->fontwidth; 1129 height = ri->ri_font->fontheight; 1130 w = ri->ri_font->fontwidth * ncols; 1131 1132 p = ri->ri_bits + y * scanspan + startx; 1133 align = (long)p & SFBALIGNMASK; 1134 p -= align; 1135 width = w + align; 1136 lmask = SFBSTIPPLEALL1 << align; 1137 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1138 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1139 1140 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1141 SFBPLANEMASK(sfb, ~0); 1142 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1143 if (width <= SFBSTIPPLEBITS) { 1144 lmask = lmask & rmask; 1145 while (height > 0) { 1146 SFBADDRESS(sfb, (long)p); 1147 SFBSTART(sfb, lmask); 1148 p += scanspan; 1149 height--; 1150 } 1151 } 1152 else { 1153 char *q = p; 1154 while (height > 0) { 1155 MEMWRITE32(p, lmask); WRITE_MB(); 1156 width -= 2 * SFBSTIPPLEBITS; 1157 while (width > 0) { 1158 p += SFBSTIPPLEBYTESDONE; 1159 MEMWRITE32(p, SFBSTIPPLEALL1); WRITE_MB(); 1160 width -= SFBSTIPPLEBITS; 1161 } 1162 p += SFBSTIPPLEBYTESDONE; 1163 MEMWRITE32(p, rmask); WRITE_MB(); 1164 WRITE_MB(); 1165 1166 p = (q += scanspan); 1167 width = w + align; 1168 height--; 1169 } 1170 } 1171 SFBMODE(sfb, MODE_SIMPLE); 1172 } 1173 1174 /* 1175 * Copy lines. 1176 */ 1177 static void 1178 sfb_copyrows(void *id, int srcrow, int dstrow, int nrows) 1179 { 1180 struct rasops_info *ri = id; 1181 char *sfb, *p; 1182 int scanspan, offset, srcy, height, width, align, w; 1183 uint32_t lmask, rmask; 1184 1185 scanspan = ri->ri_stride; 1186 height = ri->ri_font->fontheight * nrows; 1187 offset = (dstrow - srcrow) * ri->ri_yscale; 1188 srcy = ri->ri_font->fontheight * srcrow; 1189 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1190 scanspan = -scanspan; 1191 srcy += height; 1192 } 1193 1194 p = ri->ri_bits + srcy * ri->ri_stride; 1195 align = (long)p & SFBALIGNMASK; 1196 p -= align; 1197 w = ri->ri_emuwidth; 1198 width = w + align; 1199 lmask = SFBCOPYALL1 << align; 1200 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1201 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1202 1203 SFBMODE(sfb, MODE_COPY); 1204 SFBPLANEMASK(sfb, ~0); 1205 SFBPIXELSHIFT(sfb, 0); 1206 if (width <= SFBCOPYBITS) { 1207 /* never happens */; 1208 } 1209 else { 1210 char *q = p; 1211 while (height > 0) { 1212 MEMWRITE32(p, lmask); 1213 MEMWRITE32(p + offset, lmask); 1214 width -= 2 * SFBCOPYBITS; 1215 while (width > 0) { 1216 p += SFBCOPYBYTESDONE; 1217 MEMWRITE32(p, SFBCOPYALL1); 1218 MEMWRITE32(p + offset, SFBCOPYALL1); 1219 width -= SFBCOPYBITS; 1220 } 1221 p += SFBCOPYBYTESDONE; 1222 MEMWRITE32(p, rmask); 1223 MEMWRITE32(p + offset, rmask); 1224 1225 p = (q += scanspan); 1226 width = w + align; 1227 height--; 1228 } 1229 } 1230 SFBMODE(sfb, MODE_SIMPLE); 1231 } 1232 1233 /* 1234 * Erase lines. 1235 */ 1236 void 1237 sfb_eraserows(void *id, int startrow, int nrows, long attr) 1238 { 1239 struct rasops_info *ri = id; 1240 char *sfb, *p; 1241 int scanspan, starty, height, width, align, w; 1242 uint32_t lmask, rmask; 1243 1244 scanspan = ri->ri_stride; 1245 starty = ri->ri_font->fontheight * startrow; 1246 height = ri->ri_font->fontheight * nrows; 1247 1248 p = ri->ri_bits + starty * scanspan; 1249 align = (long)p & SFBALIGNMASK; 1250 p -= align; 1251 w = ri->ri_emuwidth; 1252 width = w + align; 1253 lmask = SFBSTIPPLEALL1 << align; 1254 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1255 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1256 1257 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1258 SFBPLANEMASK(sfb, ~0); 1259 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1260 if (width <= SFBSTIPPLEBITS) { 1261 /* never happens */; 1262 } 1263 else { 1264 char *q = p; 1265 while (height > 0) { 1266 MEMWRITE32(p, lmask); WRITE_MB(); 1267 width -= 2 * SFBSTIPPLEBITS; 1268 while (width > 0) { 1269 p += SFBSTIPPLEBYTESDONE; 1270 MEMWRITE32(p, SFBSTIPPLEALL1); WRITE_MB(); 1271 width -= SFBSTIPPLEBITS; 1272 } 1273 p += SFBSTIPPLEBYTESDONE; 1274 MEMWRITE32(p, rmask); WRITE_MB(); 1275 1276 p = (q += scanspan); 1277 width = w + align; 1278 height--; 1279 } 1280 } 1281 SFBMODE(sfb, MODE_SIMPLE); 1282 } 1283