Date: Mon, 7 Mar 2011 18:45:46 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 189677 for review Message-ID: <201103071845.p27Ijk6X049465@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@189677?ac=10 Change 189677 by jhb@jhb_jhbbsd on 2011/03/07 18:45:39 - Properly handle expansion ROM BARs for PCI-PCI bridges (they are at a different config space offset) and for Cardbus bridges (they don't exist). - Various compile fixes. Affected files ... .. //depot/projects/pci/sys/dev/pci/pci.c#6 edit .. //depot/projects/pci/sys/dev/pci/pci_private.h#4 edit .. //depot/projects/pci/sys/dev/pci/pci_user.c#4 edit .. //depot/projects/pci/sys/dev/pci/pcireg.h#2 edit .. //depot/projects/pci/sys/dev/pci/pcivar.h#3 edit Differences ... ==== //depot/projects/pci/sys/dev/pci/pci.c#6 (text+ko) ==== @@ -69,6 +69,11 @@ #include "pcib_if.h" #include "pci_if.h" +#define PCIR_IS_BIOS(cfg, reg) \ + (((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \ + ((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1)) + + static pci_addr_t pci_mapbase(uint64_t mapreg); static const char *pci_maptype(uint64_t mapreg); static int pci_mapsize(uint64_t testval); @@ -2376,6 +2381,7 @@ static void pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp) { + struct pci_devinfo *dinfo; pci_addr_t map, testval; int ln2range; uint16_t cmd; @@ -2385,7 +2391,8 @@ * memory BAR. Bit 0 is special and should not be set when * sizing the BAR. */ - if (reg == PCIR_BIOS) { + dinfo = device_get_ivars(dev); + if (PCIR_IS_BIOS(&dinfo->cfg, reg)) { map = pci_read_config(dev, reg, 4); pci_write_config(dev, reg, 0xfffffffe, 4); testval = pci_read_config(dev, reg, 4); @@ -2438,10 +2445,12 @@ static void pci_write_bar(device_t dev, struct pci_map *pm, pci_addr_t base) { + struct pci_devinfo *dinfo; int ln2range; /* The device ROM BAR is always a 32-bit memory BAR. */ - if (pm->pm_reg == PCIR_BIOS) + dinfo = device_get_ivars(dev); + if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg)) ln2range = 32; else ln2range = pci_maprange(pm->pm_value); @@ -2461,7 +2470,7 @@ dinfo = device_get_ivars(dev); STAILQ_FOREACH(pm, &dinfo->cfg.maps, pm_link) { - if (pm->pm_reg == bio->pbi_reg) + if (pm->pm_reg == reg) return (pm); } return (NULL); @@ -2470,18 +2479,21 @@ int pci_bar_enabled(device_t dev, struct pci_map *pm) { + struct pci_devinfo *dinfo; uint16_t cmd; - if (pm->pm_reg == PCIR_BIOS && !(pm->pm_value & PCIM_BIOS_ENABLE)) + dinfo = device_get_ivars(dev); + if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) && + !(pm->pm_value & PCIM_BIOS_ENABLE)) return (0); cmd = pci_read_config(dev, PCIR_COMMAND, 2); - if (pm->pm_reg == PCIR_BIOS || PCI_BAR_MEM(pm->pm_value)) + if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) || PCI_BAR_MEM(pm->pm_value)) return ((cmd & PCIM_CMD_MEMEN) != 0); else return ((cmd & PCIM_CMD_PORTEN) != 0); } -struct pci_map * +static struct pci_map * pci_add_bar(device_t dev, int reg, pci_addr_t value, pci_addr_t size) { struct pci_devinfo *dinfo; @@ -2495,8 +2507,8 @@ STAILQ_FOREACH(prev, &dinfo->cfg.maps, pm_link) { KASSERT(prev->pm_reg != pm->pm_reg, ("duplicate map %02x", reg)); - if (STAILQ_NEXT(prev) == NULL || STAILQ_NEXT(prev)->pm_reg > - pm->pm_reg) + if (STAILQ_NEXT(prev, pm_link) == NULL || + STAILQ_NEXT(prev, pm_link)->pm_reg > pm->pm_reg) break; } if (prev != NULL) @@ -2514,14 +2526,15 @@ int ln2range; dinfo = device_get_ivars(dev); - STAILQ_FOREACH(prev, &dinfo->cfg.maps, pm_link) { - if (pm->pm_reg == PCIR_BIOS) + STAILQ_FOREACH(pm, &dinfo->cfg.maps, pm_link) { + if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg)) ln2range = 32; else ln2range = pci_maprange(pm->pm_value); pci_write_config(dev, pm->pm_reg, pm->pm_value, 4); if (ln2range == 64) - pci_write_config(dev, pm->pm_reg + 4, pm->pm_value >> 32, 4); + pci_write_config(dev, pm->pm_reg + 4, + pm->pm_value >> 32, 4); } } @@ -3820,7 +3833,7 @@ * Determine the size of the BAR and ignore BARs with a size * of 0. Device ROM BARs use a different mask value. */ - if (*rid == PCIR_BIOS) + if (PCIR_IS_BIOS(&dinfo->cfg, *rid)) mapsize = pci_romsize(testval); else mapsize = pci_mapsize(testval); @@ -3829,7 +3842,7 @@ pm = pci_add_bar(child, *rid, map, mapsize); } - if (PCI_BAR_MEM(map) || *rid == PCIR_BIOS) { + if (PCI_BAR_MEM(map) || PCIR_IS_BIOS(&dinfo->cfg, *rid)) { if (type != SYS_RES_MEMORY) { if (bootverbose) device_printf(dev, @@ -3949,6 +3962,7 @@ pci_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { + struct pci_devinfo *dinfo; int error; error = bus_generic_activate_resource(dev, child, type, rid, r); @@ -3958,8 +3972,9 @@ /* Enable decoding in the command register when activating BARs. */ if (device_get_parent(child) == dev) { /* Device ROMs need their decoding explicitly enabled. */ - if (rid == PCIR_BIOS) - pci_write_bar(child, pci_get_bar(child, PCIR_BIOS), + dinfo = device_get_ivars(child); + if (PCIR_IS_BIOS(&dinfo->cfg, rid)) + pci_write_bar(child, pci_find_bar(child, rid), rman_get_start(r) | PCIM_BIOS_ENABLE); switch (type) { case SYS_RES_IOPORT: @@ -3975,16 +3990,20 @@ pci_deactivate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { - struct pci_map *pm; + struct pci_devinfo *dinfo; int error; error = bus_generic_deactivate_resource(dev, child, type, rid, r); if (error) return (error); - /* Disable decoding for device ROMs. */ - if (rid == PCIR_BIOS) - pci_write_bar(child, pci_get_bar(child, PCIR_BIOS), rman_get_start(r)); + /* Disable decoding for device ROMs. */ + if (device_get_parent(child) == dev) { + dinfo = device_get_ivars(child); + if (PCIR_IS_BIOS(&dinfo->cfg, rid)) + pci_write_bar(child, pci_find_bar(child, rid), + rman_get_start(r)); + } return (0); } @@ -4062,7 +4081,7 @@ switch (type) { case SYS_RES_IOPORT: case SYS_RES_MEMORY: - pci_write_bar(child, pci_get_bar(child, rid), 0); + pci_write_bar(child, pci_find_bar(child, rid), 0); break; } #endif @@ -4161,7 +4180,9 @@ void pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo) { +#if 0 int i; +#endif /* * Only do header type 0 devices. Type 1 devices are bridges, @@ -4209,7 +4230,9 @@ void pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) { +#if 0 int i; +#endif uint32_t cls; int ps; ==== //depot/projects/pci/sys/dev/pci/pci_private.h#4 (text+ko) ==== @@ -104,8 +104,6 @@ int pci_assign_interrupt_method(device_t dev, device_t child); int pci_resume(device_t dev); int pci_suspend(device_t dev); -struct pci_map *pci_find_bar(device_t dev, int reg); -int pci_bar_enabled(device_t dev, struct pci_map *pm); /** Restore the config register state. The state must be previously * saved with pci_cfg_save. However, the pci bus driver takes care of ==== //depot/projects/pci/sys/dev/pci/pci_user.c#4 (text+ko) ==== @@ -309,7 +309,6 @@ struct pci_io *io; struct pci_bar_io *bio; struct pci_match_conf *pattern_buf; - struct resource_list_entry *rle; struct pci_map *pm; size_t confsz, iolen, pbufsz; int error, ionum, i, num_patterns; @@ -685,7 +684,7 @@ error = ENODEV; break; } - pm = pci_find_bar(pcidev, reg); + pm = pci_find_bar(pcidev, bio->pbi_reg); if (pm == NULL) { error = EINVAL; break; ==== //depot/projects/pci/sys/dev/pci/pcireg.h#2 (text+ko) ==== @@ -212,6 +212,7 @@ #define PCIM_BRPM_64 0x1 #define PCIM_BRPM_MASK 0xf +#define PCIR_BIOS_1 0x38 #define PCIR_BRIDGECTL_1 0x3e /* config registers for header type 2 (CardBus) devices */ ==== //depot/projects/pci/sys/dev/pci/pcivar.h#3 (text+ko) ==== @@ -477,4 +477,7 @@ extern struct devlist pci_devq; extern uint32_t pci_generation; +struct pci_map *pci_find_bar(device_t dev, int reg); +int pci_bar_enabled(device_t dev, struct pci_map *pm); + #endif /* _PCIVAR_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103071845.p27Ijk6X049465>