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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [pci_bind.c] - Blame information for rev 67

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $)
3
 *
4
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6
 *
7
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or (at
12
 *  your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful, but
15
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 *  General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License along
20
 *  with this program; if not, write to the Free Software Foundation, Inc.,
21
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22
 *
23
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
 */
25
 
26
#include <linux/kernel.h>
27
#include <linux/module.h>
28
#include <linux/init.h>
29
#include <linux/types.h>
30
#include <linux/proc_fs.h>
31
#include <linux/spinlock.h>
32
#include <linux/pm.h>
33
#include <linux/pci.h>
34
#include <linux/acpi.h>
35
#include <acpi/acpi_bus.h>
36
#include <acpi/acpi_drivers.h>
37
 
38
#define _COMPONENT              ACPI_PCI_COMPONENT
39
ACPI_MODULE_NAME("pci_bind");
40
 
41
struct acpi_pci_data {
42
        struct acpi_pci_id id;
43
        struct pci_bus *bus;
44
        struct pci_dev *dev;
45
};
46
 
47
static void acpi_pci_data_handler(acpi_handle handle, u32 function,
48
                                  void *context)
49
{
50
 
51
        /* TBD: Anything we need to do here? */
52
 
53
        return;
54
}
55
 
56
/**
57
 * acpi_get_pci_id
58
 * ------------------
59
 * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)
60
 * to resolve PCI information for ACPI-PCI devices defined in the namespace.
61
 * This typically occurs when resolving PCI operation region information.
62
 */
63
acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id)
64
{
65
        int result = 0;
66
        acpi_status status = AE_OK;
67
        struct acpi_device *device = NULL;
68
        struct acpi_pci_data *data = NULL;
69
 
70
 
71
        if (!id)
72
                return AE_BAD_PARAMETER;
73
 
74
        result = acpi_bus_get_device(handle, &device);
75
        if (result) {
76
                printk(KERN_ERR PREFIX
77
                            "Invalid ACPI Bus context for device %s\n",
78
                            acpi_device_bid(device));
79
                return AE_NOT_EXIST;
80
        }
81
 
82
        status = acpi_get_data(handle, acpi_pci_data_handler, (void **)&data);
83
        if (ACPI_FAILURE(status) || !data) {
84
                ACPI_EXCEPTION((AE_INFO, status,
85
                                "Invalid ACPI-PCI context for device %s",
86
                                acpi_device_bid(device)));
87
                return status;
88
        }
89
 
90
        *id = data->id;
91
 
92
        /*
93
           id->segment = data->id.segment;
94
           id->bus = data->id.bus;
95
           id->device = data->id.device;
96
           id->function = data->id.function;
97
         */
98
 
99
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
100
                          "Device %s has PCI address %02x:%02x:%02x.%02x\n",
101
                          acpi_device_bid(device), id->segment, id->bus,
102
                          id->device, id->function));
103
 
104
        return AE_OK;
105
}
106
 
107
EXPORT_SYMBOL(acpi_get_pci_id);
108
 
109
int acpi_pci_bind(struct acpi_device *device)
110
{
111
        int result = 0;
112
        acpi_status status = AE_OK;
113
        struct acpi_pci_data *data = NULL;
114
        struct acpi_pci_data *pdata = NULL;
115
        char *pathname = NULL;
116
        struct acpi_buffer buffer = { 0, NULL };
117
        acpi_handle handle = NULL;
118
        struct pci_dev *dev;
119
        struct pci_bus *bus;
120
 
121
 
122
        if (!device || !device->parent)
123
                return -EINVAL;
124
 
125
        pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
126
        if (!pathname)
127
                return -ENOMEM;
128
        buffer.length = ACPI_PATHNAME_MAX;
129
        buffer.pointer = pathname;
130
 
131
        data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
132
        if (!data) {
133
                kfree(pathname);
134
                return -ENOMEM;
135
        }
136
 
137
        acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
138
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
139
                          pathname));
