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