1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier
4219b2ee8SDavid du Colombier enum
5219b2ee8SDavid du Colombier {
6*15174232SDavid du Colombier Linktarget = 0x13,
7*15174232SDavid du Colombier Funcid = 0x21,
8219b2ee8SDavid du Colombier End = 0xff,
9219b2ee8SDavid du Colombier };
10219b2ee8SDavid du Colombier
11219b2ee8SDavid du Colombier int fd;
12219b2ee8SDavid du Colombier int pos;
13219b2ee8SDavid du Colombier
14219b2ee8SDavid du Colombier void tdevice(int, int);
15*15174232SDavid du Colombier void tlonglnkmfc(int, int);
16*15174232SDavid du Colombier void tfuncid(int, int);
17219b2ee8SDavid du Colombier void tcfig(int, int);
18219b2ee8SDavid du Colombier void tentry(int, int);
19219b2ee8SDavid du Colombier void tvers1(int, int);
20219b2ee8SDavid du Colombier
21219b2ee8SDavid du Colombier void (*parse[256])(int, int) =
22219b2ee8SDavid du Colombier {
23219b2ee8SDavid du Colombier [1] tdevice,
24*15174232SDavid du Colombier [6] tlonglnkmfc,
25219b2ee8SDavid du Colombier [0x15] tvers1,
26219b2ee8SDavid du Colombier [0x17] tdevice,
27219b2ee8SDavid du Colombier [0x1A] tcfig,
28219b2ee8SDavid du Colombier [0x1B] tentry,
29*15174232SDavid du Colombier [Funcid] tfuncid,
30219b2ee8SDavid du Colombier };
31219b2ee8SDavid du Colombier
32219b2ee8SDavid du Colombier int hex;
33219b2ee8SDavid du Colombier
34219b2ee8SDavid du Colombier void
fatal(char * fmt,...)35219b2ee8SDavid du Colombier fatal(char *fmt, ...)
36219b2ee8SDavid du Colombier {
377dd7cddfSDavid du Colombier va_list arg;
389a747e4fSDavid du Colombier char buf[512];
39219b2ee8SDavid du Colombier
407dd7cddfSDavid du Colombier va_start(arg, fmt);
419a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg);
427dd7cddfSDavid du Colombier va_end(arg);
43219b2ee8SDavid du Colombier fprint(2, "pcmcia: %s\n", buf);
44219b2ee8SDavid du Colombier exits(buf);
45219b2ee8SDavid du Colombier }
46219b2ee8SDavid du Colombier
47219b2ee8SDavid du Colombier int
readc(void * x)48219b2ee8SDavid du Colombier readc(void *x)
49219b2ee8SDavid du Colombier {
50219b2ee8SDavid du Colombier int rv;
51219b2ee8SDavid du Colombier
52219b2ee8SDavid du Colombier seek(fd, 2*pos, 0);
53219b2ee8SDavid du Colombier pos++;
54219b2ee8SDavid du Colombier rv = read(fd, x, 1);
55219b2ee8SDavid du Colombier if(hex)
56219b2ee8SDavid du Colombier print("%2.2ux ", *(uchar*)x);
57219b2ee8SDavid du Colombier return rv;
58219b2ee8SDavid du Colombier }
59219b2ee8SDavid du Colombier
60219b2ee8SDavid du Colombier int
tuple(int next,int expect)61*15174232SDavid du Colombier tuple(int next, int expect)
62219b2ee8SDavid du Colombier {
63219b2ee8SDavid du Colombier uchar link;
64219b2ee8SDavid du Colombier uchar type;
65219b2ee8SDavid du Colombier
66219b2ee8SDavid du Colombier pos = next;
67219b2ee8SDavid du Colombier if(readc(&type) != 1)
68219b2ee8SDavid du Colombier return -1;
69219b2ee8SDavid du Colombier if(type == 0xff)
70219b2ee8SDavid du Colombier return -1;
71*15174232SDavid du Colombier print("type %.2uX\n", type & 0xff);
72*15174232SDavid du Colombier
73*15174232SDavid du Colombier if(expect && expect != type){
74*15174232SDavid du Colombier print("expected %.2uX found %.2uX\n",
75*15174232SDavid du Colombier expect, type);
76*15174232SDavid du Colombier return -1;
77*15174232SDavid du Colombier }
78*15174232SDavid du Colombier
79219b2ee8SDavid du Colombier if(readc(&link) != 1)
80219b2ee8SDavid du Colombier return -1;
81219b2ee8SDavid du Colombier if(parse[type])
82219b2ee8SDavid du Colombier (*parse[type])(type, link);
83219b2ee8SDavid du Colombier if(link == 0xff)
84219b2ee8SDavid du Colombier next = -1;
85219b2ee8SDavid du Colombier else
86219b2ee8SDavid du Colombier next = next+2+link;
87219b2ee8SDavid du Colombier return next;
88219b2ee8SDavid du Colombier }
89219b2ee8SDavid du Colombier
90219b2ee8SDavid du Colombier void
main(int argc,char * argv[])91219b2ee8SDavid du Colombier main(int argc, char *argv[])
92219b2ee8SDavid du Colombier {
93219b2ee8SDavid du Colombier char *file;
94219b2ee8SDavid du Colombier int next;
95219b2ee8SDavid du Colombier
96219b2ee8SDavid du Colombier ARGBEGIN{
97219b2ee8SDavid du Colombier case 'x':
98219b2ee8SDavid du Colombier hex = 1;
99219b2ee8SDavid du Colombier }ARGEND;
100219b2ee8SDavid du Colombier
101219b2ee8SDavid du Colombier if(argc == 0)
102219b2ee8SDavid du Colombier file = "#y/pcm0attr";
103219b2ee8SDavid du Colombier else
104219b2ee8SDavid du Colombier file = argv[0];
105219b2ee8SDavid du Colombier
106219b2ee8SDavid du Colombier fd = open(file, OREAD);
107219b2ee8SDavid du Colombier if(fd < 0)
108219b2ee8SDavid du Colombier fatal("opening %s: %r", file);
109219b2ee8SDavid du Colombier
110219b2ee8SDavid du Colombier for(next = 0; next >= 0;)
111*15174232SDavid du Colombier next = tuple(next, 0);
112219b2ee8SDavid du Colombier }
113219b2ee8SDavid du Colombier
114219b2ee8SDavid du Colombier ulong speedtab[16] =
115219b2ee8SDavid du Colombier {
116219b2ee8SDavid du Colombier [1] 250,
117219b2ee8SDavid du Colombier [2] 200,
118219b2ee8SDavid du Colombier [3] 150,
119219b2ee8SDavid du Colombier [4] 100,
120219b2ee8SDavid du Colombier };
121219b2ee8SDavid du Colombier
122219b2ee8SDavid du Colombier ulong mantissa[16] =
123219b2ee8SDavid du Colombier {
124219b2ee8SDavid du Colombier [1] 10,
125219b2ee8SDavid du Colombier [2] 12,
126219b2ee8SDavid du Colombier [3] 13,
127219b2ee8SDavid du Colombier [4] 15,
128219b2ee8SDavid du Colombier [5] 20,
129219b2ee8SDavid du Colombier [6] 25,
130219b2ee8SDavid du Colombier [7] 30,
131219b2ee8SDavid du Colombier [8] 35,
132219b2ee8SDavid du Colombier [9] 40,
133219b2ee8SDavid du Colombier [0xa] 45,
134219b2ee8SDavid du Colombier [0xb] 50,
135219b2ee8SDavid du Colombier [0xc] 55,
136219b2ee8SDavid du Colombier [0xd] 60,
137219b2ee8SDavid du Colombier [0xe] 70,
138219b2ee8SDavid du Colombier [0xf] 80,
139219b2ee8SDavid du Colombier };
140219b2ee8SDavid du Colombier
141219b2ee8SDavid du Colombier ulong exponent[8] =
142219b2ee8SDavid du Colombier {
143219b2ee8SDavid du Colombier [0] 1,
144219b2ee8SDavid du Colombier [1] 10,
145219b2ee8SDavid du Colombier [2] 100,
146219b2ee8SDavid du Colombier [3] 1000,
147219b2ee8SDavid du Colombier [4] 10000,
148219b2ee8SDavid du Colombier [5] 100000,
149219b2ee8SDavid du Colombier [6] 1000000,
150219b2ee8SDavid du Colombier [7] 10000000,
151219b2ee8SDavid du Colombier };
152219b2ee8SDavid du Colombier
153219b2ee8SDavid du Colombier char *typetab[256] =
154219b2ee8SDavid du Colombier {
155219b2ee8SDavid du Colombier [1] "Masked ROM",
156219b2ee8SDavid du Colombier [2] "PROM",
157219b2ee8SDavid du Colombier [3] "EPROM",
158219b2ee8SDavid du Colombier [4] "EEPROM",
159219b2ee8SDavid du Colombier [5] "FLASH",
160219b2ee8SDavid du Colombier [6] "SRAM",
161219b2ee8SDavid du Colombier [7] "DRAM",
162219b2ee8SDavid du Colombier [0xD] "IO+MEM",
163219b2ee8SDavid du Colombier };
164219b2ee8SDavid du Colombier
165219b2ee8SDavid du Colombier ulong
getlong(int size)166219b2ee8SDavid du Colombier getlong(int size)
167219b2ee8SDavid du Colombier {
168219b2ee8SDavid du Colombier uchar c;
169219b2ee8SDavid du Colombier int i;
170219b2ee8SDavid du Colombier ulong x;
171219b2ee8SDavid du Colombier
172219b2ee8SDavid du Colombier x = 0;
173219b2ee8SDavid du Colombier for(i = 0; i < size; i++){
174219b2ee8SDavid du Colombier if(readc(&c) != 1)
175219b2ee8SDavid du Colombier break;
176219b2ee8SDavid du Colombier x |= c<<(i*8);
177219b2ee8SDavid du Colombier }
178219b2ee8SDavid du Colombier return x;
179219b2ee8SDavid du Colombier }
180219b2ee8SDavid du Colombier
181219b2ee8SDavid du Colombier void
tdevice(int ttype,int len)182219b2ee8SDavid du Colombier tdevice(int ttype, int len)
183219b2ee8SDavid du Colombier {
184219b2ee8SDavid du Colombier uchar id;
185219b2ee8SDavid du Colombier uchar type;
186219b2ee8SDavid du Colombier uchar speed, aespeed;
187219b2ee8SDavid du Colombier uchar size;
188219b2ee8SDavid du Colombier ulong bytes, ns;
189219b2ee8SDavid du Colombier char *tname, *ttname;
190219b2ee8SDavid du Colombier
191219b2ee8SDavid du Colombier while(len > 0){
192219b2ee8SDavid du Colombier if(readc(&id) != 1)
193219b2ee8SDavid du Colombier return;
194219b2ee8SDavid du Colombier len--;
195219b2ee8SDavid du Colombier if(id == End)
196219b2ee8SDavid du Colombier return;
197219b2ee8SDavid du Colombier
1982a624137SDavid du Colombier /* PRISM cards have a device tuple with id = size = 0. */
1992a624137SDavid du Colombier if(id == 0x00){
2002a624137SDavid du Colombier if(readc(&size) != 1)
2012a624137SDavid du Colombier return;
2022a624137SDavid du Colombier len--;
2032a624137SDavid du Colombier continue;
2042a624137SDavid du Colombier }
2052a624137SDavid du Colombier
206219b2ee8SDavid du Colombier speed = id & 0x7;
2072a624137SDavid du Colombier if(speed == 0x7){
208219b2ee8SDavid du Colombier if(readc(&speed) != 1)
209219b2ee8SDavid du Colombier return;
210219b2ee8SDavid du Colombier len--;
211219b2ee8SDavid du Colombier if(speed & 0x80){
212219b2ee8SDavid du Colombier if(readc(&aespeed) != 1)
213219b2ee8SDavid du Colombier return;
214219b2ee8SDavid du Colombier ns = 0;
215219b2ee8SDavid du Colombier } else
216219b2ee8SDavid du Colombier ns = (mantissa[(speed>>3)&0xf]*exponent[speed&7])/10;
217219b2ee8SDavid du Colombier } else
218219b2ee8SDavid du Colombier ns = speedtab[speed];
219219b2ee8SDavid du Colombier
220219b2ee8SDavid du Colombier type = id>>4;
221219b2ee8SDavid du Colombier if(type == 0xE){
222219b2ee8SDavid du Colombier if(readc(&type) != 1)
223219b2ee8SDavid du Colombier return;
224219b2ee8SDavid du Colombier len--;
225219b2ee8SDavid du Colombier }
226219b2ee8SDavid du Colombier tname = typetab[type];
227219b2ee8SDavid du Colombier if(tname == 0)
228219b2ee8SDavid du Colombier tname = "unknown";
229219b2ee8SDavid du Colombier
230219b2ee8SDavid du Colombier if(readc(&size) != 1)
231219b2ee8SDavid du Colombier return;
232219b2ee8SDavid du Colombier len--;
233219b2ee8SDavid du Colombier bytes = ((size>>3)+1) * 512 * (1<<(2*(size&0x7)));
234219b2ee8SDavid du Colombier
235219b2ee8SDavid du Colombier if(ttype == 1)
236219b2ee8SDavid du Colombier ttname = "device";
237219b2ee8SDavid du Colombier else
238219b2ee8SDavid du Colombier ttname = "attr device";
2397dd7cddfSDavid du Colombier print("%s %ld bytes of %ldns %s\n", ttname, bytes, ns, tname);
240219b2ee8SDavid du Colombier }
241219b2ee8SDavid du Colombier }
242219b2ee8SDavid du Colombier
243219b2ee8SDavid du Colombier void
tlonglnkmfc(int,int)244*15174232SDavid du Colombier tlonglnkmfc(int, int)
245*15174232SDavid du Colombier {
246*15174232SDavid du Colombier int i, opos;
247*15174232SDavid du Colombier uchar nfn, space, expect;
248*15174232SDavid du Colombier int addr;
249*15174232SDavid du Colombier
250*15174232SDavid du Colombier readc(&nfn);
251*15174232SDavid du Colombier for(i = 0; i < nfn; i++){
252*15174232SDavid du Colombier readc(&space);
253*15174232SDavid du Colombier addr = getlong(4);
254*15174232SDavid du Colombier opos = pos;
255*15174232SDavid du Colombier expect = Linktarget;
256*15174232SDavid du Colombier while(addr > 0){
257*15174232SDavid du Colombier addr = tuple(addr, expect);
258*15174232SDavid du Colombier expect = 0;
259*15174232SDavid du Colombier }
260*15174232SDavid du Colombier pos = opos;
261*15174232SDavid du Colombier }
262*15174232SDavid du Colombier }
263*15174232SDavid du Colombier
264*15174232SDavid du Colombier static char *funcids[] = {
265*15174232SDavid du Colombier "MULTI",
266*15174232SDavid du Colombier "MEMORY",
267*15174232SDavid du Colombier "SERIAL",
268*15174232SDavid du Colombier "PARALLEL",
269*15174232SDavid du Colombier "FIXED",
270*15174232SDavid du Colombier "VIDEO",
271*15174232SDavid du Colombier "NETWORK",
272*15174232SDavid du Colombier "AIMS",
273*15174232SDavid du Colombier "SCSI",
274*15174232SDavid du Colombier };
275*15174232SDavid du Colombier
276*15174232SDavid du Colombier void
tfuncid(int,int)277*15174232SDavid du Colombier tfuncid(int, int)
278*15174232SDavid du Colombier {
279*15174232SDavid du Colombier uchar func;
280*15174232SDavid du Colombier
281*15174232SDavid du Colombier readc(&func);
282*15174232SDavid du Colombier print("Function %s\n",
283*15174232SDavid du Colombier (func >= nelem(funcids))? "unknown function": funcids[func]);
284*15174232SDavid du Colombier }
285*15174232SDavid du Colombier
286*15174232SDavid du Colombier void
tvers1(int ttype,int len)287219b2ee8SDavid du Colombier tvers1(int ttype, int len)
288219b2ee8SDavid du Colombier {
289219b2ee8SDavid du Colombier uchar c, major, minor;
290219b2ee8SDavid du Colombier int i;
291219b2ee8SDavid du Colombier char string[512];
292219b2ee8SDavid du Colombier
293219b2ee8SDavid du Colombier USED(ttype);
294219b2ee8SDavid du Colombier if(readc(&major) != 1)
295219b2ee8SDavid du Colombier return;
296219b2ee8SDavid du Colombier len--;
297219b2ee8SDavid du Colombier if(readc(&minor) != 1)
298219b2ee8SDavid du Colombier return;
299219b2ee8SDavid du Colombier len--;
300219b2ee8SDavid du Colombier print("version %d.%d\n", major, minor);
301219b2ee8SDavid du Colombier while(len > 0){
302219b2ee8SDavid du Colombier for(i = 0; len > 0 && i < sizeof(string); i++){
303219b2ee8SDavid du Colombier if(readc(&string[i]) != 1)
304219b2ee8SDavid du Colombier return;
305219b2ee8SDavid du Colombier len--;
306219b2ee8SDavid du Colombier c = string[i];
307219b2ee8SDavid du Colombier if(c == 0)
308219b2ee8SDavid du Colombier break;
309219b2ee8SDavid du Colombier if(c == 0xff){
310219b2ee8SDavid du Colombier if(i != 0){
311219b2ee8SDavid du Colombier string[i] = 0;
312219b2ee8SDavid du Colombier print("\t%s<missing null>\n", string);
313219b2ee8SDavid du Colombier }
314219b2ee8SDavid du Colombier return;
315219b2ee8SDavid du Colombier }
316219b2ee8SDavid du Colombier }
317219b2ee8SDavid du Colombier string[i] = 0;
318219b2ee8SDavid du Colombier print("\t%s\n", string);
319219b2ee8SDavid du Colombier }
320219b2ee8SDavid du Colombier }
321219b2ee8SDavid du Colombier
322219b2ee8SDavid du Colombier void
tcfig(int ttype,int len)323219b2ee8SDavid du Colombier tcfig(int ttype, int len)
324219b2ee8SDavid du Colombier {
325219b2ee8SDavid du Colombier uchar size, rasize, rmsize;
326219b2ee8SDavid du Colombier uchar last;
327219b2ee8SDavid du Colombier ulong caddr;
328219b2ee8SDavid du Colombier ulong cregs;
329219b2ee8SDavid du Colombier int i;
330219b2ee8SDavid du Colombier
331219b2ee8SDavid du Colombier USED(ttype, len);
332219b2ee8SDavid du Colombier if(readc(&size) != 1)
333219b2ee8SDavid du Colombier return;
334219b2ee8SDavid du Colombier rasize = (size&0x3) + 1;
335219b2ee8SDavid du Colombier rmsize = ((size>>2)&0xf) + 1;
336219b2ee8SDavid du Colombier if(readc(&last) != 1)
337219b2ee8SDavid du Colombier return;
338219b2ee8SDavid du Colombier caddr = getlong(rasize);
339219b2ee8SDavid du Colombier cregs = getlong(rmsize);
340219b2ee8SDavid du Colombier
341219b2ee8SDavid du Colombier print("configuration registers at");
342219b2ee8SDavid du Colombier for(i = 0; i < 16; i++)
343219b2ee8SDavid du Colombier if((1<<i) & cregs)
344219b2ee8SDavid du Colombier print(" (%d)0x%lux", i, caddr + i*2);
345219b2ee8SDavid du Colombier print("\n");
346219b2ee8SDavid du Colombier }
347219b2ee8SDavid du Colombier
348219b2ee8SDavid du Colombier char *intrname[16] =
349219b2ee8SDavid du Colombier {
350219b2ee8SDavid du Colombier [0] "memory",
351219b2ee8SDavid du Colombier [1] "I/O",
352219b2ee8SDavid du Colombier [4] "Custom 0",
353219b2ee8SDavid du Colombier [5] "Custom 1",
354219b2ee8SDavid du Colombier [6] "Custom 2",
355219b2ee8SDavid du Colombier [7] "Custom 3",
356219b2ee8SDavid du Colombier };
357219b2ee8SDavid du Colombier
358219b2ee8SDavid du Colombier ulong vexp[8] =
359219b2ee8SDavid du Colombier {
360219b2ee8SDavid du Colombier 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
361219b2ee8SDavid du Colombier };
362219b2ee8SDavid du Colombier ulong vmant[16] =
363219b2ee8SDavid du Colombier {
364219b2ee8SDavid du Colombier 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
365219b2ee8SDavid du Colombier };
366219b2ee8SDavid du Colombier
367219b2ee8SDavid du Colombier void
volt(char * name)368219b2ee8SDavid du Colombier volt(char *name)
369219b2ee8SDavid du Colombier {
370219b2ee8SDavid du Colombier uchar c;
371219b2ee8SDavid du Colombier ulong microv;
372219b2ee8SDavid du Colombier ulong exp;
373219b2ee8SDavid du Colombier
374219b2ee8SDavid du Colombier if(readc(&c) != 1)
375219b2ee8SDavid du Colombier return;
376219b2ee8SDavid du Colombier exp = vexp[c&0x7];
377219b2ee8SDavid du Colombier microv = vmant[(c>>3)&0xf]*exp;
378219b2ee8SDavid du Colombier while(c & 0x80){
379219b2ee8SDavid du Colombier if(readc(&c) != 1)
380219b2ee8SDavid du Colombier return;
381219b2ee8SDavid du Colombier switch(c){
382219b2ee8SDavid du Colombier case 0x7d:
383219b2ee8SDavid du Colombier break; /* high impedence when sleeping */
384219b2ee8SDavid du Colombier case 0x7e:
385219b2ee8SDavid du Colombier case 0x7f:
386219b2ee8SDavid du Colombier microv = 0; /* no connection */
387219b2ee8SDavid du Colombier break;
388219b2ee8SDavid du Colombier default:
389219b2ee8SDavid du Colombier exp /= 10;
390219b2ee8SDavid du Colombier microv += exp*(c&0x7f);
391219b2ee8SDavid du Colombier }
392219b2ee8SDavid du Colombier }
3937dd7cddfSDavid du Colombier print(" V%s %lduV", name, microv);
394219b2ee8SDavid du Colombier }
395219b2ee8SDavid du Colombier
396219b2ee8SDavid du Colombier void
amps(char * name)397219b2ee8SDavid du Colombier amps(char *name)
398219b2ee8SDavid du Colombier {
399219b2ee8SDavid du Colombier uchar c;
400219b2ee8SDavid du Colombier ulong amps;
401219b2ee8SDavid du Colombier
402219b2ee8SDavid du Colombier if(readc(&c) != 1)
403219b2ee8SDavid du Colombier return;
404219b2ee8SDavid du Colombier amps = vexp[c&0x7]*vmant[(c>>3)&0xf];
405219b2ee8SDavid du Colombier while(c & 0x80){
406219b2ee8SDavid du Colombier if(readc(&c) != 1)
407219b2ee8SDavid du Colombier return;
408219b2ee8SDavid du Colombier if(c == 0x7d || c == 0x7e || c == 0x7f)
409219b2ee8SDavid du Colombier amps = 0;
410219b2ee8SDavid du Colombier }
411219b2ee8SDavid du Colombier if(amps >= 1000000)
4127dd7cddfSDavid du Colombier print(" I%s %ldmA", name, amps/100000);
413219b2ee8SDavid du Colombier else if(amps >= 1000)
4147dd7cddfSDavid du Colombier print(" I%s %lduA", name, amps/100);
415219b2ee8SDavid du Colombier else
4167dd7cddfSDavid du Colombier print(" I%s %ldnA", name, amps*10);
417219b2ee8SDavid du Colombier }
418219b2ee8SDavid du Colombier
419219b2ee8SDavid du Colombier void
power(char * name)420219b2ee8SDavid du Colombier power(char *name)
421219b2ee8SDavid du Colombier {
422219b2ee8SDavid du Colombier uchar feature;
423219b2ee8SDavid du Colombier
424219b2ee8SDavid du Colombier print("\t%s: ", name);
425219b2ee8SDavid du Colombier if(readc(&feature) != 1)
426219b2ee8SDavid du Colombier return;
427219b2ee8SDavid du Colombier if(feature & 1)
428219b2ee8SDavid du Colombier volt("nominal");
429219b2ee8SDavid du Colombier if(feature & 2)
430219b2ee8SDavid du Colombier volt("min");
431219b2ee8SDavid du Colombier if(feature & 4)
432219b2ee8SDavid du Colombier volt("max");
433219b2ee8SDavid du Colombier if(feature & 8)
434219b2ee8SDavid du Colombier amps("static");
435219b2ee8SDavid du Colombier if(feature & 0x10)
436219b2ee8SDavid du Colombier amps("avg");
437219b2ee8SDavid du Colombier if(feature & 0x20)
438219b2ee8SDavid du Colombier amps("peak");
439219b2ee8SDavid du Colombier if(feature & 0x40)
440219b2ee8SDavid du Colombier amps("powerdown");
441219b2ee8SDavid du Colombier print("\n");
442219b2ee8SDavid du Colombier }
443219b2ee8SDavid du Colombier
444219b2ee8SDavid du Colombier void
ttiming(char * name,int scale)445219b2ee8SDavid du Colombier ttiming(char *name, int scale)
446219b2ee8SDavid du Colombier {
447219b2ee8SDavid du Colombier uchar unscaled;
448219b2ee8SDavid du Colombier ulong scaled;
449219b2ee8SDavid du Colombier
450219b2ee8SDavid du Colombier if(readc(&unscaled) != 1)
451219b2ee8SDavid du Colombier return;
452219b2ee8SDavid du Colombier scaled = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
453219b2ee8SDavid du Colombier scaled = scaled * vexp[scale];
4547dd7cddfSDavid du Colombier print("\t%s %ldns\n", name, scaled);
455219b2ee8SDavid du Colombier }
456219b2ee8SDavid du Colombier
457219b2ee8SDavid du Colombier void
timing(void)458219b2ee8SDavid du Colombier timing(void)
459219b2ee8SDavid du Colombier {
460219b2ee8SDavid du Colombier uchar c, i;
461219b2ee8SDavid du Colombier
462219b2ee8SDavid du Colombier if(readc(&c) != 1)
463219b2ee8SDavid du Colombier return;
464219b2ee8SDavid du Colombier i = c&0x3;
465219b2ee8SDavid du Colombier if(i != 3)
466219b2ee8SDavid du Colombier ttiming("max wait", i);
467219b2ee8SDavid du Colombier i = (c>>2)&0x7;
468219b2ee8SDavid du Colombier if(i != 7)
469219b2ee8SDavid du Colombier ttiming("max ready/busy wait", i);
470219b2ee8SDavid du Colombier i = (c>>5)&0x7;
471219b2ee8SDavid du Colombier if(i != 7)
472219b2ee8SDavid du Colombier ttiming("reserved wait", i);
473219b2ee8SDavid du Colombier }
474219b2ee8SDavid du Colombier
475219b2ee8SDavid du Colombier void
range(int asize,int lsize)476219b2ee8SDavid du Colombier range(int asize, int lsize)
477219b2ee8SDavid du Colombier {
478219b2ee8SDavid du Colombier ulong address, len;
479219b2ee8SDavid du Colombier
480219b2ee8SDavid du Colombier address = getlong(asize);
481219b2ee8SDavid du Colombier len = getlong(lsize);
482219b2ee8SDavid du Colombier print("\t\t%lux - %lux\n", address, address+len);
483219b2ee8SDavid du Colombier }
484219b2ee8SDavid du Colombier
485219b2ee8SDavid du Colombier char *ioaccess[4] =
486219b2ee8SDavid du Colombier {
487219b2ee8SDavid du Colombier " no access",
488219b2ee8SDavid du Colombier " 8bit access only",
489219b2ee8SDavid du Colombier " 8bit or 16bit access",
490219b2ee8SDavid du Colombier " selectable 8bit or 8&16bit access",
491219b2ee8SDavid du Colombier };
492219b2ee8SDavid du Colombier
493219b2ee8SDavid du Colombier int
iospace(uchar c)494219b2ee8SDavid du Colombier iospace(uchar c)
495219b2ee8SDavid du Colombier {
496219b2ee8SDavid du Colombier int i;
497219b2ee8SDavid du Colombier
498219b2ee8SDavid du Colombier print("\tIO space %d address lines%s\n", c&0x1f, ioaccess[(c>>5)&3]);
499219b2ee8SDavid du Colombier if((c & 0x80) == 0)
500219b2ee8SDavid du Colombier return -1;
501219b2ee8SDavid du Colombier
502219b2ee8SDavid du Colombier if(readc(&c) != 1)
503219b2ee8SDavid du Colombier return -1;
504219b2ee8SDavid du Colombier
505219b2ee8SDavid du Colombier for(i = (c&0xf)+1; i; i--)
506219b2ee8SDavid du Colombier range((c>>4)&0x3, (c>>6)&0x3);
507219b2ee8SDavid du Colombier return 0;
508219b2ee8SDavid du Colombier }
509219b2ee8SDavid du Colombier
510219b2ee8SDavid du Colombier void
iospaces(void)511219b2ee8SDavid du Colombier iospaces(void)
512219b2ee8SDavid du Colombier {
513219b2ee8SDavid du Colombier uchar c;
514219b2ee8SDavid du Colombier
515219b2ee8SDavid du Colombier if(readc(&c) != 1)
516219b2ee8SDavid du Colombier return;
517219b2ee8SDavid du Colombier iospace(c);
518219b2ee8SDavid du Colombier }
519219b2ee8SDavid du Colombier
520219b2ee8SDavid du Colombier void
irq(void)521219b2ee8SDavid du Colombier irq(void)
522219b2ee8SDavid du Colombier {
523219b2ee8SDavid du Colombier uchar c;
524219b2ee8SDavid du Colombier uchar irq1, irq2;
525219b2ee8SDavid du Colombier ushort i, irqs;
526219b2ee8SDavid du Colombier
527219b2ee8SDavid du Colombier if(readc(&c) != 1)
528219b2ee8SDavid du Colombier return;
529219b2ee8SDavid du Colombier if(c & 0x10){
530219b2ee8SDavid du Colombier if(readc(&irq1) != 1)
531219b2ee8SDavid du Colombier return;
532219b2ee8SDavid du Colombier if(readc(&irq2) != 1)
533219b2ee8SDavid du Colombier return;
534219b2ee8SDavid du Colombier irqs = irq1|(irq2<<8);
535219b2ee8SDavid du Colombier } else
536219b2ee8SDavid du Colombier irqs = 1<<(c&0xf);
537219b2ee8SDavid du Colombier print("\tinterrupts%s%s%s", (c&0x20)?":level":"", (c&0x40)?":pulse":"",
538219b2ee8SDavid du Colombier (c&0x80)?":shared":"");
539219b2ee8SDavid du Colombier for(i = 0; i < 16; i++)
540219b2ee8SDavid du Colombier if(irqs & (1<<i))
541219b2ee8SDavid du Colombier print(", %d", i);
542219b2ee8SDavid du Colombier print("\n");
543219b2ee8SDavid du Colombier }
544219b2ee8SDavid du Colombier
545219b2ee8SDavid du Colombier void
memspace(int asize,int lsize,int host)546219b2ee8SDavid du Colombier memspace(int asize, int lsize, int host)
547219b2ee8SDavid du Colombier {
548219b2ee8SDavid du Colombier ulong haddress, address, len;
549219b2ee8SDavid du Colombier
550219b2ee8SDavid du Colombier len = getlong(lsize)*256;
551219b2ee8SDavid du Colombier address = getlong(asize)*256;
552219b2ee8SDavid du Colombier if(host){
553219b2ee8SDavid du Colombier haddress = getlong(asize)*256;
554219b2ee8SDavid du Colombier print("\tmemory address range 0x%lux - 0x%lux hostaddr 0x%lux\n",
555219b2ee8SDavid du Colombier address, address+len, haddress);
556219b2ee8SDavid du Colombier } else
557219b2ee8SDavid du Colombier print("\tmemory address range 0x%lux - 0x%lux\n", address, address+len);
558219b2ee8SDavid du Colombier }
559219b2ee8SDavid du Colombier
560219b2ee8SDavid du Colombier void
misc(void)561219b2ee8SDavid du Colombier misc(void)
562219b2ee8SDavid du Colombier {
563219b2ee8SDavid du Colombier }
564219b2ee8SDavid du Colombier
565219b2ee8SDavid du Colombier void
tentry(int ttype,int len)566219b2ee8SDavid du Colombier tentry(int ttype, int len)
567219b2ee8SDavid du Colombier {
568219b2ee8SDavid du Colombier uchar c, i, feature;
569219b2ee8SDavid du Colombier char *tname;
570219b2ee8SDavid du Colombier char buf[16];
571219b2ee8SDavid du Colombier
572219b2ee8SDavid du Colombier USED(ttype, len);
573219b2ee8SDavid du Colombier if(readc(&c) != 1)
574219b2ee8SDavid du Colombier return;
575219b2ee8SDavid du Colombier print("configuration %d%s\n", c&0x3f, (c&0x40)?" (default)":"");
576219b2ee8SDavid du Colombier if(c & 0x80){
577219b2ee8SDavid du Colombier if(readc(&i) != 1)
578219b2ee8SDavid du Colombier return;
579219b2ee8SDavid du Colombier tname = intrname[i & 0xf];
580219b2ee8SDavid du Colombier if(tname == 0){
581219b2ee8SDavid du Colombier tname = buf;
582219b2ee8SDavid du Colombier sprint(buf, "type %d", i & 0xf);
583219b2ee8SDavid du Colombier }
584219b2ee8SDavid du Colombier print("\t%s device, %s%s%s%s\n", tname,
585219b2ee8SDavid du Colombier (i&0x10)?" Battery status active":"",
586219b2ee8SDavid du Colombier (i&0x20)?" Write Protect active":"",
587219b2ee8SDavid du Colombier (i&0x40)?" Ready/Busy active":"",
588219b2ee8SDavid du Colombier (i&0x80)?" Memory Wait required":"");
589219b2ee8SDavid du Colombier }
590219b2ee8SDavid du Colombier if(readc(&feature) != 1)
591219b2ee8SDavid du Colombier return;
592219b2ee8SDavid du Colombier switch(feature&0x3){
593219b2ee8SDavid du Colombier case 1:
594219b2ee8SDavid du Colombier power("Vcc");
595219b2ee8SDavid du Colombier break;
596219b2ee8SDavid du Colombier case 2:
597219b2ee8SDavid du Colombier power("Vcc");
598219b2ee8SDavid du Colombier power("Vpp");
599219b2ee8SDavid du Colombier break;
600219b2ee8SDavid du Colombier case 3:
601219b2ee8SDavid du Colombier power("Vcc");
602219b2ee8SDavid du Colombier power("Vpp1");
603219b2ee8SDavid du Colombier power("Vpp2");
604219b2ee8SDavid du Colombier break;
605219b2ee8SDavid du Colombier }
606219b2ee8SDavid du Colombier if(feature&0x4)
607219b2ee8SDavid du Colombier timing();
608219b2ee8SDavid du Colombier if(feature&0x8)
609219b2ee8SDavid du Colombier iospaces();
610219b2ee8SDavid du Colombier if(feature&0x10)
611219b2ee8SDavid du Colombier irq();
612219b2ee8SDavid du Colombier switch((feature>>5)&0x3){
613219b2ee8SDavid du Colombier case 1:
614219b2ee8SDavid du Colombier memspace(0, 2, 0);
615219b2ee8SDavid du Colombier break;
616219b2ee8SDavid du Colombier case 2:
617219b2ee8SDavid du Colombier memspace(2, 2, 0);
618219b2ee8SDavid du Colombier break;
619219b2ee8SDavid du Colombier case 3:
620219b2ee8SDavid du Colombier if(readc(&c) != 1)
621219b2ee8SDavid du Colombier return;
622219b2ee8SDavid du Colombier for(i = 0; i <= (c&0x7); i++)
623219b2ee8SDavid du Colombier memspace((c>>5)&0x3, (c>>3)&0x3, c&0x80);
624219b2ee8SDavid du Colombier break;
625219b2ee8SDavid du Colombier }
626219b2ee8SDavid du Colombier if(feature&0x80)
627219b2ee8SDavid du Colombier misc();
628219b2ee8SDavid du Colombier }
629