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