Commit d53e21af authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleeding_edge-2.5

into kroah.com:/home/greg/linux/BK/pci_hp-2.5
parents 9d1f716f 5fd66b2b
...@@ -2218,6 +2218,15 @@ S: 30 White Tail Lane ...@@ -2218,6 +2218,15 @@ S: 30 White Tail Lane
S: Lafayette, Indiana 47905 S: Lafayette, Indiana 47905
S: USA S: USA
N: Scott Murray
E: scottm@somanetworks.com
E: scott@spiteful.org
D: OPL3-SA2, OPL3-SA3 sound driver
D: CompactPCI hotplug core
D: Ziatech ZT5550 and generic CompactPCI hotplug drivers
S: Toronto, Ontario
S: Canada
N: Trond Myklebust N: Trond Myklebust
E: trond.myklebust@fys.uio.no E: trond.myklebust@fys.uio.no
D: current NFS client hacker. D: current NFS client hacker.
......
...@@ -317,6 +317,27 @@ L: codalist@coda.cs.cmu.edu ...@@ -317,6 +317,27 @@ L: codalist@coda.cs.cmu.edu
W: http://www.coda.cs.cmu.edu/ W: http://www.coda.cs.cmu.edu/
S: Maintained S: Maintained
COMPACTPCI HOTPLUG CORE
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
S: Supported
COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
S: Supported
COMPACTPCI HOTPLUG GENERIC DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
S: Supported
COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
P: Amy Vanzant-Hodge P: Amy Vanzant-Hodge
M: Amy Vanzant-Hodge (fibrechannel@compaq.com) M: Amy Vanzant-Hodge (fibrechannel@compaq.com)
......
...@@ -340,7 +340,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp) ...@@ -340,7 +340,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
return PCI_SLOT(dev->devfn); return PCI_SLOT(dev->devfn);
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus, pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges) struct pbus_set_ranges_data * ranges)
{ {
......
...@@ -90,6 +90,11 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) ...@@ -90,6 +90,11 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
} }
} }
void __devinit
pcibios_fixup_pbus_ranges (struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
{
}
/* /*
* Called after each bus is probed, but before its children * Called after each bus is probed, but before its children
* are examined. * are examined.
......
...@@ -138,7 +138,7 @@ static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d) ...@@ -138,7 +138,7 @@ static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
#define VIA_8363_KL133_REVISION_ID 0x81 #define VIA_8363_KL133_REVISION_ID 0x81
#define VIA_8363_KM133_REVISION_ID 0x84 #define VIA_8363_KM133_REVISION_ID 0x84
static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d) static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d)
{ {
u8 v; u8 v;
u8 revision; u8 revision;
...@@ -180,7 +180,7 @@ static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d) ...@@ -180,7 +180,7 @@ static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d)
* system to PCI bus no matter what are their window settings, so they are * system to PCI bus no matter what are their window settings, so they are
* "transparent" (or subtractive decoding) from programmers point of view. * "transparent" (or subtractive decoding) from programmers point of view.
*/ */
static void __init pci_fixup_transparent_bridge(struct pci_dev *dev) static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
{ {
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
(dev->device & 0xff00) == 0x2400) (dev->device & 0xff00) == 0x2400)
......
...@@ -297,8 +297,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) ...@@ -297,8 +297,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
} }
void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
struct pbus_set_ranges_data *ranges) struct pbus_set_ranges_data *ranges)
{ {
} }
......
...@@ -341,8 +341,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) ...@@ -341,8 +341,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
} }
void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
struct pbus_set_ranges_data *ranges) struct pbus_set_ranges_data *ranges)
{ {
/* /*
* our caller figure out range by going through the dev structures. * our caller figure out range by going through the dev structures.
......
...@@ -234,7 +234,7 @@ pcibios_fixup_bus(struct pci_bus *b) ...@@ -234,7 +234,7 @@ pcibios_fixup_bus(struct pci_bus *b)
pci_fixup_irqs(pci_swizzle, pci_map_irq); pci_fixup_irqs(pci_swizzle, pci_map_irq);
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus, pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges) struct pbus_set_ranges_data * ranges)
{ {
......
...@@ -349,8 +349,8 @@ void __init pcibios_fixup_bus (struct pci_bus *b) ...@@ -349,8 +349,8 @@ void __init pcibios_fixup_bus (struct pci_bus *b)
} }
/* XXX anybody know what this is supposed to do? */ /* XXX anybody know what this is supposed to do? */
void __init pcibios_fixup_pbus_ranges(struct pci_bus * bus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges) struct pbus_set_ranges_data * ranges)
{ {
} }
......
...@@ -345,7 +345,7 @@ pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) ...@@ -345,7 +345,7 @@ pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
/* /*
** called by drivers/pci/setup-res.c:pci_setup_bridge(). ** called by drivers/pci/setup-res.c:pci_setup_bridge().
*/ */
void pcibios_fixup_pbus_ranges( void __devinit pcibios_fixup_pbus_ranges(
struct pci_bus *bus, struct pci_bus *bus,
struct pbus_set_ranges_data *ranges struct pbus_set_ranges_data *ranges
) )
......
...@@ -1107,7 +1107,7 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp) ...@@ -1107,7 +1107,7 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp)
return PCI_SLOT(dev->devfn); return PCI_SLOT(dev->devfn);
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges) pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
{ {
} }
......
...@@ -121,8 +121,8 @@ static void fixup_windbond_82c105(struct pci_dev* dev) ...@@ -121,8 +121,8 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
} }
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges) struct pbus_set_ranges_data *pranges)
{ {
} }
......
...@@ -113,7 +113,7 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, ...@@ -113,7 +113,7 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size,
} }
void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
{ {
} }
......
...@@ -250,8 +250,8 @@ struct pci_fixup pcibios_fixups[] = { ...@@ -250,8 +250,8 @@ struct pci_fixup pcibios_fixups[] = {
{ 0 } { 0 }
}; };
void __init pcibios_fixup_pbus_ranges(struct pci_bus *b, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *b,
struct pbus_set_ranges_data *range) struct pbus_set_ranges_data *range)
{ {
/* No fixups needed */ /* No fixups needed */
} }
......
...@@ -380,7 +380,7 @@ static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) ...@@ -380,7 +380,7 @@ static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin)
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus *bus, pcibios_fixup_pbus_ranges(struct pci_bus *bus,
struct pbus_set_ranges_data *ranges) struct pbus_set_ranges_data *ranges)
{ {
......
...@@ -479,8 +479,8 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq) ...@@ -479,8 +479,8 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq)
{ {
} }
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges) struct pbus_set_ranges_data *pranges)
{ {
} }
......
...@@ -73,5 +73,48 @@ config HOTPLUG_PCI_ACPI ...@@ -73,5 +73,48 @@ config HOTPLUG_PCI_ACPI
When in doubt, say N. When in doubt, say N.
config HOTPLUG_PCI_CPCI
tristate "CompactPCI Hotplug driver"
depends on HOTPLUG_PCI
help
Say Y here if you have a CompactPCI system card with CompactPCI
hotswap support per the PICMG 2.1 specification.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cpci_hotplug.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
When in doubt, say N.
config HOTPLUG_PCI_CPCI_ZT5550
tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
depends on HOTPLUG_PCI_CPCI && X86
help
Say Y here if you have an Performance Technologies (formerly Intel,
formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cpcihp_zt5550.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
When in doubt, say N.
config HOTPLUG_PCI_CPCI_GENERIC
tristate "Generic port I/O CompactPCI Hotplug driver"
depends on HOTPLUG_PCI_CPCI && X86
help
Say Y here if you have a CompactPCI system card that exposes the #ENUM
hotswap signal as a bit in a system register that can be read through
standard port I/O.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cpcihp_generic.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
When in doubt, say N.
endmenu endmenu
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
# Makefile for the Linux kernel pci hotplug controller drivers. # Makefile for the Linux kernel pci hotplug controller drivers.
# #
export-objs := pci_hotplug_core.o pci_hotplug_util.o export-objs := pci_hotplug_core.o pci_hotplug_util.o cpci_hotplug_core.o
obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI) += cpci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
pci_hotplug-objs := pci_hotplug_core.o \ pci_hotplug-objs := pci_hotplug_core.o \
pci_hotplug_util.o pci_hotplug_util.o
...@@ -28,6 +31,9 @@ acpiphp-objs := acpiphp_core.o \ ...@@ -28,6 +31,9 @@ acpiphp-objs := acpiphp_core.o \
acpiphp_pci.o \ acpiphp_pci.o \
acpiphp_res.o acpiphp_res.o
cpci_hotplug-objs := cpci_hotplug_core.o \
cpci_hotplug_pci.o
ifdef CONFIG_HOTPLUG_PCI_ACPI ifdef CONFIG_HOTPLUG_PCI_ACPI
EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi
ifdef CONFIG_ACPI_DEBUG ifdef CONFIG_ACPI_DEBUG
......
...@@ -41,12 +41,12 @@ ...@@ -41,12 +41,12 @@
#define dbg(format, arg...) \ #define dbg(format, arg...) \
do { \ do { \
if (acpiphp_debug) \ if (acpiphp_debug) \
printk (KERN_DEBUG "%s: " format "\n", \ printk(KERN_DEBUG "%s: " format, \
MY_NAME , ## arg); \ MY_NAME , ## arg); \
} while (0) } while (0)
#define err(format, arg...) printk (KERN_ERR "%s: " format "\n", MY_NAME , ## arg) #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
#define info(format, arg...) printk (KERN_INFO "%s: " format "\n", MY_NAME , ## arg) #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk (KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
#define SLOT_MAGIC 0x67267322 #define SLOT_MAGIC 0x67267322
/* name size which is used for entries in pcihpfs */ /* name size which is used for entries in pcihpfs */
......
This diff is collapsed.
This diff is collapsed.
...@@ -77,7 +77,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -77,7 +77,7 @@ static int init_config_space (struct acpiphp_func *func)
if (!bar) /* This BAR is not implemented */ if (!bar) /* This BAR is not implemented */
continue; continue;
dbg("Device %02x.%02x BAR %d wants %x", device, function, count, bar); dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);
if (bar & PCI_BASE_ADDRESS_SPACE_IO) { if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */ /* This is IO */
...@@ -85,7 +85,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -85,7 +85,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFFC; len = bar & 0xFFFFFFFC;
len = ~len + 1; len = ~len + 1;
dbg ("len in IO %x, BAR %d", len, count); dbg("len in IO %x, BAR %d\n", len, count);
spin_lock(&bridge->res_lock); spin_lock(&bridge->res_lock);
res = acpiphp_get_io_resource(&bridge->io_head, len); res = acpiphp_get_io_resource(&bridge->io_head, len);
...@@ -110,7 +110,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -110,7 +110,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFF0; len = bar & 0xFFFFFFF0;
len = ~len + 1; len = ~len + 1;
dbg("len in PFMEM %x, BAR %d", len, count); dbg("len in PFMEM %x, BAR %d\n", len, count);
spin_lock(&bridge->res_lock); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource(&bridge->p_mem_head, len); res = acpiphp_get_resource(&bridge->p_mem_head, len);
...@@ -127,7 +127,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -127,7 +127,7 @@ static int init_config_space (struct acpiphp_func *func)
(u32)res->base); (u32)res->base);
if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
dbg ("inside the pfmem 64 case, count %d", count); dbg("inside the pfmem 64 case, count %d\n", count);
count += 1; count += 1;
pci_bus_write_config_dword(pbus, devfn, pci_bus_write_config_dword(pbus, devfn,
address[count], address[count],
...@@ -143,7 +143,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -143,7 +143,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFF0; len = bar & 0xFFFFFFF0;
len = ~len + 1; len = ~len + 1;
dbg("len in MEM %x, BAR %d", len, count); dbg("len in MEM %x, BAR %d\n", len, count);
spin_lock(&bridge->res_lock); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource(&bridge->mem_head, len); res = acpiphp_get_resource(&bridge->mem_head, len);
...@@ -161,7 +161,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -161,7 +161,7 @@ static int init_config_space (struct acpiphp_func *func)
if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */ /* takes up another dword */
dbg ("inside mem 64 case, reg. mem, count %d", count); dbg("inside mem 64 case, reg. mem, count %d\n", count);
count += 1; count += 1;
pci_bus_write_config_dword(pbus, devfn, pci_bus_write_config_dword(pbus, devfn,
address[count], address[count],
...@@ -212,16 +212,16 @@ static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bu ...@@ -212,16 +212,16 @@ static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bu
//pci_proc_attach_device(dev); //pci_proc_attach_device(dev);
//pci_announce_device_to_drivers(dev); //pci_announce_device_to_drivers(dev);
info("Device %s configured", dev->slot_name); info("Device %s configured\n", dev->slot_name);
return 0; return 0;
} }
static int is_pci_dev_in_use (struct pci_dev* dev) static int is_pci_dev_in_use (struct pci_dev* dev)
{ {
/* /*
* dev->driver will be set if the device is in use by a new-style * dev->driver will be set if the device is in use by a new-style
* driver -- otherwise, check the device's regions to see if any * driver -- otherwise, check the device's regions to see if any
* driver has claimed them * driver has claimed them
*/ */
...@@ -263,13 +263,13 @@ static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, stru ...@@ -263,13 +263,13 @@ static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, stru
{ {
struct pci_dev *dev = wrapped_dev->dev; struct pci_dev *dev = wrapped_dev->dev;
dbg("attempting removal of driver for device %s", dev->slot_name); dbg("attempting removal of driver for device %s\n", dev->slot_name);
/* Now, remove the Linux Driver Representation */ /* Now, remove the Linux Driver Representation */
if (dev->driver) { if (dev->driver) {
if (dev->driver->remove) { if (dev->driver->remove) {
dev->driver->remove(dev); dev->driver->remove(dev);
dbg("driver was properly removed"); dbg("driver was properly removed\n");
} }
dev->driver = NULL; dev->driver = NULL;
} }
...@@ -286,7 +286,7 @@ static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_ ...@@ -286,7 +286,7 @@ static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_
/* Now, remove the Linux Representation */ /* Now, remove the Linux Representation */
if (dev) { if (dev) {
if (pci_hp_remove_device(dev) == 0) { if (pci_hp_remove_device(dev) == 0) {
info("Device %s removed", dev->slot_name); info("Device %s removed\n", dev->slot_name);
kfree(dev); /* Now, remove */ kfree(dev); /* Now, remove */
} else { } else {
return -1; /* problems while freeing, abort visitation */ return -1; /* problems while freeing, abort visitation */
...@@ -338,7 +338,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * ...@@ -338,7 +338,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
int count; int count;
struct pci_resource *res; struct pci_resource *res;
dbg("Device %s", dev->slot_name); dbg("Device %s\n", dev->slot_name);
for (count = 0; address[count]; count++) { /* for 6 BARs */ for (count = 0; address[count]; count++) { /* for 6 BARs */
pci_read_config_dword(dev, address[count], &bar); pci_read_config_dword(dev, address[count], &bar);
...@@ -355,7 +355,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * ...@@ -355,7 +355,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
len &= 0xFFFFFFFC; len &= 0xFFFFFFFC;
len = ~len + 1; len = ~len + 1;
dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1); dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
spin_lock(&bridge->res_lock); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource_with_base(&bridge->io_head, base, len); res = acpiphp_get_resource_with_base(&bridge->io_head, base, len);
...@@ -372,10 +372,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * ...@@ -372,10 +372,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
len = ~len + 1; len = ~len + 1;
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
dbg ("prefetch mem 64"); dbg("prefetch mem 64\n");
count += 1; count += 1;
} }
dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1); dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
spin_lock(&bridge->res_lock); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len); res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
spin_unlock(&bridge->res_lock); spin_unlock(&bridge->res_lock);
...@@ -389,10 +389,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * ...@@ -389,10 +389,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */ /* takes up another dword */
dbg ("mem 64"); dbg("mem 64\n");
count += 1; count += 1;
} }
dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1); dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
spin_lock(&bridge->res_lock); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len); res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
spin_unlock(&bridge->res_lock); spin_unlock(&bridge->res_lock);
...@@ -414,7 +414,7 @@ static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_b ...@@ -414,7 +414,7 @@ static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_b
struct list_head *l; struct list_head *l;
struct pci_dev *dev; struct pci_dev *dev;
list_for_each(l, &bus->devices) { list_for_each (l, &bus->devices) {
dev = pci_dev_b(l); dev = pci_dev_b(l);
detect_used_resource(bridge, dev); detect_used_resource(bridge, dev);
/* XXX recursive call */ /* XXX recursive call */
...@@ -463,16 +463,16 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -463,16 +463,16 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
struct pci_dev *dev; struct pci_dev *dev;
dev = func->pci_dev; dev = func->pci_dev;
dbg("Hot-pluggable device %s", dev->slot_name); dbg("Hot-pluggable device %s\n", dev->slot_name);
for (count = 0; address[count]; count++) { /* for 6 BARs */ for (count = 0; address[count]; count++) { /* for 6 BARs */
pci_read_config_dword (dev, address[count], &bar); pci_read_config_dword(dev, address[count], &bar);
if (!bar) /* This BAR is not implemented */ if (!bar) /* This BAR is not implemented */
continue; continue;
pci_write_config_dword (dev, address[count], 0xFFFFFFFF); pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
pci_read_config_dword (dev, address[count], &len); pci_read_config_dword(dev, address[count], &len);
if (len & PCI_BASE_ADDRESS_SPACE_IO) { if (len & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */ /* This is IO */
...@@ -480,7 +480,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -480,7 +480,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len &= 0xFFFFFFFC; len &= 0xFFFFFFFC;
len = ~len + 1; len = ~len + 1;
dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1); dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
res = acpiphp_make_resource(base, len); res = acpiphp_make_resource(base, len);
if (!res) if (!res)
...@@ -499,10 +499,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -499,10 +499,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len = ~len + 1; len = ~len + 1;
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
dbg ("prefetch mem 64"); dbg("prefetch mem 64\n");
count += 1; count += 1;
} }
dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1); dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
res = acpiphp_make_resource(base, len); res = acpiphp_make_resource(base, len);
if (!res) if (!res)
goto no_memory; goto no_memory;
...@@ -518,10 +518,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -518,10 +518,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */ /* takes up another dword */
dbg ("mem 64"); dbg("mem 64\n");
count += 1; count += 1;
} }
dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1); dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
res = acpiphp_make_resource(base, len); res = acpiphp_make_resource(base, len);
if (!res) if (!res)
goto no_memory; goto no_memory;
...@@ -532,7 +532,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -532,7 +532,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
} }
} }
pci_write_config_dword (dev, address[count], bar); pci_write_config_dword(dev, address[count], bar);
} }
#if 1 #if 1
acpiphp_dump_func_resource(func); acpiphp_dump_func_resource(func);
...@@ -541,7 +541,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -541,7 +541,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
return 0; return 0;
no_memory: no_memory:
err("out of memory"); err("out of memory\n");
acpiphp_free_resource(&func->io_head); acpiphp_free_resource(&func->io_head);
acpiphp_free_resource(&func->mem_head); acpiphp_free_resource(&func->mem_head);
acpiphp_free_resource(&func->p_mem_head); acpiphp_free_resource(&func->p_mem_head);
...@@ -574,7 +574,7 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot) ...@@ -574,7 +574,7 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
if (hdr & 0x80) if (hdr & 0x80)
is_multi = 1; is_multi = 1;
list_for_each(l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (is_multi || func->function == 0) { if (is_multi || func->function == 0) {
pci_bus_read_config_dword(slot->bridge->pci_bus, pci_bus_read_config_dword(slot->bridge->pci_bus,
...@@ -583,7 +583,6 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot) ...@@ -583,7 +583,6 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
PCI_VENDOR_ID, &dvid); PCI_VENDOR_ID, &dvid);
if (dvid != 0xffffffff) { if (dvid != 0xffffffff) {
retval = init_config_space(func); retval = init_config_space(func);
if (retval) if (retval)
break; break;
} }
......
...@@ -273,7 +273,7 @@ struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 s ...@@ -273,7 +273,7 @@ struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 s
for (max = *head;max; max = max->next) { for (max = *head;max; max = max->next) {
/* If not big enough we could probably just bail, /* If not big enough we could probably just bail,
instead we'll continue to the next. */ instead we'll continue to the next. */
if (max->length < size) if (max->length < size)
continue; continue;
...@@ -370,13 +370,13 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) ...@@ -370,13 +370,13 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
return NULL; return NULL;
for (node = *head; node; node = node->next) { for (node = *head; node; node = node->next) {
dbg("%s: req_size =%x node=%p, base=%x, length=%x", dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",
__FUNCTION__, size, node, (u32)node->base, node->length); __FUNCTION__, size, node, (u32)node->base, node->length);
if (node->length < size) if (node->length < size)
continue; continue;
if (node->base & (size - 1)) { if (node->base & (size - 1)) {
dbg("%s: not aligned", __FUNCTION__); dbg("%s: not aligned\n", __FUNCTION__);
/* this one isn't base aligned properly /* this one isn't base aligned properly
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
temp_qword = (node->base | (size-1)) + 1; temp_qword = (node->base | (size-1)) + 1;
...@@ -400,7 +400,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) ...@@ -400,7 +400,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
/* Don't need to check if too small since we already did */ /* Don't need to check if too small since we already did */
if (node->length > size) { if (node->length > size) {
dbg("%s: too big", __FUNCTION__); dbg("%s: too big\n", __FUNCTION__);
/* this one is longer than we need /* this one is longer than we need
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
split_node = acpiphp_make_resource(node->base + size, node->length - size); split_node = acpiphp_make_resource(node->base + size, node->length - size);
...@@ -415,7 +415,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) ...@@ -415,7 +415,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
node->next = split_node; node->next = split_node;
} /* End of too big on top end */ } /* End of too big on top end */
dbg("%s: got one!!!", __FUNCTION__); dbg("%s: got one!!!\n", __FUNCTION__);
/* If we got here, then it is the right size /* If we got here, then it is the right size
Now take it out of the list */ Now take it out of the list */
if (*head == node) { if (*head == node) {
...@@ -437,7 +437,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) ...@@ -437,7 +437,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
/** /**
* get_resource_with_base - get resource with specific base address * get_resource_with_base - get resource with specific base address
* *
* this function * this function
* returns the first node of "size" length located at specified base address. * returns the first node of "size" length located at specified base address.
* If it finds a node larger than "size" it will split it up. * If it finds a node larger than "size" it will split it up.
* *
...@@ -458,7 +458,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, ...@@ -458,7 +458,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
return NULL; return NULL;
for (node = *head; node; node = node->next) { for (node = *head; node; node = node->next) {
dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x", dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
(u32)base, size, node, (u32)node->base, node->length); (u32)base, size, node, (u32)node->base, node->length);
if (node->base > base) if (node->base > base)
continue; continue;
...@@ -467,7 +467,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, ...@@ -467,7 +467,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
continue; continue;
if (node->base < base) { if (node->base < base) {
dbg(": split 1"); dbg(": split 1\n");
/* this one isn't base aligned properly /* this one isn't base aligned properly
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
temp_qword = base; temp_qword = base;
...@@ -489,12 +489,12 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, ...@@ -489,12 +489,12 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
node->next = split_node; node->next = split_node;
} }
dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x", dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n",
(u32)base, size, node, (u32)node->base, node->length); (u32)base, size, node, (u32)node->base, node->length);
/* Don't need to check if too small since we already did */ /* Don't need to check if too small since we already did */
if (node->length > size) { if (node->length > size) {
dbg(": split 2"); dbg(": split 2\n");
/* this one is longer than we need /* this one is longer than we need
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
split_node = acpiphp_make_resource(node->base + size, node->length - size); split_node = acpiphp_make_resource(node->base + size, node->length - size);
...@@ -509,7 +509,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, ...@@ -509,7 +509,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
node->next = split_node; node->next = split_node;
} /* End of too big on top end */ } /* End of too big on top end */
dbg(": got one!!!"); dbg(": got one!!!\n");
/* If we got here, then it is the right size /* If we got here, then it is the right size
Now take it out of the list */ Now take it out of the list */
if (*head == node) { if (*head == node) {
...@@ -547,13 +547,13 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head) ...@@ -547,13 +547,13 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
if (!(*head)) if (!(*head))
return 1; return 1;
dbg("*head->next = %p",(*head)->next); dbg("*head->next = %p\n",(*head)->next);
if (!(*head)->next) if (!(*head)->next)
return 0; /* only one item on the list, already sorted! */ return 0; /* only one item on the list, already sorted! */
dbg("*head->base = 0x%x",(u32)(*head)->base); dbg("*head->base = 0x%x\n",(u32)(*head)->base);
dbg("*head->next->base = 0x%x", (u32)(*head)->next->base); dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base);
while (out_of_order) { while (out_of_order) {
out_of_order = 0; out_of_order = 0;
...@@ -587,7 +587,7 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head) ...@@ -587,7 +587,7 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
while (node1 && node1->next) { while (node1 && node1->next) {
if ((node1->base + node1->length) == node1->next->base) { if ((node1->base + node1->length) == node1->next->base) {
/* Combine */ /* Combine */
dbg("8.."); dbg("8..\n");
node1->length += node1->next->length; node1->length += node1->next->length;
node2 = node1->next; node2 = node1->next;
node1->next = node1->next->next; node1->next = node1->next->next;
...@@ -668,7 +668,7 @@ static void dump_resource(struct pci_resource *head) ...@@ -668,7 +668,7 @@ static void dump_resource(struct pci_resource *head)
cnt = 0; cnt = 0;
while (p) { while (p) {
dbg("[%02d] %08x - %08x", dbg("[%02d] %08x - %08x\n",
cnt++, (u32)p->base, (u32)p->base + p->length - 1); cnt++, (u32)p->base, (u32)p->base + p->length - 1);
p = p->next; p = p->next;
} }
...@@ -676,24 +676,24 @@ static void dump_resource(struct pci_resource *head) ...@@ -676,24 +676,24 @@ static void dump_resource(struct pci_resource *head)
void acpiphp_dump_resource(struct acpiphp_bridge *bridge) void acpiphp_dump_resource(struct acpiphp_bridge *bridge)
{ {
dbg("I/O resource:"); dbg("I/O resource:\n");
dump_resource(bridge->io_head); dump_resource(bridge->io_head);
dbg("MEM resource:"); dbg("MEM resource:\n");
dump_resource(bridge->mem_head); dump_resource(bridge->mem_head);
dbg("PMEM resource:"); dbg("PMEM resource:\n");
dump_resource(bridge->p_mem_head); dump_resource(bridge->p_mem_head);
dbg("BUS resource:"); dbg("BUS resource:\n");
dump_resource(bridge->bus_head); dump_resource(bridge->bus_head);
} }
void acpiphp_dump_func_resource(struct acpiphp_func *func) void acpiphp_dump_func_resource(struct acpiphp_func *func)
{ {
dbg("I/O resource:"); dbg("I/O resource:\n");
dump_resource(func->io_head); dump_resource(func->io_head);
dbg("MEM resource:"); dbg("MEM resource:\n");
dump_resource(func->mem_head); dump_resource(func->mem_head);
dbg("PMEM resource:"); dbg("PMEM resource:\n");
dump_resource(func->p_mem_head); dump_resource(func->p_mem_head);
dbg("BUS resource:"); dbg("BUS resource:\n");
dump_resource(func->bus_head); dump_resource(func->bus_head);
} }
/*
* CompactPCI Hot Plug Core Functions
*
* Copyright (c) 2002 SOMA Networks, Inc.
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <scottm@somanetworks.com>
*/
#ifndef _CPCI_HOTPLUG_H
#define _CPCI_HOTPLUG_H
#include <linux/types.h>
#include <linux/pci.h>
/* PICMG 2.12 R2.0 HS CSR bits: */
#define HS_CSR_INS 0x0080
#define HS_CSR_EXT 0x0040
#define HS_CSR_PI 0x0030
#define HS_CSR_LOO 0x0008
#define HS_CSR_PIE 0x0004
#define HS_CSR_EIM 0x0002
#define HS_CSR_DHA 0x0001
#define SLOT_MAGIC 0x67267322
struct slot {
u32 magic;
u8 number;
unsigned int devfn;
struct pci_bus *bus;
struct pci_dev *dev;
unsigned int extracting;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
};
struct cpci_hp_controller_ops {
int (*query_enum) (void);
int (*enable_irq) (void);
int (*disable_irq) (void);
int (*check_irq) (void *dev_id);
int (*hardware_test) (struct slot* slot, u32 value);
u8 (*get_power) (struct slot* slot);
int (*set_power) (struct slot* slot, int value);
};
struct cpci_hp_controller {
unsigned int irq;
unsigned long irq_flags;
char *devname;
void *dev_id;
char *name;
struct cpci_hp_controller_ops *ops;
};
extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
extern int cpci_hp_unregister_bus(struct pci_bus *bus);
extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn);
extern int cpci_hp_start(void);
extern int cpci_hp_stop(void);
/*
* Internal function prototypes, these functions should not be used by
* board/chassis drivers.
*/
extern u8 cpci_get_attention_status(struct slot *slot);
extern u8 cpci_get_latch_status(struct slot *slot);
extern u8 cpci_get_adapter_status(struct slot *slot);
extern u16 cpci_get_hs_csr(struct slot * slot);
extern u16 cpci_set_hs_csr(struct slot * slot, u16 hs_csr);
extern int cpci_set_attention_status(struct slot *slot, int status);
extern int cpci_check_and_clear_ins(struct slot * slot);
extern int cpci_check_ext(struct slot * slot);
extern int cpci_clear_ext(struct slot * slot);
extern int cpci_led_on(struct slot * slot);
extern int cpci_led_off(struct slot * slot);
extern int cpci_configure_slot(struct slot *slot);
extern int cpci_unconfigure_slot(struct slot *slot);
#endif /* _CPCI_HOTPLUG_H */
This diff is collapsed.
This diff is collapsed.
/*
* cpcihp_generic.c
*
* Generic port I/O CompactPCI driver
*
* Copyright 2002 SOMA Networks, Inc.
* Copyright 2001 Intel San Luis Obispo
* Copyright 2000,2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* This generic CompactPCI hotplug driver should allow using the PCI hotplug
* mechanism on any CompactPCI board that exposes the #ENUM signal as a bit
* in a system register that can be read through standard port I/O.
*
* Send feedback to <scottm@somanetworks.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include "cpci_hotplug.h"
#define DRIVER_VERSION "0.1"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "Generic port I/O CompactPCI Hot Plug Driver"
#if !defined(CONFIG_HOTPLUG_CPCI_GENERIC_MODULE)
#define MY_NAME "cpcihp_generic"
#else
#define MY_NAME THIS_MODULE->name
#endif
#define dbg(format, arg...) \
do { \
if(debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
static int debug;
static char* bridge;
static u8 bridge_busnr;
static u8 bridge_slot;
static struct pci_bus *bus;
static u8 first_slot;
static u8 last_slot;
static u16 port;
static unsigned int enum_bit;
static u8 enum_mask;
static struct cpci_hp_controller_ops generic_hpc_ops;
static struct cpci_hp_controller generic_hpc;
/* The following allows configuring the driver when it's compiled into the kernel */
#ifndef MODULE
static int __init cpcihp_generic_setup(char* str)
{
char* p;
unsigned long tmp;
if(!str)
return -EINVAL;
bridge = str;
p = strchr(str, ',');
str = p + 1;
if(!(p && *str && *p == ','))
goto setup_error;
tmp = simple_strtoul(str, &p, 0);
if(p == str || tmp > 0xff) {
err("hotplug bus first slot number out of range");
goto setup_error;
}
first_slot = (u8) tmp;
str = p + 1;
if(!(*str && *p == ','))
return -EINVAL;
tmp = simple_strtoul(str, &p, 0);
if(p == str || tmp > 0xff) {
err("hotplug bus last slot number out of range");
goto setup_error;
}
last_slot = (u8) tmp;
str = p + 1;
if(!(*str && *p == ','))
goto setup_error;
tmp = simple_strtoul(str, &p, 0);
if(p == str || tmp > 0xffff) {
err("port number out of range");
goto setup_error;
}
port = (u16) tmp;
str = p + 1;
if(!(*str && *p == ','))
goto setup_error;
tmp = simple_strtoul(str, &p, 0);
if(p == str) {
err("invalid #ENUM bit number");
goto setup_error;
}
enum_bit = (u8) tmp;
str = p + 1;
if(*str && *p == ',') {
tmp = simple_strtoul(str, &p, 0);
if(p != str)
debug = (int) tmp;
}
return 0;
setup_error:
bridge = NULL;
return -EINVAL;
}
__setup("cpcihp_generic=", cpcihp_generic_setup);
#endif
static int __init validate_parameters(void)
{
char* str;
char* p;
unsigned long tmp;
if(!bridge) {
info("not configured, disabling.");
return 1;
}
str = bridge;
if(!*str)
return -EINVAL;
tmp = simple_strtoul(str, &p, 16);
if(p == str || tmp > 0xff) {
err("Invalid hotplug bus bridge device bus number");
return -EINVAL;
}
bridge_busnr = (u8) tmp;
dbg("bridge_busnr = 0x%02x", bridge_busnr);
if(*p != ':') {
err("Invalid hotplug bus bridge device");
return -EINVAL;
}
str = p + 1;
tmp = simple_strtoul(str, &p, 16);
if(p == str || tmp > 0x1f) {
err("Invalid hotplug bus bridge device slot number");
return -EINVAL;
}
bridge_slot = (u8) tmp;
dbg("bridge_slot = 0x%02x", bridge_slot);
dbg("first_slot = 0x%02x", first_slot);
dbg("last_slot = 0x%02x", last_slot);
if(!(first_slot && last_slot)) {
err("Need to specify first_slot and last_slot");
return -EINVAL;
}
if(last_slot < first_slot) {
err("first_slot must be less than last_slot");
return -EINVAL;
}
dbg("port = 0x%04x", port);
dbg("enum_bit = 0x%02x", enum_bit);
if(enum_bit > 7) {
err("Invalid #ENUM bit");
return -EINVAL;
}
enum_mask = 1 << enum_bit;
return 0;
}
static int query_enum(void)
{
u8 value;
value = inb_p(port);
return ((value & enum_mask) == enum_mask);
}
static int __init cpcihp_generic_init(void)
{
int status;
struct resource* r;
struct pci_dev* dev;
info(DRIVER_DESC " version: " DRIVER_VERSION);
status = validate_parameters();
if(status != 0)
return status;
r = request_region(port, 1, "#ENUM hotswap signal register");
if(!r)
return -EBUSY;
dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0));
if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
err("Invalid bridge device %s", bridge);
return -EINVAL;
}
bus = dev->subordinate;
memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
generic_hpc_ops.query_enum = query_enum;
generic_hpc.ops = &generic_hpc_ops;
status = cpci_hp_register_controller(&generic_hpc);
if(status != 0) {
err("Could not register cPCI hotplug controller");
return -ENODEV;
}
dbg("registered controller");
status = cpci_hp_register_bus(bus, first_slot, last_slot);
if(status != 0) {
err("Could not register cPCI hotplug bus");
goto init_bus_register_error;
}
dbg("registered bus");
status = cpci_hp_start();
if(status != 0) {
err("Could not started cPCI hotplug system");
goto init_start_error;
}
dbg("started cpci hp system");
return 0;
init_start_error:
cpci_hp_unregister_bus(bus);
init_bus_register_error:
cpci_hp_unregister_controller(&generic_hpc);
err("status = %d", status);
return status;
}
static void __exit cpcihp_generic_exit(void)
{
cpci_hp_stop();
cpci_hp_unregister_bus(bus);
cpci_hp_unregister_controller(&generic_hpc);
release_region(port, 1);
}
module_init(cpcihp_generic_init);
module_exit(cpcihp_generic_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
MODULE_PARM(bridge, "s");
MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)");
MODULE_PARM(first_slot, "b");
MODULE_PARM_DESC(first_slot, "Hotswap bus first slot number");
MODULE_PARM(last_slot, "b");
MODULE_PARM_DESC(last_slot, "Hotswap bus last slot number");
MODULE_PARM(port, "h");
MODULE_PARM_DESC(port, "#ENUM signal I/O port");
MODULE_PARM(enum_bit, "i");
MODULE_PARM_DESC(enum_bit, "#ENUM signal bit (0-7)");
/*
* cpcihp_zt5550.c
*
* Intel/Ziatech ZT5550 CompactPCI Host Controller driver
*
* Copyright 2002 SOMA Networks, Inc.
* Copyright 2001 Intel San Luis Obispo
* Copyright 2000,2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <scottm@somanetworks.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"
#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver"
#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
#define MY_NAME "cpcihp_zt5550"
#else
#define MY_NAME THIS_MODULE->name
#endif
#define dbg(format, arg...) \
do { \
if(debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
static int debug;
static int poll;
static struct cpci_hp_controller_ops zt5550_hpc_ops;
static struct cpci_hp_controller zt5550_hpc;
/* Primary cPCI bus bridge device */
static struct pci_dev *bus0_dev;
static struct pci_bus *bus0;
/* Host controller device */
static struct pci_dev *hc_dev;
/* Host controller register addresses */
static void *hc_registers;
static void *csr_hc_index;
static void *csr_hc_data;
static void *csr_int_status;
static void *csr_int_mask;
static int zt5550_hc_config(struct pci_dev *pdev)
{
/* Since we know that no boards exist with two HC chips, treat it as an error */
if(hc_dev) {
err("too many host controller devices?");
return -EBUSY;
}
hc_dev = pdev;
dbg("hc_dev = %p", hc_dev);
dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
dbg("pci resource len %lx", pci_resource_len(hc_dev, 1));
if(!request_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1), MY_NAME)) {
err("cannot reserve MMIO region");
return -ENOMEM;
}
hc_registers =
ioremap(pci_resource_start(hc_dev, 1), pci_resource_len(hc_dev, 1));
if(!hc_registers) {
err("cannot remap MMIO region %lx @ %lx",
pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
release_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1));
return -ENODEV;
}
csr_hc_index = hc_registers + CSR_HCINDEX;
csr_hc_data = hc_registers + CSR_HCDATA;
csr_int_status = hc_registers + CSR_INTSTAT;
csr_int_mask = hc_registers + CSR_INTMASK;
/*
* Disable host control, fault and serial interrupts
*/
dbg("disabling host control, fault and serial interrupts");
writeb((u8) HC_INT_MASK_REG, csr_hc_index);
writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data);
dbg("disabled host control, fault and serial interrupts");
/*
* Disable timer0, timer1 and ENUM interrupts
*/
dbg("disabling timer0, timer1 and ENUM interrupts");
writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
dbg("disabled timer0, timer1 and ENUM interrupts");
return 0;
}
static int zt5550_hc_cleanup(void)
{
if(!hc_dev)
return -ENODEV;
release_mem_region(pci_resource_start(hc_dev, 1),
pci_resource_len(hc_dev, 1));
return 0;
}
static int zt5550_hc_query_enum(void)
{
u8 value;
value = inb_p(ENUM_PORT);
return ((value & ENUM_MASK) == ENUM_MASK);
}
static int zt5550_hc_check_irq(void *dev_id)
{
int ret;
u8 reg;
ret = 0;
if(dev_id == zt5550_hpc.dev_id) {
reg = readb(csr_int_status);
if(reg)
ret = 1;
}
return ret;
}
static int zt5550_hc_enable_irq(void)
{
u8 reg;
if(hc_dev == NULL) {
return -ENODEV;
}
reg = readb(csr_int_mask);
reg = reg & ~ENUM_INT_MASK;
writeb(reg, csr_int_mask);
return 0;
}
int zt5550_hc_disable_irq(void)
{
u8 reg;
if(hc_dev == NULL) {
return -ENODEV;
}
reg = readb(csr_int_mask);
reg = reg | ENUM_INT_MASK;
writeb(reg, csr_int_mask);
return 0;
}
static int __devinit zt5550_hc_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int status;
status = zt5550_hc_config(pdev);
if(status != 0) {
return status;
}
dbg("returned from zt5550_hc_config");
memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller));
zt5550_hpc_ops.query_enum = zt5550_hc_query_enum;
zt5550_hpc.ops = &zt5550_hpc_ops;
if(!poll) {
zt5550_hpc.irq = hc_dev->irq;
zt5550_hpc.irq_flags = SA_SHIRQ;
zt5550_hpc.dev_id = hc_dev;
zt5550_hpc_ops.enable_irq = zt5550_hc_enable_irq;
zt5550_hpc_ops.disable_irq = zt5550_hc_disable_irq;
zt5550_hpc_ops.check_irq = zt5550_hc_check_irq;
} else {
info("using ENUM# polling mode");
}
status = cpci_hp_register_controller(&zt5550_hpc);
if(status != 0) {
err("could not register cPCI hotplug controller");
goto init_hc_error;
}
dbg("registered controller");
/* Look for first device matching cPCI bus's bridge vendor and device IDs */
if(!(bus0_dev = pci_find_device(PCI_VENDOR_ID_DEC,
PCI_DEVICE_ID_DEC_21154, NULL))) {
status = -ENODEV;
goto init_register_error;
}
bus0 = bus0_dev->subordinate;
status = cpci_hp_register_bus(bus0, 0x0a, 0x0f);
if(status != 0) {
err("could not register cPCI hotplug bus");
goto init_register_error;
}
dbg("registered bus");
status = cpci_hp_start();
if(status != 0) {
err("could not started cPCI hotplug system");
cpci_hp_unregister_bus(bus0);
goto init_register_error;
}
dbg("started cpci hp system");
return 0;
init_register_error:
cpci_hp_unregister_controller(&zt5550_hpc);
init_hc_error:
err("status = %d", status);
zt5550_hc_cleanup();
return status;
}
static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev)
{
cpci_hp_stop();
cpci_hp_unregister_bus(bus0);
cpci_hp_unregister_controller(&zt5550_hpc);
zt5550_hc_cleanup();
}
static struct pci_device_id zt5550_hc_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_ZIATECH, PCI_DEVICE_ID_ZIATECH_5550_HC, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, zt5550_hc_pci_tbl);
static struct pci_driver zt5550_hc_driver = {
.name = "zt5550_hc",
.id_table = zt5550_hc_pci_tbl,
.probe = zt5550_hc_init_one,
.remove = __devexit_p(zt5550_hc_remove_one),
};
static int __init zt5550_init(void)
{
struct resource* r;
info(DRIVER_DESC " version: " DRIVER_VERSION);
r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
if(!r)
return -EBUSY;
return pci_module_init(&zt5550_hc_driver);
}
static void __exit
zt5550_exit(void)
{
pci_unregister_driver(&zt5550_hc_driver);
release_region(ENUM_PORT, 1);
}
module_init(zt5550_init);
module_exit(zt5550_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
MODULE_PARM(poll, "i");
MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not");
/*
* cpcihp_zt5550.h
*
* Intel/Ziatech ZT5550 CompactPCI Host Controller driver definitions
*
* Copyright 2002 SOMA Networks, Inc.
* Copyright 2001 Intel San Luis Obispo
* Copyright 2000,2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <scottm@somanetworks.com>
*/
#ifndef _CPCIHP_ZT5550_H
#define _CPCIHP_ZT5550_H
/* Direct registers */
#define CSR_HCINDEX 0x00
#define CSR_HCDATA 0x04
#define CSR_INTSTAT 0x08
#define CSR_INTMASK 0x09
#define CSR_CNT0CMD 0x0C
#define CSR_CNT1CMD 0x0E
#define CSR_CNT0 0x10
#define CSR_CNT1 0x14
/* Masks for interrupt bits in CSR_INTMASK direct register */
#define CNT0_INT_MASK 0x01
#define CNT1_INT_MASK 0x02
#define ENUM_INT_MASK 0x04
#define ALL_DIRECT_INTS_MASK 0x07
/* Indexed registers (through CSR_INDEX, CSR_DATA) */
#define HC_INT_MASK_REG 0x04
#define HC_STATUS_REG 0x08
#define HC_CMD_REG 0x0C
#define ARB_CONFIG_GNT_REG 0x10
#define ARB_CONFIG_CFG_REG 0x12
#define ARB_CONFIG_REG 0x10
#define ISOL_CONFIG_REG 0x18
#define FAULT_STATUS_REG 0x20
#define FAULT_CONFIG_REG 0x24
#define WD_CONFIG_REG 0x2C
#define HC_DIAG_REG 0x30
#define SERIAL_COMM_REG 0x34
#define SERIAL_OUT_REG 0x38
#define SERIAL_IN_REG 0x3C
/* Masks for interrupt bits in HC_INT_MASK_REG indexed register */
#define SERIAL_INT_MASK 0x01
#define FAULT_INT_MASK 0x02
#define HCF_INT_MASK 0x04
#define ALL_INDEXED_INTS_MASK 0x07
/* Digital I/O port storing ENUM# */
#define ENUM_PORT 0xE1
/* Mask to get to the ENUM# bit on the bus */
#define ENUM_MASK 0x40
#endif /* _CPCIHP_ZT5550_H */
...@@ -167,5 +167,9 @@ extern int pci_visit_dev (struct pci_visit *fn, ...@@ -167,5 +167,9 @@ extern int pci_visit_dev (struct pci_visit *fn,
struct pci_dev_wrapped *wrapped_dev, struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent); struct pci_bus_wrapped *wrapped_parent);
int pci_is_dev_in_use(struct pci_dev *dev);
int pci_remove_device_safe(struct pci_dev *dev);
#endif #endif
...@@ -94,15 +94,12 @@ static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped ...@@ -94,15 +94,12 @@ static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped
static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent) static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent)
{ {
struct pci_bus *bus = wrapped_dev->dev->subordinate; struct pci_bus *bus;
struct pci_bus_wrapped wrapped_bus; struct pci_bus_wrapped wrapped_bus;
int result; int result = 0;
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
dbg("scanning bridge %02x, %02x\n", wrapped_dev->dev->devfn >> 3, dbg("scanning bridge %02x, %02x\n", PCI_SLOT(wrapped_dev->dev->devfn),
wrapped_dev->dev->devfn & 0x7); PCI_FUNC(wrapped_dev->dev->devfn));
if (fn->visit_pci_dev) { if (fn->visit_pci_dev) {
result = fn->visit_pci_dev(wrapped_dev, wrapped_parent); result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
...@@ -110,7 +107,13 @@ static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrap ...@@ -110,7 +107,13 @@ static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrap
return result; return result;
} }
result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev); bus = wrapped_dev->dev->subordinate;
if(bus) {
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
}
return result; return result;
} }
...@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st ...@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st
return result; return result;
} }
/**
* pci_is_dev_in_use - query devices' usage
* @dev: PCI device to query
*
* Queries whether a given PCI device is in use by a driver or not.
* Returns 1 if the device is in use, 0 if it is not.
*/
int pci_is_dev_in_use(struct pci_dev *dev)
{
/*
* dev->driver will be set if the device is in use by a new-style
* driver -- otherwise, check the device's regions to see if any
* driver has claimed them.
*/
int i;
int inuse = 0;
if (dev->driver) {
/* Assume driver feels responsible */
return 1;
}
for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
if (!pci_resource_start(dev, i))
continue;
if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
inuse = check_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
} else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
inuse = check_mem_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
}
}
return inuse;
}
/**
* pci_remove_device_safe - remove an unused hotplug device
* @dev: the device to remove
*
* Delete the device structure from the device lists and
* notify userspace (/sbin/hotplug), but only if the device
* in question is not being used by a driver.
* Returns 0 on success.
*/
int pci_remove_device_safe(struct pci_dev *dev)
{
if (pci_is_dev_in_use(dev)) {
return -EBUSY;
}
pci_remove_device(dev);
return 0;
}
EXPORT_SYMBOL(pci_visit_dev); EXPORT_SYMBOL(pci_visit_dev);
EXPORT_SYMBOL(pci_is_dev_in_use);
EXPORT_SYMBOL(pci_remove_device_safe);
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \ export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \
probe.o proc.o search.o compat.o probe.o proc.o search.o compat.o setup-bus.o
obj-y += access.o probe.o pci.o pool.o quirks.o \ obj-y += access.o probe.o pci.o pool.o quirks.o \
compat.o names.o pci-driver.o search.o hotplug.o compat.o names.o pci-driver.o search.o hotplug.o
...@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o ...@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_DDB5476) += setup-bus.o obj-$(CONFIG_DDB5476) += setup-bus.o
obj-$(CONFIG_SGI_IP27) += setup-irq.o obj-$(CONFIG_SGI_IP27) += setup-irq.o
# CompactPCI hotplug requires the pbus_* functions
ifdef CONFIG_HOTPLUG_PCI_CPCI
obj-y += setup-bus.o
endif
ifndef CONFIG_X86 ifndef CONFIG_X86
obj-y += syscall.o obj-y += syscall.o
endif endif
......
...@@ -71,8 +71,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp, ...@@ -71,8 +71,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
* @bus: where to insert it * @bus: where to insert it
* *
* Link the device to both the global PCI device chain and the * Link the device to both the global PCI device chain and the
* per-bus list of devices, add the /proc entry, and notify * per-bus list of devices, add the /proc entry.
* userspace (/sbin/hotplug).
*/ */
void void
pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
......
...@@ -24,6 +24,49 @@ ...@@ -24,6 +24,49 @@
#define DBG(x...) #define DBG(x...)
#endif #endif
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search
*
* Given a PCI bus, returns the highest PCI bus number present in the set
* including the given PCI bus and its list of child PCI buses.
*/
unsigned char __devinit
pci_bus_max_busnr(struct pci_bus* bus)
{
struct list_head *tmp;
unsigned char max, n;
max = bus->number;
list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp));
if(n > max)
max = n;
}
return max;
}
/**
* pci_max_busnr - returns maximum PCI bus number
*
* Returns the highest PCI bus number present in the system global list of
* PCI buses.
*/
unsigned char __devinit
pci_max_busnr(void)
{
struct pci_bus* bus;
unsigned char max, n;
max = 0;
pci_for_each_bus(bus) {
n = pci_bus_max_busnr(bus);
if(n > max)
max = n;
}
return max;
}
/** /**
* pci_find_capability - query for devices' capabilities * pci_find_capability - query for devices' capabilities
* @dev: PCI device to query * @dev: PCI device to query
...@@ -79,6 +122,49 @@ pci_find_capability(struct pci_dev *dev, int cap) ...@@ -79,6 +122,49 @@ pci_find_capability(struct pci_dev *dev, int cap)
return 0; return 0;
} }
/**
* pci_bus_find_capability - query for devices' capabilities
* @dev: PCI device to query
* @cap: capability code
*
* Like pci_find_capability() but works for pci devices that do not have a
* pci_dev structure set up yet.
* Returns the address of the requested capability structure within the
* device's PCI configuration space or 0 in case the device does not
* support it.
*/
int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
{
u16 status;
u8 pos, id;
int ttl = 48;
struct pci_dev *dev = bus->self;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
return 0;
switch (dev->hdr_type) {
case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE:
pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
break;
case PCI_HEADER_TYPE_CARDBUS:
pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
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;
}
/** /**
* pci_find_parent_resource - return resource region of parent bus of given region * pci_find_parent_resource - return resource region of parent bus of given region
...@@ -649,7 +735,10 @@ EXPORT_SYMBOL(isa_bridge); ...@@ -649,7 +735,10 @@ EXPORT_SYMBOL(isa_bridge);
EXPORT_SYMBOL(pci_enable_device); EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_disable_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_find_capability);
EXPORT_SYMBOL(pci_bus_find_capability);
EXPORT_SYMBOL(pci_release_regions); EXPORT_SYMBOL(pci_release_regions);
EXPORT_SYMBOL(pci_request_regions); EXPORT_SYMBOL(pci_request_regions);
EXPORT_SYMBOL(pci_release_region); EXPORT_SYMBOL(pci_release_region);
......
...@@ -254,7 +254,7 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de ...@@ -254,7 +254,7 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
* them, we proceed to assigning numbers to the remaining buses in * them, we proceed to assigning numbers to the remaining buses in
* order to avoid overlaps between old and new bus numbers. * order to avoid overlaps between old and new bus numbers.
*/ */
static int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
{ {
unsigned int buses; unsigned int buses;
unsigned short cr; unsigned short cr;
...@@ -480,8 +480,7 @@ struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) ...@@ -480,8 +480,7 @@ struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp)
/* /*
* Link the device to both the global PCI device chain and * Link the device to both the global PCI device chain and
* the per-bus list of devices and call /sbin/hotplug if we * the per-bus list of devices and add the /proc entry.
* should.
*/ */
pci_insert_device (dev, bus); pci_insert_device (dev, bus);
...@@ -596,4 +595,5 @@ EXPORT_SYMBOL(pci_add_new_bus); ...@@ -596,4 +595,5 @@ EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bus); EXPORT_SYMBOL(pci_scan_bus);
EXPORT_SYMBOL(pci_scan_bridge);
#endif #endif
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* Deal with broken BIOS'es that neglect to enable passive release, /* Deal with broken BIOS'es that neglect to enable passive release,
which can cause problems in combination with the 82441FX/PPro MTRRs */ which can cause problems in combination with the 82441FX/PPro MTRRs */
static void __init quirk_passive_release(struct pci_dev *dev) static void __devinit quirk_passive_release(struct pci_dev *dev)
{ {
struct pci_dev *d = NULL; struct pci_dev *d = NULL;
unsigned char dlc; unsigned char dlc;
...@@ -50,7 +50,7 @@ static void __init quirk_passive_release(struct pci_dev *dev) ...@@ -50,7 +50,7 @@ static void __init quirk_passive_release(struct pci_dev *dev)
int isa_dma_bridge_buggy; /* Exported */ int isa_dma_bridge_buggy; /* Exported */
static void __init quirk_isa_dma_hangs(struct pci_dev *dev) static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
{ {
if (!isa_dma_bridge_buggy) { if (!isa_dma_bridge_buggy) {
isa_dma_bridge_buggy=1; isa_dma_bridge_buggy=1;
...@@ -64,7 +64,7 @@ int pci_pci_problems; ...@@ -64,7 +64,7 @@ int pci_pci_problems;
* Chipsets where PCI->PCI transfers vanish or hang * Chipsets where PCI->PCI transfers vanish or hang
*/ */
static void __init quirk_nopcipci(struct pci_dev *dev) static void __devinit quirk_nopcipci(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_FAIL)==0) if((pci_pci_problems&PCIPCI_FAIL)==0)
{ {
...@@ -77,7 +77,7 @@ static void __init quirk_nopcipci(struct pci_dev *dev) ...@@ -77,7 +77,7 @@ static void __init quirk_nopcipci(struct pci_dev *dev)
* Triton requires workarounds to be used by the drivers * Triton requires workarounds to be used by the drivers
*/ */
static void __init quirk_triton(struct pci_dev *dev) static void __devinit quirk_triton(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_TRITON)==0) if((pci_pci_problems&PCIPCI_TRITON)==0)
{ {
...@@ -96,7 +96,7 @@ static void __init quirk_triton(struct pci_dev *dev) ...@@ -96,7 +96,7 @@ static void __init quirk_triton(struct pci_dev *dev)
* Updated based on further information from the site and also on * Updated based on further information from the site and also on
* information provided by VIA * information provided by VIA
*/ */
static void __init quirk_vialatency(struct pci_dev *dev) static void __devinit quirk_vialatency(struct pci_dev *dev)
{ {
struct pci_dev *p; struct pci_dev *p;
u8 rev; u8 rev;
...@@ -150,7 +150,7 @@ static void __init quirk_vialatency(struct pci_dev *dev) ...@@ -150,7 +150,7 @@ static void __init quirk_vialatency(struct pci_dev *dev)
* VIA Apollo VP3 needs ETBF on BT848/878 * VIA Apollo VP3 needs ETBF on BT848/878
*/ */
static void __init quirk_viaetbf(struct pci_dev *dev) static void __devinit quirk_viaetbf(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_VIAETBF)==0) if((pci_pci_problems&PCIPCI_VIAETBF)==0)
{ {
...@@ -158,7 +158,7 @@ static void __init quirk_viaetbf(struct pci_dev *dev) ...@@ -158,7 +158,7 @@ static void __init quirk_viaetbf(struct pci_dev *dev)
pci_pci_problems|=PCIPCI_VIAETBF; pci_pci_problems|=PCIPCI_VIAETBF;
} }
} }
static void __init quirk_vsfx(struct pci_dev *dev) static void __devinit quirk_vsfx(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_VSFX)==0) if((pci_pci_problems&PCIPCI_VSFX)==0)
{ {
...@@ -173,7 +173,7 @@ static void __init quirk_vsfx(struct pci_dev *dev) ...@@ -173,7 +173,7 @@ static void __init quirk_vsfx(struct pci_dev *dev)
* at least * at least
*/ */
static void __init quirk_natoma(struct pci_dev *dev) static void __devinit quirk_natoma(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_NATOMA)==0) if((pci_pci_problems&PCIPCI_NATOMA)==0)
{ {
...@@ -187,7 +187,7 @@ static void __init quirk_natoma(struct pci_dev *dev) ...@@ -187,7 +187,7 @@ static void __init quirk_natoma(struct pci_dev *dev)
* If it's needed, re-allocate the region. * If it's needed, re-allocate the region.
*/ */
static void __init quirk_s3_64M(struct pci_dev *dev) static void __devinit quirk_s3_64M(struct pci_dev *dev)
{ {
struct resource *r = &dev->resource[0]; struct resource *r = &dev->resource[0];
...@@ -197,7 +197,7 @@ static void __init quirk_s3_64M(struct pci_dev *dev) ...@@ -197,7 +197,7 @@ static void __init quirk_s3_64M(struct pci_dev *dev)
} }
} }
static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr) static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
{ {
region &= ~(size-1); region &= ~(size-1);
if (region) { if (region) {
...@@ -222,7 +222,7 @@ static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigne ...@@ -222,7 +222,7 @@ static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigne
* 0xE0 (64 bytes of ACPI registers) * 0xE0 (64 bytes of ACPI registers)
* 0xE2 (32 bytes of SMB registers) * 0xE2 (32 bytes of SMB registers)
*/ */
static void __init quirk_ali7101_acpi(struct pci_dev *dev) static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
{ {
u16 region; u16 region;
...@@ -237,7 +237,7 @@ static void __init quirk_ali7101_acpi(struct pci_dev *dev) ...@@ -237,7 +237,7 @@ static void __init quirk_ali7101_acpi(struct pci_dev *dev)
* 0x40 (64 bytes of ACPI registers) * 0x40 (64 bytes of ACPI registers)
* 0x90 (32 bytes of SMB registers) * 0x90 (32 bytes of SMB registers)
*/ */
static void __init quirk_piix4_acpi(struct pci_dev *dev) static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
{ {
u32 region; u32 region;
...@@ -251,7 +251,7 @@ static void __init quirk_piix4_acpi(struct pci_dev *dev) ...@@ -251,7 +251,7 @@ static void __init quirk_piix4_acpi(struct pci_dev *dev)
* VIA ACPI: One IO region pointed to by longword at * VIA ACPI: One IO region pointed to by longword at
* 0x48 or 0x20 (256 bytes of ACPI registers) * 0x48 or 0x20 (256 bytes of ACPI registers)
*/ */
static void __init quirk_vt82c586_acpi(struct pci_dev *dev) static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
{ {
u8 rev; u8 rev;
u32 region; u32 region;
...@@ -270,7 +270,7 @@ static void __init quirk_vt82c586_acpi(struct pci_dev *dev) ...@@ -270,7 +270,7 @@ static void __init quirk_vt82c586_acpi(struct pci_dev *dev)
* 0x70 (128 bytes of hardware monitoring register) * 0x70 (128 bytes of hardware monitoring register)
* 0x90 (16 bytes of SMB registers) * 0x90 (16 bytes of SMB registers)
*/ */
static void __init quirk_vt82c686_acpi(struct pci_dev *dev) static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
{ {
u16 hm; u16 hm;
u32 smb; u32 smb;
...@@ -297,7 +297,7 @@ extern int nr_ioapics; ...@@ -297,7 +297,7 @@ extern int nr_ioapics;
* TODO: When we have device-specific interrupt routers, * TODO: When we have device-specific interrupt routers,
* this code will go away from quirks. * this code will go away from quirks.
*/ */
static void __init quirk_via_ioapic(struct pci_dev *dev) static void __devinit quirk_via_ioapic(struct pci_dev *dev)
{ {
u8 tmp; u8 tmp;
...@@ -338,7 +338,7 @@ static void __init quirk_via_ioapic(struct pci_dev *dev) ...@@ -338,7 +338,7 @@ static void __init quirk_via_ioapic(struct pci_dev *dev)
* value of the ACPI SCI interrupt is only done for convenience. * value of the ACPI SCI interrupt is only done for convenience.
* -jgarzik * -jgarzik
*/ */
static void __init quirk_via_acpi(struct pci_dev *d) static void __devinit quirk_via_acpi(struct pci_dev *d)
{ {
/* /*
* VIA ACPI device: SCI IRQ line in PCI config byte 0x42 * VIA ACPI device: SCI IRQ line in PCI config byte 0x42
...@@ -350,7 +350,7 @@ static void __init quirk_via_acpi(struct pci_dev *d) ...@@ -350,7 +350,7 @@ static void __init quirk_via_acpi(struct pci_dev *d)
d->irq = irq; d->irq = irq;
} }
static void __init quirk_via_irqpic(struct pci_dev *dev) static void __devinit quirk_via_irqpic(struct pci_dev *dev)
{ {
u8 irq, new_irq = dev->irq & 0xf; u8 irq, new_irq = dev->irq & 0xf;
...@@ -377,7 +377,7 @@ static void __init quirk_via_irqpic(struct pci_dev *dev) ...@@ -377,7 +377,7 @@ static void __init quirk_via_irqpic(struct pci_dev *dev)
* *
* We mask out all r/wc bits, too. * We mask out all r/wc bits, too.
*/ */
static void __init quirk_piix3_usb(struct pci_dev *dev) static void __devinit quirk_piix3_usb(struct pci_dev *dev)
{ {
u16 legsup; u16 legsup;
...@@ -392,7 +392,7 @@ static void __init quirk_piix3_usb(struct pci_dev *dev) ...@@ -392,7 +392,7 @@ static void __init quirk_piix3_usb(struct pci_dev *dev)
* We need to switch it off to be able to recognize the real * We need to switch it off to be able to recognize the real
* type of the chip. * type of the chip.
*/ */
static void __init quirk_vt82c598_id(struct pci_dev *dev) static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
{ {
pci_write_config_byte(dev, 0xfc, 0); pci_write_config_byte(dev, 0xfc, 0);
pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
...@@ -404,7 +404,7 @@ static void __init quirk_vt82c598_id(struct pci_dev *dev) ...@@ -404,7 +404,7 @@ static void __init quirk_vt82c598_id(struct pci_dev *dev)
* do this even if the Linux CardBus driver is not loaded, because * do this even if the Linux CardBus driver is not loaded, because
* the Linux i82365 driver does not (and should not) handle CardBus. * the Linux i82365 driver does not (and should not) handle CardBus.
*/ */
static void __init quirk_cardbus_legacy(struct pci_dev *dev) static void __devinit quirk_cardbus_legacy(struct pci_dev *dev)
{ {
if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class) if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
return; return;
...@@ -421,7 +421,7 @@ static void __init quirk_cardbus_legacy(struct pci_dev *dev) ...@@ -421,7 +421,7 @@ static void __init quirk_cardbus_legacy(struct pci_dev *dev)
* of course. However the advice is demonstrably good even if so.. * of course. However the advice is demonstrably good even if so..
*/ */
static void __init quirk_amd_ioapic(struct pci_dev *dev) static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
{ {
u8 rev; u8 rev;
...@@ -441,7 +441,7 @@ static void __init quirk_amd_ioapic(struct pci_dev *dev) ...@@ -441,7 +441,7 @@ static void __init quirk_amd_ioapic(struct pci_dev *dev)
* who turn it off! * who turn it off!
*/ */
static void __init quirk_amd_ordering(struct pci_dev *dev) static void __devinit quirk_amd_ordering(struct pci_dev *dev)
{ {
u32 pcic; u32 pcic;
pci_read_config_dword(dev, 0x4C, &pcic); pci_read_config_dword(dev, 0x4C, &pcic);
...@@ -464,14 +464,14 @@ static void __init quirk_amd_ordering(struct pci_dev *dev) ...@@ -464,14 +464,14 @@ static void __init quirk_amd_ordering(struct pci_dev *dev)
* nothing gets put too close to it. * nothing gets put too close to it.
*/ */
static void __init quirk_dunord ( struct pci_dev * dev ) static void __devinit quirk_dunord ( struct pci_dev * dev )
{ {
struct resource * r = & dev -> resource [ 1 ]; struct resource * r = & dev -> resource [ 1 ];
r -> start = 0; r -> start = 0;
r -> end = 0xffffff; r -> end = 0xffffff;
} }
static void __init quirk_transparent_bridge(struct pci_dev *dev) static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
{ {
dev->transparent = 1; dev->transparent = 1;
} }
...@@ -480,7 +480,7 @@ static void __init quirk_transparent_bridge(struct pci_dev *dev) ...@@ -480,7 +480,7 @@ static void __init quirk_transparent_bridge(struct pci_dev *dev)
* The main table of quirks. * The main table of quirks.
*/ */
static struct pci_fixup pci_fixups[] __initdata = { static struct pci_fixup pci_fixups[] __devinitdata = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release },
......
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/module.h> #include <linux/module.h>
static struct pci_bus *
pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
{
struct pci_bus* child;
struct list_head *tmp;
if(bus->number == busnr)
return bus;
list_for_each(tmp, &bus->children) {
child = pci_do_find_bus(pci_bus_b(tmp), busnr);
if(child)
return child;
}
return NULL;
}
/**
* pci_find_bus - locate PCI bus from a given bus number
* @busnr: number of desired PCI bus
*
* Given a PCI bus number, the desired PCI bus is located in system
* global list of PCI buses. If the bus is found, a pointer to its
* data structure is returned. If no bus is found, %NULL is returned.
*/
struct pci_bus *
pci_find_bus(unsigned char busnr)
{
struct pci_bus* bus;
struct pci_bus* tmp_bus;
pci_for_each_bus(bus) {
tmp_bus = pci_do_find_bus(bus, busnr);
if(tmp_bus)
return tmp_bus;
}
return NULL;
}
/** /**
* pci_find_slot - locate PCI device from a given PCI slot * pci_find_slot - locate PCI device from a given PCI slot
* @bus: number of PCI bus on which desired PCI device resides * @bus: number of PCI bus on which desired PCI device resides
...@@ -104,6 +143,7 @@ pci_find_class(unsigned int class, const struct pci_dev *from) ...@@ -104,6 +143,7 @@ pci_find_class(unsigned int class, const struct pci_dev *from)
return NULL; return NULL;
} }
EXPORT_SYMBOL(pci_find_bus);
EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_class);
EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_find_slot);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -35,7 +36,7 @@ ...@@ -35,7 +36,7 @@
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
static int __init static int __devinit
pbus_assign_resources_sorted(struct pci_bus *bus) pbus_assign_resources_sorted(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -85,7 +86,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus) ...@@ -85,7 +86,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
requires that if there is no I/O ports or memory behind the requires that if there is no I/O ports or memory behind the
bridge, corresponding range must be turned off by writing base bridge, corresponding range must be turned off by writing base
value greater than limit to the bridge's base/limit registers. */ value greater than limit to the bridge's base/limit registers. */
static void __init static void __devinit
pci_setup_bridge(struct pci_bus *bus) pci_setup_bridge(struct pci_bus *bus)
{ {
struct pbus_set_ranges_data ranges; struct pbus_set_ranges_data ranges;
...@@ -168,7 +169,7 @@ pci_setup_bridge(struct pci_bus *bus) ...@@ -168,7 +169,7 @@ pci_setup_bridge(struct pci_bus *bus)
/* Check whether the bridge supports optional I/O and /* Check whether the bridge supports optional I/O and
prefetchable memory ranges. If not, the respective prefetchable memory ranges. If not, the respective
base/limit registers must be read-only and read as 0. */ base/limit registers must be read-only and read as 0. */
static void __init static void __devinit
pci_bridge_check_ranges(struct pci_bus *bus) pci_bridge_check_ranges(struct pci_bus *bus)
{ {
u16 io; u16 io;
...@@ -210,7 +211,7 @@ pci_bridge_check_ranges(struct pci_bus *bus) ...@@ -210,7 +211,7 @@ pci_bridge_check_ranges(struct pci_bus *bus)
since these windows have 4K granularity and the IO ranges since these windows have 4K granularity and the IO ranges
of non-bridge PCI devices are limited to 256 bytes. of non-bridge PCI devices are limited to 256 bytes.
We must be careful with the ISA aliasing though. */ We must be careful with the ISA aliasing though. */
static void __init static void __devinit
pbus_size_io(struct pci_bus *bus) pbus_size_io(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -259,7 +260,7 @@ pbus_size_io(struct pci_bus *bus) ...@@ -259,7 +260,7 @@ pbus_size_io(struct pci_bus *bus)
/* Calculate the size of the bus and minimal alignment which /* Calculate the size of the bus and minimal alignment which
guarantees that all child resources fit in this size. */ guarantees that all child resources fit in this size. */
static void __init static void __devinit
pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -331,7 +332,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) ...@@ -331,7 +332,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
b_res->end = size + min_align - 1; b_res->end = size + min_align - 1;
} }
void __init void __devinit
pbus_size_bridges(struct pci_bus *bus) pbus_size_bridges(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -357,8 +358,9 @@ pbus_size_bridges(struct pci_bus *bus) ...@@ -357,8 +358,9 @@ pbus_size_bridges(struct pci_bus *bus)
} }
pbus_size_mem(bus, mask, type); pbus_size_mem(bus, mask, type);
} }
EXPORT_SYMBOL(pbus_size_bridges);
void __init void __devinit
pbus_assign_resources(struct pci_bus *bus) pbus_assign_resources(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -379,6 +381,7 @@ pbus_assign_resources(struct pci_bus *bus) ...@@ -379,6 +381,7 @@ pbus_assign_resources(struct pci_bus *bus)
pci_setup_bridge(b); pci_setup_bridge(b);
} }
} }
EXPORT_SYMBOL(pbus_assign_resources);
void __init void __init
pci_assign_unassigned_resources(void) pci_assign_unassigned_resources(void)
......
...@@ -557,8 +557,12 @@ struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device, ...@@ -557,8 +557,12 @@ struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device,
unsigned int ss_vendor, unsigned int ss_device, unsigned int ss_vendor, unsigned int ss_device,
const struct pci_dev *from); const struct pci_dev *from);
struct pci_dev *pci_find_class (unsigned int class, const struct pci_dev *from); struct pci_dev *pci_find_class (unsigned int class, const struct pci_dev *from);
struct pci_bus *pci_find_bus(unsigned char busnr);
struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
unsigned char pci_bus_max_busnr(struct pci_bus* bus);
unsigned char pci_max_busnr(void);
int pci_find_capability (struct pci_dev *dev, int cap); int pci_find_capability (struct pci_dev *dev, int cap);
int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val); int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val); int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
...@@ -613,6 +617,8 @@ int pci_enable_wake(struct pci_dev *dev, u32 state, int enable); ...@@ -613,6 +617,8 @@ int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
/* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */ /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
void pbus_assign_resources(struct pci_bus *bus);
void pbus_size_bridges(struct pci_bus *bus);
int pci_claim_resource(struct pci_dev *, int); int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void); void pci_assign_unassigned_resources(void);
void pdev_enable_device(struct pci_dev *); void pdev_enable_device(struct pci_dev *);
...@@ -634,6 +640,7 @@ struct pci_driver *pci_dev_driver(const struct pci_dev *); ...@@ -634,6 +640,7 @@ struct pci_driver *pci_dev_driver(const struct pci_dev *);
const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev); const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev);
unsigned int pci_do_scan_bus(struct pci_bus *bus); unsigned int pci_do_scan_bus(struct pci_bus *bus);
struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr); struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
/* kmem_cache style wrapper around pci_alloc_consistent() */ /* kmem_cache style wrapper around pci_alloc_consistent() */
struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev, struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev,
......
...@@ -1100,6 +1100,9 @@ ...@@ -1100,6 +1100,9 @@
#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012 #define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012
#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 #define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014 #define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014
#define PCI_VENDOR_ID_ZIATECH 0x1138
#define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550
#define PCI_VENDOR_ID_CYCLONE 0x113c #define PCI_VENDOR_ID_CYCLONE 0x113c
#define PCI_DEVICE_ID_CYCLONE_SDK 0x0001 #define PCI_DEVICE_ID_CYCLONE_SDK 0x0001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment