Subversion Repositories Kolibri OS

Rev

Rev 1633 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1627 serge 1
 
2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
7
8
 
9
#include "acpi_bus.h"
10
11
 
12
13
 
14
{
15
    struct list_head    list;
16
    ACPI_PCI_ID         id;
17
    u8                  pin;
18
    ACPI_HANDLE         link;
19
    u32                 index;      /* GSI, or link _CRS index */
20
};
21
22
 
23
static DEFINE_SPINLOCK(acpi_prt_lock);
24
25
 
26
{
27
    return 'A' + pin - 1;
28
}
29
30
 
31
 
1633 serge 32
                         PCI IRQ Routing Table (PRT) Support
33
   -------------------------------------------------------------------------- */
34
35
 
36
                              int pin)
37
{
38
    struct acpi_prt_entry *entry;
39
    int segment = pci_domain_nr(dev->bus);
40
    int bus = dev->bus->number;
41
    int device = PCI_SLOT(dev->devfn);
42
43
 
44
    list_for_each_entry(entry, &acpi_prt_list, list) {
45
        if ((segment == entry->id.Segment)
46
            && (bus == entry->id.Bus)
47
            && (device == entry->id.Device)
48
            && (pin == entry->pin)) {
49
            spin_unlock(&acpi_prt_lock);
50
            return entry;
51
        }
52
    }
53
    spin_unlock(&acpi_prt_lock);
54
    return NULL;
55
}
56
57
 
1627 serge 58
                  struct acpi_pci_routing_table *prt)
59
{
60
    struct acpi_prt_entry *entry;
61
62
 
63
    if (!entry)
64
        return -ENOMEM;
65
66
 
67
     * Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses
68
     * 1=INTA, 2=INTB.  We use the PCI encoding throughout, so convert
69
     * it here.
70
     */
71
    entry->id.Segment = pci_domain_nr(bus);
72
    entry->id.Bus = bus->number;
73
    entry->id.Device = (prt->Address >> 16) & 0xFFFF;
74
    entry->pin = prt->Pin + 1;
75
76
 
77
78
 
79
80
 
81
     * Type 1: Dynamic
82
     * ---------------
83
     * The 'source' field specifies the PCI interrupt link device used to
84
     * configure the IRQ assigned to this slot|dev|pin.  The 'source_index'
85
     * indicates which resource descriptor in the resource template (of
86
     * the link device) this interrupt is allocated from.
87
     *
88
     * NOTE: Don't query the Link Device for IRQ information at this time
89
     *       because Link Device enumeration may not have occurred yet
90
     *       (e.g. exists somewhere 'below' this _PRT entry in the ACPI
91
     *       namespace).
92
     */
93
    if (prt->Source[0])
94
        AcpiGetHandle(handle, prt->Source, &entry->link);
95
96
 
97
     * Type 2: Static
98
     * --------------
99
     * The 'source' field is NULL, and the 'source_index' field specifies
100
     * the IRQ value, which is hardwired to specific interrupt inputs on
101
     * the interrupt controller.
102
     */
103
104
 
105
                  entry->id.Segment, entry->id.Bus,
106
                  entry->id.Device, pin_name(entry->pin),
107
                  prt->Source, entry->index);
108
109
 
110
    list_add_tail(&entry->list, &acpi_prt_list);
111
    spin_unlock(&acpi_prt_lock);
112
113
 
114
}
115
116
 
117
 
118
 
119
{
120
    ACPI_STATUS status;
121
    struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
122
    struct acpi_pci_routing_table *entry;
123
124
 
125
    status = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buffer);
126
    if (ACPI_FAILURE(status))
127
        return -ENODEV;
128
129
 
130
           (char *) buffer.Pointer);
131
132
 
133
134
 
135
    buffer.Pointer = NULL;
136
137
 
138
    if (ACPI_FAILURE(status))
139
    {
140
        dbgprintf("AcpiGetIrqRoutingTable failed "
141
                  "evaluating _PRT [%s]\n",AcpiFormatException(status));
142
        kfree(buffer.Pointer);
143
        return -ENODEV;
144
    }
145
146
 
147
    while (entry && (entry->Length > 0)) {
148
        acpi_pci_irq_add_entry(handle, bus, entry);
149
        entry = (struct acpi_pci_routing_table *)
150
            ((unsigned long)entry + entry->Length);
151
    }
152
153
 
154
    return 0;
155
}
156
157
 
1633 serge 158
{
159
    struct acpi_prt_entry *entry;
160
    struct pci_dev *bridge;
161
    u8 bridge_pin, orig_pin = pin;
162
163
 
164
    if (entry) {
165
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
166
                  pci_name(dev), pin_name(pin)));
