OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [pci/] [bus.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
                resource_size_t size, resource_size_t align,
38
                resource_size_t min, unsigned int type_mask,
39
                void (*alignf)(void *, struct resource *, resource_size_t,
40
                                resource_size_t),
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,
64
                                        r->start ? : min,
65
                                        -1, align,
66
                                        alignf, alignf_data);
67
                if (ret == 0)
68
                        break;
69
        }
70
        return ret;
71
}
72
 
73
/**
74
 * add a single device
75
 * @dev: device to add
76
 *
77
 * This adds a single pci device to the global
78
 * device list and adds sysfs and procfs entries
79
 */
80
int pci_bus_add_device(struct pci_dev *dev)
81
{
82
        int retval;
83
        retval = device_add(&dev->dev);
84
        if (retval)
85
                return retval;
86
 
87
        down_write(&pci_bus_sem);
88
        list_add_tail(&dev->global_list, &pci_devices);
89
        up_write(&pci_bus_sem);
90
 
91
        pci_proc_attach_device(dev);
92
        pci_create_sysfs_dev_files(dev);
93
        return 0;
94
}
95
 
96
/**
97
 * pci_bus_add_devices - insert newly discovered PCI devices
98
 * @bus: bus to check for new devices
99
 *
100
 * Add newly discovered PCI devices (which are on the bus->devices
101
 * list) to the global PCI device list, add the sysfs and procfs
102
 * entries.  Where a bridge is found, add the discovered bus to
103
 * the parents list of child buses, and recurse (breadth-first
104
 * to be compatible with 2.4)
105
 *
106
 * Call hotplug for each new devices.
107
 */
108
void pci_bus_add_devices(struct pci_bus *bus)
109
{
110
        struct pci_dev *dev;
111
        int retval;
112
 
113
        list_for_each_entry(dev, &bus->devices, bus_list) {
114
                /*
115
                 * Skip already-present devices (which are on the
116
                 * global device list.)
117
                 */
118
                if (!list_empty(&dev->global_list))
119
                        continue;
120
                retval = pci_bus_add_device(dev);
121
                if (retval)
122
                        dev_err(&dev->dev, "Error adding device, continuing\n");
123
        }
124
 
125
        list_for_each_entry(dev, &bus->devices, bus_list) {
126
 
127
                BUG_ON(list_empty(&dev->global_list));
128
 
129
                /*
130
                 * If there is an unattached subordinate bus, attach
131
                 * it and then scan for unattached PCI devices.
132
                 */
133
                if (dev->subordinate) {
134
                       if (list_empty(&dev->subordinate->node)) {
135
                               down_write(&pci_bus_sem);
136
                               list_add_tail(&dev->subordinate->node,
137
                                               &dev->bus->children);
138
                               up_write(&pci_bus_sem);
139
                        }
140
                        pci_bus_add_devices(dev->subordinate);
141
                        retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
142
                                                   &dev->dev.kobj, "bridge");
143
                        if (retval)
144
                                dev_err(&dev->dev, "Error creating sysfs "
145
                                        "bridge symlink, continuing...\n");
146
                }
147
        }
148
}
149
 
150
void pci_enable_bridges(struct pci_bus *bus)
151
{
152
        struct pci_dev *dev;
153
        int retval;
154
 
155
        list_for_each_entry(dev, &bus->devices, bus_list) {
156
                if (dev->subordinate) {
157
                        retval = pci_enable_device(dev);
158
                        pci_set_master(dev);
159
                        pci_enable_bridges(dev->subordinate);
160
                }
161
        }
162
}
163
 
164
/** pci_walk_bus - walk devices on/under bus, calling callback.
165
 *  @top      bus whose devices should be walked
166
 *  @cb       callback to be called for each device found
167
 *  @userdata arbitrary pointer to be passed to callback.
168
 *
169
 *  Walk the given bus, including any bridged devices
170
 *  on buses under this bus.  Call the provided callback
171
 *  on each device found.
172
 */
173
void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
174
                  void *userdata)
175
{
176
        struct pci_dev *dev;
177
        struct pci_bus *bus;
178
        struct list_head *next;
179
 
180
        bus = top;
181
        down_read(&pci_bus_sem);
182
        next = top->devices.next;
183
        for (;;) {
184
                if (next == &bus->devices) {
185
                        /* end of this bus, go up or finish */
186
                        if (bus == top)
187
                                break;
188
                        next = bus->self->bus_list.next;
189
                        bus = bus->self->bus;
190
                        continue;
191
                }
192
                dev = list_entry(next, struct pci_dev, bus_list);
193
                if (dev->subordinate) {
194
                        /* this is a pci-pci bridge, do its devices next */
195
                        next = dev->subordinate->devices.next;
196
                        bus = dev->subordinate;
197
                } else
198
                        next = dev->bus_list.next;
199
 
200
                /* Run device routines with the device locked */
201
                down(&dev->dev.sem);
202
                cb(dev, userdata);
203
                up(&dev->dev.sem);
204
        }
205
        up_read(&pci_bus_sem);
206
}
207
EXPORT_SYMBOL_GPL(pci_walk_bus);
208
 
209
EXPORT_SYMBOL(pci_bus_alloc_resource);
210
EXPORT_SYMBOL_GPL(pci_bus_add_device);
211
EXPORT_SYMBOL(pci_bus_add_devices);
212
EXPORT_SYMBOL(pci_enable_bridges);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.