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