Commit 82670e1f authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/pci_hp-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 42003664 d53e21af
......@@ -2218,6 +2218,15 @@ S: 30 White Tail Lane
S: Lafayette, Indiana 47905
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
E: trond.myklebust@fys.uio.no
D: current NFS client hacker.
......
......@@ -317,6 +317,27 @@ L: codalist@coda.cs.cmu.edu
W: http://www.coda.cs.cmu.edu/
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
P: Amy Vanzant-Hodge
M: Amy Vanzant-Hodge (fibrechannel@compaq.com)
......
......@@ -340,7 +340,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
return PCI_SLOT(dev->devfn);
}
void __init
void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges)
{
......
......@@ -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
* are examined.
......
......@@ -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_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 revision;
......@@ -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
* "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 &&
(dev->device & 0xff00) == 0x2400)
......
......@@ -297,8 +297,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
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)
{
}
......
......@@ -341,8 +341,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
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)
{
/*
* our caller figure out range by going through the dev structures.
......
......@@ -234,7 +234,7 @@ pcibios_fixup_bus(struct pci_bus *b)
pci_fixup_irqs(pci_swizzle, pci_map_irq);
}
void __init
void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges)
{
......
......@@ -349,8 +349,8 @@ void __init pcibios_fixup_bus (struct pci_bus *b)
}
/* XXX anybody know what this is supposed to do? */
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)
{
}
......
......@@ -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().
*/
void pcibios_fixup_pbus_ranges(
void __devinit pcibios_fixup_pbus_ranges(
struct pci_bus *bus,
struct pbus_set_ranges_data *ranges
)
......
......@@ -1107,7 +1107,7 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp)
return PCI_SLOT(dev->devfn);
}
void __init
void __devinit
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)
}
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges)
void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges)
{
}
......
......@@ -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[] = {
{ 0 }
};
void __init pcibios_fixup_pbus_ranges(struct pci_bus *b,
struct pbus_set_ranges_data *range)
void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *b,
struct pbus_set_ranges_data *range)
{
/* No fixups needed */
}
......
......@@ -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,
struct pbus_set_ranges_data *ranges)
{
......
......@@ -479,8 +479,8 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq)
{
}
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges)
void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges)
{
}
......
......@@ -73,5 +73,48 @@ config HOTPLUG_PCI_ACPI
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
......@@ -2,12 +2,15 @@
# 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_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.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_util.o
......@@ -28,6 +31,9 @@ acpiphp-objs := acpiphp_core.o \
acpiphp_pci.o \
acpiphp_res.o
cpci_hotplug-objs := cpci_hotplug_core.o \
cpci_hotplug_pci.o
ifdef CONFIG_HOTPLUG_PCI_ACPI
EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi
ifdef CONFIG_ACPI_DEBUG
......
......@@ -41,12 +41,12 @@
#define dbg(format, arg...) \
do { \
if (acpiphp_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
printk(KERN_DEBUG "%s: " format, \
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)
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
#define SLOT_MAGIC 0x67267322
/* 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)
if (!bar) /* This BAR is not implemented */
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) {
/* This is IO */
......@@ -85,7 +85,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFFC;
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);
res = acpiphp_get_io_resource(&bridge->io_head, len);
......@@ -110,7 +110,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFF0;
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);
res = acpiphp_get_resource(&bridge->p_mem_head, len);
......@@ -127,7 +127,7 @@ static int init_config_space (struct acpiphp_func *func)
(u32)res->base);
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;
pci_bus_write_config_dword(pbus, devfn,
address[count],
......@@ -143,7 +143,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFF0;
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);
res = acpiphp_get_resource(&bridge->mem_head, len);
......@@ -161,7 +161,7 @@ static int init_config_space (struct acpiphp_func *func)
if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* 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;
pci_bus_write_config_dword(pbus, devfn,
address[count],
......@@ -212,16 +212,16 @@ static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bu
//pci_proc_attach_device(dev);
//pci_announce_device_to_drivers(dev);
info("Device %s configured", dev->slot_name);
info("Device %s configured\n", dev->slot_name);
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 has claimed them
*/
......@@ -263,13 +263,13 @@ static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, stru
{
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 */
if (dev->driver) {
if (dev->driver->remove) {
dev->driver->remove(dev);
dbg("driver was properly removed");
dbg("driver was properly removed\n");
}
dev->driver = NULL;
}
......@@ -286,7 +286,7 @@ static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_
/* Now, remove the Linux Representation */
if (dev) {
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 */
} else {
return -1; /* problems while freeing, abort visitation */
......@@ -338,7 +338,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
int count;
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 */
pci_read_config_dword(dev, address[count], &bar);
......@@ -355,7 +355,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
len &= 0xFFFFFFFC;
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);
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 *
len = ~len + 1;
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
dbg ("prefetch mem 64");
dbg("prefetch mem 64\n");
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);
res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
spin_unlock(&bridge->res_lock);
......@@ -389,10 +389,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */
dbg ("mem 64");
dbg("mem 64\n");
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);
res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
spin_unlock(&bridge->res_lock);
......@@ -414,7 +414,7 @@ static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_b
struct list_head *l;
struct pci_dev *dev;
list_for_each(l, &bus->devices) {
list_for_each (l, &bus->devices) {
dev = pci_dev_b(l);
detect_used_resource(bridge, dev);
/* XXX recursive call */
......@@ -463,16 +463,16 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
struct pci_dev *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 */
pci_read_config_dword (dev, address[count], &bar);
pci_read_config_dword(dev, address[count], &bar);
if (!bar) /* This BAR is not implemented */
continue;
pci_write_config_dword (dev, address[count], 0xFFFFFFFF);
pci_read_config_dword (dev, address[count], &len);
pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
pci_read_config_dword(dev, address[count], &len);
if (len & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */
......@@ -480,7 +480,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len &= 0xFFFFFFFC;
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);
if (!res)
......@@ -499,10 +499,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len = ~len + 1;
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
dbg ("prefetch mem 64");
dbg("prefetch mem 64\n");
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);
if (!res)
goto no_memory;
......@@ -518,10 +518,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */
dbg ("mem 64");
dbg("mem 64\n");
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);
if (!res)
goto no_memory;
......@@ -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
acpiphp_dump_func_resource(func);
......@@ -541,7 +541,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
return 0;
no_memory:
err("out of memory");
err("out of memory\n");
acpiphp_free_resource(&func->io_head);
acpiphp_free_resource(&func->mem_head);
acpiphp_free_resource(&func->p_mem_head);
......@@ -574,7 +574,7 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
if (hdr & 0x80)
is_multi = 1;
list_for_each(l, &slot->funcs) {
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
if (is_multi || func->function == 0) {
pci_bus_read_config_dword(slot->bridge->pci_bus,
......@@ -583,7 +583,6 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
PCI_VENDOR_ID, &dvid);
if (dvid != 0xffffffff) {
retval = init_config_space(func);
if (retval)
break;
}
......
......@@ -273,7 +273,7 @@ struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 s
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. */
if (max->length < size)
continue;
......@@ -370,13 +370,13 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
return NULL;
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);
if (node->length < size)
continue;
if (node->base & (size - 1)) {
dbg("%s: not aligned", __FUNCTION__);
dbg("%s: not aligned\n", __FUNCTION__);
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword = (node->base | (size-1)) + 1;
......@@ -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 */
if (node->length > size) {
dbg("%s: too big", __FUNCTION__);
dbg("%s: too big\n", __FUNCTION__);
/* this one is longer than we need
so we'll make a new entry and split it up */
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)
node->next = split_node;
} /* 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
Now take it out of the list */
if (*head == node) {
......@@ -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
*
* this function
* this function
* 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.
*
......@@ -458,7 +458,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
return NULL;
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);
if (node->base > base)
continue;
......@@ -467,7 +467,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
continue;
if (node->base < base) {
dbg(": split 1");
dbg(": split 1\n");
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword = base;
......@@ -489,12 +489,12 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
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);
/* Don't need to check if too small since we already did */
if (node->length > size) {
dbg(": split 2");
dbg(": split 2\n");
/* this one is longer than we need
so we'll make a new entry and split it up */
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,
node->next = split_node;
} /* End of too big on top end */
dbg(": got one!!!");
dbg(": got one!!!\n");
/* If we got here, then it is the right size
Now take it out of the list */
if (*head == node) {
......@@ -547,13 +547,13 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
if (!(*head))
return 1;
dbg("*head->next = %p",(*head)->next);
dbg("*head->next = %p\n",(*head)->next);
if (!(*head)->next)
return 0; /* only one item on the list, already sorted! */
dbg("*head->base = 0x%x",(u32)(*head)->base);
dbg("*head->next->base = 0x%x", (u32)(*head)->next->base);
dbg("*head->base = 0x%x\n",(u32)(*head)->base);
dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base);
while (out_of_order) {
out_of_order = 0;
......@@ -587,7 +587,7 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
while (node1 && node1->next) {
if ((node1->base + node1->length) == node1->next->base) {
/* Combine */
dbg("8..");
dbg("8..\n");
node1->length += node1->next->length;
node2 = node1->next;
node1->next = node1->next->next;
......@@ -668,7 +668,7 @@ static void dump_resource(struct pci_resource *head)
cnt = 0;
while (p) {
dbg("[%02d] %08x - %08x",
dbg("[%02d] %08x - %08x\n",
cnt++, (u32)p->base, (u32)p->base + p->length - 1);
p = p->next;
}
......@@ -676,24 +676,24 @@ static void dump_resource(struct pci_resource *head)
void acpiphp_dump_resource(struct acpiphp_bridge *bridge)
{
dbg("I/O resource:");
dbg("I/O resource:\n");
dump_resource(bridge->io_head);
dbg("MEM resource:");
dbg("MEM resource:\n");
dump_resource(bridge->mem_head);
dbg("PMEM resource:");
dbg("PMEM resource:\n");
dump_resource(bridge->p_mem_head);
dbg("BUS resource:");
dbg("BUS resource:\n");
dump_resource(bridge->bus_head);
}
void acpiphp_dump_func_resource(struct acpiphp_func *func)
{
dbg("I/O resource:");
dbg("I/O resource:\n");
dump_resource(func->io_head);
dbg("MEM resource:");
dbg("MEM resource:\n");
dump_resource(func->mem_head);
dbg("PMEM resource:");
dbg("PMEM resource:\n");
dump_resource(func->p_mem_head);
dbg("BUS resource:");
dbg("BUS resource:\n");
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,
struct pci_dev_wrapped *wrapped_dev,
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
......@@ -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)
{
struct pci_bus *bus = wrapped_dev->dev->subordinate;
struct pci_bus *bus;
struct pci_bus_wrapped wrapped_bus;
int result;
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
int result = 0;
dbg("scanning bridge %02x, %02x\n", wrapped_dev->dev->devfn >> 3,
wrapped_dev->dev->devfn & 0x7);
dbg("scanning bridge %02x, %02x\n", PCI_SLOT(wrapped_dev->dev->devfn),
PCI_FUNC(wrapped_dev->dev->devfn));
if (fn->visit_pci_dev) {
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
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;
}
......@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st
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_is_dev_in_use);
EXPORT_SYMBOL(pci_remove_device_safe);
......@@ -3,7 +3,7 @@
#
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 \
compat.o names.o pci-driver.o search.o hotplug.o
......@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_DDB5476) += setup-bus.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
obj-y += syscall.o
endif
......
......@@ -71,8 +71,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
* @bus: where to insert it
*
* Link the device to both the global PCI device chain and the
* per-bus list of devices, add the /proc entry, and notify
* userspace (/sbin/hotplug).
* per-bus list of devices, add the /proc entry.
*/
void
pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
......
......@@ -24,6 +24,49 @@
#define DBG(x...)
#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
* @dev: PCI device to query
......@@ -79,6 +122,49 @@ pci_find_capability(struct pci_dev *dev, int cap)
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
......@@ -649,7 +735,10 @@ EXPORT_SYMBOL(isa_bridge);
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);
EXPORT_SYMBOL(pci_request_regions);
EXPORT_SYMBOL(pci_release_region);
......
......@@ -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
* 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 short cr;
......@@ -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
* the per-bus list of devices and call /sbin/hotplug if we
* should.
* the per-bus list of devices and add the /proc entry.
*/
pci_insert_device (dev, bus);
......@@ -596,4 +595,5 @@ EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bus);
EXPORT_SYMBOL(pci_scan_bridge);
#endif
......@@ -23,7 +23,7 @@
/* Deal with broken BIOS'es that neglect to enable passive release,
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;
unsigned char dlc;
......@@ -50,7 +50,7 @@ static void __init quirk_passive_release(struct pci_dev *dev)
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) {
isa_dma_bridge_buggy=1;
......@@ -64,7 +64,7 @@ int pci_pci_problems;
* 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)
{
......@@ -77,7 +77,7 @@ static void __init quirk_nopcipci(struct pci_dev *dev)
* 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)
{
......@@ -96,7 +96,7 @@ static void __init quirk_triton(struct pci_dev *dev)
* Updated based on further information from the site and also on
* 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;
u8 rev;
......@@ -150,7 +150,7 @@ static void __init quirk_vialatency(struct pci_dev *dev)
* 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)
{
......@@ -158,7 +158,7 @@ static void __init quirk_viaetbf(struct pci_dev *dev)
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)
{
......@@ -173,7 +173,7 @@ static void __init quirk_vsfx(struct pci_dev *dev)
* 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)
{
......@@ -187,7 +187,7 @@ static void __init quirk_natoma(struct pci_dev *dev)
* 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];
......@@ -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);
if (region) {
......@@ -222,7 +222,7 @@ static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigne
* 0xE0 (64 bytes of ACPI 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;
......@@ -237,7 +237,7 @@ static void __init quirk_ali7101_acpi(struct pci_dev *dev)
* 0x40 (64 bytes of ACPI 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;
......@@ -251,7 +251,7 @@ static void __init quirk_piix4_acpi(struct pci_dev *dev)
* VIA ACPI: One IO region pointed to by longword at
* 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;
u32 region;
......@@ -270,7 +270,7 @@ static void __init quirk_vt82c586_acpi(struct pci_dev *dev)
* 0x70 (128 bytes of hardware monitoring register)
* 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;
u32 smb;
......@@ -297,7 +297,7 @@ extern int nr_ioapics;
* TODO: When we have device-specific interrupt routers,
* 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;
......@@ -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.
* -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
......@@ -350,7 +350,7 @@ static void __init quirk_via_acpi(struct pci_dev *d)
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;
......@@ -377,7 +377,7 @@ static void __init quirk_via_irqpic(struct pci_dev *dev)
*
* 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;
......@@ -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
* 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_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
......@@ -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
* 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)
return;
......@@ -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..
*/
static void __init quirk_amd_ioapic(struct pci_dev *dev)
static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
{
u8 rev;
......@@ -441,7 +441,7 @@ static void __init quirk_amd_ioapic(struct pci_dev *dev)
* 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;
pci_read_config_dword(dev, 0x4C, &pcic);
......@@ -464,14 +464,14 @@ static void __init quirk_amd_ordering(struct pci_dev *dev)
* 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 ];
r -> start = 0;
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;
}
......@@ -480,7 +480,7 @@ static void __init quirk_transparent_bridge(struct pci_dev *dev)
* 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_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/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
* @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)
return NULL;
}
EXPORT_SYMBOL(pci_find_bus);
EXPORT_SYMBOL(pci_find_class);
EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot);
......
......@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/ioport.h>
......@@ -35,7 +36,7 @@
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
static int __init
static int __devinit
pbus_assign_resources_sorted(struct pci_bus *bus)
{
struct list_head *ln;
......@@ -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
bridge, corresponding range must be turned off by writing base
value greater than limit to the bridge's base/limit registers. */
static void __init
static void __devinit
pci_setup_bridge(struct pci_bus *bus)
{
struct pbus_set_ranges_data ranges;
......@@ -168,7 +169,7 @@ pci_setup_bridge(struct pci_bus *bus)
/* Check whether the bridge supports optional I/O and
prefetchable memory ranges. If not, the respective
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)
{
u16 io;
......@@ -210,7 +211,7 @@ pci_bridge_check_ranges(struct pci_bus *bus)
since these windows have 4K granularity and the IO ranges
of non-bridge PCI devices are limited to 256 bytes.
We must be careful with the ISA aliasing though. */
static void __init
static void __devinit
pbus_size_io(struct pci_bus *bus)
{
struct list_head *ln;
......@@ -259,7 +260,7 @@ pbus_size_io(struct pci_bus *bus)
/* Calculate the size of the bus and minimal alignment which
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)
{
struct list_head *ln;
......@@ -331,7 +332,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
b_res->end = size + min_align - 1;
}
void __init
void __devinit
pbus_size_bridges(struct pci_bus *bus)
{
struct list_head *ln;
......@@ -357,8 +358,9 @@ pbus_size_bridges(struct pci_bus *bus)
}
pbus_size_mem(bus, mask, type);
}
EXPORT_SYMBOL(pbus_size_bridges);
void __init
void __devinit
pbus_assign_resources(struct pci_bus *bus)
{
struct list_head *ln;
......@@ -379,6 +381,7 @@ pbus_assign_resources(struct pci_bus *bus)
pci_setup_bridge(b);
}
}
EXPORT_SYMBOL(pbus_assign_resources);
void __init
pci_assign_unassigned_resources(void)
......
......@@ -557,8 +557,12 @@ struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device,
unsigned int ss_vendor, unsigned int ss_device,
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);
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_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_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);
/* 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);
void pci_assign_unassigned_resources(void);
void pdev_enable_device(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);
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);
int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
/* kmem_cache style wrapper around pci_alloc_consistent() */
struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev,
......
......@@ -1100,6 +1100,9 @@
#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012
#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
#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_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