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