#include <linux/pci.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
struct list_head *tmp;
unsigned char max, n;
- max = bus->number;
+ max = bus->subordinate;
list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp));
if(n > max)
}
return max;
}
+EXPORT_SYMBOL_GPL(pci_bus_max_busnr);
+#if 0
/**
* pci_max_busnr - returns maximum PCI bus number
*
return max;
}
+#endif /* 0 */
+
+static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
+{
+ u8 id;
+ int ttl = 48;
+
+ while (ttl--) {
+ pci_bus_read_config_byte(bus, devfn, pos, &pos);
+ if (pos < 0x40)
+ break;
+ pos &= ~3;
+ pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
+ &id);
+ if (id == 0xff)
+ break;
+ if (id == cap)
+ return pos;
+ pos += PCI_CAP_LIST_NEXT;
+ }
+ return 0;
+}
+
+int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
+{
+ return __pci_find_next_cap(dev->bus, dev->devfn,
+ pos + PCI_CAP_LIST_NEXT, cap);
+}
+EXPORT_SYMBOL_GPL(pci_find_next_capability);
+
static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
{
u16 status;
- u8 pos, id;
- int ttl = 48;
+ u8 pos;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
switch (hdr_type) {
case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE:
- pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
+ pos = PCI_CAPABILITY_LIST;
break;
case PCI_HEADER_TYPE_CARDBUS:
- pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
+ pos = PCI_CB_CAPABILITY_LIST;
break;
default:
return 0;
}
- while (ttl-- && pos >= 0x40) {
- pos &= ~3;
- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
- if (id == 0xff)
- break;
- if (id == cap)
- return pos;
- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
- }
- return 0;
+ return __pci_find_next_cap(bus, devfn, pos, cap);
}
/**
return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
}
+#if 0
/**
* pci_find_ext_capability - Find an extended capability
* @dev: PCI device to query
return 0;
}
+#endif /* 0 */
/**
* pci_find_parent_resource - return resource region of parent bus of given region
pci_update_resource(dev, &dev->resource[i], i);
}
+int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
+
/**
* pci_set_power_state - Set the power state of a PCI device
* @dev: PCI device to be suspended
* -EIO if device does not support PCI PM.
* 0 if we can successfully change the power state.
*/
-int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
int
pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
* Can enter D0 from any state, but if we can only go deeper
* to sleep if we're already in a low power state
*/
- if (state != PCI_D0 && dev->current_state > state)
+ if (state != PCI_D0 && dev->current_state > state) {
+ printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
+ __FUNCTION__, pci_name(dev), state, dev->current_state);
return -EINVAL;
- else if (dev->current_state == state)
+ } else if (dev->current_state == state)
return 0; /* we're already there */
/* find PCI PM capability in list */
* sets PowerState to 0.
*/
switch (dev->current_state) {
+ case PCI_D0:
+ case PCI_D1:
+ case PCI_D2:
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pmcsr |= state;
+ break;
case PCI_UNKNOWN: /* Boot-up */
if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
&& !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
need_restore = 1;
/* Fall-through: force to D0 */
- case PCI_D3hot:
- case PCI_D3cold:
- case PCI_POWER_ERROR:
- pmcsr = 0;
- break;
default:
- pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
- pmcsr |= state;
+ pmcsr = 0;
break;
}
/* XXX: 100% dword access ok here? */
for (i = 0; i < 16; i++)
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
+ if ((i = pci_save_msi_state(dev)) != 0)
+ return i;
+ if ((i = pci_save_msix_state(dev)) != 0)
+ return i;
return 0;
}
for (i = 0; i < 16; i++)
pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]);
+ pci_restore_msi_state(dev);
+ pci_restore_msix_state(dev);
return 0;
}
int
pci_enable_device(struct pci_dev *dev)
{
- int err;
-
- if ((err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1)))
+ int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+ if (err)
return err;
pci_fixup_device(pci_fixup_enable, dev);
dev->is_enabled = 1;
{
u8 pin;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ pin = dev->pin;
if (!pin)
return -1;
pin--;
* Returns 0 on success, or %EBUSY on error. A warning
* message is also printed on failure.
*/
-int pci_request_region(struct pci_dev *pdev, int bar, char *res_name)
+int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
{
if (pci_resource_len(pdev, bar) == 0)
return 0;
* Returns 0 on success, or %EBUSY on error. A warning
* message is also printed on failure.
*/
-int pci_request_regions(struct pci_dev *pdev, char *res_name)
+int pci_request_regions(struct pci_dev *pdev, const char *res_name)
{
int i;
/**
* pci_intx - enables/disables PCI INTx for device dev
- * @dev: the PCI device to operate on
- * @enable: boolean
+ * @pdev: the PCI device to operate on
+ * @enable: boolean: whether to enable or disable PCI INTx
*
* Enables/disables PCI INTx for device dev
*/
if (k)
*k++ = 0;
if (*str && (str = pcibios_setup(str)) && *str) {
- /* PCI layer options should be handled here */
- printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
+ if (!strcmp(str, "nomsi")) {
+ pci_no_msi();
+ } else {
+ printk(KERN_ERR "PCI: Unknown option `%s'\n",
+ str);
+ }
}
str = k;
}
EXPORT_SYMBOL(pci_enable_device_bars);
EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_disable_device);
-EXPORT_SYMBOL(pci_max_busnr);
-EXPORT_SYMBOL(pci_bus_max_busnr);
EXPORT_SYMBOL(pci_find_capability);
EXPORT_SYMBOL(pci_bus_find_capability);
EXPORT_SYMBOL(pci_release_regions);