]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/archacpi.c
merge
[plan9front.git] / sys / src / 9 / pc / archacpi.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7
8 #include "mp.h"
9
10 #include <aml.h>
11
12 typedef struct Rsd Rsd;
13 typedef struct Tbl Tbl;
14
15 struct Rsd {
16         uchar   sig[8];
17         uchar   csum;
18         uchar   oemid[6];
19         uchar   rev;
20         uchar   raddr[4];
21         uchar   len[4];
22         uchar   xaddr[8];
23         uchar   xcsum;
24         uchar   reserved[3];
25 };
26
27 struct Tbl {
28         uchar   sig[4];
29         uchar   len[4];
30         uchar   rev;
31         uchar   csum;
32         uchar   oemid[6];
33         uchar   oemtid[8];
34         uchar   oemrev[4];
35         uchar   cid[4];
36         uchar   crev[4];
37         uchar   data[];
38 };
39
40 enum {
41         Tblsz   = 4+4+1+1+6+8+4+4+4,
42 };
43
44 static Rsd *rsd;
45
46 /* physical addresses visited by maptable() */
47 static int ntblpa;
48 static uintptr tblpa[64];
49
50 /* successfully mapped tables */
51 static int ntblmap;
52 static Tbl *tblmap[64];
53
54 static ushort
55 get16(uchar *p){
56         return p[1]<<8 | p[0];
57 }
58
59 static uint
60 get32(uchar *p){
61         return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
62 }
63
64 static uvlong
65 get64(uchar *p){
66         uvlong u;
67
68         u = get32(p+4);
69         return u<<32 | get32(p);
70 }
71
72 static uint
73 tbldlen(Tbl *t){
74         return get32(t->len) - Tblsz;
75 }
76
77 static void
78 maptable(uvlong xpa)
79 {
80         uchar *p, *e;
81         uintptr pa;
82         u32int l;
83         Tbl *t;
84         int i;
85
86         pa = xpa;
87         if((uvlong)pa != xpa || pa == 0)
88                 return;
89         if(ntblpa >= nelem(tblpa) || ntblmap >= nelem(tblmap))
90                 return;
91
92         for(i=0; i<ntblpa; i++){
93                 if(pa == tblpa[i])
94                         return;
95         }
96         tblpa[ntblpa++] = pa;
97
98         if((t = vmap(pa, 8)) == nil)
99                 return;
100         l = get32(t->len);
101         if(l < Tblsz){
102                 vunmap(t, 8);
103                 return;
104         }
105         vunmap(t, 8);
106         if((t = vmap(pa, l)) == nil)
107                 return;
108         if(checksum(t, l)){
109                 vunmap(t, l);
110                 return;
111         }
112         tblmap[ntblmap++] = t;
113
114         p = (uchar*)t;
115         e = p + l;
116         if(memcmp("RSDT", t->sig, 4) == 0){
117                 for(p = t->data; p+3 < e; p += 4)
118                         maptable(get32(p));
119                 return;
120         }
121         if(memcmp("XSDT", t->sig, 4) == 0){
122                 for(p = t->data; p+7 < e; p += 8)
123                         maptable(get64(p));
124                 return;
125         }
126         if(memcmp("FACP", t->sig, 4) == 0){
127                 if(l < 44)
128                         return;
129                 maptable(get32(p + 40));
130                 if(l < 148)
131                         return;
132                 maptable(get64(p + 140));
133                 return;
134         }
135 }
136
137 static void
138 maptables(void)
139 {
140         if(rsd == nil || ntblmap > 0 || ntblpa > 0)
141                 return;
142         if(!checksum(rsd, 20))
143                 maptable(get32(rsd->raddr));
144         if(rsd->rev >= 2)
145                 if(!checksum(rsd, 36))
146                         maptable(get64(rsd->xaddr));
147 }
148
149 static Apic*
150 findapic(int gsi, int *pintin)
151 {
152         Apic *a;
153         int i;
154
155         for(i=0; i<=MaxAPICNO; i++){
156                 if((a = mpioapic[i]) == nil)
157                         continue;
158                 if((a->flags & PcmpEN) == 0)
159                         continue;
160                 if(gsi >= a->gsibase && gsi <= a->gsibase+a->mre){
161                         if(pintin)
162                                 *pintin = gsi - a->gsibase;
163                         return a;
164                 }
165         }
166         print("findapic: no ioapic found for gsi %d\n", gsi);
167         return nil;
168 }
169
170 static void
171 addirq(int gsi, int type, int busno, int irq, int flags)
172 {
173         Apic *a;
174         Bus *bus;
175         Aintr *ai;
176         PCMPintr *pi;
177         int intin;
178
179         if((a = findapic(gsi, &intin)) == nil)
180                 return;
181
182         for(bus = mpbus; bus; bus = bus->next)
183                 if(bus->type == type && bus->busno == busno)
184                         goto Foundbus;
185
186         if((bus = xalloc(sizeof(Bus))) == nil)
187                 panic("addirq: no memory for Bus");
188         bus->busno = busno;
189         bus->type = type;
190         if(type == BusISA){
191                 bus->po = PcmpHIGH;
192                 bus->el = PcmpEDGE;
193                 if(mpisabus == -1)
194                         mpisabus = busno;
195         } else {
196                 bus->po = PcmpLOW;
197                 bus->el = PcmpLEVEL;
198         }
199         if(mpbus)
200                 mpbuslast->next = bus;
201         else
202                 mpbus = bus;
203         mpbuslast = bus;
204
205 Foundbus:
206         for(ai = bus->aintr; ai; ai = ai->next)
207                 if(ai->intr->irq == irq)
208                         return;
209
210         if((pi = xalloc(sizeof(PCMPintr))) == nil)
211                 panic("addirq: no memory for PCMPintr");
212         pi->type = PcmpIOINTR;
213         pi->intr = PcmpINT;
214         pi->flags = flags & (PcmpPOMASK|PcmpELMASK);
215         pi->busno = busno;
216         pi->irq = irq;
217         pi->apicno = a->apicno;
218         pi->intin = intin;
219
220         if((ai = xalloc(sizeof(Aintr))) == nil)
221                 panic("addirq: no memory for Aintr");
222         ai->intr = pi;
223         ai->apic = a;
224         ai->next = bus->aintr;
225         bus->aintr = ai;
226 }
227
228 static char*
229 eisaid(void *v)
230 {
231         static char id[8];
232         ulong b, l;
233         int i;
234
235         if(amltag(v) == 's')
236                 return v;
237         b = amlint(v);
238         for(l = 0, i=24; i>=0; i -= 8, b >>= 8)
239                 l |= (b & 0xFF) << i;
240         id[7] = 0;
241         for(i=6; i>=3; i--, l >>= 4)
242                 id[i] = "0123456789ABCDEF"[l & 0xF];
243         for(i=2; i>=0; i--, l >>= 5)
244                 id[i] = '@' + (l & 0x1F);
245         return id;
246 }
247
248 static int
249 pcibusno(void *dot)
250 {
251         int bno, adr, tbdf;
252         Pcidev *pdev;
253         void *p, *x;
254         char *id;
255
256         id = nil;
257         if((x = amlwalk(dot, "^_HID")) != nil)
258                 if((p = amlval(x)) != nil)
259                         id = eisaid(p);
260         if((x = amlwalk(dot, "^_BBN")) == nil)
261                 if((x = amlwalk(dot, "^_ADR")) == nil)
262                         return -1;
263         adr = amlint(amlval(x));
264         /* if root bridge, then we are done here */
265         if(id != nil && (strcmp(id, "PNP0A03")==0 || strcmp(id, "PNP0A08")==0))
266                 return adr;
267         x = amlwalk(dot, "^");
268         if(x == nil || x == dot)
269                 return -1;
270         if((bno = pcibusno(x)) < 0)
271                 return -1;
272         tbdf = MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
273         pdev = pcimatchtbdf(tbdf);
274         if(pdev == nil)
275                 return -1;
276         if(pdev->bridge == nil)
277                 return bno;
278         return BUSBNO(pdev->bridge->tbdf);
279 }
280
281 static int
282 pciaddr(void *dot)
283 {
284         int adr, bno;
285         void *x;
286
287         for(;;){
288                 if((x = amlwalk(dot, "_ADR")) == nil){
289                         x = amlwalk(dot, "^");
290                         if(x == nil || x == dot)
291                                 break;
292                         dot = x;
293                         continue;
294                 }
295                 if((bno = pcibusno(x)) < 0)
296                         break;
297                 if((x = amlval(x)) == nil)
298                         break;
299                 adr = amlint(x);
300                 return MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
301         }
302         return -1;
303 }
304
305 static int
306 getirqs(void *d, uchar pmask[32], int *pflags)
307 {
308         int i, n, m;
309         uchar *p;
310
311         *pflags = 0;
312         memset(pmask, 0, 32);
313         if(amltag(d) != 'b')
314                 return -1;
315         p = amlval(d);
316         if(amllen(d) >= 2 && (p[0] == 0x22 || p[0] == 0x23)){
317                 pmask[0] = p[1];
318                 pmask[1] = p[2];
319                 if(amllen(d) >= 3 && p[0] == 0x23)
320                         *pflags = ((p[3] & (1<<0)) ? PcmpEDGE : PcmpLEVEL)
321                                 | ((p[3] & (1<<3)) ? PcmpLOW : PcmpHIGH);
322                 return 0;
323         }
324         if(amllen(d) >= 5 && p[0] == 0x89){
325                 n = p[4];
326                 if(amllen(d) < 5+n*4)
327                         return -1;
328                 for(i=0; i<n; i++){
329                         m = get32(p+5 + i*4);
330                         if(m >= 0 && m < 256)
331                                 pmask[m/8] |= 1<<(m%8);
332                 }
333                 *pflags = ((p[3] & (1<<1)) ? PcmpEDGE : PcmpLEVEL)
334                         | ((p[3] & (1<<2)) ? PcmpLOW : PcmpHIGH);
335                 return 0;
336         }
337         return -1;
338 }
339
340 static uchar*
341 setirq(void *d, uint irq)
342 {
343         uchar *p;
344
345         if(amltag(d) != 'b')
346                 return nil;
347         p = amlnew('b', amllen(d));
348         memmove(p, d, amllen(p));
349         if(p[0] == 0x22 || p[0] == 0x23){
350                 irq = 1<<irq;
351                 p[1] = irq;
352                 p[2] = irq>>8;
353         }
354         if(p[0] == 0x89){
355                 p[4] = 1;
356                 p[5] = irq;
357                 p[6] = irq>>8;
358                 p[7] = irq>>16;
359                 p[8] = irq>>24;
360         }
361         return p;
362 }
363
364 static int
365 setuplink(void *link, int *pflags)
366 {
367         uchar im, pm[32], cm[32], *c;
368         static int lastirq = 1;
369         int gsi, i;
370         void *r;
371
372         if(amltag(link) != 'N')
373                 return -1;
374
375         r = nil;
376         if(amleval(amlwalk(link, "_PRS"), "", &r) < 0)
377                 return -1;
378         if(getirqs(r, pm, pflags) < 0)
379                 return -1;
380
381         r = nil;
382         if(amleval(amlwalk(link, "_CRS"), "", &r) < 0)
383                 return -1;
384         if(getirqs(r, cm, pflags) < 0)
385                 return -1;
386         
387         gsi = -1;
388         for(i=0; i<256; i++){
389                 im = 1<<(i%8);
390                 if(pm[i/8] & im){
391                         if(cm[i/8] & im)
392                                 gsi = i;
393                 }
394         }
395
396         if(gsi > 0 || getconf("*nopcirouting") != nil)
397                 return gsi;
398
399         for(i=0; i<256; i++){
400                 gsi = lastirq++ & 0xFF; /* round robin */
401                 im = 1<<(gsi%8);
402                 if(pm[gsi/8] & im){
403                         if((c = setirq(r, gsi)) == nil)
404                                 break;
405                         if(amleval(amlwalk(link, "_SRS"), "b", c, nil) < 0)
406                                 break;
407                         return gsi;
408                 }
409         }
410         return -1;
411 }
412
413 static int
414 enumprt(void *dot, void *)
415 {
416         void *p, **a, **b;
417         int bno, dno, pin, gsi, flags;
418         int n, i;
419
420         bno = pcibusno(dot);
421         if(bno < 0)
422                 return 1;
423
424         /* evalulate _PRT method */
425         p = nil;
426         if(amleval(dot, "", &p) < 0)
427                 return 1;
428         if(amltag(p) != 'p')
429                 return 1;
430
431         amltake(p);
432         n = amllen(p);
433         a = amlval(p);
434         for(i=0; i<n; i++){
435                 if(amltag(a[i]) != 'p')
436                         continue;
437                 if(amllen(a[i]) != 4)
438                         continue;
439                 flags = 0;
440                 b = amlval(a[i]);
441                 dno = amlint(b[0])>>16;
442                 pin = amlint(b[1]);
443                 gsi = amlint(b[3]);
444                 if(gsi==0){
445                         gsi = setuplink(b[2], &flags);
446                         if(gsi <= 0)
447                                 continue;
448                 }
449                 addirq(gsi, BusPCI, bno, (dno<<2)|pin, flags);
450         }
451         amldrop(p);
452
453         return 1;
454 }
455
456 static int
457 enumec(void *dot, void *)
458 {
459         int cmdport, dataport;
460         uchar *b;
461         void *x;
462         char *id;
463
464         b = nil;
465         id = eisaid(amlval(amlwalk(dot, "^_HID")));
466         if(id == nil || strcmp(id, "PNP0C09") != 0)
467                 return 1;
468         if((x = amlwalk(dot, "^_CRS")) == nil)
469                 return 1;
470         if(amleval(x, "", &b) < 0 || amltag(b) != 'b' || amllen(b) < 16)
471                 return 1;
472         if(b[0] != 0x47 || b[8] != 0x47)        /* two i/o port descriptors */
473                 return 1;
474         dataport = b[0+2] | b[0+3]<<8;
475         cmdport = b[8+2] | b[8+3]<<8;
476         ecinit(cmdport, dataport);
477         return 1;
478 }
479
480 static void
481 acpiinit(void)
482 {
483         Tbl *t;
484         Apic *a;
485         void *va;
486         uchar *s, *p, *e;
487         ulong lapicbase;
488         int machno, i, c;
489
490         maptables();
491
492         amlinit();
493
494         /* load DSDT */
495         for(i=0; i<ntblmap; i++){
496                 t = tblmap[i];
497                 if(memcmp(t->sig, "DSDT", 4) == 0){
498                         amlload(t->data, tbldlen(t));
499                         break;
500                 }
501         }
502
503         /* load SSDT, there can be multiple tables */
504         for(i=0; i<ntblmap; i++){
505                 t = tblmap[i];
506                 if(memcmp(t->sig, "SSDT", 4) == 0)
507                         amlload(t->data, tbldlen(t));
508         }
509
510         /* set APIC mode */
511         amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
512
513         for(i=0; i<ntblmap; i++){
514                 t = tblmap[i];
515                 if(memcmp(t->sig, "APIC", 4) == 0)
516                         goto Foundapic;
517         }
518         panic("acpiinit: no MADT (APIC) table");
519         return;
520
521 Foundapic:
522         s = t->data;
523         e = s + tbldlen(t);
524         lapicbase = get32(s); s += 8;
525         va = vmap(lapicbase, 1024);
526         print("LAPIC: %.8lux %#p\n", lapicbase, va);
527         if(va == nil)
528                 panic("acpiinit: cannot map lapic %.8lux", lapicbase);
529
530         machno = 0;
531         for(p = s; p < e; p += c){
532                 c = p[1];
533                 if(c < 2 || (p+c) > e)
534                         break;
535                 switch(*p){
536                 case 0x00:      /* Processor Local APIC */
537                         if(p[3] > MaxAPICNO)
538                                 break;
539                         if((a = xalloc(sizeof(Apic))) == nil)
540                                 panic("acpiinit: no memory for Apic");
541                         a->type = PcmpPROCESSOR;
542                         a->apicno = p[3];
543                         a->paddr = lapicbase;
544                         a->addr = va;
545                         a->lintr[0] = ApicIMASK;
546                         a->lintr[1] = ApicIMASK;
547                         a->flags = p[4] & PcmpEN;
548
549                         /* skip disabled processors */
550                         if((a->flags & PcmpEN) == 0 || mpapic[a->apicno] != nil){
551                                 xfree(a);
552                                 break;
553                         }
554                         a->machno = machno++;
555
556                         /*
557                          * platform firmware should list the boot processor
558                          * as the first processor entry in the MADT
559                          */
560                         if(a->machno == 0)
561                                 a->flags |= PcmpBP;
562
563                         mpapic[a->apicno] = a;
564                         break;
565                 case 0x01:      /* I/O APIC */
566                         if(p[2] > MaxAPICNO)
567                                 break;
568                         if((a = xalloc(sizeof(Apic))) == nil)
569                                 panic("acpiinit: no memory for io Apic");
570                         a->type = PcmpIOAPIC;
571                         a->apicno = p[2];
572                         a->paddr = get32(p+4);
573                         if((a->addr = vmap(a->paddr, 1024)) == nil)
574                                 panic("acpiinit: cannot map ioapic %.8lux", a->paddr);
575                         a->gsibase = get32(p+8);
576                         a->flags = PcmpEN;
577                         mpioapic[a->apicno] = a;
578                         ioapicinit(a, a->apicno);
579                         break;
580                 }
581         }
582
583         /*
584          * need 2nd pass as vbox puts interrupt overrides
585          * *before* the ioapic entries (!)
586          */
587         for(p = s; p < e; p += c){
588                 c = p[1];
589                 if(c < 2 || (p+c) > e)
590                         break;
591                 switch(*p){
592                 case 0x02:      /* Interrupt Source Override */
593                         addirq(get32(p+4), BusISA, 0, p[3], get16(p+8));
594                         break;
595                 case 0x03:      /* NMI Source */
596                 case 0x04:      /* Local APIC NMI */
597                 case 0x05:      /* Local APIC Address Override */
598                 case 0x06:      /* I/O SAPIC */
599                 case 0x07:      /* Local SAPIC */
600                 case 0x08:      /* Platform Interrupt Sources */
601                 case 0x09:      /* Processor Local x2APIC */
602                 case 0x0A:      /* x2APIC NMI */
603                 case 0x0B:      /* GIC */
604                 case 0x0C:      /* GICD */
605                         break;
606                 }
607         }
608
609         /* look for PCI interrupt mappings */
610         amlenum(amlroot, "_PRT", enumprt, nil);
611
612         /* add identity mapped legacy isa interrupts */
613         for(i=0; i<16; i++)
614                 addirq(i, BusISA, 0, i, 0);
615
616         /* find embedded controller */
617         amlenum(amlroot, "_HID", enumec, nil);
618
619         /* free the AML interpreter */
620         amlexit();
621
622         /*
623          * Ininitalize local APIC and start application processors.
624          */
625         mpinit();
626 }
627
628 static void
629 acpireset(void)
630 {
631         uchar *p;
632         Tbl *t;
633         int i;
634
635         /* stop application processors */
636         mpshutdown();
637
638         /* locate and write platform reset register */
639         for(i=0; i < ntblmap; i++){
640                 t = tblmap[i];
641                 if(memcmp(t->sig, "FACP", 4) != 0)
642                         continue;
643                 if(get32(t->len) <= 128)
644                         break;
645                 p = (uchar*)t;
646                 if((get32(p + 112) & (1<<10)) == 0)
647                         break;
648                 if(p[116+0] != IoSpace)
649                         break;
650                 outb(get32(p+116+4), p[128]);
651                 break;
652         }
653
654         /* acpi shutdown failed, try generic reset */
655         archreset();
656 }
657
658 static int identify(void);
659
660 PCArch archacpi = {
661 .id=            "ACPI", 
662 .ident=         identify,
663 .reset=         acpireset,
664 .intrinit=      acpiinit,
665 .intrenable=    mpintrenable,
666 .intron=        lapicintron,
667 .introff=       lapicintroff,
668 .fastclock=     i8253read,
669 .timerset=      lapictimerset,
670 };
671
672 static long
673 readtbls(Chan*, void *v, long n, vlong o)
674 {
675         int i, l, m;
676         uchar *p;
677         Tbl *t;
678
679         maptables();
680
681         p = v;
682         for(i=0; n > 0 && i < ntblmap; i++){
683                 t = tblmap[i];
684                 l = get32(t->len);
685                 if(o >= l){
686                         o -= l;
687                         continue;
688                 }
689                 m = l - o;
690                 if(m > n)
691                         m = n;
692                 memmove(p, (uchar*)t + o, m);
693                 p += m;
694                 n -= m;
695                 o = 0;
696         }
697         return p - (uchar*)v;
698 }
699
700 static int
701 identify(void)
702 {
703         uintptr pa;
704         char *cp;
705
706         if((cp = getconf("*acpi")) == nil)
707                 return 1;
708         pa = (uintptr)strtoull(cp, nil, 16);
709         if(pa <= 1)
710                 rsd = sigsearch("RSD PTR ");
711         else
712                 rsd = vmap(pa, sizeof(Rsd));
713         if(rsd == nil)
714                 return 1;
715         if(checksum(rsd, 20) && checksum(rsd, 36))
716                 return 1;
717         addarchfile("acpitbls", 0444, readtbls, nil);
718         if(strcmp(cp, "0") == 0)
719                 return 1;
720         if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
721                 return 1;
722         if(m->havetsc && getconf("*notsc") == nil)
723                 archacpi.fastclock = tscticks;
724         return 0;
725 }
726
727 static int
728 readpcicfg(Amlio *io, void *data, int n, int offset)
729 {
730         ulong r, x;
731         Pcidev *p;
732         uchar *a;
733         int i;
734
735         a = data;
736         p = io->aux;
737         if(p == nil)
738                 return -1;
739         offset += io->off;
740         if(offset > 256)
741                 return 0;
742         if(n+offset > 256)
743                 n = 256-offset;
744         r = offset;
745         if(!(r & 3) && n == 4){
746                 x = pcicfgr32(p, r);
747                 PBIT32(a, x);
748                 return 4;
749         }
750         if(!(r & 1) && n == 2){
751                 x = pcicfgr16(p, r);
752                 PBIT16(a, x);
753                 return 2;
754         }
755         for(i = 0; i <  n; i++){
756                 x = pcicfgr8(p, r);
757                 PBIT8(a, x);
758                 a++;
759                 r++;
760         }
761         return i;
762 }
763
764 static int
765 writepcicfg(Amlio *io, void *data, int n, int offset)
766 {
767         ulong r, x;
768         Pcidev *p;
769         uchar *a;
770         int i;
771
772         a = data;
773         p = io->aux;
774         if(p == nil)
775                 return -1;
776         offset += io->off;
777         if(offset > 256)
778                 return 0;
779         if(n+offset > 256)
780                 n = 256-offset;
781         r = offset;
782         if(!(r & 3) && n == 4){
783                 x = GBIT32(a);
784                 pcicfgw32(p, r, x);
785                 return 4;
786         }
787         if(!(r & 1) && n == 2){
788                 x = GBIT16(a);
789                 pcicfgw16(p, r, x);
790                 return 2;
791         }
792         for(i = 0; i <  n; i++){
793                 x = GBIT8(a);
794                 pcicfgw8(p, r, x);
795                 a++;
796                 r++;
797         }
798         return i;
799 }
800
801 static int
802 readioport(Amlio *io, void *data, int len, int port)
803 {
804         uchar *a;
805
806         a = data;
807         port += io->off;
808         switch(len){
809         case 4:
810                 PBIT32(a, inl(port));
811                 return 4;
812         case 2:
813                 PBIT16(a, ins(port));
814                 return 2;
815         case 1:
816                 PBIT8(a, inb(port));
817                 return 1;
818         }
819         return -1;
820 }
821
822 static int
823 writeioport(Amlio *io, void *data, int len, int port)
824 {
825         uchar *a;
826
827         a = data;
828         port += io->off;
829         switch(len){
830         case 4:
831                 outl(port, GBIT32(a));
832                 return 4;
833         case 2:
834                 outs(port, GBIT16(a));
835                 return 2;
836         case 1:
837                 outb(port, GBIT8(a));
838                 return 1;
839         }
840         return -1;
841 }
842
843 int
844 amlmapio(Amlio *io)
845 {
846         int tbdf;
847         Pcidev *pdev;
848         char buf[64];
849
850         switch(io->space){
851         default:
852                 print("amlmapio: address space %x not implemented\n", io->space);
853                 break;
854         case MemSpace:
855                 if((io->va = vmap(io->off, io->len)) == nil){
856                         print("amlmapio: vmap failed\n");
857                         break;
858                 }
859                 return 0;
860         case IoSpace:
861                 snprint(buf, sizeof(buf), "%N", io->name);
862                 if(ioalloc(io->off, io->len, 0, buf) < 0){
863                         print("amlmapio: ioalloc failed\n");
864                         break;
865                 }
866                 io->read = readioport;
867                 io->write = writeioport;
868                 return 0;
869         case PcicfgSpace:
870                 if((tbdf = pciaddr(io->name)) < 0){
871                         print("amlmapio: no address\n");
872                         break;
873                 }
874                 if((pdev = pcimatchtbdf(tbdf)) == nil){
875                         print("amlmapio: no device %T\n", tbdf);
876                         break;
877                 }
878                 io->aux = pdev;
879                 io->read = readpcicfg;
880                 io->write = writepcicfg;
881                 return 0;
882         }
883         print("amlmapio: mapping %N failed\n", io->name);
884         return -1;
885 }
886
887 void
888 amlunmapio(Amlio *io)
889 {
890         switch(io->space){
891         case MemSpace:
892                 vunmap(io->va, io->len);
893                 break;
894         case IoSpace:
895                 iofree(io->off);
896                 break;
897         }
898 }
899
900 void*
901 amlalloc(int n){
902         void *p;
903
904         if((p = malloc(n)) == nil)
905                 panic("amlalloc: no memory");
906         memset(p, 0, n);
907         return p;
908 }
909
910 void
911 amlfree(void *p){
912         free(p);
913 }
914
915 void
916 amldelay(int us)
917 {
918         microdelay(us);
919 }