Subversion Repositories shark

Rev

Rev 430 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
428 giacomo 1
/*
2
 *      drivers/pci/bus.c
3
 *
4
 * From setup-res.c, by:
5
 *      Dave Rusling (david.rusling@reo.mts.dec.com)
6
 *      David Mosberger (davidm@cs.arizona.edu)
7
 *      David Miller (davem@redhat.com)
8
 *      Ivan Kokshaysky (ink@jurassic.park.msu.ru)
9
 */
10
#include <linux/module.h>
11
#include <linux/kernel.h>
12
#include <linux/pci.h>
13
#include <linux/errno.h>
14
#include <linux/ioport.h>
15
#include <linux/proc_fs.h>
16
#include <linux/init.h>
17
 
18
#include "pci.h"
19
 
20
/**
21
 * pci_bus_alloc_resource - allocate a resource from a parent bus
22
 * @bus: PCI bus
23
 * @res: resource to allocate
24
 * @size: size of resource to allocate
25
 * @align: alignment of resource to allocate
26
 * @min: minimum /proc/iomem address to allocate
27
 * @type_mask: IORESOURCE_* type flags
28
 * @alignf: resource alignment function
29
 * @alignf_data: data argument for resource alignment function
30
 *
31
 * Given the PCI bus a device resides on, the size, minimum address,
32
 * alignment and type, try to find an acceptable resource allocation
33
 * for a specific device resource.
34
 */
35
int
36
pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
37
        unsigned long size, unsigned long align, unsigned long min,
38
        unsigned int type_mask,
39
        void (*alignf)(void *, struct resource *,
40
                        unsigned long, unsigned long),
41
        void *alignf_data)
42
{
43
        int i, ret = -ENOMEM;
44
 
45
        type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
46
 
47
        for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
48
                struct resource *r = bus->resource[i];
49
                if (!r)
50
                        continue;
51
 
52
                /* type_mask must match */
53
                if ((res->flags ^ r->flags) & type_mask)
54
                        continue;
55
 
56
                /* We cannot allocate a non-prefetching resource
57
                   from a pre-fetching area */
58
                if ((r->flags & IORESOURCE_PREFETCH) &&
59
                    !(res->flags & IORESOURCE_PREFETCH))
60
                        continue;
61
 
62
                /* Ok, try it out.. */
63
                ret = allocate_resource(r, res, size, min, -1, align,
64
                                        alignf, alignf_data);
65
                if (ret == 0)
66
                        break;
67
        }
68
        return ret;
69
}
70
 
71
/**
72
 * pci_bus_add_devices - insert newly discovered PCI devices
73
 * @bus: bus to check for new devices
74
 *
75
 * Add newly discovered PCI devices (which are on the bus->devices
76
 * list) to the global PCI device list, add the sysfs and procfs
77
 * entries.  Where a bridge is found, add the discovered bus to
78
 * the parents list of child buses, and recurse (breadth-first
79
 * to be compatible with 2.4)
80
 *
81
 * Call hotplug for each new devices.
82
 */
83
void __devinit pci_bus_add_devices(struct pci_bus *bus)
84
{
85
        struct pci_dev *dev;
86
 
87
        list_for_each_entry(dev, &bus->devices, bus_list) {
88
                /*
89
                 * Skip already-present devices (which are on the
90
                 * global device list.)
91
                 */
92
                if (!list_empty(&dev->global_list))
93
                        continue;
94
 
95
                device_add(&dev->dev);
96
 
97
                spin_lock(&pci_bus_lock);
98
                list_add_tail(&dev->global_list, &pci_devices);
99
                spin_unlock(&pci_bus_lock);
100
 
101
                pci_proc_attach_device(dev);
102
                pci_create_sysfs_dev_files(dev);
103
 
104
        }
105
 
106
        list_for_each_entry(dev, &bus->devices, bus_list) {
107
 
108
                BUG_ON(list_empty(&dev->global_list));
109
 
110
                /*
111
                 * If there is an unattached subordinate bus, attach
112
                 * it and then scan for unattached PCI devices.
113
                 */
114
                if (dev->subordinate && list_empty(&dev->subordinate->node)) {
115
                        spin_lock(&pci_bus_lock);
116
                        list_add_tail(&dev->subordinate->node, &dev->bus->children);
117
                        spin_unlock(&pci_bus_lock);
118
                        pci_bus_add_devices(dev->subordinate);
119
                }
120
        }
121
}
122
 
123
void pci_enable_bridges(struct pci_bus *bus)
124
{
125
        struct pci_dev *dev;
126
 
127
        list_for_each_entry(dev, &bus->devices, bus_list) {
128
                if (dev->subordinate) {
129
                        pci_enable_device(dev);
130
                        pci_set_master(dev);
131
                        pci_enable_bridges(dev->subordinate);
132
                }
133
        }
134
}
135
 
136
EXPORT_SYMBOL(pci_bus_add_devices);
137
EXPORT_SYMBOL(pci_enable_bridges);