Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
 
4
enum
5
{
6
	Linktarget = 0x13,
7
	Funcid = 0x21,
8
	End =	0xff,
9
};
10
 
11
int fd;
12
int pos;
13
 
14
void	tdevice(int, int);
15
void	tlonglnkmfc(int, int);
16
void	tfuncid(int, int);
17
void	tcfig(int, int);
18
void	tentry(int, int);
19
void	tvers1(int, int);
20
 
21
void (*parse[256])(int, int) =
22
{
23
[1]		tdevice,
24
[6]		tlonglnkmfc,
25
[0x15]		tvers1,
26
[0x17]		tdevice,
27
[0x1A]		tcfig,
28
[0x1B]		tentry,
29
[Funcid]	tfuncid,
30
};
31
 
32
int hex;
33
 
34
void
35
fatal(char *fmt, ...)
36
{
37
	va_list arg;
38
	char buf[512];
39
 
40
	va_start(arg, fmt);
41
	vseprint(buf, buf+sizeof(buf), fmt, arg);
42
	va_end(arg);
43
	fprint(2, "pcmcia: %s\n", buf);
44
	exits(buf);
45
}
46
 
47
int
48
readc(void *x)
49
{
50
	int rv;
51
 
52
	seek(fd, 2*pos, 0);
53
	pos++;
54
	rv = read(fd, x, 1);
55
	if(hex)
56
		print("%2.2ux ", *(uchar*)x);
57
	return rv;
58
}
59
 
60
int
61
tuple(int next, int expect)
62
{
63
	uchar link;
64
	uchar type;
65
 
66
	pos = next;
67
	if(readc(&type) != 1)
68
		return -1;
69
	if(type == 0xff)
70
		return -1;
71
print("type %.2uX\n", type & 0xff);
72
 
73
	if(expect && expect != type){
74
		print("expected %.2uX found %.2uX\n", 
75
			expect, type);
76
		return -1;
77
	}
78
 
79
	if(readc(&link) != 1)
80
		return -1;
81
	if(parse[type])
82
		(*parse[type])(type, link);
83
	if(link == 0xff)
84
		next = -1;
85
	else
86
		next = next+2+link;
87
	return next;
88
}
89
 
90
void
91
main(int argc, char *argv[])
92
{
93
	char *file;
94
	int next;
95
 
96
	ARGBEGIN{
97
	case 'x':
98
		hex = 1;
99
	}ARGEND;
100
 
101
	if(argc == 0)
102
		file = "#y/pcm0attr";
103
	else
104
		file = argv[0];
105
 
106
	fd = open(file, OREAD);
107
	if(fd < 0)
108
		fatal("opening %s: %r", file);
109
 
110
	for(next = 0; next >= 0;)
111
		next = tuple(next, 0);
112
}
113
 
114
ulong speedtab[16] =
115
{
116
[1]	250,
117
[2]	200,
118
[3]	150,
119
[4]	100,
120
};
121
 
122
ulong mantissa[16] =
123
{
124
[1]	10,
125
[2]	12,
126
[3]	13,
127
[4]	15,
128
[5]	20,
129
[6]	25,
130
[7]	30,
131
[8]	35,
132
[9]	40,
133
[0xa]	45,
134
[0xb]	50,
135
[0xc]	55,
136
[0xd]	60,
137
[0xe]	70,
138
[0xf]	80,
139
};
140
 
141
ulong exponent[8] =
142
{
143
[0]	1,
144
[1]	10,
145
[2]	100,
146
[3]	1000,
147
[4]	10000,
148
[5]	100000,
149
[6]	1000000,
150
[7]	10000000,
151
};
152
 
153
char *typetab[256] =
154
{
155
[1]	"Masked ROM",
156
[2]	"PROM",
157
[3]	"EPROM",
158
[4]	"EEPROM",
159
[5]	"FLASH",
160
[6]	"SRAM",
161
[7]	"DRAM",
162
[0xD]	"IO+MEM",
163
};
164
 
165
ulong
166
getlong(int size)
167
{
168
	uchar c;
169
	int i;
170
	ulong x;
171
 
172
	x = 0;
173
	for(i = 0; i < size; i++){
174
		if(readc(&c) != 1)
175
			break;
176
		x |= c<<(i*8);
177
	}
178
	return x;
179
}
180
 
