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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [hotplug/] [acpiphp_pci.c] - Blame information for rev 1780

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * ACPI PCI HotPlug PCI configuration space management
3
 *
4
 * Copyright (C) 1995,2001 Compaq Computer Corporation
5
 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6
 * Copyright (C) 2001,2002 IBM Corp.
7
 * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
8
 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
9
 * Copyright (C) 2002 NEC Corporation
10
 *
11
 * All rights reserved.
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or (at
16
 * your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful, but
19
 * WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
21
 * NON INFRINGEMENT.  See the GNU General Public License for more
22
 * details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
 *
28
 * Send feedback to <t-kochi@bq.jp.nec.com>
29
 *
30
 */
31
 
32
#include <linux/config.h>
33
#include <linux/kernel.h>
34
#include <linux/module.h>
35
#include <linux/pci.h>
36
#include <linux/init.h>
37
#include "pci_hotplug.h"
38
#include "acpiphp.h"
39
 
40
#define MY_NAME "acpiphp_pci"
41
 
42
static void acpiphp_configure_irq (struct pci_dev *dev);
43
 
44
 
45
/* allocate mem/pmem/io resource to a new function */
46
static int init_config_space (struct acpiphp_func *func)
47
{
48
        u32 bar, len;
49
        u32 address[] = {
50
                PCI_BASE_ADDRESS_0,
51
                PCI_BASE_ADDRESS_1,
52
                PCI_BASE_ADDRESS_2,
53
                PCI_BASE_ADDRESS_3,
54
                PCI_BASE_ADDRESS_4,
55
                PCI_BASE_ADDRESS_5,
56
 
57
        };
58
        int count;
59
        struct acpiphp_bridge *bridge;
60
        struct pci_resource *res;
61
        struct pci_bus *bus;
62
        int devfn;
63
 
64
        bridge = func->slot->bridge;
65
        bus = bridge->pci_bus;
66
        devfn = PCI_DEVFN(func->slot->device, func->function);
67
 
68
        for (count = 0; address[count]; count++) {       /* for 6 BARs */
69
                pci_bus_write_config_dword(bus, devfn, address[count], 0xFFFFFFFF);
70
                pci_bus_read_config_dword(bus, devfn, address[count], &bar);
71
 
72
                if (!bar)       /* This BAR is not implemented */
73
                        continue;
74
 
75
                dbg("Device %02x.%d BAR %d wants %x\n", PCI_SLOT(devfn),
76
                                PCI_FUNC(devfn), count, bar);
77
 
78
                if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
79
                        /* This is IO */
80
 
81
                        len = bar & 0xFFFFFFFC;
82
                        len = ~len + 1;
83
 
84
                        dbg("len in IO %x, BAR %d\n", len, count);
85
 
86
                        spin_lock(&bridge->res_lock);
87
                        res = acpiphp_get_io_resource(&bridge->io_head, len);
88
                        spin_unlock(&bridge->res_lock);
89
 
90
                        if (!res) {
91
                                err("cannot allocate requested io for %02x:%02x.%d len %x\n",
92
                                    bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len);
93
                                return -1;
94
                        }
95
                        pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base);
96
                        res->next = func->io_head;
97
                        func->io_head = res;
98
 
99
                } else {
100
                        /* This is Memory */
101
                        if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
102
                                /* pfmem */
103
 
104
                                len = bar & 0xFFFFFFF0;
105
                                len = ~len + 1;
106
 
107
                                dbg("len in PFMEM %x, BAR %d\n", len, count);
108
 
109
                                spin_lock(&bridge->res_lock);
110
                                res = acpiphp_get_resource(&bridge->p_mem_head, len);
111
                                spin_unlock(&bridge->res_lock);
112
 
113
                                if (!res) {
114
                                        err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
115
                                            bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len);
116
                                        return -1;
117
                                }
118
 
119
                                pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base);
120
 
121
                                if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {       /* takes up another dword */
122
                                        dbg("inside the pfmem 64 case, count %d\n", count);
123
                                        count += 1;
124
                                        pci_bus_write_config_dword(bus, devfn, address[count], (u32)(res->base >> 32));
125
                                }
126
 
127
                                res->next = func->p_mem_head;
128
                                func->p_mem_head = res;
129
 
130
                        } else {
131
                                /* regular memory */
132
 
133
                                len = bar & 0xFFFFFFF0;
134
                                len = ~len + 1;
135
 
136
                                dbg("len in MEM %x, BAR %d\n", len, count);
137
 
138
                                spin_lock(&bridge->res_lock);
139
                                res = acpiphp_get_resource(&bridge->mem_head, len);
140
                                spin_unlock(&bridge->res_lock);
141
 
142
                                if (!res) {
143
                                        err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",
144
                                            bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), len);
