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