xref: /plan9/sys/src/cmd/aux/pcmcia.c (revision 1517423268547a2c0be806559a31cb95653443d5)
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