PCI helper find_cap
[akaros.git] / kern / arch / x86 / ioapic.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 #include <vfs.h>
11 #include <kfs.h>
12 #include <slab.h>
13 #include <kmalloc.h>
14 #include <kref.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <assert.h>
18 #include <error.h>
19 #include <cpio.h>
20 #include <pmap.h>
21 #include <smp.h>
22 #include <ip.h>
23 #include <arch/io.h>
24 #include <acpi.h>
25 #include <trap.h>
26
27 /* Rbus chains, one for each device bus: each rbus matches a device to an rdt */
28 struct Rbus {
29         struct Rbus *next;
30         int devno;
31         struct Rdt *rdt;
32 };
33
34 /* Each rdt describes an ioapic input pin (intin, from the bus/device) */
35 struct Rdt {
36         struct apic *apic;
37         int intin;
38         uint32_t lo;                            /* matches the lo in the intin, incl Im */
39         uint32_t hi;                            /* matches the hi in the intin, incl routing */
40
41         int ref;                                        /* could map to multiple busses */
42         int enabled;                            /* times enabled */
43 };
44
45 enum {                                                  /* IOAPIC registers */
46         Ioregsel = 0x00,                        /* indirect register address */
47         Iowin = 0x10,   /* indirect register data */
48         Ioipa = 0x08,   /* IRQ Pin Assertion */
49         Ioeoi = 0x10,   /* EOI */
50
51         Ioapicid = 0x00,        /* Identification */
52         Ioapicver = 0x01,       /* Version */
53         Ioapicarb = 0x02,       /* Arbitration */
54         Ioabcfg = 0x03, /* Boot Coniguration */
55         Ioredtbl = 0x10,        /* Redirection Table */
56 };
57
58 static struct Rdt rdtarray[Nrdt];
59 static int nrdtarray;
60 static struct Rbus *rdtbus[Nbus];
61 /* reverse mapping of IDT vector to the RDT/IOAPIC entry triggering vector */
62 static struct Rdt *rdtvecno[IdtMAX + 1];
63
64 static spinlock_t idtnolock;
65 static int idtno = IdtIOAPIC;
66
67 struct apic xioapic[Napic];
68
69 static bool ioapic_exists(void)
70 {
71         /* not foolproof, if we called this before parsing */
72         for (int i = 0; i < Napic; i++)
73                 if (xioapic[i].useable)
74                         return TRUE;
75         return FALSE;
76 }
77
78 static void rtblget(struct apic *apic, int sel, uint32_t * hi, uint32_t * lo)
79 {
80         sel = Ioredtbl + 2 * sel;
81
82         write_mmreg32(apic->addr + Ioregsel, sel + 1);
83         *hi = read_mmreg32(apic->addr + Iowin);
84         write_mmreg32(apic->addr + Ioregsel, sel);
85         *lo = read_mmreg32(apic->addr + Iowin);
86 }
87
88 static void rtblput(struct apic *apic, int sel, uint32_t hi, uint32_t lo)
89 {
90         sel = Ioredtbl + 2 * sel;
91
92         write_mmreg32(apic->addr + Ioregsel, sel + 1);
93         write_mmreg32(apic->addr + Iowin, hi);
94         write_mmreg32(apic->addr + Ioregsel, sel);
95         write_mmreg32(apic->addr + Iowin, lo);
96 }
97
98 struct Rdt *rdtlookup(struct apic *apic, int intin)
99 {
100         int i;
101         struct Rdt *r;
102
103         for (i = 0; i < nrdtarray; i++) {
104                 r = rdtarray + i;
105                 if (apic == r->apic && intin == r->intin)
106                         return r;
107         }
108         return NULL;
109 }
110
111 struct Rdt *rbus_get_rdt(int busno, int devno)
112 {
113         struct Rbus *rbus;
114         for (rbus = rdtbus[busno]; rbus != NULL; rbus = rbus->next) {
115                 if (rbus->devno == devno)
116                         return rbus->rdt;
117         }
118         return 0;
119 }
120
121 /* builds RDT and Rbus entries, given the wiring of bus:dev to ioapicno:intin.
122  * - busno is the source bus
123  * - devno is the device number in the style of a PCI Interrupt Assignment
124  * Entry.  Which is the irq << 2 (check MP spec D.3).
125  * - ioapic is the ioapic the device is connected to
126  * - intin is the INTIN pin on the ioapic
127  * - lo is the lower part of the IOAPIC apic-message, which has the polarity and
128  * trigger mode flags. */
129 void ioapicintrinit(int busno, int ioapicno, int intin, int devno, int lo)
130 {
131         struct Rbus *rbus;
132         struct Rdt *rdt;
133         struct apic *ioapic;
134
135         if (busno >= Nbus || ioapicno >= Napic || nrdtarray >= Nrdt) {
136                 printk("Bad bus %d ioapic %d or nrdtarray %d too big\n", busno,
137                        ioapicno, nrdtarray);
138                 return;
139         }
140         ioapic = &xioapic[ioapicno];
141         if (!ioapic->useable || intin >= ioapic->nrdt) {
142                 printk("IOAPIC unusable (%d) or not enough nrdt (%d) for %d\n",
143                        ioapic->useable, ioapic->nrdt, intin);
144                 return;
145         }
146
147         rdt = rdtlookup(ioapic, intin);
148         if (rdt == NULL) {
149                 rdt = &rdtarray[nrdtarray++];
150                 rdt->apic = ioapic;
151                 rdt->intin = intin;
152                 rdt->lo = lo;
153                 rdt->hi = 0;
154         } else {
155                 /* Polarity/trigger check.  Stored lo also has the vector in 0xff */
156                 if (lo != (rdt->lo & ~0xff)) {
157                         printk("multiple irq botch bus %d %d/%d/%d lo %d vs %d\n",
158                                    busno, ioapicno, intin, devno, lo, rdt->lo);
159                         return;
160                 }
161         }
162         /* TODO: this shit is racy.  (refcnt, linked list addition) */
163         rdt->ref++;
164         rbus = kzmalloc(sizeof *rbus, 0);
165         rbus->rdt = rdt;
166         rbus->devno = devno;
167         rbus->next = rdtbus[busno];
168         rdtbus[busno] = rbus;
169 }
170
171 static int map_polarity[4] = {
172         -1, IPhigh, -1, IPlow
173 };
174
175 static int map_edge_level[4] = {
176         -1, TMedge, -1, TMlevel
177 };
178
179 static int acpi_irq2ioapic(int irq)
180 {
181         int ioapic_idx = 0;
182         struct apic *ioapic;
183         /* with acpi, the ioapics map a global interrupt space.  each covers a
184          * window of the space from [ibase, ibase + nrdt). */
185         for (ioapic = xioapic; ioapic < &xioapic[Napic]; ioapic++, ioapic_idx++) {
186                 /* addr check is just for sanity */
187                 if (!ioapic->useable || !ioapic->addr)
188                         continue;
189                 if ((ioapic->ibase <= irq) && (irq < ioapic->ibase + ioapic->nrdt))
190                         return ioapic_idx;
191         }
192         return -1;
193 }
194
195 /* Build an RDT route, like we would have had from the MP tables had they been
196  * parsed, via ACPI.
197  *
198  * This only really deals with the ISA IRQs and maybe PCI ones that happen to
199  * have an override.  FWIW, on qemu the PCI NIC shows up as an ACPI intovr.
200  *
201  * From Brendan http://f.osdev.org/viewtopic.php?f=1&t=25951:
202  *
203  *              Before parsing the MADT you should begin by assuming that redirection
204  *              entries 0 to 15 are used for ISA IRQs 0 to 15. The MADT's "Interrupt
205  *              Source Override Structures" will tell you when this initial/default
206  *              assumption is wrong. For example, the MADT might tell you that ISA IRQ 9
207  *              is connected to IO APIC 44 and is level triggered; and (in this case)
208  *              it'd be silly to assume that ISA IRQ 9 is also connected to IO APIC
209  *              input 9 just because IO APIC input 9 is not listed.
210  *
211  *              For PCI IRQs, the MADT tells you nothing and you can't assume anything
212  *              at all. Sadly, you have to interpret the ACPI AML to determine how PCI
213  *              IRQs are connected to IO APIC inputs (or find some other work-around;
214  *              like implementing a motherboard driver for each different motherboard,
215  *              or some complex auto-detection scheme, or just configure PCI devices to
216  *              use MSI instead). */
217 static int acpi_make_rdt(int tbdf, int irq, int busno, int devno)
218 {
219         struct Apicst *st;
220         uint32_t lo;
221         int pol, edge_level, ioapic_nr, gsi_irq;
222
223         for (st = apics->st; st != NULL; st = st->next) {
224                 if (st->type == ASintovr) {
225                         if (st->intovr.irq == irq)
226                                 break;
227                 }
228         }
229         if (st) {
230                 pol = map_polarity[st->intovr.flags & AFpmask];
231                 if (pol < 0) {
232                         printk("ACPI override had bad polarity\n");
233                         return -1;
234                 }
235                 edge_level = map_edge_level[(st->intovr.flags & AFlevel) >> 2];
236                 if (edge_level < 0) {
237                         printk("ACPI override had bad edge/level\n");
238                         return -1;
239                 }
240                 lo = pol | edge_level;
241                 gsi_irq = st->intovr.intr;
242         } else {
243                 if (BUSTYPE(tbdf) == BusISA) {
244                         lo = IPhigh | TMedge;
245                         gsi_irq = irq;
246                 } else {
247                         /* Need to query ACPI at some point to handle this */
248                         printk("Non-ISA IRQ %d not found in MADT, aborting\n", irq);
249                         return -1;
250                 }
251         }
252         ioapic_nr = acpi_irq2ioapic(gsi_irq);
253         if (ioapic_nr < 0) {
254                 printk("Could not find an IOAPIC for global irq %d!\n", gsi_irq);
255                 return -1;
256         }
257         ioapicintrinit(busno, ioapic_nr, gsi_irq - xioapic[ioapic_nr].ibase,
258                        devno, lo);
259         return 0;
260 }
261
262 void ioapicinit(int id, int ibase, uintptr_t pa)
263 {
264         struct apic *apic;
265         static int base;
266
267         assert((IOAPIC_PBASE <= pa) && (pa + PGSIZE <= IOAPIC_PBASE + APIC_SIZE));
268         /*
269          * Mark the IOAPIC useable if it has a good ID
270          * and the registers can be mapped.
271          */
272         if (id >= Napic)
273                 return;
274
275         apic = &xioapic[id];
276         apic->addr = IOAPIC_BASE + (pa - IOAPIC_PBASE);
277         if (apic->useable)
278                 return;
279         apic->useable = 1;
280         apic->paddr = pa;
281
282         /*
283          * Initialise the I/O APIC.
284          * The MultiProcessor Specification says it is the
285          * responsibility of the O/S to set the APIC ID.
286          */
287         spin_lock(&apic->lock);
288         write_mmreg32(apic->addr + Ioregsel, Ioapicver);
289         apic->nrdt = ((read_mmreg32(apic->addr + Iowin) >> 16) & 0xff) + 1;
290         /* the ibase is the global system interrupt base, told to us by ACPI.  if
291          * it's -1, we're called from mpparse, and just guess/make up our own
292          * assignments. */
293         if (ibase != -1)
294                 apic->ibase = ibase;
295         else {
296                 apic->ibase = base;
297                 base += apic->nrdt;
298         }
299         write_mmreg32(apic->addr + Ioregsel, Ioapicid);
300         write_mmreg32(apic->addr + Iowin, id << 24);
301         spin_unlock(&apic->lock);
302         printk("IOAPIC initialized at %p\n", apic->addr);
303 }
304
305 char *ioapicdump(char *start, char *end)
306 {
307         int i, n;
308         struct Rbus *rbus;
309         struct Rdt *rdt;
310         struct apic *apic;
311         uint32_t hi, lo;
312
313         if (!2)
314                 return start;
315         for (i = 0; i < Napic; i++) {
316                 apic = &xioapic[i];
317                 if (!apic->useable || apic->addr == 0)
318                         continue;
319                 start = seprintf(start, end, "ioapic %d addr %p nrdt %d ibase %d\n",
320                                                  i, apic->addr, apic->nrdt, apic->ibase);
321                 for (n = 0; n < apic->nrdt; n++) {
322                         spin_lock(&apic->lock);
323                         rtblget(apic, n, &hi, &lo);
324                         spin_unlock(&apic->lock);
325                         start = seprintf(start, end, " rdt %2.2d %p %p\n", n, hi, lo);
326                 }
327         }
328         for (i = 0; i < Nbus; i++) {
329                 if ((rbus = rdtbus[i]) == NULL)
330                         continue;
331                 start = seprintf(start, end, "iointr bus %d:\n", i);
332                 for (; rbus != NULL; rbus = rbus->next) {
333                         rdt = rbus->rdt;
334                         start = seprintf(start, end,
335                                                          " apic %ld devno %p(%d %d) intin %d hi %p lo %p\n",
336                                                          rdt->apic - xioapic, rbus->devno, rbus->devno >> 2,
337                                                          rbus->devno & 0x03, rdt->intin, rdt->hi, rdt->lo);
338                 }
339         }
340         return start;
341 }
342
343 /* Zeros and masks every redirect entry in every IOAPIC */
344 void ioapiconline(void)
345 {
346         int i;
347         struct apic *apic;
348
349         for (apic = xioapic; apic < &xioapic[Napic]; apic++) {
350                 if (!apic->useable || !apic->addr)
351                         continue;
352                 for (i = 0; i < apic->nrdt; i++) {
353                         spin_lock(&apic->lock);
354                         rtblput(apic, i, 0, Im);
355                         spin_unlock(&apic->lock);
356                 }
357         }
358 }
359
360 int nextvec(void)
361 {
362         unsigned int vecno;
363
364         /* TODO: half-way decent integer service (vmem) */
365         spin_lock(&idtnolock);
366         vecno = idtno;
367         idtno = (idtno + 1) % IdtMAX;
368         if (idtno < IdtIOAPIC)
369                 idtno += IdtIOAPIC;
370         spin_unlock(&idtnolock);
371
372         return vecno;
373 }
374
375 static void msi_mask_irq(struct irq_handler *irq_h, int apic_vector)
376 {
377         pci_msi_mask(irq_h->dev_private);
378 }
379
380 static void msi_unmask_irq(struct irq_handler *irq_h, int apic_vector)
381 {
382         pci_msi_unmask(irq_h->dev_private);
383 }
384
385 static void msi_route_irq(struct irq_handler *irq_h, int apic_vector, int dest)
386 {
387         pci_msi_route(irq_h->dev_private, dest);
388 }
389
390 static void msix_mask_irq(struct irq_handler *irq_h, int apic_vector)
391 {
392         pci_msix_mask_vector(irq_h->dev_private);
393 }
394
395 static void msix_unmask_irq(struct irq_handler *irq_h, int apic_vector)
396 {
397         pci_msix_unmask_vector(irq_h->dev_private);
398 }
399
400 static void msix_route_irq(struct irq_handler *irq_h, int apic_vector, int dest)
401 {
402         pci_msix_route_vector(irq_h->dev_private, dest);
403 }
404
405 static int msi_irq_enable(struct irq_handler *irq_h, struct pci_device *p)
406 {
407         unsigned int vno, lo, hi = 0;
408         uint64_t msivec;
409         struct msix_irq_vector *linkage;
410
411         vno = nextvec();
412
413         /* routing the IRQ to core 0 (hi = 0) in physical mode (Pm) */
414         lo = IPlow | TMedge | Pm | vno;
415
416         msivec = (uint64_t) hi << 32 | lo;
417         irq_h->dev_private = pci_msix_enable(p, msivec);
418         if (!irq_h->dev_private) {
419                 if (pci_msi_enable(p, msivec) == -1) {
420                         /* TODO: should free vno here */
421                         return -1;
422                 }
423                 irq_h->dev_private = p;
424                 irq_h->check_spurious = lapic_check_spurious;
425                 irq_h->eoi = lapic_send_eoi;
426                 irq_h->mask = msi_mask_irq;
427                 irq_h->unmask = msi_unmask_irq;
428                 irq_h->route_irq = msi_route_irq;
429                 irq_h->type = "msi";
430                 printk("MSI irq: (%x,%x,%x): enabling %p %s vno %d\n",
431                            p->bus, p->dev, p->func, msivec, irq_h->name, vno);
432                 return vno;
433         }
434         irq_h->check_spurious = lapic_check_spurious;
435         irq_h->eoi = lapic_send_eoi;
436         irq_h->mask = msix_mask_irq;
437         irq_h->unmask = msix_unmask_irq;
438         irq_h->route_irq = msix_route_irq;
439         irq_h->type = "msi-x";
440         printk("MSI-X irq: (%x,%x,%x): enabling %p %s vno %d\n",
441                p->bus, p->dev, p->func, msivec, irq_h->name, vno);
442         return vno;
443 }
444
445 static struct Rdt *ioapic_vector2rdt(int apic_vector)
446 {
447         struct Rdt *rdt;
448         if (apic_vector < IdtIOAPIC || apic_vector > MaxIdtIOAPIC) {
449                 printk("ioapic vector %d out of range", apic_vector);
450                 return 0;
451         }
452         /* Fortunately rdtvecno[vecno] is static once assigned. o/w, we'll need some
453          * global sync for the callers, both for lookup and keeping rdt valid. */
454         rdt = rdtvecno[apic_vector];
455         if (!rdt) {
456                 printk("vector %d has no RDT! (did you enable it?)", apic_vector);
457                 return 0;
458         }
459         return rdt;
460 }
461
462 /* Routes the IRQ to the hw_coreid.  Will take effect immediately.  Route
463  * masking from rdt->lo will take effect.  The early return cases are probably
464  * bugs in IOAPIC irq_h setup. */
465 static void ioapic_route_irq(struct irq_handler *unused, int apic_vector,
466                              int hw_coreid)
467 {
468         struct Rdt *rdt = ioapic_vector2rdt(apic_vector);
469         if (!rdt) {
470                 printk("Missing IOAPIC route for vector!\n", apic_vector);
471                 return;
472         }
473         spin_lock(&rdt->apic->lock);
474         /* this bit gets set in apicinit, only if we found it via MP or ACPI */
475         if (!xlapic[hw_coreid].useable) {
476                 printk("Can't route to uninitialized LAPIC %d!\n", hw_coreid);
477                 spin_unlock(&rdt->apic->lock);
478                 return;
479         }
480         rdt->hi = hw_coreid << 24;
481         rdt->lo |= Pm | MTf;
482         rtblput(rdt->apic, rdt->intin, rdt->hi, rdt->lo);
483         spin_unlock(&rdt->apic->lock);
484 }
485
486 static void ioapic_mask_irq(struct irq_handler *unused, int apic_vector)
487 {
488         /* could store the rdt in the irq_h */
489         struct Rdt *rdt = ioapic_vector2rdt(apic_vector);
490         if (!rdt)
491                 return;
492         spin_lock(&rdt->apic->lock);
493         /* don't allow shared vectors to be masked.  whatever. */
494         if (rdt->enabled > 1) {
495                 spin_unlock(&rdt->apic->lock);
496                 return;
497         }
498         rdt->lo |= Im;
499         rtblput(rdt->apic, rdt->intin, rdt->hi, rdt->lo);
500         spin_unlock(&rdt->apic->lock);
501 }
502
503 static void ioapic_unmask_irq(struct irq_handler *unused, int apic_vector)
504 {
505         struct Rdt *rdt = ioapic_vector2rdt(apic_vector);
506         if (!rdt)
507                 return;
508         spin_lock(&rdt->apic->lock);
509         rdt->lo &= ~Im;
510         rtblput(rdt->apic, rdt->intin, rdt->hi, rdt->lo);
511         spin_unlock(&rdt->apic->lock);
512 }
513
514 /* Attempts to init a bus interrupt, initializes irq_h, and returns the IDT
515  * vector to use (-1 on error).  If routable, the IRQ will route to core 0.  The
516  * IRQ will be masked, if possible.  Call irq_h->unmask() when you're ready.
517  *
518  * This will determine the type of bus the device is on (LAPIC, IOAPIC, PIC,
519  * etc), and set the appropriate fields in isr_h.  If applicable, it'll also
520  * allocate an IDT vector, such as for an IOAPIC, and route the IOAPIC entries
521  * appropriately.
522  *
523  * Callers init irq_h->dev_irq and ->tbdf.  tbdf encodes the bus type and the
524  * classic PCI bus:dev:func.  dev_irq may be ignored based on the bus type (e.g.
525  * PCI, esp MSI).
526  *
527  * In plan9, this was ioapicintrenable(), which also unmasked.  We don't have a
528  * deinit/disable method that would tear down the route yet.  All the plan9 one
529  * did was dec enabled and mask the entry. */
530 int bus_irq_setup(struct irq_handler *irq_h)
531 {
532         struct Rbus *rbus;
533         struct Rdt *rdt;
534         int busno, devno, vecno;
535         struct pci_device *pcidev;
536
537         if (!ioapic_exists()) {
538                 switch (BUSTYPE(irq_h->tbdf)) {
539                         case BusLAPIC:
540                         case BusIPI:
541                                 break;
542                         default:
543                                 irq_h->check_spurious = pic_check_spurious;
544                                 irq_h->eoi = pic_send_eoi;
545                                 irq_h->mask = pic_mask_irq;
546                                 irq_h->unmask = pic_unmask_irq;
547                                 irq_h->route_irq = 0;
548                                 irq_h->type = "pic";
549                                 /* PIC devices have vector = irq + 32 */
550                                 return irq_h->dev_irq + IdtPIC;
551                 }
552         }
553         switch (BUSTYPE(irq_h->tbdf)) {
554                 case BusLAPIC:
555                         /* nxm used to set the initial 'isr' method (i think equiv to our
556                          * check_spurious) to apiceoi for non-spurious lapic vectors.  in
557                          * effect, i think they were sending the EOI early, and their eoi
558                          * method was 0.  we're not doing that (unless we have to). */
559                         irq_h->check_spurious = lapic_check_spurious;
560                         irq_h->eoi = lapic_send_eoi;
561                         irq_h->mask = lapic_mask_irq;
562                         irq_h->unmask = lapic_unmask_irq;
563                         irq_h->route_irq = 0;
564                         irq_h->type = "lapic";
565                         /* For the LAPIC, irq == vector */
566                         return irq_h->dev_irq;
567                 case BusIPI:
568                         /* similar to LAPIC, but we don't actually have LVT entries */
569                         irq_h->check_spurious = lapic_check_spurious;
570                         irq_h->eoi = lapic_send_eoi;
571                         irq_h->mask = 0;
572                         irq_h->unmask = 0;
573                         irq_h->route_irq = 0;
574                         irq_h->type = "IPI";
575                         return irq_h->dev_irq;
576                 case BusISA:
577                         if (mpisabusno == -1)
578                                 panic("No ISA bus allocated");
579                         busno = mpisabusno;
580                         /* need to track the irq in devno in PCI interrupt assignment entry
581                          * format (see mp.c or MP spec D.3). */
582                         devno = irq_h->dev_irq << 2;
583                         break;
584                 case BusPCI:
585                         pcidev = pci_match_tbdf(irq_h->tbdf);
586                         if (!pcidev) {
587                                 printk("No PCI dev for tbdf %p!", irq_h->tbdf);
588                                 return -1;
589                         }
590                         if ((vecno = msi_irq_enable(irq_h, pcidev)) != -1)
591                                 return vecno;
592                         busno = BUSBNO(irq_h->tbdf);
593                         assert(busno == pcidev->bus);
594                         devno = pcidev_read8(pcidev, PciINTP);
595
596                         /* this might not be a big deal - some PCI devices have no INTP.  if
597                          * so, change our devno - 1 below. */
598                         if (devno == 0)
599                                 panic("no INTP for tbdf %p", irq_h->tbdf);
600                         /* remember, devno is the device shifted with irq pin in bits 0-1.
601                          * we subtract 1, since the PCI intp maps 1 -> INTA, 2 -> INTB, etc,
602                          * and the MP spec uses 0 -> INTA, 1 -> INTB, etc. */
603                         devno = BUSDNO(irq_h->tbdf) << 2 | (devno - 1);
604                         break;
605                 default:
606                         panic("Unknown bus type, TBDF %p", irq_h->tbdf);
607         }
608         /* busno and devno are set, regardless of the bustype, enough to find rdt.
609          * these may differ from the values in tbdf. */
610         rdt = rbus_get_rdt(busno, devno);
611         if (!rdt) {
612                 /* second chance.  if we didn't find the item the first time, then (if
613                  * it exists at all), it wasn't in the MP tables (or we had no tables).
614                  * So maybe we can figure it out via ACPI. */
615                 acpi_make_rdt(irq_h->tbdf, irq_h->dev_irq, busno, devno);
616                 rdt = rbus_get_rdt(busno, devno);
617         }
618         if (!rdt) {
619                 printk("Unable to build IOAPIC route for irq %d\n", irq_h->dev_irq);
620                 return -1;
621         }
622         /*
623          * what to do about devices that intrenable/intrdisable frequently?
624          * 1) there is no ioapicdisable yet;
625          * 2) it would be good to reuse freed vectors.
626          * Oh bugger.
627          * brho: plus the diff btw mask/unmask and enable/disable is unclear
628          */
629         /*
630          * This is a low-frequency event so just lock
631          * the whole IOAPIC to initialise the RDT entry
632          * rather than putting a Lock in each entry.
633          */
634         spin_lock(&rdt->apic->lock);
635         /* if a destination has already been picked, we store it in the lo.  this
636          * stays around regardless of enabled/disabled, since we don't reap vectors
637          * yet.  nor do we really mess with enabled... */
638         if ((rdt->lo & 0xff) == 0) {
639                 vecno = nextvec();
640                 rdt->lo |= vecno;
641                 rdtvecno[vecno] = rdt;
642         } else {
643                 printd("%p: mutiple irq bus %d dev %d\n", irq_h->tbdf, busno, devno);
644         }
645         rdt->enabled++;
646         rdt->hi = 0;                    /* route to 0 by default */
647         rdt->lo |= Pm | MTf;
648         rtblput(rdt->apic, rdt->intin, rdt->hi, rdt->lo);
649         vecno = rdt->lo & 0xff;
650         spin_unlock(&rdt->apic->lock);
651
652         irq_h->check_spurious = lapic_check_spurious;
653         irq_h->eoi = lapic_send_eoi;
654         irq_h->mask = ioapic_mask_irq;
655         irq_h->unmask = ioapic_unmask_irq;
656         irq_h->route_irq = ioapic_route_irq;
657         irq_h->type = "ioapic";
658
659         return vecno;
660 }