1 /* $NetBSD: sfbplus.c,v 1.35 2010/05/15 08:53:27 tsutsui 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.35 2010/05/15 08:53:27 tsutsui 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) *((uint32_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 uint8_t r[CMAP_SIZE]; 85 uint8_t g[CMAP_SIZE]; 86 uint8_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 uint8_t cc_color[6]; 96 uint64_t cc_image[CURSOR_MAX_SIZE]; 97 uint64_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 *, uint64_t *); 106 void (*color)(void *, uint8_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 *, uint64_t *); 177 static void bt459color(void *, uint8_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 *, uint64_t *); 183 static void bt463init(void *); 184 static void bt463color(void *, uint8_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 uint8_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 ri->ri_flg &= ~RI_NO_AUTO; 264 sc->nscreens = 1; 265 } 266 else { 267 ri = malloc(sizeof(struct rasops_info), 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 *(uint32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 307 *(uint32_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 uint8_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 = *(uint32_t *)(asic + SFB_ASIC_VIDEO_HSETUP); 345 vsetup = *(uint32_t *)(asic + SFB_ASIC_VIDEO_VSETUP); 346 i = *(uint32_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 *(uint32_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 *(uint32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0; 359 *(uint32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0; 360 *(uint32_t *)(asic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */ 361 *(uint32_t *)(asic + SFB_ASIC_ROP) = 3; /* ROP_COPY */ 362 363 /* initialize colormap and cursor hardware */ 364 if (depth != 32) { 365 *(uint32_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 if (ri == &sfbp_console_ri) 374 ri->ri_flg |= RI_NO_AUTO; 375 ri->ri_flg = 0; /* XXX 32bpp RI_CENTER fails XXX */ 376 ri->ri_depth = depth; 377 ri->ri_width = (hsetup & 0x1ff) << 2; 378 ri->ri_height = (vsetup & 0x7ff); 379 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8); 380 ri->ri_bits = base + 0x800000 + vbase; 381 382 if (depth == 32) { 383 ri->ri_rnum = 8; 384 ri->ri_gnum = 8; 385 ri->ri_bnum = 8; 386 ri->ri_rpos = 16; 387 ri->ri_gpos = 8; 388 ri->ri_bpos = 0; 389 } 390 391 /* clear the screen */ 392 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 393 394 wsfont_init(); 395 /* prefer 12 pixel wide font */ 396 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L, 397 WSDISPLAY_FONTORDER_L2R); 398 if (cookie <= 0) 399 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L, 400 WSDISPLAY_FONTORDER_L2R); 401 if (cookie <= 0) { 402 printf("sfbp: font table is empty\n"); 403 return; 404 } 405 406 /* the accelerated sfbp_putchar() needs LSbit left */ 407 if (wsfont_lock(cookie, &ri->ri_font)) { 408 printf("sfb: couldn't lock font\n"); 409 return; 410 } 411 ri->ri_wsfcookie = cookie; 412 413 rasops_init(ri, 34, 80); 414 415 /* add our accelerated functions */ 416 ri->ri_ops.putchar = sfbp_putchar; 417 ri->ri_ops.erasecols = sfbp_erasecols; 418 ri->ri_ops.copyrows = sfbp_copyrows; 419 ri->ri_ops.eraserows = sfbp_eraserows; 420 421 /* XXX shouldn't be global */ 422 sfbp_stdscreen.nrows = ri->ri_rows; 423 sfbp_stdscreen.ncols = ri->ri_cols; 424 sfbp_stdscreen.textops = &ri->ri_ops; 425 sfbp_stdscreen.capabilities = ri->ri_caps; 426 /* our accelerated putchar can't underline */ 427 sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE; 428 } 429 430 static int 431 sfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 432 { 433 struct sfbp_softc *sc = v; 434 struct rasops_info *ri = sc->sc_ri; 435 int turnoff, s; 436 437 switch (cmd) { 438 case WSDISPLAYIO_GTYPE: 439 *(u_int *)data = WSDISPLAY_TYPE_SFBP; 440 return (0); 441 442 case WSDISPLAYIO_GINFO: 443 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 444 wsd_fbip->height = ri->ri_height; 445 wsd_fbip->width = ri->ri_width; 446 wsd_fbip->depth = ri->ri_depth; 447 wsd_fbip->cmsize = CMAP_SIZE; /* XXX */ 448 #undef fbt 449 return (0); 450 451 case WSDISPLAYIO_GETCMAP: 452 return get_cmap(sc, (struct wsdisplay_cmap *)data); 453 454 case WSDISPLAYIO_PUTCMAP: 455 return set_cmap(sc, (struct wsdisplay_cmap *)data); 456 457 case WSDISPLAYIO_SVIDEO: 458 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 459 if ((sc->sc_blanked == 0) ^ turnoff) { 460 sc->sc_blanked = turnoff; 461 #if 0 /* XXX later XXX */ 462 Low order 3bit control visibilities of screen and builtin cursor. 463 #endif /* XXX XXX XXX */ 464 } 465 return (0); 466 467 case WSDISPLAYIO_GVIDEO: 468 *(u_int *)data = sc->sc_blanked ? 469 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 470 return (0); 471 472 case WSDISPLAYIO_GCURPOS: 473 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 474 return (0); 475 476 case WSDISPLAYIO_SCURPOS: 477 s = spltty(); 478 set_curpos(sc, (struct wsdisplay_curpos *)data); 479 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 480 splx(s); 481 return (0); 482 483 case WSDISPLAYIO_GCURMAX: 484 ((struct wsdisplay_curpos *)data)->x = 485 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 486 return (0); 487 488 case WSDISPLAYIO_GCURSOR: 489 return get_cursor(sc, (struct wsdisplay_cursor *)data); 490 491 case WSDISPLAYIO_SCURSOR: 492 return set_cursor(sc, (struct wsdisplay_cursor *)data); 493 494 case WSDISPLAYIO_SMODE: 495 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { 496 s = spltty(); 497 sfbp_cmap_init(sc); 498 sc->sc_curenb = 0; 499 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR | 500 WSDISPLAY_CMAP_DOLUT); 501 splx(s); 502 } 503 return (0); 504 } 505 return (EPASSTHROUGH); 506 } 507 508 paddr_t 509 sfbmmap(void *v, void *vs, off_t offset, int prot) 510 { 511 struct sfbp_softc *sc = v; 512 513 if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */ 514 return (-1); 515 return machine_btop(sc->sc_vaddr + offset); 516 } 517 518 static int 519 sfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 520 int *curxp, int *curyp, long *attrp) 521 { 522 struct sfbp_softc *sc = v; 523 struct rasops_info *ri = sc->sc_ri; 524 long defattr; 525 526 if (sc->nscreens > 0) 527 return (ENOMEM); 528 529 *cookiep = ri; /* one and only for now */ 530 *curxp = 0; 531 *curyp = 0; 532 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 533 *attrp = defattr; 534 sc->nscreens++; 535 return (0); 536 } 537 538 void 539 sfb_free_screen(void *v, void *cookie) 540 { 541 struct sfbp_softc *sc = v; 542 543 if (sc->sc_ri == &sfbp_console_ri) 544 panic("sfb_free_screen: console"); 545 546 sc->nscreens--; 547 } 548 549 static int 550 sfb_show_screen(void *v, void *cookie, int waitok, 551 void (*cb)(void *, int, int), void *cbarg) 552 { 553 554 return (0); 555 } 556 557 int 558 sfbp_cnattach(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.allocattr)(&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(void *arg) 574 { 575 #define cc (&sc->sc_cursor) 576 struct sfbp_softc *sc = arg; 577 char *base, *asic; 578 uint32_t sisr; 579 int v; 580 581 base = sc->sc_ri->ri_hw; 582 asic = base + SFB_ASIC_OFFSET; 583 sisr = *((uint32_t *)asic + TGA_REG_SISR); 584 *(uint32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0; 585 586 if (sc->sc_changed == 0) 587 goto done; 588 589 v = sc->sc_changed; 590 if (v & WSDISPLAY_CURSOR_DOCUR) 591 (*sc->sc_hwops.visible)(base, sc->sc_curenb); 592 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) 593 (*sc->sc_hwops.locate)(base, cc); 594 if (v & WSDISPLAY_CURSOR_DOCMAP) 595 (*sc->sc_hwops.color)(base, cc->cc_color); 596 if (v & WSDISPLAY_CURSOR_DOSHAPE) 597 (*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image); 598 if (v & WSDISPLAY_CMAP_DOLUT) 599 (*sc->sc_hwops.setlut)(base, &sc->sc_cmap); 600 sc->sc_changed = 0; 601 done: 602 *((uint32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb(); 603 return (1); 604 #undef cc 605 } 606 607 static void 608 bt459init(void *vdac) 609 { 610 const uint8_t *p; 611 int i; 612 613 SELECT(vdac, BT459_IREG_COMMAND_0); 614 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb(); 615 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb(); 616 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb(); 617 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb(); 618 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb(); 619 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb(); 620 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb(); 621 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb(); 622 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb(); 623 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb(); 624 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb(); 625 626 SELECT(vdac, BT459_IREG_CCR); 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 REG(vdac, bt_reg) = 0x0; tc_wmb(); 639 REG(vdac, bt_reg) = 0x0; tc_wmb(); 640 641 /* build sane colormap */ 642 SELECT(vdac, 0); 643 p = rasops_cmap; 644 for (i = 0; i < CMAP_SIZE; i++, p += 3) { 645 REG(vdac, bt_cmap) = p[0]; tc_wmb(); 646 REG(vdac, bt_cmap) = p[1]; tc_wmb(); 647 REG(vdac, bt_cmap) = p[2]; tc_wmb(); 648 } 649 650 /* clear out cursor image */ 651 SELECT(vdac, BT459_IREG_CRAM_BASE); 652 for (i = 0; i < 1024; i++) 653 REG(vdac, bt_reg) = 0xff; tc_wmb(); 654 655 /* 656 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 657 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 658 * image color. CCOLOR_1 will be never used. 659 */ 660 SELECT(vdac, BT459_IREG_CCOLOR_1); 661 REG(vdac, bt_reg) = 0xff; tc_wmb(); 662 REG(vdac, bt_reg) = 0xff; tc_wmb(); 663 REG(vdac, bt_reg) = 0xff; tc_wmb(); 664 665 REG(vdac, bt_reg) = 0; tc_wmb(); 666 REG(vdac, bt_reg) = 0; tc_wmb(); 667 REG(vdac, bt_reg) = 0; tc_wmb(); 668 669 REG(vdac, bt_reg) = 0xff; tc_wmb(); 670 REG(vdac, bt_reg) = 0xff; tc_wmb(); 671 REG(vdac, bt_reg) = 0xff; tc_wmb(); 672 } 673 674 static void 675 bt463init(void *vdac) 676 { 677 int i; 678 679 SELECT(vdac, BT463_IREG_COMMAND_0); 680 REG(vdac, bt_reg) = 0x40; tc_wmb(); /* CMD 0 */ 681 REG(vdac, bt_reg) = 0x48; tc_wmb(); /* CMD 1 */ 682 REG(vdac, bt_reg) = 0xc0; tc_wmb(); /* CMD 2 */ 683 REG(vdac, bt_reg) = 0; tc_wmb(); /* !? 204 !? */ 684 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 0:7 */ 685 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 8:15 */ 686 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 16:23 */ 687 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 24:27 */ 688 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 0:7 */ 689 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 8:15 */ 690 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 16:23 */ 691 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 24:27 */ 692 REG(vdac, bt_reg) = 0x00; tc_wmb(); 693 694 SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE); 695 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) { 696 REG(vdac, bt_reg) = 0x00; /* 0:7 */ 697 REG(vdac, bt_reg) = 0xe1; /* 8:15 */ 698 REG(vdac, bt_reg) = 0x81; /* 16:23 */ 699 } 700 } 701 702 static int 703 get_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p) 704 { 705 u_int index = p->index, count = p->count; 706 int error; 707 708 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 709 return (EINVAL); 710 711 error = copyout(&sc->sc_cmap.r[index], p->red, count); 712 if (error) 713 return error; 714 error = copyout(&sc->sc_cmap.g[index], p->green, count); 715 if (error) 716 return error; 717 error = copyout(&sc->sc_cmap.b[index], p->blue, count); 718 return error; 719 } 720 721 static int 722 set_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p) 723 { 724 struct hwcmap256 cmap; 725 u_int index = p->index, count = p->count; 726 int error, s; 727 728 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 729 return (EINVAL); 730 731 error = copyin(p->red, &cmap.r[index], count); 732 if (error) 733 return error; 734 error = copyin(p->green, &cmap.g[index], count); 735 if (error) 736 return error; 737 error = copyin(p->blue, &cmap.b[index], count); 738 if (error) 739 return error; 740 741 s = spltty(); 742 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count); 743 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count); 744 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count); 745 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 746 splx(s); 747 return (0); 748 } 749 750 static int 751 set_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p) 752 { 753 #define cc (&sc->sc_cursor) 754 u_int v, index = 0, count = 0, icount = 0; 755 uint8_t r[2], g[2], b[2], image[512], mask[512]; 756 int error, s; 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 error = copyin(p->cmap.red, &r[index], count); 765 if (error) 766 return error; 767 error = copyin(p->cmap.green, &g[index], count); 768 if (error) 769 return error; 770 error = copyin(p->cmap.blue, &b[index], count); 771 if (error) 772 return error; 773 } 774 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 775 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 776 return (EINVAL); 777 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 778 error = copyin(p->image, image, icount); 779 if (error) 780 return error; 781 error = copyin(p->mask, mask, icount); 782 if (error) 783 return error; 784 } 785 786 s = spltty(); 787 if (v & WSDISPLAY_CURSOR_DOCUR) 788 sc->sc_curenb = p->enable; 789 if (v & WSDISPLAY_CURSOR_DOPOS) 790 set_curpos(sc, &p->pos); 791 if (v & WSDISPLAY_CURSOR_DOHOT) 792 cc->cc_hot = p->hot; 793 if (v & WSDISPLAY_CURSOR_DOCMAP) { 794 memcpy(&cc->cc_color[index], &r[index], count); 795 memcpy(&cc->cc_color[index + 2], &g[index], count); 796 memcpy(&cc->cc_color[index + 4], &b[index], count); 797 } 798 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 799 cc->cc_size = p->size; 800 memset(cc->cc_image, 0, sizeof cc->cc_image); 801 memcpy(cc->cc_image, image, icount); 802 memset(cc->cc_mask, 0, sizeof cc->cc_mask); 803 memcpy(cc->cc_mask, mask, icount); 804 } 805 sc->sc_changed |= v; 806 splx(s); 807 808 return (0); 809 #undef cc 810 } 811 812 static int 813 get_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p) 814 { 815 return (EPASSTHROUGH); /* XXX */ 816 } 817 818 static void 819 set_curpos(struct sfbp_softc *sc, struct wsdisplay_curpos *curpos) 820 { 821 struct rasops_info *ri = sc->sc_ri; 822 int x = curpos->x, y = curpos->y; 823 824 if (y < 0) 825 y = 0; 826 else if (y > ri->ri_height) 827 y = ri->ri_height; 828 if (x < 0) 829 x = 0; 830 else if (x > ri->ri_width) 831 x = ri->ri_width; 832 sc->sc_cursor.cc_pos.x = x; 833 sc->sc_cursor.cc_pos.y = y; 834 } 835 836 static void 837 bt459visible(void *hw, int on) 838 { 839 hw = (char *)hw + SFB_RAMDAC_OFFSET; 840 SELECT(hw, BT459_IREG_CCR); 841 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00; 842 tc_wmb(); 843 } 844 845 static void 846 sfbpvisible(void *hw, int on) 847 { 848 /* XXX use SFBplus ASIC XX */ 849 } 850 851 static void 852 bt459locate(void *hw, struct hwcursor64 *cc) 853 { 854 int x, y, s; 855 856 x = cc->cc_pos.x - cc->cc_hot.x; 857 y = cc->cc_pos.y - cc->cc_hot.y; 858 x += cc->cc_magic.x; 859 y += cc->cc_magic.y; 860 861 hw = (char *)hw + SFB_RAMDAC_OFFSET; 862 863 s = spltty(); 864 SELECT(hw, BT459_IREG_CURSOR_X_LOW); 865 REG(hw, bt_reg) = x; tc_wmb(); 866 REG(hw, bt_reg) = x >> 8; tc_wmb(); 867 REG(hw, bt_reg) = y; tc_wmb(); 868 REG(hw, bt_reg) = y >> 8; tc_wmb(); 869 splx(s); 870 } 871 872 static void 873 sfbplocate(void *hw, 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 = (char *)hw + SFB_ASIC_OFFSET; 881 *((uint32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff); 882 tc_wmb(); 883 } 884 885 static void 886 bt459color(void *hw, uint8_t *cp) 887 { 888 889 hw = (char *)hw + SFB_RAMDAC_OFFSET; 890 891 SELECT(hw, BT459_IREG_CCOLOR_2); 892 REG(hw, bt_reg) = cp[1]; tc_wmb(); 893 REG(hw, bt_reg) = cp[3]; tc_wmb(); 894 REG(hw, bt_reg) = cp[5]; tc_wmb(); 895 896 REG(hw, bt_reg) = cp[0]; tc_wmb(); 897 REG(hw, bt_reg) = cp[2]; tc_wmb(); 898 REG(hw, bt_reg) = cp[4]; tc_wmb(); 899 } 900 901 static void 902 bt463color(void *hw, uint8_t *cp) 903 { 904 } 905 906 static void 907 bt459shape(void *hw, struct wsdisplay_curpos *size, uint64_t *image) 908 { 909 uint8_t *ip, *mp, img, msk; 910 uint8_t u; 911 int bcnt; 912 913 hw = (char *)hw + SFB_RAMDAC_OFFSET; 914 ip = (uint8_t *)image; 915 mp = (uint8_t *)(image + CURSOR_MAX_SIZE); 916 917 bcnt = 0; 918 SELECT(hw, BT459_IREG_CRAM_BASE+0); 919 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 920 while (bcnt < size->y * 16) { 921 /* pad right half 32 pixel when smaller than 33 */ 922 if ((bcnt & 0x8) && size->x < 33) { 923 REG(hw, bt_reg) = 0; tc_wmb(); 924 REG(hw, bt_reg) = 0; tc_wmb(); 925 } 926 else { 927 img = *ip++; 928 msk = *mp++; 929 img &= msk; /* cookie off image */ 930 u = (msk & 0x0f) << 4 | (img & 0x0f); 931 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 932 u = (msk & 0xf0) | (img & 0xf0) >> 4; 933 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 934 } 935 bcnt += 2; 936 } 937 /* pad unoccupied scan lines */ 938 while (bcnt < CURSOR_MAX_SIZE * 16) { 939 REG(hw, bt_reg) = 0; tc_wmb(); 940 REG(hw, bt_reg) = 0; tc_wmb(); 941 bcnt += 2; 942 } 943 } 944 945 static void 946 sfbpshape(void *hw, struct wsdisplay_curpos *size, uint64_t *image) 947 { 948 /* XXX use SFBplus ASIC XXX */ 949 } 950 951 static void 952 bt459setlut(void *hw, struct hwcmap256 *cm) 953 { 954 int index; 955 956 hw = (char *)hw + SFB_RAMDAC_OFFSET; 957 SELECT(hw, 0); 958 for (index = 0; index < CMAP_SIZE; index++) { 959 REG(hw, bt_cmap) = cm->r[index]; tc_wmb(); 960 REG(hw, bt_cmap) = cm->g[index]; tc_wmb(); 961 REG(hw, bt_cmap) = cm->b[index]; tc_wmb(); 962 } 963 } 964 965 static void 966 noplut(void *hw, struct hwcmap256 *cm) 967 { 968 } 969 970 #define SFBBPP 32 971 972 #define MODE_SIMPLE 0 973 #define MODE_OPAQUESTIPPLE 1 974 #define MODE_OPAQUELINE 2 975 #define MODE_TRANSPARENTSTIPPLE 5 976 #define MODE_TRANSPARENTLINE 6 977 #define MODE_COPY 7 978 979 #if SFBBPP == 8 980 /* parameters for 8bpp configuration */ 981 #define SFBALIGNMASK 0x7 982 #define SFBPIXELBYTES 1 983 #define SFBSTIPPLEALL1 0xffffffff 984 #define SFBSTIPPLEBITS 32 985 #define SFBSTIPPLEBITMASK 0x1f 986 #define SFBSTIPPLEBYTESDONE 32 987 #define SFBCOPYALL1 0xffffffff 988 #define SFBCOPYBITS 32 989 #define SFBCOPYBITMASK 0x1f 990 #define SFBCOPYBYTESDONE 32 991 992 #elif SFBBPP == 32 993 /* parameters for 32bpp configuration */ 994 #define SFBALIGNMASK 0x7 995 #define SFBPIXELBYTES 4 996 #define SFBSTIPPLEALL1 0x0000ffff 997 #define SFBSTIPPLEBITS 16 998 #define SFBSTIPPLEBITMASK 0xf 999 #define SFBSTIPPLEBYTESDONE 32 1000 #define SFBCOPYALL1 0x000000ff 1001 #define SFBCOPYBITS 8 1002 #define SFBCOPYBITMASK 0x3 1003 #define SFBCOPYBYTESDONE 32 1004 #endif 1005 1006 #ifdef pmax 1007 #define WRITE_MB() 1008 #define BUMP(p) (p) 1009 #endif 1010 1011 #ifdef alpha 1012 #define WRITE_MB() tc_wmb() 1013 /* registers is replicated in 1KB stride; rap round 4th iteration */ 1014 #define BUMP(p) ((p) = (void *)(((long)(p) + 0x400) & ~0x1000)) 1015 #endif 1016 1017 #define SFBMODE(p, v) \ 1018 (*(uint32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v)) 1019 #define SFBROP(p, v) \ 1020 (*(uint32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v)) 1021 #define SFBPLANEMASK(p, v) \ 1022 (*(uint32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v)) 1023 #define SFBPIXELMASK(p, v) \ 1024 (*(uint32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v)) 1025 #define SFBADDRESS(p, v) \ 1026 (*(uint32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v)) 1027 #define SFBSTART(p, v) \ 1028 (*(uint32_t *)(BUMP(p) + SFB_ASIC_START) = (v)) 1029 #define SFBPIXELSHIFT(p, v) \ 1030 (*(uint32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v)) 1031 #define SFBFG(p, v) \ 1032 (*(uint32_t *)(BUMP(p) + SFB_ASIC_FG) = (v)) 1033 #define SFBBG(p, v) \ 1034 (*(uint32_t *)(BUMP(p) + SFB_ASIC_BG) = (v)) 1035 #define SFBBCONT(p, v) \ 1036 (*(uint32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v)) 1037 1038 #define SFBDATA(p, v) \ 1039 (*((uint32_t *)BUMP(p) + TGA_REG_GDAR) = (v)) 1040 1041 #define SFBCOPY64BYTESDONE 8 1042 #define SFBCOPY64BITS 64 1043 #define SFBCOPY64SRC(p, v) \ 1044 (*((uint32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v)) 1045 #define SFBCOPY64DST(p, v) \ 1046 (*((uint32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v)) 1047 1048 /* 1049 * Actually write a string to the frame buffer. 1050 */ 1051 static void 1052 sfbp_putchar(void *id, int row, int col, u_int uc, long attr) 1053 { 1054 struct rasops_info *ri = id; 1055 char *sfb, *p; 1056 int scanspan, height, width, align, x, y; 1057 uint32_t lmask, rmask, glyph; 1058 uint8_t *g; 1059 1060 x = col * ri->ri_font->fontwidth; 1061 y = row * ri->ri_font->fontheight; 1062 scanspan = ri->ri_stride; 1063 height = ri->ri_font->fontheight; 1064 uc -= ri->ri_font->firstchar; 1065 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; 1066 1067 p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES; 1068 align = (long)p & SFBALIGNMASK; 1069 p -= align; 1070 align /= SFBPIXELBYTES; 1071 width = ri->ri_font->fontwidth + align; 1072 lmask = SFBSTIPPLEALL1 << align; 1073 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1074 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1075 1076 SFBMODE(sfb, MODE_OPAQUESTIPPLE); 1077 SFBPLANEMASK(sfb, ~0); 1078 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]); 1079 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 1080 SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */ 1081 *((uint32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask; 1082 1083 /* XXX 2B stride fonts only XXX */ 1084 while (height > 0) { 1085 glyph = *(uint16_t *)g; /* XXX */ 1086 *(uint32_t *)p = glyph << align; 1087 p += scanspan; 1088 g += 2; /* XXX */ 1089 height--; 1090 } 1091 SFBMODE(sfb, MODE_SIMPLE); 1092 *((uint32_t *)sfb + TGA_REG_GPXR_P) = ~0; 1093 } 1094 1095 #undef SFBSTIPPLEALL1 1096 #undef SFBSTIPPLEBITS 1097 #undef SFBSTIPPLEBITMASK 1098 #define SFBSTIPPLEALL1 SFBCOPYALL1 1099 #define SFBSTIPPLEBITS SFBCOPYBITS 1100 #define SFBSTIPPLEBITMASK SFBCOPYBITMASK 1101 1102 /* 1103 * Clear characters in a line. 1104 */ 1105 static void 1106 sfbp_erasecols(void *id, int row, int startcol, int ncols, long attr) 1107 { 1108 struct rasops_info *ri = id; 1109 char *sfb, *p; 1110 int scanspan, startx, height, width, align, w, y; 1111 uint32_t lmask, rmask; 1112 1113 scanspan = ri->ri_stride; 1114 y = row * ri->ri_font->fontheight; 1115 startx = startcol * ri->ri_font->fontwidth; 1116 height = ri->ri_font->fontheight; 1117 w = ri->ri_font->fontwidth * ncols; 1118 1119 p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES; 1120 align = (long)p & SFBALIGNMASK; 1121 align /= SFBPIXELBYTES; 1122 p -= align; 1123 width = w + align; 1124 lmask = SFBSTIPPLEALL1 << align; 1125 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1126 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1127 1128 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1129 SFBPLANEMASK(sfb, ~0); 1130 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */ 1131 if (width <= SFBSTIPPLEBITS) { 1132 lmask = lmask & rmask; 1133 while (height > 0) { 1134 *(uint32_t *)p = lmask; 1135 p += scanspan; 1136 height--; 1137 } 1138 } 1139 else { 1140 char *q = p; 1141 while (height > 0) { 1142 *(uint32_t *)p = lmask; 1143 WRITE_MB(); 1144 width -= 2 * SFBSTIPPLEBITS; 1145 while (width > 0) { 1146 p += SFBSTIPPLEBYTESDONE; 1147 *(uint32_t *)p = SFBSTIPPLEALL1; 1148 WRITE_MB(); 1149 width -= SFBSTIPPLEBITS; 1150 } 1151 p += SFBSTIPPLEBYTESDONE; 1152 *(uint32_t *)p = rmask; 1153 WRITE_MB(); 1154 1155 p = (q += scanspan); 1156 width = w + align; 1157 height--; 1158 } 1159 } 1160 SFBMODE(sfb, MODE_SIMPLE); 1161 } 1162 1163 #if 1 1164 /* 1165 * Copy lines. 1166 */ 1167 static void 1168 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows) 1169 { 1170 struct rasops_info *ri = id; 1171 char *sfb, *p; 1172 int scanspan, offset, srcy, height, width, align, w; 1173 uint32_t lmask, rmask; 1174 1175 scanspan = ri->ri_stride; 1176 height = ri->ri_font->fontheight * nrows; 1177 offset = (dstrow - srcrow) * ri->ri_yscale; 1178 srcy = ri->ri_font->fontheight * srcrow; 1179 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1180 scanspan = -scanspan; 1181 srcy += height; 1182 } 1183 1184 p = ri->ri_bits + srcy * ri->ri_stride; 1185 align = (long)p & SFBALIGNMASK; 1186 p -= align; 1187 align /= SFBPIXELBYTES; 1188 w = ri->ri_emuwidth; 1189 width = w + align; 1190 lmask = SFBCOPYALL1 << align; 1191 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1192 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1193 1194 SFBMODE(sfb, MODE_COPY); 1195 SFBPLANEMASK(sfb, ~0); 1196 SFBPIXELSHIFT(sfb, 0); 1197 if (width <= SFBCOPYBITS) { 1198 /* never happens */; 1199 } 1200 else { 1201 char *q = p; 1202 while (height > 0) { 1203 *(uint32_t *)p = lmask; 1204 *(uint32_t *)(p + offset) = lmask; 1205 width -= 2 * SFBCOPYBITS; 1206 while (width > 0) { 1207 p += SFBCOPYBYTESDONE; 1208 *(uint32_t *)p = SFBCOPYALL1; 1209 *(uint32_t *)(p + offset) = SFBCOPYALL1; 1210 width -= SFBCOPYBITS; 1211 } 1212 p += SFBCOPYBYTESDONE; 1213 *(uint32_t *)p = rmask; 1214 *(uint32_t *)(p + offset) = rmask; 1215 1216 p = (q += scanspan); 1217 width = w + align; 1218 height--; 1219 } 1220 } 1221 SFBMODE(sfb, MODE_SIMPLE); 1222 } 1223 1224 #else 1225 1226 1227 static void 1228 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows) 1229 { 1230 struct rasops_info *ri = id; 1231 void *sfb, *p, *q; 1232 int scanspan, offset, srcy, height, width, w, align; 1233 uint32_t rmask, lmask; 1234 1235 scanspan = ri->ri_stride; 1236 height = ri->ri_font->fontheight * nrows; 1237 offset = (dstrow - srcrow) * ri->ri_yscale; 1238 srcy = ri->ri_font->fontheight * srcrow; 1239 if (srcrow < dstrow && srcrow + nrows > dstrow) { 1240 scanspan = -scanspan; 1241 srcy += height; 1242 } 1243 1244 p = ri->ri_bits + srcy * ri->ri_stride; 1245 align = (long)p & SFBALIGNMASK; 1246 w = ri->ri_emuwidth; 1247 width = w + align; 1248 lmask = SFBCOPYALL1 << align; 1249 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK); 1250 sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET; 1251 q = p; 1252 1253 SFBMODE(sfb, MODE_COPY); 1254 SFBPLANEMASK(sfb, ~0); 1255 SFBPIXELSHIFT(sfb, 0); 1256 1257 if (width <= SFBCOPYBITS) 1258 ; /* never happens */ 1259 else if (width < SFBCOPY64BITS) { 1260 ; /* unlikely happens */ 1261 1262 } 1263 else { 1264 while (height > 0) { 1265 while (width >= SFBCOPY64BITS) { 1266 SFBCOPY64SRC(sfb, *p); 1267 SFBCOPY64DST(sfb, *p + offset); 1268 p += SFBCOPY64BYTESDONE; 1269 width -= SFBCOPY64BITS; 1270 } 1271 if (width >= SFBCOPYBITS) { 1272 *(uint32_t *)p = SFBCOPYALL1; 1273 *(uint32_t *)(p + offset) = SFBCOPYALL1; 1274 p += SFBCOPYBYTESDONE; 1275 width -= SFBCOPYBITS; 1276 } 1277 if (width > 0) { 1278 *(uint32_t *)p = rmask; 1279 *(uint32_t *)(p + offset) = rmask; 1280 } 1281 1282 p = (q += scanspan); 1283 width = w; 1284 height--; 1285 } 1286 } 1287 SFBMODE(sfb, MODE_SIMPLE); 1288 } 1289 #endif 1290 1291 /* 1292 * Erase lines. 1293 */ 1294 static void 1295 sfbp_eraserows(void *id, int startrow, int nrows, long attr) 1296 { 1297 struct rasops_info *ri = id; 1298 char *sfb, *p; 1299 int scanspan, starty, height, width, align, w; 1300 uint32_t lmask, rmask; 1301 1302 scanspan = ri->ri_stride; 1303 starty = ri->ri_font->fontheight * startrow; 1304 height = ri->ri_font->fontheight * nrows; 1305 1306 p = ri->ri_bits + starty * scanspan; 1307 align = (long)p & SFBALIGNMASK; 1308 p -= align; 1309 align /= SFBPIXELBYTES; 1310 w = ri->ri_emuwidth * SFBPIXELBYTES; 1311 width = w + align; 1312 lmask = SFBSTIPPLEALL1 << align; 1313 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK); 1314 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET; 1315 1316 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE); 1317 SFBPLANEMASK(sfb, ~0); 1318 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); 1319 if (width <= SFBSTIPPLEBITS) { 1320 /* never happens */; 1321 } 1322 else { 1323 char *q = p; 1324 while (height > 0) { 1325 *(uint32_t *)p = lmask; 1326 WRITE_MB(); 1327 width -= 2 * SFBSTIPPLEBITS; 1328 while (width > 0) { 1329 p += SFBSTIPPLEBYTESDONE; 1330 *(uint32_t *)p = SFBSTIPPLEALL1; 1331 WRITE_MB(); 1332 width -= SFBSTIPPLEBITS; 1333 } 1334 p += SFBSTIPPLEBYTESDONE; 1335 *(uint32_t *)p = rmask; 1336 WRITE_MB(); 1337 1338 p = (q += scanspan); 1339 width = w + align; 1340 height--; 1341 } 1342 } 1343 SFBMODE(sfb, MODE_SIMPLE); 1344 } 1345