1780 lines · 35.4 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"../port/error.h"#include "mp.h"#include "acpi.h" /* * ACPI 4.0 Support. * Still WIP. * * This driver locates tables and parses only the FADT * and the XSDT. All other tables are mapped and kept there * for the user-level interpreter. */  #define l16get(p)	(((p)[1]<<8)|(p)[0])#define l32get(p)	(((u32int)l16get(p+2)<<16)|l16get(p))static Atable* acpifadt(uchar*, int);static Atable* acpitable(uchar*, int);static Atable* acpimadt(uchar*, int);static Atable* acpimsct(uchar*, int);static Atable* acpisrat(uchar*, int);static Atable* acpimcfg(uchar*, int);static Atable* acpihpet(uchar*, int); #pragma	varargck	type	"G"	Gas* static Cmdtab ctls[] ={	{CMregion,	"region",	6},	{CMgpe,		"gpe",		3},}; static Dirtab acpidir[]={	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555,	"acpictl",	{Qctl},			0,	0666,	"acpitbl",	{Qtbl},			0,	0444,	"acpiregio",	{Qio},			0,	0666,}; /* * The DSDT is always given to the user interpreter. * Tables listed here are also loaded from the XSDT: * MSCT, MADT, and FADT are processed by us, because they are * required to do early initialization before we have user processes. * Other tables are given to the user level interpreter for * execution. */static Parse ptables[] ={	"FACP", acpifadt,	"APIC",	acpimadt,	"SRAT",	acpisrat,	"MSCT",	acpimsct,	"SSDT", acpitable,	"MCFG",	acpimcfg,	"HPET",	acpihpet,}; static Facs*	facs;	/* Firmware ACPI control structure */static Fadt	fadt;	/* Fixed ACPI description. To reach ACPI registers */static Xsdt*	xsdt;	/* XSDT table */static Atable*	tfirst;	/* loaded DSDT/SSDT/... tables */static Atable*	tlast;	/* pointer to last table */	Madt*	apics;	/* APIC info */static Srat*	srat;	/* System resource affinity, used by physalloc */static Msct*	msct;	/* Maximum system characteristics table */static Reg*	reg;	/* region used for I/O */static Gpe*	gpes;	/* General purpose events */static int	ngpes; static char* regnames[] = {	"mem", "io", "pcicfg", "embed",	"smb", "cmos", "pcibar",}; static char*acpiregstr(int id){	static char buf[20];	/* BUG */ 	if(id >= 0 && id < nelem(regnames))		return regnames[id];	seprint(buf, buf+sizeof(buf), "spc:%#x", id);	return buf;} static intacpiregid(char *s){	int i; 	for(i = 0; i < nelem(regnames); i++)		if(strcmp(regnames[i], s) == 0)			return i;	return -1;} static u64intl64get(u8int* p){	/*	 * Doing this as a define	 * #define l64get(p)	(((u64int)l32get(p+4)<<32)|l32get(p))	 * causes 8c to abort with "out of fixed registers" in	 * rsdlink() below.	 */	return (((u64int)l32get(p+4)<<32)|l32get(p));} static u8intmget8(uintptr p, void*){	u8int *cp = (u8int*)p;	return *cp;} static voidmset8(uintptr p, u8int v, void*){	u8int *cp = (u8int*)p;	*cp = v;} static u16intmget16(uintptr p, void*){	u16int *cp = (u16int*)p;	return *cp;} static voidmset16(uintptr p, u16int v, void*){	u16int *cp = (u16int*)p;	*cp = v;} static u32intmget32(uintptr p, void*){	u32int *cp = (u32int*)p;	return *cp;} static voidmset32(uintptr p, u32int v, void*){	u32int *cp = (u32int*)p;	*cp = v;} static u64intmget64(uintptr p, void*){	u64int *cp = (u64int*)p;	return *cp;} static voidmset64(uintptr p, u64int v, void*){	u64int *cp = (u64int*)p;	*cp = v;} static u8intioget8(uintptr p, void*){	return inb(p);} static voidioset8(uintptr p, u8int v, void*){	outb(p, v);} static u16intioget16(uintptr p, void*){	return ins(p);} static voidioset16(uintptr p, u16int v, void*){	outs(p, v);} static u32intioget32(uintptr p, void*){	return inl(p);} static voidioset32(uintptr p, u32int v, void*){	outl(p, v);} static u8intcfgget8(uintptr p, void* r){	Reg *ro = r;	Pcidev d; 	d.tbdf = ro->tbdf;	return pcicfgr8(&d, p);} static voidcfgset8(uintptr p, u8int v, void* r){	Reg *ro = r;	Pcidev d; 	d.tbdf = ro->tbdf;	pcicfgw8(&d, p, v);} static u16intcfgget16(uintptr p, void* r){	Reg *ro = r;	Pcidev d; 	d.tbdf = ro->tbdf;	return pcicfgr16(&d, p);} static voidcfgset16(uintptr p, u16int v, void* r){	Reg *ro = r;	Pcidev d; 	d.tbdf = ro->tbdf;	pcicfgw16(&d, p, v);} static u32intcfgget32(uintptr p, void* r){	Reg *ro = r;	Pcidev d; 	d.tbdf = ro->tbdf;	return pcicfgr32(&d, p);} static voidcfgset32(uintptr p, u32int v, void* r){	Reg *ro = r;	Pcidev d; 	d.tbdf = ro->tbdf;	pcicfgw32(&d, p, v);} static Regio memio = {	nil,	mget8, mset8, mget16, mset16,	mget32, mset32, mget64, mset64}; static Regio ioio = {	nil,	ioget8, ioset8, ioget16, ioset16,	ioget32, ioset32, nil, nil}; static Regio cfgio = {	nil,	cfgget8, cfgset8, cfgget16, cfgset16,	cfgget32, cfgset32, nil, nil}; /* * Copy memory, 1/2/4/8-bytes at a time, to/from a region. */static longregcpy(Regio *dio, uintptr da, Regio *sio, uintptr sa, long len, int align){	int n, i; 	DBG("regcpy %#ullx %#ullx %#ulx %#ux\n", da, sa, len, align);	if((len%align) != 0)		print("regcpy: bug: copy not aligned. truncated\n");	n = len/align;	for(i = 0; i < n; i++){		switch(align){		case 1:			DBG("cpy8 %#p %#p\n", da, sa);			dio->set8(da, sio->get8(sa, sio->arg), dio->arg);			break;		case 2:			DBG("cpy16 %#p %#p\n", da, sa);			dio->set16(da, sio->get16(sa, sio->arg), dio->arg);			break;		case 4:			DBG("cpy32 %#p %#p\n", da, sa);			dio->set32(da, sio->get32(sa, sio->arg), dio->arg);			break;		case 8:			DBG("cpy64 %#p %#p\n", da, sa);		//	dio->set64(da, sio->get64(sa, sio->arg), dio->arg);			break;		default:			panic("regcpy: align bug");		}		da += align;		sa += align;	}	return n*align;} /* * Perform I/O within region in access units of accsz bytes. * All units in bytes. */static longregio(Reg *r, void *p, usize len, uintptr off, int iswr){	Regio rio;	uintptr rp; 	DBG("reg%s %s %#p %#ullx %#lx sz=%d\n",		iswr ? "out" : "in", r->name, p, off, len, r->accsz);	rp = 0;	if(off + len > r->len){		print("regio: access outside limits");		len = r->len - off;	}	if(len <= 0){		print("regio: zero len\n");		return 0;	}	switch(r->spc){	case Rsysmem:print("RSYMMEM %p %ld\n", r->base, len);		if(r->p == nil)			r->p = vmap(r->base, len);		if(r->p == nil)			error("regio: vmap failed");		rp = (uintptr)r->p + off;		rio = memio;		break;	case Rsysio:		rp = r->base + off;		rio = ioio;		break;	case Rpcicfg:		rp = r->base + off;		rio = cfgio;		rio.arg = r;		break;	case Rpcibar:	case Rembed:	case Rsmbus:	case Rcmos:	case Ripmi:	case Rfixedhw:		print("regio: reg %s not supported\n", acpiregstr(r->spc));		error("region not supported");	}	if(iswr)		regcpy(&rio, rp, &memio, (uintptr)p, len, r->accsz);	else		regcpy(&memio, (uintptr)p, &rio, rp, len, r->accsz);	return len;} static Atable*newtable(uchar *p){	Atable *t;	Sdthdr *h; 	t = malloc(sizeof(Atable));	if(t == nil)		panic("no memory for more aml tables");	t->tbl = p;	h = (Sdthdr*)t->tbl;	t->is64 = h->rev >= 2;	t->dlen = l32get(h->length) - Sdthdrsz;	memmove(t->sig, h->sig, sizeof(h->sig));	t->sig[sizeof(t->sig)-1] = 0;	memmove(t->oemid, h->oemid, sizeof(h->oemid));	t->oemtblid[sizeof(t->oemtblid)-1] = 0;	memmove(t->oemtblid, h->oemtblid, sizeof(h->oemtblid));	t->oemtblid[sizeof(t->oemtblid)-1] = 0;	t->next = nil;	if(tfirst == nil)		tfirst = tlast = t;	else{		tlast->next = t;		tlast = t;	}	return t;} static void*sdtchecksum(void* addr, int len){	u8int *p, sum; 	sum = 0;	for(p = addr; len-- > 0; p++)		sum += *p;	if(sum == 0)		return addr; 	return nil;} /* * sleezy code to deal with overlapping allocations. * please remove this by either just mapping all acpi * memory (can we count on good acpi tables?), or * keeping one map at a time. */typedef struct Sdtmap Sdtmap;struct Sdtmap {	uintmem	map[150];	uint	n;};static	Sdtmap	smap; static void*findmap(uintmem pa0, uint size){	int i, o;	uintmem pa, p; 	o = pa0 - (pa0 & ~(PGSZ-1));	pa = pa0 - o;	size = ROUNDUP(size+o, PGSZ); 	if(pa+size < 1ull*MiB)		return KADDR(pa);	if(pa < 1ull*MiB)		return nil;	for(p = pa; p < pa+size; p += PGSZ){		for(i = 0; i < smap.n; i++)			if(p == smap.map[i])				break;		if(i == smap.n){			if(smap.n == nelem(smap.map))				panic("smap.map too small %d", smap.n);			if(vmap(p, PGSZ) == nil)				return nil;			smap.map[smap.n++] = p;		}	}	/* sleezy assumption, we know everything's direct mapped at KSEG2 */	return UINT2PTR(KSEG2 + pa0);} static voidsdtunmap(void *va, usize sz){	/* first cut */	USED(va, sz);} static void*sdtmap(uintmem pa, int *n, int cksum){	Sdthdr* sdt; 	sdt = findmap(pa, sizeof *sdt);	if(sdt == nil){		DBG("acpi: findmap: nil\n");		return nil;	}	*n = l32get(sdt->length); if(*n>200000){		char tsig[5];		memmove(tsig, sdt, 4);		tsig[4] = 0;		print("%s (too big %d)", tsig, *n);		return nil;} 	sdtunmap(sdt, sizeof(Sdthdr));	if((sdt = findmap(pa, *n)) == nil){		DBG("acpi: findmap: nil\n");		return nil;

Lines 1–500 of 1780.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t