145
                                        return -1;
146
                                }
147
 
148
                                pci_bus_write_config_dword(bus, devfn, address[count], (u32)res->base);
149
 
150
                                if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
151
                                        /* takes up another dword */
152
                                        dbg("inside mem 64 case, reg. mem, count %d\n", count);
153
                                        count += 1;
154
                                        pci_bus_write_config_dword(bus, devfn, address[count], (u32)(res->base >> 32));
155
                                }
156
 
157
                                res->next = func->mem_head;
158
                                func->mem_head = res;
159
 
160
                        }
161
                }
162
        }
163
 
164
        /* disable expansion rom */
165
        pci_bus_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, 0x00000000);
166
 
167
        return 0;
168
}
169
 
170
 
171
/* enable pci_dev */
172
static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
173
{
174
        u16 tmp;
175
        struct acpiphp_func *func;
176
        struct acpiphp_bridge *bridge;
177
        struct pci_dev *dev;
178
 
179
        func = (struct acpiphp_func *)wrapped_dev->data;
180
        bridge = (struct acpiphp_bridge *)wrapped_bus->data;
181
        dev = wrapped_dev->dev;
182
 
183
        /* TBD: support PCI-to-PCI bridge case */
184
        if (!func || !bridge)
185
                return 0;
186
 
187
        pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, bridge->hpp.cache_line_size);
188
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, bridge->hpp.latency_timer);
189
 
190
        pci_read_config_word(dev, PCI_COMMAND, &tmp);
191
        if (bridge->hpp.enable_SERR)
192
                tmp |= PCI_COMMAND_SERR;
193
        if (bridge->hpp.enable_PERR)
194
                tmp |= PCI_COMMAND_PARITY;
195
        //tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
196
        pci_write_config_word(dev, PCI_COMMAND, tmp);
197
 
198
        acpiphp_configure_irq(dev);
199
#ifdef CONFIG_PROC_FS
200
        pci_proc_attach_device(dev);
201
#endif
202
        pci_announce_device_to_drivers(dev);
203
        info("Device %s configured\n", dev->slot_name);
204
 
205
        return 0;
206
}
207
 
208
 
209
static int is_pci_dev_in_use (struct pci_dev* dev)
210
{
211
        /*
212
         * dev->driver will be set if the device is in use by a new-style
213
         * driver -- otherwise, check the device's regions to see if any
214
         * driver has claimed them
215
         */
216
 
217
        int i, inuse=0;
218
 
219
        if (dev->driver) return 1; //assume driver feels responsible
220
 
221
        for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
222
                if (!pci_resource_start(dev, i))
223
                        continue;
224
 
225
                if (pci_resource_flags(dev, i) & IORESOURCE_IO)
226
                        inuse = check_region(pci_resource_start(dev, i),
227
                                             pci_resource_len(dev, i));
228
                else if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
229
                        inuse = check_mem_region(pci_resource_start(dev, i),
230
                                                 pci_resource_len(dev, i));
231
        }
232
 
233
        return inuse;
234
}
235
 
236
 
237
static int pci_hp_remove_device (struct pci_dev *dev)
238
{
239
        if (is_pci_dev_in_use(dev)) {
240
                err("***Cannot safely power down device -- "
241
                       "it appears to be in use***\n");
242
                return -EBUSY;
243
        }
244
        pci_remove_device(dev);
245
        return 0;
246
}
247
 
248
 
249
/* remove device driver */
250
static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
251
{
252
        struct pci_dev *dev = wrapped_dev->dev;
253
 
254
        dbg("attempting removal of driver for device %s\n", dev->slot_name);
255
 
256
        /* Now, remove the Linux Driver Representation */
257
        if (dev->driver) {
258
                if (dev->driver->remove) {
259
                        dev->driver->remove(dev);
260
                        dbg("driver was properly removed\n");
261
                }
262
                dev->driver = NULL;
263
        }
264
 
265
        return is_pci_dev_in_use(dev);
266
}
267
 
268
 
269
/* remove pci_dev itself from system */
270
static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
271
{
272
        struct pci_dev *dev = wrapped_dev->dev;
273
 
274
        /* Now, remove the Linux Representation */
275
        if (dev) {
276
                if (pci_hp_remove_device(dev) == 0) {
277
                        info("Device %s removed\n", dev->slot_name);
278
                        kfree(dev); /* Now, remove */
279
                } else {
280
                        return -1; /* problems while freeing, abort visitation */
281
                }
282
        }
283
 
284
        return 0;
285
}
286
 
