19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier
79ef1f84bSDavid du Colombier #include "apic.h"
89ef1f84bSDavid du Colombier #include "io.h"
99ef1f84bSDavid du Colombier
10bbf74bb6SDavid du Colombier typedef struct Rbus Rbus;
119ef1f84bSDavid du Colombier typedef struct Rdt Rdt;
12bbf74bb6SDavid du Colombier
13bbf74bb6SDavid du Colombier struct Rbus {
14bbf74bb6SDavid du Colombier Rbus *next;
15ffa640cdSDavid du Colombier int bustype;
169ef1f84bSDavid du Colombier int devno;
17bbf74bb6SDavid du Colombier Rdt *rdt;
18bbf74bb6SDavid du Colombier };
19bbf74bb6SDavid du Colombier
20bbf74bb6SDavid du Colombier struct Rdt {
21bbf74bb6SDavid du Colombier Apic* apic;
229ef1f84bSDavid du Colombier int intin;
239ef1f84bSDavid du Colombier u32int lo;
249ef1f84bSDavid du Colombier
25bbf74bb6SDavid du Colombier int ref; /* could map to multiple busses */
26bbf74bb6SDavid du Colombier int enabled; /* times enabled */
27bbf74bb6SDavid du Colombier };
289ef1f84bSDavid du Colombier
299ef1f84bSDavid du Colombier enum { /* IOAPIC registers */
309ef1f84bSDavid du Colombier Ioregsel = 0x00, /* indirect register address */
319ef1f84bSDavid du Colombier Iowin = 0x04, /* indirect register data */
329ef1f84bSDavid du Colombier Ioipa = 0x08, /* IRQ Pin Assertion */
339ef1f84bSDavid du Colombier Ioeoi = 0x10, /* EOI */
349ef1f84bSDavid du Colombier
359ef1f84bSDavid du Colombier Ioapicid = 0x00, /* Identification */
369ef1f84bSDavid du Colombier Ioapicver = 0x01, /* Version */
379ef1f84bSDavid du Colombier Ioapicarb = 0x02, /* Arbitration */
389ef1f84bSDavid du Colombier Ioabcfg = 0x03, /* Boot Coniguration */
399ef1f84bSDavid du Colombier Ioredtbl = 0x10, /* Redirection Table */
409ef1f84bSDavid du Colombier };
419ef1f84bSDavid du Colombier
429ef1f84bSDavid du Colombier static Rdt rdtarray[Nrdt];
439ef1f84bSDavid du Colombier static int nrdtarray;
449ef1f84bSDavid du Colombier static int gsib;
45bbf74bb6SDavid du Colombier static Rbus* rdtbus[Nbus];
469ef1f84bSDavid du Colombier static Rdt* rdtvecno[IdtMAX+1];
479ef1f84bSDavid du Colombier
489ef1f84bSDavid du Colombier static Lock idtnolock;
499ef1f84bSDavid du Colombier static int idtno = IdtIOAPIC;
509ef1f84bSDavid du Colombier
519ef1f84bSDavid du Colombier static void
rtblget(Apic * apic,int sel,u32int * hi,u32int * lo)529ef1f84bSDavid du Colombier rtblget(Apic* apic, int sel, u32int* hi, u32int* lo)
539ef1f84bSDavid du Colombier {
549ef1f84bSDavid du Colombier u32int r;
559ef1f84bSDavid du Colombier
569ef1f84bSDavid du Colombier sel = Ioredtbl + 2*sel;
579ef1f84bSDavid du Colombier
589ef1f84bSDavid du Colombier *(apic->addr+Ioregsel) = sel+1;
599ef1f84bSDavid du Colombier r = *(apic->addr+Iowin);
609ef1f84bSDavid du Colombier if(hi)
619ef1f84bSDavid du Colombier *hi = r;
629ef1f84bSDavid du Colombier *(apic->addr+Ioregsel) = sel;
639ef1f84bSDavid du Colombier r = *(apic->addr+Iowin);
649ef1f84bSDavid du Colombier if(lo)
659ef1f84bSDavid du Colombier *lo = r;
669ef1f84bSDavid du Colombier }
679ef1f84bSDavid du Colombier
689ef1f84bSDavid du Colombier static void
rtblput(Apic * apic,int sel,u32int hi,u32int lo)699ef1f84bSDavid du Colombier rtblput(Apic* apic, int sel, u32int hi, u32int lo)
709ef1f84bSDavid du Colombier {
719ef1f84bSDavid du Colombier sel = Ioredtbl + 2*sel;
729ef1f84bSDavid du Colombier
739ef1f84bSDavid du Colombier *(apic->addr+Ioregsel) = sel+1;
749ef1f84bSDavid du Colombier *(apic->addr+Iowin) = hi;
759ef1f84bSDavid du Colombier *(apic->addr+Ioregsel) = sel;
769ef1f84bSDavid du Colombier *(apic->addr+Iowin) = lo;
779ef1f84bSDavid du Colombier }
789ef1f84bSDavid du Colombier
79bbf74bb6SDavid du Colombier Rdt*
rdtlookup(Apic * apic,int intin)80bbf74bb6SDavid du Colombier rdtlookup(Apic *apic, int intin)
81bbf74bb6SDavid du Colombier {
82bbf74bb6SDavid du Colombier int i;
83bbf74bb6SDavid du Colombier Rdt *r;
84bbf74bb6SDavid du Colombier
85bbf74bb6SDavid du Colombier for(i = 0; i < nrdtarray; i++){
86bbf74bb6SDavid du Colombier r = rdtarray + i;
87bbf74bb6SDavid du Colombier if(apic == r->apic && intin == r->intin)
88bbf74bb6SDavid du Colombier return r;
89bbf74bb6SDavid du Colombier }
90bbf74bb6SDavid du Colombier return nil;
91bbf74bb6SDavid du Colombier }
92bbf74bb6SDavid du Colombier
939ef1f84bSDavid du Colombier void
ioapicintrinit(int bustype,int busno,int apicno,int intin,int devno,u32int lo)94ffa640cdSDavid du Colombier ioapicintrinit(int bustype, int busno, int apicno, int intin, int devno, u32int lo)
959ef1f84bSDavid du Colombier {
96bbf74bb6SDavid du Colombier Rbus *rbus;
979ef1f84bSDavid du Colombier Rdt *rdt;
989ef1f84bSDavid du Colombier Apic *apic;
999ef1f84bSDavid du Colombier
1009ef1f84bSDavid du Colombier if(busno >= Nbus || apicno >= Napic || nrdtarray >= Nrdt)
1019ef1f84bSDavid du Colombier return;
1029ef1f84bSDavid du Colombier apic = &ioapic[apicno];
1039ef1f84bSDavid du Colombier if(!apic->useable || intin >= apic->nrdt)
1049ef1f84bSDavid du Colombier return;
1059ef1f84bSDavid du Colombier
106bbf74bb6SDavid du Colombier rdt = rdtlookup(apic, intin);
107bbf74bb6SDavid du Colombier if(rdt == nil){
108bbf74bb6SDavid du Colombier if(nrdtarray == nelem(rdtarray)){
109bbf74bb6SDavid du Colombier print("ioapic: intrinit: rdtarray too small\n");
110bbf74bb6SDavid du Colombier return;
111bbf74bb6SDavid du Colombier }
1129ef1f84bSDavid du Colombier rdt = &rdtarray[nrdtarray++];
1139ef1f84bSDavid du Colombier rdt->apic = apic;
1149ef1f84bSDavid du Colombier rdt->intin = intin;
1159ef1f84bSDavid du Colombier rdt->lo = lo;
116bbf74bb6SDavid du Colombier }else{
117bbf74bb6SDavid du Colombier if(lo != rdt->lo){
118ffa640cdSDavid du Colombier if(bustype == BusISA && intin < 16 && lo == (Im|IPhigh|TMedge)){
119ffa640cdSDavid du Colombier DBG("override: isa %d %.8ux\n", intin, rdt->lo);
120ffa640cdSDavid du Colombier return; /* expected; default was overridden*/
121ffa640cdSDavid du Colombier }
122ffa640cdSDavid du Colombier print("multiple irq botch type %d bus %d %d/%d/%d lo %.8ux vs %.8ux\n",
123ffa640cdSDavid du Colombier bustype, busno, apicno, intin, devno, lo, rdt->lo);
124bbf74bb6SDavid du Colombier return;
125bbf74bb6SDavid du Colombier }
126bbf74bb6SDavid du Colombier DBG("dup rdt %d %d %d %d %.8ux\n", busno, apicno, intin, devno, lo);
127bbf74bb6SDavid du Colombier }
128bbf74bb6SDavid du Colombier rdt->ref++;
129bbf74bb6SDavid du Colombier rbus = malloc(sizeof(*rbus));
130bbf74bb6SDavid du Colombier rbus->rdt = rdt;
131ffa640cdSDavid du Colombier rbus->bustype = bustype;
132bbf74bb6SDavid du Colombier rbus->devno = devno;
133bbf74bb6SDavid du Colombier rbus->next = rdtbus[busno];
134bbf74bb6SDavid du Colombier rdtbus[busno] = rbus;
1359ef1f84bSDavid du Colombier }
1369ef1f84bSDavid du Colombier
1379ef1f84bSDavid du Colombier void
ioapicinit(int id,uintmem pa)1389ef1f84bSDavid du Colombier ioapicinit(int id, uintmem pa)
1399ef1f84bSDavid du Colombier {
1409ef1f84bSDavid du Colombier Apic *apic;
1419ef1f84bSDavid du Colombier
1429ef1f84bSDavid du Colombier /*
1439ef1f84bSDavid du Colombier * Mark the IOAPIC useable if it has a good ID
1449ef1f84bSDavid du Colombier * and the registers can be mapped.
1459ef1f84bSDavid du Colombier */
1469ef1f84bSDavid du Colombier if(id >= Napic)
1479ef1f84bSDavid du Colombier return;
1489ef1f84bSDavid du Colombier
1499ef1f84bSDavid du Colombier apic = &ioapic[id];
1509ef1f84bSDavid du Colombier if(apic->useable || (apic->addr = vmap(pa, 1024)) == nil)
1519ef1f84bSDavid du Colombier return;
1529ef1f84bSDavid du Colombier apic->useable = 1;
1539ef1f84bSDavid du Colombier
1549ef1f84bSDavid du Colombier /*
1559ef1f84bSDavid du Colombier * Initialise the IOAPIC.
1569ef1f84bSDavid du Colombier * The MultiProcessor Specification says it is the
1579ef1f84bSDavid du Colombier * responsibility of the O/S to set the APIC ID.
1589ef1f84bSDavid du Colombier */
1599ef1f84bSDavid du Colombier lock(apic);
1609ef1f84bSDavid du Colombier *(apic->addr+Ioregsel) = Ioapicver;
1619ef1f84bSDavid du Colombier apic->nrdt = ((*(apic->addr+Iowin)>>16) & 0xff) + 1;
1629ef1f84bSDavid du Colombier apic->gsib = gsib;
1639ef1f84bSDavid du Colombier gsib += apic->nrdt;
1649ef1f84bSDavid du Colombier
1659ef1f84bSDavid du Colombier *(apic->addr+Ioregsel) = Ioapicid;
1669ef1f84bSDavid du Colombier *(apic->addr+Iowin) = id<<24;
1679ef1f84bSDavid du Colombier unlock(apic);
1689ef1f84bSDavid du Colombier }
1699ef1f84bSDavid du Colombier
1709ef1f84bSDavid du Colombier void
ioapicdump(void)1719ef1f84bSDavid du Colombier ioapicdump(void)
1729ef1f84bSDavid du Colombier {
1739ef1f84bSDavid du Colombier int i, n;
174bbf74bb6SDavid du Colombier Rbus *rbus;
1759ef1f84bSDavid du Colombier Rdt *rdt;
1769ef1f84bSDavid du Colombier Apic *apic;
1779ef1f84bSDavid du Colombier u32int hi, lo;
1789ef1f84bSDavid du Colombier
1799ef1f84bSDavid du Colombier if(!DBGFLG)
1809ef1f84bSDavid du Colombier return;
1819ef1f84bSDavid du Colombier
1829ef1f84bSDavid du Colombier for(i = 0; i < Napic; i++){
1839ef1f84bSDavid du Colombier apic = &ioapic[i];
1849ef1f84bSDavid du Colombier if(!apic->useable || apic->addr == 0)
1859ef1f84bSDavid du Colombier continue;
1869ef1f84bSDavid du Colombier DBG("ioapic %d addr %#p nrdt %d gsib %d\n",
1879ef1f84bSDavid du Colombier i, apic->addr, apic->nrdt, apic->gsib);
1889ef1f84bSDavid du Colombier for(n = 0; n < apic->nrdt; n++){
1899ef1f84bSDavid du Colombier lock(apic);
1909ef1f84bSDavid du Colombier rtblget(apic, n, &hi, &lo);
1919ef1f84bSDavid du Colombier unlock(apic);
1929ef1f84bSDavid du Colombier DBG(" rdt %2.2d %#8.8ux %#8.8ux\n", n, hi, lo);
1939ef1f84bSDavid du Colombier }
1949ef1f84bSDavid du Colombier }
1959ef1f84bSDavid du Colombier for(i = 0; i < Nbus; i++){
196bbf74bb6SDavid du Colombier if((rbus = rdtbus[i]) == nil)
1979ef1f84bSDavid du Colombier continue;
1989ef1f84bSDavid du Colombier DBG("iointr bus %d:\n", i);
199bbf74bb6SDavid du Colombier while(rbus != nil){
200bbf74bb6SDavid du Colombier rdt = rbus->rdt;
201bbf74bb6SDavid du Colombier DBG(" apic %ld devno %#ux (%d %d) intin %d lo %#ux ref %d\n",
202bbf74bb6SDavid du Colombier rdt->apic-ioapic, rbus->devno, rbus->devno>>2,
203bbf74bb6SDavid du Colombier rbus->devno & 0x03, rdt->intin, rdt->lo, rdt->ref);
204bbf74bb6SDavid du Colombier rbus = rbus->next;
2059ef1f84bSDavid du Colombier }
2069ef1f84bSDavid du Colombier }
2079ef1f84bSDavid du Colombier }
2089ef1f84bSDavid du Colombier
2099ef1f84bSDavid du Colombier void
ioapiconline(void)2109ef1f84bSDavid du Colombier ioapiconline(void)
2119ef1f84bSDavid du Colombier {
2129ef1f84bSDavid du Colombier int i;
2139ef1f84bSDavid du Colombier Apic *apic;
2149ef1f84bSDavid du Colombier
2159ef1f84bSDavid du Colombier for(apic = ioapic; apic < &ioapic[Napic]; apic++){
2169ef1f84bSDavid du Colombier if(!apic->useable || apic->addr == nil)
2179ef1f84bSDavid du Colombier continue;
2189ef1f84bSDavid du Colombier for(i = 0; i < apic->nrdt; i++){
2199ef1f84bSDavid du Colombier lock(apic);
2209ef1f84bSDavid du Colombier rtblput(apic, i, 0, Im);
2219ef1f84bSDavid du Colombier unlock(apic);
2229ef1f84bSDavid du Colombier }
2239ef1f84bSDavid du Colombier }
2249ef1f84bSDavid du Colombier if(DBGFLG)
2259ef1f84bSDavid du Colombier ioapicdump();
2269ef1f84bSDavid du Colombier }
2279ef1f84bSDavid du Colombier
2289ef1f84bSDavid du Colombier static int dfpolicy = 0;
2299ef1f84bSDavid du Colombier
2309ef1f84bSDavid du Colombier static void
ioapicintrdd(u32int * hi,u32int * lo)2319ef1f84bSDavid du Colombier ioapicintrdd(u32int* hi, u32int* lo)
2329ef1f84bSDavid du Colombier {
2339ef1f84bSDavid du Colombier int i;
2349ef1f84bSDavid du Colombier static int df;
2359ef1f84bSDavid du Colombier static Lock dflock;
2369ef1f84bSDavid du Colombier
2379ef1f84bSDavid du Colombier /*
2389ef1f84bSDavid du Colombier * Set delivery mode (lo) and destination field (hi),
2399ef1f84bSDavid du Colombier * according to interrupt routing policy.
2409ef1f84bSDavid du Colombier */
2419ef1f84bSDavid du Colombier /*
2429ef1f84bSDavid du Colombier * The bulk of this code was written ~1995, when there was
2439ef1f84bSDavid du Colombier * one architecture and one generation of hardware, the number
2449ef1f84bSDavid du Colombier * of CPUs was up to 4(8) and the choices for interrupt routing
2459ef1f84bSDavid du Colombier * were physical, or flat logical (optionally with lowest
2469ef1f84bSDavid du Colombier * priority interrupt). Logical mode hasn't scaled well with
2479ef1f84bSDavid du Colombier * the increasing number of packages/cores/threads, so the
2489ef1f84bSDavid du Colombier * fall-back is to physical mode, which works across all processor
2499ef1f84bSDavid du Colombier * generations, both AMD and Intel, using the APIC and xAPIC.
2509ef1f84bSDavid du Colombier *
2519ef1f84bSDavid du Colombier * Interrupt routing policy can be set here.
2529ef1f84bSDavid du Colombier */
2539ef1f84bSDavid du Colombier switch(dfpolicy){
2549ef1f84bSDavid du Colombier default: /* noise core 0 */
2559ef1f84bSDavid du Colombier *hi = sys->machptr[0]->apicno<<24;
2569ef1f84bSDavid du Colombier break;
2579ef1f84bSDavid du Colombier case 1: /* round-robin */
2589ef1f84bSDavid du Colombier /*
2599ef1f84bSDavid du Colombier * Assign each interrupt to a different CPU on a round-robin
2609ef1f84bSDavid du Colombier * Some idea of the packages/cores/thread topology would be
2619ef1f84bSDavid du Colombier * useful here, e.g. to not assign interrupts to more than one
2629ef1f84bSDavid du Colombier * thread in a core. But, as usual, Intel make that an onerous
2639ef1f84bSDavid du Colombier * task.
2649ef1f84bSDavid du Colombier */
2659ef1f84bSDavid du Colombier lock(&dflock);
2669ef1f84bSDavid du Colombier for(;;){
2679ef1f84bSDavid du Colombier i = df++;
2689ef1f84bSDavid du Colombier if(df >= MACHMAX+1)
2699ef1f84bSDavid du Colombier df = 0;
2709ef1f84bSDavid du Colombier if(sys->machptr[i] == nil || !sys->machptr[i]->online)
2719ef1f84bSDavid du Colombier continue;
2729ef1f84bSDavid du Colombier i = sys->machptr[i]->apicno;
2739ef1f84bSDavid du Colombier if(xapic[i].useable && xapic[i].addr == 0)
2749ef1f84bSDavid du Colombier break;
2759ef1f84bSDavid du Colombier }
2769ef1f84bSDavid du Colombier unlock(&dflock);
2779ef1f84bSDavid du Colombier
2789ef1f84bSDavid du Colombier *hi = i<<24;
2799ef1f84bSDavid du Colombier break;
2809ef1f84bSDavid du Colombier }
2819ef1f84bSDavid du Colombier *lo |= Pm|MTf;
2829ef1f84bSDavid du Colombier }
2839ef1f84bSDavid du Colombier
2849ef1f84bSDavid du Colombier int
ioapicintrenable(Vctl * v)2859ef1f84bSDavid du Colombier ioapicintrenable(Vctl* v)
2869ef1f84bSDavid du Colombier {
287bbf74bb6SDavid du Colombier Rbus *rbus;
2889ef1f84bSDavid du Colombier Rdt *rdt;
2899ef1f84bSDavid du Colombier u32int hi, lo;
290ffa640cdSDavid du Colombier int bustype, busno, devno, vecno;
2919ef1f84bSDavid du Colombier
2929ef1f84bSDavid du Colombier /*
2939ef1f84bSDavid du Colombier * Bridge between old and unspecified new scheme,
2949ef1f84bSDavid du Colombier * the work in progress...
2959ef1f84bSDavid du Colombier */
2969ef1f84bSDavid du Colombier if(v->tbdf == BUSUNKNOWN){
2979ef1f84bSDavid du Colombier if(v->irq >= IdtLINT0 && v->irq <= IdtSPURIOUS){
2989ef1f84bSDavid du Colombier if(v->irq != IdtSPURIOUS)
2999ef1f84bSDavid du Colombier v->isr = apiceoi;
300*099a302fSDavid du Colombier v->type = "lapic";
3019ef1f84bSDavid du Colombier return v->irq;
3029ef1f84bSDavid du Colombier }
3039ef1f84bSDavid du Colombier else{
3049ef1f84bSDavid du Colombier /*
3059ef1f84bSDavid du Colombier * Legacy ISA.
3069ef1f84bSDavid du Colombier * Make a busno and devno using the
3079ef1f84bSDavid du Colombier * ISA bus number and the irq.
3089ef1f84bSDavid du Colombier */
3099ef1f84bSDavid du Colombier extern int mpisabusno;
3109ef1f84bSDavid du Colombier
3119ef1f84bSDavid du Colombier if(mpisabusno == -1)
3129ef1f84bSDavid du Colombier panic("no ISA bus allocated");
3139ef1f84bSDavid du Colombier busno = mpisabusno;
314ffa640cdSDavid du Colombier devno = v->irq;
315ffa640cdSDavid du Colombier bustype = BusISA;
3169ef1f84bSDavid du Colombier }
3179ef1f84bSDavid du Colombier }
318ffa640cdSDavid du Colombier else if((bustype = BUSTYPE(v->tbdf)) == BusPCI){
3199ef1f84bSDavid du Colombier /*
3209ef1f84bSDavid du Colombier * PCI.
3219ef1f84bSDavid du Colombier * Make a devno from BUSDNO(tbdf) and pcidev->intp.
3229ef1f84bSDavid du Colombier */
3239ef1f84bSDavid du Colombier Pcidev *pcidev;
3249ef1f84bSDavid du Colombier
3259ef1f84bSDavid du Colombier busno = BUSBNO(v->tbdf);
3269ef1f84bSDavid du Colombier if((pcidev = pcimatchtbdf(v->tbdf)) == nil)
3279ef1f84bSDavid du Colombier panic("no PCI dev for tbdf %#8.8ux\n", v->tbdf);
3289ef1f84bSDavid du Colombier if((devno = pcicfgr8(pcidev, PciINTP)) == 0)
3299ef1f84bSDavid du Colombier panic("no INTP for tbdf %#8.8ux\n", v->tbdf);
3309ef1f84bSDavid du Colombier devno = BUSDNO(v->tbdf)<<2|(devno-1);
3319ef1f84bSDavid du Colombier DBG("ioapicintrenable: tbdf %#8.8ux busno %d devno %d\n",
3329ef1f84bSDavid du Colombier v->tbdf, busno, devno);
3339ef1f84bSDavid du Colombier }
3349ef1f84bSDavid du Colombier else{
3359ef1f84bSDavid du Colombier SET(busno, devno);
3369ef1f84bSDavid du Colombier panic("unknown tbdf %#8.8ux\n", v->tbdf);
3379ef1f84bSDavid du Colombier }
3389ef1f84bSDavid du Colombier
339bbf74bb6SDavid du Colombier rdt = nil;
340bbf74bb6SDavid du Colombier for(rbus = rdtbus[busno]; rbus != nil; rbus = rbus->next)
341ffa640cdSDavid du Colombier if(rbus->devno == devno && rbus->bustype == bustype){
342bbf74bb6SDavid du Colombier rdt = rbus->rdt;
3439ef1f84bSDavid du Colombier break;
3449ef1f84bSDavid du Colombier }
3459ef1f84bSDavid du Colombier if(rdt == nil){
3469ef1f84bSDavid du Colombier extern int mpisabusno;
3479ef1f84bSDavid du Colombier
3489ef1f84bSDavid du Colombier /*
3499ef1f84bSDavid du Colombier * First crack in the smooth exterior of the new code:
3509ef1f84bSDavid du Colombier * some BIOS make an MPS table where the PCI devices are
3519ef1f84bSDavid du Colombier * just defaulted to ISA.
3529ef1f84bSDavid du Colombier * Rewrite this to be cleaner.
3539ef1f84bSDavid du Colombier */
3549ef1f84bSDavid du Colombier if((busno = mpisabusno) == -1)
3559ef1f84bSDavid du Colombier return -1;
3569ef1f84bSDavid du Colombier devno = v->irq<<2;
357bbf74bb6SDavid du Colombier for(rbus = rdtbus[busno]; rbus != nil; rbus = rbus->next){
358bbf74bb6SDavid du Colombier if(rbus->devno == devno){
359bbf74bb6SDavid du Colombier rdt = rbus->rdt;
3609ef1f84bSDavid du Colombier break;
3619ef1f84bSDavid du Colombier }
362bbf74bb6SDavid du Colombier }
3639ef1f84bSDavid du Colombier DBG("isa: tbdf %#8.8ux busno %d devno %d %#p\n",
3649ef1f84bSDavid du Colombier v->tbdf, busno, devno, rdt);
3659ef1f84bSDavid du Colombier }
3669ef1f84bSDavid du Colombier if(rdt == nil)
3679ef1f84bSDavid du Colombier return -1;
3689ef1f84bSDavid du Colombier
3699ef1f84bSDavid du Colombier /*
3709ef1f84bSDavid du Colombier * Second crack:
3719ef1f84bSDavid du Colombier * what to do about devices that intrenable/intrdisable frequently?
3729ef1f84bSDavid du Colombier * 1) there is no ioapicdisable yet;
3739ef1f84bSDavid du Colombier * 2) it would be good to reuse freed vectors.
3749ef1f84bSDavid du Colombier * Oh bugger.
3759ef1f84bSDavid du Colombier */
3769ef1f84bSDavid du Colombier /*
3779ef1f84bSDavid du Colombier * This is a low-frequency event so just lock
3789ef1f84bSDavid du Colombier * the whole IOAPIC to initialise the RDT entry
3799ef1f84bSDavid du Colombier * rather than putting a Lock in each entry.
3809ef1f84bSDavid du Colombier */
3819ef1f84bSDavid du Colombier lock(rdt->apic);
3829ef1f84bSDavid du Colombier if((rdt->lo & 0xff) == 0){
3839ef1f84bSDavid du Colombier lock(&idtnolock);
3849ef1f84bSDavid du Colombier vecno = idtno;
3859ef1f84bSDavid du Colombier idtno = (idtno+8) % IdtMAX;
3869ef1f84bSDavid du Colombier if(idtno < IdtIOAPIC)
3879ef1f84bSDavid du Colombier idtno += IdtIOAPIC;
3889ef1f84bSDavid du Colombier unlock(&idtnolock);
3899ef1f84bSDavid du Colombier
3909ef1f84bSDavid du Colombier rdt->lo |= vecno;
3919ef1f84bSDavid du Colombier rdtvecno[vecno] = rdt;
3929ef1f84bSDavid du Colombier }
3939ef1f84bSDavid du Colombier
394bbf74bb6SDavid du Colombier rdt->enabled++;
3959ef1f84bSDavid du Colombier lo = (rdt->lo & ~Im);
3969ef1f84bSDavid du Colombier ioapicintrdd(&hi, &lo);
3979ef1f84bSDavid du Colombier rtblput(rdt->apic, rdt->intin, hi, lo);
3989ef1f84bSDavid du Colombier vecno = lo & 0xff;
3999ef1f84bSDavid du Colombier unlock(rdt->apic);
4009ef1f84bSDavid du Colombier
4019ef1f84bSDavid du Colombier DBG("busno %d devno %d hi %#8.8ux lo %#8.8ux vecno %d\n",
4029ef1f84bSDavid du Colombier busno, devno, hi, lo, vecno);
4039ef1f84bSDavid du Colombier v->isr = apicisr;
4049ef1f84bSDavid du Colombier v->eoi = apiceoi;
4059ef1f84bSDavid du Colombier v->vno = vecno;
406*099a302fSDavid du Colombier v->type = "ioapic";
4079ef1f84bSDavid du Colombier
4089ef1f84bSDavid du Colombier return vecno;
4099ef1f84bSDavid du Colombier }
4109ef1f84bSDavid du Colombier
4119ef1f84bSDavid du Colombier int
ioapicintrdisable(int vecno)4129ef1f84bSDavid du Colombier ioapicintrdisable(int vecno)
4139ef1f84bSDavid du Colombier {
4149ef1f84bSDavid du Colombier Rdt *rdt;
4159ef1f84bSDavid du Colombier
4169ef1f84bSDavid du Colombier /*
4179ef1f84bSDavid du Colombier * FOV. Oh dear. This isn't very good.
4189ef1f84bSDavid du Colombier * Fortunately rdtvecno[vecno] is static
4199ef1f84bSDavid du Colombier * once assigned.
4209ef1f84bSDavid du Colombier * Must do better.
4219ef1f84bSDavid du Colombier *
4229ef1f84bSDavid du Colombier * What about any pending interrupts?
4239ef1f84bSDavid du Colombier */
4249ef1f84bSDavid du Colombier if(vecno < 0 || vecno > IdtMAX){
4259ef1f84bSDavid du Colombier panic("ioapicintrdisable: vecno %d out of range", vecno);
4269ef1f84bSDavid du Colombier return -1;
4279ef1f84bSDavid du Colombier }
4289ef1f84bSDavid du Colombier if((rdt = rdtvecno[vecno]) == nil){
4299ef1f84bSDavid du Colombier panic("ioapicintrdisable: vecno %d has no rdt", vecno);
4309ef1f84bSDavid du Colombier return -1;
4319ef1f84bSDavid du Colombier }
4329ef1f84bSDavid du Colombier
4339ef1f84bSDavid du Colombier lock(rdt->apic);
434bbf74bb6SDavid du Colombier rdt->enabled--;
435bbf74bb6SDavid du Colombier if(rdt->enabled == 0)
4369ef1f84bSDavid du Colombier rtblput(rdt->apic, rdt->intin, 0, rdt->lo);
4379ef1f84bSDavid du Colombier unlock(rdt->apic);
4389ef1f84bSDavid du Colombier
4399ef1f84bSDavid du Colombier return 0;
4409ef1f84bSDavid du Colombier }
441