]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/archacpi.c
pc, pc64: implement acpi reset (for efi)
[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         if((p = amlval(x)) == nil)
264                 return -1;
265         adr = amlint(p);
266         /* if root bridge, then we are done here */
267         if(id != nil && (strcmp(id, "PNP0A03")==0 || strcmp(id, "PNP0A08")==0))
268                 return adr;
269         x = amlwalk(dot, "^");
270         if(x == nil || x == dot)
271                 return -1;
272         if((bno = pcibusno(x)) < 0)
273                 return -1;
274         tbdf = MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
275         pdev = pcimatchtbdf(tbdf);
276         if(pdev == nil)
277                 return -1;
278         if(pdev->bridge == nil)
279                 return bno;
280         return BUSBNO(pdev->bridge->tbdf);
281 }
282
283 static int
284 pciaddr(void *dot)
285 {
286         int adr, bno;
287         void *x;
288
289         for(;;){
290                 if((x = amlwalk(dot, "_ADR")) == nil){
291                         x = amlwalk(dot, "^");
292                         if(x == nil || x == dot)
293                                 break;
294                         dot = x;
295                         continue;
296                 }
297                 if((bno = pcibusno(x)) < 0)
298                         break;
299                 if((x = amlval(x)) == nil)
300                         break;
301                 adr = amlint(x);
302                 return MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
303         }
304         return -1;
305 }
306
307 static int
308 getirqs(void *d, uchar pmask[32], int *pflags)
309 {
310         int i, n, m;
311         uchar *p;
312
313         *pflags = 0;
314         memset(pmask, 0, 32);
315         if(amltag(d) != 'b')
316                 return -1;
317         p = amlval(d);
318         if(amllen(d) >= 2 && (p[0] == 0x22 || p[0] == 0x23)){
319                 pmask[0] = p[1];
320                 pmask[1] = p[2];
321                 if(amllen(d) >= 3 && p[0] == 0x23)
322                         *pflags = ((p[3] & (1<<0)) ? PcmpEDGE : PcmpLEVEL)
323                                 | ((p[3] & (1<<3)) ? PcmpLOW : PcmpHIGH);
324                 return 0;
325         }
326         if(amllen(d) >= 5 && p[0] == 0x89){
327                 n = p[4];
328                 if(amllen(d) < 5+n*4)
329                         return -1;
330                 for(i=0; i<n; i++){
331                         m = get32(p+5 + i*4);
332                         if(m >= 0 && m < 256)
333                                 pmask[m/8] |= 1<<(m%8);
334                 }
335                 *pflags = ((p[3] & (1<<1)) ? PcmpEDGE : PcmpLEVEL)
336                         | ((p[3] & (1<<2)) ? PcmpLOW : PcmpHIGH);
337                 return 0;
338         }
339         return -1;
340 }
341
342 static uchar*
343 setirq(void *d, uint irq)
344 {
345         uchar *p;
346
347         if(amltag(d) != 'b')
348                 return nil;
349         p = amlnew('b', amllen(d));
350         memmove(p, d, amllen(p));
351         if(p[0] == 0x22 || p[0] == 0x23){
352                 irq = 1<<irq;
353                 p[1] = irq;
354                 p[2] = irq>>8;
355         }
356         if(p[0] == 0x89){
357                 p[4] = 1;
358                 p[5] = irq;
359                 p[6] = irq>>8;
360                 p[7] = irq>>16;
361                 p[8] = irq>>24;
362         }
363         return p;
364 }
365
366 static int
367 setuplink(void *link, int *pflags)
368 {
369         uchar im, pm[32], cm[32], *c;
370         static int lastirq = 1;
371         int gsi, i;
372         void *r;
373
374         if(amltag(link) != 'N')
375                 return -1;
376
377         r = nil;
378         if(amleval(amlwalk(link, "_PRS"), "", &r) < 0)
379                 return -1;
380         if(getirqs(r, pm, pflags) < 0)
381                 return -1;
382
383         r = nil;
384         if(amleval(amlwalk(link, "_CRS"), "", &r) < 0)
385                 return -1;
386         if(getirqs(r, cm, pflags) < 0)
387                 return -1;
388         
389         gsi = -1;
390         for(i=0; i<256; i++){
391                 im = 1<<(i%8);
392                 if(pm[i/8] & im){
393                         if(cm[i/8] & im)
394                                 gsi = i;
395                 }
396         }
397
398         if(gsi > 0 || getconf("*nopcirouting") != nil)
399                 return gsi;
400
401         for(i=0; i<256; i++){
402                 gsi = lastirq++ & 0xFF; /* round robin */
403                 im = 1<<(gsi%8);
404                 if(pm[gsi/8] & im){
405                         if((c = setirq(r, gsi)) == nil)
406                                 break;
407                         if(amleval(amlwalk(link, "_SRS"), "b", c, nil) < 0)
408                                 break;
409                         return gsi;
410                 }
411         }
412         return -1;
413 }
414
415 static int
416 enumprt(void *dot, void *)
417 {
418         void *p, **a, **b;
419         int bno, dno, pin, gsi, flags;
420         int n, i;
421
422         bno = pcibusno(dot);
423         if(bno < 0)
424                 return 1;
425
426         /* evalulate _PRT method */
427         p = nil;
428         if(amleval(dot, "", &p) < 0)
429                 return 1;
430         if(amltag(p) != 'p')
431                 return 1;
432
433         amltake(p);
434         n = amllen(p);
435         a = amlval(p);
436         for(i=0; i<n; i++){
437                 if(amltag(a[i]) != 'p')
438                         continue;
439                 if(amllen(a[i]) != 4)
440                         continue;
441                 flags = 0;
442                 b = amlval(a[i]);
443                 dno = amlint(b[0])>>16;
444                 pin = amlint(b[1]);
445                 gsi = amlint(b[3]);
446                 if(gsi==0){
447                         gsi = setuplink(b[2], &flags);
448                         if(gsi <= 0)
449                                 continue;
450                 }
451                 addirq(gsi, BusPCI, bno, (dno<<2)|pin, flags);
452         }
453         amldrop(p);
454
455         return 1;
456 }
457
458 static void
459 acpiinit(void)
460 {
461         Tbl *t;
462         Apic *a;
463         void *va;
464         uchar *s, *p, *e;
465         ulong lapicbase;
466         int machno, i, c;
467
468         maptables();
469
470         amlinit();
471
472         /* load DSDT */
473         for(i=0; i<ntblmap; i++){
474                 t = tblmap[i];
475                 if(memcmp(t->sig, "DSDT", 4) == 0){
476                         amlload(t->data, tbldlen(t));
477                         break;
478                 }
479         }
480
481         /* load SSDT, there can be multiple tables */
482         for(i=0; i<ntblmap; i++){
483                 t = tblmap[i];
484                 if(memcmp(t->sig, "SSDT", 4) == 0)
485                         amlload(t->data, tbldlen(t));
486         }
487
488         /* set APIC mode */
489         amleval(amlwalk(amlroot, "_PIC"), "i", 1, nil);
490
491         for(i=0; i<ntblmap; i++){
492                 t = tblmap[i];
493                 if(memcmp(t->sig, "APIC", 4) == 0)
494                         goto Foundapic;
495         }
496         panic("acpiinit: no MADT (APIC) table");
497         return;
498
499 Foundapic:
500         s = t->data;
501         e = s + tbldlen(t);
502         lapicbase = get32(s); s += 8;
503         va = vmap(lapicbase, 1024);
504         print("LAPIC: %.8lux %#p\n", lapicbase, va);
505         if(va == nil)
506                 panic("acpiinit: cannot map lapic %.8lux", lapicbase);
507
508         machno = 0;
509         for(p = s; p < e; p += c){
510                 c = p[1];
511                 if(c < 2 || (p+c) > e)
512                         break;
513                 switch(*p){
514                 case 0x00:      /* Processor Local APIC */
515                         if(p[3] > MaxAPICNO)
516                                 break;
517                         if((a = xalloc(sizeof(Apic))) == nil)
518                                 panic("acpiinit: no memory for Apic");
519                         a->type = PcmpPROCESSOR;
520                         a->apicno = p[3];
521                         a->paddr = lapicbase;
522                         a->addr = va;
523                         a->lintr[0] = ApicIMASK;
524                         a->lintr[1] = ApicIMASK;
525                         a->flags = p[4] & PcmpEN;
526
527                         /* skip disabled processors */
528                         if((a->flags & PcmpEN) == 0 || mpapic[a->apicno] != nil){
529                                 xfree(a);
530                                 break;
531                         }
532                         a->machno = machno++;
533
534                         /*
535                          * platform firmware should list the boot processor
536                          * as the first processor entry in the MADT
537                          */
538                         if(a->machno == 0)
539                                 a->flags |= PcmpBP;
540
541                         mpapic[a->apicno] = a;
542                         break;
543                 case 0x01:      /* I/O APIC */
544                         if(p[2] > MaxAPICNO)
545                                 break;
546                         if((a = xalloc(sizeof(Apic))) == nil)
547                                 panic("acpiinit: no memory for io Apic");
548                         a->type = PcmpIOAPIC;
549                         a->apicno = p[2];
550                         a->paddr = get32(p+4);
551                         if((a->addr = vmap(a->paddr, 1024)) == nil)
552                                 panic("acpiinit: cannot map ioapic %.8lux", a->paddr);
553                         a->gsibase = get32(p+8);
554                         a->flags = PcmpEN;
555                         mpioapic[a->apicno] = a;
556                         ioapicinit(a, a->apicno);
557                         break;
558                 }
559         }
560
561         /*
562          * need 2nd pass as vbox puts interrupt overrides
563          * *before* the ioapic entries (!)
564          */
565         for(p = s; p < e; p += c){
566                 c = p[1];
567                 if(c < 2 || (p+c) > e)
568                         break;
569                 switch(*p){
570                 case 0x02:      /* Interrupt Source Override */
571                         addirq(get32(p+4), BusISA, 0, p[3], get16(p+8));
572                         break;
573                 case 0x03:      /* NMI Source */
574                 case 0x04:      /* Local APIC NMI */
575                 case 0x05:      /* Local APIC Address Override */
576                 case 0x06:      /* I/O SAPIC */
577                 case 0x07:      /* Local SAPIC */
578                 case 0x08:      /* Platform Interrupt Sources */
579                 case 0x09:      /* Processor Local x2APIC */
580                 case 0x0A:      /* x2APIC NMI */
581                 case 0x0B:      /* GIC */
582                 case 0x0C:      /* GICD */
583                         break;
584                 }
585         }
586
587         /* look for PCI interrupt mappings */
588         amlenum(amlroot, "_PRT", enumprt, nil);
589
590         /* add identity mapped legacy isa interrupts */
591         for(i=0; i<16; i++)
592                 addirq(i, BusISA, 0, i, 0);
593
594         /* free the AML interpreter */
595         amlexit();
596
597         /*
598          * Ininitalize local APIC and start application processors.
599          */
600         mpinit();
601 }
602
603 static int identify(void);
604
605 PCArch archacpi = {
606 .id=            "ACPI", 
607 .ident=         identify,
608 .reset=         mpshutdown,
609 .intrinit=      acpiinit,
610 .intrenable=    mpintrenable,
611 .intron=        lapicintron,
612 .introff=       lapicintroff,
613 .fastclock=     i8253read,
614 .timerset=      lapictimerset,
615 };
616
617 static long
618 readtbls(Chan*, void *v, long n, vlong o)
619 {
620         int i, l, m;
621         uchar *p;
622         Tbl *t;
623
624         maptables();
625
626         p = v;
627         for(i=0; n > 0 && i < ntblmap; i++){
628                 t = tblmap[i];
629                 l = get32(t->len);
630                 if(o >= l){
631                         o -= l;
632                         continue;
633                 }
634                 m = l - o;
635                 if(m > n)
636                         m = n;
637                 memmove(p, (uchar*)t + o, m);
638                 p += m;
639                 n -= m;
640                 o = 0;
641         }
642         return p - (uchar*)v;
643 }
644
645 static int
646 identify(void)
647 {
648         uintptr pa;
649         char *cp;
650
651         if((cp = getconf("*acpi")) == nil)
652                 return 1;
653         pa = (uintptr)strtoull(cp, nil, 16);
654         if(pa <= 1)
655                 rsd = sigsearch("RSD PTR ");
656         else
657                 rsd = vmap(pa, sizeof(Rsd));
658         if(rsd == nil)
659                 return 1;
660         if(checksum(rsd, 20) && checksum(rsd, 36))
661                 return 1;
662         addarchfile("acpitbls", 0444, readtbls, nil);
663         if(strcmp(cp, "0") == 0)
664                 return 1;
665         if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
666                 return 1;
667         if(m->havetsc && getconf("*notsc") == nil)
668                 archacpi.fastclock = tscticks;
669         return 0;
670 }
671
672 static int
673 readpcicfg(Amlio *io, void *data, int n, int offset)
674 {
675         ulong r, x;
676         Pcidev *p;
677         uchar *a;
678         int i;
679
680         a = data;
681         p = io->aux;
682         if(p == nil)
683                 return -1;
684         offset += io->off;
685         if(offset > 256)
686                 return 0;
687         if(n+offset > 256)
688                 n = 256-offset;
689         r = offset;
690         if(!(r & 3) && n == 4){
691                 x = pcicfgr32(p, r);
692                 PBIT32(a, x);
693                 return 4;
694         }
695         if(!(r & 1) && n == 2){
696                 x = pcicfgr16(p, r);
697                 PBIT16(a, x);
698                 return 2;
699         }
700         for(i = 0; i <  n; i++){
701                 x = pcicfgr8(p, r);
702                 PBIT8(a, x);
703                 a++;
704                 r++;
705         }
706         return i;
707 }
708
709 static int
710 writepcicfg(Amlio *io, void *data, int n, int offset)
711 {
712         ulong r, x;
713         Pcidev *p;
714         uchar *a;
715         int i;
716
717         a = data;
718         p = io->aux;
719         if(p == nil)
720                 return -1;
721         offset += io->off;
722         if(offset > 256)
723                 return 0;
724         if(n+offset > 256)
725                 n = 256-offset;
726         r = offset;
727         if(!(r & 3) && n == 4){
728                 x = GBIT32(a);
729                 pcicfgw32(p, r, x);
730                 return 4;
731         }
732         if(!(r & 1) && n == 2){
733                 x = GBIT16(a);
734                 pcicfgw16(p, r, x);
735                 return 2;
736         }
737         for(i = 0; i <  n; i++){
738                 x = GBIT8(a);
739                 pcicfgw8(p, r, x);
740                 a++;
741                 r++;
742         }
743         return i;
744 }
745
746 static int
747 readioport(Amlio *io, void *data, int len, int port)
748 {
749         uchar *a;
750
751         a = data;
752         port += io->off;
753         switch(len){
754         case 4:
755                 PBIT32(a, inl(port));
756                 return 4;
757         case 2:
758                 PBIT16(a, ins(port));
759                 return 2;
760         case 1:
761                 PBIT8(a, inb(port));
762                 return 1;
763         }
764         return -1;
765 }
766
767 static int
768 writeioport(Amlio *io, void *data, int len, int port)
769 {
770         uchar *a;
771
772         a = data;
773         port += io->off;
774         switch(len){
775         case 4:
776                 outl(port, GBIT32(a));
777                 return 4;
778         case 2:
779                 outs(port, GBIT16(a));
780                 return 2;
781         case 1:
782                 outb(port, GBIT8(a));
783                 return 1;
784         }
785         return -1;
786 }
787
788 int
789 amlmapio(Amlio *io)
790 {
791         int tbdf;
792         Pcidev *pdev;
793         char buf[64];
794
795         switch(io->space){
796         default:
797                 print("amlmapio: address space %x not implemented\n", io->space);
798                 break;
799         case MemSpace:
800                 if((io->va = vmap(io->off, io->len)) == nil){
801                         print("amlmapio: vmap failed\n");
802                         break;
803                 }
804                 return 0;
805         case IoSpace:
806                 snprint(buf, sizeof(buf), "%N", io->name);
807                 if(ioalloc(io->off, io->len, 0, buf) < 0){
808                         print("amlmapio: ioalloc failed\n");
809                         break;
810                 }
811                 io->read = readioport;
812                 io->write = writeioport;
813                 return 0;
814         case PcicfgSpace:
815                 if((tbdf = pciaddr(io->name)) < 0){
816                         print("amlmapio: no address\n");
817                         break;
818                 }
819                 if((pdev = pcimatchtbdf(tbdf)) == nil){
820                         print("amlmapio: no device %T\n", tbdf);
821                         break;
822                 }
823                 io->aux = pdev;
824                 io->read = readpcicfg;
825                 io->write = writepcicfg;
826                 return 0;
827         }
828         print("amlmapio: mapping %N failed\n", io->name);
829         return -1;
830 }
831
832 void
833 amlunmapio(Amlio *io)
834 {
835         switch(io->space){
836         case MemSpace:
837                 vunmap(io->va, io->len);
838                 break;
839         case IoSpace:
840                 iofree(io->off);
841                 break;
842         }
843 }
844
845 void*
846 amlalloc(int n){
847         void *p;
848
849         if((p = malloc(n)) == nil)
850                 panic("amlalloc: no memory");
851         memset(p, 0, n);
852         return p;
853 }
854
855 void
856 amlfree(void *p){
857         free(p);
858 }
859
860 void
861 amldelay(int us)
862 {
863         microdelay(us);
864 }
865
866 /*
867  * reset machine by writing acpi reset register.
868  */
869 void
870 acpireset(void)
871 {
872         uchar *p;
873         Tbl *t;
874         int i;
875
876         for(i=0; i < ntblmap; i++){
877                 t = tblmap[i];
878                 if(memcmp(t->sig, "FACP", 4) != 0)
879                         continue;
880                 if(get32(t->len) <= 128)
881                         break;
882                 p = (uchar*)t;
883                 if((get32(p + 112) & (1<<10)) == 0)
884                         break;
885                 if(p[116+0] != IoSpace)
886                         break;
887                 outb(get32(p+116+4), p[128]);
888                 break;
889         }
890 }