1 /* $NetBSD: mfb.c,v 1.59 2013/11/04 16:53:09 christos 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.59 2013/11/04 16:53:09 christos 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_NOWAIT); 241 if (ri == NULL) { 242 printf(": can't alloc memory\n"); 243 return; 244 } 245 memset(ri, 0, sizeof(struct rasops_info)); 246 247 ri->ri_hw = (void *)ta->ta_addr; 248 mfb_common_init(ri); 249 sc->sc_ri = ri; 250 } 251 printf(": %dx%d, 1bpp\n", ri->ri_width, ri->ri_height); 252 253 sc->sc_vaddr = ta->ta_addr; 254 sc->sc_cursor.cc_magic.x = MX_MAGIC_X; 255 sc->sc_cursor.cc_magic.y = MX_MAGIC_Y; 256 sc->sc_blanked = sc->sc_curenb = 0; 257 258 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, mfbintr, sc); 259 260 /* clear any pending interrupts */ 261 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 0; 262 junk = *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET); 263 __USE(junk); 264 *(uint8_t *)((char *)ri->ri_hw + MX_IREQ_OFFSET) = 1; 265 266 waa.console = console; 267 waa.scrdata = &mfb_screenlist; 268 waa.accessops = &mfb_accessops; 269 waa.accesscookie = sc; 270 271 config_found(self, &waa, wsemuldisplaydevprint); 272 } 273 274 static void 275 mfb_common_init(struct rasops_info *ri) 276 { 277 char *base; 278 int cookie; 279 280 base = (void *)ri->ri_hw; 281 282 /* initialize colormap and cursor hardware */ 283 mfbhwinit(base); 284 285 ri->ri_flg = RI_CENTER | RI_FORCEMONO; 286 if (ri == &mfb_console_ri) 287 ri->ri_flg |= RI_NO_AUTO; 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, WSFONT_FIND_BITMAP); 301 if (cookie <= 0) 302 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R, 303 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP); 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 = *(uint8_t *)(base + MX_IREQ_OFFSET); 475 __USE(junk); 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