140
 
141
        /*
142
         * Segment & Bus
143
         * -------------
144
         * These are obtained via the parent device's ACPI-PCI context.
145
         */
146
        status = acpi_get_data(device->parent->handle, acpi_pci_data_handler,
147
                               (void **)&pdata);
148
        if (ACPI_FAILURE(status) || !pdata || !pdata->bus) {
149
                ACPI_EXCEPTION((AE_INFO, status,
150
                                "Invalid ACPI-PCI context for parent device %s",
151
                                acpi_device_bid(device->parent)));
152
                result = -ENODEV;
153
                goto end;
154
        }
155
        data->id.segment = pdata->id.segment;
156
        data->id.bus = pdata->bus->number;
157
 
158
        /*
159
         * Device & Function
160
         * -----------------
161
         * These are simply obtained from the device's _ADR method.  Note
162
         * that a value of zero is valid.
163
         */
164
        data->id.device = device->pnp.bus_address >> 16;
165
        data->id.function = device->pnp.bus_address & 0xFFFF;
166
 
167
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n",
168
                          data->id.segment, data->id.bus, data->id.device,
169
                          data->id.function));
170
 
171
        /*
172
         * TBD: Support slot devices (e.g. function=0xFFFF).
173
         */
174
 
175
        /*
176
         * Locate PCI Device
177
         * -----------------
178
         * Locate matching device in PCI namespace.  If it doesn't exist
179
         * this typically means that the device isn't currently inserted
180
         * (e.g. docking station, port replicator, etc.).
181
         * We cannot simply search the global pci device list, since
182
         * PCI devices are added to the global pci list when the root
183
         * bridge start ops are run, which may not have happened yet.
184
         */
185
        bus = pci_find_bus(data->id.segment, data->id.bus);
186
        if (bus) {
187
                list_for_each_entry(dev, &bus->devices, bus_list) {
188
                        if (dev->devfn == PCI_DEVFN(data->id.device,
189
                                                    data->id.function)) {
190
                                data->dev = dev;
191
                                break;
192
                        }
193
                }
194
        }
195
        if (!data->dev) {
196
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
197
                                  "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
198
                                  data->id.segment, data->id.bus,
199
                                  data->id.device, data->id.function));
200
                result = -ENODEV;
201
                goto end;
202
        }
203
        if (!data->dev->bus) {
204
                printk(KERN_ERR PREFIX
205
                            "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
206
                            data->id.segment, data->id.bus,
207
                            data->id.device, data->id.function);
208
                result = -ENODEV;
209
                goto end;
210
        }
211
 
212
        /*
213
         * PCI Bridge?
214
         * -----------
215
         * If so, set the 'bus' field and install the 'bind' function to
216
         * facilitate callbacks for all of its children.
217
         */
218
        if (data->dev->subordinate) {
219
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
220
                                  "Device %02x:%02x:%02x.%02x is a PCI bridge\n",
221
                                  data->id.segment, data->id.bus,
222
                                  data->id.device, data->id.function));
223
                data->bus = data->dev->subordinate;
224
                device->ops.bind = acpi_pci_bind;
225
                device->ops.unbind = acpi_pci_unbind;
226
        }
227
 
228
        /*
229
         * Attach ACPI-PCI Context
230
         * -----------------------
231
         * Thus binding the ACPI and PCI devices.
232
         */
233
        status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
234
        if (ACPI_FAILURE(status)) {
235
                ACPI_EXCEPTION((AE_INFO, status,
236
                                "Unable to attach ACPI-PCI context to device %s",
237
                                acpi_device_bid(device)));
238
                result = -ENODEV;
239
                goto end;
240
        }
241
 
