diff options
author | Matthieu Herrb <matthieu.herrb@laas.fr> | 2008-12-07 19:06:30 +0100 |
---|---|---|
committer | Matthieu Herrb <matthieu.herrb@laas.fr> | 2008-12-07 19:06:30 +0100 |
commit | 4ed838a238e4016b03e8a045b30d91cd974f836b (patch) | |
tree | 80ab6d39d91b747acb64169fa40f898ec96b75fe | |
parent | 7ac4cc8666fc217118ea3070e9c82ae7d2d79380 (diff) | |
parent | 565c8fcbf39a56319cee4f77f689dfc79e0c6614 (diff) |
Merge commit 'origin/master' into obsd
Conflicts:
src/openbsd_pci.c
-rw-r--r-- | src/openbsd_pci.c | 84 |
1 files changed, 64 insertions, 20 deletions
diff --git a/src/openbsd_pci.c b/src/openbsd_pci.c index e4f2592..b7348e4 100644 --- a/src/openbsd_pci.c +++ b/src/openbsd_pci.c @@ -75,35 +75,63 @@ pci_write(int bus, int dev, int func, uint32_t reg, uint32_t val) } /** - * Read a VGA rom using the 0xc0000 mapping. + * Read a VGA ROM * - * This function should be extended to handle access through PCI resources, - * which should be more reliable when available. */ static int -pci_device_openbsd_read_rom(struct pci_device * dev, void * buffer) +pci_device_openbsd_read_rom(struct pci_device *device, void *buffer) { -#if defined(__alpha__) || defined(__amd64__) || defined(__i386__) - void *bios; + struct pci_device_private *priv = (struct pci_device_private *)device; + unsigned char *bios; + pciaddr_t rom_base; + pciaddr_t rom_size; + u_int32_t csr, rom; + int pci_rom, bus, dev, func; + + bus = device->bus; + dev = device->dev; + func = device->func; - if ((dev->device_class & 0x00ffff00) != - ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8))) { - return ENOSYS; - } - if (aperturefd == -1) return ENOSYS; - bios = mmap(NULL, dev->rom_size, PROT_READ, 0, aperturefd, 0xc0000); + if (priv->base.rom_size == 0) { +#if defined(__alpha__) || defined(__amd64__) || defined(__i386__) + if ((device->device_class & 0x00ffff00) == + ((PCI_CLASS_DISPLAY << 16) | + (PCI_SUBCLASS_DISPLAY_VGA << 8))) { + rom_base = 0xc0000; + rom_size = 0x10000; + pci_rom = 0; + } else +#endif + return ENOSYS; + } else { + rom_base = priv->rom_base; + rom_size = priv->base.rom_size; + pci_rom = 1; + + pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG, &csr); + pci_write(bus, dev, func, PCI_COMMAND_STATUS_REG, + csr | PCI_COMMAND_MEM_ENABLE); + pci_read(bus, dev, func, PCI_ROM_REG, &rom); + pci_write(bus, dev, func, PCI_ROM_REG, rom | PCI_ROM_ENABLE); + } + + bios = mmap(NULL, rom_size, PROT_READ, MAP_SHARED, + aperturefd, (off_t)rom_base); if (bios == MAP_FAILED) return errno; - memcpy(buffer, bios, dev->rom_size); - munmap(bios, dev->rom_size); - + + memcpy(buffer, bios, device->rom_size); + munmap(bios, device->rom_size); + + if (pci_rom) { + /* Restore PCI config space */ + pci_write(bus, dev, func, PCI_ROM_REG, rom); + pci_write(bus, dev, func, PCI_COMMAND_STATUS_REG, csr); + } return 0; -#else - return ENOSYS; -#endif } static int @@ -233,7 +261,7 @@ pci_device_openbsd_write(struct pci_device *dev, const void *data, io.pi_width = 4; memcpy(&io.pi_data, data, 4); - if (ioctl(pcifd, PCIOCWRITE, &io) == -1) + if (ioctl(pcifd, PCIOCWRITE, &io) == -1) return errno; offset += 4; @@ -332,6 +360,22 @@ pci_device_openbsd_probe(struct pci_device *device) } } + /* Probe expansion ROM if present */ + err = pci_read(bus, dev, func, PCI_ROM_REG, ®); + if (err) + return err; + if (reg != 0) { + err = pci_write(bus, dev, func, PCI_ROM_REG, ~PCI_ROM_ENABLE); + if (err) + return err; + pci_read(bus, dev, func, PCI_ROM_REG, &size); + pci_write(bus, dev, func, PCI_ROM_REG, reg); + + if (PCI_ROM_ADDR(reg) != 0) { + priv->rom_base = PCI_ROM_ADDR(reg); + device->rom_size = PCI_ROM_SIZE(size); + } + } return 0; } @@ -354,7 +398,7 @@ pci_system_openbsd_create(void) int bus, dev, func, ndevs, nfuncs; uint32_t reg; - if (pcifd != -1) + if (pcifd != -1) return 0; pcifd = open("/dev/pci", O_RDWR); |