1 /* $NetBSD: tfb.c,v 1.50 2006/04/12 19:38:24 jmmv Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 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> 34 __KERNEL_RCSID(0, "$NetBSD: tfb.c,v 1.50 2006/04/12 19:38:24 jmmv Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/device.h> 40 #include <sys/malloc.h> 41 #include <sys/buf.h> 42 #include <sys/ioctl.h> 43 44 #include <machine/bus.h> 45 #include <machine/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/bt463reg.h> 55 #include <dev/ic/bt431reg.h> 56 57 #include <uvm/uvm_extern.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 /* 68 * struct bt463reg { 69 * u_int8_t bt_lo; 70 * unsigned : 24; 71 * u_int8_t bt_hi; 72 * unsigned : 24; 73 * u_int8_t bt_reg; 74 * unsigned : 24; 75 * u_int8_t bt_cmap; 76 * }; 77 * 78 * N.B. a pair of Bt431s are located adjascently. 79 * struct bt431twin { 80 * struct { 81 * u_int8_t u0; for sprite mask 82 * u_int8_t u1; for sprite image 83 * unsigned :16; 84 * } bt_lo; 85 * ... 86 * 87 * struct bt431reg { 88 * u_int16_t bt_lo; 89 * unsigned : 16; 90 * u_int16_t bt_hi; 91 * unsigned : 16; 92 * u_int16_t bt_ram; 93 * unsigned : 16; 94 * u_int16_t bt_ctl; 95 * }; 96 */ 97 98 /* Bt463 hardware registers, memory-mapped in 32bit stride */ 99 #define bt_lo 0x0 100 #define bt_hi 0x4 101 #define bt_reg 0x8 102 #define bt_cmap 0xc 103 104 /* Bt431 hardware registers, memory-mapped in 32bit stride */ 105 #define bt_ram 0x8 106 #define bt_ctl 0xc 107 108 #define REGWRITE32(p,i,v) do { \ 109 *(volatile u_int32_t *)((p) + (i)) = (v); tc_wmb(); \ 110 } while (0) 111 112 #define SELECT463(p,r) do { \ 113 REGWRITE32((p), bt_lo, 0xff & (r)); \ 114 REGWRITE32((p), bt_hi, 0xff & ((r)>>8)); \ 115 } while (0) 116 117 #define TWIN(x) ((x) | ((x) << 8)) 118 #define TWIN_LO(x) (twin = (x) & 0x00ff, (twin << 8) | twin) 119 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | (twin >> 8)) 120 121 #define SELECT431(p,r) do { \ 122 REGWRITE32((p), bt_lo, TWIN(r)); \ 123 REGWRITE32((p), bt_hi, 0); \ 124 } while (0) 125 126 struct hwcmap256 { 127 #define CMAP_SIZE 256 /* R/G/B entries */ 128 u_int8_t r[CMAP_SIZE]; 129 u_int8_t g[CMAP_SIZE]; 130 u_int8_t b[CMAP_SIZE]; 131 }; 132 133 struct hwcursor64 { 134 struct wsdisplay_curpos cc_pos; 135 struct wsdisplay_curpos cc_hot; 136 struct wsdisplay_curpos cc_size; 137 struct wsdisplay_curpos cc_magic; 138 #define CURSOR_MAX_SIZE 64 139 u_int8_t cc_color[6]; 140 u_int64_t cc_image[CURSOR_MAX_SIZE]; 141 u_int64_t cc_mask[CURSOR_MAX_SIZE]; 142 }; 143 144 struct tfb_softc { 145 struct device sc_dev; 146 vaddr_t sc_vaddr; 147 size_t sc_size; 148 struct rasops_info *sc_ri; 149 struct hwcmap256 sc_cmap; /* software copy of colormap */ 150 struct hwcursor64 sc_cursor; /* software copy of cursor */ 151 int sc_blanked; /* video visibility disabled */ 152 int sc_curenb; /* cursor sprite enabled */ 153 int sc_changed; /* need update of hardware */ 154 #define WSDISPLAY_CMAP_DOLUT 0x20 155 int nscreens; 156 }; 157 158 #define TX_MAGIC_X 360 159 #define TX_MAGIC_Y 36 160 161 #define TX_BT463_OFFSET 0x040000 162 #define TX_BT431_OFFSET 0x040010 163 #define TX_CONTROL 0x040030 164 #define TX_MAP_REGISTER 0x040030 165 #define TX_PIP_OFFSET 0x0800c0 166 #define TX_SELECTION 0x100000 167 #define TX_8BPP_OFFSET 0x200000 168 #define TX_8BPP_SIZE 0x200000 169 #define TX_24BPP_OFFSET 0x400000 170 #define TX_24BPP_SIZE 0x600000 171 #define TX_VIDEO_ENABLE 0xa00000 172 173 #define TX_CTL_VIDEO_ON 0x80 174 #define TX_CTL_INT_ENA 0x40 175 #define TX_CTL_INT_PEND 0x20 176 #define TX_CTL_SEG_ENA 0x10 177 #define TX_CTL_SEG 0x0f 178 179 static int tfbmatch(struct device *, struct cfdata *, void *); 180 static void tfbattach(struct device *, struct device *, void *); 181 182 CFATTACH_DECL(tfb, sizeof(struct tfb_softc), 183 tfbmatch, tfbattach, NULL, NULL); 184 185 static void tfb_common_init(struct rasops_info *); 186 static void tfb_cmap_init(struct tfb_softc *); 187 static struct rasops_info tfb_console_ri; 188 static tc_addr_t tfb_consaddr; 189 190 static struct wsscreen_descr tfb_stdscreen = { 191 "std", 0, 0, 192 0, /* textops */ 193 0, 0, 194 WSSCREEN_REVERSE 195 }; 196 197 static const struct wsscreen_descr *_tfb_scrlist[] = { 198 &tfb_stdscreen, 199 }; 200 201 static const struct wsscreen_list tfb_screenlist = { 202 sizeof(_tfb_scrlist) / sizeof(struct wsscreen_descr *), _tfb_scrlist 203 }; 204 205 static int tfbioctl(void *, void *, u_long, caddr_t, int, struct lwp *); 206 static paddr_t tfbmmap(void *, void *, off_t, int); 207 208 static int tfb_alloc_screen(void *, const struct wsscreen_descr *, 209 void **, int *, int *, long *); 210 static void tfb_free_screen(void *, void *); 211 static int tfb_show_screen(void *, void *, int, 212 void (*) (void *, int, int), void *); 213 214 static const struct wsdisplay_accessops tfb_accessops = { 215 tfbioctl, 216 tfbmmap, 217 tfb_alloc_screen, 218 tfb_free_screen, 219 tfb_show_screen, 220 0 /* load_font */ 221 }; 222 223 int tfb_cnattach(tc_addr_t); 224 static int tfbintr(void *); 225 static void tfbhwinit(caddr_t); 226 227 static int get_cmap(struct tfb_softc *, struct wsdisplay_cmap *); 228 static int set_cmap(struct tfb_softc *, struct wsdisplay_cmap *); 229 static int set_cursor(struct tfb_softc *, struct wsdisplay_cursor *); 230 static int get_cursor(struct tfb_softc *, struct wsdisplay_cursor *); 231 static void set_curpos(struct tfb_softc *, struct wsdisplay_curpos *); 232 233 /* bit order reverse */ 234 static const u_int8_t flip[256] = { 235 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 236 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 237 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 238 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 239 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 240 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 241 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 242 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 243 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 244 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 245 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 246 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 247 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 248 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 249 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 250 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 251 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 252 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 253 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 254 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 255 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 256 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 257 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 258 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 259 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 260 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 261 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 262 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 263 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 264 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 265 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 266 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 267 }; 268 269 static int 270 tfbmatch(struct device *parent, struct cfdata *match, void *aux) 271 { 272 struct tc_attach_args *ta = aux; 273 274 if (strncmp("PMAG-RO ", ta->ta_modname, TC_ROM_LLEN) != 0 275 && strncmp("PMAG-JA ", ta->ta_modname, TC_ROM_LLEN) != 0) 276 return (0); 277 278 return (1); 279 } 280 281 282 static void 283 tfbattach(struct device *parent, struct device *self, void *aux) 284 { 285 struct tfb_softc *sc = device_private(self); 286 struct tc_attach_args *ta = aux; 287 struct rasops_info *ri; 288 struct wsemuldisplaydev_attach_args waa; 289 int console; 290 291 console = (ta->ta_addr == tfb_consaddr); 292 if (console) { 293 sc->sc_ri = ri = &tfb_console_ri; 294 sc->nscreens = 1; 295 } 296 else { 297 MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info), 298 M_DEVBUF, M_NOWAIT); 299 if (ri == NULL) { 300 printf(": can't alloc memory\n"); 301 return; 302 } 303 memset(ri, 0, sizeof(struct rasops_info)); 304 305 ri->ri_hw = (void *)ta->ta_addr; 306 tfb_common_init(ri); 307 sc->sc_ri = ri; 308 } 309 printf(": %dx%d, 8,24bpp\n", ri->ri_width, ri->ri_height); 310 311 tfb_cmap_init(sc); 312 313 sc->sc_vaddr = ta->ta_addr; 314 sc->sc_cursor.cc_magic.x = TX_MAGIC_X; 315 sc->sc_cursor.cc_magic.y = TX_MAGIC_Y; 316 sc->sc_blanked = sc->sc_curenb = 0; 317 318 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, tfbintr, sc); 319 320 *(u_int8_t *)((caddr_t)ri->ri_hw + TX_CONTROL) &= ~0x40; 321 *(u_int8_t *)((caddr_t)ri->ri_hw + TX_CONTROL) |= 0x40; 322 323 waa.console = console; 324 waa.scrdata = &tfb_screenlist; 325 waa.accessops = &tfb_accessops; 326 waa.accesscookie = sc; 327 328 config_found(self, &waa, wsemuldisplaydevprint); 329 } 330 331 static void 332 tfb_common_init(struct rasops_info *ri) 333 { 334 caddr_t base; 335 int cookie; 336 337 base = (caddr_t)ri->ri_hw; 338 339 /* initialize colormap and cursor hardware */ 340 tfbhwinit(base); 341 342 ri->ri_flg = RI_CENTER; 343 ri->ri_depth = 8; 344 ri->ri_width = 1280; 345 ri->ri_height = 1024; 346 ri->ri_stride = 1280; 347 ri->ri_bits = base + TX_8BPP_OFFSET; 348 349 /* clear the screen */ 350 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 351 352 wsfont_init(); 353 /* prefer 12 pixel wide font */ 354 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R, 355 WSDISPLAY_FONTORDER_L2R); 356 if (cookie <= 0) 357 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R, 358 WSDISPLAY_FONTORDER_L2R); 359 if (cookie <= 0) { 360 printf("tfb: font table is empty\n"); 361 return; 362 } 363 364 if (wsfont_lock(cookie, &ri->ri_font)) { 365 printf("tfb: couldn't lock font\n"); 366 return; 367 } 368 ri->ri_wsfcookie = cookie; 369 370 rasops_init(ri, 34, 80); 371 372 /* XXX shouldn't be global */ 373 tfb_stdscreen.nrows = ri->ri_rows; 374 tfb_stdscreen.ncols = ri->ri_cols; 375 tfb_stdscreen.textops = &ri->ri_ops; 376 tfb_stdscreen.capabilities = ri->ri_caps; 377 } 378 379 static void 380 tfb_cmap_init(struct tfb_softc *sc) 381 { 382 struct hwcmap256 *cm; 383 const u_int8_t *p; 384 int index; 385 386 cm = &sc->sc_cmap; 387 p = rasops_cmap; 388 for (index = 0; index < CMAP_SIZE; index++, p += 3) { 389 cm->r[index] = p[0]; 390 cm->g[index] = p[1]; 391 cm->b[index] = p[2]; 392 } 393 } 394 395 static int 396 tfbioctl(void *v, void *vs, u_long cmd, caddr_t data, int flag, struct lwp *l) 397 { 398 struct tfb_softc *sc = v; 399 struct rasops_info *ri = sc->sc_ri; 400 int turnoff, s; 401 402 switch (cmd) { 403 case WSDISPLAYIO_GTYPE: 404 *(u_int *)data = WSDISPLAY_TYPE_TX; 405 return (0); 406 407 case WSDISPLAYIO_GINFO: 408 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 409 wsd_fbip->height = ri->ri_height; 410 wsd_fbip->width = ri->ri_width; 411 wsd_fbip->depth = ri->ri_depth; 412 wsd_fbip->cmsize = CMAP_SIZE; 413 #undef fbt 414 return (0); 415 416 case WSDISPLAYIO_GETCMAP: 417 return get_cmap(sc, (struct wsdisplay_cmap *)data); 418 419 case WSDISPLAYIO_PUTCMAP: 420 return set_cmap(sc, (struct wsdisplay_cmap *)data); 421 422 case WSDISPLAYIO_SVIDEO: 423 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 424 if (sc->sc_blanked != turnoff) { 425 sc->sc_blanked = turnoff; 426 #if 0 /* XXX later XXX */ 427 To turn off; 428 - clear the MSB of TX control register; &= ~0x80, 429 - assign Bt431 register #0 with value 0x4 to hide sprite cursor. 430 #endif /* XXX XXX XXX */ 431 } 432 return (0); 433 434 case WSDISPLAYIO_GVIDEO: 435 *(u_int *)data = sc->sc_blanked ? 436 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 437 return (0); 438 439 case WSDISPLAYIO_GCURPOS: 440 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 441 return (0); 442 443 case WSDISPLAYIO_SCURPOS: 444 s = spltty(); 445 set_curpos(sc, (struct wsdisplay_curpos *)data); 446 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 447 splx(s); 448 return (0); 449 450 case WSDISPLAYIO_GCURMAX: 451 ((struct wsdisplay_curpos *)data)->x = 452 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 453 return (0); 454 455 case WSDISPLAYIO_GCURSOR: 456 return get_cursor(sc, (struct wsdisplay_cursor *)data); 457 458 case WSDISPLAYIO_SCURSOR: 459 return set_cursor(sc, (struct wsdisplay_cursor *)data); 460 461 case WSDISPLAYIO_SMODE: 462 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { 463 s = spltty(); 464 tfb_cmap_init(sc); 465 sc->sc_curenb = 0; 466 sc->sc_blanked = 0; 467 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR | 468 WSDISPLAY_CMAP_DOLUT); 469 splx(s); 470 } 471 return (0); 472 } 473 return (EPASSTHROUGH); 474 } 475 476 static paddr_t 477 tfbmmap(void *v, void *vs, off_t offset, int prot) 478 { 479 struct tfb_softc *sc = v; 480 481 if (offset >= TX_8BPP_SIZE || offset < 0) /* XXX 24bpp XXX */ 482 return (-1); 483 return machine_btop(sc->sc_vaddr + TX_8BPP_OFFSET + offset); 484 } 485 486 static int 487 tfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 488 int *curxp, int *curyp, long *attrp) 489 { 490 struct tfb_softc *sc = v; 491 struct rasops_info *ri = sc->sc_ri; 492 long defattr; 493 494 if (sc->nscreens > 0) 495 return (ENOMEM); 496 497 *cookiep = ri; /* one and only for now */ 498 *curxp = 0; 499 *curyp = 0; 500 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 501 *attrp = defattr; 502 sc->nscreens++; 503 return (0); 504 } 505 506 static void 507 tfb_free_screen(void *v, void *cookie) 508 { 509 struct tfb_softc *sc = v; 510 511 if (sc->sc_ri == &tfb_console_ri) 512 panic("tfb_free_screen: console"); 513 514 sc->nscreens--; 515 } 516 517 static int 518 tfb_show_screen(void *v, void *cookie, int waitok, 519 void (*cb)(void *, int, int), void *cbarg) 520 { 521 522 return (0); 523 } 524 525 /* EXPORT */ int 526 tfb_cnattach(tc_addr_t addr) 527 { 528 struct rasops_info *ri; 529 long defattr; 530 531 ri = &tfb_console_ri; 532 ri->ri_hw = (void *)addr; 533 tfb_common_init(ri); 534 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 535 wsdisplay_cnattach(&tfb_stdscreen, ri, 0, 0, defattr); 536 tfb_consaddr = addr; 537 return (0); 538 } 539 540 static int 541 tfbintr(void *arg) 542 { 543 struct tfb_softc *sc = arg; 544 caddr_t base, vdac, curs; 545 int v; 546 547 base = (caddr_t)sc->sc_ri->ri_hw; 548 *(u_int8_t *)(base + TX_CONTROL) &= ~0x40; 549 if (sc->sc_changed == 0) 550 goto done; 551 552 vdac = base + TX_BT463_OFFSET; 553 curs = base + TX_BT431_OFFSET; 554 v = sc->sc_changed; 555 if (v & WSDISPLAY_CURSOR_DOCUR) { 556 int onoff; 557 558 onoff = (sc->sc_curenb) ? 0x4444 : 0x0404; 559 SELECT431(curs, BT431_REG_COMMAND); 560 REGWRITE32(curs, bt_ctl, onoff); 561 } 562 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 563 int x, y; 564 u_int32_t twin; 565 566 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 567 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 568 569 x += sc->sc_cursor.cc_magic.x; 570 y += sc->sc_cursor.cc_magic.y; 571 572 SELECT431(curs, BT431_REG_CURSOR_X_LOW); 573 REGWRITE32(curs, bt_ctl, TWIN_LO(x)); 574 REGWRITE32(curs, bt_ctl, TWIN_HI(x)); 575 REGWRITE32(curs, bt_ctl, TWIN_LO(y)); 576 REGWRITE32(curs, bt_ctl, TWIN_HI(y)); 577 } 578 if (v & WSDISPLAY_CURSOR_DOCMAP) { 579 u_int8_t *cp = sc->sc_cursor.cc_color; 580 581 SELECT463(vdac, BT463_IREG_CURSOR_COLOR_0); 582 REGWRITE32(vdac, bt_reg, cp[1]); 583 REGWRITE32(vdac, bt_reg, cp[3]); 584 REGWRITE32(vdac, bt_reg, cp[5]); 585 586 REGWRITE32(vdac, bt_reg, cp[0]); 587 REGWRITE32(vdac, bt_reg, cp[2]); 588 REGWRITE32(vdac, bt_reg, cp[4]); 589 590 REGWRITE32(vdac, bt_reg, cp[1]); 591 REGWRITE32(vdac, bt_reg, cp[3]); 592 REGWRITE32(vdac, bt_reg, cp[5]); 593 594 REGWRITE32(vdac, bt_reg, cp[1]); 595 REGWRITE32(vdac, bt_reg, cp[3]); 596 REGWRITE32(vdac, bt_reg, cp[5]); 597 } 598 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 599 u_int8_t *ip, *mp, img, msk; 600 int bcnt; 601 602 ip = (u_int8_t *)sc->sc_cursor.cc_image; 603 mp = (u_int8_t *)sc->sc_cursor.cc_mask; 604 bcnt = 0; 605 SELECT431(curs, BT431_REG_CRAM_BASE); 606 607 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 608 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 609 /* pad right half 32 pixel when smaller than 33 */ 610 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 611 REGWRITE32(curs, bt_ram, 0); 612 } 613 else { 614 int half; 615 img = *ip++; 616 msk = *mp++; 617 img &= msk; /* cookie off image */ 618 half = (flip[img] << 8) | flip[msk]; 619 REGWRITE32(curs, bt_ram, half); 620 } 621 bcnt += 2; 622 } 623 /* pad unoccupied scan lines */ 624 while (bcnt < CURSOR_MAX_SIZE * 16) { 625 REGWRITE32(curs, bt_ram, 0); 626 bcnt += 2; 627 } 628 } 629 if (v & WSDISPLAY_CMAP_DOLUT) { 630 struct hwcmap256 *cm = &sc->sc_cmap; 631 int index; 632 633 SELECT463(vdac, BT463_IREG_CPALETTE_RAM); 634 for (index = 0; index < CMAP_SIZE; index++) { 635 REGWRITE32(vdac, bt_cmap, cm->r[index]); 636 REGWRITE32(vdac, bt_cmap, cm->g[index]); 637 REGWRITE32(vdac, bt_cmap, cm->b[index]); 638 } 639 } 640 sc->sc_changed = 0; 641 done: 642 *(u_int8_t *)(base + TX_CONTROL) &= ~0x40; /* !? Eeeh !? */ 643 *(u_int8_t *)(base + TX_CONTROL) |= 0x40; 644 return (1); 645 } 646 647 static void 648 tfbhwinit(caddr_t tfbbase) 649 { 650 caddr_t vdac, curs; 651 const u_int8_t *p; 652 int i; 653 654 vdac = tfbbase + TX_BT463_OFFSET; 655 curs = tfbbase + TX_BT431_OFFSET; 656 SELECT463(vdac, BT463_IREG_COMMAND_0); 657 REGWRITE32(vdac, bt_reg, 0x40); /* CMD 0 */ 658 REGWRITE32(vdac, bt_reg, 0x46); /* CMD 1 */ 659 REGWRITE32(vdac, bt_reg, 0xc0); /* CMD 2 */ 660 REGWRITE32(vdac, bt_reg, 0); /* !? 204 !? */ 661 REGWRITE32(vdac, bt_reg, 0xff); /* plane 0:7 */ 662 REGWRITE32(vdac, bt_reg, 0xff); /* plane 8:15 */ 663 REGWRITE32(vdac, bt_reg, 0xff); /* plane 16:23 */ 664 REGWRITE32(vdac, bt_reg, 0xff); /* plane 24:27 */ 665 REGWRITE32(vdac, bt_reg, 0x00); /* blink 0:7 */ 666 REGWRITE32(vdac, bt_reg, 0x00); /* blink 8:15 */ 667 REGWRITE32(vdac, bt_reg, 0x00); /* blink 16:23 */ 668 REGWRITE32(vdac, bt_reg, 0x00); /* blink 24:27 */ 669 REGWRITE32(vdac, bt_reg, 0x00); 670 671 #if 0 /* XXX ULTRIX does initialize 16 entry window type here XXX */ 672 { 673 static u_int32_t windowtype[BT463_IREG_WINDOW_TYPE_TABLE] = { 674 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 675 }; 676 677 SELECT463(vdac, BT463_IREG_WINDOW_TYPE_TABLE); 678 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) { 679 BYTE(vdac, bt_reg) = windowtype[i]; /* 0:7 */ 680 BYTE(vdac, bt_reg) = windowtype[i] >> 8; /* 8:15 */ 681 BYTE(vdac, bt_reg) = windowtype[i] >> 16; /* 16:23 */ 682 } 683 } 684 #endif 685 686 SELECT463(vdac, BT463_IREG_CPALETTE_RAM); 687 p = rasops_cmap; 688 for (i = 0; i < 256; i++, p += 3) { 689 REGWRITE32(vdac, bt_cmap, p[0]); 690 REGWRITE32(vdac, bt_cmap, p[1]); 691 REGWRITE32(vdac, bt_cmap, p[2]); 692 } 693 694 /* !? Eeeh !? */ 695 SELECT463(vdac, 0x0100 /* BT463_IREG_CURSOR_COLOR_0 */); 696 for (i = 0; i < 256; i++) { 697 REGWRITE32(vdac, bt_cmap, i); 698 REGWRITE32(vdac, bt_cmap, i); 699 REGWRITE32(vdac, bt_cmap, i); 700 } 701 702 SELECT431(curs, BT431_REG_COMMAND); 703 REGWRITE32(curs, bt_ctl, 0x0404); 704 REGWRITE32(curs, bt_ctl, 0); /* XLO */ 705 REGWRITE32(curs, bt_ctl, 0); /* XHI */ 706 REGWRITE32(curs, bt_ctl, 0); /* YLO */ 707 REGWRITE32(curs, bt_ctl, 0); /* YHI */ 708 REGWRITE32(curs, bt_ctl, 0); /* XWLO */ 709 REGWRITE32(curs, bt_ctl, 0); /* XWHI */ 710 REGWRITE32(curs, bt_ctl, 0); /* WYLO */ 711 REGWRITE32(curs, bt_ctl, 0); /* WYLO */ 712 REGWRITE32(curs, bt_ctl, 0); /* WWLO */ 713 REGWRITE32(curs, bt_ctl, 0); /* WWHI */ 714 REGWRITE32(curs, bt_ctl, 0); /* WHLO */ 715 REGWRITE32(curs, bt_ctl, 0); /* WHHI */ 716 717 SELECT431(curs, BT431_REG_CRAM_BASE); 718 for (i = 0; i < 512; i++) { 719 REGWRITE32(curs, bt_ram, 0); 720 } 721 } 722 723 static int 724 get_cmap(struct tfb_softc *sc, struct wsdisplay_cmap *p) 725 { 726 u_int index = p->index, count = p->count; 727 int error; 728 729 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 730 return (EINVAL); 731 732 error = copyout(&sc->sc_cmap.r[index], p->red, count); 733 if (error) 734 return error; 735 error = copyout(&sc->sc_cmap.g[index], p->green, count); 736 if (error) 737 return error; 738 error = copyout(&sc->sc_cmap.b[index], p->blue, count); 739 return error; 740 } 741 742 static int 743 set_cmap(struct tfb_softc *sc, struct wsdisplay_cmap *p) 744 { 745 struct hwcmap256 cmap; 746 u_int index = p->index, count = p->count; 747 int error, s; 748 749 if (index >= CMAP_SIZE || count > CMAP_SIZE - index) 750 return (EINVAL); 751 752 error = copyin(p->red, &cmap.r[index], count); 753 if (error) 754 return error; 755 error = copyin(p->green, &cmap.g[index], count); 756 if (error) 757 return error; 758 error = copyin(p->blue, &cmap.b[index], count); 759 if (error) 760 return error; 761 s = spltty(); 762 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count); 763 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count); 764 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count); 765 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 766 splx(s); 767 return (0); 768 } 769 770 static int 771 set_cursor(struct tfb_softc *sc, struct wsdisplay_cursor *p) 772 { 773 #define cc (&sc->sc_cursor) 774 u_int v, index = 0, count = 0, icount = 0; 775 uint8_t r[2], g[2], b[2], image[512], mask[512]; 776 int error, s; 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 error = copyin(p->cmap.red, &r[index], count); 785 if (error) 786 return error; 787 error = copyin(p->cmap.green, &g[index], count); 788 if (error) 789 return error; 790 error = copyin(p->cmap.blue, &b[index], count); 791 if (error) 792 return error; 793 } 794 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 795 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 796 return (EINVAL); 797 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 798 error = copyin(p->image, image, icount); 799 if (error) 800 return error; 801 error = copyin(p->mask, mask, icount); 802 if (error) 803 return error; 804 } 805 806 s = spltty(); 807 if (v & WSDISPLAY_CURSOR_DOCUR) 808 sc->sc_curenb = p->enable; 809 if (v & WSDISPLAY_CURSOR_DOPOS) 810 set_curpos(sc, &p->pos); 811 if (v & WSDISPLAY_CURSOR_DOHOT) 812 cc->cc_hot = p->hot; 813 if (v & WSDISPLAY_CURSOR_DOCMAP) { 814 memcpy(&cc->cc_color[index], &r[index], count); 815 memcpy(&cc->cc_color[index + 2], &g[index], count); 816 memcpy(&cc->cc_color[index + 4], &b[index], count); 817 } 818 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 819 cc->cc_size = p->size; 820 memset(cc->cc_image, 0, sizeof cc->cc_image); 821 memcpy(cc->cc_image, image, icount); 822 memset(cc->cc_mask, 0, sizeof cc->cc_mask); 823 memcpy(cc->cc_mask, mask, icount); 824 } 825 sc->sc_changed |= v; 826 splx(s); 827 828 return (0); 829 #undef cc 830 } 831 832 static int 833 get_cursor(struct tfb_softc *sc, struct wsdisplay_cursor *p) 834 { 835 return (EPASSTHROUGH); /* XXX */ 836 } 837 838 static void 839 set_curpos(struct tfb_softc *sc, struct wsdisplay_curpos *curpos) 840 { 841 struct rasops_info *ri = sc->sc_ri; 842 int x = curpos->x, y = curpos->y; 843 844 if (y < 0) 845 y = 0; 846 else if (y > ri->ri_height) 847 y = ri->ri_height; 848 if (x < 0) 849 x = 0; 850 else if (x > ri->ri_width) 851 x = ri->ri_width; 852 sc->sc_cursor.cc_pos.x = x; 853 sc->sc_cursor.cc_pos.y = y; 854 } 855