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