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