181
void
182
tdevice(int ttype, int len)
183
{
184
	uchar id;
185
	uchar type;
186
	uchar speed, aespeed;
187
	uchar size;
188
	ulong bytes, ns;
189
	char *tname, *ttname;
190
 
191
	while(len > 0){
192
		if(readc(&id) != 1)
193
			return;
194
		len--;
195
		if(id == End)
196
			return;
197
 
198
		/* PRISM cards have a device tuple with id = size = 0. */
199
		if(id == 0x00){
200
			if(readc(&size) != 1)
201
				return;
202
			len--;
203
			continue;
204
		}
205
 
206
		speed = id & 0x7;
207
		if(speed == 0x7){
208
			if(readc(&speed) != 1)
209
				return;
210
			len--;
211
			if(speed & 0x80){
212
				if(readc(&aespeed) != 1)
213
					return;
214
				ns = 0;
215
			} else
216
				ns = (mantissa[(speed>>3)&0xf]*exponent[speed&7])/10;
217
		} else
218
			ns = speedtab[speed];
219
 
220
		type = id>>4;
221
		if(type == 0xE){
222
			if(readc(&type) != 1)
223
				return;
224
			len--;
225
		}
226
		tname = typetab[type];
227
		if(tname == 0)
228
			tname = "unknown";
229
 
230
		if(readc(&size) != 1)
231
			return;
232
		len--;
233
		bytes = ((size>>3)+1) * 512 * (1<<(2*(size&0x7)));
234
 
235
		if(ttype == 1)
236
			ttname = "device";
237
		else
238
			ttname = "attr device";
239
		print("%s %ld bytes of %ldns %s\n", ttname, bytes, ns, tname);
240
	}
241
}
242
 
243
void
244
tlonglnkmfc(int, int)
245
{
246
	int i, opos;
247
	uchar nfn, space, expect;
248
	int addr;
249
 
250
	readc(&nfn);
251
	for(i = 0; i < nfn; i++){
252
		readc(&space);
253
		addr = getlong(4);
254
		opos = pos;
255
		expect = Linktarget;
256
		while(addr > 0){
257
			addr = tuple(addr, expect);
258
			expect = 0;
259
		}
260
		pos = opos;
261
	}
262
}
263
 
264
static char *funcids[] = {
265
	"MULTI",
266
	"MEMORY",
267
	"SERIAL",
268
	"PARALLEL",
269
	"FIXED",
270
	"VIDEO",
271
	"NETWORK",
272
	"AIMS",
273
	"SCSI",
274
};
275
 
276
void
277
tfuncid(int, int)
278
{
279
	uchar func;
280
 
281
	readc(&func);
282
	print("Function %s\n", 
283
		(func >= nelem(funcids))? "unknown function": funcids[func]);
284
}
285
 
286
void
287
tvers1(int ttype, int len)
288
{
289
	uchar c, major, minor;
290
	int  i;
291
	char string[512];
292
 
293
	USED(ttype);
294
	if(readc(&major) != 1)
295
		return;
296
	len--;
297
	if(readc(&minor) != 1)
298
		return;
299
	len--;
300
	print("version %d.%d\n", major, minor);
301
	while(len > 0){
302
		for(i = 0; len > 0 && i < sizeof(string); i++){
303
			if(readc(&string[i]) != 1)
304
				return;
305
			len--;
306
			c = string[i];
307
			if(c == 0)
308
				break;
309
			if(c == 0xff){
310
				if(i != 0){
311
					string[i] = 0;
312
					print("\t%s<missing null>\n", string);
313
				}
314
				return;
315
			}
316
		}
317
		string[i] = 0;
318
		print("\t%s\n", string);
319
	}
320
}
321
 
