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