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