1 /* $NetBSD: mfb.c,v 1.56 2010/05/15 08:53:27 tsutsui 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: mfb.c,v 1.56 2010/05/15 08:53:27 tsutsui 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/bt431reg.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #if defined(pmax) 58 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x)) 59 #endif 60 61 #if defined(alpha) 62 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x)) 63 #endif 64 65 /* Bt455 hardware registers, memory-mapped in 32bit stride */ 66 #define bt_reg 0x0 67 #define bt_cmap 0x4 68 #define bt_clr 0x8 69 #define bt_ovly 0xc 70 71 /* Bt431 hardware registers, memory-mapped in 32bit stride */ 72 #define bt_lo 0x0 73 #define bt_hi 0x4 74 #define bt_ram 0x8 75 #define bt_ctl 0xc 76 77 #define REGWRITE32(p,i,v) do { \ 78 *(volatile uint32_t *)((p) + (i)) = (v); tc_wmb(); \ 79 } while (0) 80 81 #define SELECT455(p,r) do { \ 82 REGWRITE32((p), bt_reg, (r)); \ 83 REGWRITE32((p), bt_clr, 0); \ 84 } while (0) 85 86 #define TWIN(x) ((x)|((x) << 8)) 87 #define TWIN_LO(x) (twin = (x) & 0x00ff, twin << 8 | twin) 88 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | twin >> 8) 89 90 #define SELECT431(p,r) do { \ 91 REGWRITE32((p), bt_lo, TWIN(r)); \ 92 REGWRITE32((p), bt_hi, 0); \ 93 } while (0) 94 95 struct hwcursor64 { 96 struct wsdisplay_curpos cc_pos; 97 struct wsdisplay_curpos cc_hot; 98 struct wsdisplay_curpos cc_size; 99 struct wsdisplay_curpos cc_magic; 100 #define CURSOR_MAX_SIZE 64 101 uint8_t cc_color[6]; 102 uint64_t cc_image[CURSOR_MAX_SIZE]; 103 uint64_t cc_mask[CURSOR_MAX_SIZE]; 104 }; 105 106 struct mfb_softc { 107 vaddr_t sc_vaddr; 108 size_t sc_size; 109 struct rasops_info *sc_ri; 110 struct hwcursor64 sc_cursor; /* software copy of cursor */ 111 int sc_blanked; 112 int sc_curenb; /* cursor sprite enabled */ 113 int sc_changed; /* need update of hardware */ 114 int nscreens; 115 }; 116 117 #define MX_MAGIC_X 360 118 #define MX_MAGIC_Y 36 119 120 #define MX_FB_OFFSET 0x200000 121 #define MX_FB_SIZE 0x200000 122 #define MX_BT455_OFFSET 0x100000 123 #define MX_BT431_OFFSET 0x180000 124 #define MX_IREQ_OFFSET 0x080000 /* Interrupt req. control */ 125 126 static int mfbmatch(device_t, cfdata_t, void *); 127 static void mfbattach(device_t, device_t, void *); 128 129 CFATTACH_DECL_NEW(mfb, sizeof(struct mfb_softc), 130 mfbmatch, mfbattach, NULL, NULL); 131 132 static void mfb_common_init(struct rasops_info *); 133 static struct rasops_info mfb_console_ri; 134 static tc_addr_t mfb_consaddr; 135 136 static struct wsscreen_descr mfb_stdscreen = { 137 "std", 0, 0, 138 0, /* textops */ 139 0, 0, 140 WSSCREEN_REVERSE 141 }; 142 143 static const struct wsscreen_descr *_mfb_scrlist[] = { 144 &mfb_stdscreen, 145 }; 146 147 static const struct wsscreen_list mfb_screenlist = { 148 sizeof(_mfb_scrlist) / sizeof(struct wsscreen_descr *), _mfb_scrlist 149 }; 150 151 static int mfbioctl(void *, void *, u_long, void *, int, struct lwp *); 152 static paddr_t mfbmmap(void *, void *, off_t, int); 153 154 static int mfb_alloc_screen(void *, const struct wsscreen_descr *, 155 void **, int *, int *, long *); 156 static void mfb_free_screen(void *, void *); 157 static int mfb_show_screen(void *, void *, int, 158 void (*) (void *, int, int), void *); 159 160 static const struct wsdisplay_accessops mfb_accessops = { 161 mfbioctl, 162 mfbmmap, 163 mfb_alloc_screen, 164 mfb_free_screen, 165 mfb_show_screen, 166 0 /* load_font */ 167 }; 168 169 int mfb_cnattach(tc_addr_t); 170 static int mfbintr(void *); 171 static void mfbhwinit(void *); 172 173 static int set_cursor(struct mfb_softc *, struct wsdisplay_cursor *); 174 static int get_cursor(struct mfb_softc *, struct wsdisplay_cursor *); 175 static void set_curpos(struct mfb_softc *, struct wsdisplay_curpos *); 176 177 /* bit order reverse */ 178 static const uint8_t flip[256] = { 179 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 180 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 181 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 182 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 183 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 184 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 185 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 186 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 187 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 188 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 189 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 190 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 191 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 192 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 193 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 194 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 195 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 196 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 197 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 198 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 199 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 200 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 201 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 202 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 203 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 204 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 205 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 206 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 207 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 208 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 209 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 210 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 211 }; 212 213 static int 214 mfbmatch(device_t parent, cfdata_t match, void *aux) 215 { 216 struct tc_attach_args *ta = aux; 217 218 if (strncmp("PMAG-AA ", ta->ta_modname, TC_ROM_LLEN) != 0) 219 return (0); 220 221 return (1); 222 } 223 224 static void 225 mfbattach(device_t parent, device_t self, void *aux) 226 { 227 struct mfb_softc *sc = device_private(self); 228 struct tc_attach_args *ta = aux; 229 struct rasops_info *ri; 230 struct wsemuldisplaydev_attach_args waa; 231 int console; 232 volatile register int junk; 233 234 console = (ta->ta_addr == mfb_consaddr); 235 if (console) { 236 sc->sc_ri = ri = &mfb_console_ri; 237 ri->ri_flg &= ~RI_NO_AUTO; 238 sc->nscreens = 1; 239 } 240 else { 241 ri = malloc(sizeof(struct rasops_info), 242 M_DEVBUF, M_NOWAIT); 243 if (ri == NULL) { 244 printf(": can't alloc memory\n"); 245 return; 246 } 247 memset(ri, 0, sizeof(struct rasops_info)); 248 249 ri->ri_hw = (void *)ta->ta_addr; 250 mfb_common_init(ri); 251 sc->sc_ri = ri; 252 } 253 printf(": %dx%d, 1bpp\n", ri->ri_width, ri->ri_height); 254 255 sc->sc_vaddr = ta->ta_addr; 256 sc->sc_cursor.cc_magic.x = MX_MAGIC_X; 257 sc->sc_cursor.cc_magic.y = MX_MAGIC_Y; 258 sc->sc_blanked = sc->sc_curenb = 0; 259 260 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, mfbintr, sc); 261 262 /* clear any pending interrupts */ 263 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 0; 264 junk = *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET); 265 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 1; 266 267 waa.console = console; 268 waa.scrdata = &mfb_screenlist; 269 waa.accessops = &mfb_accessops; 270 waa.accesscookie = sc; 271 272 config_found(self, &waa, wsemuldisplaydevprint); 273 } 274 275 static void 276 mfb_common_init(struct rasops_info *ri) 277 { 278 char *base; 279 int cookie; 280 281 base = (void *)ri->ri_hw; 282 283 /* initialize colormap and cursor hardware */ 284 mfbhwinit(base); 285 286 ri->ri_flg = RI_CENTER | RI_FORCEMONO; 287 if (ri == &mfb_console_ri) 288 ri->ri_flg |= RI_NO_AUTO; 289 ri->ri_depth = 8; /* !! watch out !! */ 290 ri->ri_width = 1280; 291 ri->ri_height = 1024; 292 ri->ri_stride = 2048; 293 ri->ri_bits = base + MX_FB_OFFSET; 294 295 /* clear the screen */ 296 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 297 298 wsfont_init(); 299 /* prefer 12 pixel wide font */ 300 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R, 301 WSDISPLAY_FONTORDER_L2R); 302 if (cookie <= 0) 303 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R, 304 WSDISPLAY_FONTORDER_L2R); 305 if (cookie <= 0) { 306 printf("mfb: font table is empty\n"); 307 return; 308 } 309 310 if (wsfont_lock(cookie, &ri->ri_font)) { 311 printf("mfb: couldn't lock font\n"); 312 return; 313 } 314 ri->ri_wsfcookie = cookie; 315 316 rasops_init(ri, 34, 80); 317 318 /* XXX shouldn't be global */ 319 mfb_stdscreen.nrows = ri->ri_rows; 320 mfb_stdscreen.ncols = ri->ri_cols; 321 mfb_stdscreen.textops = &ri->ri_ops; 322 mfb_stdscreen.capabilities = ri->ri_caps; 323 } 324 325 static int 326 mfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 327 { 328 struct mfb_softc *sc = v; 329 struct rasops_info *ri = sc->sc_ri; 330 int turnoff, s; 331 332 switch (cmd) { 333 case WSDISPLAYIO_GTYPE: 334 *(u_int *)data = WSDISPLAY_TYPE_MFB; 335 return (0); 336 337 case WSDISPLAYIO_GINFO: 338 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 339 wsd_fbip->height = ri->ri_height; 340 wsd_fbip->width = ri->ri_width; 341 wsd_fbip->depth = ri->ri_depth; 342 wsd_fbip->cmsize = 0; 343 #undef fbt 344 return (0); 345 346 case WSDISPLAYIO_GETCMAP: 347 case WSDISPLAYIO_PUTCMAP: 348 return (EPASSTHROUGH); 349 350 case WSDISPLAYIO_SVIDEO: 351 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 352 if (sc->sc_blanked != turnoff) { 353 sc->sc_blanked = turnoff; 354 #if 0 /* XXX later XXX */ 355 To turn off, 356 - assign Bt455 cmap[1].green with value 0 (black), 357 - assign Bt431 register #0 with value 0x04 to hide sprite cursor. 358 #endif /* XXX XXX XXX */ 359 } 360 return (0); 361 362 case WSDISPLAYIO_GVIDEO: 363 *(u_int *)data = sc->sc_blanked ? 364 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 365 return (0); 366 367 case WSDISPLAYIO_GCURPOS: 368 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 369 return (0); 370 371 case WSDISPLAYIO_SCURPOS: 372 s = spltty(); 373 set_curpos(sc, (struct wsdisplay_curpos *)data); 374 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 375 splx(s); 376 return (0); 377 378 case WSDISPLAYIO_GCURMAX: 379 ((struct wsdisplay_curpos *)data)->x = 380 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 381 return (0); 382 383 case WSDISPLAYIO_GCURSOR: 384 return get_cursor(sc, (struct wsdisplay_cursor *)data); 385 386 case WSDISPLAYIO_SCURSOR: 387 return set_cursor(sc, (struct wsdisplay_cursor *)data); 388 389 case WSDISPLAYIO_SMODE: 390 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) { 391 s = spltty(); 392 sc->sc_curenb = 0; 393 sc->sc_blanked = 0; 394 sc->sc_changed |= WSDISPLAY_CURSOR_DOCUR; 395 splx(s); 396 } 397 return (0); 398 } 399 return (EPASSTHROUGH); 400 } 401 402 static paddr_t 403 mfbmmap(void *v, void *vs, off_t offset, int prot) 404 { 405 struct mfb_softc *sc = v; 406 407 if (offset >= MX_FB_SIZE || offset < 0) 408 return (-1); 409 return machine_btop(sc->sc_vaddr + MX_FB_OFFSET + offset); 410 } 411 412 static int 413 mfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 414 int *curxp, int *curyp, long *attrp) 415 { 416 struct mfb_softc *sc = v; 417 struct rasops_info *ri = sc->sc_ri; 418 long defattr; 419 420 if (sc->nscreens > 0) 421 return (ENOMEM); 422 423 *cookiep = ri; /* one and only for now */ 424 *curxp = 0; 425 *curyp = 0; 426 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 427 *attrp = defattr; 428 sc->nscreens++; 429 return (0); 430 } 431 432 static void 433 mfb_free_screen(void *v, void *cookie) 434 { 435 struct mfb_softc *sc = v; 436 437 if (sc->sc_ri == &mfb_console_ri) 438 panic("mfb_free_screen: console"); 439 440 sc->nscreens--; 441 } 442 443 static int 444 mfb_show_screen(void *v, void *cookie, int waitok, 445 void (*cb)(void *, int, int), void *cbarg) 446 { 447 448 return (0); 449 } 450 451 /* EXPORT */ int 452 mfb_cnattach(tc_addr_t addr) 453 { 454 struct rasops_info *ri; 455 long defattr; 456 457 ri = &mfb_console_ri; 458 ri->ri_hw = (void *)addr; 459 mfb_common_init(ri); 460 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 461 wsdisplay_cnattach(&mfb_stdscreen, ri, 0, 0, defattr); 462 mfb_consaddr = addr; 463 return (0); 464 } 465 466 static int 467 mfbintr(void *arg) 468 { 469 struct mfb_softc *sc = arg; 470 char *base, *vdac, *curs; 471 int v; 472 volatile register int junk; 473 474 base = (void *)sc->sc_ri->ri_hw; 475 junk = *(uint8_t *)(base + MX_IREQ_OFFSET); 476 #if 0 477 *(uint8_t *)(base + MX_IREQ_OFFSET) = 0; 478 #endif 479 if (sc->sc_changed == 0) 480 return (1); 481 482 vdac = base + MX_BT455_OFFSET; 483 curs = base + MX_BT431_OFFSET; 484 v = sc->sc_changed; 485 if (v & WSDISPLAY_CURSOR_DOCUR) { 486 int onoff; 487 488 onoff = (sc->sc_curenb) ? 0x4444 : 0x0404; 489 SELECT431(curs, BT431_REG_COMMAND); 490 REGWRITE32(curs, bt_ctl, onoff); 491 } 492 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 493 int x, y; 494 uint32_t twin; 495 496 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 497 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 498 499 x += sc->sc_cursor.cc_magic.x; 500 y += sc->sc_cursor.cc_magic.y; 501 502 SELECT431(curs, BT431_REG_CURSOR_X_LOW); 503 REGWRITE32(curs, bt_ctl, TWIN_LO(x)); 504 REGWRITE32(curs, bt_ctl, TWIN_HI(x)); 505 REGWRITE32(curs, bt_ctl, TWIN_LO(y)); 506 REGWRITE32(curs, bt_ctl, TWIN_HI(y)); 507 } 508 if (v & WSDISPLAY_CURSOR_DOCMAP) { 509 uint8_t *cp = sc->sc_cursor.cc_color; 510 511 SELECT455(vdac, 8); 512 REGWRITE32(vdac, bt_cmap, 0); 513 REGWRITE32(vdac, bt_cmap, cp[1]); 514 REGWRITE32(vdac, bt_cmap, 0); 515 516 REGWRITE32(vdac, bt_cmap, 0); 517 REGWRITE32(vdac, bt_cmap, cp[1]); 518 REGWRITE32(vdac, bt_cmap, 0); 519 520 REGWRITE32(vdac, bt_ovly, 0); 521 REGWRITE32(vdac, bt_ovly, cp[0]); 522 REGWRITE32(vdac, bt_ovly, 0); 523 } 524 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 525 uint8_t *ip, *mp, img, msk; 526 int bcnt; 527 528 ip = (uint8_t *)sc->sc_cursor.cc_image; 529 mp = (uint8_t *)sc->sc_cursor.cc_mask; 530 bcnt = 0; 531 SELECT431(curs, BT431_REG_CRAM_BASE); 532 533 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 534 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 535 /* pad right half 32 pixel when smaller than 33 */ 536 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 537 REGWRITE32(curs, bt_ram, 0); 538 } 539 else { 540 int half; 541 542 img = *ip++; 543 msk = *mp++; 544 img &= msk; /* cookie off image */ 545 half = (flip[msk] << 8) | flip[img]; 546 REGWRITE32(curs, bt_ram, half); 547 } 548 bcnt += 2; 549 } 550 /* pad unoccupied scan lines */ 551 while (bcnt < CURSOR_MAX_SIZE * 16) { 552 REGWRITE32(curs, bt_ram, 0); 553 bcnt += 2; 554 } 555 } 556 sc->sc_changed = 0; 557 return (1); 558 } 559 560 static void 561 mfbhwinit(void *mfbbase) 562 { 563 char *vdac, *curs; 564 int i; 565 566 vdac = (char *)mfbbase + MX_BT455_OFFSET; 567 curs = (char *)mfbbase + MX_BT431_OFFSET; 568 SELECT431(curs, BT431_REG_COMMAND); 569 REGWRITE32(curs, bt_ctl, 0x0404); 570 REGWRITE32(curs, bt_ctl, 0); /* XLO */ 571 REGWRITE32(curs, bt_ctl, 0); /* XHI */ 572 REGWRITE32(curs, bt_ctl, 0); /* YLO */ 573 REGWRITE32(curs, bt_ctl, 0); /* YHI */ 574 REGWRITE32(curs, bt_ctl, 0); /* XWLO */ 575 REGWRITE32(curs, bt_ctl, 0); /* XWHI */ 576 REGWRITE32(curs, bt_ctl, 0); /* WYLO */ 577 REGWRITE32(curs, bt_ctl, 0); /* WYLO */ 578 REGWRITE32(curs, bt_ctl, 0); /* WWLO */ 579 REGWRITE32(curs, bt_ctl, 0); /* WWHI */ 580 REGWRITE32(curs, bt_ctl, 0); /* WHLO */ 581 REGWRITE32(curs, bt_ctl, 0); /* WHHI */ 582 583 /* 0: black, 1: white, 8,9: cursor mask, ovly: cursor image */ 584 SELECT455(vdac, 0); 585 REGWRITE32(vdac, bt_cmap, 0); 586 REGWRITE32(vdac, bt_cmap, 0); 587 REGWRITE32(vdac, bt_cmap, 0); 588 REGWRITE32(vdac, bt_cmap, 0); 589 REGWRITE32(vdac, bt_cmap, 0xff); 590 REGWRITE32(vdac, bt_cmap, 0); 591 for (i = 2; i < 16; i++) { 592 REGWRITE32(vdac, bt_cmap, 0); 593 REGWRITE32(vdac, bt_cmap, 0); 594 REGWRITE32(vdac, bt_cmap, 0); 595 } 596 REGWRITE32(vdac, bt_ovly, 0); 597 REGWRITE32(vdac, bt_ovly, 0xff); 598 REGWRITE32(vdac, bt_ovly, 0); 599 600 SELECT431(curs, BT431_REG_CRAM_BASE); 601 for (i = 0; i < 512; i++) { 602 REGWRITE32(curs, bt_ram, 0); 603 } 604 } 605 606 static int 607 set_cursor(struct mfb_softc *sc, struct wsdisplay_cursor *p) 608 { 609 #define cc (&sc->sc_cursor) 610 u_int v, count = 0, icount = 0, index = 0; 611 uint64_t image[CURSOR_MAX_SIZE]; 612 uint64_t mask[CURSOR_MAX_SIZE]; 613 uint8_t color[6]; 614 int error, s; 615 616 v = p->which; 617 if (v & WSDISPLAY_CURSOR_DOCMAP) { 618 index = p->cmap.index; 619 count = p->cmap.count; 620 if (index >= 2 || (index + count) > 2) 621 return (EINVAL); 622 error = copyin(p->cmap.red, &color[index], count); 623 if (error) 624 return error; 625 } 626 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 627 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 628 return (EINVAL); 629 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y; 630 error = copyin(p->image, image, icount); 631 if (error) 632 return error; 633 error = copyin(p->mask, mask, icount); 634 if (error) 635 return error; 636 } 637 638 s = spltty(); 639 if (v & WSDISPLAY_CURSOR_DOCUR) 640 sc->sc_curenb = p->enable; 641 if (v & WSDISPLAY_CURSOR_DOPOS) 642 set_curpos(sc, &p->pos); 643 if (v & WSDISPLAY_CURSOR_DOHOT) 644 cc->cc_hot = p->hot; 645 if (v & WSDISPLAY_CURSOR_DOCMAP) 646 memcpy(&cc->cc_color[index], &color[index], count); 647 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 648 cc->cc_size = p->size; 649 memset(cc->cc_image, 0, sizeof cc->cc_image); 650 memcpy(cc->cc_image, image, icount); 651 memset(cc->cc_mask, 0, sizeof cc->cc_mask); 652 memcpy(cc->cc_mask, mask, icount); 653 } 654 sc->sc_changed |= v; 655 splx(s); 656 657 return (0); 658 #undef cc 659 } 660 661 static int 662 get_cursor(struct mfb_softc *sc, struct wsdisplay_cursor *p) 663 { 664 return (EPASSTHROUGH); /* XXX */ 665 } 666 667 static void 668 set_curpos(struct mfb_softc *sc, struct wsdisplay_curpos *curpos) 669 { 670 struct rasops_info *ri = sc->sc_ri; 671 int x = curpos->x, y = curpos->y; 672 673 if (y < 0) 674 y = 0; 675 else if (y > ri->ri_height) 676 y = ri->ri_height; 677 if (x < 0) 678 x = 0; 679 else if (x > ri->ri_width) 680 x = ri->ri_width; 681 sc->sc_cursor.cc_pos.x = x; 682 sc->sc_cursor.cc_pos.y = y; 683 } 684