diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-06 16:20:21 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-11-11 10:08:08 +0100 |
commit | 66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch) | |
tree | 48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev/pci | |
parent | Define __GLOBL1() and __GLOBL() (diff) | |
download | rtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2 |
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/dev/pci')
-rw-r--r-- | freebsd/sys/dev/pci/pci.c | 542 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pci_pci.c | 367 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pci_private.h | 6 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pci_user.c | 246 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pcib_private.h | 29 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pcireg.h | 39 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pcivar.h | 7 |
7 files changed, 834 insertions, 402 deletions
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index ea1e841e..94eeb844 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <dev/pci/pci_private.h> +#include <dev/usb/controller/xhcireg.h> #include <dev/usb/controller/ehcireg.h> #include <dev/usb/controller/ohcireg.h> #include <dev/usb/controller/uhcireg.h> @@ -71,13 +72,6 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/pcib_if.h> #include <rtems/bsd/local/pci_if.h> -#ifdef __HAVE_ACPI -#include <contrib/dev/acpica/include/acpi.h> -#include <rtems/bsd/local/acpi_if.h> -#else -#define ACPI_PWR_FOR_SLEEP(x, y, z) -#endif - /* * XXX: Due to a limitation of the bus_dma_tag_create() API, we cannot * specify a 4GB boundary on 32-bit targets. Usually this does not @@ -97,6 +91,7 @@ __FBSDID("$FreeBSD$"); (((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \ ((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1)) +static int pci_has_quirk(uint32_t devid, int quirk); static pci_addr_t pci_mapbase(uint64_t mapreg); static const char *pci_maptype(uint64_t mapreg); static int pci_mapsize(uint64_t testval); @@ -138,6 +133,7 @@ static void pci_enable_msix(device_t dev, u_int index, static void pci_mask_msix(device_t dev, u_int index); static void pci_unmask_msix(device_t dev, u_int index); static int pci_msi_blacklisted(void); +static int pci_msix_blacklisted(void); static void pci_resume_msi(device_t dev); static void pci_resume_msix(device_t dev); static int pci_remap_intr_method(device_t bus, device_t dev, @@ -201,7 +197,7 @@ static device_method_t pci_methods[] = { DEFINE_CLASS_0(pci, pci_driver, pci_methods, sizeof(struct pci_softc)); static devclass_t pci_devclass; -DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); +DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, NULL); MODULE_VERSION(pci, 1); static char *pci_vendordata; @@ -211,15 +207,16 @@ struct pci_quirk { uint32_t devid; /* Vendor/device of the card */ int type; #define PCI_QUIRK_MAP_REG 1 /* PCI map register in weird place */ -#define PCI_QUIRK_DISABLE_MSI 2 /* MSI/MSI-X doesn't work */ +#define PCI_QUIRK_DISABLE_MSI 2 /* Neither MSI nor MSI-X work */ #define PCI_QUIRK_ENABLE_MSI_VM 3 /* Older chipset in VM where MSI works */ #define PCI_QUIRK_UNMAP_REG 4 /* Ignore PCI map register */ +#define PCI_QUIRK_DISABLE_MSIX 5 /* MSI-X doesn't work */ int arg1; int arg2; }; static const struct pci_quirk pci_quirks[] = { - /* The Intel 82371AB and 82443MX has a map register at offset 0x90. */ + /* The Intel 82371AB and 82443MX have a map register at offset 0x90. */ { 0x71138086, PCI_QUIRK_MAP_REG, 0x90, 0 }, { 0x719b8086, PCI_QUIRK_MAP_REG, 0x90, 0 }, /* As does the Serverworks OSB4 (the SMBus mapping register) */ @@ -254,8 +251,8 @@ static const struct pci_quirk pci_quirks[] = { * MSI-X allocation doesn't work properly for devices passed through * by VMware up to at least ESXi 5.1. */ - { 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCI/PCI-X */ - { 0x07a015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCIe */ + { 0x079015ad, PCI_QUIRK_DISABLE_MSIX, 0, 0 }, /* PCI/PCI-X */ + { 0x07a015ad, PCI_QUIRK_DISABLE_MSIX, 0, 0 }, /* PCIe */ /* * Some virtualization environments emulate an older chipset @@ -297,6 +294,12 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_io_modes, CTLFLAG_RW, enable these bits correctly. We'd like to do this all the time, but there\n\ are some peripherals that this causes problems with."); +static int pci_do_realloc_bars = 0; +TUNABLE_INT("hw.pci.realloc_bars", &pci_do_realloc_bars); +SYSCTL_INT(_hw_pci, OID_AUTO, realloc_bars, CTLFLAG_RW, + &pci_do_realloc_bars, 0, + "Attempt to allocate a new range for any BARs whose original firmware-assigned ranges fail to allocate during the initial device scan."); + static int pci_do_power_nodriver = 0; TUNABLE_INT("hw.pci.do_power_nodriver", &pci_do_power_nodriver); SYSCTL_INT(_hw_pci, OID_AUTO, do_power_nodriver, CTLFLAG_RW, @@ -306,12 +309,18 @@ disable. 1 means conservatively place devices into D3 state. 2 means\n\ agressively place devices into D3 state. 3 means put absolutely everything\n\ in D3 state."); -static int pci_do_power_resume = 1; +int pci_do_power_resume = 1; TUNABLE_INT("hw.pci.do_power_resume", &pci_do_power_resume); SYSCTL_INT(_hw_pci, OID_AUTO, do_power_resume, CTLFLAG_RW, &pci_do_power_resume, 1, "Transition from D3 -> D0 on resume."); +int pci_do_power_suspend = 1; +TUNABLE_INT("hw.pci.do_power_suspend", &pci_do_power_suspend); +SYSCTL_INT(_hw_pci, OID_AUTO, do_power_suspend, CTLFLAG_RW, + &pci_do_power_suspend, 1, + "Transition from D0 -> D3 on suspend."); + static int pci_do_msi = 1; TUNABLE_INT("hw.pci.enable_msi", &pci_do_msi); SYSCTL_INT(_hw_pci, OID_AUTO, enable_msi, CTLFLAG_RW, &pci_do_msi, 1, @@ -325,7 +334,7 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_msix, CTLFLAG_RW, &pci_do_msix, 1, static int pci_honor_msi_blacklist = 1; TUNABLE_INT("hw.pci.honor_msi_blacklist", &pci_honor_msi_blacklist); SYSCTL_INT(_hw_pci, OID_AUTO, honor_msi_blacklist, CTLFLAG_RD, - &pci_honor_msi_blacklist, 1, "Honor chipset blacklist for MSI"); + &pci_honor_msi_blacklist, 1, "Honor chipset blacklist for MSI/MSI-X"); #if defined(__i386__) || defined(__amd64__) static int pci_usb_takeover = 1; @@ -338,6 +347,18 @@ SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RDTUN, Disable this if you depend on BIOS emulation of USB devices, that is\n\ you use USB devices (like keyboard or mouse) but do not load USB drivers"); +static int +pci_has_quirk(uint32_t devid, int quirk) +{ + const struct pci_quirk *q; + + for (q = &pci_quirks[0]; q->devid; q++) { + if (q->devid == devid && q->type == quirk) + return (1); + } + return (0); +} + /* Find a device_t by bus/slot/function in domain 0 */ device_t @@ -515,12 +536,12 @@ pci_maprange(uint64_t mapreg) static void pci_fixancient(pcicfgregs *cfg) { - if (cfg->hdrtype != 0) + if ((cfg->hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL) return; /* PCI to PCI bridges use header type 1 */ if (cfg->baseclass == PCIC_BRIDGE && cfg->subclass == PCIS_BRIDGE_PCI) - cfg->hdrtype = 1; + cfg->hdrtype = PCIM_HDRTYPE_BRIDGE; } /* extract header type specific config data */ @@ -529,16 +550,16 @@ static void pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg) { #define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w) - switch (cfg->hdrtype) { - case 0: + switch (cfg->hdrtype & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_NORMAL: cfg->subvendor = REG(PCIR_SUBVEND_0, 2); cfg->subdevice = REG(PCIR_SUBDEV_0, 2); cfg->nummaps = PCI_MAXMAPS_0; break; - case 1: + case PCIM_HDRTYPE_BRIDGE: cfg->nummaps = PCI_MAXMAPS_1; break; - case 2: + case PCIM_HDRTYPE_CARDBUS: cfg->subvendor = REG(PCIR_SUBVEND_2, 2); cfg->subdevice = REG(PCIR_SUBDEV_2, 2); cfg->nummaps = PCI_MAXMAPS_2; @@ -635,11 +656,11 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) int ptr, nextptr, ptrptr; switch (cfg->hdrtype & PCIM_HDRTYPE) { - case 0: - case 1: + case PCIM_HDRTYPE_NORMAL: + case PCIM_HDRTYPE_BRIDGE: ptrptr = PCIR_CAP_PTR; break; - case 2: + case PCIM_HDRTYPE_CARDBUS: ptrptr = PCIR_CAP_PTR_2; /* cardbus capabilities ptr */ break; default: @@ -667,7 +688,7 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) if (cfg->pp.pp_cap == 0) { cfg->pp.pp_cap = REG(ptr + PCIR_POWER_CAP, 2); cfg->pp.pp_status = ptr + PCIR_POWER_STATUS; - cfg->pp.pp_pmcsr = ptr + PCIR_POWER_PMCSR; + cfg->pp.pp_bse = ptr + PCIR_POWER_BSE; if ((nextptr - ptr) > PCIR_POWER_DATA) cfg->pp.pp_data = ptr + PCIR_POWER_DATA; } @@ -730,7 +751,8 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) break; case PCIY_SUBVENDOR: /* Should always be true. */ - if ((cfg->hdrtype & PCIM_HDRTYPE) == 1) { + if ((cfg->hdrtype & PCIM_HDRTYPE) == + PCIM_HDRTYPE_BRIDGE) { val = REG(ptr + PCIR_SUBVENDCAP_ID, 4); cfg->subvendor = val & 0xffff; cfg->subdevice = val >> 16; @@ -744,7 +766,8 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) * PCI-express or HT chipsets might match on * this check as well. */ - if ((cfg->hdrtype & PCIM_HDRTYPE) == 1) + if ((cfg->hdrtype & PCIM_HDRTYPE) == + PCIM_HDRTYPE_BRIDGE) pcix_chipset = 1; break; case PCIY_EXPRESS: /* PCI-express */ @@ -1202,11 +1225,11 @@ pci_find_extcap_method(device_t dev, device_t child, int capability, * Determine the start pointer of the capabilities list. */ switch (cfg->hdrtype & PCIM_HDRTYPE) { - case 0: - case 1: + case PCIM_HDRTYPE_NORMAL: + case PCIM_HDRTYPE_BRIDGE: ptr = PCIR_CAP_PTR; break; - case 2: + case PCIM_HDRTYPE_CARDBUS: ptr = PCIR_CAP_PTR_2; break; default: @@ -1354,8 +1377,8 @@ pci_alloc_msix_method(device_t dev, device_t child, int *count) if (cfg->msi.msi_alloc != 0 || cfg->msix.msix_alloc != 0) return (ENXIO); - /* If MSI is blacklisted for this system, fail. */ - if (pci_msi_blacklisted()) + /* If MSI-X is blacklisted for this system, fail. */ + if (pci_msix_blacklisted()) return (ENXIO); /* MSI-X capability present? */ @@ -1907,38 +1930,15 @@ pci_remap_intr_method(device_t bus, device_t dev, u_int irq) int pci_msi_device_blacklisted(device_t dev) { - const struct pci_quirk *q; if (!pci_honor_msi_blacklist) return (0); - for (q = &pci_quirks[0]; q->devid; q++) { - if (q->devid == pci_get_devid(dev) && - q->type == PCI_QUIRK_DISABLE_MSI) - return (1); - } - return (0); -} - -/* - * Returns true if a specified chipset supports MSI when it is - * emulated hardware in a virtual machine. - */ -static int -pci_msi_vm_chipset(device_t dev) -{ - const struct pci_quirk *q; - - for (q = &pci_quirks[0]; q->devid; q++) { - if (q->devid == pci_get_devid(dev) && - q->type == PCI_QUIRK_ENABLE_MSI_VM) - return (1); - } - return (0); + return (pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_DISABLE_MSI)); } /* - * Determine if MSI is blacklisted globally on this sytem. Currently, + * Determine if MSI is blacklisted globally on this system. Currently, * we just check for blacklisted chipsets as represented by the * host-PCI bridge at device 0:0:0. In the future, it may become * necessary to check other system attributes, such as the kenv values @@ -1955,9 +1955,14 @@ pci_msi_blacklisted(void) /* Blacklist all non-PCI-express and non-PCI-X chipsets. */ if (!(pcie_chipset || pcix_chipset)) { if (vm_guest != VM_GUEST_NO) { + /* + * Whitelist older chipsets in virtual + * machines known to support MSI. + */ dev = pci_find_bsf(0, 0, 0); if (dev != NULL) - return (pci_msi_vm_chipset(dev) == 0); + return (!pci_has_quirk(pci_get_devid(dev), + PCI_QUIRK_ENABLE_MSI_VM)); } return (1); } @@ -1969,6 +1974,45 @@ pci_msi_blacklisted(void) } /* + * Returns true if the specified device is blacklisted because MSI-X + * doesn't work. Note that this assumes that if MSI doesn't work, + * MSI-X doesn't either. + */ +int +pci_msix_device_blacklisted(device_t dev) +{ + + if (!pci_honor_msi_blacklist) + return (0); + + if (pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_DISABLE_MSIX)) + return (1); + + return (pci_msi_device_blacklisted(dev)); +} + +/* + * Determine if MSI-X is blacklisted globally on this system. If MSI + * is blacklisted, assume that MSI-X is as well. Check for additional + * chipsets where MSI works but MSI-X does not. + */ +static int +pci_msix_blacklisted(void) +{ + device_t dev; + + if (!pci_honor_msi_blacklist) + return (0); + + dev = pci_find_bsf(0, 0, 0); + if (dev != NULL && pci_has_quirk(pci_get_devid(dev), + PCI_QUIRK_DISABLE_MSIX)) + return (1); + + return (pci_msi_blacklisted()); +} + +/* * Attempt to allocate *count MSI messages. The actual number allocated is * returned in *count. After this function returns, each message will be * available to the driver as SYS_RES_IRQ resources starting at a rid 1. @@ -2745,22 +2789,40 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl, * driver for this device will later inherit this resource in * pci_alloc_resource(). */ - res = resource_list_alloc(rl, bus, dev, type, ®, start, end, count, + res = resource_list_reserve(rl, bus, dev, type, ®, start, end, count, prefetch ? RF_PREFETCHABLE : 0); + if (pci_do_realloc_bars && res == NULL && (start != 0 || end != ~0ul)) { + /* + * If the allocation fails, try to allocate a resource for + * this BAR using any available range. The firmware felt + * it was important enough to assign a resource, so don't + * disable decoding if we can help it. + */ + resource_list_delete(rl, type, reg); + resource_list_add(rl, type, reg, 0, ~0ul, count); + res = resource_list_reserve(rl, bus, dev, type, ®, 0, ~0ul, + count, prefetch ? RF_PREFETCHABLE : 0); + } if (res == NULL) { /* - * If the allocation fails, clear the BAR and delete - * the resource list entry to force - * pci_alloc_resource() to allocate resources from the - * parent. + * If the allocation fails, delete the resource list entry + * and disable decoding for this device. + * + * If the driver requests this resource in the future, + * pci_reserve_map() will try to allocate a fresh + * resource range. */ resource_list_delete(rl, type, reg); - start = 0; + pci_disable_io(dev, type); + if (bootverbose) + device_printf(bus, + "pci%d:%d:%d:%d bar %#x failed to allocate\n", + pci_get_domain(dev), pci_get_bus(dev), + pci_get_slot(dev), pci_get_function(dev), reg); } else { start = rman_get_start(res); - rman_set_device(res, bus); + pci_write_bar(dev, pm, start); } - pci_write_bar(dev, pm, start); return (barlen); } @@ -2798,14 +2860,12 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force, } else { rid = PCIR_BAR(0); resource_list_add(rl, type, rid, 0x1f0, 0x1f7, 8); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x1f0, 0x1f7, - 8, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0, + 0x1f7, 8, 0); rid = PCIR_BAR(1); resource_list_add(rl, type, rid, 0x3f6, 0x3f6, 1); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x3f6, 0x3f6, - 1, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6, + 0x3f6, 1, 0); } if (progif & PCIP_STORAGE_IDE_MODESEC) { pci_add_map(bus, dev, PCIR_BAR(2), rl, force, @@ -2815,14 +2875,12 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force, } else { rid = PCIR_BAR(2); resource_list_add(rl, type, rid, 0x170, 0x177, 8); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x170, 0x177, - 8, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x170, + 0x177, 8, 0); rid = PCIR_BAR(3); resource_list_add(rl, type, rid, 0x376, 0x376, 1); - r = resource_list_alloc(rl, bus, dev, type, &rid, 0x376, 0x376, - 1, 0); - rman_set_device(r, bus); + r = resource_list_reserve(rl, bus, dev, type, &rid, 0x376, + 0x376, 1, 0); } pci_add_map(bus, dev, PCIR_BAR(4), rl, force, prefetchmask & (1 << 4)); @@ -2999,6 +3057,68 @@ ehci_early_takeover(device_t self) bus_release_resource(self, SYS_RES_MEMORY, rid, res); } +/* Perform early XHCI takeover from SMM. */ +static void +xhci_early_takeover(device_t self) +{ + struct resource *res; + uint32_t cparams; + uint32_t eec; + uint8_t eecp; + uint8_t bios_sem; + uint8_t offs; + int rid; + int i; + + rid = PCIR_BAR(0); + res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (res == NULL) + return; + + cparams = bus_read_4(res, XHCI_HCSPARAMS0); + + eec = -1; + + /* Synchronise with the BIOS if it owns the controller. */ + for (eecp = XHCI_HCS0_XECP(cparams) << 2; eecp != 0 && XHCI_XECP_NEXT(eec); + eecp += XHCI_XECP_NEXT(eec) << 2) { + eec = bus_read_4(res, eecp); + + if (XHCI_XECP_ID(eec) != XHCI_ID_USB_LEGACY) + continue; + + bios_sem = bus_read_1(res, eecp + XHCI_XECP_BIOS_SEM); + if (bios_sem == 0) + continue; + + if (bootverbose) + printf("xhci early: " + "SMM active, request owner change\n"); + + bus_write_1(res, eecp + XHCI_XECP_OS_SEM, 1); + + /* wait a maximum of 5 second */ + + for (i = 0; (i < 5000) && (bios_sem != 0); i++) { + DELAY(1000); + bios_sem = bus_read_1(res, eecp + + XHCI_XECP_BIOS_SEM); + } + + if (bios_sem != 0) { + if (bootverbose) + printf("xhci early: " + "SMM does not respond\n"); + } + + /* Disable interrupts */ + offs = bus_read_1(res, XHCI_CAPLENGTH); + bus_write_4(res, offs + XHCI_USBCMD, 0); + bus_read_4(res, offs + XHCI_USBSTS); + } + bus_release_resource(self, SYS_RES_MEMORY, rid, res); +} + void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) { @@ -3062,7 +3182,9 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) if (pci_usb_takeover && pci_get_class(dev) == PCIC_SERIALBUS && pci_get_subclass(dev) == PCIS_SERIALBUS_USB) { - if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_EHCI) + if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_XHCI) + xhci_early_takeover(dev); + else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_EHCI) ehci_early_takeover(dev); else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_OHCI) ohci_early_takeover(dev); @@ -3184,20 +3306,43 @@ pci_attach(device_t dev) return (bus_generic_attach(dev)); } +static void +pci_set_power_children(device_t dev, device_t *devlist, int numdevs, + int state) +{ + device_t child, pcib; + struct pci_devinfo *dinfo; + int dstate, i; + + /* + * Set the device to the given state. If the firmware suggests + * a different power state, use it instead. If power management + * is not present, the firmware is responsible for managing + * device power. Skip children who aren't attached since they + * are handled separately. + */ + pcib = device_get_parent(dev); + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + dinfo = device_get_ivars(child); + dstate = state; + if (device_is_attached(child) && + PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) + pci_set_powerstate(child, dstate); + } +} + int pci_suspend(device_t dev) { - int dstate, error, i, numdevs; - device_t acpi_dev, child, *devlist; + device_t child, *devlist; struct pci_devinfo *dinfo; + int error, i, numdevs; /* * Save the PCI configuration space for each child and set the * device in the appropriate power state for this sleep state. */ - acpi_dev = NULL; - if (pci_do_power_resume) - acpi_dev = devclass_get_device(devclass_find("acpi"), 0); if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) return (error); for (i = 0; i < numdevs; i++) { @@ -3212,23 +3357,9 @@ pci_suspend(device_t dev) free(devlist, M_TEMP); return (error); } - - /* - * Always set the device to D3. If ACPI suggests a different - * power state, use it instead. If ACPI is not present, the - * firmware is responsible for managing device power. Skip - * children who aren't attached since they are powered down - * separately. Only manage type 0 devices for now. - */ - for (i = 0; acpi_dev && i < numdevs; i++) { - child = devlist[i]; - dinfo = (struct pci_devinfo *) device_get_ivars(child); - if (device_is_attached(child) && dinfo->cfg.hdrtype == 0) { - dstate = PCI_POWERSTATE_D3; - ACPI_PWR_FOR_SLEEP(acpi_dev, child, &dstate); - pci_set_powerstate(child, dstate); - } - } + if (pci_do_power_suspend) + pci_set_power_children(dev, devlist, numdevs, + PCI_POWERSTATE_D3); free(devlist, M_TEMP); return (0); } @@ -3236,51 +3367,76 @@ pci_suspend(device_t dev) int pci_resume(device_t dev) { - int i, numdevs, error; - device_t acpi_dev, child, *devlist; + device_t child, *devlist; struct pci_devinfo *dinfo; + int error, i, numdevs; /* * Set each child to D0 and restore its PCI configuration space. */ - acpi_dev = NULL; - if (pci_do_power_resume) - acpi_dev = devclass_get_device(devclass_find("acpi"), 0); if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) return (error); + if (pci_do_power_resume) + pci_set_power_children(dev, devlist, numdevs, + PCI_POWERSTATE_D0); + + /* Now the device is powered up, restore its config space. */ for (i = 0; i < numdevs; i++) { - /* - * Notify ACPI we're going to D0 but ignore the result. If - * ACPI is not present, the firmware is responsible for - * managing device power. Only manage type 0 devices for now. - */ child = devlist[i]; - dinfo = (struct pci_devinfo *) device_get_ivars(child); - if (acpi_dev && device_is_attached(child) && - dinfo->cfg.hdrtype == 0) { - ACPI_PWR_FOR_SLEEP(acpi_dev, child, NULL); - pci_set_powerstate(child, PCI_POWERSTATE_D0); - } + dinfo = device_get_ivars(child); - /* Now the device is powered up, restore its config space. */ pci_cfg_restore(child, dinfo); + if (!device_is_attached(child)) + pci_cfg_save(child, dinfo, 1); + } + + /* + * Resume critical devices first, then everything else later. + */ + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + switch (pci_get_class(child)) { + case PCIC_DISPLAY: + case PCIC_MEMORY: + case PCIC_BRIDGE: + case PCIC_BASEPERIPH: + DEVICE_RESUME(child); + break; + } + } + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + switch (pci_get_class(child)) { + case PCIC_DISPLAY: + case PCIC_MEMORY: + case PCIC_BRIDGE: + case PCIC_BASEPERIPH: + break; + default: + DEVICE_RESUME(child); + } } free(devlist, M_TEMP); - return (bus_generic_resume(dev)); + return (0); } static void pci_load_vendor_data(void) { - caddr_t vendordata, info; - - if ((vendordata = preload_search_by_type("pci_vendor_data")) != NULL) { - info = preload_search_info(vendordata, MODINFO_ADDR); - pci_vendordata = *(char **)info; - info = preload_search_info(vendordata, MODINFO_SIZE); - pci_vendordata_size = *(size_t *)info; - /* terminate the database */ - pci_vendordata[pci_vendordata_size] = '\n'; + caddr_t data; + void *ptr; + size_t sz; + + data = preload_search_by_type("pci_vendor_data"); + if (data != NULL) { + ptr = preload_fetch_addr(data); + sz = preload_fetch_size(data); + if (ptr != NULL && sz != 0) { + pci_vendordata = ptr; + pci_vendordata_size = sz; + /* terminate the database */ + pci_vendordata[pci_vendordata_size] = '\n'; + } } } @@ -3742,7 +3898,7 @@ pci_describe_device(device_t dev) if ((desc = malloc(strlen(vp) + strlen(dp) + 3, M_DEVBUF, M_NOWAIT)) != NULL) sprintf(desc, "%s, %s", vp, dp); - out: +out: if (vp != NULL) free(vp, M_DEVBUF); if (dp != NULL) @@ -3917,7 +4073,7 @@ DB_SHOW_COMMAND(pciregs, db_pci_dump) #endif /* DDB */ static struct resource * -pci_alloc_map(device_t dev, device_t child, int type, int *rid, +pci_reserve_map(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct pci_devinfo *dinfo = device_get_ivars(child); @@ -4003,22 +4159,22 @@ pci_alloc_map(device_t dev, device_t child, int type, int *rid, count, *rid, type, start, end); goto out; } - rman_set_device(res, dev); resource_list_add(rl, type, *rid, start, end, count); rle = resource_list_find(rl, type, *rid); if (rle == NULL) - panic("pci_alloc_map: unexpectedly can't find resource."); + panic("pci_reserve_map: unexpectedly can't find resource."); rle->res = res; rle->start = rman_get_start(res); rle->end = rman_get_end(res); rle->count = count; + rle->flags = RLE_RESERVED; if (bootverbose) device_printf(child, "Lazy allocation of %#lx bytes rid %#x type %d at %#lx\n", count, *rid, type, rman_get_start(res)); map = rman_get_start(res); pci_write_bar(child, pm, map); -out:; +out: return (res); } @@ -4080,34 +4236,13 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, } } #endif - /* Allocate resources for this BAR if needed. */ + /* Reserve resources for this BAR if needed. */ rle = resource_list_find(rl, type, *rid); if (rle == NULL) { - res = pci_alloc_map(dev, child, type, rid, start, end, + res = pci_reserve_map(dev, child, type, rid, start, end, count, flags); if (res == NULL) return (NULL); - rle = resource_list_find(rl, type, *rid); - } - - /* - * If the resource belongs to the bus, then give it to - * the child. We need to activate it if requested - * since the bus always allocates inactive resources. - */ - if (rle != NULL && rle->res != NULL && - rman_get_device(rle->res) == dev) { - if (bootverbose) - device_printf(child, - "Reserved %#lx bytes for rid %#x type %d at %#lx\n", - rman_get_size(rle->res), *rid, type, - rman_get_start(rle->res)); - rman_set_device(rle->res, child); - if ((flags & RF_ACTIVE) && - bus_activate_resource(child, type, *rid, - rle->res) != 0) - return (NULL); - return (rle->res); } } return (resource_list_alloc(rl, dev, child, type, rid, @@ -4115,37 +4250,6 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, } int -pci_release_resource(device_t dev, device_t child, int type, int rid, - struct resource *r) -{ - int error; - - if (device_get_parent(child) != dev) - return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - type, rid, r)); - - /* - * For BARs we don't actually want to release the resource. - * Instead, we deactivate the resource if needed and then give - * ownership of the BAR back to the bus. - */ - switch (type) { - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - if (rman_get_device(r) != child) - return (EINVAL); - if (rman_get_flags(r) & RF_ACTIVE) { - error = bus_deactivate_resource(child, type, rid, r); - if (error) - return (error); - } - rman_set_device(r, dev); - return (0); - } - return (bus_generic_rl_release_resource(dev, child, type, rid, r)); -} - -int pci_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { @@ -4195,6 +4299,46 @@ pci_deactivate_resource(device_t dev, device_t child, int type, } void +pci_delete_child(device_t dev, device_t child) +{ + struct resource_list_entry *rle; + struct resource_list *rl; + struct pci_devinfo *dinfo; + + dinfo = device_get_ivars(child); + rl = &dinfo->resources; + + if (device_is_attached(child)) + device_detach(child); + + /* Turn off access to resources we're about to free */ + pci_write_config(child, PCIR_COMMAND, pci_read_config(child, + PCIR_COMMAND, 2) & ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN), 2); + + /* Free all allocated resources */ + STAILQ_FOREACH(rle, rl, link) { + if (rle->res) { + if (rman_get_flags(rle->res) & RF_ACTIVE || + resource_list_busy(rl, rle->type, rle->rid)) { + pci_printf(&dinfo->cfg, + "Resource still owned, oops. " + "(type=%d, rid=%d, addr=%lx)\n", + rle->type, rle->rid, + rman_get_start(rle->res)); + bus_release_resource(child, rle->type, rle->rid, + rle->res); + } + resource_list_unreserve(rl, dev, child, rle->type, + rle->rid); + } + } + resource_list_free(rl); + + device_delete_child(dev, child); + pci_freecfg(dinfo); +} + +void pci_delete_resource(device_t dev, device_t child, int type, int rid) { struct pci_devinfo *dinfo; @@ -4211,29 +4355,15 @@ pci_delete_resource(device_t dev, device_t child, int type, int rid) return; if (rle->res) { - if (rman_get_device(rle->res) != dev || - rman_get_flags(rle->res) & RF_ACTIVE) { + if (rman_get_flags(rle->res) & RF_ACTIVE || + resource_list_busy(rl, type, rid)) { device_printf(dev, "delete_resource: " "Resource still owned by child, oops. " "(type=%d, rid=%d, addr=%lx)\n", - rle->type, rle->rid, - rman_get_start(rle->res)); + type, rid, rman_get_start(rle->res)); return; } - -#ifndef __PCI_BAR_ZERO_VALID - /* - * If this is a BAR, clear the BAR so it stops - * decoding before releasing the resource. - */ - switch (type) { - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - pci_write_bar(child, pci_find_bar(child, rid), 0); - break; - } -#endif - bus_release_resource(dev, type, rid, rle->res); + resource_list_unreserve(rl, dev, child, type, rid); } resource_list_delete(rl, type, rid); } @@ -4344,7 +4474,7 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo) * Other types are unknown, and we err on the side of safety * by ignoring them. */ - if (dinfo->cfg.hdrtype != 0) + if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL) return; /* @@ -4388,7 +4518,7 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) * we err on the side of safety by ignoring them. Powering down * bridges should not be undertaken lightly. */ - if (dinfo->cfg.hdrtype != 0) + if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL) return; /* diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c index b0951024..bfaabf35 100644 --- a/freebsd/sys/dev/pci/pci_pci.c +++ b/freebsd/sys/dev/pci/pci_pci.c @@ -40,23 +40,24 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/sys/param.h> #include <sys/bus.h> #include <sys/kernel.h> -#include <sys/libkern.h> #include <sys/malloc.h> #include <sys/module.h> #include <sys/rman.h> #include <sys/sysctl.h> #include <sys/systm.h> -#include <machine/bus.h> -#include <machine/resource.h> - #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> +#include <dev/pci/pci_private.h> #include <dev/pci/pcib_private.h> #include <rtems/bsd/local/pcib_if.h> static int pcib_probe(device_t dev); +static int pcib_suspend(device_t dev); +static int pcib_resume(device_t dev); +static int pcib_power_for_sleep(device_t pcib, device_t dev, + int *pstate); static device_method_t pcib_methods[] = { /* Device interface */ @@ -64,8 +65,8 @@ static device_method_t pcib_methods[] = { DEVMETHOD(device_attach, pcib_attach), DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, pcib_suspend), + DEVMETHOD(device_resume, pcib_resume), /* Bus interface */ DEVMETHOD(bus_read_ivar, pcib_read_ivar), @@ -93,6 +94,7 @@ static device_method_t pcib_methods[] = { DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix), DEVMETHOD(pcib_release_msix, pcib_release_msix), DEVMETHOD(pcib_map_msi, pcib_map_msi), + DEVMETHOD(pcib_power_for_sleep, pcib_power_for_sleep), DEVMETHOD_END }; @@ -100,7 +102,7 @@ static device_method_t pcib_methods[] = { static devclass_t pcib_devclass; DEFINE_CLASS_0(pcib, pcib_driver, pcib_methods, sizeof(struct pcib_softc)); -DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); +DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, NULL, NULL); #ifdef NEW_PCIB /* @@ -365,7 +367,161 @@ pcib_is_io_open(struct pcib_softc *sc) { return (sc->iobase > 0 && sc->iobase < sc->iolimit); } + +/* + * Get current I/O decode. + */ +static void +pcib_get_io_decode(struct pcib_softc *sc) +{ + device_t dev; + uint32_t iolow; + + dev = sc->dev; + + iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); + if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) + sc->iobase = PCI_PPBIOBASE( + pci_read_config(dev, PCIR_IOBASEH_1, 2), iolow); + else + sc->iobase = PCI_PPBIOBASE(0, iolow); + + iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); + if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) + sc->iolimit = PCI_PPBIOLIMIT( + pci_read_config(dev, PCIR_IOLIMITH_1, 2), iolow); + else + sc->iolimit = PCI_PPBIOLIMIT(0, iolow); +} + +/* + * Get current memory decode. + */ +static void +pcib_get_mem_decode(struct pcib_softc *sc) +{ + device_t dev; + pci_addr_t pmemlow; + + dev = sc->dev; + + sc->membase = PCI_PPBMEMBASE(0, + pci_read_config(dev, PCIR_MEMBASE_1, 2)); + sc->memlimit = PCI_PPBMEMLIMIT(0, + pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); + + pmemlow = pci_read_config(dev, PCIR_PMBASEL_1, 2); + if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) + sc->pmembase = PCI_PPBMEMBASE( + pci_read_config(dev, PCIR_PMBASEH_1, 4), pmemlow); + else + sc->pmembase = PCI_PPBMEMBASE(0, pmemlow); + + pmemlow = pci_read_config(dev, PCIR_PMLIMITL_1, 2); + if ((pmemlow & PCIM_BRPM_MASK) == PCIM_BRPM_64) + sc->pmemlimit = PCI_PPBMEMLIMIT( + pci_read_config(dev, PCIR_PMLIMITH_1, 4), pmemlow); + else + sc->pmemlimit = PCI_PPBMEMLIMIT(0, pmemlow); +} + +/* + * Restore previous I/O decode. + */ +static void +pcib_set_io_decode(struct pcib_softc *sc) +{ + device_t dev; + uint32_t iohi; + + dev = sc->dev; + + iohi = sc->iobase >> 16; + if (iohi > 0) + pci_write_config(dev, PCIR_IOBASEH_1, iohi, 2); + pci_write_config(dev, PCIR_IOBASEL_1, sc->iobase >> 8, 1); + + iohi = sc->iolimit >> 16; + if (iohi > 0) + pci_write_config(dev, PCIR_IOLIMITH_1, iohi, 2); + pci_write_config(dev, PCIR_IOLIMITL_1, sc->iolimit >> 8, 1); +} + +/* + * Restore previous memory decode. + */ +static void +pcib_set_mem_decode(struct pcib_softc *sc) +{ + device_t dev; + pci_addr_t pmemhi; + + dev = sc->dev; + + pci_write_config(dev, PCIR_MEMBASE_1, sc->membase >> 16, 2); + pci_write_config(dev, PCIR_MEMLIMIT_1, sc->memlimit >> 16, 2); + + pmemhi = sc->pmembase >> 32; + if (pmemhi > 0) + pci_write_config(dev, PCIR_PMBASEH_1, pmemhi, 4); + pci_write_config(dev, PCIR_PMBASEL_1, sc->pmembase >> 16, 2); + + pmemhi = sc->pmemlimit >> 32; + if (pmemhi > 0) + pci_write_config(dev, PCIR_PMLIMITH_1, pmemhi, 4); + pci_write_config(dev, PCIR_PMLIMITL_1, sc->pmemlimit >> 16, 2); +} +#endif + +/* + * Get current bridge configuration. + */ +static void +pcib_cfg_save(struct pcib_softc *sc) +{ + device_t dev; + + dev = sc->dev; + + sc->command = pci_read_config(dev, PCIR_COMMAND, 2); + sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1); + sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); + sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); + sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); + sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); +#ifndef NEW_PCIB + if (sc->command & PCIM_CMD_PORTEN) + pcib_get_io_decode(sc); + if (sc->command & PCIM_CMD_MEMEN) + pcib_get_mem_decode(sc); +#endif +} + +/* + * Restore previous bridge configuration. + */ +static void +pcib_cfg_restore(struct pcib_softc *sc) +{ + device_t dev; + + dev = sc->dev; + + pci_write_config(dev, PCIR_COMMAND, sc->command, 2); + pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1); + pci_write_config(dev, PCIR_SECBUS_1, sc->secbus, 1); + pci_write_config(dev, PCIR_SUBBUS_1, sc->subbus, 1); + pci_write_config(dev, PCIR_BRIDGECTL_1, sc->bridgectl, 2); + pci_write_config(dev, PCIR_SECLAT_1, sc->seclat, 1); +#ifdef NEW_PCIB + pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM); +#else + if (sc->command & PCIM_CMD_PORTEN) + pcib_set_io_decode(sc); + if (sc->command & PCIM_CMD_MEMEN) + pcib_set_mem_decode(sc); #endif +} /* * Generic device interface @@ -385,9 +541,6 @@ void pcib_attach_common(device_t dev) { struct pcib_softc *sc; -#ifndef NEW_PCIB - uint8_t iolow; -#endif struct sysctl_ctx_list *sctx; struct sysctl_oid *soid; @@ -397,14 +550,9 @@ pcib_attach_common(device_t dev) /* * Get current bridge configuration. */ - sc->command = pci_read_config(dev, PCIR_COMMAND, 1); - sc->domain = pci_get_domain(dev); - sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1); - sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1); - sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1); - sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); - sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2); - sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1); + sc->domain = pci_get_domain(dev); + sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2); + pcib_cfg_save(sc); /* * Setup sysctl reporting nodes @@ -420,53 +568,6 @@ pcib_attach_common(device_t dev) SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus", CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number"); -#ifndef NEW_PCIB - /* - * Determine current I/O decode. - */ - if (sc->command & PCIM_CMD_PORTEN) { - iolow = pci_read_config(dev, PCIR_IOBASEL_1, 1); - if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { - sc->iobase = PCI_PPBIOBASE(pci_read_config(dev, PCIR_IOBASEH_1, 2), - pci_read_config(dev, PCIR_IOBASEL_1, 1)); - } else { - sc->iobase = PCI_PPBIOBASE(0, pci_read_config(dev, PCIR_IOBASEL_1, 1)); - } - - iolow = pci_read_config(dev, PCIR_IOLIMITL_1, 1); - if ((iolow & PCIM_BRIO_MASK) == PCIM_BRIO_32) { - sc->iolimit = PCI_PPBIOLIMIT(pci_read_config(dev, PCIR_IOLIMITH_1, 2), - pci_read_config(dev, PCIR_IOLIMITL_1, 1)); - } else { - sc->iolimit = PCI_PPBIOLIMIT(0, pci_read_config(dev, PCIR_IOLIMITL_1, 1)); - } - } - - /* - * Determine current memory decode. - */ - if (sc->command & PCIM_CMD_MEMEN) { - sc->membase = PCI_PPBMEMBASE(0, pci_read_config(dev, PCIR_MEMBASE_1, 2)); - sc->memlimit = PCI_PPBMEMLIMIT(0, pci_read_config(dev, PCIR_MEMLIMIT_1, 2)); - iolow = pci_read_config(dev, PCIR_PMBASEL_1, 1); - if ((iolow & PCIM_BRPM_MASK) == PCIM_BRPM_64) - sc->pmembase = PCI_PPBMEMBASE( - pci_read_config(dev, PCIR_PMBASEH_1, 4), - pci_read_config(dev, PCIR_PMBASEL_1, 2)); - else - sc->pmembase = PCI_PPBMEMBASE(0, - pci_read_config(dev, PCIR_PMBASEL_1, 2)); - iolow = pci_read_config(dev, PCIR_PMLIMITL_1, 1); - if ((iolow & PCIM_BRPM_MASK) == PCIM_BRPM_64) - sc->pmemlimit = PCI_PPBMEMLIMIT( - pci_read_config(dev, PCIR_PMLIMITH_1, 4), - pci_read_config(dev, PCIR_PMLIMITL_1, 2)); - else - sc->pmemlimit = PCI_PPBMEMLIMIT(0, - pci_read_config(dev, PCIR_PMLIMITL_1, 2)); - } -#endif - /* * Quirk handling. */ @@ -527,6 +628,9 @@ pcib_attach_common(device_t dev) if (pci_msi_device_blacklisted(dev)) sc->flags |= PCIB_DISABLE_MSI; + if (pci_msix_device_blacklisted(dev)) + sc->flags |= PCIB_DISABLE_MSIX; + /* * Intel 815, 845 and other chipsets say they are PCI-PCI bridges, * but have a ProgIF of 0x80. The 82801 family (AA, AB, BAM/CAM, @@ -614,6 +718,37 @@ pcib_attach(device_t dev) } int +pcib_suspend(device_t dev) +{ + device_t pcib; + int dstate, error; + + pcib_cfg_save(device_get_softc(dev)); + error = bus_generic_suspend(dev); + if (error == 0 && pci_do_power_suspend) { + dstate = PCI_POWERSTATE_D3; + pcib = device_get_parent(device_get_parent(dev)); + if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) + pci_set_powerstate(dev, dstate); + } + return (error); +} + +int +pcib_resume(device_t dev) +{ + device_t pcib; + + if (pci_do_power_resume) { + pcib = device_get_parent(device_get_parent(dev)); + if (PCIB_POWER_FOR_SLEEP(pcib, dev, NULL) == 0) + pci_set_powerstate(dev, PCI_POWERSTATE_D0); + } + pcib_cfg_restore(device_get_softc(dev)); + return (bus_generic_resume(dev)); +} + +int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct pcib_softc *sc = device_get_softc(dev); @@ -645,18 +780,6 @@ pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) } #ifdef NEW_PCIB -static const char * -pcib_child_name(device_t child) -{ - static char buf[64]; - - if (device_get_nameunit(child) != NULL) - return (device_get_nameunit(child)); - snprintf(buf, sizeof(buf), "pci%d:%d:%d:%d", pci_get_domain(child), - pci_get_bus(child), pci_get_slot(child), pci_get_function(child)); - return (buf); -} - /* * Attempt to allocate a resource from the existing resources assigned * to a window. @@ -1263,7 +1386,7 @@ pcib_alloc_msix(device_t pcib, device_t dev, int *irq) struct pcib_softc *sc = device_get_softc(pcib); device_t bus; - if (sc->flags & PCIB_DISABLE_MSI) + if (sc->flags & PCIB_DISABLE_MSIX) return (ENXIO); bus = device_get_parent(pcib); return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); @@ -1296,90 +1419,12 @@ pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, return (0); } -/* - * Try to read the bus number of a host-PCI bridge using appropriate config - * registers. - */ +/* Pass request for device power state up to parent bridge. */ int -host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, - uint8_t *busnum) +pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate) { - uint32_t id; - - id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); - if (id == 0xffffffff) - return (0); - - switch (id) { - case 0x12258086: - /* Intel 824?? */ - /* XXX This is a guess */ - /* *busnum = read_config(bus, slot, func, 0x41, 1); */ - *busnum = bus; - break; - case 0x84c48086: - /* Intel 82454KX/GX (Orion) */ - *busnum = read_config(bus, slot, func, 0x4a, 1); - break; - case 0x84ca8086: - /* - * For the 450nx chipset, there is a whole bundle of - * things pretending to be host bridges. The MIOC will - * be seen first and isn't really a pci bridge (the - * actual busses are attached to the PXB's). We need to - * read the registers of the MIOC to figure out the - * bus numbers for the PXB channels. - * - * Since the MIOC doesn't have a pci bus attached, we - * pretend it wasn't there. - */ - return (0); - case 0x84cb8086: - switch (slot) { - case 0x12: - /* Intel 82454NX PXB#0, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd0, 1); - break; - case 0x13: - /* Intel 82454NX PXB#0, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; - break; - case 0x14: - /* Intel 82454NX PXB#1, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd3, 1); - break; - case 0x15: - /* Intel 82454NX PXB#1, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; - break; - } - break; - - /* ServerWorks -- vendor 0x1166 */ - case 0x00051166: - case 0x00061166: - case 0x00081166: - case 0x00091166: - case 0x00101166: - case 0x00111166: - case 0x00171166: - case 0x01011166: - case 0x010f1014: - case 0x01101166: - case 0x02011166: - case 0x02251166: - case 0x03021014: - *busnum = read_config(bus, slot, func, 0x44, 1); - break; - - /* Compaq/HP -- vendor 0x0e11 */ - case 0x60100e11: - *busnum = read_config(bus, slot, func, 0xc8, 1); - break; - default: - /* Don't know how to read bus number. */ - return 0; - } + device_t bus; - return 1; + bus = device_get_parent(pcib); + return (PCIB_POWER_FOR_SLEEP(bus, dev, pstate)); } diff --git a/freebsd/sys/dev/pci/pci_private.h b/freebsd/sys/dev/pci/pci_private.h index b3ff50d5..b8e446ea 100644 --- a/freebsd/sys/dev/pci/pci_private.h +++ b/freebsd/sys/dev/pci/pci_private.h @@ -42,12 +42,16 @@ struct pci_softc { bus_dma_tag_t sc_dma_tag; }; +extern int pci_do_power_resume; +extern int pci_do_power_suspend; + void pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size); void pci_add_child(device_t bus, struct pci_devinfo *dinfo); void pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask); int pci_attach_common(device_t dev); +void pci_delete_child(device_t dev, device_t child); void pci_driver_added(device_t dev, driver_t *driver); int pci_print_child(device_t dev, device_t child); void pci_probe_nomatch(device_t dev, device_t child); @@ -87,8 +91,6 @@ int pci_msix_count_method(device_t dev, device_t child); struct resource *pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags); -int pci_release_resource(device_t dev, device_t child, int type, - int rid, struct resource *r); int pci_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r); int pci_deactivate_resource(device_t dev, device_t child, int type, diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c index c2723ad3..63d64c39 100644 --- a/freebsd/sys/dev/pci/pci_user.c +++ b/freebsd/sys/dev/pci/pci_user.c @@ -227,6 +227,51 @@ struct pci_io_old { u_int32_t pi_data; /* data to write or result of read */ }; +#ifdef COMPAT_FREEBSD32 +struct pci_conf_old32 { + struct pcisel_old pc_sel; /* bus+slot+function */ + uint8_t pc_hdr; /* PCI header type */ + uint16_t pc_subvendor; /* card vendor ID */ + uint16_t pc_subdevice; /* card device ID, assigned by + card vendor */ + uint16_t pc_vendor; /* chip vendor ID */ + uint16_t pc_device; /* chip device ID, assigned by + chip vendor */ + uint8_t pc_class; /* chip PCI class */ + uint8_t pc_subclass; /* chip PCI subclass */ + uint8_t pc_progif; /* chip PCI programming interface */ + uint8_t pc_revid; /* chip revision ID */ + char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ + uint32_t pd_unit; /* device unit number (u_long) */ +}; + +struct pci_match_conf_old32 { + struct pcisel_old pc_sel; /* bus+slot+function */ + char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ + uint32_t pd_unit; /* Unit number (u_long) */ + uint16_t pc_vendor; /* PCI Vendor ID */ + uint16_t pc_device; /* PCI Device ID */ + uint8_t pc_class; /* PCI class */ + pci_getconf_flags_old flags; /* Matching expression */ +}; + +struct pci_conf_io32 { + uint32_t pat_buf_len; /* pattern buffer length */ + uint32_t num_patterns; /* number of patterns */ + uint32_t patterns; /* pattern buffer + (struct pci_match_conf_old32 *) */ + uint32_t match_buf_len; /* match buffer length */ + uint32_t num_matches; /* number of matches returned */ + uint32_t matches; /* match buffer + (struct pci_conf_old32 *) */ + uint32_t offset; /* offset into device list */ + uint32_t generation; /* device list generation */ + pci_getconf_status status; /* request status */ +}; + +#define PCIOCGETCONF_OLD32 _IOWR('p', 1, struct pci_conf_io32) +#endif /* COMPAT_FREEBSD32 */ + #define PCIOCGETCONF_OLD _IOWR('p', 1, struct pci_conf_io) #define PCIOCREAD_OLD _IOWR('p', 2, struct pci_io_old) #define PCIOCWRITE_OLD _IOWR('p', 3, struct pci_io_old) @@ -297,7 +342,71 @@ pci_conf_match_old(struct pci_match_conf_old *matches, int num_matches, return(1); } -#endif +#ifdef COMPAT_FREEBSD32 +static int +pci_conf_match_old32(struct pci_match_conf_old32 *matches, int num_matches, + struct pci_conf *match_buf) +{ + int i; + + if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0)) + return(1); + + for (i = 0; i < num_matches; i++) { + if (match_buf->pc_sel.pc_domain != 0) + continue; + + /* + * I'm not sure why someone would do this...but... + */ + if (matches[i].flags == PCI_GETCONF_NO_MATCH_OLD) + continue; + + /* + * Look at each of the match flags. If it's set, do the + * comparison. If the comparison fails, we don't have a + * match, go on to the next item if there is one. + */ + if (((matches[i].flags & PCI_GETCONF_MATCH_BUS_OLD) != 0) && + (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_DEV_OLD) != 0) && + (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC_OLD) != 0) && + (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR_OLD) != 0) && + (match_buf->pc_vendor != matches[i].pc_vendor)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE_OLD) != 0) && + (match_buf->pc_device != matches[i].pc_device)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS_OLD) != 0) && + (match_buf->pc_class != matches[i].pc_class)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT_OLD) != 0) && + ((u_int32_t)match_buf->pd_unit != matches[i].pd_unit)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_NAME_OLD) != 0) && + (strncmp(matches[i].pd_name, match_buf->pd_name, + sizeof(match_buf->pd_name)) != 0)) + continue; + + return (0); + } + + return (1); +} +#endif /* COMPAT_FREEBSD32 */ +#endif /* PRE7_COMPAT */ static int pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) @@ -306,7 +415,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t void *confdata; const char *name; struct devlist *devlist_head; - struct pci_conf_io *cio; + struct pci_conf_io *cio = NULL; struct pci_devinfo *dinfo; struct pci_io *io; struct pci_bar_io *bio; @@ -315,13 +424,17 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t size_t confsz, iolen, pbufsz; int error, ionum, i, num_patterns; #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + struct pci_conf_io32 *cio32 = NULL; + struct pci_conf_old32 conf_old32; + struct pci_match_conf_old32 *pattern_buf_old32 = NULL; +#endif struct pci_conf_old conf_old; struct pci_io iodata; struct pci_io_old *io_old; - struct pci_match_conf_old *pattern_buf_old; + struct pci_match_conf_old *pattern_buf_old = NULL; io_old = NULL; - pattern_buf_old = NULL; if (!(flag & FWRITE) && cmd != PCIOCGETBAR && cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD) @@ -333,11 +446,36 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t switch(cmd) { #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + case PCIOCGETCONF_OLD32: + cio32 = (struct pci_conf_io32 *)data; + cio = malloc(sizeof(struct pci_conf_io), M_TEMP, M_WAITOK); + cio->pat_buf_len = cio32->pat_buf_len; + cio->num_patterns = cio32->num_patterns; + cio->patterns = (void *)(uintptr_t)cio32->patterns; + cio->match_buf_len = cio32->match_buf_len; + cio->num_matches = cio32->num_matches; + cio->matches = (void *)(uintptr_t)cio32->matches; + cio->offset = cio32->offset; + cio->generation = cio32->generation; + cio->status = cio32->status; + cio32->num_matches = 0; + break; +#endif case PCIOCGETCONF_OLD: - /* FALLTHROUGH */ #endif case PCIOCGETCONF: cio = (struct pci_conf_io *)data; + } + + switch(cmd) { +#ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + case PCIOCGETCONF_OLD32: +#endif + case PCIOCGETCONF_OLD: +#endif + case PCIOCGETCONF: pattern_buf = NULL; num_patterns = 0; @@ -355,7 +493,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t && (cio->generation != pci_generation)){ cio->status = PCI_GETCONF_LIST_CHANGED; error = 0; - break; + goto getconfexit; } /* @@ -365,7 +503,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t if (cio->offset >= pci_numdevs) { cio->status = PCI_GETCONF_LAST_DEVICE; error = 0; - break; + goto getconfexit; } /* get the head of the device queue */ @@ -378,6 +516,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t * didn't specify a multiple of that size. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) + confsz = sizeof(struct pci_conf_old32); + else +#endif if (cmd == PCIOCGETCONF_OLD) confsz = sizeof(struct pci_conf_old); else @@ -412,6 +555,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t * updated their kernel but not their userland. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) + pbufsz = sizeof(struct pci_match_conf_old32); + else +#endif if (cmd == PCIOCGETCONF_OLD) pbufsz = sizeof(struct pci_match_conf_old); else @@ -421,20 +569,28 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t /* The user made a mistake, return an error. */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; - break; + goto getconfexit; } /* * Allocate a buffer to hold the patterns. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) { + pattern_buf_old32 = malloc(cio->pat_buf_len, + M_TEMP, M_WAITOK); + error = copyin(cio->patterns, + pattern_buf_old32, cio->pat_buf_len); + } else +#endif /* COMPAT_FREEBSD32 */ if (cmd == PCIOCGETCONF_OLD) { pattern_buf_old = malloc(cio->pat_buf_len, M_TEMP, M_WAITOK); error = copyin(cio->patterns, pattern_buf_old, cio->pat_buf_len); } else -#endif +#endif /* PRE7_COMPAT */ { pattern_buf = malloc(cio->pat_buf_len, M_TEMP, M_WAITOK); @@ -453,7 +609,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; - break; + goto getconfexit; } /* @@ -485,7 +641,14 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t } #ifdef PRE7_COMPAT - if ((cmd == PCIOCGETCONF_OLD && + if ( +#ifdef COMPAT_FREEBSD32 + (cmd == PCIOCGETCONF_OLD32 && + (pattern_buf_old32 == NULL || + pci_conf_match_old32(pattern_buf_old32, + num_patterns, &dinfo->conf) == 0)) || +#endif + (cmd == PCIOCGETCONF_OLD && (pattern_buf_old == NULL || pci_conf_match_old(pattern_buf_old, num_patterns, &dinfo->conf) == 0)) || @@ -510,6 +673,40 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t break; #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) { + conf_old32.pc_sel.pc_bus = + dinfo->conf.pc_sel.pc_bus; + conf_old32.pc_sel.pc_dev = + dinfo->conf.pc_sel.pc_dev; + conf_old32.pc_sel.pc_func = + dinfo->conf.pc_sel.pc_func; + conf_old32.pc_hdr = dinfo->conf.pc_hdr; + conf_old32.pc_subvendor = + dinfo->conf.pc_subvendor; + conf_old32.pc_subdevice = + dinfo->conf.pc_subdevice; + conf_old32.pc_vendor = + dinfo->conf.pc_vendor; + conf_old32.pc_device = + dinfo->conf.pc_device; + conf_old32.pc_class = + dinfo->conf.pc_class; + conf_old32.pc_subclass = + dinfo->conf.pc_subclass; + conf_old32.pc_progif = + dinfo->conf.pc_progif; + conf_old32.pc_revid = + dinfo->conf.pc_revid; + strncpy(conf_old32.pd_name, + dinfo->conf.pd_name, + sizeof(conf_old32.pd_name)); + conf_old32.pd_name[PCI_MAXNAMELEN] = 0; + conf_old32.pd_unit = + (uint32_t)dinfo->conf.pd_unit; + confdata = &conf_old32; + } else +#endif /* COMPAT_FREEBSD32 */ if (cmd == PCIOCGETCONF_OLD) { conf_old.pc_sel.pc_bus = dinfo->conf.pc_sel.pc_bus; @@ -542,7 +739,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t dinfo->conf.pd_unit; confdata = &conf_old; } else -#endif +#endif /* PRE7_COMPAT */ confdata = &dinfo->conf; /* Only if we can copy it out do we count it. */ if (!(error = copyout(confdata, @@ -576,12 +773,23 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t cio->status = PCI_GETCONF_MORE_DEVS; getconfexit: - if (pattern_buf != NULL) - free(pattern_buf, M_TEMP); #ifdef PRE7_COMPAT +#ifdef COMPAT_FREEBSD32 + if (cmd == PCIOCGETCONF_OLD32) { + cio32->status = cio->status; + cio32->generation = cio->generation; + cio32->offset = cio->offset; + cio32->num_matches = cio->num_matches; + free(cio, M_TEMP); + } + if (pattern_buf_old32 != NULL) + free(pattern_buf_old32, M_TEMP); +#endif if (pattern_buf_old != NULL) free(pattern_buf_old, M_TEMP); #endif + if (pattern_buf != NULL) + free(pattern_buf, M_TEMP); break; @@ -696,6 +904,16 @@ getconfexit: bio->pbi_enabled = pci_bar_enabled(pcidev, pm); error = 0; break; + case PCIOCATTACHED: + error = 0; + io = (struct pci_io *)data; + pcidev = pci_find_dbsf(io->pi_sel.pc_domain, io->pi_sel.pc_bus, + io->pi_sel.pc_dev, io->pi_sel.pc_func); + if (pcidev != NULL) + io->pi_data = device_is_attached(pcidev); + else + error = ENODEV; + break; default: error = ENOTTY; break; diff --git a/freebsd/sys/dev/pci/pcib_private.h b/freebsd/sys/dev/pci/pcib_private.h index 1574deb7..79135afa 100644 --- a/freebsd/sys/dev/pci/pcib_private.h +++ b/freebsd/sys/dev/pci/pcib_private.h @@ -33,6 +33,31 @@ #ifndef __PCIB_PRIVATE_H__ #define __PCIB_PRIVATE_H__ +#ifdef NEW_PCIB +/* + * Data structure and routines that Host to PCI bridge drivers can use + * to restrict allocations for child devices to ranges decoded by the + * bridge. + */ +struct pcib_host_resources { + device_t hr_pcib; + struct resource_list hr_rl; +}; + +int pcib_host_res_init(device_t pcib, + struct pcib_host_resources *hr); +int pcib_host_res_free(device_t pcib, + struct pcib_host_resources *hr); +int pcib_host_res_decodes(struct pcib_host_resources *hr, int type, + u_long start, u_long end, u_int flags); +struct resource *pcib_host_res_alloc(struct pcib_host_resources *hr, + device_t dev, int type, int *rid, u_long start, u_long end, + u_long count, u_int flags); +int pcib_host_res_adjust(struct pcib_host_resources *hr, + device_t dev, int type, struct resource *r, u_long start, + u_long end); +#endif + /* * Export portions of generic PCI:PCI bridge support so that it can be * used by subclasses. @@ -66,6 +91,7 @@ struct pcib_softc uint32_t flags; /* flags */ #define PCIB_SUBTRACTIVE 0x1 #define PCIB_DISABLE_MSI 0x2 +#define PCIB_DISABLE_MSIX 0x4 uint16_t command; /* command register */ u_int domain; /* domain number */ u_int pribus; /* primary bus number */ @@ -90,6 +116,9 @@ struct pcib_softc typedef uint32_t pci_read_config_fn(int b, int s, int f, int reg, int width); +#ifdef NEW_PCIB +const char *pcib_child_name(device_t child); +#endif int host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, uint8_t *busnum); int pcib_attach(device_t dev); diff --git a/freebsd/sys/dev/pci/pcireg.h b/freebsd/sys/dev/pci/pcireg.h index 0127e776..ef351356 100644 --- a/freebsd/sys/dev/pci/pcireg.h +++ b/freebsd/sys/dev/pci/pcireg.h @@ -69,7 +69,6 @@ #define PCIM_STATUS_66CAPABLE 0x0020 #define PCIM_STATUS_BACKTOBACK 0x0080 #define PCIM_STATUS_MDPERR 0x0100 -#define PCIM_STATUS_PERRREPORT PCIM_STATUS_MDPERR #define PCIM_STATUS_SEL_FAST 0x0000 #define PCIM_STATUS_SEL_MEDIMUM 0x0200 #define PCIM_STATUS_SEL_SLOW 0x0400 @@ -445,12 +444,16 @@ #define PCIR_POWER_CAP 0x2 #define PCIM_PCAP_SPEC 0x0007 #define PCIM_PCAP_PMEREQCLK 0x0008 -#define PCIM_PCAP_PMEREQPWR 0x0010 #define PCIM_PCAP_DEVSPECINIT 0x0020 -#define PCIM_PCAP_DYNCLOCK 0x0040 -#define PCIM_PCAP_SECCLOCK 0x00c0 -#define PCIM_PCAP_CLOCKMASK 0x00c0 -#define PCIM_PCAP_REQFULLCLOCK 0x0100 +#define PCIM_PCAP_AUXPWR_0 0x0000 +#define PCIM_PCAP_AUXPWR_55 0x0040 +#define PCIM_PCAP_AUXPWR_100 0x0080 +#define PCIM_PCAP_AUXPWR_160 0x00c0 +#define PCIM_PCAP_AUXPWR_220 0x0100 +#define PCIM_PCAP_AUXPWR_270 0x0140 +#define PCIM_PCAP_AUXPWR_320 0x0180 +#define PCIM_PCAP_AUXPWR_375 0x01c0 +#define PCIM_PCAP_AUXPWRMASK 0x01c0 #define PCIM_PCAP_D1SUPP 0x0200 #define PCIM_PCAP_D2SUPP 0x0400 #define PCIM_PCAP_D0PME 0x0800 @@ -465,16 +468,17 @@ #define PCIM_PSTAT_D2 0x0002 #define PCIM_PSTAT_D3 0x0003 #define PCIM_PSTAT_DMASK 0x0003 -#define PCIM_PSTAT_REPENABLE 0x0010 +#define PCIM_PSTAT_NOSOFTRESET 0x0008 #define PCIM_PSTAT_PMEENABLE 0x0100 #define PCIM_PSTAT_D0POWER 0x0000 #define PCIM_PSTAT_D1POWER 0x0200 #define PCIM_PSTAT_D2POWER 0x0400 #define PCIM_PSTAT_D3POWER 0x0600 #define PCIM_PSTAT_D0HEAT 0x0800 -#define PCIM_PSTAT_D1HEAT 0x1000 -#define PCIM_PSTAT_D2HEAT 0x1200 -#define PCIM_PSTAT_D3HEAT 0x1400 +#define PCIM_PSTAT_D1HEAT 0x0a00 +#define PCIM_PSTAT_D2HEAT 0x0c00 +#define PCIM_PSTAT_D3HEAT 0x0e00 +#define PCIM_PSTAT_DATASELMASK 0x1e00 #define PCIM_PSTAT_DATAUNKN 0x0000 #define PCIM_PSTAT_DATADIV10 0x2000 #define PCIM_PSTAT_DATADIV100 0x4000 @@ -482,11 +486,10 @@ #define PCIM_PSTAT_DATADIVMASK 0x6000 #define PCIM_PSTAT_PME 0x8000 -#define PCIR_POWER_PMCSR 0x6 -#define PCIM_PMCSR_DCLOCK 0x10 -#define PCIM_PMCSR_B2SUPP 0x20 -#define PCIM_BMCSR_B3SUPP 0x40 -#define PCIM_BMCSR_BPCE 0x80 +#define PCIR_POWER_BSE 0x6 +#define PCIM_PMCSR_BSE_D3B3 0x00 +#define PCIM_PMCSR_BSE_D3B2 0x40 +#define PCIM_PMCSR_BSE_BPCCE 0x80 #define PCIR_POWER_DATA 0x7 @@ -609,6 +612,10 @@ #define PCIM_HTCAP_VCSET 0xb800 /* 10111 */ #define PCIM_HTCAP_RETRY_MODE 0xc000 /* 11000 */ #define PCIM_HTCAP_X86_ENCODING 0xc800 /* 11001 */ +#define PCIM_HTCAP_GEN3 0xd000 /* 11010 */ +#define PCIM_HTCAP_FLE 0xd800 /* 11011 */ +#define PCIM_HTCAP_PM 0xe000 /* 11100 */ +#define PCIM_HTCAP_HIGH_NODE_COUNT 0xe800 /* 11101 */ /* HT MSI Mapping Capability definitions. */ #define PCIM_HTCMD_MSI_ENABLE 0x0001 @@ -770,7 +777,7 @@ #define PCIER_SLOT_CAP2 0x34 #define PCIER_SLOT_CTL2 0x38 #define PCIER_SLOT_STA2 0x3a - + /* Old compatibility definitions for PCI Express registers */ #define PCIR_EXPRESS_FLAGS PCIER_FLAGS #define PCIM_EXP_FLAGS_VERSION PCIEM_FLAGS_VERSION diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h index b0359d30..84e7c871 100644 --- a/freebsd/sys/dev/pci/pcivar.h +++ b/freebsd/sys/dev/pci/pcivar.h @@ -42,9 +42,9 @@ typedef uint64_t pci_addr_t; /* Interesting values for PCI power management */ struct pcicfg_pp { uint16_t pp_cap; /* PCI power management capabilities */ - uint8_t pp_status; /* config space address of PCI power status reg */ - uint8_t pp_pmcsr; /* config space address of PMCSR reg */ - uint8_t pp_data; /* config space address of PCI power data reg */ + uint8_t pp_status; /* conf. space addr. of PM control/status reg */ + uint8_t pp_bse; /* conf. space addr. of PM BSE reg */ + uint8_t pp_data; /* conf. space addr. of PM data reg */ }; struct pci_map { @@ -465,6 +465,7 @@ device_t pci_find_class(uint8_t class, uint8_t subclass); int pci_pending_msix(device_t dev, u_int index); int pci_msi_device_blacklisted(device_t dev); +int pci_msix_device_blacklisted(device_t dev); void pci_ht_map_msi(device_t dev, uint64_t addr); |