]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/pcmcia.c
audiohda: fix syntax error
[plan9front.git] / sys / src / cmd / aux / pcmcia.c
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 }