diff options
author | Matthieu Herrb <matthieu.herrb@laas.fr> | 2008-12-07 19:00:22 +0100 |
---|---|---|
committer | Matthieu Herrb <matthieu.herrb@laas.fr> | 2008-12-07 19:00:22 +0100 |
commit | 565c8fcbf39a56319cee4f77f689dfc79e0c6614 (patch) | |
tree | 3ec7b20cd7af72317701539045f4b88d301b4939 | |
parent | 8222fb8534cf09e433f0f3d68c35d6c390fbba5e (diff) |
Sync with OpenBSD code.
- implement pci_read_rom()
- only set MTRR on x86 cpus
- failure to set non-cacheable attributes is not fatal
- fix a logic error in pci_write()
-rw-r--r-- | src/openbsd_pci.c | 92 |
1 files changed, 85 insertions, 7 deletions
diff --git a/src/openbsd_pci.c b/src/openbsd_pci.c index 12547f0..b7348e4 100644 --- a/src/openbsd_pci.c +++ b/src/openbsd_pci.c @@ -74,6 +74,66 @@ pci_write(int bus, int dev, int func, uint32_t reg, uint32_t val) return ioctl(pcifd, PCIOCWRITE, &io); } +/** + * Read a VGA ROM + * + */ +static int +pci_device_openbsd_read_rom(struct pci_device *device, void *buffer) +{ + 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 (aperturefd == -1) + return ENOSYS; + + 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, 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; +} + static int pci_nfuncs(int bus, int dev) { @@ -100,7 +160,7 @@ pci_device_openbsd_map_range(struct pci_device *dev, map->base); if (map->memory == MAP_FAILED) return errno; - +#if defined(__i386__) || defined(__amd64__) /* No need to set an MTRR if it's the default mode. */ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) { @@ -117,9 +177,10 @@ pci_device_openbsd_map_range(struct pci_device *dev, mo.mo_arg[0] = MEMRANGE_SET_UPDATE; if (ioctl(aperturefd, MEMRANGE_SET, &mo)) - return errno; + (void)fprintf(stderr, "mtrr set failed: %s\n", + strerror(errno)); } - +#endif return 0; } @@ -127,6 +188,7 @@ static int pci_device_openbsd_unmap_range(struct pci_device *dev, struct pci_device_mapping *map) { +#if defined(__i386__) || defined(__amd64__) struct mem_range_desc mr; struct mem_range_op mo; @@ -142,7 +204,7 @@ pci_device_openbsd_unmap_range(struct pci_device *dev, (void)ioctl(aperturefd, MEMRANGE_SET, &mo); } - +#endif return pci_device_generic_unmap_range(dev, map); } @@ -199,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; @@ -298,13 +360,29 @@ 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; } static const struct pci_system_methods openbsd_pci_methods = { pci_system_openbsd_destroy, NULL, - NULL, + pci_device_openbsd_read_rom, pci_device_openbsd_probe, pci_device_openbsd_map_range, pci_device_openbsd_unmap_range, @@ -320,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); |