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