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