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