1*d6dfd9efSDavid du Colombier #include "u.h"
2*d6dfd9efSDavid du Colombier #include "../port/lib.h"
3*d6dfd9efSDavid du Colombier #include "mem.h"
4*d6dfd9efSDavid du Colombier #include "dat.h"
5*d6dfd9efSDavid du Colombier #include "fns.h"
6*d6dfd9efSDavid du Colombier #include "../port/error.h"
7*d6dfd9efSDavid du Colombier
8*d6dfd9efSDavid du Colombier #include "../ip/ip.h"
9*d6dfd9efSDavid du Colombier
10*d6dfd9efSDavid du Colombier enum {
11*d6dfd9efSDavid du Colombier Qdir = 0,
12*d6dfd9efSDavid du Colombier Qbase,
13*d6dfd9efSDavid du Colombier
14*d6dfd9efSDavid du Colombier Qmax = 16,
15*d6dfd9efSDavid du Colombier };
16*d6dfd9efSDavid du Colombier
17*d6dfd9efSDavid du Colombier typedef long Rdwrfn(Chan*, void*, long, vlong);
18*d6dfd9efSDavid du Colombier
19*d6dfd9efSDavid du Colombier static Rdwrfn *readfn[Qmax];
20*d6dfd9efSDavid du Colombier static Rdwrfn *writefn[Qmax];
21*d6dfd9efSDavid du Colombier
22*d6dfd9efSDavid du Colombier static Dirtab archdir[Qmax] = {
23*d6dfd9efSDavid du Colombier ".", { Qdir, 0, QTDIR }, 0, 0555,
24*d6dfd9efSDavid du Colombier };
25*d6dfd9efSDavid du Colombier
26*d6dfd9efSDavid du Colombier Lock archwlock; /* the lock is only for changing archdir */
27*d6dfd9efSDavid du Colombier int narchdir = Qbase;
28*d6dfd9efSDavid du Colombier
29*d6dfd9efSDavid du Colombier /*
30*d6dfd9efSDavid du Colombier * Add a file to the #P listing. Once added, you can't delete it.
31*d6dfd9efSDavid du Colombier * You can't add a file with the same name as one already there,
32*d6dfd9efSDavid du Colombier * and you get a pointer to the Dirtab entry so you can do things
33*d6dfd9efSDavid du Colombier * like change the Qid version. Changing the Qid path is disallowed.
34*d6dfd9efSDavid du Colombier */
35*d6dfd9efSDavid du Colombier Dirtab*
addarchfile(char * name,int perm,Rdwrfn * rdfn,Rdwrfn * wrfn)36*d6dfd9efSDavid du Colombier addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
37*d6dfd9efSDavid du Colombier {
38*d6dfd9efSDavid du Colombier int i;
39*d6dfd9efSDavid du Colombier Dirtab d;
40*d6dfd9efSDavid du Colombier Dirtab *dp;
41*d6dfd9efSDavid du Colombier
42*d6dfd9efSDavid du Colombier memset(&d, 0, sizeof d);
43*d6dfd9efSDavid du Colombier strcpy(d.name, name);
44*d6dfd9efSDavid du Colombier d.perm = perm;
45*d6dfd9efSDavid du Colombier
46*d6dfd9efSDavid du Colombier lock(&archwlock);
47*d6dfd9efSDavid du Colombier if(narchdir >= Qmax){
48*d6dfd9efSDavid du Colombier unlock(&archwlock);
49*d6dfd9efSDavid du Colombier return nil;
50*d6dfd9efSDavid du Colombier }
51*d6dfd9efSDavid du Colombier
52*d6dfd9efSDavid du Colombier for(i=0; i<narchdir; i++)
53*d6dfd9efSDavid du Colombier if(strcmp(archdir[i].name, name) == 0){
54*d6dfd9efSDavid du Colombier unlock(&archwlock);
55*d6dfd9efSDavid du Colombier return nil;
56*d6dfd9efSDavid du Colombier }
57*d6dfd9efSDavid du Colombier
58*d6dfd9efSDavid du Colombier d.qid.path = narchdir;
59*d6dfd9efSDavid du Colombier archdir[narchdir] = d;
60*d6dfd9efSDavid du Colombier readfn[narchdir] = rdfn;
61*d6dfd9efSDavid du Colombier writefn[narchdir] = wrfn;
62*d6dfd9efSDavid du Colombier dp = &archdir[narchdir++];
63*d6dfd9efSDavid du Colombier unlock(&archwlock);
64*d6dfd9efSDavid du Colombier
65*d6dfd9efSDavid du Colombier return dp;
66*d6dfd9efSDavid du Colombier }
67*d6dfd9efSDavid du Colombier
68*d6dfd9efSDavid du Colombier static Chan*
archattach(char * spec)69*d6dfd9efSDavid du Colombier archattach(char* spec)
70*d6dfd9efSDavid du Colombier {
71*d6dfd9efSDavid du Colombier return devattach('P', spec);
72*d6dfd9efSDavid du Colombier }
73*d6dfd9efSDavid du Colombier
74*d6dfd9efSDavid du Colombier Walkqid*
archwalk(Chan * c,Chan * nc,char ** name,int nname)75*d6dfd9efSDavid du Colombier archwalk(Chan* c, Chan *nc, char** name, int nname)
76*d6dfd9efSDavid du Colombier {
77*d6dfd9efSDavid du Colombier return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
78*d6dfd9efSDavid du Colombier }
79*d6dfd9efSDavid du Colombier
80*d6dfd9efSDavid du Colombier static int
archstat(Chan * c,uchar * dp,int n)81*d6dfd9efSDavid du Colombier archstat(Chan* c, uchar* dp, int n)
82*d6dfd9efSDavid du Colombier {
83*d6dfd9efSDavid du Colombier return devstat(c, dp, n, archdir, narchdir, devgen);
84*d6dfd9efSDavid du Colombier }
85*d6dfd9efSDavid du Colombier
86*d6dfd9efSDavid du Colombier static Chan*
archopen(Chan * c,int omode)87*d6dfd9efSDavid du Colombier archopen(Chan* c, int omode)
88*d6dfd9efSDavid du Colombier {
89*d6dfd9efSDavid du Colombier return devopen(c, omode, archdir, narchdir, devgen);
90*d6dfd9efSDavid du Colombier }
91*d6dfd9efSDavid du Colombier
92*d6dfd9efSDavid du Colombier static void
archclose(Chan *)93*d6dfd9efSDavid du Colombier archclose(Chan*)
94*d6dfd9efSDavid du Colombier {
95*d6dfd9efSDavid du Colombier }
96*d6dfd9efSDavid du Colombier
97*d6dfd9efSDavid du Colombier static long
archread(Chan * c,void * a,long n,vlong offset)98*d6dfd9efSDavid du Colombier archread(Chan *c, void *a, long n, vlong offset)
99*d6dfd9efSDavid du Colombier {
100*d6dfd9efSDavid du Colombier Rdwrfn *fn;
101*d6dfd9efSDavid du Colombier
102*d6dfd9efSDavid du Colombier switch((ulong)c->qid.path){
103*d6dfd9efSDavid du Colombier case Qdir:
104*d6dfd9efSDavid du Colombier return devdirread(c, a, n, archdir, narchdir, devgen);
105*d6dfd9efSDavid du Colombier
106*d6dfd9efSDavid du Colombier default:
107*d6dfd9efSDavid du Colombier if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
108*d6dfd9efSDavid du Colombier return fn(c, a, n, offset);
109*d6dfd9efSDavid du Colombier error(Eperm);
110*d6dfd9efSDavid du Colombier break;
111*d6dfd9efSDavid du Colombier }
112*d6dfd9efSDavid du Colombier
113*d6dfd9efSDavid du Colombier return 0;
114*d6dfd9efSDavid du Colombier }
115*d6dfd9efSDavid du Colombier
116*d6dfd9efSDavid du Colombier static long
archwrite(Chan * c,void * a,long n,vlong offset)117*d6dfd9efSDavid du Colombier archwrite(Chan *c, void *a, long n, vlong offset)
118*d6dfd9efSDavid du Colombier {
119*d6dfd9efSDavid du Colombier Rdwrfn *fn;
120*d6dfd9efSDavid du Colombier
121*d6dfd9efSDavid du Colombier if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
122*d6dfd9efSDavid du Colombier return fn(c, a, n, offset);
123*d6dfd9efSDavid du Colombier error(Eperm);
124*d6dfd9efSDavid du Colombier
125*d6dfd9efSDavid du Colombier return 0;
126*d6dfd9efSDavid du Colombier }
127*d6dfd9efSDavid du Colombier
128*d6dfd9efSDavid du Colombier Dev archdevtab = {
129*d6dfd9efSDavid du Colombier 'P',
130*d6dfd9efSDavid du Colombier "arch",
131*d6dfd9efSDavid du Colombier
132*d6dfd9efSDavid du Colombier devreset,
133*d6dfd9efSDavid du Colombier archinit,
134*d6dfd9efSDavid du Colombier devshutdown,
135*d6dfd9efSDavid du Colombier archattach,
136*d6dfd9efSDavid du Colombier archwalk,
137*d6dfd9efSDavid du Colombier archstat,
138*d6dfd9efSDavid du Colombier archopen,
139*d6dfd9efSDavid du Colombier devcreate,
140*d6dfd9efSDavid du Colombier archclose,
141*d6dfd9efSDavid du Colombier archread,
142*d6dfd9efSDavid du Colombier devbread,
143*d6dfd9efSDavid du Colombier archwrite,
144*d6dfd9efSDavid du Colombier devbwrite,
145*d6dfd9efSDavid du Colombier devremove,
146*d6dfd9efSDavid du Colombier devwstat,
147*d6dfd9efSDavid du Colombier };
148*d6dfd9efSDavid du Colombier
149*d6dfd9efSDavid du Colombier /* convert m->cputype and pvr register to a string in buf and return buf */
150*d6dfd9efSDavid du Colombier char *
cputype2name(char * buf,int size)151*d6dfd9efSDavid du Colombier cputype2name(char *buf, int size)
152*d6dfd9efSDavid du Colombier {
153*d6dfd9efSDavid du Colombier char *s, *es;
154*d6dfd9efSDavid du Colombier ulong cputype = getpvr();
155*d6dfd9efSDavid du Colombier
156*d6dfd9efSDavid du Colombier s = buf;
157*d6dfd9efSDavid du Colombier es = buf + size;
158*d6dfd9efSDavid du Colombier /* ignoring 460, 8xx & 8xxx, e200*, e500* */
159*d6dfd9efSDavid du Colombier switch (m->cputype) {
160*d6dfd9efSDavid du Colombier case 1:
161*d6dfd9efSDavid du Colombier seprint(s, es, "601");
162*d6dfd9efSDavid du Colombier break;
163*d6dfd9efSDavid du Colombier case 3: case 6: case 7:
164*d6dfd9efSDavid du Colombier seprint(s, es, "603");
165*d6dfd9efSDavid du Colombier break;
166*d6dfd9efSDavid du Colombier case 4: case 9: case 0xa:
167*d6dfd9efSDavid du Colombier seprint(s, es, "604");
168*d6dfd9efSDavid du Colombier break;
169*d6dfd9efSDavid du Colombier case 8: case 0x7000: case 0x7002:
170*d6dfd9efSDavid du Colombier seprint(s, es, "G3 7xx");
171*d6dfd9efSDavid du Colombier break;
172*d6dfd9efSDavid du Colombier case 0x000c: case 0x800c: case 0x8000: case 0x8001:
173*d6dfd9efSDavid du Colombier case 0x8002: case 0x8003: case 0x8004:
174*d6dfd9efSDavid du Colombier seprint(s, es, "G4 74xx");
175*d6dfd9efSDavid du Colombier break;
176*d6dfd9efSDavid du Colombier case 0x39: case 0x3c:
177*d6dfd9efSDavid du Colombier seprint(s, es, "G5 970");
178*d6dfd9efSDavid du Colombier break;
179*d6dfd9efSDavid du Colombier case 0x20:
180*d6dfd9efSDavid du Colombier seprint(s, es, "403");
181*d6dfd9efSDavid du Colombier break;
182*d6dfd9efSDavid du Colombier case 0x1291: case 0x4011: case 0x41f1: case 0x5091: case 0x5121:
183*d6dfd9efSDavid du Colombier seprint(s, es, "405");
184*d6dfd9efSDavid du Colombier break;
185*d6dfd9efSDavid du Colombier case 0x2001: /* 200 is Xilinx, 1 is ppc405 */
186*d6dfd9efSDavid du Colombier cputype &= ~0xfff;
187*d6dfd9efSDavid du Colombier s = seprint(s, es, "Xilinx ");
188*d6dfd9efSDavid du Colombier switch (cputype) {
189*d6dfd9efSDavid du Colombier case 0x20010000:
190*d6dfd9efSDavid du Colombier seprint(s, es, "Virtex-II Pro 405");
191*d6dfd9efSDavid du Colombier break;
192*d6dfd9efSDavid du Colombier case 0x20011000:
193*d6dfd9efSDavid du Colombier seprint(s, es, "Virtex 4 FX 405D5X2");
194*d6dfd9efSDavid du Colombier break;
195*d6dfd9efSDavid du Colombier default:
196*d6dfd9efSDavid du Colombier seprint(s, es, "405");
197*d6dfd9efSDavid du Colombier break;
198*d6dfd9efSDavid du Colombier }
199*d6dfd9efSDavid du Colombier break;
200*d6dfd9efSDavid du Colombier case 0x7ff2:
201*d6dfd9efSDavid du Colombier s = seprint(s, es, "Xilinx ");
202*d6dfd9efSDavid du Colombier if ((cputype & ~0xf) == 0x7ff21910)
203*d6dfd9efSDavid du Colombier seprint(s, es, "Virtex 5 FXT 440X5");
204*d6dfd9efSDavid du Colombier else
205*d6dfd9efSDavid du Colombier seprint(s, es, "440");
206*d6dfd9efSDavid du Colombier break;
207*d6dfd9efSDavid du Colombier default:
208*d6dfd9efSDavid du Colombier /* oddballs */
209*d6dfd9efSDavid du Colombier if ((cputype & 0xf0000ff7) == 0x400008d4 ||
210*d6dfd9efSDavid du Colombier (cputype & 0xf0000ffb) == 0x200008d0 ||
211*d6dfd9efSDavid du Colombier (cputype & 0xf0000ffb) == 0x200008d8 ||
212*d6dfd9efSDavid du Colombier (cputype & 0xfff00fff) == 0x53200891 ||
213*d6dfd9efSDavid du Colombier (cputype & 0xfff00fff) == 0x53400890 ||
214*d6dfd9efSDavid du Colombier (cputype & 0xfff00fff) == 0x53400891) {
215*d6dfd9efSDavid du Colombier seprint(s, es, "440");
216*d6dfd9efSDavid du Colombier break;
217*d6dfd9efSDavid du Colombier }
218*d6dfd9efSDavid du Colombier cputype &= 0xf0000fff;
219*d6dfd9efSDavid du Colombier switch (cputype) {
220*d6dfd9efSDavid du Colombier case 0x40000440: case 0x40000481: case 0x40000850:
221*d6dfd9efSDavid du Colombier case 0x40000858: case 0x400008d3: case 0x400008db:
222*d6dfd9efSDavid du Colombier case 0x50000850: case 0x50000851: case 0x50000892:
223*d6dfd9efSDavid du Colombier case 0x50000894:
224*d6dfd9efSDavid du Colombier seprint(s, es, "440");
225*d6dfd9efSDavid du Colombier break;
226*d6dfd9efSDavid du Colombier default:
227*d6dfd9efSDavid du Colombier seprint(s, es, "%#ux", m->cputype);
228*d6dfd9efSDavid du Colombier break;
229*d6dfd9efSDavid du Colombier }
230*d6dfd9efSDavid du Colombier break;
231*d6dfd9efSDavid du Colombier }
232*d6dfd9efSDavid du Colombier return buf;
233*d6dfd9efSDavid du Colombier }
234*d6dfd9efSDavid du Colombier
235*d6dfd9efSDavid du Colombier static long
cputyperead(Chan *,void * a,long n,vlong offset)236*d6dfd9efSDavid du Colombier cputyperead(Chan*, void *a, long n, vlong offset)
237*d6dfd9efSDavid du Colombier {
238*d6dfd9efSDavid du Colombier char name[64], str[128];
239*d6dfd9efSDavid du Colombier
240*d6dfd9efSDavid du Colombier cputype2name(name, sizeof name);
241*d6dfd9efSDavid du Colombier snprint(str, sizeof str, "PowerPC %s %lud\n", name, m->cpuhz / 1000000);
242*d6dfd9efSDavid du Colombier return readstr(offset, a, n, str);
243*d6dfd9efSDavid du Colombier }
244*d6dfd9efSDavid du Colombier
245*d6dfd9efSDavid du Colombier static long
tbread(Chan *,void * a,long n,vlong offset)246*d6dfd9efSDavid du Colombier tbread(Chan*, void *a, long n, vlong offset)
247*d6dfd9efSDavid du Colombier {
248*d6dfd9efSDavid du Colombier char str[16];
249*d6dfd9efSDavid du Colombier uvlong tb;
250*d6dfd9efSDavid du Colombier
251*d6dfd9efSDavid du Colombier cycles(&tb);
252*d6dfd9efSDavid du Colombier
253*d6dfd9efSDavid du Colombier snprint(str, sizeof(str), "%16.16llux", tb);
254*d6dfd9efSDavid du Colombier return readstr(offset, a, n, str);
255*d6dfd9efSDavid du Colombier }
256*d6dfd9efSDavid du Colombier
257*d6dfd9efSDavid du Colombier static long
nsread(Chan *,void * a,long n,vlong offset)258*d6dfd9efSDavid du Colombier nsread(Chan*, void *a, long n, vlong offset)
259*d6dfd9efSDavid du Colombier {
260*d6dfd9efSDavid du Colombier char str[16];
261*d6dfd9efSDavid du Colombier uvlong tb;
262*d6dfd9efSDavid du Colombier
263*d6dfd9efSDavid du Colombier cycles(&tb);
264*d6dfd9efSDavid du Colombier
265*d6dfd9efSDavid du Colombier snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
266*d6dfd9efSDavid du Colombier return readstr(offset, a, n, str);
267*d6dfd9efSDavid du Colombier }
268*d6dfd9efSDavid du Colombier
269*d6dfd9efSDavid du Colombier uvlong
fastns(void)270*d6dfd9efSDavid du Colombier fastns(void)
271*d6dfd9efSDavid du Colombier {
272*d6dfd9efSDavid du Colombier return gettbl();
273*d6dfd9efSDavid du Colombier }
274*d6dfd9efSDavid du Colombier
275*d6dfd9efSDavid du Colombier static long
mutread(Chan *,void * a,long n,vlong offset)276*d6dfd9efSDavid du Colombier mutread(Chan*, void *a, long n, vlong offset)
277*d6dfd9efSDavid du Colombier {
278*d6dfd9efSDavid du Colombier char str[256];
279*d6dfd9efSDavid du Colombier
280*d6dfd9efSDavid du Colombier snprint(str, sizeof str, "period (sec.s) %lud\n"
281*d6dfd9efSDavid du Colombier "last start sec. %lud\n"
282*d6dfd9efSDavid du Colombier "ticks of last mutation %lud\n"
283*d6dfd9efSDavid du Colombier "mutations %lud\n"
284*d6dfd9efSDavid du Colombier "ticks of average mutation %lud\n"
285*d6dfd9efSDavid du Colombier "border %#lux\n",
286*d6dfd9efSDavid du Colombier mutstats.period, mutstats.lasttm, mutstats.lastticks,
287*d6dfd9efSDavid du Colombier mutstats.count, mutstats.totticks / mutstats.count,
288*d6dfd9efSDavid du Colombier qtmborder());
289*d6dfd9efSDavid du Colombier return readstr(offset, a, n, str);
290*d6dfd9efSDavid du Colombier }
291*d6dfd9efSDavid du Colombier
292*d6dfd9efSDavid du Colombier enum {
293*d6dfd9efSDavid du Colombier CMnow,
294*d6dfd9efSDavid du Colombier CMperiod,
295*d6dfd9efSDavid du Colombier CMstop,
296*d6dfd9efSDavid du Colombier };
297*d6dfd9efSDavid du Colombier
298*d6dfd9efSDavid du Colombier Cmdtab mutmsg[] = {
299*d6dfd9efSDavid du Colombier CMnow, "now", 1,
300*d6dfd9efSDavid du Colombier CMperiod, "period", 2,
301*d6dfd9efSDavid du Colombier CMstop, "stop", 1,
302*d6dfd9efSDavid du Colombier };
303*d6dfd9efSDavid du Colombier
304*d6dfd9efSDavid du Colombier static long
mutwrite(Chan *,void * a,long n,vlong)305*d6dfd9efSDavid du Colombier mutwrite(Chan*, void *a, long n, vlong /* offset */)
306*d6dfd9efSDavid du Colombier {
307*d6dfd9efSDavid du Colombier Cmdbuf *cb;
308*d6dfd9efSDavid du Colombier Cmdtab *ct;
309*d6dfd9efSDavid du Colombier
310*d6dfd9efSDavid du Colombier cb = parsecmd(a, n);
311*d6dfd9efSDavid du Colombier if(waserror()) {
312*d6dfd9efSDavid du Colombier free(cb);
313*d6dfd9efSDavid du Colombier nexterror();
314*d6dfd9efSDavid du Colombier }
315*d6dfd9efSDavid du Colombier ct = lookupcmd(cb, mutmsg, nelem(mutmsg));
316*d6dfd9efSDavid du Colombier switch(ct->index) {
317*d6dfd9efSDavid du Colombier case CMnow:
318*d6dfd9efSDavid du Colombier if (mutatetrigger() < 0)
319*d6dfd9efSDavid du Colombier error("mutate in progress");
320*d6dfd9efSDavid du Colombier break;
321*d6dfd9efSDavid du Colombier case CMperiod:
322*d6dfd9efSDavid du Colombier mutstats.period = atoi(cb->f[1]);
323*d6dfd9efSDavid du Colombier break;
324*d6dfd9efSDavid du Colombier case CMstop:
325*d6dfd9efSDavid du Colombier mutstats.period = 0;
326*d6dfd9efSDavid du Colombier break;
327*d6dfd9efSDavid du Colombier default:
328*d6dfd9efSDavid du Colombier error(Ebadctl);
329*d6dfd9efSDavid du Colombier break;
330*d6dfd9efSDavid du Colombier }
331*d6dfd9efSDavid du Colombier poperror();
332*d6dfd9efSDavid du Colombier free(cb);
333*d6dfd9efSDavid du Colombier return n;
334*d6dfd9efSDavid du Colombier }
335*d6dfd9efSDavid du Colombier
336*d6dfd9efSDavid du Colombier static long
intrsread(Chan *,void * a,long n,vlong offset)337*d6dfd9efSDavid du Colombier intrsread(Chan*, void *a, long n, vlong offset)
338*d6dfd9efSDavid du Colombier {
339*d6dfd9efSDavid du Colombier char *p;
340*d6dfd9efSDavid du Colombier
341*d6dfd9efSDavid du Colombier if(n == 0)
342*d6dfd9efSDavid du Colombier return 0;
343*d6dfd9efSDavid du Colombier p = malloc(READSTR);
344*d6dfd9efSDavid du Colombier intrfmtcounts(p, p + READSTR);
345*d6dfd9efSDavid du Colombier n = readstr(offset, a, n, p);
346*d6dfd9efSDavid du Colombier free(p);
347*d6dfd9efSDavid du Colombier return n;
348*d6dfd9efSDavid du Colombier }
349*d6dfd9efSDavid du Colombier
350*d6dfd9efSDavid du Colombier void
archinit(void)351*d6dfd9efSDavid du Colombier archinit(void)
352*d6dfd9efSDavid du Colombier {
353*d6dfd9efSDavid du Colombier addarchfile("cputype", 0444, cputyperead, nil);
354*d6dfd9efSDavid du Colombier addarchfile("timebase",0444, tbread, nil);
355*d6dfd9efSDavid du Colombier addarchfile("nsec", 0444, nsread, nil);
356*d6dfd9efSDavid du Colombier addarchfile("mutate", 0644, mutread, mutwrite);
357*d6dfd9efSDavid du Colombier addarchfile("intrs", 0444, intrsread, nil);
358*d6dfd9efSDavid du Colombier }
359