1 /* $NetBSD: mfb.c,v 1.29 2001/11/13 06:26:10 lukem 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.29 2001/11/13 06:26:10 lukem 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; 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 if ((cookie = wsfont_find(NULL, 12, 0, 0)) <= 0) 310 cookie = wsfont_find(NULL, 0, 0, 0); 311 if (cookie <= 0) { 312 printf("mfb: font table is empty\n"); 313 return; 314 } 315 316 if (wsfont_lock(cookie, &ri->ri_font, 317 WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R) <= 0) { 318 printf("mfb: couldn't lock font\n"); 319 return; 320 } 321 ri->ri_wsfcookie = cookie; 322 323 rasops_init(ri, 34, 80); 324 325 /* XXX shouldn't be global */ 326 mfb_stdscreen.nrows = ri->ri_rows; 327 mfb_stdscreen.ncols = ri->ri_cols; 328 mfb_stdscreen.textops = &ri->ri_ops; 329 mfb_stdscreen.capabilities = ri->ri_caps; 330 } 331 332 static int 333 mfbioctl(v, cmd, data, flag, p) 334 void *v; 335 u_long cmd; 336 caddr_t data; 337 int flag; 338 struct proc *p; 339 { 340 struct mfb_softc *sc = v; 341 struct rasops_info *ri = sc->sc_ri; 342 int turnoff; 343 344 switch (cmd) { 345 case WSDISPLAYIO_GTYPE: 346 *(u_int *)data = WSDISPLAY_TYPE_MFB; 347 return (0); 348 349 case WSDISPLAYIO_GINFO: 350 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 351 wsd_fbip->height = ri->ri_height; 352 wsd_fbip->width = ri->ri_width; 353 wsd_fbip->depth = ri->ri_depth; 354 wsd_fbip->cmsize = 0; 355 #undef fbt 356 return (0); 357 358 case WSDISPLAYIO_GETCMAP: 359 case WSDISPLAYIO_PUTCMAP: 360 return (ENOTTY); 361 362 case WSDISPLAYIO_SVIDEO: 363 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF; 364 if ((sc->sc_blanked == 0) ^ turnoff) { 365 sc->sc_blanked = turnoff; 366 #if 0 /* XXX later XXX */ 367 To turn off, 368 - assign Bt455 cmap[1].green with value 0 (black), 369 - assign Bt431 register #0 with value 0x04 to hide sprite cursor. 370 #endif /* XXX XXX XXX */ 371 } 372 return (0); 373 374 case WSDISPLAYIO_GVIDEO: 375 *(u_int *)data = sc->sc_blanked ? 376 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 377 return (0); 378 379 case WSDISPLAYIO_GCURPOS: 380 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 381 return (0); 382 383 case WSDISPLAYIO_SCURPOS: 384 set_curpos(sc, (struct wsdisplay_curpos *)data); 385 sc->sc_changed = WSDISPLAY_CURSOR_DOPOS; 386 return (0); 387 388 case WSDISPLAYIO_GCURMAX: 389 ((struct wsdisplay_curpos *)data)->x = 390 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 391 return (0); 392 393 case WSDISPLAYIO_GCURSOR: 394 return get_cursor(sc, (struct wsdisplay_cursor *)data); 395 396 case WSDISPLAYIO_SCURSOR: 397 return set_cursor(sc, (struct wsdisplay_cursor *)data); 398 } 399 return (ENOTTY); 400 } 401 402 static paddr_t 403 mfbmmap(v, offset, prot) 404 void *v; 405 off_t offset; 406 int prot; 407 { 408 struct mfb_softc *sc = v; 409 410 if (offset >= MX_FB_SIZE || offset < 0) 411 return (-1); 412 return machine_btop(sc->sc_vaddr + MX_FB_OFFSET + offset); 413 } 414 415 static int 416 mfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 417 void *v; 418 const struct wsscreen_descr *type; 419 void **cookiep; 420 int *curxp, *curyp; 421 long *attrp; 422 { 423 struct mfb_softc *sc = v; 424 struct rasops_info *ri = sc->sc_ri; 425 long defattr; 426 427 if (sc->nscreens > 0) 428 return (ENOMEM); 429 430 *cookiep = ri; /* one and only for now */ 431 *curxp = 0; 432 *curyp = 0; 433 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 434 *attrp = defattr; 435 sc->nscreens++; 436 return (0); 437 } 438 439 static void 440 mfb_free_screen(v, cookie) 441 void *v; 442 void *cookie; 443 { 444 struct mfb_softc *sc = v; 445 446 if (sc->sc_ri == &mfb_console_ri) 447 panic("mfb_free_screen: console"); 448 449 sc->nscreens--; 450 } 451 452 static int 453 mfb_show_screen(v, cookie, waitok, cb, cbarg) 454 void *v; 455 void *cookie; 456 int waitok; 457 void (*cb) __P((void *, int, int)); 458 void *cbarg; 459 { 460 461 return (0); 462 } 463 464 /* EXPORT */ int 465 mfb_cnattach(addr) 466 tc_addr_t addr; 467 { 468 struct rasops_info *ri; 469 long defattr; 470 471 ri = &mfb_console_ri; 472 ri->ri_hw = (void *)addr; 473 mfb_common_init(ri); 474 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 475 wsdisplay_cnattach(&mfb_stdscreen, ri, 0, 0, defattr); 476 mfb_consaddr = addr; 477 return (0); 478 } 479 480 static int 481 mfbintr(arg) 482 void *arg; 483 { 484 struct mfb_softc *sc = arg; 485 caddr_t base, vdac, curs; 486 int v; 487 volatile register int junk; 488 489 base = (caddr_t)sc->sc_ri->ri_hw; 490 junk = *(u_int8_t *)(base + MX_IREQ_OFFSET); 491 #if 0 492 *(u_int8_t *)(base + MX_IREQ_OFFSET) = 0; 493 #endif 494 if (sc->sc_changed == 0) 495 goto done; 496 497 vdac = base + MX_BT455_OFFSET; 498 curs = base + MX_BT431_OFFSET; 499 v = sc->sc_changed; 500 if (v & WSDISPLAY_CURSOR_DOCUR) { 501 SELECT431(curs, BT431_REG_COMMAND); 502 HALF(curs, bt_ctl) = (sc->sc_curenb) ? 0x4444 : 0x0404; 503 } 504 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 505 int x, y; 506 u_int16_t twin; 507 508 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 509 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 510 511 x += sc->sc_cursor.cc_magic.x; 512 y += sc->sc_cursor.cc_magic.y; 513 514 SELECT431(curs, BT431_REG_CURSOR_X_LOW); 515 HALF(curs, bt_ctl) = TWIN_LO(x); tc_wmb(); 516 HALF(curs, bt_ctl) = TWIN_HI(x); tc_wmb(); 517 HALF(curs, bt_ctl) = TWIN_LO(y); tc_wmb(); 518 HALF(curs, bt_ctl) = TWIN_HI(y); tc_wmb(); 519 } 520 if (v & WSDISPLAY_CURSOR_DOCMAP) { 521 u_int8_t *cp = sc->sc_cursor.cc_color; 522 523 SELECT455(vdac, 8); 524 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 525 BYTE(vdac, bt_cmap) = cp[1]; tc_wmb(); 526 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 527 528 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 529 BYTE(vdac, bt_cmap) = cp[1]; tc_wmb(); 530 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 531 532 BYTE(vdac, bt_ovly) = 0; tc_wmb(); 533 BYTE(vdac, bt_ovly) = cp[0]; tc_wmb(); 534 BYTE(vdac, bt_ovly) = 0; tc_wmb(); 535 } 536 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 537 u_int8_t *ip, *mp, img, msk; 538 int bcnt; 539 540 ip = (u_int8_t *)sc->sc_cursor.cc_image; 541 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE); 542 bcnt = 0; 543 SELECT431(curs, BT431_REG_CRAM_BASE); 544 545 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 546 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 547 /* pad right half 32 pixel when smaller than 33 */ 548 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 549 HALF(curs, bt_ram) = 0; 550 tc_wmb(); 551 } 552 else { 553 img = *ip++; 554 msk = *mp++; 555 img &= msk; /* cookie off image */ 556 HALF(curs, bt_ram) 557 = (flip[msk] << 8) | flip[img]; 558 tc_wmb(); 559 } 560 bcnt += 2; 561 } 562 /* pad unoccupied scan lines */ 563 while (bcnt < CURSOR_MAX_SIZE * 16) { 564 HALF(curs, bt_ram) = 0; 565 tc_wmb(); 566 bcnt += 2; 567 } 568 } 569 sc->sc_changed = 0; 570 done: 571 return (1); 572 } 573 574 static void 575 mfbhwinit(mfbbase) 576 caddr_t mfbbase; 577 { 578 caddr_t vdac, curs; 579 int i; 580 581 vdac = mfbbase + MX_BT455_OFFSET; 582 curs = mfbbase + MX_BT431_OFFSET; 583 SELECT431(curs, BT431_REG_COMMAND); 584 HALF(curs, bt_ctl) = 0x0404; tc_wmb(); 585 HALF(curs, bt_ctl) = 0; /* XLO */ tc_wmb(); 586 HALF(curs, bt_ctl) = 0; /* XHI */ tc_wmb(); 587 HALF(curs, bt_ctl) = 0; /* YLO */ tc_wmb(); 588 HALF(curs, bt_ctl) = 0; /* YHI */ tc_wmb(); 589 HALF(curs, bt_ctl) = 0; /* XWLO */ tc_wmb(); 590 HALF(curs, bt_ctl) = 0; /* XWHI */ tc_wmb(); 591 HALF(curs, bt_ctl) = 0; /* WYLO */ tc_wmb(); 592 HALF(curs, bt_ctl) = 0; /* WYLO */ tc_wmb(); 593 HALF(curs, bt_ctl) = 0; /* WWLO */ tc_wmb(); 594 HALF(curs, bt_ctl) = 0; /* WWHI */ tc_wmb(); 595 HALF(curs, bt_ctl) = 0; /* WHLO */ tc_wmb(); 596 HALF(curs, bt_ctl) = 0; /* WHHI */ tc_wmb(); 597 598 /* 0: black, 1: white, 8,9: cursor mask, ovly: cursor image */ 599 SELECT455(vdac, 0); 600 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 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) = 0xff; tc_wmb(); 605 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 606 for (i = 2; i < 16; i++) { 607 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 608 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 609 BYTE(vdac, bt_cmap) = 0; tc_wmb(); 610 } 611 BYTE(vdac, bt_ovly) = 0; tc_wmb(); 612 BYTE(vdac, bt_ovly) = 0xff; tc_wmb(); 613 BYTE(vdac, bt_ovly) = 0; tc_wmb(); 614 615 SELECT431(curs, BT431_REG_CRAM_BASE); 616 for (i = 0; i < 512; i++) { 617 HALF(curs, bt_ram) = 0; tc_wmb(); 618 } 619 } 620 621 static int 622 set_cursor(sc, p) 623 struct mfb_softc *sc; 624 struct wsdisplay_cursor *p; 625 { 626 #define cc (&sc->sc_cursor) 627 u_int v, count, index; 628 629 v = p->which; 630 if (v & WSDISPLAY_CURSOR_DOCMAP) { 631 index = p->cmap.index; 632 count = p->cmap.count; 633 if (index >= 2 || (index + count) > 2) 634 return (EINVAL); 635 if (!uvm_useracc(p->cmap.red, count, B_READ)) 636 return (EFAULT); 637 } 638 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 639 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE) 640 return (EINVAL); 641 count = ((p->size.x < 33) ? 4 : 8) * p->size.y; 642 if (!uvm_useracc(p->image, count, B_READ) || 643 !uvm_useracc(p->mask, count, B_READ)) 644 return (EFAULT); 645 } 646 647 if (v & WSDISPLAY_CURSOR_DOCUR) 648 sc->sc_curenb = p->enable; 649 if (v & WSDISPLAY_CURSOR_DOPOS) 650 set_curpos(sc, &p->pos); 651 if (v & WSDISPLAY_CURSOR_DOHOT) 652 cc->cc_hot = p->hot; 653 if (v & WSDISPLAY_CURSOR_DOCMAP) 654 copyin(p->cmap.red, &cc->cc_color[index], count); 655 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 656 cc->cc_size = p->size; 657 memset(cc->cc_image, 0, sizeof cc->cc_image); 658 copyin(p->image, cc->cc_image, count); 659 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, count); 660 } 661 sc->sc_changed = v; 662 663 return (0); 664 #undef cc 665 } 666 667 static int 668 get_cursor(sc, p) 669 struct mfb_softc *sc; 670 struct wsdisplay_cursor *p; 671 { 672 return (ENOTTY); /* XXX */ 673 } 674 675 static void 676 set_curpos(sc, curpos) 677 struct mfb_softc *sc; 678 struct wsdisplay_curpos *curpos; 679 { 680 struct rasops_info *ri = sc->sc_ri; 681 int x = curpos->x, y = curpos->y; 682 683 if (y < 0) 684 y = 0; 685 else if (y > ri->ri_height) 686 y = ri->ri_height; 687 if (x < 0) 688 x = 0; 689 else if (x > ri->ri_width) 690 x = ri->ri_width; 691 sc->sc_cursor.cc_pos.x = x; 692 sc->sc_cursor.cc_pos.y = y; 693 } 694