xref: /plan9/sys/src/9/omap/devarch.c (revision add6b5c507a81def2a34db772d748c24f818bb5b)
18e32b400SDavid du Colombier #include "u.h"
28e32b400SDavid du Colombier #include "../port/lib.h"
38e32b400SDavid du Colombier #include "mem.h"
48e32b400SDavid du Colombier #include "dat.h"
58e32b400SDavid du Colombier #include "fns.h"
68e32b400SDavid du Colombier #include "../port/error.h"
78e32b400SDavid du Colombier #include "io.h"
88e32b400SDavid du Colombier 
98e32b400SDavid du Colombier #include "../ip/ip.h"
108e32b400SDavid du Colombier 
118e32b400SDavid du Colombier enum {
128e32b400SDavid du Colombier 	Qdir = 0,
138e32b400SDavid du Colombier 	Qbase,
148e32b400SDavid du Colombier 
158e32b400SDavid du Colombier 	Qmax = 16,
168e32b400SDavid du Colombier };
178e32b400SDavid du Colombier 
188e32b400SDavid du Colombier typedef long Rdwrfn(Chan*, void*, long, vlong);
198e32b400SDavid du Colombier 
208e32b400SDavid du Colombier static Rdwrfn *readfn[Qmax];
218e32b400SDavid du Colombier static Rdwrfn *writefn[Qmax];
228e32b400SDavid du Colombier 
238e32b400SDavid du Colombier static Dirtab archdir[Qmax] = {
248e32b400SDavid du Colombier 	".",		{ Qdir, 0, QTDIR },	0,	0555,
258e32b400SDavid du Colombier };
268e32b400SDavid du Colombier 
278e32b400SDavid du Colombier Lock archwlock;	/* the lock is only for changing archdir */
288e32b400SDavid du Colombier int narchdir = Qbase;
298e32b400SDavid du Colombier 
308e32b400SDavid du Colombier /*
318e32b400SDavid du Colombier  * Add a file to the #P listing.  Once added, you can't delete it.
328e32b400SDavid du Colombier  * You can't add a file with the same name as one already there,
338e32b400SDavid du Colombier  * and you get a pointer to the Dirtab entry so you can do things
348e32b400SDavid du Colombier  * like change the Qid version.  Changing the Qid path is disallowed.
358e32b400SDavid du Colombier  */
368e32b400SDavid du Colombier Dirtab*
addarchfile(char * name,int perm,Rdwrfn * rdfn,Rdwrfn * wrfn)378e32b400SDavid du Colombier addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
388e32b400SDavid du Colombier {
398e32b400SDavid du Colombier 	int i;
408e32b400SDavid du Colombier 	Dirtab d;
418e32b400SDavid du Colombier 	Dirtab *dp;
428e32b400SDavid du Colombier 
438e32b400SDavid du Colombier 	memset(&d, 0, sizeof d);
448e32b400SDavid du Colombier 	strcpy(d.name, name);
458e32b400SDavid du Colombier 	d.perm = perm;
468e32b400SDavid du Colombier 
478e32b400SDavid du Colombier 	lock(&archwlock);
488e32b400SDavid du Colombier 	if(narchdir >= Qmax){
498e32b400SDavid du Colombier 		unlock(&archwlock);
508e32b400SDavid du Colombier 		return nil;
518e32b400SDavid du Colombier 	}
528e32b400SDavid du Colombier 
538e32b400SDavid du Colombier 	for(i=0; i<narchdir; i++)
548e32b400SDavid du Colombier 		if(strcmp(archdir[i].name, name) == 0){
558e32b400SDavid du Colombier 			unlock(&archwlock);
568e32b400SDavid du Colombier 			return nil;
578e32b400SDavid du Colombier 		}
588e32b400SDavid du Colombier 
598e32b400SDavid du Colombier 	d.qid.path = narchdir;
608e32b400SDavid du Colombier 	archdir[narchdir] = d;
618e32b400SDavid du Colombier 	readfn[narchdir] = rdfn;
628e32b400SDavid du Colombier 	writefn[narchdir] = wrfn;
638e32b400SDavid du Colombier 	dp = &archdir[narchdir++];
648e32b400SDavid du Colombier 	unlock(&archwlock);
658e32b400SDavid du Colombier 
668e32b400SDavid du Colombier 	return dp;
678e32b400SDavid du Colombier }
688e32b400SDavid du Colombier 
698e32b400SDavid du Colombier static Chan*
archattach(char * spec)708e32b400SDavid du Colombier archattach(char* spec)
718e32b400SDavid du Colombier {
728e32b400SDavid du Colombier 	return devattach('P', spec);
738e32b400SDavid du Colombier }
748e32b400SDavid du Colombier 
758e32b400SDavid du Colombier Walkqid*
archwalk(Chan * c,Chan * nc,char ** name,int nname)768e32b400SDavid du Colombier archwalk(Chan* c, Chan *nc, char** name, int nname)
778e32b400SDavid du Colombier {
788e32b400SDavid du Colombier 	return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
798e32b400SDavid du Colombier }
808e32b400SDavid du Colombier 
818e32b400SDavid du Colombier static int
archstat(Chan * c,uchar * dp,int n)828e32b400SDavid du Colombier archstat(Chan* c, uchar* dp, int n)
838e32b400SDavid du Colombier {
848e32b400SDavid du Colombier 	return devstat(c, dp, n, archdir, narchdir, devgen);
858e32b400SDavid du Colombier }
868e32b400SDavid du Colombier 
878e32b400SDavid du Colombier static Chan*
archopen(Chan * c,int omode)888e32b400SDavid du Colombier archopen(Chan* c, int omode)
898e32b400SDavid du Colombier {
908e32b400SDavid du Colombier 	return devopen(c, omode, archdir, narchdir, devgen);
918e32b400SDavid du Colombier }
928e32b400SDavid du Colombier 
938e32b400SDavid du Colombier static void
archclose(Chan *)948e32b400SDavid du Colombier archclose(Chan*)
958e32b400SDavid du Colombier {
968e32b400SDavid du Colombier }
978e32b400SDavid du Colombier 
988e32b400SDavid du Colombier static long
archread(Chan * c,void * a,long n,vlong offset)998e32b400SDavid du Colombier archread(Chan *c, void *a, long n, vlong offset)
1008e32b400SDavid du Colombier {
1018e32b400SDavid du Colombier 	Rdwrfn *fn;
1028e32b400SDavid du Colombier 
1038e32b400SDavid du Colombier 	switch((ulong)c->qid.path){
1048e32b400SDavid du Colombier 	case Qdir:
1058e32b400SDavid du Colombier 		return devdirread(c, a, n, archdir, narchdir, devgen);
1068e32b400SDavid du Colombier 
1078e32b400SDavid du Colombier 	default:
1088e32b400SDavid du Colombier 		if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
1098e32b400SDavid du Colombier 			return fn(c, a, n, offset);
1108e32b400SDavid du Colombier 		error(Eperm);
1118e32b400SDavid du Colombier 		break;
1128e32b400SDavid du Colombier 	}
1138e32b400SDavid du Colombier 
1148e32b400SDavid du Colombier 	return 0;
1158e32b400SDavid du Colombier }
1168e32b400SDavid du Colombier 
1178e32b400SDavid du Colombier static long
archwrite(Chan * c,void * a,long n,vlong offset)1188e32b400SDavid du Colombier archwrite(Chan *c, void *a, long n, vlong offset)
1198e32b400SDavid du Colombier {
1208e32b400SDavid du Colombier 	Rdwrfn *fn;
1218e32b400SDavid du Colombier 
1228e32b400SDavid du Colombier 	if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
1238e32b400SDavid du Colombier 		return fn(c, a, n, offset);
1248e32b400SDavid du Colombier 	error(Eperm);
1258e32b400SDavid du Colombier 
1268e32b400SDavid du Colombier 	return 0;
1278e32b400SDavid du Colombier }
1288e32b400SDavid du Colombier 
1298e32b400SDavid du Colombier void archinit(void);
1308e32b400SDavid du Colombier 
1318e32b400SDavid du Colombier Dev archdevtab = {
1328e32b400SDavid du Colombier 	'P',
1338e32b400SDavid du Colombier 	"arch",
1348e32b400SDavid du Colombier 
1358e32b400SDavid du Colombier 	devreset,
1368e32b400SDavid du Colombier 	archinit,
1378e32b400SDavid du Colombier 	devshutdown,
1388e32b400SDavid du Colombier 	archattach,
1398e32b400SDavid du Colombier 	archwalk,
1408e32b400SDavid du Colombier 	archstat,
1418e32b400SDavid du Colombier 	archopen,
1428e32b400SDavid du Colombier 	devcreate,
1438e32b400SDavid du Colombier 	archclose,
1448e32b400SDavid du Colombier 	archread,
1458e32b400SDavid du Colombier 	devbread,
1468e32b400SDavid du Colombier 	archwrite,
1478e32b400SDavid du Colombier 	devbwrite,
1488e32b400SDavid du Colombier 	devremove,
1498e32b400SDavid du Colombier 	devwstat,
1508e32b400SDavid du Colombier };
1518e32b400SDavid du Colombier 
1528e32b400SDavid du Colombier /* convert AddrDevid register to a string in buf and return buf */
1538e32b400SDavid du Colombier char *
cputype2name(char * buf,int size)1548e32b400SDavid du Colombier cputype2name(char *buf, int size)
1558e32b400SDavid du Colombier {
1568e32b400SDavid du Colombier 	seprint(buf, buf + size, "Cortex-A8");
1578e32b400SDavid du Colombier 	return buf;
1588e32b400SDavid du Colombier }
1598e32b400SDavid du Colombier 
1608e32b400SDavid du Colombier static long
cputyperead(Chan *,void * a,long n,vlong offset)1618e32b400SDavid du Colombier cputyperead(Chan*, void *a, long n, vlong offset)
1628e32b400SDavid du Colombier {
1638e32b400SDavid du Colombier 	char name[64], str[128];
1648e32b400SDavid du Colombier 
1658e32b400SDavid du Colombier 	cputype2name(name, sizeof name);
166*df2dbabfSDavid du Colombier 	snprint(str, sizeof str, "ARM %s %llud\n", name, m->cpuhz / Mhz);
1678e32b400SDavid du Colombier 	return readstr(offset, a, n, str);
1688e32b400SDavid du Colombier }
1698e32b400SDavid du Colombier 
1708e32b400SDavid du Colombier static long
tbread(Chan *,void * a,long n,vlong offset)1718e32b400SDavid du Colombier tbread(Chan*, void *a, long n, vlong offset)
1728e32b400SDavid du Colombier {
1738e32b400SDavid du Colombier 	char str[16];
1748e32b400SDavid du Colombier 	uvlong tb;
1758e32b400SDavid du Colombier 
1768e32b400SDavid du Colombier 	cycles(&tb);
1778e32b400SDavid du Colombier 
1788e32b400SDavid du Colombier 	snprint(str, sizeof(str), "%16.16llux", tb);
1798e32b400SDavid du Colombier 	return readstr(offset, a, n, str);
1808e32b400SDavid du Colombier }
1818e32b400SDavid du Colombier 
1828e32b400SDavid du Colombier static long
nsread(Chan *,void * a,long n,vlong offset)1838e32b400SDavid du Colombier nsread(Chan*, void *a, long n, vlong offset)
1848e32b400SDavid du Colombier {
1858e32b400SDavid du Colombier 	char str[16];
1868e32b400SDavid du Colombier 	uvlong tb;
1878e32b400SDavid du Colombier 
1888e32b400SDavid du Colombier 	cycles(&tb);
1898e32b400SDavid du Colombier 
1908e32b400SDavid du Colombier 	snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
1918e32b400SDavid du Colombier 	return readstr(offset, a, n, str);
1928e32b400SDavid du Colombier }
1938e32b400SDavid du Colombier 
1948e32b400SDavid du Colombier void
archinit(void)1958e32b400SDavid du Colombier archinit(void)
1968e32b400SDavid du Colombier {
1978e32b400SDavid du Colombier 	addarchfile("cputype", 0444, cputyperead, nil);
1988e32b400SDavid du Colombier 	addarchfile("timebase",0444, tbread, nil);
1998e32b400SDavid du Colombier //	addarchfile("nsec", 0444, nsread, nil);
2008e32b400SDavid du Colombier }
201