1 /* $NetBSD: sfbplus.c,v 1.31 2008/07/09 13:19:33 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tohru Nishimura. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: sfbplus.c,v 1.31 2008/07/09 13:19:33 joerg Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/device.h> 39 #include <sys/errno.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 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(device_t, cfdata_t, void *); 127 static void sfbpattach(device_t, device_t, void *); 128 129 CFATTACH_DECL_NEW(sfbp, sizeof(struct sfbp_softc), 130 sfbpmatch, sfbpattach, NULL, NULL); 131 132 static void sfbp_common_init(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(void *, void *, u_long, void *, int, struct lwp *); 152 static paddr_t sfbmmap(void *, void *, off_t, int); 153 154 static int sfb_alloc_screen(void *, const struct wsscreen_descr *, 155 void **, int *, int *, long *); 156 static void sfb_free_screen(void *, void *); 157 static int sfb_show_screen(void *, void *, int, 158 void (*) (void *, int, int), void *); 159 static void sfbp_putchar(void *, int, int, u_int, long); 160 static void sfbp_erasecols(void *, int, int, int, long); 161 static void sfbp_eraserows(void *, int, int, long); 162 static void sfbp_copyrows(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(void *); 174 static void bt459visible(void *, int); 175 static void bt459locate(void *, struct hwcursor64 *); 176 static void bt459shape(void *, struct wsdisplay_curpos *, u_int64_t *); 177 static void bt459color(void *, u_int8_t *); 178 static void bt459setlut(void *, struct hwcmap256 *); 179 180 static void sfbpvisible(void *, int); 181 static void sfbplocate(void *, struct hwcursor64 *); 182 static void sfbpshape(void *, struct wsdisplay_curpos *, u_int64_t *); 183 static void bt463init(void *); 184 static void bt463color(void *, u_int8_t *); 185 static void noplut(void *, struct hwcmap256 *); 186 187 /* EXPORT */ int sfbp_cnattach(tc_addr_t); 188 static int sfbpintr(void *); 189 static void sfbp_cmap_init(struct sfbp_softc *); 190 191 static int get_cmap(struct sfbp_softc *, struct wsdisplay_cmap *); 192 static int set_cmap(struct sfbp_softc *, struct wsdisplay_cmap *); 193 static int set_cursor(struct sfbp_softc *, struct wsdisplay_cursor *); 194 static int get_cursor(struct sfbp_softc *, struct wsdisplay_cursor *); 195 static void set_curpos(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(device_t parent, cfdata_t match, void *aux) 241 { 242 struct tc_attach_args *ta = aux; 243 244 if (strncmp("PMAGD ", ta->ta_modname, TC_ROM_LLEN) != 0) 245 return (0); 246 247 return (1); 248 } 249 250 static void 251 sfbpattach(device_t parent, device_t self, void *aux) 252 { 253 struct sfbp_softc *sc = device_private(self); 254 struct tc_attach_args *ta = aux; 255 struct rasops_info *ri; 256 struct wsemuldisplaydev_attach_args waa; 257 char *asic; 258 int console; 259 260 console = (ta->ta_addr == sfbp_consaddr); 261 if (console) { 262 sc->sc_ri = ri = &sfbp_console_ri; 263 sc->nscreens = 1; 264 } 265 else { 266 MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info), 267 M_DEVBUF, M_NOWAIT); 268 if (ri == NULL) { 269 printf(": can't alloc memory\n"); 270 return; 271 } 272 memset(ri, 0, sizeof(struct rasops_info)); 273 274 ri->ri_hw = (void *)ta->ta_addr; 275 sfbp_common_init(ri); 276 sc->sc_ri = ri; 277 } 278 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, 279 (ri->ri_depth != 32) ? 8 : 24); 280 281 sc->sc_vaddr = ta->ta_addr; 282 sc->sc_cursor.cc_magic.x = HX_MAGIC_X; 283 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y; 284 sc->sc_blanked = sc->sc_curenb = 0; 285 286 if (ri->ri_depth == 8) { 287 sc->sc_hwops.visible = bt459visible; 288 sc->sc_hwops.locate = bt459locate; 289 sc->sc_hwops.shape = bt459shape; 290 sc->sc_hwops.color = bt459color; 291 sc->sc_hwops.setlut = bt459setlut; 292 sc->sc_hwops.getlut = noplut; 293 } else { 294 sc->sc_hwops.visible = sfbpvisible; 295 sc->sc_hwops.locate = sfbplocate; 296 sc->sc_hwops.shape = sfbpshape; 297 sc->sc_hwops.color = bt463color; 298 sc->sc_hwops.setlut = noplut; 299 sc->sc_hwops.getlut = noplut; 300 } 301 sfbp_cmap_init(sc); 302 303 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc); 304 305 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 306 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 307 *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; 308 309 waa.console = console; 310 waa.scrdata = &sfb_screenlist; 311 waa.accessops = &sfb_accessops; 312 waa.accesscookie = sc; 313 314 config_found(self, &waa, wsemuldisplaydevprint); 315 } 316 317 static void 318 sfbp_cmap_init(struct sfbp_softc *sc) 319 { 320 struct hwcmap256 *cm; 321 const u_int8_t *p; 322 int index; 323 324 if (sc->sc_ri->ri_depth != 8) 325 return; 326 327 cm = &sc->sc_cmap; 328 p = rasops_cmap; 329 for (index = 0; index < CMAP_SIZE; index++, p += 3) { 330 cm->r[index] = p[0]; 331 cm->g[index] = p[1]; 332 cm->b[index] = p[2]; 333 } 334 } 335 336 static void 337 sfbp_common_init(struct rasops_info *ri) 338 { 339 char *base, *asic; 340 int i, depth, hsetup, vsetup, vbase, cookie; 341 342 base = ri->ri_hw; 343 asic = base + SFB_ASIC_OFFSET; 344 hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP); 345 vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP); 346 i = *(u_int32_t *)(asic + SFB_ASIC_DEEP); 347 depth = (i & 01) ? 32 : 8; 348 349 /* 350 * - neglect 0,1 cases of hsetup register. 351 * - observed 804x600?, 644x480? values. 352 */ 353 354 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1; 355 vbase *= (i & 0x20) ? 2048 : 4096; /* VRAM chip size */ 356 if (i & 1) vbase *= 4; /* bytes per pixel */ 357 358 *(u_int32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0; 359 *(u_int32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0; 360 *(u_int32_t *)(asic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */ 361 *(u_int32_t *)(asic + SFB_ASIC_ROP) = 3; /* ROP_COPY */ 362 363 /* initialize colormap and cursor hardware */ 364 if (depth != 32) { 365 *(u_int32_t *)(asic + 0x180000) = 0; /* Bt459 reset */ 366 bt459init(base + SFB_RAMDAC_OFFSET); 367 } 368 else { 369 bt463init(base + SFB_RAMDAC_OFFSET); 370 } 371 372 ri->ri_flg = RI_CENTER; 373 ri->ri_flg = 0; /* XXX 32bpp RI_CENTER fails XXX */ 374 ri->ri_depth = depth; 375 ri->ri_width = (hsetup & 0x1ff) << 2; 376 ri->ri_height = (vsetup & 0x7ff); 377 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8); 378 ri->ri_bits = base + 0x800000 + vbase; 379 380 if (depth == 32) { 381 ri->ri_rnum = 8; 382 ri->ri_gnum = 8; 383 ri->ri_bnum = 8; 384 ri->ri_rpos = 16; 385 ri->ri_gpos = 8; 386 ri->ri_bpos = 0; 387 } 388 389 /* clear the screen */ 390 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 391 392 wsfont_init(); 393 /* prefer 12 pixel wide font */ 394 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L, 395 WSDISPLAY_FONTORDER_L2R); 396 if (cookie <= 0) 397 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, 398 WSDISPLAY_FONTORDER_L2R); 399 if (cookie <= 0) { 400 printf("sfbp: font table is empty\n"); 401 return; 402 } 403 404 /* the accelerated sfbp_putchar() needs LSbit left */ 405 if (wsfont_lock(cookie, &ri->ri_font)) { 406 printf("sfb: couldn't lock font\n"); 407 return; 408 } 409 ri->ri_wsfcookie = cookie; 410 411 rasops_init(ri, 34, 80); 412 413 /* add our accelerated functions */ 414 ri->ri_ops.putchar = sfbp_putchar; 415 ri->ri_ops.erasecols = sfbp_erasecols; 416 ri->ri_ops.copyrows = sfbp_copyrows; 417 ri->ri_ops.eraserows = sfbp_eraserows; 418 419 /* XXX shouldn't be global */ 420 sfbp_stdscreen.nrows = ri->ri_rows; 421 sfbp_stdscreen.ncols = ri->ri_cols; 422 sfbp_stdscreen.textops = &ri->ri_ops; 423 sfbp_stdscreen.capabilities = ri->ri_caps; 424 /* our accelerated putchar can't underline */ 425 sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE; 426 } 427 428 static int 429 sfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 430 { 431 struct sfbp_softc *sc = v; 432 struct rasops_info *ri = sc->sc_ri; 433 int turnoff, s; 434 435 switch (cmd) { 436 case WSDISPLAYIO_GTYPE: 437 *(u_int *)data = WSDISPLAY_TYPE_SFBP; 438 return (0); 439 440 case WSDISPLAYIO_GINFO: 441 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 442 wsd_fbip->height = ri->ri_height; 443 wsd_fbip->width = ri->ri_width; 444 wsd_fbip->depth = ri->ri_depth; 445 wsd_fbip->cmsize = CMAP_SIZE; /* XXX */ 446 #undef fbt 447 return (0); 448 449 case WSDISPLAYIO_GETCMAP: 450 return get_cmap(sc, (struct wsdisplay_cmap *)data); 451 452 case WSDISPLAYIO_PUTCMAP: 453 return set_cmap(sc, (struct wsdisplay_cmap *)data); 454 455 case WSDISPLAYIO_SVIDEO: 456 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 457 if ((sc->sc_blanked == 0) ^ turnoff) { 458 sc->sc_blanked = turnoff; 459 #if 0 /* XXX later XXX */ 460 Low order 3bit control visibilities of screen and builtin cursor. 461 #endif /* XXX XXX XXX */ 462 } 463 return (0); 464 465 case WSDISPLAYIO_GVIDEO: 466 *(u_int *)data = sc->sc_blanked ? 467 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 468 return (0); 469 470 case WSDISPLAYIO_GCURPOS: 471 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 472 return (0); 473 474 case WSDISPLAYIO_SCURPOS: 475 s = spltty(); 476 set_curpos(sc, (struct wsdisplay_curpos *)data); 477 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 478 splx(s); 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 case WSDISPLAYIO_SMODE: 493 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { 494 s = spltty(); 495 sfbp_cmap_init(sc); 496 sc->sc_curenb = 0; 497 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR | 498 WSDISPLAY_CMAP_DOLUT); 499 splx(s); 500 } 501 return (0); 502 } 503 return (EPASSTHROUGH); 504 } 505 506 paddr_t 507 sfbmmap(void *v, void *vs, off_t offset, int prot) 508 { 509 struct sfbp_softc *sc = v; 510 511 if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */ 512 return (-1); 513 return machine_btop(sc->sc_vaddr + offset); 514 } 515 516 static int 517 sfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 518 int *curxp, int *curyp, long *attrp) 519 { 520 struct sfbp_softc *sc = v; 521 struct rasops_info *ri = sc->sc_ri; 522 long defattr; 523 524 if (sc->nscreens > 0) 525 return (ENOMEM); 526 527 *cookiep = ri; /* one and only for now */ 528 *curxp = 0; 529 *curyp = 0; 530 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 531 *attrp = defattr; 532 sc->nscreens++; 533 return (0); 534 } 535 536 void 537 sfb_free_screen(void *v, void *cookie) 538 { 539 struct sfbp_softc *sc = v; 540 541 if (sc->sc_ri == &sfbp_console_ri) 542 panic("sfb_free_screen: console"); 543 544 sc->nscreens--; 545 } 546 547 static int 548 sfb_show_screen(void *v, void *cookie, int waitok, 549 void (*cb)(void *, int, int), void *cbarg) 550 { 551 552 return (0); 553 } 554 555 int 556 sfbp_cnattach(tc_addr_t addr) 557 { 558 struct rasops_info *ri; 559 long defattr; 560 561 ri = &sfbp_console_ri; 562 ri->ri_hw = (void *)addr; 563 sfbp_common_init(ri); 564 (*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr); 565 wsdisplay_cnattach(&sfbp_stdscreen, ri, 0, 0, defattr); 566 sfbp_consaddr = addr; 567 return (0); 568 } 569 570 static int 571 sfbpintr(void *arg) 572 { 573 #define cc (&sc->sc_cursor) 574 struct sfbp_softc *sc = arg; 575 char *base, *asic; 576 u_int32_t sisr; 577 int v; 578 579 base = sc->sc_ri->ri_hw; 580 asic = base + SFB_ASIC_OFFSET; 581 sisr = *((u_int32_t *)asic + TGA_REG_SISR); 582 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 583 584 if (sc->sc_changed == 0) 585 goto done; 586 587 v = sc->sc_changed; 588 if (v & WSDISPLAY_CURSOR_DOCUR) 589 (*sc->sc_hwops.visible)(base, sc->sc_curenb); 590 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) 591 (*sc->sc_hwops.locate)(base, cc); 592 if (v & WSDISPLAY_CURSOR_DOCMAP) 593 (*sc->sc_hwops.color)(base, cc->cc_color); 594 if (v & WSDISPLAY_CURSOR_DOSHAPE) 595 (*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image); 596 if (v & WSDISPLAY_CMAP_DOLUT) 597 (*sc->sc_hwops.setlut)(base, &sc->sc_cmap); 598 sc->sc_changed = 0; 599 done: 600 *((u_int32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb(); 601 return (1); 602 #undef cc 603 } 604 605 static void 606 bt459init(void *vdac) 607 { 608 const u_int8_t *p; 609 int i; 610 611 SELECT(vdac, BT459_IREG_COMMAND_0); 612 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb(); 613 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb(); 614 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb(); 615 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb(); 616 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb(); 617 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb(); 618 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb(); 619 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb(); 620 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb(); 621 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb(); 622 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb(); 623 624 SELECT(vdac, BT459_IREG_CCR); 625 REG(vdac, bt_reg) = 0x0; tc_wmb(); 626 REG(vdac, bt_reg) = 0x0; tc_wmb(); 627 REG(vdac, bt_reg) = 0x0; tc_wmb(); 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 639 /* build sane colormap */ 640 SELECT(vdac, 0); 641 p = rasops_cmap; 642 for (i = 0; i < CMAP_SIZE; i++, p += 3) { 643 REG(vdac, bt_cmap) = p[0]; tc_wmb(); 644 REG(vdac, bt_cmap) = p[1]; tc_wmb(); 645 REG(vdac, bt_cmap) = p[2]; tc_wmb(); 646 } 647 648 /* clear out cursor image */ 649 SELECT(vdac, BT459_IREG_CRAM_BASE); 650 for (i = 0; i < 1024; i++) 651 REG(vdac, bt_reg) = 0xff; tc_wmb(); 652 653 /* 654 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 655 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 656 * image color. CCOLOR_1 will be never used. 657 */ 658 SELECT(vdac, BT459_IREG_CCOLOR_1); 659 REG(vdac, bt_reg) = 0xff; tc_wmb(); 660 REG(vdac, bt_reg) = 0xff; tc_wmb(); 661 REG(vdac, bt_reg) = 0xff; tc_wmb(); 662 663 REG(vdac, bt_reg) = 0; tc_wmb(); 664 REG(vdac, bt_reg) = 0; tc_wmb(); 665 REG(vdac, bt_reg) = 0; tc_wmb(); 666 667 REG(vdac, bt_reg) = 0xff; tc_wmb(); 668 REG(vdac, bt_reg) = 0xff; tc_wmb(); 669 REG(vdac, bt_reg) = 0xff; tc_wmb(); 670 } 671 672 static void 673 bt463init(void *vdac) 674 { 675 int i; 676 677 SELECT(vdac, BT463_IREG_COMMAND_0); 678 REG(vdac, bt_reg) = 0x40; tc_wmb(); /* CMD 0 */ 679 REG(vdac, bt_reg) = 0x48; tc_wmb(); /* CMD 1 */ 680 REG(vdac, bt_reg) = 0xc0; tc_wmb(); /* CMD 2 */ 681 REG(vdac, bt_reg) = 0; tc_wmb(); /* !? 204 !? */ 682 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 0:7 */ 683 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 8:15 */ 684 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 16:23 */ 685 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 24:27 */ 686 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 0:7 */ 687 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 8:15 */ 688 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 16:23 */ 689 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 24:27 */ 690 REG(vdac, bt_reg) = 0x00; tc_wmb(); 691 692 SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE); 693 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) { 694 REG(vdac, bt_reg) = 0x00; /* 0:7 */ 695 REG(vdac, bt_reg) = 0xe1; /* 8:15 */ 696 REG(vdac, bt_reg) = 0x81; /* 16:23 */ 697 } 698 } 699 700 static int 701 get_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p) 702 { 703 u_int index = p->index, count = p->count; 704 int error; 705 706 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 707 return (EINVAL); 708 709 error = copyout(&sc->sc_cmap.r[index], p->red, count); 710 if (error) 711 return error; 712 error = copyout(&sc->sc_cmap.g[index], p->green, count); 713 if (error) 714 return error; 715 error = copyout(&sc->sc_cmap.b[index], p->blue, count); 716 return error; 717 } 718 719 static int 720 set_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p) 721 { 722 struct hwcmap256 cmap; 723 u_int index = p->index, count = p->count; 724 int error, s; 725 726 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 727 return (EINVAL); 728 729 error = copyin(p->red, &cmap.r[index], count); 730 if (error) 731 return error; 732 error = copyin(p->green, &cmap.g[index], count); 733 if (error) 734 return error; 735 error = copyin(p->blue, &cmap.b[index], count); 736 if (error) 737 return error; 738 739 s = spltty(); 740 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count); 741 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count); 742 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count); 743 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 744 splx(s); 745 return (0); 746 } 747 748 static int 749 set_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p) 750 { 751 #define cc (&sc->sc_cursor) 752 u_int v, index = 0, count = 0, icount = 0; 753 uint8_t r[2], g[2], b[2], image[512], mask[512]; 754 int error, s; 755 756 v = p->which; 757 if (v & WSDISPLAY_CURSOR_DOCMAP) { 758 index = p->cmap.index; 759 count = p->cmap.count; 760 if (index >= 2 || (index + count) > 2) 761 return (EINVAL); 762 error = copyin(p->cmap.red, &r[index], count); 763 if (error) 764 return error; 765 error = copyin(p->cmap.green, &g[index], count); 766 if (error) 767 return error; 768 error = copyin(p->cmap.blue, &b[index], count); 769 if (error) 770 return error; 771 } 772 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 773 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 774 return (EINVAL); 775 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 776 error = copyin(p->image, image, icount); 777 if (error) 778 return error; 779 error = copyin(p->mask, mask, icount); 780 if (error) 781 return error; 782 } 783 784 s = spltty(); 785 if (v & WSDISPLAY_CURSOR_DOCUR) 786 sc->sc_curenb = p->enable; 787 if (v & WSDISPLAY_CURSOR_DOPOS) 788 set_curpos(sc, &p->pos); 789 if (v & WSDISPLAY_CURSOR_DOHOT) 790 cc->cc_hot = p->hot; 791 if (v & WSDISPLAY_CURSOR_DOCMAP) { 792 memcpy(&cc->cc_color[index], &r[index], count); 793 memcpy(&cc->cc_color[index + 2], &g[index], count); 794 memcpy(&cc->cc_color[index + 4], &b[index], count); 795 } 796 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 797 cc->cc_size = p->size; 798 memset(cc->cc_image, 0, sizeof cc->cc_image); 799 memcpy(cc->cc_image, image, icount); 800 memset(cc->cc_mask, 0, sizeof cc->cc_mask); 801 memcpy(cc->cc_mask, mask, icount); 802 } 803 sc->sc_changed |= v; 804 splx(s); 805 806 return (0); 807 #undef cc 808 } 809 810 static int 811 get_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p) 812 { 813 return (EPASSTHROUGH); /* XXX */ 814 } 815 816 static void 817 set_curpos(struct sfbp_softc *sc, struct wsdisplay_curpos *curpos) 818 { 819 struct rasops_info *ri = sc->sc_ri; 820 int x = curpos->x, y = curpos->y; 821 822 if (y < 0) 823 y = 0; 824 else if (y > ri->ri_height) 825 y = ri->ri_height; 826 if (x < 0) 827 x = 0; 828 else if (x > ri->ri_width) 829 x = ri->ri_width; 830 sc->sc_cursor.cc_pos.x = x; 831 sc->sc_cursor.cc_pos.y = y; 832 } 833 834 static void 835 bt459visible(void *hw, int on) 836 { 837 hw = (char *)hw + SFB_RAMDAC_OFFSET; 838 SELECT(hw, BT459_IREG_CCR); 839 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00; 840 tc_wmb(); 841 } 842 843 static void 844 sfbpvisible(void *hw, int on) 845 { 846 /* XXX use SFBplus ASIC XX */ 847 } 848 849 static void 850 bt459locate(void *hw, 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 = (char *)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(void *hw, struct hwcursor64 *cc) 872 { 873 int x, y; 874 875 x = cc->cc_pos.x - cc->cc_hot.x; 876 y = cc->cc_pos.y - cc->cc_hot.y; 877 878 hw = (char *)hw + SFB_ASIC_OFFSET; 879 *((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff); 880 tc_wmb(); 881 } 882 883 static void 884 bt459color(void *hw, u_int8_t *cp) 885 { 886 887 hw = (char *)hw + SFB_RAMDAC_OFFSET; 888 889 SELECT(hw, BT459_IREG_CCOLOR_2); 890 REG(hw, bt_reg) = cp[1]; tc_wmb(); 891 REG(hw, bt_reg) = cp[3]; tc_wmb(); 892 REG(hw, bt_reg) = cp[5]; tc_wmb(); 893 894 REG(hw, bt_reg) = cp[0]; tc_wmb(); 895 REG(hw, bt_reg) = cp[2]; tc_wmb(); 896 REG(hw, bt_reg) = cp[4]; tc_wmb(); 897 } 898 899 static void 900 bt463color(void *hw, u_int8_t *cp) 901 { 902 } 903 904 static void 905 bt459shape(void *hw, struct wsdisplay_curpos *size, u_int64_t *image) 906 { 907 u_int8_t *ip, *mp, img, msk; 908 u_int8_t u; 909 int bcnt; 910 911 hw = (char *)hw + SFB_RAMDAC_OFFSET; 912 ip = (u_int8_t *)image; 913 mp = (u_int8_t *)(image + CURSOR_MAX_SIZE); 914 915 bcnt = 0; 916 SELECT(hw, BT459_IREG_CRAM_BASE+0); 917 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 918 while (bcnt < size->y * 16) { 919 /* pad right half 32 pixel when smaller than 33 */ 920 if ((bcnt & 0x8) && size->x < 33) { 921 REG(hw, bt_reg) = 0; tc_wmb(); 922 REG(hw, bt_reg) = 0; tc_wmb(); 923 } 924 else { 925 img = *ip++; 926 msk = *mp++; 927 img &= msk; /* cookie off image */ 928 u = (msk & 0x0f) << 4 | (img & 0x0f); 929 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 930 u = (msk & 0xf0) | (img & 0xf0) >> 4; 931 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 932 } 933 bcnt += 2; 934 } 935 /* pad unoccupied scan lines */ 936 while (bcnt < CURSOR_MAX_SIZE * 16) { 937 REG(hw, bt_reg) = 0; tc_wmb(); 938 REG(hw, bt_reg) = 0; tc_wmb(); 939 bcnt += 2; 940 } 941 } 942 943 static void 944 sfbpshape(void *hw, struct wsdisplay_curpos *size, u_int64_t *image) 945 { 946 /* XXX use SFBplus ASIC XXX */ 947 } 948 949 static void 950 bt459setlut(void *hw, struct hwcmap256 *cm) 951 { 952 int index; 953 954 hw = (char *)hw + SFB_RAMDAC_OFFSET; 955 SELECT(hw, 0); 956 for (index = 0; index < CMAP_SIZE; index++) { 957 REG(hw, bt_cmap) = cm->r[index]; tc_wmb(); 958 REG(hw, bt_cmap) = cm->g[index]; tc_wmb(); 959 REG(hw, bt_cmap) = cm->b[index]; tc_wmb(); 960 } 961 } 962 963 static void 964 noplut(void *hw, struct hwcmap256 *cm) 965 { 966 } 967 968 #define SFBBPP 32 969 970 #define MODE_SIMPLE 0 971 #define MODE_OPAQUESTIPPLE 1 972 #define MODE_OPAQUELINE 2 973 #define MODE_TRANSPARENTSTIPPLE 5 974 #define MODE_TRANSPARENTLINE 6 975 #define MODE_COPY 7 976 977 #if SFBBPP == 8 978 /* parameters for 8bpp configuration */ 979 #define SFBALIGNMASK 0x7 980 #define SFBPIXELBYTES 1 981 #define SFBSTIPPLEALL1 0xffffffff 982 #define SFBSTIPPLEBITS 32 983 #define SFBSTIPPLEBITMASK 0x1f 984 #define SFBSTIPPLEBYTESDONE 32 985 #define SFBCOPYALL1 0xffffffff 986 #define SFBCOPYBITS 32 987 #define SFBCOPYBITMASK 0x1f 988 #define SFBCOPYBYTESDONE 32 989 990 #elif SFBBPP == 32 991 /* parameters for 32bpp configuration */ 992 #define SFBALIGNMASK 0x7 993 #define SFBPIXELBYTES 4 994 #define SFBSTIPPLEALL1 0x0000ffff 995 #define SFBSTIPPLEBITS 16 996 #define SFBSTIPPLEBITMASK 0xf 997 #define SFBSTIPPLEBYTESDONE 32 998 #define SFBCOPYALL1 0x000000ff 999 #define SFBCOPYBITS 8 1000 #define SFBCOPYBITMASK 0x3 1001 #define SFBCOPYBYTESDONE 32 1002 #endif 1003 1004 #ifdef pmax 1005 #define WRITE_MB() 1006 #define BUMP(p) (p) 1007 #endif 1008 1009 #ifdef alpha 1010 #define WRITE_MB() tc_wmb() 1011 /* registers is replicated in 1KB stride; rap round 4th iteration */ 1012 #define BUMP(p) ((p) = (void *)(((long)(p) + 0x400) & ~0x1000)) 1013 #endif 1014 1015 #define SFBMODE(p, v) \ 1016 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v)) 1017 #define SFBROP(p, v) \ 1018 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v)) 1019 #define SFBPLANEMASK(p, v) \ 1020 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v)) 1021 #define SFBPIXELMASK(p, v) \ 1022 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v)) 1023 #define SFBADDRESS(p, v) \ 1024 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v)) 1025 #define SFBSTART(p, v) \ 1026 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v)) 1027 #define SFBPIXELSHIFT(p, v) \ 1028 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v)) 1029 #define SFBFG(p, v) \ 1030 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v)) 1031 #define SFBBG(p, v) \ 1032 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v)) 1033 #define SFBBCONT(p, v) \ 1034 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v)) 1035 1036 #define SFBDATA(p, v) \ 1037 (*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v)) 1038 1039 #define SFBCOPY64BYTESDONE 8 1040 #define SFBCOPY64BITS 64 1041 #define SFBCOPY64SRC(p, v) \ 1042 (*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v)) 1043 #define SFBCOPY64DST(p, v) \ 1044 (*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v)) 1045 1046 /* 1047 * Actually write a string to the frame buffer. 1048 */ 1049 static void 1050 sfbp_putchar(void *id, int row, int col, u_int uc, long attr) 1051 { 1052 struct rasops_info *ri = id; 1053 char *sfb, *p; 1054 int scanspan, height, width, align, x, y; 1055 u_int32_t lmask, rmask, glyph; 1056 u_int8_t *g; 1057 1058 x = col * ri->ri_font->fontwidth; 1059 y = row * ri->ri_font->fontheight; 1060 scanspan = ri->ri_stride; 1061 height = ri->ri_font->fontheight; 1062 uc -= ri->ri_font->firstchar; 1063 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 1064 1065 p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES; 1066 align = (long)p & SFBALIGNMASK; 1067 p -= align; 1068 align /= SFBPIXELBYTES; 1069 width = ri->ri_font->fontwidth + align; 1070 lmask = SFBSTIPPLEALL1 << align; 1071 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1072 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1073 1074 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 1075 SFBPLANEMASK(sfb, ~0); 1076 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]); 1077 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 1078 SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */ 1079 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask; 1080 1081 /* XXX 2B stride fonts only XXX */ 1082 while (height > 0) { 1083 glyph = *(u_int16_t *)g; /* XXX */ 1084 *(u_int32_t *)p = glyph << align; 1085 p += scanspan; 1086 g += 2; /* XXX */ 1087 height--; 1088 } 1089 SFBMODE(sfb, MODE_SIMPLE); 1090 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0; 1091 } 1092 1093 #undef SFBSTIPPLEALL1 1094 #undef SFBSTIPPLEBITS 1095 #undef SFBSTIPPLEBITMASK 1096 #define SFBSTIPPLEALL1 SFBCOPYALL1 1097 #define SFBSTIPPLEBITS SFBCOPYBITS 1098 #define SFBSTIPPLEBITMASK SFBCOPYBITMASK 1099 1100 /* 1101 * Clear characters in a line. 1102 */ 1103 static void 1104 sfbp_erasecols(void *id, int row, int startcol, int ncols, long attr) 1105 { 1106 struct rasops_info *ri = id; 1107 char *sfb, *p; 1108 int scanspan, startx, height, width, align, w, y; 1109 u_int32_t lmask, rmask; 1110 1111 scanspan = ri->ri_stride; 1112 y = row * ri->ri_font->fontheight; 1113 startx = startcol * ri->ri_font->fontwidth; 1114 height = ri->ri_font->fontheight; 1115 w = ri->ri_font->fontwidth * ncols; 1116 1117 p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES; 1118 align = (long)p & SFBALIGNMASK; 1119 align /= SFBPIXELBYTES; 1120 p -= align; 1121 width = w + align; 1122 lmask = SFBSTIPPLEALL1 << align; 1123 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1124 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1125 1126 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1127 SFBPLANEMASK(sfb, ~0); 1128 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1129 if (width <= SFBSTIPPLEBITS) { 1130 lmask = lmask & rmask; 1131 while (height > 0) { 1132 *(u_int32_t *)p = lmask; 1133 p += scanspan; 1134 height--; 1135 } 1136 } 1137 else { 1138 char *q = p; 1139 while (height > 0) { 1140 *(u_int32_t *)p = lmask; 1141 WRITE_MB(); 1142 width -= 2 * SFBSTIPPLEBITS; 1143 while (width > 0) { 1144 p += SFBSTIPPLEBYTESDONE; 1145 *(u_int32_t *)p = SFBSTIPPLEALL1; 1146 WRITE_MB(); 1147 width -= SFBSTIPPLEBITS; 1148 } 1149 p += SFBSTIPPLEBYTESDONE; 1150 *(u_int32_t *)p = rmask; 1151 WRITE_MB(); 1152 1153 p = (q += scanspan); 1154 width = w + align; 1155 height--; 1156 } 1157 } 1158 SFBMODE(sfb, MODE_SIMPLE); 1159 } 1160 1161 #if 1 1162 /* 1163 * Copy lines. 1164 */ 1165 static void 1166 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows) 1167 { 1168 struct rasops_info *ri = id; 1169 char *sfb, *p; 1170 int scanspan, offset, srcy, height, width, align, w; 1171 u_int32_t lmask, rmask; 1172 1173 scanspan = ri->ri_stride; 1174 height = ri->ri_font->fontheight * nrows; 1175 offset = (dstrow - srcrow) * ri->ri_yscale; 1176 srcy = ri->ri_font->fontheight * srcrow; 1177 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1178 scanspan = -scanspan; 1179 srcy += height; 1180 } 1181 1182 p = ri->ri_bits + srcy * ri->ri_stride; 1183 align = (long)p & SFBALIGNMASK; 1184 p -= align; 1185 align /= SFBPIXELBYTES; 1186 w = ri->ri_emuwidth; 1187 width = w + align; 1188 lmask = SFBCOPYALL1 << align; 1189 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1190 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1191 1192 SFBMODE(sfb, MODE_COPY); 1193 SFBPLANEMASK(sfb, ~0); 1194 SFBPIXELSHIFT(sfb, 0); 1195 if (width <= SFBCOPYBITS) { 1196 /* never happens */; 1197 } 1198 else { 1199 char *q = p; 1200 while (height > 0) { 1201 *(u_int32_t *)p = lmask; 1202 *(u_int32_t *)(p + offset) = lmask; 1203 width -= 2 * SFBCOPYBITS; 1204 while (width > 0) { 1205 p += SFBCOPYBYTESDONE; 1206 *(u_int32_t *)p = SFBCOPYALL1; 1207 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1208 width -= SFBCOPYBITS; 1209 } 1210 p += SFBCOPYBYTESDONE; 1211 *(u_int32_t *)p = rmask; 1212 *(u_int32_t *)(p + offset) = rmask; 1213 1214 p = (q += scanspan); 1215 width = w + align; 1216 height--; 1217 } 1218 } 1219 SFBMODE(sfb, MODE_SIMPLE); 1220 } 1221 1222 #else 1223 1224 1225 static void 1226 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows) 1227 { 1228 struct rasops_info *ri = id; 1229 void *sfb, *p, *q; 1230 int scanspan, offset, srcy, height, width, w, align; 1231 u_int32_t rmask, lmask; 1232 1233 scanspan = ri->ri_stride; 1234 height = ri->ri_font->fontheight * nrows; 1235 offset = (dstrow - srcrow) * ri->ri_yscale; 1236 srcy = ri->ri_font->fontheight * srcrow; 1237 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1238 scanspan = -scanspan; 1239 srcy += height; 1240 } 1241 1242 p = ri->ri_bits + srcy * ri->ri_stride; 1243 align = (long)p & SFBALIGNMASK; 1244 w = ri->ri_emuwidth; 1245 width = w + align; 1246 lmask = SFBCOPYALL1 << align; 1247 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1248 sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET; 1249 q = p; 1250 1251 SFBMODE(sfb, MODE_COPY); 1252 SFBPLANEMASK(sfb, ~0); 1253 SFBPIXELSHIFT(sfb, 0); 1254 1255 if (width <= SFBCOPYBITS) 1256 ; /* never happens */ 1257 else if (width < SFBCOPY64BITS) { 1258 ; /* unlikely happens */ 1259 1260 } 1261 else { 1262 while (height > 0) { 1263 while (width >= SFBCOPY64BITS) { 1264 SFBCOPY64SRC(sfb, *p); 1265 SFBCOPY64DST(sfb, *p + offset); 1266 p += SFBCOPY64BYTESDONE; 1267 width -= SFBCOPY64BITS; 1268 } 1269 if (width >= SFBCOPYBITS) { 1270 *(u_int32_t *)p = SFBCOPYALL1; 1271 *(u_int32_t *)(p + offset) = SFBCOPYALL1; 1272 p += SFBCOPYBYTESDONE; 1273 width -= SFBCOPYBITS; 1274 } 1275 if (width > 0) { 1276 *(u_int32_t *)p = rmask; 1277 *(u_int32_t *)(p + offset) = rmask; 1278 } 1279 1280 p = (q += scanspan); 1281 width = w; 1282 height--; 1283 } 1284 } 1285 SFBMODE(sfb, MODE_SIMPLE); 1286 } 1287 #endif 1288 1289 /* 1290 * Erase lines. 1291 */ 1292 static void 1293 sfbp_eraserows(void *id, int startrow, int nrows, long attr) 1294 { 1295 struct rasops_info *ri = id; 1296 char *sfb, *p; 1297 int scanspan, starty, height, width, align, w; 1298 u_int32_t lmask, rmask; 1299 1300 scanspan = ri->ri_stride; 1301 starty = ri->ri_font->fontheight * startrow; 1302 height = ri->ri_font->fontheight * nrows; 1303 1304 p = ri->ri_bits + starty * scanspan; 1305 align = (long)p & SFBALIGNMASK; 1306 p -= align; 1307 align /= SFBPIXELBYTES; 1308 w = ri->ri_emuwidth * SFBPIXELBYTES; 1309 width = w + align; 1310 lmask = SFBSTIPPLEALL1 << align; 1311 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1312 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1313 1314 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1315 SFBPLANEMASK(sfb, ~0); 1316 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 1317 if (width <= SFBSTIPPLEBITS) { 1318 /* never happens */; 1319 } 1320 else { 1321 char *q = p; 1322 while (height > 0) { 1323 *(u_int32_t *)p = lmask; 1324 WRITE_MB(); 1325 width -= 2 * SFBSTIPPLEBITS; 1326 while (width > 0) { 1327 p += SFBSTIPPLEBYTESDONE; 1328 *(u_int32_t *)p = SFBSTIPPLEALL1; 1329 WRITE_MB(); 1330 width -= SFBSTIPPLEBITS; 1331 } 1332 p += SFBSTIPPLEBYTESDONE; 1333 *(u_int32_t *)p = rmask; 1334 WRITE_MB(); 1335 1336 p = (q += scanspan); 1337 width = w + align; 1338 height--; 1339 } 1340 } 1341 SFBMODE(sfb, MODE_SIMPLE); 1342 } 1343