167
        return entry;
168
    }
169
170
 
171
     * Attempt to derive an IRQ for this device from a parent bridge's
172
     * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
173
     */
174
    bridge = dev->bus->self;
175
    while (bridge)
176
    {
177
        pin = pci_swizzle_interrupt_pin(dev, pin);
178
179
 
180
            /* PC card has the same IRQ as its cardbridge */
181
            bridge_pin = bridge->pin;
182
            if (!bridge_pin) {
183
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
184
                          "No interrupt pin configured for device %s\n",
185
                          pci_name(bridge)));
186
                return NULL;
187
            }
188
            pin = bridge_pin;
189
        }
190
191
 
192
        if (entry) {
193
            ACPI_DEBUG_PRINT((ACPI_DB_INFO,
194
                     "Derived GSI for %s INT %c from %s\n",
195
                     pci_name(dev), pin_name(orig_pin),
196
                     pci_name(bridge)));
197
            return entry;
198
        }
199
200
 
201
        bridge = dev->bus->self;
202
    }
203
204
 
205
         pin_name(orig_pin));
206
    return NULL;
207
}
208
209
 
210
 
211
{
212
    struct acpi_prt_entry *entry;
213
    int gsi = -1;
214
    u8 pin;
215
216
 
217
    int polarity = ACPI_ACTIVE_LOW;
218
219
 
220
    char link_desc[16];
221
    int rc;
222
223
 
224
1867 serge 225
 
226
    {
227
        dbgprintf("No interrupt pin configured for device %s\n",
228
                  pci_name(dev));
229
        return 0;
1633 serge 230
    }
231
232
 
233
    if (!entry) {
234
        /*
235
         * IDE legacy mode controller IRQs are magic. Why do compat
236
         * extensions always make such a nasty mess.
237
         */
238
        if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE &&
239
                (dev->class & 0x05) == 0)
240
            return 0;
241
    }
242
243
 
244
    {
245
        if (entry->link)
246
        {
247
            gsi = acpi_pci_link_allocate_irq(entry->link,
248
                             entry->index,
249
                             &triggering, &polarity,
250
                             &link);
251
//            dbgprintf("link not implemen\n");
252
        }
253
        else
254
            gsi = entry->index;
255
    } else
256
        gsi = -1;
257
258
 
259
260
 
261
     * No IRQ known to the ACPI subsystem - maybe the BIOS /
262
     * driver reported one, then use it. Exit in any case.
263
     */
264
    if (gsi < 0) {
265
        u32 dev_gsi;
266
        dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
267
        /* Interrupt Line values above 0xF are forbidden */
268
        if (dev->irq > 0 && (dev->irq <= 0xF) &&
269
            (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
270
            printk(" - using ISA IRQ %d\n", dev->irq);
271
            acpi_register_gsi(&dev->dev, dev_gsi,
272
                      ACPI_LEVEL_SENSITIVE,
273
                      ACPI_ACTIVE_LOW);
274
            return 0;
275
        } else {
276
            printk("\n");
277
            return 0;
278
        }
279
    }
280
281
 
282
    if (rc < 0) {
283
        dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
284
             pin_name(pin));
285
        return rc;
286
    }
287
    dev->irq = rc;
288
289
 
290
        snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
291
    else
292
        link_desc[0] = '\0';
293
294
 
295
         pin_name(pin), link_desc, gsi,
296
         (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
297
         (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
298
#endif
299
    return gsi;
300
}
301
302
 
303
 
304
305
 
306
 * If a link is initialized, we never change its active and initialized
307
 * later even the link is disable. Instead, we just repick the active irq
308
 */
309
struct acpi_pci_link_irq {
310
    u8 active;      /* Current IRQ */
311
    u8 triggering;      /* All IRQs */
312
    u8 polarity;        /* All IRQs */
313
    u8 resource_type;
314
    u8 possible_count;
315
    u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
316
    u8 initialized:1;
317
    u8 reserved:7;
318
};
319
320
 
321
    struct list_head        list;
322
    struct acpi_device      *device;
323
    struct acpi_pci_link_irq    irq;
324
    int             refcnt;
325
};
326
327
 
328
static DEFINE_MUTEX(acpi_link_lock);
329
330
 
331
 