322
void
323
tcfig(int ttype, int len)
324
{
325
	uchar size, rasize, rmsize;
326
	uchar last;
327
	ulong caddr;
328
	ulong cregs;
329
	int i;
330
 
331
	USED(ttype, len);
332
	if(readc(&size) != 1)
333
		return;
334
	rasize = (size&0x3) + 1;
335
	rmsize = ((size>>2)&0xf) + 1;
336
	if(readc(&last) != 1)
337
		return;
338
	caddr = getlong(rasize);
339
	cregs = getlong(rmsize);
340
 
341
	print("configuration registers at");
342
	for(i = 0; i < 16; i++)
343
		if((1<<i) & cregs)
344
			print(" (%d)0x%lux", i, caddr + i*2);
345
	print("\n");
346
}
347
 
348
char *intrname[16] =
349
{
350
[0]	"memory",
351
[1]	"I/O",
352
[4]	"Custom 0",
353
[5]	"Custom 1",
354
[6]	"Custom 2",
355
[7]	"Custom 3",
356
};
357
 
358
ulong vexp[8] =
359
{
360
	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
361
};
362
ulong vmant[16] =
363
{
364
	10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
365
};
366
 
367
void
368
volt(char *name)
369
{
370
	uchar c;
371
	ulong microv;
372
	ulong exp;
373
 
374
	if(readc(&c) != 1)
375
		return;
376
	exp = vexp[c&0x7];
377
	microv = vmant[(c>>3)&0xf]*exp;
378
	while(c & 0x80){
379
		if(readc(&c) != 1)
380
			return;
381
		switch(c){
382
		case 0x7d:
383
			break;		/* high impedence when sleeping */
384
		case 0x7e:
385
		case 0x7f:
386
			microv = 0;	/* no connection */
387
			break;
388
		default:
389
			exp /= 10;
390
			microv += exp*(c&0x7f);
391
		}
392
	}
393
	print(" V%s %lduV", name, microv);
394
}
395
 
396
void
397
amps(char *name)
398
{
399
	uchar c;
400
	ulong amps;
401
 
402
	if(readc(&c) != 1)
403
		return;
404
	amps = vexp[c&0x7]*vmant[(c>>3)&0xf];
405
	while(c & 0x80){
406
		if(readc(&c) != 1)
407
			return;
408
		if(c == 0x7d || c == 0x7e || c == 0x7f)
409
			amps = 0;
410
	}
411
	if(amps >= 1000000)
412
		print(" I%s %ldmA", name, amps/100000);
413
	else if(amps >= 1000)
414
		print(" I%s %lduA", name, amps/100);
415
	else
416
		print(" I%s %ldnA", name, amps*10);
417
}
418
 
419
void
420
power(char *name)
421
{
422
	uchar feature;
423
 
424
	print("\t%s: ", name);
425
	if(readc(&feature) != 1)
426
		return;
427
	if(feature & 1)
428
		volt("nominal");
429
	if(feature & 2)
430
		volt("min");
431
	if(feature & 4)
432
		volt("max");
433
	if(feature & 8)
434
		amps("static");
435
	if(feature & 0x10)
436
		amps("avg");
437
	if(feature & 0x20)
438
		amps("peak");
439
	if(feature & 0x40)
440
		amps("powerdown");
441
	print("\n");
442
}
443
 
444
void
445
ttiming(char *name, int scale)
446
{
447
	uchar unscaled;
448
	ulong scaled;
449
 
450
	if(readc(&unscaled) != 1)
451
		return;
452
	scaled = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
453
	scaled = scaled * vexp[scale];
454
	print("\t%s %ldns\n", name, scaled);
455
}
456
 
457
void
458
timing(void)
459
{
460
	uchar c, i;
461
 
462
	if(readc(&c) != 1)
463
		return;
464
	i = c&0x3;
465
	if(i != 3)
466
		ttiming("max wait", i);
467
	i = (c>>2)&0x7;
468
	if(i != 7)
469
		ttiming("max ready/busy wait", i);
470
	i = (c>>5)&0x7;
471
	if(i != 7)
472
		ttiming("reserved wait", i);
473
}
474
 
475
void
476
range(int asize, int lsize)
477
{
478
	ulong address, len;
479
 
480
	address = getlong(asize);
481
	len = getlong(lsize);
482
	print("\t\t%lux - %lux\n", address, address+len);
483
}
484
 
