1 /* $NetBSD: tfb.c,v 1.3 1998/11/09 03:58:06 nisimura Exp $ */ 2 3 /* 4 * Copyright (c) 1998 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: tfb.c,v 1.3 1998/11/09 03:58:06 nisimura 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 #include <machine/autoconf.h> 54 55 #include <dev/tc/tcvar.h> 56 #include <dev/ic/bt463reg.h> 57 #include <dev/ic/bt431reg.h> 58 59 #include "opt_uvm.h" 60 #if defined(UVM) 61 #include <uvm/uvm_extern.h> 62 #define useracc uvm_useracc 63 #endif 64 65 /* XXX BUS'IFYING XXX */ 66 67 #if defined(__pmax__) 68 #define machine_btop(x) mips_btop(x) 69 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG0_TO_PHYS(x) 70 71 struct bt463reg { 72 u_int8_t bt_lo; 73 unsigned : 24; 74 u_int8_t bt_hi; 75 unsigned : 24; 76 u_int8_t bt_reg; 77 unsigned : 24; 78 u_int8_t bt_cmap; 79 }; 80 81 /* it's really painful to manipulate 'twined' registers... */ 82 struct bt431reg { 83 u_int16_t bt_lo; 84 unsigned : 16; 85 u_int16_t bt_hi; 86 unsigned : 16; 87 u_int16_t bt_ram; 88 unsigned : 16; 89 u_int16_t bt_ctl; 90 }; 91 #endif 92 93 #if defined(__alpha__) || defined(alpha) 94 #define machine_btop(x) alpha_btop(x) 95 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x) 96 97 struct bt463reg { 98 u_int32_t bt_lo; 99 u_int32_t bt_hi; 100 u_int32_t bt_reg; 101 u_int32_t bt_cmap; 102 }; 103 104 /* 105 * N.B. a paif of Bt431s are located adjascently. 106 * struct bt431twin { 107 * struct { 108 * u_int8_t u0; for sprite image 109 * u_int8_t u1; for sprite mask 110 * unsigned :16; 111 * } bt_lo; 112 * ... 113 */ 114 struct bt431reg { 115 u_int32_t bt_lo; 116 u_int32_t bt_hi; 117 u_int32_t bt_ram; 118 u_int32_t bt_ctl; 119 }; 120 #endif 121 122 /* XXX XXX XXX */ 123 124 struct fb_devconfig { 125 vaddr_t dc_vaddr; /* memory space virtual base address */ 126 paddr_t dc_paddr; /* memory space physical base address */ 127 vsize_t dc_size; /* size of slot memory */ 128 int dc_wid; /* width of frame buffer */ 129 int dc_ht; /* height of frame buffer */ 130 int dc_depth; /* depth, bits per pixel */ 131 int dc_rowbytes; /* bytes in a FB scan line */ 132 vaddr_t dc_videobase; /* base of flat frame buffer */ 133 struct raster dc_raster; /* raster description */ 134 struct rcons dc_rcons; /* raster blitter control info */ 135 int dc_blanked; /* currently has video disabled */ 136 }; 137 138 struct hwcmap { 139 #define CMAP_SIZE 256 /* R/G/B entries */ 140 u_int8_t r[CMAP_SIZE]; 141 u_int8_t g[CMAP_SIZE]; 142 u_int8_t b[CMAP_SIZE]; 143 }; 144 145 struct hwcursor { 146 struct wsdisplay_curpos cc_pos; 147 struct wsdisplay_curpos cc_hot; 148 struct wsdisplay_curpos cc_size; 149 #define CURSOR_MAX_SIZE 64 150 u_int8_t cc_color[6]; 151 u_int64_t cc_image[64 + 64]; 152 }; 153 154 struct tfb_softc { 155 struct device sc_dev; 156 struct fb_devconfig *sc_dc; /* device configuration */ 157 struct hwcmap sc_cmap; /* software copy of colormap */ 158 struct hwcursor sc_cursor; /* software copy of cursor */ 159 int sc_curenb; /* cursor sprite enabled */ 160 int sc_changed; /* need update of colormap */ 161 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */ 162 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */ 163 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */ 164 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */ 165 #define DATA_ALL_CHANGED 0x0f 166 int nscreens; 167 short magic_x, magic_y; /* TX cursor location offset */ 168 #define TX_MAGIC_X 220 169 #define TX_MAGIC_Y 35 170 }; 171 172 #define TX_BT463_OFFSET 0x040000 173 #define TX_BT431_OFFSET 0x040010 174 #define TX_CONTROL 0x040030 175 #define TX_MAP_REGISTER 0x040030 176 #define TX_PIP_OFFSET 0x0800c0 177 #define TX_SELECTION 0x100000 178 #define TX_8FB_OFFSET 0x200000 179 #define TX_8FB_SIZE 0x100000 180 #define TX_24FB_OFFSET 0x400000 181 #define TX_24FB_SIZE 0x400000 182 #define TX_VIDEO_ENABLE 0xa00000 183 184 #define TX_CTL_VIDEO_ON 0x80 185 #define TX_CTL_INT_ENA 0x40 186 #define TX_CTL_INT_PEND 0x20 187 #define TX_CTL_SEG_ENA 0x10 188 #define TX_CTL_SEG 0x0f 189 190 int tfbmatch __P((struct device *, struct cfdata *, void *)); 191 void tfbattach __P((struct device *, struct device *, void *)); 192 193 struct cfattach tfb_ca = { 194 sizeof(struct tfb_softc), tfbmatch, tfbattach, 195 }; 196 197 void tfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *)); 198 struct fb_devconfig tfb_console_dc; 199 tc_addr_t tfb_consaddr; 200 201 struct wsdisplay_emulops tfb_emulops = { 202 rcons_cursor, /* could use hardware cursor; punt */ 203 rcons_mapchar, 204 rcons_putchar, 205 rcons_copycols, 206 rcons_erasecols, 207 rcons_copyrows, 208 rcons_eraserows, 209 rcons_alloc_attr 210 }; 211 212 struct wsscreen_descr tfb_stdscreen = { 213 "std", 0, 0, 214 &tfb_emulops, 215 0, 0, 216 0 217 }; 218 219 const struct wsscreen_descr *_tfb_scrlist[] = { 220 &tfb_stdscreen, 221 }; 222 223 struct wsscreen_list tfb_screenlist = { 224 sizeof(_tfb_scrlist) / sizeof(struct wsscreen_descr *), _tfb_scrlist 225 }; 226 227 int tfbioctl __P((void *, u_long, caddr_t, int, struct proc *)); 228 int tfbmmap __P((void *, off_t, int)); 229 230 int tfb_alloc_screen __P((void *, const struct wsscreen_descr *, 231 void **, int *, int *, long *)); 232 void tfb_free_screen __P((void *, void *)); 233 void tfb_show_screen __P((void *, void *)); 234 int tfb_load_font __P((void *, void *, int, int, int, void *)); 235 236 struct wsdisplay_accessops tfb_accessops = { 237 tfbioctl, 238 tfbmmap, 239 tfb_alloc_screen, 240 tfb_free_screen, 241 tfb_show_screen, 242 tfb_load_font 243 }; 244 245 int tfb_cnattach __P((tc_addr_t)); 246 int tfbintr __P((void *)); 247 void tfbinit __P((struct fb_devconfig *)); 248 249 static int get_cmap __P((struct tfb_softc *, struct wsdisplay_cmap *)); 250 static int set_cmap __P((struct tfb_softc *, struct wsdisplay_cmap *)); 251 static int set_cursor __P((struct tfb_softc *, struct wsdisplay_cursor *)); 252 static int get_cursor __P((struct tfb_softc *, struct wsdisplay_cursor *)); 253 static void set_curpos __P((struct tfb_softc *, struct wsdisplay_curpos *)); 254 static void bt431_set_curpos __P((struct tfb_softc *)); 255 256 #define TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin) 257 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8) 258 259 /* XXX XXX XXX */ 260 #define BT431_SELECT(curs, regno) do { \ 261 u_int16_t twin; \ 262 curs->bt_lo = TWIN_LO(regno); \ 263 curs->bt_hi = TWIN_HI(regno); \ 264 tc_wmb(); \ 265 } while (0) 266 267 #define BT463_SELECT(vdac, regno) do { \ 268 vdac->bt_lo = (regno) & 0x00ff; \ 269 vdac->bt_hi = ((regno)& 0xff00) >> 8; \ 270 tc_wmb(); \ 271 } while (0) 272 /* XXX XXX XXX */ 273 274 /* bit order reverse */ 275 const static u_int8_t flip[256] = { 276 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 277 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 278 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 279 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 280 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 281 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 282 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 283 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 284 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 285 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 286 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 287 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 288 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 289 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 290 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 291 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 292 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 293 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 294 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 295 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 296 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 297 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 298 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 299 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 300 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 301 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 302 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 303 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 304 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 305 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 306 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 307 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 308 }; 309 310 int 311 tfbmatch(parent, match, aux) 312 struct device *parent; 313 struct cfdata *match; 314 void *aux; 315 { 316 struct tc_attach_args *ta = aux; 317 318 if (strncmp("PMAG-RO ", ta->ta_modname, TC_ROM_LLEN) != 0 319 && strncmp("PMAG-JA ", ta->ta_modname, TC_ROM_LLEN) != 0) 320 return (0); 321 322 return (1); 323 } 324 325 void 326 tfb_getdevconfig(dense_addr, dc) 327 tc_addr_t dense_addr; 328 struct fb_devconfig *dc; 329 { 330 struct raster *rap; 331 struct rcons *rcp; 332 int i; 333 334 dc->dc_vaddr = dense_addr; 335 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr); 336 337 dc->dc_wid = 1280; 338 dc->dc_ht = 1024; 339 dc->dc_depth = 8; 340 dc->dc_rowbytes = 1280; 341 dc->dc_videobase = dc->dc_vaddr + TX_8FB_OFFSET; 342 dc->dc_blanked = 0; 343 344 /* initialize colormap and cursor resource */ 345 tfbinit(dc); 346 347 /* clear the screen */ 348 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t)) 349 *(u_int32_t *)(dc->dc_videobase + i) = 0x0; 350 351 /* initialize the raster */ 352 rap = &dc->dc_raster; 353 rap->width = dc->dc_wid; 354 rap->height = dc->dc_ht; 355 rap->depth = dc->dc_depth; 356 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t); 357 rap->pixels = (u_int32_t *)dc->dc_videobase; 358 359 /* initialize the raster console blitter */ 360 rcp = &dc->dc_rcons; 361 rcp->rc_sp = rap; 362 rcp->rc_crow = rcp->rc_ccol = -1; 363 rcp->rc_crowp = &rcp->rc_crow; 364 rcp->rc_ccolp = &rcp->rc_ccol; 365 rcons_init(rcp, 34, 80); 366 367 tfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow; 368 tfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol; 369 } 370 371 void 372 tfbattach(parent, self, aux) 373 struct device *parent, *self; 374 void *aux; 375 { 376 struct tfb_softc *sc = (struct tfb_softc *)self; 377 struct tc_attach_args *ta = aux; 378 struct wsemuldisplaydev_attach_args waa; 379 struct hwcmap *cm; 380 int console, i; 381 382 console = (ta->ta_addr == tfb_consaddr); 383 if (console) { 384 sc->sc_dc = &tfb_console_dc; 385 sc->nscreens = 1; 386 } 387 else { 388 sc->sc_dc = (struct fb_devconfig *) 389 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK); 390 tfb_getdevconfig(ta->ta_addr, sc->sc_dc); 391 } 392 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, 393 sc->sc_dc->dc_depth); 394 395 cm = &sc->sc_cmap; 396 cm->r[0] = cm->g[0] = cm->b[0] = 0; 397 for (i = 1; i < CMAP_SIZE; i++) { 398 cm->r[i] = cm->g[i] = cm->b[i] = 0xff; 399 } 400 sc->magic_x = TX_MAGIC_X; sc->magic_y = TX_MAGIC_Y; 401 402 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, tfbintr, sc); 403 *(u_int8_t *)(sc->sc_dc->dc_vaddr + TX_CONTROL) &= ~0x40; 404 *(u_int8_t *)(sc->sc_dc->dc_vaddr + TX_CONTROL) |= 0x40; 405 406 waa.console = console; 407 waa.scrdata = &tfb_screenlist; 408 waa.accessops = &tfb_accessops; 409 waa.accesscookie = sc; 410 411 config_found(self, &waa, wsemuldisplaydevprint); 412 } 413 414 int 415 tfbioctl(v, cmd, data, flag, p) 416 void *v; 417 u_long cmd; 418 caddr_t data; 419 int flag; 420 struct proc *p; 421 { 422 struct tfb_softc *sc = v; 423 struct fb_devconfig *dc = sc->sc_dc; 424 int turnoff; 425 426 switch (cmd) { 427 case WSDISPLAYIO_GTYPE: 428 *(u_int *)data = /* WSDISPLAY_TYPE_TX */ 0x19980910; 429 return (0); 430 431 case WSDISPLAYIO_GINFO: 432 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 433 wsd_fbip->height = sc->sc_dc->dc_ht; 434 wsd_fbip->width = sc->sc_dc->dc_wid; 435 wsd_fbip->depth = sc->sc_dc->dc_depth; 436 wsd_fbip->cmsize = CMAP_SIZE; 437 #undef fbt 438 return (0); 439 440 case WSDISPLAYIO_GETCMAP: 441 return get_cmap(sc, (struct wsdisplay_cmap *)data); 442 443 case WSDISPLAYIO_PUTCMAP: 444 return set_cmap(sc, (struct wsdisplay_cmap *)data); 445 446 case WSDISPLAYIO_SVIDEO: 447 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 448 if ((dc->dc_blanked == 0) ^ turnoff) { 449 dc->dc_blanked = turnoff; 450 /* XXX later XXX */ 451 } 452 return (0); 453 454 case WSDISPLAYIO_GVIDEO: 455 *(u_int *)data = dc->dc_blanked ? 456 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 457 return (0); 458 459 case WSDISPLAYIO_GCURPOS: 460 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 461 return (0); 462 463 case WSDISPLAYIO_SCURPOS: 464 set_curpos(sc, (struct wsdisplay_curpos *)data); 465 bt431_set_curpos(sc); 466 return (0); 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 int 483 tfbmmap(v, offset, prot) 484 void *v; 485 off_t offset; 486 int prot; 487 { 488 struct tfb_softc *sc = v; 489 490 if (offset > TX_8FB_SIZE) /* XXX */ 491 return (-1); 492 return machine_btop(sc->sc_dc->dc_paddr + TX_8FB_OFFSET + offset); 493 } 494 495 int 496 tfb_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 tfb_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 rcons_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 tfb_free_screen(v, cookie) 520 void *v; 521 void *cookie; 522 { 523 struct tfb_softc *sc = v; 524 525 if (sc->sc_dc == &tfb_console_dc) 526 panic("tfb_free_screen: console"); 527 528 sc->nscreens--; 529 } 530 531 void 532 tfb_show_screen(v, cookie) 533 void *v; 534 void *cookie; 535 { 536 } 537 538 int 539 tfb_load_font(v, cookie, first, num, stride, data) 540 void *v; 541 void *cookie; 542 int first, num, stride; 543 void *data; 544 { 545 return (EINVAL); 546 } 547 548 int 549 tfb_cnattach(addr) 550 tc_addr_t addr; 551 { 552 struct fb_devconfig *dcp = &tfb_console_dc; 553 long defattr; 554 555 tfb_getdevconfig(addr, dcp); 556 557 rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr); 558 559 wsdisplay_cnattach(&tfb_stdscreen, &dcp->dc_rcons, 560 0, 0, defattr); 561 tfb_consaddr = addr; 562 return(0); 563 } 564 565 int 566 tfbintr(arg) 567 void *arg; 568 { 569 struct tfb_softc *sc = arg; 570 caddr_t tfbbase; 571 struct bt463reg *vdac; 572 struct bt431reg *curs; 573 int v; 574 575 if (sc->sc_changed == 0) 576 return (1); 577 578 tfbbase = (caddr_t)sc->sc_dc->dc_vaddr; 579 vdac = (void *)(tfbbase + TX_BT463_OFFSET); 580 curs = (void *)(tfbbase + TX_BT431_OFFSET); 581 *(u_int8_t *)(tfbbase + TX_CONTROL) &= ~0x40; 582 v = sc->sc_changed; 583 sc->sc_changed = 0; 584 if (v & DATA_ENB_CHANGED) { 585 BT431_SELECT(curs, BT431_REG_COMMAND); 586 curs->bt_ctl = (sc->sc_curenb) ? 0x4444 : 0x0404; 587 } 588 if (v & DATA_CURCMAP_CHANGED) { 589 u_int8_t *cp = sc->sc_cursor.cc_color; 590 591 BT463_SELECT(vdac, BT463_IREG_CURSOR_COLOR_0); 592 vdac->bt_reg = cp[1]; tc_wmb(); 593 vdac->bt_reg = cp[3]; tc_wmb(); 594 vdac->bt_reg = cp[5]; tc_wmb(); 595 596 vdac->bt_reg = cp[0]; tc_wmb(); 597 vdac->bt_reg = cp[2]; tc_wmb(); 598 vdac->bt_reg = cp[4]; tc_wmb(); 599 600 vdac->bt_reg = cp[1]; tc_wmb(); 601 vdac->bt_reg = cp[3]; tc_wmb(); 602 vdac->bt_reg = cp[5]; tc_wmb(); 603 604 vdac->bt_reg = cp[1]; tc_wmb(); 605 vdac->bt_reg = cp[3]; tc_wmb(); 606 vdac->bt_reg = cp[5]; tc_wmb(); 607 } 608 if (v & DATA_CURSHAPE_CHANGED) { 609 u_int8_t *ip, *mp, img, msk; 610 int bcnt; 611 612 ip = (u_int8_t *)sc->sc_cursor.cc_image; 613 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE); 614 615 bcnt = 0; 616 BT431_SELECT(curs, BT431_REG_CRAM_BASE+0); 617 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 618 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 619 /* pad right half 32 pixel when smaller than 33 */ 620 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 621 curs->bt_ram = 0; 622 tc_wmb(); 623 } 624 else { 625 img = *ip++; 626 msk = *mp++; 627 img &= msk; /* cookie off image */ 628 curs->bt_ram = (flip[msk] << 8) | flip[img]; 629 tc_wmb(); 630 } 631 bcnt += 2; 632 } 633 /* pad unoccupied scan lines */ 634 while (bcnt < CURSOR_MAX_SIZE * 16) { 635 curs->bt_ram = 0; 636 tc_wmb(); 637 bcnt += 2; 638 } 639 } 640 if (v & DATA_CMAP_CHANGED) { 641 struct hwcmap *cm = &sc->sc_cmap; 642 int index; 643 644 BT463_SELECT(vdac, BT463_IREG_CPALETTE_RAM); 645 for (index = 0; index < CMAP_SIZE; index++) { 646 vdac->bt_cmap = cm->r[index]; 647 vdac->bt_cmap = cm->g[index]; 648 vdac->bt_cmap = cm->b[index]; 649 } 650 } 651 *(u_int8_t *)(tfbbase + TX_CONTROL) |= 0x40; 652 return (1); 653 } 654 655 void 656 tfbinit(dc) 657 struct fb_devconfig *dc; 658 { 659 caddr_t tfbbase = (caddr_t)dc->dc_vaddr; 660 struct bt463reg *vdac = (void *)(tfbbase + TX_BT463_OFFSET); 661 struct bt431reg *curs = (void *)(tfbbase + TX_BT431_OFFSET); 662 int i; 663 664 BT463_SELECT(vdac, BT463_IREG_COMMAND_0); 665 vdac->bt_reg = 0x40; tc_wmb(); 666 vdac->bt_reg = 0x46; tc_wmb(); 667 vdac->bt_reg = 0xc0; tc_wmb(); 668 vdac->bt_reg = 0; tc_wmb(); /* !? 204 !? */ 669 vdac->bt_reg = 0xff; tc_wmb(); /* plane 0:7 */ 670 vdac->bt_reg = 0xff; tc_wmb(); /* plane 8:15 */ 671 vdac->bt_reg = 0xff; tc_wmb(); /* plane 16:23 */ 672 vdac->bt_reg = 0xff; tc_wmb(); /* plane 24:27 */ 673 vdac->bt_reg = 0x00; tc_wmb(); /* blink 0:7 */ 674 vdac->bt_reg = 0x00; tc_wmb(); /* blink 8:15 */ 675 vdac->bt_reg = 0x00; tc_wmb(); /* blink 16:23 */ 676 vdac->bt_reg = 0x00; tc_wmb(); /* blink 24:27 */ 677 vdac->bt_reg = 0x00; tc_wmb(); 678 679 BT463_SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE); 680 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) { 681 vdac->bt_reg = /* ??? */ 0; 682 vdac->bt_reg = /* ??? */ 0; 683 vdac->bt_reg = /* ??? */ 0; 684 } 685 686 BT463_SELECT(vdac, BT463_IREG_CPALETTE_RAM); 687 vdac->bt_cmap = 0; tc_wmb(); 688 vdac->bt_cmap = 0; tc_wmb(); 689 vdac->bt_cmap = 0; tc_wmb(); 690 for (i = 1; i < BT463_NCMAP_ENTRIES; i++) { 691 vdac->bt_cmap = 0xff; tc_wmb(); 692 vdac->bt_cmap = 0xff; tc_wmb(); 693 vdac->bt_cmap = 0xff; tc_wmb(); 694 } 695 696 BT431_SELECT(curs, BT431_REG_COMMAND); 697 curs->bt_ctl = 0x0404; tc_wmb(); 698 curs->bt_ctl = 0; tc_wmb(); 699 curs->bt_ctl = 0; tc_wmb(); 700 curs->bt_ctl = 0; tc_wmb(); 701 curs->bt_ctl = 0; tc_wmb(); 702 curs->bt_ctl = 0; tc_wmb(); 703 curs->bt_ctl = 0; tc_wmb(); 704 curs->bt_ctl = 0; tc_wmb(); 705 curs->bt_ctl = 0; tc_wmb(); 706 curs->bt_ctl = 0; tc_wmb(); 707 curs->bt_ctl = 0; tc_wmb(); 708 curs->bt_ctl = 0; tc_wmb(); 709 curs->bt_ctl = 0; tc_wmb(); 710 } 711 712 static int 713 get_cmap(sc, p) 714 struct tfb_softc *sc; 715 struct wsdisplay_cmap *p; 716 { 717 u_int index = p->index, count = p->count; 718 719 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 720 return (EINVAL); 721 722 if (!useracc(p->red, count, B_WRITE) || 723 !useracc(p->green, count, B_WRITE) || 724 !useracc(p->blue, count, B_WRITE)) 725 return (EFAULT); 726 727 copyout(&sc->sc_cmap.r[index], p->red, count); 728 copyout(&sc->sc_cmap.g[index], p->green, count); 729 copyout(&sc->sc_cmap.b[index], p->blue, count); 730 731 return (0); 732 } 733 734 static int 735 set_cmap(sc, p) 736 struct tfb_softc *sc; 737 struct wsdisplay_cmap *p; 738 { 739 u_int index = p->index, count = p->count; 740 741 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 742 return (EINVAL); 743 744 if (!useracc(p->red, count, B_READ) || 745 !useracc(p->green, count, B_READ) || 746 !useracc(p->blue, count, B_READ)) 747 return (EFAULT); 748 749 copyin(p->red, &sc->sc_cmap.r[index], count); 750 copyin(p->green, &sc->sc_cmap.g[index], count); 751 copyin(p->blue, &sc->sc_cmap.b[index], count); 752 753 sc->sc_changed |= DATA_CMAP_CHANGED; 754 755 return (0); 756 } 757 758 static int 759 set_cursor(sc, p) 760 struct tfb_softc *sc; 761 struct wsdisplay_cursor *p; 762 { 763 #define cc (&sc->sc_cursor) 764 int v, index, count; 765 766 v = p->which; 767 if (v & WSDISPLAY_CURSOR_DOCMAP) { 768 index = p->cmap.index; 769 count = p->cmap.count; 770 if (index >= 2 || (index + count) > 2) 771 return (EINVAL); 772 if (!useracc(p->cmap.red, count, B_READ) || 773 !useracc(p->cmap.green, count, B_READ) || 774 !useracc(p->cmap.blue, count, B_READ)) 775 return (EFAULT); 776 } 777 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 778 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 779 return (EINVAL); 780 count = ((p->size.x < 33) ? 4 : 8) * p->size.y; 781 if (!useracc(p->image, count, B_READ) || 782 !useracc(p->mask, count, B_READ)) 783 return (EFAULT); 784 } 785 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) { 786 if (v & WSDISPLAY_CURSOR_DOCUR) 787 cc->cc_hot = p->hot; 788 if (v & WSDISPLAY_CURSOR_DOPOS) 789 set_curpos(sc, &p->pos); 790 bt431_set_curpos(sc); 791 } 792 793 sc->sc_changed = 0; 794 if (v & WSDISPLAY_CURSOR_DOCUR) { 795 sc->sc_curenb = p->enable; 796 sc->sc_changed |= DATA_ENB_CHANGED; 797 } 798 if (v & WSDISPLAY_CURSOR_DOCMAP) { 799 count = p->cmap.count; 800 copyin(p->cmap.red, &cc->cc_color[index], count); 801 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 802 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 803 sc->sc_changed |= DATA_CURCMAP_CHANGED; 804 } 805 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 806 cc->cc_size = p->size; 807 memset(cc->cc_image, 0, sizeof cc->cc_image); 808 copyin(p->image, cc->cc_image, count); 809 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count); 810 sc->sc_changed |= DATA_CURSHAPE_CHANGED; 811 } 812 813 return (0); 814 #undef cc 815 } 816 817 static int 818 get_cursor(sc, p) 819 struct tfb_softc *sc; 820 struct wsdisplay_cursor *p; 821 { 822 return (ENOTTY); /* XXX */ 823 } 824 825 static void 826 set_curpos(sc, curpos) 827 struct tfb_softc *sc; 828 struct wsdisplay_curpos *curpos; 829 { 830 struct fb_devconfig *dc = sc->sc_dc; 831 int x = curpos->x, y = curpos->y; 832 833 if (y < 0) 834 y = 0; 835 else if (y > dc->dc_ht) 836 y = dc->dc_ht; 837 if (x < 0) 838 x = 0; 839 else if (x > dc->dc_wid) 840 x = dc->dc_wid; 841 sc->sc_cursor.cc_pos.x = x; 842 sc->sc_cursor.cc_pos.y = y; 843 } 844 845 static void 846 bt431_set_curpos(sc) 847 struct tfb_softc *sc; 848 { 849 caddr_t tfbbase = (caddr_t)sc->sc_dc->dc_vaddr; 850 struct bt431reg *curs = (void *)(tfbbase + TX_BT431_OFFSET); 851 u_int16_t twin; 852 int x, y, s; 853 854 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 855 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 856 x += sc->magic_x; y += sc->magic_y; /* magic offset of TX coordinate */ 857 858 s = spltty(); 859 860 BT431_SELECT(curs, BT431_REG_CURSOR_X_LOW); 861 curs->bt_ctl = TWIN_LO(x); tc_wmb(); 862 curs->bt_ctl = TWIN_HI(x); tc_wmb(); 863 curs->bt_ctl = TWIN_LO(y); tc_wmb(); 864 curs->bt_ctl = TWIN_HI(y); tc_wmb(); 865 866 splx(s); 867 } 868