287
 
288
/* remove pci_bus itself from system */
289
static int unconfigure_pci_bus (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev)
290
{
291
        struct pci_bus *bus = wrapped_bus->bus;
292
 
293
#ifdef CONFIG_PROC_FS
294
        /* Now, remove the Linux Representation */
295
        if (bus->procdir) {
296
                pci_proc_detach_bus(bus);
297
        }
298
#endif
299
        /* the cleanup code should live in the kernel ... */
300
        bus->self->subordinate = NULL;
301
        /* unlink from parent bus */
302
        list_del(&bus->node);
303
 
304
        /* Now, remove */
305
        if (bus)
306
                kfree(bus);
307
 
308
        return 0;
309
}
310
 
311
 
312
/* detect_used_resource - subtract resource under dev from bridge */
313
static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
314
{
315
        u32 bar, len;
316
        u64 base;
317
        u32 address[] = {
318
                PCI_BASE_ADDRESS_0,
319
                PCI_BASE_ADDRESS_1,
320
                PCI_BASE_ADDRESS_2,
321
                PCI_BASE_ADDRESS_3,
322
                PCI_BASE_ADDRESS_4,
323
                PCI_BASE_ADDRESS_5,
324
 
325
        };
326
        int count;
327
        struct pci_resource *res;
328
 
329
        dbg("Device %s\n", dev->slot_name);
330
 
331
        for (count = 0; address[count]; count++) {       /* for 6 BARs */
332
                pci_read_config_dword(dev, address[count], &bar);
333
 
334
                if (!bar)       /* This BAR is not implemented */
335
                        continue;
336
 
337
                pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
338
                pci_read_config_dword(dev, address[count], &len);
339
 
340
                if (len & PCI_BASE_ADDRESS_SPACE_IO) {
341
                        /* This is IO */
342
                        base = bar & 0xFFFFFFFC;
343
                        len &= 0xFFFFFFFC;
344
                        len = ~len + 1;
345
 
346
                        dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
347
 
348
                        spin_lock(&bridge->res_lock);
349
                        res = acpiphp_get_resource_with_base(&bridge->io_head, base, len);
350
                        spin_unlock(&bridge->res_lock);
351
                        if (res)
352
                                kfree(res);
353
                } else {
354
                        /* This is Memory */
355
                        base = bar & 0xFFFFFFF0;
356
                        if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
357
                                /* pfmem */
358
 
359
                                len &= 0xFFFFFFF0;
360
                                len = ~len + 1;
361
 
362
                                if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {       /* takes up another dword */
363
                                        dbg("prefetch mem 64\n");
364
                                        count += 1;
365
                                }
366
                                dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
367
                                spin_lock(&bridge->res_lock);
368
                                res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
369
                                spin_unlock(&bridge->res_lock);
370
                                if (res)
371
                                        kfree(res);
372
                        } else {
373
                                /* regular memory */
374
 
375
                                len &= 0xFFFFFFF0;
376
                                len = ~len + 1;
377
 
378
                                if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
379
                                        /* takes up another dword */
380
                                        dbg("mem 64\n");
381
                                        count += 1;
382
                                }
383
                                dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
384
                                spin_lock(&bridge->res_lock);
385
                                res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
386
                                spin_unlock(&bridge->res_lock);
387
                                if (res)
388
                                        kfree(res);
389
                        }
390
                }
391
 
392
                pci_write_config_dword(dev, address[count], bar);
393
        }
394
 
395
        return 0;
396
}
397
 
398
 
399
/* detect_pci_resource_bus - subtract resource under pci_bus */
400
static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_bus *bus)
401
{
402
        struct list_head *l;
403
        struct pci_dev *dev;
404
 
405
        list_for_each (l, &bus->devices) {
406
                dev = pci_dev_b(l);
407
                detect_used_resource(bridge, dev);
408
                /* XXX recursive call */
409
                if (dev->subordinate)
410
                        detect_used_resource_bus(bridge, dev->subordinate);
411
        }
412
}
413
 
414
 
415
/**
416
 * acpiphp_detect_pci_resource - detect resources under bridge
417
 * @bridge: detect all resources already used under this bridge
418
 *
419
 * collect all resources already allocated for all devices under a bridge.
420
 */