332
{
333
    int result;
334
    ACPI_STATUS status;
335
    struct {
336
        struct acpi_resource res;
337
        struct acpi_resource end;
338
    } *resource;
339
340
 
341
342
 
343
        return -EINVAL;
344
345
 
346
    if (!resource)
347
        return -ENOMEM;
348
349
 
350
    buffer.Pointer = resource;
351
352
 
353
    case ACPI_RESOURCE_TYPE_IRQ:
354
        resource->res.Type = ACPI_RESOURCE_TYPE_IRQ;
355
        resource->res.Length = sizeof(struct acpi_resource);
356
        resource->res.Data.Irq.Triggering = link->irq.triggering;
357
        resource->res.Data.Irq.Polarity =
358
            link->irq.polarity;
359
        if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
360
            resource->res.Data.Irq.Sharable =
361
                ACPI_EXCLUSIVE;
362
        else
363
            resource->res.Data.Irq.Sharable = ACPI_SHARED;
364
        resource->res.Data.Irq.InterruptCount = 1;
365
        resource->res.Data.Irq.Interrupts[0] = irq;
366
        break;
367
368
 
369
        resource->res.Type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
370
        resource->res.Length = sizeof(struct acpi_resource);
371
        resource->res.Data.ExtendedIrq.ProducerConsumer =
372
            ACPI_CONSUMER;
373
        resource->res.Data.ExtendedIrq.Triggering =
374
            link->irq.triggering;
375
        resource->res.Data.ExtendedIrq.Polarity =
376
            link->irq.polarity;
377
        if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
378
            resource->res.Data.Irq.Sharable =
379
                ACPI_EXCLUSIVE;
380
        else
381
            resource->res.Data.Irq.Sharable = ACPI_SHARED;
382
        resource->res.Data.ExtendedIrq.InterruptCount = 1;
383
        resource->res.Data.ExtendedIrq.Interrupts[0] = irq;
384
        /* ignore resource_source, it's optional */
385
        break;
386
    default:
387
        printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
388
        result = -EINVAL;
389
        goto end;
390
391
 
392
    resource->end.Type = ACPI_RESOURCE_TYPE_END_TAG;
393
394
 
395
    /* Attempt to set the resource */
396
    status = acpi_set_current_resources(link->device->handle, &buffer);
397
398
 
399
    if (ACPI_FAILURE(status)) {
400
        dbgprintf("%s failure Evaluating _SRS", __FUNCTION__);
401
        result = -ENODEV;
402
        goto end;
403
    }
404
405
 
406
    result = acpi_bus_get_status(link->device);
407
    if (result) {
408
        printk(KERN_ERR PREFIX "Unable to read status\n");
409
        goto end;
410
    }
411
    if (!link->device->status.enabled) {
412
        printk(KERN_WARNING PREFIX
413
                  "%s [%s] disabled and referenced, BIOS bug\n",
414
                  acpi_device_name(link->device),
415
                  acpi_device_bid(link->device));
416
    }
417
418
 
419
    result = acpi_pci_link_get_current(link);
420
    if (result) {
421
        goto end;
422
    }
423
424
 
425
     * Is current setting not what we set?
426
     * set link->irq.active
427
     */
428
    if (link->irq.active != irq) {
429
        /*
430
         * policy: when _CRS doesn't return what we just _SRS
431
         * assume _SRS worked and override _CRS value.
432
         */
433
        printk(KERN_WARNING PREFIX
434
                  "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
435
                  acpi_device_name(link->device),
436
                  acpi_device_bid(link->device), link->irq.active, irq);
437
        link->irq.active = irq;
438
    }
439
#endif
440
441
 
442
443
 
444
    kfree(resource);
445
    return result;
446
}
447
448
 
449
 
450
 
451
#define ACPI_MAX_ISA_IRQ    16
452
453
 
454
#define PIRQ_PENALTY_PCI_POSSIBLE   (16*16)
455
#define PIRQ_PENALTY_PCI_USING      (16*16*16)
456
#define PIRQ_PENALTY_ISA_TYPICAL    (16*16*16*16)
457
#define PIRQ_PENALTY_ISA_USED       (16*16*16*16*16)
458
#define PIRQ_PENALTY_ISA_ALWAYS     (16*16*16*16*16*16)
459
460
 
461
    PIRQ_PENALTY_ISA_ALWAYS,    /* IRQ0 timer */
462
    PIRQ_PENALTY_ISA_ALWAYS,    /* IRQ1 keyboard */
463
    PIRQ_PENALTY_ISA_ALWAYS,    /* IRQ2 cascade */
464
    PIRQ_PENALTY_ISA_TYPICAL,   /* IRQ3 serial */
465
    PIRQ_PENALTY_ISA_TYPICAL,   /* IRQ4 serial */
466
    PIRQ_PENALTY_ISA_TYPICAL,   /* IRQ5 sometimes SoundBlaster */
