1 /* $NetBSD: mgx.c,v 1.15 2021/04/24 23:36:58 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 Michael Lorenz 5 * 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* a console driver for the SSB 4096V-MGX graphics card */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: mgx.c,v 1.15 2021/04/24 23:36:58 thorpej Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/buf.h> 37 #include <sys/device.h> 38 #include <sys/ioctl.h> 39 #include <sys/conf.h> 40 #include <sys/kmem.h> 41 #include <sys/kauth.h> 42 #include <sys/atomic.h> 43 44 #include <sys/bus.h> 45 #include <machine/autoconf.h> 46 47 #include <dev/sbus/sbusvar.h> 48 #include <dev/sun/fbio.h> 49 #include <dev/sun/fbvar.h> 50 51 #include <dev/wscons/wsdisplayvar.h> 52 #include <dev/wscons/wsconsio.h> 53 #include <dev/wsfont/wsfont.h> 54 #include <dev/rasops/rasops.h> 55 56 #include <dev/wscons/wsdisplay_vconsvar.h> 57 #include <dev/wscons/wsdisplay_glyphcachevar.h> 58 59 #include <dev/ic/vgareg.h> 60 #include <dev/sbus/mgxreg.h> 61 62 #include "ioconf.h" 63 64 #include "opt_wsemul.h" 65 #include "opt_mgx.h" 66 67 struct mgx_softc { 68 device_t sc_dev; 69 struct fbdevice sc_fb; /* frame buffer device */ 70 bus_space_tag_t sc_tag; 71 bus_space_handle_t sc_blith; 72 bus_space_handle_t sc_vgah; 73 bus_addr_t sc_paddr, sc_rpaddr; 74 void *sc_fbaddr; 75 uint8_t *sc_cursor; 76 int sc_width; 77 int sc_height; 78 int sc_stride; 79 int sc_depth; 80 int sc_fbsize; 81 int sc_mode; 82 char sc_name[8]; 83 uint32_t sc_dec; 84 u_char sc_cmap_red[256]; 85 u_char sc_cmap_green[256]; 86 u_char sc_cmap_blue[256]; 87 int sc_cursor_x, sc_cursor_y; 88 int sc_hotspot_x, sc_hotspot_y; 89 int sc_video, sc_buf; 90 void (*sc_putchar)(void *, int, int, u_int, long); 91 struct vcons_screen sc_console_screen; 92 struct wsscreen_descr sc_defaultscreen_descr; 93 const struct wsscreen_descr *sc_screens[1]; 94 struct wsscreen_list sc_screenlist; 95 struct vcons_data vd; 96 glyphcache sc_gc; 97 uint8_t sc_in[256]; 98 }; 99 100 static int mgx_match(device_t, cfdata_t, void *); 101 static void mgx_attach(device_t, device_t, void *); 102 static int mgx_ioctl(void *, void *, u_long, void *, int, 103 struct lwp*); 104 static paddr_t mgx_mmap(void *, void *, off_t, int); 105 static void mgx_init_screen(void *, struct vcons_screen *, int, 106 long *); 107 static void mgx_write_dac(struct mgx_softc *, int, int, int, int); 108 static void mgx_setup(struct mgx_softc *, int); 109 static void mgx_init_palette(struct mgx_softc *); 110 static int mgx_putcmap(struct mgx_softc *, struct wsdisplay_cmap *); 111 static int mgx_getcmap(struct mgx_softc *, struct wsdisplay_cmap *); 112 static int mgx_wait_engine(struct mgx_softc *); 113 __unused static int mgx_wait_host(struct mgx_softc *); 114 /*static*/ int mgx_wait_fifo(struct mgx_softc *, unsigned int); 115 116 static void mgx_bitblt(void *, int, int, int, int, int, int, int); 117 static void mgx_rectfill(void *, int, int, int, int, long); 118 119 static void mgx_putchar_aa(void *, int, int, u_int, long); 120 static void mgx_putchar_mono(void *, int, int, u_int, long); 121 static void mgx_cursor(void *, int, int, int); 122 static void mgx_copycols(void *, int, int, int, int); 123 static void mgx_erasecols(void *, int, int, int, long); 124 static void mgx_copyrows(void *, int, int, int); 125 static void mgx_eraserows(void *, int, int, long); 126 static void mgx_adapt(struct vcons_screen *, void *); 127 128 static int mgx_do_cursor(struct mgx_softc *, struct wsdisplay_cursor *); 129 static void mgx_set_cursor(struct mgx_softc *); 130 static void mgx_set_video(struct mgx_softc *, int); 131 132 CFATTACH_DECL_NEW(mgx, sizeof(struct mgx_softc), 133 mgx_match, mgx_attach, NULL, NULL); 134 135 struct wsdisplay_accessops mgx_accessops = { 136 mgx_ioctl, 137 mgx_mmap, 138 NULL, /* vcons_alloc_screen */ 139 NULL, /* vcons_free_screen */ 140 NULL, /* vcons_show_screen */ 141 NULL, /* load_font */ 142 NULL, /* polls */ 143 NULL, /* scroll */ 144 }; 145 146 static void mgx_unblank(device_t); 147 148 dev_type_open(mgxopen); 149 dev_type_close(mgxclose); 150 dev_type_ioctl(mgxioctl); 151 dev_type_mmap(mgxmmap); 152 153 const struct cdevsw mgx_cdevsw = { 154 .d_open = mgxopen, 155 .d_close = mgxclose, 156 .d_read = noread, 157 .d_write = nowrite, 158 .d_ioctl = mgxioctl, 159 .d_stop = nostop, 160 .d_tty = notty, 161 .d_poll = nopoll, 162 .d_mmap = mgxmmap, 163 .d_kqfilter = nokqfilter, 164 .d_discard = nodiscard, 165 .d_flag = D_OTHER 166 }; 167 168 /* frame buffer generic driver */ 169 static struct fbdriver mgx_fbdriver = { 170 mgx_unblank, mgxopen, mgxclose, mgxioctl, nopoll, mgxmmap, 171 nokqfilter 172 }; 173 174 175 static inline void 176 mgx_write_vga(struct mgx_softc *sc, uint32_t reg, uint8_t val) 177 { 178 bus_space_write_1(sc->sc_tag, sc->sc_vgah, reg ^ 3, val); 179 } 180 181 static inline uint8_t 182 mgx_read_vga(struct mgx_softc *sc, uint32_t reg) 183 { 184 return bus_space_read_1(sc->sc_tag, sc->sc_vgah, reg ^ 3); 185 } 186 187 static inline void 188 mgx_write_1(struct mgx_softc *sc, uint32_t reg, uint8_t val) 189 { 190 bus_space_write_1(sc->sc_tag, sc->sc_blith, reg ^ 3, val); 191 } 192 193 static inline uint8_t 194 mgx_read_1(struct mgx_softc *sc, uint32_t reg) 195 { 196 return bus_space_read_1(sc->sc_tag, sc->sc_blith, reg ^ 3); 197 } 198 199 #if 0 200 static inline uint32_t 201 mgx_read_4(struct mgx_softc *sc, uint32_t reg) 202 { 203 return bus_space_read_4(sc->sc_tag, sc->sc_blith, reg); 204 } 205 #endif 206 207 static inline void 208 mgx_write_2(struct mgx_softc *sc, uint32_t reg, uint16_t val) 209 { 210 bus_space_write_2(sc->sc_tag, sc->sc_blith, reg ^ 2, val); 211 } 212 213 static inline void 214 mgx_write_4(struct mgx_softc *sc, uint32_t reg, uint32_t val) 215 { 216 bus_space_write_4(sc->sc_tag, sc->sc_blith, reg, val); 217 } 218 219 static int 220 mgx_match(device_t parent, cfdata_t cf, void *aux) 221 { 222 struct sbus_attach_args *sa = aux; 223 224 if (strcmp("SMSI,mgx", sa->sa_name) == 0) 225 return 100; 226 return 0; 227 } 228 229 /* 230 * Attach a display. We need to notice if it is the console, too. 231 */ 232 static void 233 mgx_attach(device_t parent, device_t self, void *args) 234 { 235 struct mgx_softc *sc = device_private(self); 236 struct sbus_attach_args *sa = args; 237 struct wsemuldisplaydev_attach_args aa; 238 struct fbdevice *fb = &sc->sc_fb; 239 struct rasops_info *ri; 240 unsigned long defattr; 241 bus_space_handle_t bh; 242 int node = sa->sa_node, bsize; 243 int isconsole; 244 245 aprint_normal("\n"); 246 sc->sc_dev = self; 247 sc->sc_tag = sa->sa_bustag; 248 249 sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, 250 sa->sa_reg[8].oa_base); 251 sc->sc_rpaddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, 252 sa->sa_reg[5].oa_base + MGX_REG_ATREG_OFFSET); 253 254 /* read geometry information from the device tree */ 255 sc->sc_width = prom_getpropint(sa->sa_node, "width", 1152); 256 sc->sc_height = prom_getpropint(sa->sa_node, "height", 900); 257 sc->sc_stride = prom_getpropint(sa->sa_node, "linebytes", 1152); 258 sc->sc_fbsize = prom_getpropint(sa->sa_node, "fb_size", 0x00400000); 259 sc->sc_fbaddr = NULL; 260 if (sc->sc_fbaddr == NULL) { 261 if (sbus_bus_map(sa->sa_bustag, 262 sa->sa_slot, 263 sa->sa_reg[8].oa_base, 264 sc->sc_fbsize, 265 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, 266 &bh) != 0) { 267 aprint_error_dev(self, "couldn't map framebuffer\n"); 268 return; 269 } 270 sc->sc_fbaddr = bus_space_vaddr(sa->sa_bustag, bh); 271 } 272 273 if (sbus_bus_map(sa->sa_bustag, 274 sa->sa_slot, 275 sa->sa_reg[4].oa_base, 0x1000, 0, 276 &sc->sc_vgah) != 0) { 277 aprint_error("%s: couldn't map VGA registers\n", 278 device_xname(sc->sc_dev)); 279 return; 280 } 281 282 if (sbus_bus_map(sa->sa_bustag, 283 sa->sa_slot, 284 sa->sa_reg[5].oa_base + MGX_REG_ATREG_OFFSET, 0x1000, 285 0, &sc->sc_blith) != 0) { 286 aprint_error("%s: couldn't map blitter registers\n", 287 device_xname(sc->sc_dev)); 288 return; 289 } 290 291 mgx_setup(sc, MGX_DEPTH); 292 293 aprint_normal_dev(self, "[%s] %d MB framebuffer, %d x %d\n", 294 sc->sc_name, sc->sc_fbsize >> 20, sc->sc_width, sc->sc_height); 295 296 297 sc->sc_defaultscreen_descr = (struct wsscreen_descr) { 298 "default", 299 0, 0, 300 NULL, 301 8, 16, 302 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 303 WSSCREEN_RESIZE, 304 NULL 305 }; 306 307 sc->sc_cursor_x = 0; 308 sc->sc_cursor_y = 0; 309 sc->sc_hotspot_x = 0; 310 sc->sc_hotspot_y = 0; 311 sc->sc_video = WSDISPLAYIO_VIDEO_ON; 312 313 sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 314 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 315 316 isconsole = fb_is_console(node); 317 318 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 319 wsfont_init(); 320 321 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, &mgx_accessops); 322 sc->vd.init_screen = mgx_init_screen; 323 sc->vd.show_screen_cookie = sc; 324 sc->vd.show_screen_cb = mgx_adapt; 325 326 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); 327 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 328 329 ri = &sc->sc_console_screen.scr_ri; 330 331 sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 332 sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 333 sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 334 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 335 336 sc->sc_gc.gc_bitblt = mgx_bitblt; 337 sc->sc_gc.gc_rectfill = mgx_rectfill; 338 sc->sc_gc.gc_blitcookie = sc; 339 sc->sc_gc.gc_rop = ROP_SRC; 340 341 /* 342 * leave some room between visible screen and glyph cache for upload 343 * buffers used by putchar_mono() 344 */ 345 bsize = (32 * 1024 * sc->sc_stride - 1) / sc->sc_stride; 346 glyphcache_init(&sc->sc_gc, 347 sc->sc_height + bsize, 348 (0x400000 / sc->sc_stride) - (sc->sc_height + bsize), 349 sc->sc_width, 350 ri->ri_font->fontwidth, 351 ri->ri_font->fontheight, 352 defattr); 353 354 mgx_init_palette(sc); 355 356 if(isconsole) { 357 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 358 defattr); 359 vcons_replay_msgbuf(&sc->sc_console_screen); 360 } 361 362 aa.console = isconsole; 363 aa.scrdata = &sc->sc_screenlist; 364 aa.accessops = &mgx_accessops; 365 aa.accesscookie = &sc->vd; 366 367 config_found(self, &aa, wsemuldisplaydevprint, CFARG_EOL); 368 369 /* now the Sun fb goop */ 370 fb->fb_driver = &mgx_fbdriver; 371 fb->fb_device = sc->sc_dev; 372 fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK; 373 fb->fb_type.fb_type = FBTYPE_MGX; 374 fb->fb_pixels = NULL; 375 376 fb->fb_type.fb_depth = 32; 377 fb->fb_type.fb_width = sc->sc_width; 378 fb->fb_type.fb_height = sc->sc_height; 379 fb->fb_linebytes = sc->sc_stride * 4; 380 381 fb->fb_type.fb_cmsize = 256; 382 fb->fb_type.fb_size = sc->sc_fbsize; 383 fb_attach(&sc->sc_fb, isconsole); 384 } 385 386 static void 387 mgx_write_dac(struct mgx_softc *sc, int idx, int r, int g, int b) 388 { 389 mgx_write_vga(sc, VGA_BASE + VGA_DAC_ADDRW, idx); 390 mgx_write_vga(sc, VGA_BASE + VGA_DAC_PALETTE, r); 391 mgx_write_vga(sc, VGA_BASE + VGA_DAC_PALETTE, g); 392 mgx_write_vga(sc, VGA_BASE + VGA_DAC_PALETTE, b); 393 } 394 395 static void 396 mgx_init_palette(struct mgx_softc *sc) 397 { 398 struct rasops_info *ri = &sc->sc_console_screen.scr_ri; 399 int i, j = 0; 400 uint8_t cmap[768]; 401 402 if (sc->sc_depth == 8) { 403 rasops_get_cmap(ri, cmap, sizeof(cmap)); 404 for (i = 0; i < 256; i++) { 405 sc->sc_cmap_red[i] = cmap[j]; 406 sc->sc_cmap_green[i] = cmap[j + 1]; 407 sc->sc_cmap_blue[i] = cmap[j + 2]; 408 mgx_write_dac(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); 409 j += 3; 410 } 411 } else { 412 /* linear ramp for true colour modes */ 413 for (i = 0; i < 256; i++) { 414 mgx_write_dac(sc, i, i, i, i); 415 } 416 } 417 } 418 419 static int 420 mgx_putcmap(struct mgx_softc *sc, struct wsdisplay_cmap *cm) 421 { 422 u_char *r, *g, *b; 423 u_int index = cm->index; 424 u_int count = cm->count; 425 int i, error; 426 u_char rbuf[256], gbuf[256], bbuf[256]; 427 428 if (cm->index >= 256 || cm->count > 256 || 429 (cm->index + cm->count) > 256) 430 return EINVAL; 431 error = copyin(cm->red, &rbuf[index], count); 432 if (error) 433 return error; 434 error = copyin(cm->green, &gbuf[index], count); 435 if (error) 436 return error; 437 error = copyin(cm->blue, &bbuf[index], count); 438 if (error) 439 return error; 440 441 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 442 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 443 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 444 445 r = &sc->sc_cmap_red[index]; 446 g = &sc->sc_cmap_green[index]; 447 b = &sc->sc_cmap_blue[index]; 448 449 for (i = 0; i < count; i++) { 450 mgx_write_dac(sc, index, *r, *g, *b); 451 index++; 452 r++, g++, b++; 453 } 454 return 0; 455 } 456 457 static int 458 mgx_getcmap(struct mgx_softc *sc, struct wsdisplay_cmap *cm) 459 { 460 u_int index = cm->index; 461 u_int count = cm->count; 462 int error; 463 464 if (index >= 255 || count > 256 || index + count > 256) 465 return EINVAL; 466 467 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 468 if (error) 469 return error; 470 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 471 if (error) 472 return error; 473 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 474 if (error) 475 return error; 476 477 return 0; 478 } 479 480 static int 481 mgx_wait_engine(struct mgx_softc *sc) 482 { 483 unsigned int i; 484 uint8_t stat; 485 486 for (i = 100000; i != 0; i--) { 487 stat = mgx_read_1(sc, ATR_BLT_STATUS); 488 if ((stat & (BLT_HOST_BUSY | BLT_ENGINE_BUSY)) == 0) 489 break; 490 } 491 492 return i; 493 } 494 495 static inline int 496 mgx_wait_host(struct mgx_softc *sc) 497 { 498 unsigned int i; 499 uint8_t stat; 500 501 for (i = 10000; i != 0; i--) { 502 stat = mgx_read_1(sc, ATR_BLT_STATUS); 503 if ((stat & BLT_HOST_BUSY) == 0) 504 break; 505 } 506 507 return i; 508 } 509 510 /*static inline*/ int 511 mgx_wait_fifo(struct mgx_softc *sc, unsigned int nfifo) 512 { 513 unsigned int i; 514 uint8_t stat; 515 516 for (i = 100000; i != 0; i--) { 517 stat = mgx_read_1(sc, ATR_FIFO_STATUS); 518 stat = (stat & FIFO_MASK) >> FIFO_SHIFT; 519 if (stat >= nfifo) 520 break; 521 mgx_write_1(sc, ATR_FIFO_STATUS, 0); 522 } 523 524 return i; 525 } 526 527 static void 528 mgx_setup(struct mgx_softc *sc, int depth) 529 { 530 uint32_t stride; 531 int i; 532 uint8_t reg; 533 534 /* wait for everything to go idle */ 535 if (mgx_wait_engine(sc) == 0) 536 return; 537 if (mgx_wait_fifo(sc, FIFO_AT24) == 0) 538 return; 539 540 sc->sc_buf = 0; 541 /* read name from sequencer */ 542 for (i = 0; i < 8; i++) { 543 mgx_write_vga(sc, SEQ_INDEX, i + 0x11); 544 sc->sc_name[i] = mgx_read_vga(sc, SEQ_DATA); 545 } 546 sc->sc_name[7] = 0; 547 548 reg = mgx_read_1(sc, ATR_PIXEL); 549 reg &= ~PIXEL_DEPTH_MASK; 550 551 switch (depth) { 552 case 8: 553 sc->sc_dec = DEC_DEPTH_8 << DEC_DEPTH_SHIFT; 554 reg |= PIXEL_8; 555 break; 556 case 15: 557 sc->sc_dec = DEC_DEPTH_16 << DEC_DEPTH_SHIFT; 558 reg |= PIXEL_15; 559 break; 560 case 16: 561 sc->sc_dec = DEC_DEPTH_16 << DEC_DEPTH_SHIFT; 562 reg |= PIXEL_16; 563 break; 564 case 32: 565 sc->sc_dec = DEC_DEPTH_32 << DEC_DEPTH_SHIFT; 566 reg |= PIXEL_32; 567 break; 568 default: 569 return; /* not supported */ 570 } 571 572 /* the chip wants stride in units of 8 bytes */ 573 sc->sc_stride = sc->sc_width * (depth >> 3); 574 stride = sc->sc_stride >> 3; 575 #ifdef MGX_DEBUG 576 sc->sc_height -= 150; 577 #endif 578 579 sc->sc_depth = depth; 580 581 switch (sc->sc_width) { 582 case 640: 583 sc->sc_dec |= DEC_WIDTH_640 << DEC_WIDTH_SHIFT; 584 break; 585 case 800: 586 sc->sc_dec |= DEC_WIDTH_800 << DEC_WIDTH_SHIFT; 587 break; 588 case 1024: 589 sc->sc_dec |= DEC_WIDTH_1024 << DEC_WIDTH_SHIFT; 590 break; 591 case 1152: 592 sc->sc_dec |= DEC_WIDTH_1152 << DEC_WIDTH_SHIFT; 593 break; 594 case 1280: 595 sc->sc_dec |= DEC_WIDTH_1280 << DEC_WIDTH_SHIFT; 596 break; 597 case 1600: 598 sc->sc_dec |= DEC_WIDTH_1600 << DEC_WIDTH_SHIFT; 599 break; 600 default: 601 return; /* not supported */ 602 } 603 mgx_wait_fifo(sc, 4); 604 mgx_write_1(sc, ATR_CLIP_CONTROL, 0); 605 mgx_write_1(sc, ATR_BYTEMASK, 0xff); 606 mgx_write_1(sc, ATR_PIXEL, reg); 607 mgx_write_4(sc, ATR_OFFSET, 0); 608 mgx_wait_fifo(sc, 4); 609 mgx_write_vga(sc, CRTC_INDEX, 0x13); 610 mgx_write_vga(sc, CRTC_DATA, stride & 0xff); 611 mgx_write_vga(sc, CRTC_INDEX, 0x1c); 612 mgx_write_vga(sc, CRTC_DATA, (stride & 0xf00) >> 4); 613 614 /* clean up the screen if we're switching to != 8bit */ 615 if (depth != MGX_DEPTH) 616 mgx_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 0); 617 618 mgx_wait_fifo(sc, 4); 619 /* initialize hardware cursor stuff */ 620 mgx_write_2(sc, ATR_CURSOR_ADDRESS, (sc->sc_fbsize - 1024) >> 10); 621 mgx_write_1(sc, ATR_CURSOR_ENABLE, 0); 622 sc->sc_cursor = (uint8_t *)sc->sc_fbaddr + sc->sc_fbsize - 1024; 623 memset(sc->sc_cursor, 0xf0, 1024); 624 memset(sc->sc_in, 0, sizeof(sc->sc_in)); 625 } 626 627 static void 628 mgx_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi, int he, 629 int rop) 630 { 631 struct mgx_softc *sc = cookie; 632 uint32_t dec = sc->sc_dec; 633 634 dec |= (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) | 635 (DEC_START_DIMX << DEC_START_SHIFT); 636 if (xs < xd) { 637 xs += wi - 1; 638 xd += wi - 1; 639 dec |= DEC_DIR_X_REVERSE; 640 } 641 if (ys < yd) { 642 ys += he - 1; 643 yd += he - 1; 644 dec |= DEC_DIR_Y_REVERSE; 645 } 646 mgx_wait_fifo(sc, 5); 647 mgx_write_1(sc, ATR_ROP, rop); 648 mgx_write_4(sc, ATR_DEC, dec); 649 mgx_write_4(sc, ATR_SRC_XY, (ys << 16) | xs); 650 mgx_write_4(sc, ATR_DST_XY, (yd << 16) | xd); 651 mgx_write_4(sc, ATR_WH, (he << 16) | wi); 652 } 653 654 static void 655 mgx_rectfill(void *cookie, int x, int y, int wi, int he, long fg) 656 { 657 struct mgx_softc *sc = cookie; 658 struct vcons_screen *scr = sc->vd.active; 659 uint32_t dec = sc->sc_dec; 660 uint32_t col; 661 662 if (scr == NULL) 663 return; 664 col = scr->scr_ri.ri_devcmap[fg]; 665 666 dec = sc->sc_dec; 667 dec |= (DEC_COMMAND_RECT << DEC_COMMAND_SHIFT) | 668 (DEC_START_DIMX << DEC_START_SHIFT); 669 mgx_wait_fifo(sc, 5); 670 mgx_write_1(sc, ATR_ROP, ROP_SRC); 671 mgx_write_4(sc, ATR_FG, col); 672 mgx_write_4(sc, ATR_DEC, dec); 673 mgx_write_4(sc, ATR_DST_XY, (y << 16) | x); 674 mgx_write_4(sc, ATR_WH, (he << 16) | wi); 675 } 676 677 static void 678 mgx_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 679 { 680 struct rasops_info *ri = cookie; 681 struct wsdisplay_font *font = PICK_FONT(ri, c); 682 struct vcons_screen *scr = ri->ri_hw; 683 struct mgx_softc *sc = scr->scr_cookie; 684 uint32_t fg, bg; 685 int x, y, wi, he, rv; 686 687 wi = font->fontwidth; 688 he = font->fontheight; 689 690 bg = (attr >> 16) & 0xf; 691 fg = (attr >> 24) & 0xf; 692 693 x = ri->ri_xorigin + col * wi; 694 y = ri->ri_yorigin + row * he; 695 696 if (c == 0x20) { 697 mgx_rectfill(sc, x, y, wi, he, bg); 698 if (attr & 1) 699 mgx_rectfill(sc, x, y + he - 2, wi, 1, fg); 700 return; 701 } 702 703 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 704 if (rv != GC_OK) { 705 volatile uint32_t junk; 706 707 mgx_wait_engine(sc); 708 sc->sc_putchar(cookie, row, col, c, attr & ~1); 709 if (rv == GC_ADD) { 710 /* 711 * try to make sure the glyph made it all the way to 712 * video memory before trying to blit it into the cache 713 */ 714 junk = *(uint32_t *)sc->sc_fbaddr; 715 __USE(junk); 716 glyphcache_add(&sc->sc_gc, c, x, y); 717 } 718 } 719 if (attr & 1) 720 mgx_rectfill(sc, x, y + he - 2, wi, 1, fg); 721 } 722 723 static void 724 mgx_putchar_mono(void *cookie, int row, int col, u_int c, long attr) 725 { 726 struct rasops_info *ri = cookie; 727 struct wsdisplay_font *font = PICK_FONT(ri, c); 728 struct vcons_screen *scr = ri->ri_hw; 729 struct mgx_softc *sc = scr->scr_cookie; 730 uint8_t *s, *d; 731 uint32_t fg, bg, scratch = ((sc->sc_stride * sc->sc_height) + 7) & ~7; 732 int x, y, wi, he, len, i; 733 734 wi = font->fontwidth; 735 he = font->fontheight; 736 737 bg = (attr >> 16) & 0xf; 738 fg = (attr >> 24) & 0xf; 739 740 x = ri->ri_xorigin + col * wi; 741 y = ri->ri_yorigin + row * he; 742 743 if (!CHAR_IN_FONT(c, font)) { 744 c = 0x20; 745 #ifdef MGX_DEBUG 746 bg = WSCOL_LIGHT_BLUE; 747 #endif 748 } 749 if (c == 0x20) { 750 mgx_rectfill(sc, x, y, wi, he, bg); 751 if (attr & 1) 752 mgx_rectfill(sc, x, y + he - 2, wi, 1, fg); 753 return; 754 } 755 756 mgx_wait_fifo(sc, 3); 757 mgx_write_4(sc, ATR_FG, ri->ri_devcmap[fg]); 758 mgx_write_4(sc, ATR_BG, ri->ri_devcmap[bg]); 759 mgx_write_1(sc, ATR_ROP, ROP_SRC); 760 761 /* 762 * do hardware colour expansion 763 * there has to be an upload port somewhere, since there are host blit 764 * commands, but it's not used or mentioned in the xf86-video-apm driver 765 * so for now we use the vram-to-vram blits to draw characters. 766 * stash most of the font in vram for speed, also: 767 * - the sbus-pci bridge doesn't seem to support 64bit accesses, 768 * they will cause occasional data corruption and all sorts of weird 769 * side effects, so copy font bitmaps byte-wise 770 * - at least it doesn't seem to need any kind of buffer flushing 771 * - still use rotation buffers for characters that don't fall into the 772 * 8 bit range 773 */ 774 775 len = (ri->ri_fontscale + 7) & ~7; 776 s = WSFONT_GLYPH(c, font); 777 if ((c > 32) && (c < 256)) { 778 scratch += len * c; 779 if (sc->sc_in[c] == 0) { 780 d = (uint8_t *)sc->sc_fbaddr + scratch; 781 for (i = 0; i < ri->ri_fontscale; i++) 782 d[i] = s[i]; 783 sc->sc_in[c] = 1; 784 } 785 } else { 786 sc->sc_buf = (sc->sc_buf + 1) & 7; /* rotate through 8 buffers */ 787 scratch += sc->sc_buf * len; 788 d = (uint8_t *)sc->sc_fbaddr + scratch; 789 for (i = 0; i < ri->ri_fontscale; i++) 790 d[i] = s[i]; 791 } 792 mgx_wait_fifo(sc, 5); 793 mgx_write_4(sc, ATR_DEC, sc->sc_dec | (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) | 794 (DEC_START_DIMX << DEC_START_SHIFT) | 795 DEC_SRC_LINEAR | DEC_SRC_CONTIGUOUS | DEC_MONOCHROME); 796 mgx_write_4(sc, ATR_SRC_XY, ((scratch & 0xfff000) << 4) | (scratch & 0xfff)); 797 mgx_write_4(sc, ATR_DST_XY, (y << 16) | x); 798 mgx_write_4(sc, ATR_WH, (he << 16) | wi); 799 800 if (attr & 1) 801 mgx_rectfill(sc, x, y + he - 2, wi, 1, fg); 802 } 803 804 static void 805 mgx_cursor(void *cookie, int on, int row, int col) 806 { 807 struct rasops_info *ri = cookie; 808 struct vcons_screen *scr = ri->ri_hw; 809 struct mgx_softc *sc = scr->scr_cookie; 810 int x, y, wi,he; 811 812 wi = ri->ri_font->fontwidth; 813 he = ri->ri_font->fontheight; 814 815 if (ri->ri_flg & RI_CURSOR) { 816 x = ri->ri_ccol * wi + ri->ri_xorigin; 817 y = ri->ri_crow * he + ri->ri_yorigin; 818 mgx_bitblt(sc, x, y, x, y, wi, he, ROP_INV); 819 ri->ri_flg &= ~RI_CURSOR; 820 } 821 822 ri->ri_crow = row; 823 ri->ri_ccol = col; 824 825 if (on) 826 { 827 x = ri->ri_ccol * wi + ri->ri_xorigin; 828 y = ri->ri_crow * he + ri->ri_yorigin; 829 mgx_bitblt(sc, x, y, x, y, wi, he, ROP_INV); 830 ri->ri_flg |= RI_CURSOR; 831 } 832 } 833 834 static void 835 mgx_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 836 { 837 struct rasops_info *ri = cookie; 838 struct vcons_screen *scr = ri->ri_hw; 839 struct mgx_softc *sc = scr->scr_cookie; 840 int32_t xs, xd, y, width, height; 841 842 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 843 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 844 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 845 width = ri->ri_font->fontwidth * ncols; 846 height = ri->ri_font->fontheight; 847 mgx_bitblt(sc, xs, y, xd, y, width, height, ROP_SRC); 848 } 849 850 static void 851 mgx_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 852 { 853 struct rasops_info *ri = cookie; 854 struct vcons_screen *scr = ri->ri_hw; 855 struct mgx_softc *sc = scr->scr_cookie; 856 int32_t x, y, width, height, bg; 857 858 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 859 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 860 width = ri->ri_font->fontwidth * ncols; 861 height = ri->ri_font->fontheight; 862 bg = (fillattr >> 16) & 0xff; 863 mgx_rectfill(sc, x, y, width, height, bg); 864 } 865 866 static void 867 mgx_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 868 { 869 struct rasops_info *ri = cookie; 870 struct vcons_screen *scr = ri->ri_hw; 871 struct mgx_softc *sc = scr->scr_cookie; 872 int32_t x, ys, yd, width, height; 873 874 x = ri->ri_xorigin; 875 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 876 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 877 width = ri->ri_emuwidth; 878 height = ri->ri_font->fontheight * nrows; 879 mgx_bitblt(sc, x, ys, x, yd, width, height, ROP_SRC); 880 } 881 882 static void 883 mgx_eraserows(void *cookie, int row, int nrows, long fillattr) 884 { 885 struct rasops_info *ri = cookie; 886 struct vcons_screen *scr = ri->ri_hw; 887 struct mgx_softc *sc = scr->scr_cookie; 888 int32_t x, y, width, height, bg; 889 890 if ((row == 0) && (nrows == ri->ri_rows)) { 891 x = y = 0; 892 width = ri->ri_width; 893 height = ri->ri_height; 894 } else { 895 x = ri->ri_xorigin; 896 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 897 width = ri->ri_emuwidth; 898 height = ri->ri_font->fontheight * nrows; 899 } 900 bg = (fillattr >> 16) & 0xff; 901 mgx_rectfill(sc, x, y, width, height, bg); 902 } 903 904 static void 905 mgx_adapt(struct vcons_screen *scr, void *cookie) 906 { 907 struct mgx_softc *sc = cookie; 908 memset(sc->sc_in, 0, sizeof(sc->sc_in)); 909 glyphcache_adapt(scr, &sc->sc_gc); 910 } 911 912 static void 913 mgx_init_screen(void *cookie, struct vcons_screen *scr, 914 int existing, long *defattr) 915 { 916 struct mgx_softc *sc = cookie; 917 struct rasops_info *ri = &scr->scr_ri; 918 919 ri->ri_depth = sc->sc_depth; 920 ri->ri_width = sc->sc_width; 921 ri->ri_height = sc->sc_height; 922 ri->ri_stride = sc->sc_stride; 923 ri->ri_flg = RI_CENTER | RI_ENABLE_ALPHA; 924 925 if (ri->ri_depth == 8) 926 ri->ri_flg |= RI_8BIT_IS_RGB; 927 928 #ifdef MGX_NOACCEL 929 scr->scr_flags |= VCONS_DONT_READ; 930 #endif 931 scr->scr_flags |= VCONS_LOADFONT; 932 933 ri->ri_rnum = 8; 934 ri->ri_rpos = 0; 935 ri->ri_gnum = 8; 936 ri->ri_gpos = 8; 937 ri->ri_bnum = 8; 938 ri->ri_bpos = 16; 939 940 ri->ri_bits = sc->sc_fbaddr; 941 942 rasops_init(ri, 0, 0); 943 944 ri->ri_caps = WSSCREEN_REVERSE | WSSCREEN_WSCOLORS | 945 WSSCREEN_UNDERLINE | WSSCREEN_RESIZE; 946 947 rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight, 948 ri->ri_width / ri->ri_font->fontwidth); 949 950 ri->ri_hw = scr; 951 952 #ifdef MGX_NOACCEL 953 if (0) 954 #endif 955 { 956 if (FONT_IS_ALPHA(ri->ri_font)) { 957 sc->sc_putchar = ri->ri_ops.putchar; 958 ri->ri_ops.putchar = mgx_putchar_aa; 959 } else { 960 ri->ri_ops.putchar = mgx_putchar_mono; 961 } 962 ri->ri_ops.cursor = mgx_cursor; 963 ri->ri_ops.copyrows = mgx_copyrows; 964 ri->ri_ops.eraserows = mgx_eraserows; 965 ri->ri_ops.copycols = mgx_copycols; 966 ri->ri_ops.erasecols = mgx_erasecols; 967 } 968 } 969 970 static int 971 mgx_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 972 struct lwp *l) 973 { 974 struct vcons_data *vd = v; 975 struct mgx_softc *sc = vd->cookie; 976 struct wsdisplay_fbinfo *wdf; 977 struct vcons_screen *ms = vd->active; 978 979 switch (cmd) { 980 case WSDISPLAYIO_GTYPE: 981 *(u_int *)data = WSDISPLAY_TYPE_MGX; 982 return 0; 983 984 case WSDISPLAYIO_GINFO: 985 wdf = (void *)data; 986 wdf->height = sc->sc_height; 987 wdf->width = sc->sc_width; 988 wdf->depth = 8; 989 wdf->cmsize = 256; 990 return 0; 991 992 case FBIOGTYPE: 993 *(struct fbtype *)data = sc->sc_fb.fb_type; 994 break; 995 996 case FBIOGATTR: 997 #define fba ((struct fbgattr *)data) 998 fba->real_type = sc->sc_fb.fb_type.fb_type; 999 fba->owner = 0; /* XXX ??? */ 1000 fba->fbtype = sc->sc_fb.fb_type; 1001 fba->sattr.flags = 0; 1002 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 1003 fba->sattr.dev_specific[0] = -1; 1004 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 1005 fba->emu_types[1] = -1; 1006 #undef fba 1007 break; 1008 case FBIOGVIDEO: 1009 case WSDISPLAYIO_GVIDEO: 1010 *(int *)data = sc->sc_video; 1011 return 0; 1012 1013 case WSDISPLAYIO_SVIDEO: 1014 case FBIOSVIDEO: 1015 mgx_set_video(sc, *(int *)data); 1016 return 0; 1017 1018 case WSDISPLAYIO_LINEBYTES: 1019 { 1020 int *ret = (int *)data; 1021 *ret = sc->sc_stride; 1022 } 1023 return 0; 1024 1025 case WSDISPLAYIO_SMODE: 1026 { 1027 int new_mode = *(int*)data; 1028 if (new_mode != sc->sc_mode) 1029 { 1030 sc->sc_mode = new_mode; 1031 if (new_mode == WSDISPLAYIO_MODE_EMUL) 1032 { 1033 mgx_setup(sc, MGX_DEPTH); 1034 glyphcache_wipe(&sc->sc_gc); 1035 mgx_init_palette(sc); 1036 vcons_redraw_screen(ms); 1037 } else { 1038 mgx_setup(sc, 32); 1039 mgx_init_palette(sc); 1040 } 1041 } 1042 } 1043 return 0; 1044 1045 case WSDISPLAYIO_GETCMAP: 1046 return mgx_getcmap(sc, (struct wsdisplay_cmap *)data); 1047 1048 case WSDISPLAYIO_PUTCMAP: 1049 return mgx_putcmap(sc, (struct wsdisplay_cmap *)data); 1050 1051 case WSDISPLAYIO_GCURPOS: 1052 { 1053 struct wsdisplay_curpos *cp = (void *)data; 1054 1055 cp->x = sc->sc_cursor_x; 1056 cp->y = sc->sc_cursor_y; 1057 } 1058 return 0; 1059 1060 case WSDISPLAYIO_SCURPOS: 1061 { 1062 struct wsdisplay_curpos *cp = (void *)data; 1063 1064 sc->sc_cursor_x = cp->x; 1065 sc->sc_cursor_y = cp->y; 1066 mgx_set_cursor(sc); 1067 } 1068 return 0; 1069 1070 case WSDISPLAYIO_GCURMAX: 1071 { 1072 struct wsdisplay_curpos *cp = (void *)data; 1073 1074 cp->x = 64; 1075 cp->y = 64; 1076 } 1077 return 0; 1078 1079 case WSDISPLAYIO_SCURSOR: 1080 { 1081 struct wsdisplay_cursor *cursor = (void *)data; 1082 1083 return mgx_do_cursor(sc, cursor); 1084 } 1085 case WSDISPLAYIO_GET_FBINFO: 1086 { 1087 struct wsdisplayio_fbinfo *fbi = data; 1088 1089 fbi->fbi_fbsize = sc->sc_fbsize - 1024; 1090 fbi->fbi_width = sc->sc_width; 1091 fbi->fbi_height = sc->sc_height; 1092 fbi->fbi_bitsperpixel = sc->sc_depth; 1093 fbi->fbi_stride = sc->sc_stride; 1094 fbi->fbi_pixeltype = WSFB_RGB; 1095 fbi->fbi_subtype.fbi_rgbmasks.red_offset = 8; 1096 fbi->fbi_subtype.fbi_rgbmasks.red_size = 8; 1097 fbi->fbi_subtype.fbi_rgbmasks.green_offset = 16; 1098 fbi->fbi_subtype.fbi_rgbmasks.green_size = 8; 1099 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 24; 1100 fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8; 1101 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0; 1102 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 8; 1103 return 0; 1104 } 1105 } 1106 return EPASSTHROUGH; 1107 } 1108 1109 static paddr_t 1110 mgx_mmap(void *v, void *vs, off_t offset, int prot) 1111 { 1112 struct vcons_data *vd = v; 1113 struct mgx_softc *sc = vd->cookie; 1114 1115 /* regular fb mapping at 0 */ 1116 if ((offset >= 0) && (offset < sc->sc_fbsize)) { 1117 return bus_space_mmap(sc->sc_tag, sc->sc_paddr, 1118 offset, prot, BUS_SPACE_MAP_LINEAR); 1119 } 1120 1121 /* 1122 * Blitter registers at 0x80000000, only in mapped mode. 1123 * Restrict to root, even though I'm fairly sure the DMA engine lives 1124 * elsewhere ( and isn't documented anyway ) 1125 */ 1126 if (kauth_authorize_machdep(kauth_cred_get(), 1127 KAUTH_MACHDEP_UNMANAGEDMEM, 1128 NULL, NULL, NULL, NULL) != 0) { 1129 aprint_normal("%s: mmap() rejected.\n", 1130 device_xname(sc->sc_dev)); 1131 return -1; 1132 } 1133 if ((sc->sc_mode == WSDISPLAYIO_MODE_MAPPED) && 1134 (offset >= 0x80000000) && (offset < 0x80001000)) { 1135 return bus_space_mmap(sc->sc_tag, sc->sc_rpaddr, 1136 offset, prot, BUS_SPACE_MAP_LINEAR); 1137 } 1138 return -1; 1139 } 1140 1141 static int 1142 mgx_do_cursor(struct mgx_softc *sc, struct wsdisplay_cursor *cur) 1143 { 1144 int i; 1145 if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1146 1147 if (cur->enable) { 1148 mgx_set_cursor(sc); 1149 mgx_write_1(sc, ATR_CURSOR_ENABLE, 1); 1150 } else { 1151 mgx_write_1(sc, ATR_CURSOR_ENABLE, 0); 1152 } 1153 } 1154 if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1155 1156 sc->sc_hotspot_x = cur->hot.x; 1157 sc->sc_hotspot_y = cur->hot.y; 1158 mgx_set_cursor(sc); 1159 } 1160 if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1161 1162 sc->sc_cursor_x = cur->pos.x; 1163 sc->sc_cursor_y = cur->pos.y; 1164 mgx_set_cursor(sc); 1165 } 1166 if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1167 int cnt = uimin(2, cur->cmap.count); 1168 uint8_t c; 1169 uint8_t r[2], g[2], b[2]; 1170 1171 copyin(cur->cmap.red, r, cnt); 1172 copyin(cur->cmap.green, g, cnt); 1173 copyin(cur->cmap.blue, b, cnt); 1174 1175 for (i = 0; i < cnt; i++) { 1176 c = r[i] & 0xe0; 1177 c |= (g[i] & 0xe0) >> 3; 1178 c |= (b[i] & 0xc0) >> 6; 1179 mgx_write_1(sc, ATR_CURSOR_FG + i, c); 1180 } 1181 } 1182 if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1183 int j; 1184 uint8_t *fb = sc->sc_cursor; 1185 uint8_t temp; 1186 uint8_t im, ma, px; 1187 1188 for (i = 0; i < 512; i++) { 1189 temp = 0; 1190 copyin(&cur->image[i], &im, 1); 1191 copyin(&cur->mask[i], &ma, 1); 1192 for (j = 0; j < 4; j++) { 1193 temp >>= 2; 1194 px = (ma & 1) ? 0 : 0x80; 1195 if (px == 0) 1196 px |= (im & 1) ? 0 : 0x40; 1197 temp |= px; 1198 im >>= 1; 1199 ma >>= 1; 1200 } 1201 *fb = temp; 1202 fb++; 1203 temp = 0; 1204 for (j = 0; j < 4; j++) { 1205 temp >>= 2; 1206 px = (ma & 1) ? 0 : 0x80; 1207 if (px == 0) 1208 px |= (im & 1) ? 0 : 0x40; 1209 temp |= px; 1210 im >>= 1; 1211 ma >>= 1; 1212 } 1213 *fb = temp; 1214 fb++; 1215 } 1216 } 1217 return 0; 1218 } 1219 1220 static void 1221 mgx_set_cursor(struct mgx_softc *sc) 1222 { 1223 uint32_t reg; 1224 uint16_t hot; 1225 1226 reg = (sc->sc_cursor_y << 16) | (sc->sc_cursor_x & 0xffff); 1227 mgx_write_4(sc, ATR_CURSOR_POSITION, reg); 1228 hot = (sc->sc_hotspot_y << 8) | (sc->sc_hotspot_x & 0xff); 1229 mgx_write_2(sc, ATR_CURSOR_HOTSPOT, hot); 1230 } 1231 1232 static void 1233 mgx_set_video(struct mgx_softc *sc, int v) 1234 { 1235 uint8_t reg; 1236 1237 if (sc->sc_video == v) 1238 return; 1239 1240 sc->sc_video = v; 1241 reg = mgx_read_1(sc, ATR_DPMS); 1242 1243 if (v == WSDISPLAYIO_VIDEO_ON) { 1244 reg &= ~DPMS_SYNC_DISABLE_ALL; 1245 } else { 1246 reg |= DPMS_SYNC_DISABLE_ALL; 1247 } 1248 mgx_write_1(sc, ATR_DPMS, reg); 1249 } 1250 1251 /* Sun fb dev goop */ 1252 static void 1253 mgx_unblank(device_t dev) 1254 { 1255 struct mgx_softc *sc = device_private(dev); 1256 1257 mgx_set_video(sc, WSDISPLAYIO_VIDEO_ON); 1258 } 1259 1260 paddr_t 1261 mgxmmap(dev_t dev, off_t offset, int prot) 1262 { 1263 struct mgx_softc *sc = device_lookup_private(&mgx_cd, minor(dev)); 1264 1265 /* regular fb mapping at 0 */ 1266 if ((offset >= 0) && (offset < sc->sc_fbsize)) { 1267 return bus_space_mmap(sc->sc_tag, sc->sc_paddr, 1268 offset, prot, BUS_SPACE_MAP_LINEAR); 1269 } 1270 1271 /* 1272 * Blitter registers at 0x80000000, only in mapped mode. 1273 * Restrict to root, even though I'm fairly sure the DMA engine lives 1274 * elsewhere ( and isn't documented anyway ) 1275 */ 1276 if (kauth_authorize_machdep(kauth_cred_get(), 1277 KAUTH_MACHDEP_UNMANAGEDMEM, 1278 NULL, NULL, NULL, NULL) != 0) { 1279 aprint_normal("%s: mmap() rejected.\n", 1280 device_xname(sc->sc_dev)); 1281 return -1; 1282 } 1283 if ((sc->sc_mode == WSDISPLAYIO_MODE_MAPPED) && 1284 (offset >= 0x80000000) && (offset < 0x80001000)) { 1285 return bus_space_mmap(sc->sc_tag, sc->sc_rpaddr, 1286 offset, prot, BUS_SPACE_MAP_LINEAR); 1287 } 1288 return -1; 1289 } 1290 1291 int 1292 mgxopen(dev_t dev, int flags, int mode, struct lwp *l) 1293 { 1294 device_t dv = device_lookup(&mgx_cd, minor(dev)); 1295 struct mgx_softc *sc = device_private(dv); 1296 1297 if (dv == NULL) 1298 return ENXIO; 1299 if (sc->sc_mode == WSDISPLAYIO_MODE_MAPPED) 1300 return 0; 1301 sc->sc_mode = WSDISPLAYIO_MODE_MAPPED; 1302 mgx_setup(sc, 32); 1303 mgx_init_palette(sc); 1304 return 0; 1305 } 1306 1307 int 1308 mgxclose(dev_t dev, int flags, int mode, struct lwp *l) 1309 { 1310 device_t dv = device_lookup(&mgx_cd, minor(dev)); 1311 struct mgx_softc *sc = device_private(dv); 1312 struct vcons_screen *ms = sc->vd.active; 1313 1314 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 1315 return 0; 1316 1317 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 1318 1319 mgx_setup(sc, MGX_DEPTH); 1320 glyphcache_wipe(&sc->sc_gc); 1321 mgx_init_palette(sc); 1322 if (ms != NULL) { 1323 vcons_redraw_screen(ms); 1324 } 1325 return 0; 1326 } 1327 1328 int 1329 mgxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 1330 { 1331 struct mgx_softc *sc = device_lookup_private(&mgx_cd, minor(dev)); 1332 1333 return mgx_ioctl(&sc->vd, NULL, cmd, data, flags, l); 1334 } 1335