]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/archacpi.c
pc, pc64: provide access to embedded controller with #P/ec file
[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 int identify(void);
629
630 PCArch archacpi = {
631 .id=            "ACPI", 
632 .ident=         identify,
633 .reset=         mpshutdown,
634 .intrinit=      acpiinit,
635 .intrenable=    mpintrenable,
636 .intron=        lapicintron,
637 .introff=       lapicintroff,
638 .fastclock=     i8253read,
639 .timerset=      lapictimerset,
640 };
641
642 static long
643 readtbls(Chan*, void *v, long n, vlong o)
644 {
645         int i, l, m;
646         uchar *p;
647         Tbl *t;
648
649         maptables();
650
651         p = v;
652         for(i=0; n > 0 && i < ntblmap; i++){
653                 t = tblmap[i];
654                 l = get32(t->len);
655                 if(o >= l){
656                         o -= l;
657                         continue;
658                 }
659                 m = l - o;
660                 if(m > n)
661                         m = n;
662                 memmove(p, (uchar*)t + o, m);
663                 p += m;
664                 n -= m;
665                 o = 0;
666         }
667         return p - (uchar*)v;
668 }
669
670 static int
671 identify(void)
672 {
673         uintptr pa;
674         char *cp;
675
676         if((cp = getconf("*acpi")) == nil)
677                 return 1;
678         pa = (uintptr)strtoull(cp, nil, 16);
679         if(pa <= 1)
680                 rsd = sigsearch("RSD PTR ");
681         else
682                 rsd = vmap(pa, sizeof(Rsd));
683         if(rsd == nil)
684                 return 1;
685         if(checksum(rsd, 20) && checksum(rsd, 36))
686                 return 1;
687         addarchfile("acpitbls", 0444, readtbls, nil);
688         if(strcmp(cp, "0") == 0)
689                 return 1;
690         if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
691                 return 1;
692         if(m->havetsc && getconf("*notsc") == nil)
693                 archacpi.fastclock = tscticks;
694         return 0;
695 }
696
697 static int
698 readpcicfg(Amlio *io, void *data, int n, int offset)
699 {
700         ulong r, x;
701         Pcidev *p;
702         uchar *a;
703         int i;
704
705         a = data;
706         p = io->aux;
707         if(p == nil)
708                 return -1;
709         offset += io->off;
710         if(offset > 256)
711                 return 0;
712         if(n+offset > 256)
713                 n = 256-offset;
714         r = offset;
715         if(!(r & 3) && n == 4){
716                 x = pcicfgr32(p, r);
717                 PBIT32(a, x);
718                 return 4;
719         }
720         if(!(r & 1) && n == 2){
721                 x = pcicfgr16(p, r);
722                 PBIT16(a, x);
723                 return 2;
724         }
725         for(i = 0; i <  n; i++){
726                 x = pcicfgr8(p, r);
727                 PBIT8(a, x);
728                 a++;
729                 r++;
730         }
731         return i;
732 }
733
734 static int
735 writepcicfg(Amlio *io, void *data, int n, int offset)
736 {
737         ulong r, x;
738         Pcidev *p;
739         uchar *a;
740         int i;
741
742         a = data;
743         p = io->aux;
744         if(p == nil)
745                 return -1;
746         offset += io->off;
747         if(offset > 256)
748                 return 0;
749         if(n+offset > 256)
750                 n = 256-offset;
751         r = offset;
752         if(!(r & 3) && n == 4){
753                 x = GBIT32(a);
754                 pcicfgw32(p, r, x);
755                 return 4;
756         }
757         if(!(r & 1) && n == 2){
758                 x = GBIT16(a);
759                 pcicfgw16(p, r, x);
760                 return 2;
761         }
762         for(i = 0; i <  n; i++){
763                 x = GBIT8(a);
764                 pcicfgw8(p, r, x);
765                 a++;
766                 r++;
767         }
768         return i;
769 }
770
771 static int
772 readioport(Amlio *io, void *data, int len, int port)
773 {
774         uchar *a;
775
776         a = data;
777         port += io->off;
778         switch(len){
779         case 4:
780                 PBIT32(a, inl(port));
781                 return 4;
782         case 2:
783                 PBIT16(a, ins(port));
784                 return 2;
785         case 1:
786                 PBIT8(a, inb(port));
787                 return 1;
788         }
789         return -1;
790 }
791
792 static int
793 writeioport(Amlio *io, void *data, int len, int port)
794 {
795         uchar *a;
796
797         a = data;
798         port += io->off;
799         switch(len){
800         case 4:
801                 outl(port, GBIT32(a));
802                 return 4;
803         case 2:
804                 outs(port, GBIT16(a));
805                 return 2;
806         case 1:
807                 outb(port, GBIT8(a));
808                 return 1;
809         }
810         return -1;
811 }
812
813 int
814 amlmapio(Amlio *io)
815 {
816         int tbdf;
817         Pcidev *pdev;
818         char buf[64];
819
820         switch(io->space){
821         default:
822                 print("amlmapio: address space %x not implemented\n", io->space);
823                 break;
824         case MemSpace:
825                 if((io->va = vmap(io->off, io->len)) == nil){
826                         print("amlmapio: vmap failed\n");
827                         break;
828                 }
829                 return 0;
830         case IoSpace:
831                 snprint(buf, sizeof(buf), "%N", io->name);
832                 if(ioalloc(io->off, io->len, 0, buf) < 0){
833                         print("amlmapio: ioalloc failed\n");
834                         break;
835                 }
836                 io->read = readioport;
837                 io->write = writeioport;
838                 return 0;
839         case PcicfgSpace:
840                 if((tbdf = pciaddr(io->name)) < 0){
841                         print("amlmapio: no address\n");
842                         break;
843                 }
844                 if((pdev = pcimatchtbdf(tbdf)) == nil){
845                         print("amlmapio: no device %T\n", tbdf);
846                         break;
847                 }
848                 io->aux = pdev;
849                 io->read = readpcicfg;
850                 io->write = writepcicfg;
851                 return 0;
852         }
853         print("amlmapio: mapping %N failed\n", io->name);
854         return -1;
855 }
856
857 void
858 amlunmapio(Amlio *io)
859 {
860         switch(io->space){
861         case MemSpace:
862                 vunmap(io->va, io->len);
863                 break;
864         case IoSpace:
865                 iofree(io->off);
866                 break;
867         }
868 }
869
870 void*
871 amlalloc(int n){
872         void *p;
873
874         if((p = malloc(n)) == nil)
875                 panic("amlalloc: no memory");
876         memset(p, 0, n);
877         return p;
878 }
879
880 void
881 amlfree(void *p){
882         free(p);
883 }
884
885 void
886 amldelay(int us)
887 {
888         microdelay(us);
889 }
890
891 /*
892  * reset machine by writing acpi reset register.
893  */
894 void
895 acpireset(void)
896 {
897         uchar *p;
898         Tbl *t;
899         int i;
900
901         for(i=0; i < ntblmap; i++){
902                 t = tblmap[i];
903                 if(memcmp(t->sig, "FACP", 4) != 0)
904                         continue;
905                 if(get32(t->len) <= 128)
906                         break;
907                 p = (uchar*)t;
908                 if((get32(p + 112) & (1<<10)) == 0)
909                         break;
910                 if(p[116+0] != IoSpace)
911                         break;
912                 outb(get32(p+116+4), p[128]);
913                 break;
914         }
915 }