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