1 /* $NetBSD: sfbplus.c,v 1.5 2000/06/28 17:05:24 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1999 Tohru Nishimura. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Tohru Nishimura 17 * for the NetBSD Project. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 34 35 __KERNEL_RCSID(0, "$NetBSD: sfbplus.c,v 1.5 2000/06/28 17:05:24 mrg Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/device.h> 41 #include <sys/malloc.h> 42 #include <sys/buf.h> 43 #include <sys/ioctl.h> 44 45 #include <machine/bus.h> 46 #include <machine/intr.h> 47 48 #include <dev/rcons/raster.h> 49 #include <dev/wscons/wsconsio.h> 50 #include <dev/wscons/wscons_raster.h> 51 #include <dev/wscons/wsdisplayvar.h> 52 53 #include <dev/tc/tcvar.h> 54 #include <dev/ic/bt459reg.h> 55 #include <dev/ic/bt463reg.h> 56 #include <dev/tc/sfbreg.h> 57 #include <dev/pci/tgareg.h> 58 59 #include <uvm/uvm_extern.h> 60 61 #if defined(pmax) 62 #define machine_btop(x) mips_btop(x) 63 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x) 64 #endif 65 66 #if defined(__alpha__) || defined(alpha) 67 #define machine_btop(x) alpha_btop(x) 68 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x) 69 #endif 70 71 /* Bt459/Bt463 hardware registers */ 72 #define bt_lo 0 73 #define bt_hi 1 74 #define bt_reg 2 75 #define bt_cmap 3 76 77 #define REG(base, index) *((u_int32_t *)(base) + (index)) 78 #define SELECT(vdac, regno) do { \ 79 REG(vdac, bt_lo) = ((regno) & 0x00ff); \ 80 REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \ 81 tc_wmb(); \ 82 } while (0) 83 84 struct fb_devconfig { 85 vaddr_t dc_vaddr; /* memory space virtual base address */ 86 paddr_t dc_paddr; /* memory space physical base address */ 87 vsize_t dc_size; /* size of slot memory */ 88 int dc_wid; /* width of frame buffer */ 89 int dc_ht; /* height of frame buffer */ 90 int dc_depth; /* depth, bits per pixel */ 91 int dc_rowbytes; /* bytes in a FB scan line */ 92 vaddr_t dc_videobase; /* base of flat frame buffer */ 93 struct raster dc_raster; /* raster description */ 94 struct rcons dc_rcons; /* raster blitter control info */ 95 int dc_blanked; /* currently has video disabled */ 96 }; 97 98 struct hwcmap256 { 99 #define CMAP_SIZE 256 /* 256 R/G/B entries */ 100 u_int8_t r[CMAP_SIZE]; 101 u_int8_t g[CMAP_SIZE]; 102 u_int8_t b[CMAP_SIZE]; 103 }; 104 105 struct hwcursor64 { 106 struct wsdisplay_curpos cc_pos; 107 struct wsdisplay_curpos cc_hot; 108 struct wsdisplay_curpos cc_size; 109 struct wsdisplay_curpos cc_magic; 110 #define CURSOR_MAX_SIZE 64 111 u_int8_t cc_color[6]; 112 u_int64_t cc_image[64 + 64]; 113 }; 114 115 struct hwops { 116 void (*setlut) __P((void *, struct hwcmap256 *)); 117 void (*getlut) __P((void *, struct hwcmap256 *)); 118 void (*visible) __P((void *, int)); 119 void (*locate) __P((void *, int, int)); 120 void (*shape) __P((void *, struct wsdisplay_curpos *, u_int64_t *)); 121 void (*color) __P((void *, u_int8_t *)); 122 }; 123 124 struct sfb_softc { 125 struct device sc_dev; 126 struct fb_devconfig *sc_dc; /* device configuration */ 127 struct hwcmap256 sc_cmap; /* software copy of colormap */ 128 struct hwcursor64 sc_cursor; /* software copy of cursor */ 129 int sc_curenb; /* cursor sprite enabled */ 130 int sc_changed; /* need update of colormap */ 131 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */ 132 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */ 133 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */ 134 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */ 135 #define DATA_ALL_CHANGED 0x0f 136 int nscreens; 137 struct hwops sc_hwops; 138 void *sc_hw0, *sc_hw1; 139 }; 140 141 #define HX_MAGIC_X 368 142 #define HX_MAGIC_Y 38 143 144 static int sfbpmatch __P((struct device *, struct cfdata *, void *)); 145 static void sfbpattach __P((struct device *, struct device *, void *)); 146 147 struct cfattach sfbp_ca = { 148 sizeof(struct sfb_softc), sfbpmatch, sfbpattach, 149 }; 150 151 static void sfbp_getdevconfig __P((tc_addr_t, struct fb_devconfig *)); 152 static struct fb_devconfig sfbp_console_dc; 153 static tc_addr_t sfbp_consaddr; 154 155 extern const struct wsdisplay_emulops sfbp_emulops, sfbp_emulops32; 156 157 static struct wsscreen_descr sfb_stdscreen = { 158 "std", 0, 0, 159 NULL, /* textops */ 160 0, 0, 161 WSSCREEN_REVERSE 162 }; 163 164 static const struct wsscreen_descr *_sfb_scrlist[] = { 165 &sfb_stdscreen, 166 }; 167 168 static const struct wsscreen_list sfb_screenlist = { 169 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist 170 }; 171 172 static int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *)); 173 static paddr_t sfbmmap __P((void *, off_t, int)); 174 175 static int sfb_alloc_screen __P((void *, const struct wsscreen_descr *, 176 void **, int *, int *, long *)); 177 static void sfb_free_screen __P((void *, void *)); 178 static int sfb_show_screen __P((void *, void *, int, 179 void (*) (void *, int, int), void *)); 180 /* EXPORT */ int sfb_alloc_attr __P((void *, int, int, int, long *)); 181 182 static const struct wsdisplay_accessops sfb_accessops = { 183 sfbioctl, 184 sfbmmap, 185 sfb_alloc_screen, 186 sfb_free_screen, 187 sfb_show_screen, 188 0 /* load_font */ 189 }; 190 191 static void bt459visible __P((void *, int)); 192 static void bt459locate __P((void *, int, int)); 193 static void bt459shape __P((void *, struct wsdisplay_curpos *, u_int64_t *)); 194 static void bt459color __P((void *, u_int8_t *)); 195 static void bt459setlut __P((void *, struct hwcmap256 *)); 196 197 static void sfbpvisible __P((void *, int)); 198 static void sfbplocate __P((void *, int, int)); 199 static void sfbpshape __P((void *, struct wsdisplay_curpos *, u_int64_t *)); 200 static void bt463color __P((void *, u_int8_t *)); 201 static void noplut __P((void *, struct hwcmap256 *)); 202 203 204 /* EXPORT */ int sfbp_cnattach __P((tc_addr_t)); 205 static int sfbpintr __P((void *)); 206 static void sfbpinit __P((struct fb_devconfig *)); 207 208 static int get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *)); 209 static int set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *)); 210 static int set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *)); 211 static int get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *)); 212 213 214 /* 215 * Compose 2 bit/pixel cursor image. Bit order will be reversed. 216 * M M M M I I I I M I M I M I M I 217 * [ before ] [ after ] 218 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3 219 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7 220 */ 221 static const u_int8_t shuffle[256] = { 222 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 223 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 224 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4, 225 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5, 226 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74, 227 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75, 228 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4, 229 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5, 230 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c, 231 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d, 232 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc, 233 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd, 234 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c, 235 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d, 236 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc, 237 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd, 238 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56, 239 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57, 240 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6, 241 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7, 242 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76, 243 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77, 244 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6, 245 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7, 246 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e, 247 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f, 248 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde, 249 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf, 250 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e, 251 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f, 252 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe, 253 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff, 254 }; 255 256 static int 257 sfbpmatch(parent, match, aux) 258 struct device *parent; 259 struct cfdata *match; 260 void *aux; 261 { 262 struct tc_attach_args *ta = aux; 263 264 if (strncmp("PMAGD", ta->ta_modname, 5) != 0) 265 return (0); 266 267 return (1); 268 } 269 270 static void 271 sfbp_getdevconfig(dense_addr, dc) 272 tc_addr_t dense_addr; 273 struct fb_devconfig *dc; 274 { 275 struct raster *rap; 276 struct rcons *rcp; 277 caddr_t sfbasic; 278 int i, hsetup, vsetup, vbase; 279 280 dc->dc_vaddr = dense_addr; 281 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr); 282 283 sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET); 284 hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP); 285 vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP); 286 i = *(u_int32_t *)(sfbasic + SFB_ASIC_DEEP); 287 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1; 288 289 dc->dc_wid = (hsetup & 0x1ff) << 2; 290 dc->dc_ht = (vsetup & 0x7ff); 291 dc->dc_depth = (i & 1) ? 32 : 8; 292 dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8); 293 dc->dc_videobase = dc->dc_vaddr + 0x800000 + vbase * 4096; /* XXX */ 294 dc->dc_blanked = 0; 295 296 /* initialize colormap and cursor resource */ 297 sfbpinit(dc); 298 299 /* clear the screen */ 300 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t)) 301 *(u_int32_t *)(dc->dc_videobase + i) = 0x0; 302 303 /* initialize the raster */ 304 rap = &dc->dc_raster; 305 rap->width = dc->dc_wid; 306 rap->height = dc->dc_ht; 307 rap->depth = dc->dc_depth; 308 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t); 309 rap->pixels = (u_int32_t *)dc->dc_videobase; 310 rap->data = sfbasic; 311 312 /* initialize the raster console blitter */ 313 rcp = &dc->dc_rcons; 314 rcp->rc_sp = rap; 315 rcp->rc_crow = rcp->rc_ccol = -1; 316 rcp->rc_crowp = &rcp->rc_crow; 317 rcp->rc_ccolp = &rcp->rc_ccol; 318 rcons_init(rcp, 34, 80); 319 320 sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow; 321 sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol; 322 sfb_stdscreen.textops 323 = (dc->dc_depth == 8) ? &sfbp_emulops : &sfbp_emulops32; 324 } 325 326 static void 327 sfbpattach(parent, self, aux) 328 struct device *parent, *self; 329 void *aux; 330 { 331 struct sfb_softc *sc = (struct sfb_softc *)self; 332 struct tc_attach_args *ta = aux; 333 struct wsemuldisplaydev_attach_args waa; 334 struct hwcmap256 *cm; 335 caddr_t sfbasic; 336 int console; 337 338 console = (ta->ta_addr == sfbp_consaddr); 339 if (console) { 340 sc->sc_dc = &sfbp_console_dc; 341 sc->nscreens = 1; 342 } 343 else { 344 sc->sc_dc = (struct fb_devconfig *) 345 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK); 346 sfbp_getdevconfig(ta->ta_addr, sc->sc_dc); 347 } 348 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, 349 sc->sc_dc->dc_depth); 350 351 cm = &sc->sc_cmap; 352 memset(cm, 255, sizeof(struct hwcmap256)); /* XXX */ 353 cm->r[0] = cm->g[0] = cm->b[0] = 0; /* XXX */ 354 355 sc->sc_cursor.cc_magic.x = HX_MAGIC_X; 356 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y; 357 358 if (sc->sc_dc->dc_depth == 8) { 359 sc->sc_hw0 = (caddr_t)ta->ta_addr + SFB_RAMDAC_OFFSET; 360 sc->sc_hw1 = sc->sc_hw0; 361 sc->sc_hwops.visible = bt459visible; 362 sc->sc_hwops.locate = bt459locate; 363 sc->sc_hwops.shape = bt459shape; 364 sc->sc_hwops.color = bt459color; 365 sc->sc_hwops.setlut = bt459setlut; 366 sc->sc_hwops.getlut = noplut; 367 } 368 else { 369 sc->sc_hw0 = (caddr_t)ta->ta_addr + SFB_ASIC_OFFSET; 370 sc->sc_hw1 = (caddr_t)ta->ta_addr + SFB_RAMDAC_OFFSET; 371 sc->sc_hwops.visible = sfbpvisible; 372 sc->sc_hwops.locate = sfbplocate; 373 sc->sc_hwops.shape = sfbpshape; 374 sc->sc_hwops.color = bt463color; 375 sc->sc_hwops.setlut = noplut; 376 sc->sc_hwops.getlut = noplut; 377 } 378 379 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc); 380 381 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET); 382 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0; tc_wmb(); 383 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; tc_wmb(); 384 385 waa.console = console; 386 waa.scrdata = &sfb_screenlist; 387 waa.accessops = &sfb_accessops; 388 waa.accesscookie = sc; 389 390 config_found(self, &waa, wsemuldisplaydevprint); 391 } 392 393 static int 394 sfbioctl(v, cmd, data, flag, p) 395 void *v; 396 u_long cmd; 397 caddr_t data; 398 int flag; 399 struct proc *p; 400 { 401 struct sfb_softc *sc = v; 402 struct fb_devconfig *dc = sc->sc_dc; 403 int turnoff; 404 405 switch (cmd) { 406 case WSDISPLAYIO_GTYPE: 407 *(u_int *)data = WSDISPLAY_TYPE_SFB; /* XXX SFBP XXX */ 408 return (0); 409 410 case WSDISPLAYIO_GINFO: 411 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 412 wsd_fbip->height = sc->sc_dc->dc_ht; 413 wsd_fbip->width = sc->sc_dc->dc_wid; 414 wsd_fbip->depth = sc->sc_dc->dc_depth; 415 wsd_fbip->cmsize = CMAP_SIZE; 416 #undef fbt 417 return (0); 418 419 case WSDISPLAYIO_GETCMAP: 420 return get_cmap(sc, (struct wsdisplay_cmap *)data); 421 422 case WSDISPLAYIO_PUTCMAP: 423 return set_cmap(sc, (struct wsdisplay_cmap *)data); 424 425 case WSDISPLAYIO_SVIDEO: 426 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 427 if ((dc->dc_blanked == 0) ^ turnoff) { 428 dc->dc_blanked = turnoff; 429 #if 0 /* XXX later XXX */ 430 Low order 3bit control visibilities of screen and builtin cursor. 431 #endif /* XXX XXX XXX */ 432 } 433 return (0); 434 435 case WSDISPLAYIO_GVIDEO: 436 *(u_int *)data = dc->dc_blanked ? 437 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 438 return (0); 439 440 case WSDISPLAYIO_GCURPOS: 441 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 442 return (0); 443 444 case WSDISPLAYIO_SCURPOS: { 445 struct wsdisplay_curpos *pos = (void *)data; 446 int x, y; 447 448 x = pos->x; 449 y = pos->y; 450 if (y < 0) 451 y = 0; 452 else if (y > dc->dc_ht) 453 y = dc->dc_ht; 454 if (x < 0) 455 x = 0; 456 else if (x > dc->dc_wid) 457 x = dc->dc_wid; 458 sc->sc_cursor.cc_pos.x = x; 459 sc->sc_cursor.cc_pos.y = y; 460 x -= sc->sc_cursor.cc_hot.x; 461 y -= sc->sc_cursor.cc_hot.y; 462 x += sc->sc_cursor.cc_magic.x; 463 y += sc->sc_cursor.cc_magic.y; 464 (*sc->sc_hwops.locate)(sc->sc_hw0, x, y); 465 return (0); 466 } 467 468 case WSDISPLAYIO_GCURMAX: 469 ((struct wsdisplay_curpos *)data)->x = 470 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 471 return (0); 472 473 case WSDISPLAYIO_GCURSOR: 474 return get_cursor(sc, (struct wsdisplay_cursor *)data); 475 476 case WSDISPLAYIO_SCURSOR: 477 return set_cursor(sc, (struct wsdisplay_cursor *)data); 478 } 479 return ENOTTY; 480 } 481 482 paddr_t 483 sfbmmap(v, offset, prot) 484 void *v; 485 off_t offset; 486 int prot; 487 { 488 struct sfb_softc *sc = v; 489 490 if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */ 491 return (-1); 492 return machine_btop(sc->sc_dc->dc_paddr + offset); 493 } 494 495 static int 496 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 497 void *v; 498 const struct wsscreen_descr *type; 499 void **cookiep; 500 int *curxp, *curyp; 501 long *attrp; 502 { 503 struct sfb_softc *sc = v; 504 long defattr; 505 506 if (sc->nscreens > 0) 507 return (ENOMEM); 508 509 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */ 510 *curxp = 0; 511 *curyp = 0; 512 sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr); 513 *attrp = defattr; 514 sc->nscreens++; 515 return (0); 516 } 517 518 void 519 sfb_free_screen(v, cookie) 520 void *v; 521 void *cookie; 522 { 523 struct sfb_softc *sc = v; 524 525 if (sc->sc_dc == &sfbp_console_dc) 526 panic("sfb_free_screen: console"); 527 528 sc->nscreens--; 529 } 530 531 static int 532 sfb_show_screen(v, cookie, waitok, cb, cbarg) 533 void *v; 534 void *cookie; 535 int waitok; 536 void (*cb) __P((void *, int, int)); 537 void *cbarg; 538 { 539 540 return (0); 541 } 542 543 int 544 sfbp_cnattach(addr) 545 tc_addr_t addr; 546 { 547 struct fb_devconfig *dcp = &sfbp_console_dc; 548 long defattr; 549 550 sfbp_getdevconfig(addr, dcp); 551 552 sfb_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr); 553 554 wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons, 555 0, 0, defattr); 556 sfbp_consaddr = addr; 557 return(0); 558 } 559 560 static int 561 sfbpintr(arg) 562 void *arg; 563 { 564 struct sfb_softc *sc = arg; 565 caddr_t sfbasic = (caddr_t)sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET; 566 int v; 567 u_int32_t sisr; 568 569 #define cc (&sc->sc_cursor) 570 sisr = *((u_int32_t *)sfbasic + TGA_REG_SISR); 571 572 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0; 573 574 if (sc->sc_changed == 0) 575 goto finish; 576 577 v = sc->sc_changed; 578 sc->sc_changed = 0; 579 580 if (v & DATA_ENB_CHANGED) 581 (*sc->sc_hwops.visible)(sc->sc_hw0, sc->sc_curenb); 582 if (v & DATA_CURCMAP_CHANGED) 583 (*sc->sc_hwops.color)(sc->sc_hw1, cc->cc_color); 584 if (v & DATA_CURSHAPE_CHANGED) 585 (*sc->sc_hwops.shape)(sc->sc_hw0, &cc->cc_size, cc->cc_image); 586 if (v & DATA_CMAP_CHANGED) 587 (*sc->sc_hwops.setlut)(sc->sc_hw1, &sc->sc_cmap); 588 589 finish: 590 *((u_int32_t *)sfbasic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb(); 591 return (1); 592 #undef cc 593 } 594 595 static void 596 sfbpinit(dc) 597 struct fb_devconfig *dc; 598 { 599 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET); 600 caddr_t vdac = (caddr_t)(dc->dc_vaddr + SFB_RAMDAC_OFFSET); 601 int i; 602 603 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0; 604 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0; 605 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */ 606 *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3; /* ROP_COPY */ 607 608 if (dc->dc_depth == 8) { 609 *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */ 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 REG(vdac, bt_cmap) = 0; tc_wmb(); 642 REG(vdac, bt_cmap) = 0; tc_wmb(); 643 REG(vdac, bt_cmap) = 0; tc_wmb(); 644 for (i = 1; i < CMAP_SIZE; i++) { 645 REG(vdac, bt_cmap) = 0xff; tc_wmb(); 646 REG(vdac, bt_cmap) = 0xff; tc_wmb(); 647 REG(vdac, bt_cmap) = 0xff; tc_wmb(); 648 } 649 650 /* clear out cursor image */ 651 SELECT(vdac, BT459_IREG_CRAM_BASE); 652 for (i = 0; i < 1024; i++) 653 REG(vdac, bt_reg) = 0xff; tc_wmb(); 654 655 /* 656 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for 657 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for 658 * image color. CCOLOR_1 will be never used. 659 */ 660 SELECT(vdac, BT459_IREG_CCOLOR_1); 661 REG(vdac, bt_reg) = 0xff; tc_wmb(); 662 REG(vdac, bt_reg) = 0xff; tc_wmb(); 663 REG(vdac, bt_reg) = 0xff; tc_wmb(); 664 665 REG(vdac, bt_reg) = 0; tc_wmb(); 666 REG(vdac, bt_reg) = 0; tc_wmb(); 667 REG(vdac, bt_reg) = 0; tc_wmb(); 668 669 REG(vdac, bt_reg) = 0xff; tc_wmb(); 670 REG(vdac, bt_reg) = 0xff; tc_wmb(); 671 REG(vdac, bt_reg) = 0xff; tc_wmb(); 672 } else { 673 SELECT(vdac, BT463_IREG_COMMAND_0); 674 REG(vdac, bt_reg) = 0x40; tc_wmb(); /* CMD 0 */ 675 REG(vdac, bt_reg) = 0x46; tc_wmb(); /* CMD 1 */ 676 REG(vdac, bt_reg) = 0xc0; tc_wmb(); /* CMD 2 */ 677 REG(vdac, bt_reg) = 0; tc_wmb(); /* !? 204 !? */ 678 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 0:7 */ 679 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 8:15 */ 680 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 16:23 */ 681 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 24:27 */ 682 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 0:7 */ 683 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 8:15 */ 684 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 16:23 */ 685 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 24:27 */ 686 REG(vdac, bt_reg) = 0x00; tc_wmb(); 687 688 #if 0 /* XXX ULTRIX does initialize 16 entry window type here XXX */ 689 { 690 static u_int32_t windowtype[BT463_IREG_WINDOW_TYPE_TABLE] = { 691 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 692 }; 693 694 SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE); 695 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) { 696 REG(vdac, bt_reg) = windowtype[i]; /* 0:7 */ 697 REG(vdac, bt_reg) = windowtype[i] >> 8; /* 8:15 */ 698 REG(vdac, bt_reg) = windowtype[i] >> 16; /* 16:23 */ 699 } 700 } 701 #endif 702 703 SELECT(vdac, BT463_IREG_CPALETTE_RAM); 704 REG(vdac, bt_cmap) = 0; tc_wmb(); 705 REG(vdac, bt_cmap) = 0; tc_wmb(); 706 REG(vdac, bt_cmap) = 0; tc_wmb(); 707 for (i = 1; i < 256; i++) { 708 REG(vdac, bt_cmap) = 0xff; tc_wmb(); 709 REG(vdac, bt_cmap) = 0xff; tc_wmb(); 710 REG(vdac, bt_cmap) = 0xff; tc_wmb(); 711 } 712 713 /* !? Eeeh !? */ 714 SELECT(vdac, 0x0100 /* BT463_IREG_CURSOR_COLOR_0 */); 715 for (i = 0; i < 256; i++) { 716 REG(vdac, bt_cmap) = i; tc_wmb(); 717 REG(vdac, bt_cmap) = i; tc_wmb(); 718 REG(vdac, bt_cmap) = i; tc_wmb(); 719 } 720 } 721 } 722 723 static int 724 get_cmap(sc, p) 725 struct sfb_softc *sc; 726 struct wsdisplay_cmap *p; 727 { 728 u_int index = p->index, count = p->count; 729 730 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 731 return (EINVAL); 732 733 if (!uvm_useracc(p->red, count, B_WRITE) || 734 !uvm_useracc(p->green, count, B_WRITE) || 735 !uvm_useracc(p->blue, count, B_WRITE)) 736 return (EFAULT); 737 738 copyout(&sc->sc_cmap.r[index], p->red, count); 739 copyout(&sc->sc_cmap.g[index], p->green, count); 740 copyout(&sc->sc_cmap.b[index], p->blue, count); 741 742 return (0); 743 } 744 745 static int 746 set_cmap(sc, p) 747 struct sfb_softc *sc; 748 struct wsdisplay_cmap *p; 749 { 750 u_int index = p->index, count = p->count; 751 752 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 753 return (EINVAL); 754 755 if (!uvm_useracc(p->red, count, B_READ) || 756 !uvm_useracc(p->green, count, B_READ) || 757 !uvm_useracc(p->blue, count, B_READ)) 758 return (EFAULT); 759 760 copyin(p->red, &sc->sc_cmap.r[index], count); 761 copyin(p->green, &sc->sc_cmap.g[index], count); 762 copyin(p->blue, &sc->sc_cmap.b[index], count); 763 764 sc->sc_changed |= DATA_CMAP_CHANGED; 765 766 return (0); 767 } 768 769 770 static int 771 set_cursor(sc, p) 772 struct sfb_softc *sc; 773 struct wsdisplay_cursor *p; 774 { 775 #define cc (&sc->sc_cursor) 776 int v, index, count, icount, x, y; 777 778 v = p->which; 779 if (v & WSDISPLAY_CURSOR_DOCMAP) { 780 index = p->cmap.index; 781 count = p->cmap.count; 782 if (index >= 2 || (index + count) > 2) 783 return (EINVAL); 784 if (!uvm_useracc(p->cmap.red, count, B_READ) || 785 !uvm_useracc(p->cmap.green, count, B_READ) || 786 !uvm_useracc(p->cmap.blue, count, B_READ)) 787 return (EFAULT); 788 } 789 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 790 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 791 return (EINVAL); 792 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 793 if (!uvm_useracc(p->image, icount, B_READ) || 794 !uvm_useracc(p->mask, icount, B_READ)) 795 return (EFAULT); 796 } 797 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) { 798 if (v & WSDISPLAY_CURSOR_DOCUR) 799 cc->cc_hot = p->hot; 800 if (v & WSDISPLAY_CURSOR_DOPOS) { 801 struct fb_devconfig *dc = sc->sc_dc; 802 803 x = p->pos.x; 804 y = p->pos.y; 805 if (y < 0) 806 y = 0; 807 else if (y > dc->dc_ht) 808 y = dc->dc_ht; 809 if (x < 0) 810 x = 0; 811 else if (x > dc->dc_wid) 812 x = dc->dc_wid; 813 sc->sc_cursor.cc_pos.x = x; 814 sc->sc_cursor.cc_pos.y = y; 815 } 816 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 817 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 818 x += sc->sc_cursor.cc_magic.x; 819 y += sc->sc_cursor.cc_magic.y; 820 (*sc->sc_hwops.locate)(sc->sc_hw0, x, y); 821 } 822 823 sc->sc_changed = 0; 824 if (v & WSDISPLAY_CURSOR_DOCUR) { 825 sc->sc_curenb = p->enable; 826 sc->sc_changed |= DATA_ENB_CHANGED; 827 } 828 if (v & WSDISPLAY_CURSOR_DOCMAP) { 829 copyin(p->cmap.red, &cc->cc_color[index], count); 830 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 831 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 832 sc->sc_changed |= DATA_CURCMAP_CHANGED; 833 } 834 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 835 cc->cc_size = p->size; 836 memset(cc->cc_image, 0, sizeof cc->cc_image); 837 copyin(p->image, cc->cc_image, icount); 838 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount); 839 sc->sc_changed |= DATA_CURSHAPE_CHANGED; 840 } 841 842 return (0); 843 #undef cc 844 } 845 846 static int 847 get_cursor(sc, p) 848 struct sfb_softc *sc; 849 struct wsdisplay_cursor *p; 850 { 851 return (ENOTTY); /* XXX */ 852 } 853 854 int 855 sfb_alloc_attr(id, fg, bg, flags, attrp) 856 void *id; 857 int fg, bg, flags; 858 long *attrp; 859 { 860 if (flags & (WSATTR_HILIT | WSATTR_BLINK | 861 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) 862 return (EINVAL); 863 if (flags & WSATTR_REVERSE) 864 *attrp = 1; 865 else 866 *attrp = 0; 867 return (0); 868 } 869 870 static void 871 bt459visible(hw, on) 872 void *hw; 873 int on; 874 { 875 SELECT(hw, BT459_IREG_CCR); 876 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00; 877 tc_wmb(); 878 } 879 880 static void 881 sfbpvisible(hw, on) 882 void *hw; 883 int on; 884 { 885 } 886 887 static void 888 bt459locate(hw, x, y) 889 void *hw; 890 int x, y; 891 { 892 int s; 893 894 s = spltty(); 895 SELECT(hw, BT459_IREG_CURSOR_X_LOW); 896 REG(hw, bt_reg) = x; tc_wmb(); 897 REG(hw, bt_reg) = x >> 8; tc_wmb(); 898 REG(hw, bt_reg) = y; tc_wmb(); 899 REG(hw, bt_reg) = y >> 8; tc_wmb(); 900 splx(s); 901 } 902 903 static void 904 sfbplocate(hw, x, y) 905 void *hw; 906 int x, y; 907 { 908 *((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff); 909 tc_wmb(); 910 } 911 912 static void 913 bt459color(hw, cp) 914 void *hw; 915 u_int8_t *cp; 916 { 917 SELECT(hw, BT459_IREG_CCOLOR_2); 918 REG(hw, bt_reg) = cp[1]; tc_wmb(); 919 REG(hw, bt_reg) = cp[3]; tc_wmb(); 920 REG(hw, bt_reg) = cp[5]; tc_wmb(); 921 922 REG(hw, bt_reg) = cp[0]; tc_wmb(); 923 REG(hw, bt_reg) = cp[2]; tc_wmb(); 924 REG(hw, bt_reg) = cp[4]; tc_wmb(); 925 } 926 927 static void 928 bt463color(hw, cp) 929 void *hw; 930 u_int8_t *cp; 931 { 932 } 933 934 static void 935 bt459shape(hw, size, image) 936 void *hw; 937 struct wsdisplay_curpos *size; 938 u_int64_t *image; 939 { 940 u_int8_t *ip, *mp, img, msk; 941 u_int8_t u; 942 int bcnt; 943 944 ip = (u_int8_t *)image; 945 mp = (u_int8_t *)(image + CURSOR_MAX_SIZE); 946 947 bcnt = 0; 948 SELECT(hw, BT459_IREG_CRAM_BASE+0); 949 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 950 while (bcnt < size->y * 16) { 951 /* pad right half 32 pixel when smaller than 33 */ 952 if ((bcnt & 0x8) && size->x < 33) { 953 REG(hw, bt_reg) = 0; tc_wmb(); 954 REG(hw, bt_reg) = 0; tc_wmb(); 955 } 956 else { 957 img = *ip++; 958 msk = *mp++; 959 img &= msk; /* cookie off image */ 960 u = (msk & 0x0f) << 4 | (img & 0x0f); 961 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 962 u = (msk & 0xf0) | (img & 0xf0) >> 4; 963 REG(hw, bt_reg) = shuffle[u]; tc_wmb(); 964 } 965 bcnt += 2; 966 } 967 /* pad unoccupied scan lines */ 968 while (bcnt < CURSOR_MAX_SIZE * 16) { 969 REG(hw, bt_reg) = 0; tc_wmb(); 970 REG(hw, bt_reg) = 0; tc_wmb(); 971 bcnt += 2; 972 } 973 } 974 975 static void 976 sfbpshape(hw, size, image) 977 void *hw; 978 struct wsdisplay_curpos *size; 979 u_int64_t *image; 980 { 981 } 982 983 static void 984 bt459setlut(hw, cm) 985 void *hw; 986 struct hwcmap256 *cm; 987 { 988 int index; 989 990 SELECT(hw, 0); 991 for (index = 0; index < CMAP_SIZE; index++) { 992 REG(hw, bt_cmap) = cm->r[index]; tc_wmb(); 993 REG(hw, bt_cmap) = cm->g[index]; tc_wmb(); 994 REG(hw, bt_cmap) = cm->b[index]; tc_wmb(); 995 } 996 } 997 998 static void 999 noplut(hw, cm) 1000 void *hw; 1001 struct hwcmap256 *cm; 1002 { 1003 } 1004