467
    PIRQ_PENALTY_ISA_TYPICAL,   /* IRQ6 */
468
    PIRQ_PENALTY_ISA_TYPICAL,   /* IRQ7 parallel, spurious */
469
    PIRQ_PENALTY_ISA_TYPICAL,   /* IRQ8 rtc, sometimes */
470
    PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9  PCI, often acpi */
471
    PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */
472
    PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */
473
    PIRQ_PENALTY_ISA_USED,      /* IRQ12 mouse */
474
    PIRQ_PENALTY_ISA_USED,      /* IRQ13 fpe, sometimes */
475
    PIRQ_PENALTY_ISA_USED,      /* IRQ14 ide0 */
476
    PIRQ_PENALTY_ISA_USED,      /* IRQ15 ide1 */
477
    /* >IRQ15 */
478
};
479
480
 
481
 
482
 
483
 
484
485
 
486
{
487
    int irq;
488
    int i;
489
490
 
491
        if (link->refcnt == 0)
492
            /* This means the link is disabled but initialized */
493
            acpi_pci_link_set(link, link->irq.active);
494
        return 0;
495
    }
496
497
 
498
     * search for active IRQ in list of possible IRQs.
499
     */
500
    for (i = 0; i < link->irq.possible_count; ++i) {
501
        if (link->irq.active == link->irq.possible[i])
502
            break;
503
    }
504
    /*
505
     * forget active IRQ that is not in possible list
506
     */
507
    if (i == link->irq.possible_count) {
508
        dbgprintf(KERN_WARNING PREFIX "_CRS %d not found"
1867 serge 509
                      " in _PRS\n", link->irq.active);
1633 serge 510
        link->irq.active = 0;
511
    }
512
513
 
514
     * if active found, use it; else pick entry from end of possible list.
515
     */
516
    if (link->irq.active)
517
        irq = link->irq.active;
518
    else
519
        irq = link->irq.possible[link->irq.possible_count - 1];
520
521
 
522
        /*
523
         * Select the best IRQ.  This is done in reverse to promote
524
         * the use of IRQs 9, 10, 11, and >15.
525
         */
526
        for (i = (link->irq.possible_count - 1); i >= 0; i--) {
527
            if (acpi_irq_penalty[irq] >
528
                acpi_irq_penalty[link->irq.possible[i]])
529
                irq = link->irq.possible[i];
530
        }
531
    }
532
533
 
534
    if (acpi_pci_link_set(link, irq)) {
535
        printk(KERN_ERR PREFIX "Unable to set IRQ for %s [%s]. "
536
                "Try pci=noacpi or acpi=off\n",
537
                acpi_device_name(link->device),
538
                acpi_device_bid(link->device));
539
        return -ENODEV;
540
    } else {
541
        acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
542
        printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
543
               acpi_device_name(link->device),
544
               acpi_device_bid(link->device), link->irq.active);
545
    }
546
547
 
548
    return 0;
549
}
550
551
 
552
 
553
 * acpi_pci_link_allocate_irq
554
 * success: return IRQ >= 0
555
 * failure: return -1
556
 */
557
int acpi_pci_link_allocate_irq(ACPI_HANDLE handle, int index,
558
                               int *triggering, int *polarity, char **name)
559
{
560
    int result;
561
    struct acpi_device *device;
562
    struct acpi_pci_link *link;
563
564
 
565
    if (result) {
566
        printk(KERN_ERR PREFIX "Invalid link device\n");
567
        return -1;
568
    }
569
570
 
571
    if (!link) {
572
        printk(KERN_ERR PREFIX "Invalid link context\n");
573
        return -1;
574
    }
575
576
 
577
    if (index) {
578
        printk(KERN_ERR PREFIX "Invalid index %d\n", index);
579
        return -1;
580
    }
581
582
 
583
    if (acpi_pci_link_allocate(link)) {
584
        mutex_unlock(&acpi_link_lock);
585
        return -1;
586
    }
587
588
 
589
        mutex_unlock(&acpi_link_lock);
590
        printk(KERN_ERR PREFIX "Link active IRQ is 0!\n");
591
        return -1;
592
    }
593
    link->refcnt++;
594
    mutex_unlock(&acpi_link_lock);
595
596
 
597
        *triggering = link->irq.triggering;
598
    if (polarity)
599
        *polarity = link->irq.polarity;
600
    if (name)
601
        *name = acpi_device_bid(link->device);
602
    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
603
              "Link %s is referenced\n",
604
              acpi_device_bid(link->device)));
605
    return (link->irq.active);
606
}
607