Subversion Repositories shark

Rev

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

Rev Author Line No. Line
428 giacomo 1
#include <linux/pci.h>
2
#include <linux/module.h>
3
#include "pci.h"
4
 
5
#undef DEBUG
6
 
7
#ifdef DEBUG
8
#define DBG(x...) printk(x)
9
#else
10
#define DBG(x...)
11
#endif
12
 
13
int pci_hotplug (struct device *dev, char **envp, int num_envp,
14
                 char *buffer, int buffer_size)
15
{
16
        struct pci_dev *pdev;
17
        char *scratch;
18
        int i = 0;
19
        int length = 0;
20
 
21
        if (!dev)
22
                return -ENODEV;
23
 
24
        pdev = to_pci_dev(dev);
25
        if (!pdev)
26
                return -ENODEV;
27
 
28
        scratch = buffer;
29
 
30
        /* stuff we want to pass to /sbin/hotplug */
31
        envp[i++] = scratch;
32
        length += snprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
33
                            pdev->class);
34
        if ((buffer_size - length <= 0) || (i >= num_envp))
35
                return -ENOMEM;
36
        ++length;
37
        scratch += length;
38
 
39
        envp[i++] = scratch;
40
        length += snprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
41
                            pdev->vendor, pdev->device);
42
        if ((buffer_size - length <= 0) || (i >= num_envp))
43
                return -ENOMEM;
44
        ++length;
45
        scratch += length;
46
 
47
        envp[i++] = scratch;
48
        length += snprintf (scratch, buffer_size - length,
49
                            "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
50
                            pdev->subsystem_device);
51
        if ((buffer_size - length <= 0) || (i >= num_envp))
52
                return -ENOMEM;
53
        ++length;
54
        scratch += length;
55
 
56
        envp[i++] = scratch;
57
        length += snprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
58
                            pci_name(pdev));
59
        if ((buffer_size - length <= 0) || (i >= num_envp))
60
                return -ENOMEM;
61
 
62
        envp[i] = 0;
63
 
64
        return 0;
65
}
66
 
67
static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
68
{
69
        struct list_head *ln;
70
        struct pci_dev *dev;
71
        struct pci_dev_wrapped wrapped_dev;
72
        int result = 0;
73
 
74
        DBG("scanning bus %02x\n", wrapped_bus->bus->number);
75
 
76
        if (fn->pre_visit_pci_bus) {
77
                result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
78
                if (result)
79
                        return result;
80
        }
81
 
82
        ln = wrapped_bus->bus->devices.next;
83
        while (ln != &wrapped_bus->bus->devices) {
84
                dev = pci_dev_b(ln);
85
                ln = ln->next;
86
 
87
                memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
88
                wrapped_dev.dev = dev;
89
 
90
                result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
91
                if (result)
92
                        return result;
93
        }
94
 
95
        if (fn->post_visit_pci_bus)
96
                result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
97
 
98
        return result;
99
}
100
 
101
static int pci_visit_bridge (struct pci_visit * fn,
102
                             struct pci_dev_wrapped *wrapped_dev,
103
                             struct pci_bus_wrapped *wrapped_parent)
104
{
105
        struct pci_bus *bus;
106
        struct pci_bus_wrapped wrapped_bus;
107
        int result = 0;
108
 
109
        DBG("scanning bridge %02x, %02x\n", PCI_SLOT(wrapped_dev->dev->devfn),
110
            PCI_FUNC(wrapped_dev->dev->devfn));
111
 
112
        if (fn->visit_pci_dev) {
113
                result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
114
                if (result)
115
                        return result;
116
        }
117
 
118
        bus = wrapped_dev->dev->subordinate;
119
        if(bus) {
120
                memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
121
                wrapped_bus.bus = bus;
122
 
123
                result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
124
        }
125
        return result;
126
}
127
 
128
/**
129
 * pci_visit_dev - scans the pci buses.
130
 * Every bus and every function is presented to a custom
131
 * function that can act upon it.
132
 */
133
int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev,
134
                   struct pci_bus_wrapped *wrapped_parent)
135
{
136
        struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
137
        int result = 0;
138
 
139
        if (!dev)
140
                return 0;
141
 
142
        if (fn->pre_visit_pci_dev) {
143
                result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
144
                if (result)
145
                        return result;
146
        }
147
 
148
        switch (dev->class >> 8) {
149
                case PCI_CLASS_BRIDGE_PCI:
150
                        result = pci_visit_bridge(fn, wrapped_dev,
151
                                                  wrapped_parent);
152
                        if (result)
153
                                return result;
154
                        break;
155
                default:
156
                        DBG("scanning device %02x, %02x\n",
157
                            PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
158
                        if (fn->visit_pci_dev) {
159
                                result = fn->visit_pci_dev (wrapped_dev,
160
                                                            wrapped_parent);
161
                                if (result)
162
                                        return result;
163
                        }
164
        }
165
 
166
        if (fn->post_visit_pci_dev)
167
                result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
168
 
169
        return result;
170
}
171
EXPORT_SYMBOL(pci_visit_dev);
172