1 /* $NetBSD: sfb.c,v 1.77 2008/07/09 13:19:33 joerg 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.77 2008/07/09 13:19:33 joerg 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 * u_int8_t u0; 73 * u_int8_t u1; 74 * u_int8_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 * u_int32_t bt_lo; 81 * u_int32_t bt_hi; 82 * u_int32_t bt_reg; 83 * u_int32_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 u_int32_t *)((p) + (i)) = (v); tc_wmb(); \ 95 } while (/* CONSTCOND */ 0) 96 #define SFBWRITE32(p,i,v) do { \ 97 *(volatile u_int32_t *)((p) + (i)) = (v); \ 98 } while (/* CONSTCOND */ 0) 99 #define MEMWRITE32(p,v) do { \ 100 *(volatile u_int32_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 u_int8_t r[CMAP_SIZE]; 111 u_int8_t g[CMAP_SIZE]; 112 u_int8_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 u_int8_t cc_color[6]; 122 u_int64_t cc_image[CURSOR_MAX_SIZE]; 123 u_int64_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 u_int8_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 sc->nscreens = 1; 272 } 273 else { 274 MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info), 275 M_DEVBUF, M_NOWAIT); 276 if (ri == NULL) { 277 printf(": can't alloc memory\n"); 278 return; 279 } 280 memset(ri, 0, sizeof(struct rasops_info)); 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 u_int8_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 = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP); 335 vsetup = *(u_int32_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 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); 362 if (cookie <= 0) 363 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, 364 WSDISPLAY_FONTORDER_L2R); 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 u_int8_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 u_int8_t *ip, *mp, img, msk; 599 u_int8_t u; 600 int bcnt; 601 602 ip = (u_int8_t *)sc->sc_cursor.cc_image; 603 mp = (u_int8_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 u_int8_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 u_int32_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 u_int32_t lmask, rmask, glyph; 948 u_int8_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 = *(u_int16_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 u_int32_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 u_int32_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 u_int32_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 u_int32_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