1 /* $NetBSD: vidcvideo.c,v 1.2 2001/11/27 01:03:53 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Reinoud Zandijk 5 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Tohru Nishimura 18 * and Reinoud Zandijk for the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Created vidcvideo.c from /dev/tc/cfb.c to fit the Acorn/ARM VIDC1 and VIDC20 chips 34 * 35 */ 36 37 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 38 39 __KERNEL_RCSID(0, "$NetBSD: vidcvideo.c,v 1.2 2001/11/27 01:03:53 thorpej Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 #include <sys/buf.h> 47 #include <sys/ioctl.h> 48 49 #include <arm/mainbus/mainbus.h> 50 #include <machine/bus.h> 51 #include <machine/intr.h> 52 53 #include <dev/wscons/wsconsio.h> 54 #include <dev/wscons/wsdisplayvar.h> 55 56 #include <dev/rasops/rasops.h> 57 #include <dev/wsfont/wsfont.h> 58 59 #include <uvm/uvm_extern.h> 60 #include <arm/arm32/pmap.h> 61 #include <machine/intr.h> 62 63 /* for vidc_mode ... needs to be MI indepenent one day */ 64 #include <arm/iomd/vidc.h> 65 #include <arm/iomd/vidc20config.h> 66 #include <machine/bootconfig.h> 67 extern videomemory_t videomemory; 68 69 #define machine_btop(x) arm_byte_to_page(x) 70 #define MACHINE_KSEG0_TO_PHYS(x) vtophys(x) 71 72 /* FOR DEBUG */ 73 extern videomemory_t videomemory; 74 75 struct fb_devconfig { 76 vaddr_t dc_vaddr; /* memory space virtual base address */ 77 paddr_t dc_paddr; /* memory space physical base address */ 78 vsize_t dc_size; /* size of slot memory */ 79 int dc_wid; /* width of frame buffer */ 80 int dc_ht; /* height of frame buffer */ 81 int dc_log2_depth; /* log2 of bits per pixel */ 82 int dc_depth; /* depth, bits per pixel */ 83 int dc_rowbytes; /* bytes in a FB scan line */ 84 vaddr_t dc_videobase; /* base of flat frame buffer */ 85 int dc_blanked; /* currently has video disabled */ 86 void *dc_hwscroll_cookie; /* cookie for hardware scroll */ 87 88 struct vidc_mode mode_info; 89 struct rasops_info rinfo; 90 }; 91 92 93 struct hwcmap256 { 94 #define CMAP_SIZE 256 /* 256 R/G/B entries */ 95 u_int8_t r[CMAP_SIZE]; 96 u_int8_t g[CMAP_SIZE]; 97 u_int8_t b[CMAP_SIZE]; 98 }; 99 100 101 /* XXX for CURSOR_MAX_WIDTH = 32 */ 102 struct hwcursor32 { 103 struct wsdisplay_curpos cc_pos; 104 struct wsdisplay_curpos cc_hot; 105 struct wsdisplay_curpos cc_size; 106 struct wsdisplay_curpos cc_magic; 107 u_int8_t cc_color[6]; /* how many? */ 108 u_int32_t cc_image[(CURSOR_MAX_WIDTH/4) * CURSOR_MAX_HEIGHT]; 109 u_int32_t cc_mask[(CURSOR_MAX_WIDTH/4) * CURSOR_MAX_HEIGHT]; 110 }; 111 112 113 struct vidcvideo_softc { 114 struct device sc_dev; 115 struct fb_devconfig *sc_dc; /* device configuration */ 116 struct hwcmap256 sc_cmap; /* software copy of colormap */ 117 struct hwcursor32 sc_cursor; /* software copy of cursor */ 118 int sc_curenb; /* cursor sprite enabled */ 119 int sc_changed; /* need update of hardware */ 120 #define WSDISPLAY_CMAP_DOLUT 0x20 121 #define WSDISPLAY_VIDEO_ONOFF 0x40 122 int nscreens; 123 }; 124 125 126 /* XXX has to go XXX */ 127 #define CX_MAGIC_X 220 128 #define CX_MAGIC_Y 35 129 #define CX_FB_OFFSET 0x000000 130 #define CX_FB_SIZE 0x100000 131 #define CX_BT459_OFFSET 0x200000 132 #define CX_OFFSET_IREQ 0x300000 /* Interrupt req. control */ 133 /* XXX till here XXX */ 134 135 136 /* Function prototypes for glue */ 137 static int vidcvideo_match __P((struct device *, struct cfdata *, void *)); 138 static void vidcvideo_attach __P((struct device *, struct device *, void *)); 139 140 141 /* config glue */ 142 const struct cfattach vidcvideo_ca = { 143 sizeof(struct vidcvideo_softc), vidcvideo_match, vidcvideo_attach, 144 }; 145 146 147 static struct fb_devconfig vidcvideo_console_dc; 148 static int vidcvideo_is_console; 149 150 151 static struct wsscreen_descr vidcvideo_stdscreen = { 152 "std", 0, 0, 153 0, /* textops */ 154 0, 0, 155 WSSCREEN_REVERSE 156 }; 157 158 static const struct wsscreen_descr *_vidcvideo_scrlist[] = { 159 &vidcvideo_stdscreen, 160 }; 161 162 static const struct wsscreen_list vidcvideo_screenlist = { 163 sizeof(_vidcvideo_scrlist) / sizeof(struct wsscreen_descr *), _vidcvideo_scrlist 164 }; 165 166 static int vidcvideoioctl __P((void *, u_long, caddr_t, int, struct proc *)); 167 static paddr_t vidcvideommap __P((void *, off_t, int)); 168 169 static int vidcvideo_alloc_screen __P((void *, const struct wsscreen_descr *, 170 void **, int *, int *, long *)); 171 static void vidcvideo_free_screen __P((void *, void *)); 172 static int vidcvideo_show_screen __P((void *, void *, int, 173 void (*) (void *, int, int), void *)); 174 175 static const struct wsdisplay_accessops vidcvideo_accessops = { 176 vidcvideoioctl, 177 vidcvideommap, 178 vidcvideo_alloc_screen, 179 vidcvideo_free_screen, 180 vidcvideo_show_screen, 181 0 /* load_font */ 182 }; 183 184 /* Function prototypes */ 185 int vidcvideo_cnattach __P((vaddr_t)); 186 static void vidcvideo_colourmap_and_cursor_init __P((struct fb_devconfig *)); 187 188 static int get_cmap __P((struct vidcvideo_softc *, struct wsdisplay_cmap *)); 189 static int set_cmap __P((struct vidcvideo_softc *, struct wsdisplay_cmap *)); 190 static int set_cursor __P((struct vidcvideo_softc *, struct wsdisplay_cursor *)); 191 static int get_cursor __P((struct vidcvideo_softc *, struct wsdisplay_cursor *)); 192 static void set_curpos __P((struct vidcvideo_softc *, struct wsdisplay_curpos *)); 193 static void vidcvideo_getdevconfig __P((vaddr_t, struct fb_devconfig *)); 194 195 static int vidcvideointr __P((void *)); 196 197 /* Acceleration function prototypes */ 198 static void vv_copyrows __P((void *, int, int, int)); 199 static void vv_eraserows __P((void *, int, int, long)); 200 201 202 static int 203 vidcvideo_match(parent, match, aux) 204 struct device *parent; 205 struct cfdata *match; 206 void *aux; 207 { 208 /* Can't probe AFAIK ; how ? */ 209 return (1); 210 } 211 212 213 static void 214 vidcvideo_getdevconfig(dense_addr, dc) 215 vaddr_t dense_addr; 216 struct fb_devconfig *dc; 217 { 218 dc->dc_vaddr = dense_addr; 219 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr); 220 221 vidcvideo_getmode(&dc->mode_info); 222 223 dc->dc_wid = dc->mode_info.hder; 224 dc->dc_ht = dc->mode_info.vder; 225 dc->dc_log2_depth = dc->mode_info.log2_bpp; 226 dc->dc_depth = 1 << dc->dc_log2_depth; 227 dc->dc_videobase = dc->dc_vaddr; 228 dc->dc_blanked = 0; 229 230 /* this should/could be done somewhat more elegant! */ 231 switch (dc->dc_depth) { 232 case 1: 233 dc->dc_rowbytes = dc->dc_wid / 8; 234 break; 235 case 2: 236 dc->dc_rowbytes = dc->dc_wid / 4; 237 break; 238 case 4: 239 dc->dc_rowbytes = dc->dc_wid / 2; 240 break; 241 case 8: 242 dc->dc_rowbytes = dc->dc_wid; 243 break; 244 case 16: 245 dc->dc_rowbytes = dc->dc_wid * 2; 246 break; 247 case 32: 248 dc->dc_rowbytes = dc->dc_wid * 4; 249 break; 250 default: 251 printf("Unknown colour depth %d ... what to do ?", dc->dc_depth); 252 break; 253 }; 254 255 /* euhm... correct ? i.e. not complete VIDC memory */ 256 dc->dc_size = dc->mode_info.vder * dc->dc_rowbytes; 257 258 /* initialize colormap and cursor resource */ 259 vidcvideo_colourmap_and_cursor_init(dc); 260 261 dc->rinfo.ri_flg = 0; /* RI_CENTER; */ 262 dc->rinfo.ri_depth = dc->dc_depth; 263 dc->rinfo.ri_bits = (void *) dc->dc_videobase; 264 dc->rinfo.ri_width = dc->dc_wid; 265 dc->rinfo.ri_height = dc->dc_ht; 266 dc->rinfo.ri_stride = dc->dc_rowbytes; 267 dc->rinfo.ri_hw = NULL; 268 } 269 270 271 static void 272 vidcvideo_config_wscons(dc) 273 struct fb_devconfig *dc; 274 { 275 int i, cookie, font_locked; 276 277 /* clear the screen ; why not a memset ? - it was this way so keep it for now */ 278 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t)) 279 *(u_int32_t *)(dc->dc_videobase + i) = 0x0; 280 281 wsfont_init(); 282 283 /* prefer 8 pixel wide font */ 284 if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0) 285 cookie = wsfont_find(NULL, 0, 0, 0); 286 287 if (cookie < 0) { 288 /* Can I even print here ? */ 289 printf("Font table empty! exiting\n"); 290 return; 291 }; 292 293 font_locked = wsfont_lock(cookie, &dc->rinfo.ri_font, 294 WSDISPLAY_FONTORDER_L2R, WSDISPLAY_FONTORDER_L2R); 295 296 dc->rinfo.ri_wsfcookie = cookie; 297 298 rasops_init(&dc->rinfo, 299 dc->rinfo.ri_height / dc->rinfo.ri_font->fontheight, 300 dc->rinfo.ri_width / dc->rinfo.ri_font->fontwidth 301 ); 302 303 /* XXX add our accelerated functions */ 304 dc->rinfo.ri_ops.eraserows = vv_eraserows; 305 dc->rinfo.ri_ops.copyrows = vv_copyrows; 306 307 /* XXX shouldn't be global */ 308 vidcvideo_stdscreen.nrows = dc->rinfo.ri_rows; 309 vidcvideo_stdscreen.ncols = dc->rinfo.ri_cols; 310 vidcvideo_stdscreen.textops = &dc->rinfo.ri_ops; 311 vidcvideo_stdscreen.capabilities = dc->rinfo.ri_caps; 312 313 if (font_locked < 0) { 314 printf(" warning ... couldn't lock font! "); 315 }; 316 } 317 318 319 static void 320 vidcvideo_attach(parent, self, aux) 321 struct device *parent, *self; 322 void *aux; 323 { 324 struct vidcvideo_softc *sc = (struct vidcvideo_softc *)self; 325 struct wsemuldisplaydev_attach_args waa; 326 struct hwcmap256 *cm; 327 const u_int8_t *p; 328 int index; 329 330 vidcvideo_init(); 331 if (sc->nscreens == 0) { 332 if (vidcvideo_is_console) { 333 sc->sc_dc = &vidcvideo_console_dc; 334 } else { 335 printf(" : non console vidcvideo fb ... can't cope with this\n"); 336 return; 337 /* 338 * sc->sc_dc = (struct fb_devconfig *) 339 * malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK); 340 * vidcvideo_getdevconfig(videomemory.vidm_vbase, sc->sc_dc); 341 */ 342 }; 343 sc->nscreens = 1; 344 } else { 345 printf(": allready attached ... can't cope with this\n"); 346 return; 347 }; 348 349 vidcvideo_printdetails(); 350 printf(": using %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, 351 sc->sc_dc->dc_depth); 352 353 /* initialise rasops */ 354 cm = &sc->sc_cmap; 355 p = rasops_cmap; 356 for (index = 0; index < CMAP_SIZE; index++, p += 3) { 357 cm->r[index] = p[0]; 358 cm->g[index] = p[1]; 359 cm->b[index] = p[2]; 360 } 361 362 /* what does these do ? */ 363 sc->sc_cursor.cc_magic.x = CX_MAGIC_X; 364 sc->sc_cursor.cc_magic.y = CX_MAGIC_Y; 365 366 /* set up interrupt flags */ 367 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 368 369 /* set up a link in the rasops structure to our softc for acceleration stuff */ 370 sc->sc_dc->rinfo.ri_hw = sc; 371 372 /* Establish an interrupt handler, and clear any pending interrupts */ 373 intr_claim(IRQ_FLYBACK, IPL_TTY, "vblank", vidcvideointr, sc); 374 375 waa.console = (vidcvideo_is_console ? 1 : 0); 376 waa.scrdata = &vidcvideo_screenlist; 377 waa.accessops = &vidcvideo_accessops; 378 waa.accesscookie = sc; 379 380 config_found(self, &waa, wsemuldisplaydevprint); 381 } 382 383 384 static int 385 vidcvideoioctl(v, cmd, data, flag, p) 386 void *v; 387 u_long cmd; 388 caddr_t data; 389 int flag; 390 struct proc *p; 391 { 392 struct vidcvideo_softc *sc = v; 393 struct fb_devconfig *dc = sc->sc_dc; 394 int state; 395 396 switch (cmd) { 397 case WSDISPLAYIO_GTYPE: 398 *(u_int *)data = WSDISPLAY_TYPE_VIDC; 399 return (0); 400 401 case WSDISPLAYIO_GINFO: 402 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 403 wsd_fbip->height = sc->sc_dc->dc_ht; 404 wsd_fbip->width = sc->sc_dc->dc_wid; 405 wsd_fbip->depth = sc->sc_dc->dc_depth; 406 wsd_fbip->cmsize = CMAP_SIZE; 407 #undef fbt 408 return (0); 409 410 case WSDISPLAYIO_GETCMAP: 411 return get_cmap(sc, (struct wsdisplay_cmap *)data); 412 413 case WSDISPLAYIO_PUTCMAP: 414 return set_cmap(sc, (struct wsdisplay_cmap *)data); 415 416 case WSDISPLAYIO_SVIDEO: 417 state = *(int *)data; 418 dc->dc_blanked = (state == WSDISPLAYIO_VIDEO_OFF); 419 sc->sc_changed |= WSDISPLAY_VIDEO_ONOFF; 420 /* done on video blank */ 421 return (0); 422 423 case WSDISPLAYIO_GVIDEO: 424 *(u_int *)data = dc->dc_blanked ? 425 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 426 return (0); 427 428 case WSDISPLAYIO_GCURPOS: 429 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 430 return (0); 431 432 case WSDISPLAYIO_SCURPOS: 433 set_curpos(sc, (struct wsdisplay_curpos *)data); 434 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 435 return (0); 436 437 case WSDISPLAYIO_GCURMAX: 438 ((struct wsdisplay_curpos *)data)->x = CURSOR_MAX_WIDTH; 439 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_HEIGHT; 440 return (0); 441 442 case WSDISPLAYIO_GCURSOR: 443 return get_cursor(sc, (struct wsdisplay_cursor *)data); 444 445 case WSDISPLAYIO_SCURSOR: 446 return set_cursor(sc, (struct wsdisplay_cursor *)data); 447 448 case WSDISPLAYIO_SMODE: 449 state = *(int *)data; 450 if (state == WSDISPLAYIO_MODE_MAPPED) { 451 dc->dc_hwscroll_cookie = vidcvideo_hwscroll_reset(); 452 }; 453 if (state == WSDISPLAYIO_MODE_EMUL) { 454 vidcvideo_hwscroll_back(dc->dc_hwscroll_cookie); 455 }; 456 vidcvideo_progr_scroll(); 457 return (0); 458 } 459 return ENOTTY; 460 } 461 462 463 paddr_t 464 vidcvideommap(v, offset, prot) 465 void *v; 466 off_t offset; 467 int prot; 468 { 469 struct vidcvideo_softc *sc = v; 470 471 if (offset >= sc->sc_dc->dc_size || offset < 0) 472 return (-1); 473 return machine_btop(sc->sc_dc->dc_paddr + offset); 474 } 475 476 477 static int 478 vidcvideo_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 479 void *v; 480 const struct wsscreen_descr *type; 481 void **cookiep; 482 int *curxp, *curyp; 483 long *attrp; 484 { 485 struct vidcvideo_softc *sc = v; 486 long defattr; 487 488 if (sc->nscreens > 0) 489 return (ENOMEM); 490 491 *cookiep = &sc->sc_dc->rinfo; /* one and only for now */ 492 *curxp = 0; 493 *curyp = 0; 494 (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr); 495 *attrp = defattr; 496 sc->nscreens++; 497 return (0); 498 } 499 500 501 static void 502 vidcvideo_free_screen(v, cookie) 503 void *v; 504 void *cookie; 505 { 506 struct vidcvideo_softc *sc = v; 507 508 if (sc->sc_dc == &vidcvideo_console_dc) 509 panic("vidcvideo_free_screen: console"); 510 511 sc->nscreens--; 512 } 513 514 515 static int 516 vidcvideo_show_screen(v, cookie, waitok, cb, cbarg) 517 void *v; 518 void *cookie; 519 int waitok; 520 void (*cb) __P((void *, int, int)); 521 void *cbarg; 522 { 523 524 return (0); 525 } 526 527 528 /* EXPORT */ int 529 vidcvideo_cnattach(addr) 530 vaddr_t addr; 531 { 532 struct fb_devconfig *dcp = &vidcvideo_console_dc; 533 long defattr; 534 535 vidcvideo_init(); 536 vidcvideo_getdevconfig(addr, dcp); 537 vidcvideo_config_wscons(dcp); 538 (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr); 539 wsdisplay_cnattach(&vidcvideo_stdscreen, &dcp->rinfo, 0, 0, defattr); 540 541 vidcvideo_is_console = 1; 542 return(0); 543 } 544 545 546 static int 547 vidcvideointr(arg) 548 void *arg; 549 { 550 struct vidcvideo_softc *sc = arg; 551 int v; 552 553 v = sc->sc_changed; 554 if (v == 0) 555 return (1); 556 557 if (v & WSDISPLAY_CMAP_DOLUT) { 558 struct hwcmap256 *cm = &sc->sc_cmap; 559 int index; 560 561 if (sc->sc_dc->dc_depth == 4) { 562 /* palette for 4 bpp is different from 8bpp */ 563 vidcvideo_write(VIDC_PALREG, 0x00000000); 564 for (index=0; index < 1<<sc->sc_dc->dc_depth; index++) 565 vidcvideo_write(VIDC_PALETTE, 566 VIDC_COL(cm->r[index], 567 cm->g[index], 568 cm->b[index])); 569 ; 570 }; 571 572 if (sc->sc_dc->dc_depth == 8) { 573 /* XXX dunno what to do in less than 8bpp */ 574 /* palettes only make sense in 8bpp and less modes on VIDC */ 575 vidcvideo_write(VIDC_PALREG, 0x00000000); 576 for (index = 0; index < CMAP_SIZE; index++) { 577 vidcvideo_write(VIDC_PALETTE, 578 VIDC_COL(cm->r[index], cm->g[index], cm->b[index]) 579 ); 580 }; 581 }; 582 } 583 584 if (v & WSDISPLAY_VIDEO_ONOFF) { 585 vidcvideo_blank(sc->sc_dc->dc_blanked); 586 }; 587 588 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 589 int x, y; 590 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 591 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 592 593 vidcvideo_updatecursor(x, y); 594 }; 595 596 if (v & WSDISPLAY_CURSOR_DOCUR) { 597 vidcvideo_enablecursor(sc->sc_curenb); 598 }; 599 600 601 #if 0 /* XXX snip XXX */ 602 /* XXX kept here as an archive for now XXX */ 603 604 vdac = vidcvideobase + CX_BT459_OFFSET; 605 v = sc->sc_changed; 606 if (v & WSDISPLAY_CURSOR_DOCUR) { 607 SELECT(vdac, BT459_IREG_CCR); 608 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00; 609 } 610 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) { 611 int x, y; 612 613 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 614 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 615 616 x += sc->sc_cursor.cc_magic.x; 617 y += sc->sc_cursor.cc_magic.y; 618 619 SELECT(vdac, BT459_IREG_CURSOR_X_LOW); 620 REG(vdac, bt_reg) = x; tc_wmb(); 621 REG(vdac, bt_reg) = x >> 8; tc_wmb(); 622 REG(vdac, bt_reg) = y; tc_wmb(); 623 REG(vdac, bt_reg) = y >> 8; tc_wmb(); 624 } 625 if (v & WSDISPLAY_CURSOR_DOCMAP) { 626 u_int8_t *cp = sc->sc_cursor.cc_color; 627 628 SELECT(vdac, BT459_IREG_CCOLOR_2); 629 REG(vdac, bt_reg) = cp[1]; tc_wmb(); 630 REG(vdac, bt_reg) = cp[3]; tc_wmb(); 631 REG(vdac, bt_reg) = cp[5]; tc_wmb(); 632 633 REG(vdac, bt_reg) = cp[0]; tc_wmb(); 634 REG(vdac, bt_reg) = cp[2]; tc_wmb(); 635 REG(vdac, bt_reg) = cp[4]; tc_wmb(); 636 } 637 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 638 u_int8_t *ip, *mp, img, msk; 639 u_int8_t u; 640 int bcnt; 641 642 ip = (u_int8_t *)sc->sc_cursor.cc_image; 643 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_HEIGHT); 644 645 bcnt = 0; 646 SELECT(vdac, BT459_IREG_CRAM_BASE+0); 647 /* 64 pixel scan line is consisted with 16 byte cursor ram */ 648 while (bcnt < sc->sc_cursor.cc_size.y * 16) { 649 /* pad right half 32 pixel when smaller than 33 */ 650 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) { 651 REG(vdac, bt_reg) = 0; tc_wmb(); 652 REG(vdac, bt_reg) = 0; tc_wmb(); 653 } 654 else { 655 img = *ip++; 656 msk = *mp++; 657 img &= msk; /* cookie off image */ 658 u = (msk & 0x0f) << 4 | (img & 0x0f); 659 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 660 u = (msk & 0xf0) | (img & 0xf0) >> 4; 661 REG(vdac, bt_reg) = shuffle[u]; tc_wmb(); 662 } 663 bcnt += 2; 664 } 665 /* pad unoccupied scan lines */ 666 while (bcnt < CURSOR_MAX_HEIGHT * 16) { 667 REG(vdac, bt_reg) = 0; tc_wmb(); 668 REG(vdac, bt_reg) = 0; tc_wmb(); 669 bcnt += 2; 670 } 671 } 672 #endif /* XXX snip XXX */ 673 674 sc->sc_changed = 0; 675 return (1); 676 } 677 678 679 static u_char ri_col_data[6][6] = { 680 { 0, 0, 0, 0, 0, 0}, /* 1 bpp */ 681 { 0, 0, 0, 0, 0, 0}, /* 2 bpp */ 682 { 0, 0, 0, 0, 0, 0}, /* 4 bpp */ 683 { 0, 0, 0, 0, 0, 0}, /* 8 bpp */ 684 { 5, 5, 5, 0, 5, 10}, /* 16 bpp */ 685 { 8, 8, 8, 0, 8, 16}, /* 32 bpp */ 686 }; 687 688 static void 689 vidcvideo_colourmap_and_cursor_init(dc) 690 struct fb_devconfig *dc; 691 { 692 struct rasops_info *ri = &dc->rinfo; 693 u_char *rgbdat; 694 695 /* Whatever we do later... just make sure we have a 696 * sane palette to start with 697 */ 698 vidcvideo_stdpalette(); 699 700 /* set up rgb bit pattern values for rasops_init */ 701 rgbdat = ri_col_data[dc->dc_log2_depth]; 702 ri->ri_rnum = rgbdat[0]; 703 ri->ri_gnum = rgbdat[1]; 704 ri->ri_bnum = rgbdat[2]; 705 ri->ri_rpos = rgbdat[3]; 706 ri->ri_gpos = rgbdat[4]; 707 ri->ri_bpos = rgbdat[5]; 708 709 } 710 711 712 static int 713 get_cmap(sc, p) 714 struct vidcvideo_softc *sc; 715 struct wsdisplay_cmap *p; 716 { 717 u_int index = p->index, count = p->count; 718 719 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 720 return (EINVAL); 721 722 if (!uvm_useracc(p->red, count, B_WRITE) || 723 !uvm_useracc(p->green, count, B_WRITE) || 724 !uvm_useracc(p->blue, count, B_WRITE)) 725 return (EFAULT); 726 727 copyout(&sc->sc_cmap.r[index], p->red, count); 728 copyout(&sc->sc_cmap.g[index], p->green, count); 729 copyout(&sc->sc_cmap.b[index], p->blue, count); 730 731 return (0); 732 } 733 734 735 static int 736 set_cmap(sc, p) 737 struct vidcvideo_softc *sc; 738 struct wsdisplay_cmap *p; 739 { 740 u_int index = p->index, count = p->count; 741 742 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE) 743 return (EINVAL); 744 745 if (!uvm_useracc(p->red, count, B_READ) || 746 !uvm_useracc(p->green, count, B_READ) || 747 !uvm_useracc(p->blue, count, B_READ)) 748 return (EFAULT); 749 750 copyin(p->red, &sc->sc_cmap.r[index], count); 751 copyin(p->green, &sc->sc_cmap.g[index], count); 752 copyin(p->blue, &sc->sc_cmap.b[index], count); 753 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 754 return (0); 755 } 756 757 758 static int 759 set_cursor(sc, p) 760 struct vidcvideo_softc *sc; 761 struct wsdisplay_cursor *p; 762 { 763 #define cc (&sc->sc_cursor) 764 u_int v, index, count, icount; 765 766 v = p->which; 767 if (v & WSDISPLAY_CURSOR_DOCMAP) { 768 index = p->cmap.index; 769 count = p->cmap.count; 770 if (index >= CURSOR_MAX_COLOURS || (index + count) > CURSOR_MAX_COLOURS) 771 return (EINVAL); 772 if (!uvm_useracc(p->cmap.red, count, B_READ) || 773 !uvm_useracc(p->cmap.green, count, B_READ) || 774 !uvm_useracc(p->cmap.blue, count, B_READ)) 775 return (EFAULT); 776 } 777 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 778 if (p->size.x > CURSOR_MAX_WIDTH || p->size.y > CURSOR_MAX_HEIGHT) 779 return (EINVAL); 780 icount = sizeof(u_int32_t) * p->size.y; 781 if (!uvm_useracc(p->image, icount, B_READ) || 782 !uvm_useracc(p->mask, icount, B_READ)) 783 return (EFAULT); 784 } 785 786 if (v & WSDISPLAY_CURSOR_DOCUR) 787 sc->sc_curenb = p->enable; 788 if (v & WSDISPLAY_CURSOR_DOPOS) 789 set_curpos(sc, &p->pos); 790 if (v & WSDISPLAY_CURSOR_DOHOT) 791 cc->cc_hot = p->hot; 792 if (v & WSDISPLAY_CURSOR_DOCMAP) { 793 copyin(p->cmap.red, &cc->cc_color[index], count); 794 copyin(p->cmap.green, &cc->cc_color[index + 2], count); 795 copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 796 } 797 if (v & WSDISPLAY_CURSOR_DOSHAPE) { 798 cc->cc_size = p->size; 799 memset(cc->cc_image, 0, sizeof cc->cc_image); 800 memset(cc->cc_mask, 0, sizeof cc->cc_mask); 801 copyin(p->image, cc->cc_image, icount); 802 copyin(p->mask, cc->cc_mask, icount); 803 } 804 sc->sc_changed |= v; 805 806 return (0); 807 #undef cc 808 } 809 810 811 static int 812 get_cursor(sc, p) 813 struct vidcvideo_softc *sc; 814 struct wsdisplay_cursor *p; 815 { 816 return (ENOTTY); /* XXX */ 817 } 818 819 820 static void 821 set_curpos(sc, curpos) 822 struct vidcvideo_softc *sc; 823 struct wsdisplay_curpos *curpos; 824 { 825 struct fb_devconfig *dc = sc->sc_dc; 826 int x = curpos->x, y = curpos->y; 827 828 if (y < 0) 829 y = 0; 830 else if (y > dc->dc_ht) 831 y = dc->dc_ht; 832 if (x < 0) 833 x = 0; 834 else if (x > dc->dc_wid) 835 x = dc->dc_wid; 836 sc->sc_cursor.cc_pos.x = x; 837 sc->sc_cursor.cc_pos.y = y; 838 } 839 840 841 static void vv_copyrows(id, srcrow, dstrow, nrows) 842 void *id; 843 int srcrow, dstrow, nrows; 844 { 845 struct rasops_info *ri = id; 846 int height, offset, size; 847 int scrollup, scrolldown; 848 unsigned char *src, *dst; 849 850 /* All movements are done in multiples of character heigths */ 851 height = ri->ri_font->fontheight * nrows; 852 offset = (srcrow - dstrow) * ri->ri_yscale; 853 size = height * ri->ri_stride; 854 855 /* check if we are full screen scrolling */ 856 scrollup = (srcrow + nrows >= ri->ri_rows); 857 scrolldown = (dstrow + nrows >= ri->ri_rows); 858 859 if ((scrollup || scrolldown) && (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM)) { 860 ri->ri_bits = vidcvideo_hwscroll(offset); 861 vidcvideo_progr_scroll(); /* sadistic ; shouldnt this be on vsync? */ 862 863 /* wipe out remains of the screen if nessisary */ 864 if (ri->ri_emuheight != ri->ri_height) vv_eraserows(id, ri->ri_rows, 1, NULL); 865 return; 866 }; 867 868 /* Else we just copy the area : we're braindead for now 869 * Note: we can't use hardware scrolling when the softc isnt known yet... 870 * if its not known we dont have interrupts and we can't change the display 871 * address reliable other than in a Vsync 872 */ 873 874 src = ri->ri_bits + srcrow * ri->ri_font->fontheight * ri->ri_stride; 875 dst = ri->ri_bits + dstrow * ri->ri_font->fontheight * ri->ri_stride; 876 877 bcopy(src, dst, size); 878 } 879 880 881 static void vv_eraserows(id, startrow, nrows, attr) 882 void *id; 883 int startrow, nrows; 884 long attr; 885 { 886 struct rasops_info *ri = id; 887 int height; 888 unsigned char *src; 889 890 /* we're braindead for now */ 891 height = ri->ri_font->fontheight * nrows * ri->ri_stride; 892 893 src = ri->ri_bits + startrow * ri->ri_font->fontheight * ri->ri_stride; 894 895 bzero(src, height); 896 } 897 898