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