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