xref: /plan9-contrib/sys/src/9/kw/devarch.c (revision 7365b686ae7154552580a79fd89a0ba5dc9297c4)
1154abd99SDavid du Colombier #include "u.h"
2154abd99SDavid du Colombier #include "../port/lib.h"
3154abd99SDavid du Colombier #include "mem.h"
4154abd99SDavid du Colombier #include "dat.h"
5154abd99SDavid du Colombier #include "fns.h"
6154abd99SDavid du Colombier #include "../port/error.h"
7154abd99SDavid du Colombier #include "io.h"
8154abd99SDavid du Colombier 
9154abd99SDavid du Colombier #include "../ip/ip.h"
10154abd99SDavid du Colombier 
11154abd99SDavid du Colombier enum {
12154abd99SDavid du Colombier 	Qdir = 0,
13154abd99SDavid du Colombier 	Qbase,
14154abd99SDavid du Colombier 
15154abd99SDavid du Colombier 	Qmax = 16,
16154abd99SDavid du Colombier };
17154abd99SDavid du Colombier 
18154abd99SDavid du Colombier typedef long Rdwrfn(Chan*, void*, long, vlong);
19154abd99SDavid du Colombier 
20154abd99SDavid du Colombier static Rdwrfn *readfn[Qmax];
21154abd99SDavid du Colombier static Rdwrfn *writefn[Qmax];
22154abd99SDavid du Colombier 
23154abd99SDavid du Colombier static Dirtab archdir[Qmax] = {
24154abd99SDavid du Colombier 	".",		{ Qdir, 0, QTDIR },	0,	0555,
25154abd99SDavid du Colombier };
26154abd99SDavid du Colombier 
27154abd99SDavid du Colombier Lock archwlock;	/* the lock is only for changing archdir */
28154abd99SDavid du Colombier int narchdir = Qbase;
29154abd99SDavid du Colombier 
30154abd99SDavid du Colombier /*
31154abd99SDavid du Colombier  * Add a file to the #P listing.  Once added, you can't delete it.
32154abd99SDavid du Colombier  * You can't add a file with the same name as one already there,
33154abd99SDavid du Colombier  * and you get a pointer to the Dirtab entry so you can do things
34154abd99SDavid du Colombier  * like change the Qid version.  Changing the Qid path is disallowed.
35154abd99SDavid du Colombier  */
36154abd99SDavid du Colombier Dirtab*
addarchfile(char * name,int perm,Rdwrfn * rdfn,Rdwrfn * wrfn)37154abd99SDavid du Colombier addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
38154abd99SDavid du Colombier {
39154abd99SDavid du Colombier 	int i;
40154abd99SDavid du Colombier 	Dirtab d;
41154abd99SDavid du Colombier 	Dirtab *dp;
42154abd99SDavid du Colombier 
43154abd99SDavid du Colombier 	memset(&d, 0, sizeof d);
44154abd99SDavid du Colombier 	strcpy(d.name, name);
45154abd99SDavid du Colombier 	d.perm = perm;
46154abd99SDavid du Colombier 
47154abd99SDavid du Colombier 	lock(&archwlock);
48154abd99SDavid du Colombier 	if(narchdir >= Qmax){
49154abd99SDavid du Colombier 		unlock(&archwlock);
50154abd99SDavid du Colombier 		return nil;
51154abd99SDavid du Colombier 	}
52154abd99SDavid du Colombier 
53154abd99SDavid du Colombier 	for(i=0; i<narchdir; i++)
54154abd99SDavid du Colombier 		if(strcmp(archdir[i].name, name) == 0){
55154abd99SDavid du Colombier 			unlock(&archwlock);
56154abd99SDavid du Colombier 			return nil;
57154abd99SDavid du Colombier 		}
58154abd99SDavid du Colombier 
59154abd99SDavid du Colombier 	d.qid.path = narchdir;
60154abd99SDavid du Colombier 	archdir[narchdir] = d;
61154abd99SDavid du Colombier 	readfn[narchdir] = rdfn;
62154abd99SDavid du Colombier 	writefn[narchdir] = wrfn;
63154abd99SDavid du Colombier 	dp = &archdir[narchdir++];
64154abd99SDavid du Colombier 	unlock(&archwlock);
65154abd99SDavid du Colombier 
66154abd99SDavid du Colombier 	return dp;
67154abd99SDavid du Colombier }
68154abd99SDavid du Colombier 
69154abd99SDavid du Colombier static Chan*
archattach(char * spec)70154abd99SDavid du Colombier archattach(char* spec)
71154abd99SDavid du Colombier {
72154abd99SDavid du Colombier 	return devattach('P', spec);
73154abd99SDavid du Colombier }
74154abd99SDavid du Colombier 
75154abd99SDavid du Colombier Walkqid*
archwalk(Chan * c,Chan * nc,char ** name,int nname)76154abd99SDavid du Colombier archwalk(Chan* c, Chan *nc, char** name, int nname)
77154abd99SDavid du Colombier {
78154abd99SDavid du Colombier 	return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
79154abd99SDavid du Colombier }
80154abd99SDavid du Colombier 
81154abd99SDavid du Colombier static int
archstat(Chan * c,uchar * dp,int n)82154abd99SDavid du Colombier archstat(Chan* c, uchar* dp, int n)
83154abd99SDavid du Colombier {
84154abd99SDavid du Colombier 	return devstat(c, dp, n, archdir, narchdir, devgen);
85154abd99SDavid du Colombier }
86154abd99SDavid du Colombier 
87154abd99SDavid du Colombier static Chan*
archopen(Chan * c,int omode)88154abd99SDavid du Colombier archopen(Chan* c, int omode)
89154abd99SDavid du Colombier {
90154abd99SDavid du Colombier 	return devopen(c, omode, archdir, narchdir, devgen);
91154abd99SDavid du Colombier }
92154abd99SDavid du Colombier 
93154abd99SDavid du Colombier static void
archclose(Chan *)94154abd99SDavid du Colombier archclose(Chan*)
95154abd99SDavid du Colombier {
96154abd99SDavid du Colombier }
97154abd99SDavid du Colombier 
98154abd99SDavid du Colombier static long
archread(Chan * c,void * a,long n,vlong offset)99154abd99SDavid du Colombier archread(Chan *c, void *a, long n, vlong offset)
100154abd99SDavid du Colombier {
101154abd99SDavid du Colombier 	Rdwrfn *fn;
102154abd99SDavid du Colombier 
103154abd99SDavid du Colombier 	switch((ulong)c->qid.path){
104154abd99SDavid du Colombier 	case Qdir:
105154abd99SDavid du Colombier 		return devdirread(c, a, n, archdir, narchdir, devgen);
106154abd99SDavid du Colombier 
107154abd99SDavid du Colombier 	default:
108154abd99SDavid du Colombier 		if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
109154abd99SDavid du Colombier 			return fn(c, a, n, offset);
110154abd99SDavid du Colombier 		error(Eperm);
111154abd99SDavid du Colombier 		break;
112154abd99SDavid du Colombier 	}
113154abd99SDavid du Colombier 
114154abd99SDavid du Colombier 	return 0;
115154abd99SDavid du Colombier }
116154abd99SDavid du Colombier 
117154abd99SDavid du Colombier static long
archwrite(Chan * c,void * a,long n,vlong offset)118154abd99SDavid du Colombier archwrite(Chan *c, void *a, long n, vlong offset)
119154abd99SDavid du Colombier {
120154abd99SDavid du Colombier 	Rdwrfn *fn;
121154abd99SDavid du Colombier 
122154abd99SDavid du Colombier 	if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
123154abd99SDavid du Colombier 		return fn(c, a, n, offset);
124154abd99SDavid du Colombier 	error(Eperm);
125154abd99SDavid du Colombier 
126154abd99SDavid du Colombier 	return 0;
127154abd99SDavid du Colombier }
128154abd99SDavid du Colombier 
129154abd99SDavid du Colombier void archinit(void);
130154abd99SDavid du Colombier 
131154abd99SDavid du Colombier Dev archdevtab = {
132154abd99SDavid du Colombier 	'P',
133154abd99SDavid du Colombier 	"arch",
134154abd99SDavid du Colombier 
135154abd99SDavid du Colombier 	devreset,
136154abd99SDavid du Colombier 	archinit,
137154abd99SDavid du Colombier 	devshutdown,
138154abd99SDavid du Colombier 	archattach,
139154abd99SDavid du Colombier 	archwalk,
140154abd99SDavid du Colombier 	archstat,
141154abd99SDavid du Colombier 	archopen,
142154abd99SDavid du Colombier 	devcreate,
143154abd99SDavid du Colombier 	archclose,
144154abd99SDavid du Colombier 	archread,
145154abd99SDavid du Colombier 	devbread,
146154abd99SDavid du Colombier 	archwrite,
147154abd99SDavid du Colombier 	devbwrite,
148154abd99SDavid du Colombier 	devremove,
149154abd99SDavid du Colombier 	devwstat,
150154abd99SDavid du Colombier };
151154abd99SDavid du Colombier 
152154abd99SDavid du Colombier /* convert AddrDevid register to a string in buf and return buf */
153154abd99SDavid du Colombier char *
cputype2name(char * buf,int size)154154abd99SDavid du Colombier cputype2name(char *buf, int size)
155154abd99SDavid du Colombier {
156ec4ca6beSDavid du Colombier 	ulong id, archid, rev;
157ec4ca6beSDavid du Colombier 	char *manu, *arch, *socrev;
158*7365b686SDavid du Colombier 	char unk[32], socnm[32], revname[32];
159ec4ca6beSDavid du Colombier 	Pciex *pci;
160154abd99SDavid du Colombier 
161*7365b686SDavid du Colombier 	m->cputype = *(ulong *)soc.devid;
162ec4ca6beSDavid du Colombier #ifdef OLD
163154abd99SDavid du Colombier 	switch(m->cputype & 3) {
164154abd99SDavid du Colombier 	case 0:
165*7365b686SDavid du Colombier 		socnm = "88F6[12]80";
166154abd99SDavid du Colombier 		break;
167154abd99SDavid du Colombier 	case 1:
168*7365b686SDavid du Colombier 		socnm = "88F619[02]";
169154abd99SDavid du Colombier 		break;
170154abd99SDavid du Colombier 	case 2:
171*7365b686SDavid du Colombier 		socnm = "88F6281";
172154abd99SDavid du Colombier 		break;
173154abd99SDavid du Colombier 	default:
174*7365b686SDavid du Colombier 		socnm = "unknown";
175154abd99SDavid du Colombier 		break;
176154abd99SDavid du Colombier 	}
177ec4ca6beSDavid du Colombier #endif
178ec4ca6beSDavid du Colombier 	/* strange way to get this information, but it's what u-boot does */
179*7365b686SDavid du Colombier 	pci = (Pciex *)soc.pci;
180*7365b686SDavid du Colombier 	snprint(socnm, sizeof socnm, "88F%ux", pci->devid);
181a7a38e3eSDavid du Colombier 	/* stash rev for benefit of later usb initialisation */
182ab6ce076SDavid du Colombier 	m->socrev = rev = pci->revid & MASK(4);
183ec4ca6beSDavid du Colombier 
184ec4ca6beSDavid du Colombier 	id = cpidget();
185ec4ca6beSDavid du Colombier 	if ((id >> 24) == 0x56 && pci->venid == 0x11ab)
186ec4ca6beSDavid du Colombier 		manu = "Marvell";
187ec4ca6beSDavid du Colombier 	else
188ec4ca6beSDavid du Colombier 		manu = "unknown";
189ab6ce076SDavid du Colombier 	archid = (id >> 16) & MASK(4);
190ec4ca6beSDavid du Colombier 	switch (archid) {
191ec4ca6beSDavid du Colombier 	case 5:
192ec4ca6beSDavid du Colombier 		arch = "v5te";
193ec4ca6beSDavid du Colombier 		break;
194ec4ca6beSDavid du Colombier 	default:
195ec4ca6beSDavid du Colombier 		snprint(unk, sizeof unk, "unknown (%ld)", archid);
196ec4ca6beSDavid du Colombier 		arch = unk;
197ec4ca6beSDavid du Colombier 		break;
198ec4ca6beSDavid du Colombier 	}
199ab6ce076SDavid du Colombier 	if (pci->devid != 0x6281)
200ab6ce076SDavid du Colombier 		socrev = "unknown";
201ab6ce076SDavid du Colombier 	else
202ec4ca6beSDavid du Colombier 		switch (rev) {
203897ae9c1SDavid du Colombier 		case Socrevz0:
204ab6ce076SDavid du Colombier 			socrev = "Z0";
205ab6ce076SDavid du Colombier 			break;
206897ae9c1SDavid du Colombier 		case Socreva0:
207ec4ca6beSDavid du Colombier 			socrev = "A0";
208ec4ca6beSDavid du Colombier 			break;
209897ae9c1SDavid du Colombier 		case Socreva1:
210ab6ce076SDavid du Colombier 			socrev = "A1";
211ec4ca6beSDavid du Colombier 			break;
212ec4ca6beSDavid du Colombier 		default:
213ab6ce076SDavid du Colombier 			snprint(revname, sizeof revname, "unknown rev (%ld)",
214ab6ce076SDavid du Colombier 				rev);
215ec4ca6beSDavid du Colombier 			socrev = revname;
216ec4ca6beSDavid du Colombier 			break;
217ec4ca6beSDavid du Colombier 		}
218ec4ca6beSDavid du Colombier 	seprint(buf, buf + size,
219ec4ca6beSDavid du Colombier 		"%s %s %s; arm926ej-s arch %s rev %ld.%ld part %lux",
220*7365b686SDavid du Colombier 		manu, socnm, socrev, arch, (id >> 20) & MASK(4),
221ab6ce076SDavid du Colombier 		id & MASK(4), (id >> 4) & MASK(12));
222154abd99SDavid du Colombier 	return buf;
223154abd99SDavid du Colombier }
224154abd99SDavid du Colombier 
225154abd99SDavid du Colombier static long
cputyperead(Chan *,void * a,long n,vlong offset)226154abd99SDavid du Colombier cputyperead(Chan*, void *a, long n, vlong offset)
227154abd99SDavid du Colombier {
228154abd99SDavid du Colombier 	char name[64], str[128];
229154abd99SDavid du Colombier 
230154abd99SDavid du Colombier 	cputype2name(name, sizeof name);
231154abd99SDavid du Colombier 	snprint(str, sizeof str, "ARM %s %llud\n", name, m->cpuhz / 1000000);
232154abd99SDavid du Colombier 	return readstr(offset, a, n, str);
233154abd99SDavid du Colombier }
234154abd99SDavid du Colombier 
235154abd99SDavid du Colombier static long
tbread(Chan *,void * a,long n,vlong offset)236154abd99SDavid du Colombier tbread(Chan*, void *a, long n, vlong offset)
237154abd99SDavid du Colombier {
238154abd99SDavid du Colombier 	char str[16];
239154abd99SDavid du Colombier 	uvlong tb;
240154abd99SDavid du Colombier 
241154abd99SDavid du Colombier 	cycles(&tb);
242154abd99SDavid du Colombier 
243154abd99SDavid du Colombier 	snprint(str, sizeof(str), "%16.16llux", tb);
244154abd99SDavid du Colombier 	return readstr(offset, a, n, str);
245154abd99SDavid du Colombier }
246154abd99SDavid du Colombier 
247154abd99SDavid du Colombier static long
nsread(Chan *,void * a,long n,vlong offset)248154abd99SDavid du Colombier nsread(Chan*, void *a, long n, vlong offset)
249154abd99SDavid du Colombier {
250154abd99SDavid du Colombier 	char str[16];
251154abd99SDavid du Colombier 	uvlong tb;
252154abd99SDavid du Colombier 
253154abd99SDavid du Colombier 	cycles(&tb);
254154abd99SDavid du Colombier 
255154abd99SDavid du Colombier 	snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
256154abd99SDavid du Colombier 	return readstr(offset, a, n, str);
257154abd99SDavid du Colombier }
258154abd99SDavid du Colombier 
259154abd99SDavid du Colombier void
archinit(void)260154abd99SDavid du Colombier archinit(void)
261154abd99SDavid du Colombier {
262154abd99SDavid du Colombier 	addarchfile("cputype", 0444, cputyperead, nil);
263154abd99SDavid du Colombier 	addarchfile("timebase",0444, tbread, nil);
264154abd99SDavid du Colombier //	addarchfile("nsec", 0444, nsread, nil);
265154abd99SDavid du Colombier }
266