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