421
int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
422
{
423
        detect_used_resource_bus(bridge, bridge->pci_bus);
424
 
425
        return 0;
426
}
427
 
428
 
429
/**
430
 * acpiphp_init_slot_resource - gather resource usage information of a slot
431
 * @slot: ACPI slot object to be checked, should have valid pci_dev member
432
 *
433
 * TBD: PCI-to-PCI bridge case
434
 *      use pci_dev->resource[]
435
 */
436
int acpiphp_init_func_resource (struct acpiphp_func *func)
437
{
438
        u64 base;
439
        u32 bar, len;
440
        u32 address[] = {
441
                PCI_BASE_ADDRESS_0,
442
                PCI_BASE_ADDRESS_1,
443
                PCI_BASE_ADDRESS_2,
444
                PCI_BASE_ADDRESS_3,
445
                PCI_BASE_ADDRESS_4,
446
                PCI_BASE_ADDRESS_5,
447
 
448
        };
449
        int count;
450
        struct pci_resource *res;
451
        struct pci_dev *dev;
452
 
453
        dev = func->pci_dev;
454
        dbg("Hot-pluggable device %s\n", dev->slot_name);
455
 
456
        for (count = 0; address[count]; count++) {       /* for 6 BARs */
457
                pci_read_config_dword(dev, address[count], &bar);
458
 
459
                if (!bar)       /* This BAR is not implemented */
460
                        continue;
461
 
462
                pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
463
                pci_read_config_dword(dev, address[count], &len);
464
 
465
                if (len & PCI_BASE_ADDRESS_SPACE_IO) {
466
                        /* This is IO */
467
                        base = bar & 0xFFFFFFFC;
468
                        len &= 0xFFFFFFFC;
469
                        len = ~len + 1;
470
 
471
                        dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
472
 
473
                        res = acpiphp_make_resource(base, len);
474
                        if (!res)
475
                                goto no_memory;
476
 
477
                        res->next = func->io_head;
478
                        func->io_head = res;
479
 
480
                } else {
481
                        /* This is Memory */
482
                        base = bar & 0xFFFFFFF0;
483
                        if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
484
                                /* pfmem */
485
 
486
                                len &= 0xFFFFFFF0;
487
                                len = ~len + 1;
488
 
489
                                if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {       /* takes up another dword */
490
                                        dbg("prefetch mem 64\n");
491
                                        count += 1;
492
                                }
493
                                dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);
494
                                res = acpiphp_make_resource(base, len);
495
                                if (!res)
496
                                        goto no_memory;
497
 
498
                                res->next = func->p_mem_head;
499
                                func->p_mem_head = res;
500
 
501
                        } else {
502
                                /* regular memory */
503
 
504
                                len &= 0xFFFFFFF0;
505
                                len = ~len + 1;
506
 
507
                                if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
508
                                        /* takes up another dword */
509
                                        dbg("mem 64\n");
510
                                        count += 1;
511
                                }
512
                                dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);
513
                                res = acpiphp_make_resource(base, len);
514
                                if (!res)
515
                                        goto no_memory;
516
 
517
                                res->next = func->mem_head;
518
                                func->mem_head = res;
519
 
520
                        }
521
                }
522
 
523
                pci_write_config_dword(dev, address[count], bar);
524
        }
525
#if 1
526
        acpiphp_dump_func_resource(func);
527
#endif
528
 
529
        return 0;
530
 
531
 no_memory:
532
        err("out of memory\n");
533
        acpiphp_free_resource(&func->io_head);
534
        acpiphp_free_resource(&func->mem_head);
535
        acpiphp_free_resource(&func->p_mem_head);
536
 
537
        return -1;
538
}
539
 
540
 
541
/**
542
 * acpiphp_configure_slot - allocate PCI resources
543
 * @slot: slot to be configured
544
 *
545
 * initializes a PCI functions on a device inserted
546
 * into the slot
547
 *
548
 */
549
int acpiphp_configure_slot (struct acpiphp_slot *slot)
550
{
551
        struct acpiphp_func *func;
552
        struct list_head *l;
553
        u8 hdr;
554
        u32 dvid;
555
        int retval = 0;
556
        int is_multi = 0;
557
 
558
        pci_bus_read_config_byte(slot->bridge->pci_bus,
559
                                        PCI_DEVFN(slot->device, 0),
560
                                        PCI_HEADER_TYPE, &hdr);
561
 
562
        if (hdr & 0x80)
563
                is_multi = 1;
564
 
565
        list_for_each (l, &slot->funcs) {
566
                func = list_entry(l, struct acpiphp_func, sibling);
567
                if (is_multi || func->function == 0) {
568
                        pci_bus_read_config_dword(slot->bridge->pci_bus,
569
                                                    PCI_DEVFN(slot->device,
570
                                                                func->function),
571
                                                    PCI_VENDOR_ID, &dvid);
572
                        if (dvid != 0xffffffff) {
573
                                retval = init_config_space(func);
574
                                if (retval)
575
                                        break;
576
                        }
577
                }
578
        }
579
 
580
        return retval;
581
}
582
 
