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