242
        /*
243
         * PCI Routing Table
244
         * -----------------
245
         * Evaluate and parse _PRT, if exists.  This code is independent of
246
         * PCI bridges (above) to allow parsing of _PRT objects within the
247
         * scope of non-bridge devices.  Note that _PRTs within the scope of
248
         * a PCI bridge assume the bridge's subordinate bus number.
249
         *
250
         * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
251
         */
252
        status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
253
        if (ACPI_SUCCESS(status)) {
254
                if (data->bus)  /* PCI-PCI bridge */
255
                        acpi_pci_irq_add_prt(device->handle, data->id.segment,
256
                                             data->bus->number);
257
                else            /* non-bridge PCI device */
258
                        acpi_pci_irq_add_prt(device->handle, data->id.segment,
259
                                             data->id.bus);
260
        }
261
 
262
      end:
263
        kfree(pathname);
264
        if (result)
265
                kfree(data);
266
 
267
        return result;
268
}
269
 
270
int acpi_pci_unbind(struct acpi_device *device)
271
{
272
        int result = 0;
273
        acpi_status status = AE_OK;
274
        struct acpi_pci_data *data = NULL;
275
        char *pathname = NULL;
276
        struct acpi_buffer buffer = { 0, NULL };
277
 
278
 
279
        if (!device || !device->parent)
280
                return -EINVAL;
281
 
282
        pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
283
        if (!pathname)
284
                return -ENOMEM;
285
 
286
        buffer.length = ACPI_PATHNAME_MAX;
287
        buffer.pointer = pathname;
288
        acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
289
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
290
                          pathname));
291
        kfree(pathname);
292
 
293
        status =
294
            acpi_get_data(device->handle, acpi_pci_data_handler,
295
                          (void **)&data);
296
        if (ACPI_FAILURE(status)) {
297
                result = -ENODEV;
298
                goto end;
299
        }
300
 
301
        status = acpi_detach_data(device->handle, acpi_pci_data_handler);
302
        if (ACPI_FAILURE(status)) {
303
                ACPI_EXCEPTION((AE_INFO, status,
304
                                "Unable to detach data from device %s",
305
                                acpi_device_bid(device)));
306
                result = -ENODEV;
307
                goto end;
308
        }
309
        if (data->dev->subordinate) {
310
                acpi_pci_irq_del_prt(data->id.segment, data->bus->number);
311
        }
312
        kfree(data);
313
 
314
      end:
315
        return result;
316
}
317
 
318
int
319
acpi_pci_bind_root(struct acpi_device *device,
320
                   struct acpi_pci_id *id, struct pci_bus *bus)
321
{
322
        int result = 0;
323
        acpi_status status = AE_OK;
324
        struct acpi_pci_data *data = NULL;
325
        char *pathname = NULL;
326
        struct acpi_buffer buffer = { 0, NULL };
327
 
328
        pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
329
        if (!pathname)
330
                return -ENOMEM;
331
 
332
        buffer.length = ACPI_PATHNAME_MAX;
333
        buffer.pointer = pathname;
334
 
335
        if (!device || !id || !bus) {
336
                kfree(pathname);
337
                return -EINVAL;
338
        }
339
 
340
        data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
341
        if (!data) {
342
                kfree(pathname);
343
                return -ENOMEM;
344
        }
345
 
346
        data->id = *id;
347
        data->bus = bus;
348
        device->ops.bind = acpi_pci_bind;
349
        device->ops.unbind = acpi_pci_unbind;
350
 
351
        acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
352
 
353
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
354
                          "%02x:%02x\n", pathname, id->segment, id->bus));
355
 
356
        status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
357
        if (ACPI_FAILURE(status)) {
358
                ACPI_EXCEPTION((AE_INFO, status,
359
                                "Unable to attach ACPI-PCI context to device %s",
360
                                pathname));
361
                result = -ENODEV;
362
                goto end;
363
        }
364
 
365
      end:
366
        kfree(pathname);
367
        if (result != 0)
368
                kfree(data);
369
 
370
        return result;
371
}

powered by: WebSVN 2.1.0

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