583
 
584
/* for pci_visit_dev() */
585
static struct pci_visit configure_functions = {
586
        .post_visit_pci_dev =   configure_pci_dev
587
};
588
 
589
static struct pci_visit unconfigure_functions_phase1 = {
590
        .post_visit_pci_dev =   unconfigure_pci_dev_driver
591
};
592
 
593
static struct pci_visit unconfigure_functions_phase2 = {
594
        .post_visit_pci_bus =   unconfigure_pci_bus,
595
        .post_visit_pci_dev =   unconfigure_pci_dev
596
};
597
 
598
 
599
/**
600
 * acpiphp_configure_function - configure PCI function
601
 * @func: function to be configured
602
 *
603
 * initializes a PCI functions on a device inserted
604
 * into the slot
605
 *
606
 */
607
int acpiphp_configure_function (struct acpiphp_func *func)
608
{
609
        int retval = 0;
610
        struct pci_dev_wrapped wrapped_dev;
611
        struct pci_bus_wrapped wrapped_bus;
612
        struct acpiphp_bridge *bridge;
613
 
614
        /* if pci_dev is NULL, ignore it */
615
        if (!func->pci_dev)
616
                goto err_exit;
617
 
618
        bridge = func->slot->bridge;
619
 
620
        memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
621
        memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
622
        wrapped_dev.dev = func->pci_dev;
623
        wrapped_dev.data = func;
624
        wrapped_bus.bus = bridge->pci_bus;
625
        wrapped_bus.data = bridge;
626
 
627
        retval = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
628
        if (retval)
629
                goto err_exit;
630
 
631
 err_exit:
632
        return retval;
633
}
634
 
635
 
636
/**
637
 * acpiphp_unconfigure_function - unconfigure PCI function
638
 * @func: function to be unconfigured
639
 *
640
 */
641
int acpiphp_unconfigure_function (struct acpiphp_func *func)
642
{
643
        struct acpiphp_bridge *bridge;
644
        struct pci_dev_wrapped wrapped_dev;
645
        struct pci_bus_wrapped wrapped_bus;
646
        int retval = 0;
647
 
648
        /* if pci_dev is NULL, ignore it */
649
        if (!func->pci_dev)
650
                goto err_exit;
651
 
652
        memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
653
        memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
654
        wrapped_dev.dev = func->pci_dev;
655
        //wrapped_dev.data = func;
656
        wrapped_bus.bus = func->slot->bridge->pci_bus;
657
        //wrapped_bus.data = func->slot->bridge;
658
 
659
        retval = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus);
660
        if (retval)
661
                goto err_exit;
662
 
663
        retval = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus);
664
        if (retval)
665
                goto err_exit;
666
 
667
        /* free all resources */
668
        bridge = func->slot->bridge;
669
 
670
        spin_lock(&bridge->res_lock);
671
        acpiphp_move_resource(&func->io_head, &bridge->io_head);
672
        acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
673
        acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
674
        acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
675
        spin_unlock(&bridge->res_lock);
676
 
677
 err_exit:
678
        return retval;
679
}
680
 
681
 
682
/*
683
 * acpiphp_configure_irq - configure PCI_INTERRUPT_PIN
684
 *
685
 * for x86 platforms, pcibios_enable_device calls pcibios_enable_irq,
686
 * which allocates irq for pci_dev
687
 *
688
 * for IA64 platforms, we have to program dev->irq from pci IRQ routing
689
 * information derived from ACPI table
690
 *
691
 * TBD:
692
 * separate architecture dependent part
693
 * (preferably, pci_enable_device() cares for allocating irq...)
694
 */
695
static void acpiphp_configure_irq (struct pci_dev *dev)
696
{
697
#if CONFIG_IA64             /* XXX IA64 specific */
698
        extern void iosapic_fixup_pci_interrupt (struct pci_dev *dev);
699
 
700
        iosapic_fixup_pci_interrupt(dev);
701
        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
702
#endif
703
}

powered by: WebSVN 2.1.0

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