1 /* $OpenBSD: vga_pci.c,v 1.67 2011/04/14 21:04:29 oga Exp $ */ 2 /* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 2001 Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Frank van der Linden for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 /* 39 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 40 * All rights reserved. 41 * 42 * Author: Chris G. Demetriou 43 * 44 * Permission to use, copy, modify and distribute this software and 45 * its documentation is hereby granted, provided that both the copyright 46 * notice and this permission notice appear in all copies of the 47 * software, derivative works or modified versions, and any portions 48 * thereof, and that both notices appear in supporting documentation. 49 * 50 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 51 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 52 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 53 * 54 * Carnegie Mellon requests users of this software to return to 55 * 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 57 * School of Computer Science 58 * Carnegie Mellon University 59 * Pittsburgh PA 15213-3890 60 * 61 * any improvements or extensions that they make and grant Carnegie the 62 * rights to redistribute these changes. 63 */ 64 65 #include "vga.h" 66 #if defined(__i386__) || defined(__amd64__) 67 #include "acpi.h" 68 #endif 69 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/kernel.h> 73 #include <sys/device.h> 74 #include <sys/malloc.h> 75 #include <sys/agpio.h> 76 77 #include <uvm/uvm.h> 78 79 #include <machine/bus.h> 80 81 #include <dev/pci/pcireg.h> 82 #include <dev/pci/pcivar.h> 83 #include <dev/pci/pcidevs.h> 84 85 #include <dev/pci/agpvar.h> 86 87 #include <dev/ic/mc6845reg.h> 88 #include <dev/ic/pcdisplayvar.h> 89 #include <dev/ic/vgareg.h> 90 #include <dev/ic/vgavar.h> 91 #include <dev/pci/vga_pcivar.h> 92 93 94 #include <dev/wscons/wsconsio.h> 95 #include <dev/wscons/wsdisplayvar.h> 96 97 #ifdef X86EMU 98 #include <machine/vga_post.h> 99 #endif 100 101 #ifdef VESAFB 102 #include <dev/vesa/vesabiosvar.h> 103 #endif 104 105 #include "intagp.h" 106 #include "drm.h" 107 108 int vga_pci_match(struct device *, void *, void *); 109 void vga_pci_attach(struct device *, struct device *, void *); 110 int vga_pci_activate(struct device *, int); 111 paddr_t vga_pci_mmap(void* v, off_t off, int prot); 112 void vga_pci_bar_init(struct vga_pci_softc *, struct pci_attach_args *); 113 114 #if NINTAGP > 0 115 int intagpsubmatch(struct device *, void *, void *); 116 int intagp_print(void *, const char *); 117 #endif 118 #if NDRM > 0 119 int drmsubmatch(struct device *, void *, void *); 120 int vga_drm_print(void *, const char *); 121 #endif 122 123 #ifdef VESAFB 124 int vesafb_putcmap(struct vga_pci_softc *, struct wsdisplay_cmap *); 125 int vesafb_getcmap(struct vga_pci_softc *, struct wsdisplay_cmap *); 126 #endif 127 128 #if !defined(SMALL_KERNEL) && NACPI > 0 129 void vga_save_state(struct vga_pci_softc *); 130 void vga_restore_state(struct vga_pci_softc *); 131 #endif 132 133 134 /* 135 * Function pointers for wsconsctl parameter handling. 136 * XXX These should be per-softc, but right now we only attach 137 * XXX a single vga@pci instance, so this will do. 138 */ 139 int (*ws_get_param)(struct wsdisplay_param *); 140 int (*ws_set_param)(struct wsdisplay_param *); 141 142 143 struct cfattach vga_pci_ca = { 144 sizeof(struct vga_pci_softc), vga_pci_match, vga_pci_attach, 145 NULL, vga_pci_activate 146 }; 147 148 #if !defined(SMALL_KERNEL) && NACPI > 0 149 int vga_pci_do_post; 150 extern int do_real_mode_post; 151 152 struct vga_device_description { 153 u_int16_t rval[4]; 154 u_int16_t rmask[4]; 155 char vga_pci_post; 156 char real_mode_post; 157 }; 158 159 static const struct vga_device_description vga_devs[] = { 160 /* 161 * Header description: 162 * 163 * First entry is a list of the pci video information in the following 164 * order: VENDOR, PRODUCT, SUBVENDOR, SUBPRODUCT 165 * 166 * The next entry is a list of corresponding masks. 167 * 168 * Finally the last two values set what resume should do, repost with 169 * vga_pci (i.e. the x86emulator) or with a locore call to the video 170 * bios. 171 */ 172 { /* All machines with Intel US15W (until more evidence) */ 173 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_US15W_IGD, 174 0x0000, 0x0000 }, 175 { 0xffff, 0xffff, 0x0000, 0x0000 }, 1, 0 176 }, 177 { /* All machines with Intel US15L (until more evidence) */ 178 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_US15L_IGD, 179 0x0000, 0x0000 }, 180 { 0xffff, 0xffff, 0x0000, 0x0000 }, 1, 0 181 }, 182 183 { /* Anything with on-die intel graphics, for now */ 184 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ARRANDALE_IGD, 185 0x0000, 0x0000 }, 186 { 0xffff, 0xffff, 0x0000, 0x0000 }, 1, 0 187 }, 188 189 { /* Anything with on-die intel graphics, for now */ 190 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CLARKDALE_IGD, 191 0x0000, 0x0000 }, 192 { 0xffff, 0xffff, 0x0000, 0x0000 }, 1, 0 193 }, 194 195 { /* All ATI video until further notice */ 196 { PCI_VENDOR_ATI, 0x0000, 197 0x0000, 0x0000 }, 198 { 0xffff, 0x0000, 0x0000, 0x0000}, 1, 0 199 }, 200 }; 201 #endif 202 203 int 204 vga_pci_match(struct device *parent, void *match, void *aux) 205 { 206 struct pci_attach_args *pa = aux; 207 208 if (DEVICE_IS_VGA_PCI(pa->pa_class) == 0) 209 return (0); 210 211 /* check whether it is disabled by firmware */ 212 if ((pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) 213 & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) 214 != (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) 215 return (0); 216 217 /* If it's the console, we have a winner! */ 218 if (vga_is_console(pa->pa_iot, WSDISPLAY_TYPE_PCIVGA)) 219 return (1); 220 221 /* 222 * If we might match, make sure that the card actually looks OK. 223 */ 224 if (!vga_common_probe(pa->pa_iot, pa->pa_memt)) 225 return (0); 226 227 return (1); 228 } 229 230 void 231 vga_pci_attach(struct device *parent, struct device *self, void *aux) 232 { 233 struct pci_attach_args *pa = aux; 234 pcireg_t reg; 235 struct vga_pci_softc *sc = (struct vga_pci_softc *)self; 236 237 #if !defined(SMALL_KERNEL) && NACPI > 0 238 int prod, vend, subid, subprod, subvend, i; 239 #endif 240 241 /* 242 * Enable bus master; X might need this for accelerated graphics. 243 */ 244 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 245 reg |= PCI_COMMAND_MASTER_ENABLE; 246 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); 247 248 #ifdef VESAFB 249 if (vesabios_softc != NULL && vesabios_softc->sc_nmodes > 0) { 250 sc->sc_textmode = vesafb_get_mode(sc); 251 printf(", vesafb\n"); 252 sc->sc_vc = vga_extended_attach(self, pa->pa_iot, pa->pa_memt, 253 WSDISPLAY_TYPE_PCIVGA, vga_pci_mmap); 254 return; 255 } 256 #endif 257 printf("\n"); 258 sc->sc_vc = vga_common_attach(self, pa->pa_iot, pa->pa_memt, 259 WSDISPLAY_TYPE_PCIVGA); 260 261 vga_pci_bar_init(sc, pa); 262 263 #if !defined(SMALL_KERNEL) && NACPI > 0 264 265 #ifdef X86EMU 266 if ((sc->sc_posth = vga_post_init(pa->pa_bus, pa->pa_device, 267 pa->pa_function)) == NULL) 268 printf("couldn't set up vga POST handler\n"); 269 #endif 270 271 vend = PCI_VENDOR(pa->pa_id); 272 prod = PCI_PRODUCT(pa->pa_id); 273 subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 274 subvend = PCI_VENDOR(subid); 275 subprod = PCI_PRODUCT(subid); 276 277 for (i = 0; i < nitems(vga_devs); i++) 278 if ((vend & vga_devs[i].rmask[0]) == vga_devs[i].rval[0] && 279 (prod & vga_devs[i].rmask[1]) == vga_devs[i].rval[1] && 280 (subvend & vga_devs[i].rmask[2]) == vga_devs[i].rval[2] && 281 (subprod & vga_devs[i].rmask[3]) == vga_devs[i].rval[3]) { 282 vga_pci_do_post = vga_devs[i].vga_pci_post; 283 if (sc->sc_dev.dv_unit == 0) /* main screen only */ 284 do_real_mode_post = vga_devs[i].real_mode_post; 285 break; 286 } 287 #endif 288 289 #if NINTAGP > 0 290 /* 291 * attach intagp here instead of pchb so it can share mappings 292 * with the DRM. 293 */ 294 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL) { 295 config_found_sm(self, aux, intagp_print, intagpsubmatch); 296 297 } 298 #endif 299 300 #if NDRM > 0 301 config_found_sm(self, aux, NULL, drmsubmatch); 302 #endif 303 } 304 305 int 306 vga_pci_activate(struct device *self, int act) 307 { 308 int rv = 0; 309 310 #if !defined(SMALL_KERNEL) && NACPI > 0 311 struct vga_pci_softc *sc = (struct vga_pci_softc *)self; 312 #endif 313 314 switch (act) { 315 case DVACT_QUIESCE: 316 rv = config_activate_children(self, act); 317 break; 318 case DVACT_SUSPEND: 319 rv = config_activate_children(self, act); 320 #if !defined(SMALL_KERNEL) && NACPI > 0 321 /* 322 * Save the common vga state. This should theoretically only 323 * be necessary if we intend to POST, but it is preferrable 324 * to do it unconditionnaly, as many systems do not restore 325 * this state correctly upon resume. 326 */ 327 vga_save_state(sc); 328 #endif 329 break; 330 case DVACT_RESUME: 331 #if !defined(SMALL_KERNEL) && NACPI > 0 332 #if defined (X86EMU) 333 if (vga_pci_do_post) { 334 #ifdef obnoxious 335 printf("%s: reposting video using BIOS. Is this necessary?\n", 336 sc->sc_dev.dv_xname); 337 #endif 338 vga_post_call(sc->sc_posth); 339 } 340 #endif 341 vga_restore_state(sc); 342 #endif 343 rv = config_activate_children(self, act); 344 break; 345 } 346 347 return (rv); 348 } 349 350 #if NINTAGP > 0 351 int 352 intagpsubmatch(struct device *parent, void *match, void *aux) 353 { 354 extern struct cfdriver intagp_cd; 355 struct cfdata *cf = match; 356 357 /* only allow intagp to attach */ 358 if (cf->cf_driver == &intagp_cd) 359 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 360 return (0); 361 } 362 363 int 364 intagp_print(void *vaa, const char *pnp) 365 { 366 if (pnp) 367 printf("intagp at %s", pnp); 368 return (UNCONF); 369 } 370 #endif 371 372 #if NDRM > 0 373 int 374 drmsubmatch(struct device *parent, void *match, void *aux) 375 { 376 struct cfdata *cf = match; 377 struct cfdriver *cd; 378 size_t len = 0; 379 char *sm; 380 381 cd = cf->cf_driver; 382 383 /* is this a *drm device? */ 384 len = strlen(cd->cd_name); 385 sm = cd->cd_name + len - 3; 386 if (strncmp(sm, "drm", 3) == 0) 387 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 388 389 return (0); 390 } 391 #endif 392 393 paddr_t 394 vga_pci_mmap(void *v, off_t off, int prot) 395 { 396 #ifdef VESAFB 397 struct vga_config *vc = (struct vga_config *)v; 398 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc; 399 400 if (sc->sc_mode == WSDISPLAYIO_MODE_DUMBFB) { 401 if (off < 0 || off > vesabios_softc->sc_size) 402 return (-1); 403 return (sc->sc_base + off); 404 } 405 #endif 406 return -1; 407 } 408 409 int 410 vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, 411 pci_chipset_tag_t pc, int bus, int device, int function) 412 { 413 return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0)); 414 } 415 416 int 417 vga_pci_ioctl(void *v, u_long cmd, caddr_t addr, int flag, struct proc *pb) 418 { 419 int error = 0; 420 #ifdef VESAFB 421 struct vga_config *vc = (struct vga_config *)v; 422 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc; 423 struct wsdisplay_fbinfo *wdf; 424 struct wsdisplay_gfx_mode *gfxmode; 425 int mode; 426 #endif 427 428 switch (cmd) { 429 #ifdef VESAFB 430 case WSDISPLAYIO_SMODE: 431 mode = *(u_int *)addr; 432 switch (mode) { 433 case WSDISPLAYIO_MODE_EMUL: 434 /* back to text mode */ 435 vesafb_set_mode(sc, sc->sc_textmode); 436 sc->sc_mode = mode; 437 break; 438 case WSDISPLAYIO_MODE_DUMBFB: 439 if (sc->sc_gfxmode == -1) 440 return (-1); 441 vesafb_set_mode(sc, sc->sc_gfxmode); 442 sc->sc_mode = mode; 443 break; 444 default: 445 error = -1; 446 } 447 break; 448 case WSDISPLAYIO_GINFO: 449 if (sc->sc_gfxmode == -1) 450 return (-1); 451 wdf = (void *)addr; 452 wdf->height = sc->sc_height; 453 wdf->width = sc->sc_width; 454 wdf->depth = sc->sc_depth; 455 wdf->cmsize = 256; 456 break; 457 458 case WSDISPLAYIO_LINEBYTES: 459 if (sc->sc_gfxmode == -1) 460 return (-1); 461 *(u_int *)addr = sc->sc_linebytes; 462 break; 463 464 case WSDISPLAYIO_SVIDEO: 465 case WSDISPLAYIO_GVIDEO: 466 break; 467 case WSDISPLAYIO_GETCMAP: 468 if (sc->sc_depth == 8) 469 error = vesafb_getcmap(sc, 470 (struct wsdisplay_cmap *)addr); 471 break; 472 473 case WSDISPLAYIO_PUTCMAP: 474 if (sc->sc_depth == 8) 475 error = vesafb_putcmap(sc, 476 (struct wsdisplay_cmap *)addr); 477 break; 478 479 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 480 *(int *)addr = vesafb_get_supported_depth(sc); 481 break; 482 483 case WSDISPLAYIO_SETGFXMODE: 484 gfxmode = (struct wsdisplay_gfx_mode *)addr; 485 sc->sc_gfxmode = vesafb_find_mode(sc, gfxmode->width, 486 gfxmode->height, gfxmode->depth); 487 if (sc->sc_gfxmode == -1) 488 error = -1; 489 break; 490 491 #endif 492 case WSDISPLAYIO_GETPARAM: 493 if (ws_get_param != NULL) 494 return (*ws_get_param)((struct wsdisplay_param *)addr); 495 else 496 error = ENOTTY; 497 break; 498 case WSDISPLAYIO_SETPARAM: 499 if (ws_set_param != NULL) 500 return (*ws_set_param)((struct wsdisplay_param *)addr); 501 else 502 error = ENOTTY; 503 break; 504 default: 505 error = ENOTTY; 506 } 507 508 return (error); 509 } 510 511 #ifdef notyet 512 void 513 vga_pci_close(void *v) 514 { 515 } 516 #endif 517 518 /* 519 * Prepare dev->bars to be used for information. we do this at startup 520 * so we can do the whole array at once, dealing with 64-bit BARs correctly. 521 */ 522 void 523 vga_pci_bar_init(struct vga_pci_softc *dev, struct pci_attach_args *pa) 524 { 525 pcireg_t type; 526 int addr = PCI_MAPREG_START, i = 0; 527 memcpy(&dev->pa, pa, sizeof(dev->pa)); 528 529 while (i < VGA_PCI_MAX_BARS) { 530 dev->bars[i] = malloc(sizeof((*dev->bars[i])), M_DEVBUF, 531 M_NOWAIT | M_ZERO); 532 if (dev->bars[i] == NULL) { 533 return; 534 } 535 536 dev->bars[i]->addr = addr; 537 538 type = dev->bars[i]->maptype = pci_mapreg_type(pa->pa_pc, 539 pa->pa_tag, addr); 540 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, addr, 541 dev->bars[i]->maptype, &dev->bars[i]->base, 542 &dev->bars[i]->maxsize, &dev->bars[i]->flags) != 0) { 543 free(dev->bars[i], M_DEVBUF); 544 dev->bars[i] = NULL; 545 } 546 547 if (type == PCI_MAPREG_MEM_TYPE_64BIT) { 548 addr += 8; 549 i += 2; 550 } else { 551 addr += 4; 552 i++; 553 } 554 } 555 } 556 557 /* 558 * Get the vga_pci_bar struct for the address in question. returns NULL if 559 * invalid BAR is passed. 560 */ 561 struct vga_pci_bar* 562 vga_pci_bar_info(struct vga_pci_softc *dev, int no) 563 { 564 if (dev == NULL || no >= VGA_PCI_MAX_BARS) 565 return (NULL); 566 return (dev->bars[no]); 567 } 568 569 /* 570 * map the BAR in question, returning the vga_pci_bar struct in case any more 571 * processing needs to be done. Returns NULL on failure. Can be called multiple 572 * times. 573 */ 574 struct vga_pci_bar* 575 vga_pci_bar_map(struct vga_pci_softc *dev, int addr, bus_size_t size, 576 int busflags) 577 { 578 struct vga_pci_bar *bar = NULL; 579 int i; 580 581 if (dev == NULL) 582 return (NULL); 583 584 for (i = 0; i < VGA_PCI_MAX_BARS; i++) { 585 if (dev->bars[i] && dev->bars[i]->addr == addr) { 586 bar = dev->bars[i]; 587 break; 588 } 589 } 590 if (bar == NULL) { 591 printf("vga_pci_bar_map: given invalid address 0x%x\n", addr); 592 return (NULL); 593 } 594 595 if (bar->mapped == 0) { 596 if (pci_mapreg_map(&dev->pa, bar->addr, bar->maptype, 597 bar->flags | busflags, &bar->bst, &bar->bsh, NULL, 598 &bar->size, size)) { 599 printf("vga_pci_bar_map: can't map bar 0x%x\n", addr); 600 return (NULL); 601 } 602 } 603 604 bar->mapped++; 605 return (bar); 606 } 607 608 /* 609 * "unmap" the BAR referred to by argument. If more than one place has mapped it 610 * we just decrement the reference counter so nothing untoward happens. 611 */ 612 void 613 vga_pci_bar_unmap(struct vga_pci_bar *bar) 614 { 615 if (bar != NULL && bar->mapped != 0) { 616 if (--bar->mapped == 0) 617 bus_space_unmap(bar->bst, bar->bsh, bar->size); 618 } 619 } 620 621 #if !defined(SMALL_KERNEL) && NACPI > 0 622 void 623 vga_save_state(struct vga_pci_softc *sc) 624 { 625 struct vga_config *vc = sc->sc_vc; 626 struct vga_handle *vh; 627 struct vgascreen *scr; 628 size_t i; 629 char *buf; 630 631 if (vc == NULL) 632 return; 633 634 vh = &vc->hdl; 635 636 /* 637 * Save sequencer registers 638 */ 639 vga_ts_write(vh, syncreset, 1); /* stop sequencer */ 640 buf = (char *)&sc->sc_save_ts; 641 *buf++ = 0; 642 for (i = 1; i < sizeof(sc->sc_save_ts); i++) 643 *buf++ = _vga_ts_read(vh, i); 644 vga_ts_write(vh, syncreset, 3); /* start sequencer */ 645 /* pretend screen is not blanked */ 646 sc->sc_save_ts.mode &= ~0x20; 647 sc->sc_save_ts.mode |= 0x80; 648 649 /* 650 * Save CRTC registers 651 */ 652 buf = (char *)&sc->sc_save_crtc; 653 for (i = 0; i < sizeof(sc->sc_save_crtc); i++) 654 *buf++ = _pcdisplay_6845_read(&vh->vh_ph, i); 655 656 /* 657 * Save ATC registers 658 */ 659 buf = (char *)&sc->sc_save_atc; 660 for (i = 0; i < sizeof(sc->sc_save_atc); i++) 661 *buf++ = _vga_attr_read(vh, i); 662 663 /* 664 * Save GDC registers 665 */ 666 buf = (char *)&sc->sc_save_gdc; 667 for (i = 0; i < sizeof(sc->sc_save_gdc); i++) 668 *buf++ = _vga_gdc_read(vh, i); 669 670 vga_save_palette(vc); 671 672 /* XXX should also save font data */ 673 674 /* 675 * Save current screen contents if we have backing store for it, 676 * and intend to POST on resume. 677 * XXX Since we don't allocate backing store unless the second VT is 678 * XXX created, we could theoretically have no backing store available 679 * XXX at this point. 680 */ 681 if (vga_pci_do_post) { 682 scr = vc->active; 683 if (scr != NULL && scr->pcs.active && scr->pcs.mem != NULL) 684 bus_space_read_region_2(vh->vh_memt, vh->vh_memh, 685 scr->pcs.dispoffset, scr->pcs.mem, 686 scr->pcs.type->ncols * scr->pcs.type->nrows); 687 } 688 } 689 690 void 691 vga_restore_state(struct vga_pci_softc *sc) 692 { 693 struct vga_config *vc = sc->sc_vc; 694 struct vga_handle *vh; 695 struct vgascreen *scr; 696 size_t i; 697 char *buf; 698 699 if (vc == NULL) 700 return; 701 702 vh = &vc->hdl; 703 704 /* 705 * Restore sequencer registers 706 */ 707 vga_ts_write(vh, syncreset, 1); /* stop sequencer */ 708 buf = (char *)&sc->sc_save_ts + 1; 709 for (i = 1; i < sizeof(sc->sc_save_ts); i++) 710 _vga_ts_write(vh, i, *buf++); 711 vga_ts_write(vh, syncreset, 3); /* start sequencer */ 712 713 /* 714 * Restore CRTC registers 715 */ 716 /* unprotect registers 00-07 */ 717 vga_6845_write(vh, vsynce, 718 vga_6845_read(vh, vsynce) & ~0x80); 719 buf = (char *)&sc->sc_save_crtc; 720 for (i = 0; i < sizeof(sc->sc_save_crtc); i++) 721 _pcdisplay_6845_write(&vh->vh_ph, i, *buf++); 722 723 /* 724 * Restore ATC registers 725 */ 726 buf = (char *)&sc->sc_save_atc; 727 for (i = 0; i < sizeof(sc->sc_save_atc); i++) 728 _vga_attr_write(vh, i, *buf++); 729 730 /* 731 * Restore GDC registers 732 */ 733 buf = (char *)&sc->sc_save_gdc; 734 for (i = 0; i < sizeof(sc->sc_save_gdc); i++) 735 _vga_gdc_write(vh, i, *buf++); 736 737 vga_restore_palette(vc); 738 739 /* 740 * Restore current screen contents if we have backing store for it, 741 * and have POSTed on resume. 742 * XXX Since we don't allocate backing store unless the second VT is 743 * XXX created, we could theoretically have no backing store available 744 * XXX at this point. 745 */ 746 if (vga_pci_do_post) { 747 scr = vc->active; 748 if (scr != NULL && scr->pcs.active && scr->pcs.mem != NULL) 749 bus_space_write_region_2(vh->vh_memt, vh->vh_memh, 750 scr->pcs.dispoffset, scr->pcs.mem, 751 scr->pcs.type->ncols * scr->pcs.type->nrows); 752 } 753 } 754 #endif 755