485
char *ioaccess[4] =
486
{
487
	" no access",
488
	" 8bit access only",
489
	" 8bit or 16bit access",
490
	" selectable 8bit or 8&16bit access",
491
};
492
 
493
int
494
iospace(uchar c)
495
{
496
	int i;
497
 
498
	print("\tIO space %d address lines%s\n", c&0x1f, ioaccess[(c>>5)&3]);
499
	if((c & 0x80) == 0)
500
		return -1;
501
 
502
	if(readc(&c) != 1)
503
		return -1;
504
 
505
	for(i = (c&0xf)+1; i; i--)
506
		range((c>>4)&0x3, (c>>6)&0x3);
507
	return 0;
508
}
509
 
510
void
511
iospaces(void)
512
{
513
	uchar c;
514
 
515
	if(readc(&c) != 1)
516
		return;
517
	iospace(c);
518
}
519
 
520
void
521
irq(void)
522
{
523
	uchar c;
524
	uchar irq1, irq2;
525
	ushort i, irqs;
526
 
527
	if(readc(&c) != 1)
528
		return;
529
	if(c & 0x10){
530
		if(readc(&irq1) != 1)
531
			return;
532
		if(readc(&irq2) != 1)
533
			return;
534
		irqs = irq1|(irq2<<8);
535
	} else
536
		irqs = 1<<(c&0xf);
537
	print("\tinterrupts%s%s%s", (c&0x20)?":level":"", (c&0x40)?":pulse":"",
538
		(c&0x80)?":shared":"");
539
	for(i = 0; i < 16; i++)
540
		if(irqs & (1<<i))
541
			print(", %d", i);
542
	print("\n");
543
}
544
 
545
void
546
memspace(int asize, int lsize, int host)
547
{
548
	ulong haddress, address, len;
549
 
550
	len = getlong(lsize)*256;
551
	address = getlong(asize)*256;
552
	if(host){
553
		haddress = getlong(asize)*256;
554
		print("\tmemory address range 0x%lux - 0x%lux hostaddr 0x%lux\n",
555
			address, address+len, haddress);
556
	} else
557
		print("\tmemory address range 0x%lux - 0x%lux\n", address, address+len);
558
}
559
 
560
void
561
misc(void)
562
{
563
}
564
 
565
void
566
tentry(int ttype, int len)
567
{
568
	uchar c, i, feature;
569
	char *tname;
570
	char buf[16];
571
 
572
	USED(ttype, len);
573
	if(readc(&c) != 1)
574
		return;
575
	print("configuration %d%s\n", c&0x3f, (c&0x40)?" (default)":"");
576
	if(c & 0x80){
577
		if(readc(&i) != 1)
578
			return;
579
		tname = intrname[i & 0xf];
580
		if(tname == 0){
581
			tname = buf;
582
			sprint(buf, "type %d", i & 0xf);
583
		}
584
		print("\t%s device, %s%s%s%s\n", tname,
585
			(i&0x10)?" Battery status active":"",
586
			(i&0x20)?" Write Protect active":"",
587
			(i&0x40)?" Ready/Busy active":"",
588
			(i&0x80)?" Memory Wait required":"");
589
	}
590
	if(readc(&feature) != 1)
591
		return;
592
	switch(feature&0x3){
593
	case 1:
594
		power("Vcc");
595
		break;
596
	case 2:
597
		power("Vcc");
598
		power("Vpp");
599
		break;
600
	case 3:
601
		power("Vcc");
602
		power("Vpp1");
603
		power("Vpp2");
604
		break;
605
	}
606
	if(feature&0x4)
607
		timing();
608
	if(feature&0x8)
609
		iospaces();
610
	if(feature&0x10)
611
		irq();
612
	switch((feature>>5)&0x3){
613
	case 1:
614
		memspace(0, 2, 0);
615
		break;
616
	case 2:
617
		memspace(2, 2, 0);
618
		break;
619
	case 3:
620
		if(readc(&c) != 1)
621
			return;
622
		for(i = 0; i <= (c&0x7); i++)
623
			memspace((c>>5)&0x3, (c>>3)&0x3, c&0x80);
624
		break;
625
	}
626
	if(feature&0x80)
627
		misc();
628
}