123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- #include <u.h>
- #include <libc.h>
- enum
- {
- Linktarget = 0x13,
- Funcid = 0x21,
- End = 0xff,
- };
- int fd;
- int pos;
- void tdevice(int, int);
- void tlonglnkmfc(int, int);
- void tfuncid(int, int);
- void tcfig(int, int);
- void tentry(int, int);
- void tvers1(int, int);
- void (*parse[256])(int, int) =
- {
- [1] tdevice,
- [6] tlonglnkmfc,
- [0x15] tvers1,
- [0x17] tdevice,
- [0x1A] tcfig,
- [0x1B] tentry,
- [Funcid] tfuncid,
- };
- int hex;
- void
- fatal(char *fmt, ...)
- {
- va_list arg;
- char buf[512];
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "pcmcia: %s\n", buf);
- exits(buf);
- }
- int
- readc(void *x)
- {
- int rv;
- seek(fd, 2*pos, 0);
- pos++;
- rv = read(fd, x, 1);
- if(hex)
- print("%2.2ux ", *(uchar*)x);
- return rv;
- }
- int
- tuple(int next, int expect)
- {
- uchar link;
- uchar type;
- pos = next;
- if(readc(&type) != 1)
- return -1;
- if(type == 0xff)
- return -1;
- print("type %.2uX\n", type & 0xff);
- if(expect && expect != type){
- print("expected %.2uX found %.2uX\n",
- expect, type);
- return -1;
- }
- if(readc(&link) != 1)
- return -1;
- if(parse[type])
- (*parse[type])(type, link);
- if(link == 0xff)
- next = -1;
- else
- next = next+2+link;
- return next;
- }
- void
- main(int argc, char *argv[])
- {
- char *file;
- int next;
- ARGBEGIN{
- case 'x':
- hex = 1;
- }ARGEND;
- if(argc == 0)
- file = "#y/pcm0attr";
- else
- file = argv[0];
- fd = open(file, OREAD);
- if(fd < 0)
- fatal("opening %s: %r", file);
- for(next = 0; next >= 0;)
- next = tuple(next, 0);
- }
- ulong speedtab[16] =
- {
- [1] 250,
- [2] 200,
- [3] 150,
- [4] 100,
- };
- ulong mantissa[16] =
- {
- [1] 10,
- [2] 12,
- [3] 13,
- [4] 15,
- [5] 20,
- [6] 25,
- [7] 30,
- [8] 35,
- [9] 40,
- [0xa] 45,
- [0xb] 50,
- [0xc] 55,
- [0xd] 60,
- [0xe] 70,
- [0xf] 80,
- };
- ulong exponent[8] =
- {
- [0] 1,
- [1] 10,
- [2] 100,
- [3] 1000,
- [4] 10000,
- [5] 100000,
- [6] 1000000,
- [7] 10000000,
- };
- char *typetab[256] =
- {
- [1] "Masked ROM",
- [2] "PROM",
- [3] "EPROM",
- [4] "EEPROM",
- [5] "FLASH",
- [6] "SRAM",
- [7] "DRAM",
- [0xD] "IO+MEM",
- };
- ulong
- getlong(int size)
- {
- uchar c;
- int i;
- ulong x;
- x = 0;
- for(i = 0; i < size; i++){
- if(readc(&c) != 1)
- break;
- x |= c<<(i*8);
- }
- return x;
- }
- void
- tdevice(int ttype, int len)
- {
- uchar id;
- uchar type;
- uchar speed, aespeed;
- uchar size;
- ulong bytes, ns;
- char *tname, *ttname;
- while(len > 0){
- if(readc(&id) != 1)
- return;
- len--;
- if(id == End)
- return;
- /* PRISM cards have a device tuple with id = size = 0. */
- if(id == 0x00){
- if(readc(&size) != 1)
- return;
- len--;
- continue;
- }
- speed = id & 0x7;
- if(speed == 0x7){
- if(readc(&speed) != 1)
- return;
- len--;
- if(speed & 0x80){
- if(readc(&aespeed) != 1)
- return;
- ns = 0;
- } else
- ns = (mantissa[(speed>>3)&0xf]*exponent[speed&7])/10;
- } else
- ns = speedtab[speed];
- type = id>>4;
- if(type == 0xE){
- if(readc(&type) != 1)
- return;
- len--;
- }
- tname = typetab[type];
- if(tname == 0)
- tname = "unknown";
- if(readc(&size) != 1)
- return;
- len--;
- bytes = ((size>>3)+1) * 512 * (1<<(2*(size&0x7)));
- if(ttype == 1)
- ttname = "device";
- else
- ttname = "attr device";
- print("%s %ld bytes of %ldns %s\n", ttname, bytes, ns, tname);
- }
- }
- void
- tlonglnkmfc(int, int)
- {
- int i, opos;
- uchar nfn, space, expect;
- int addr;
- readc(&nfn);
- for(i = 0; i < nfn; i++){
- readc(&space);
- addr = getlong(4);
- opos = pos;
- expect = Linktarget;
- while(addr > 0){
- addr = tuple(addr, expect);
- expect = 0;
- }
- pos = opos;
- }
- }
- static char *funcids[] = {
- "MULTI",
- "MEMORY",
- "SERIAL",
- "PARALLEL",
- "FIXED",
- "VIDEO",
- "NETWORK",
- "AIMS",
- "SCSI",
- };
- void
- tfuncid(int, int)
- {
- uchar func;
- readc(&func);
- print("Function %s\n",
- (func >= nelem(funcids))? "unknown function": funcids[func]);
- }
- void
- tvers1(int ttype, int len)
- {
- uchar c, major, minor;
- int i;
- char string[512];
- USED(ttype);
- if(readc(&major) != 1)
- return;
- len--;
- if(readc(&minor) != 1)
- return;
- len--;
- print("version %d.%d\n", major, minor);
- while(len > 0){
- for(i = 0; len > 0 && i < sizeof(string); i++){
- if(readc(&string[i]) != 1)
- return;
- len--;
- c = string[i];
- if(c == 0)
- break;
- if(c == 0xff){
- if(i != 0){
- string[i] = 0;
- print("\t%s<missing null>\n", string);
- }
- return;
- }
- }
- string[i] = 0;
- print("\t%s\n", string);
- }
- }
- void
- tcfig(int ttype, int len)
- {
- uchar size, rasize, rmsize;
- uchar last;
- ulong caddr;
- ulong cregs;
- int i;
- USED(ttype, len);
- if(readc(&size) != 1)
- return;
- rasize = (size&0x3) + 1;
- rmsize = ((size>>2)&0xf) + 1;
- if(readc(&last) != 1)
- return;
- caddr = getlong(rasize);
- cregs = getlong(rmsize);
- print("configuration registers at");
- for(i = 0; i < 16; i++)
- if((1<<i) & cregs)
- print(" (%d)0x%lux", i, caddr + i*2);
- print("\n");
- }
- char *intrname[16] =
- {
- [0] "memory",
- [1] "I/O",
- [4] "Custom 0",
- [5] "Custom 1",
- [6] "Custom 2",
- [7] "Custom 3",
- };
- ulong vexp[8] =
- {
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
- };
- ulong vmant[16] =
- {
- 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
- };
- void
- volt(char *name)
- {
- uchar c;
- ulong microv;
- ulong exp;
- if(readc(&c) != 1)
- return;
- exp = vexp[c&0x7];
- microv = vmant[(c>>3)&0xf]*exp;
- while(c & 0x80){
- if(readc(&c) != 1)
- return;
- switch(c){
- case 0x7d:
- break; /* high impedence when sleeping */
- case 0x7e:
- case 0x7f:
- microv = 0; /* no connection */
- break;
- default:
- exp /= 10;
- microv += exp*(c&0x7f);
- }
- }
- print(" V%s %lduV", name, microv);
- }
- void
- amps(char *name)
- {
- uchar c;
- ulong amps;
- if(readc(&c) != 1)
- return;
- amps = vexp[c&0x7]*vmant[(c>>3)&0xf];
- while(c & 0x80){
- if(readc(&c) != 1)
- return;
- if(c == 0x7d || c == 0x7e || c == 0x7f)
- amps = 0;
- }
- if(amps >= 1000000)
- print(" I%s %ldmA", name, amps/100000);
- else if(amps >= 1000)
- print(" I%s %lduA", name, amps/100);
- else
- print(" I%s %ldnA", name, amps*10);
- }
- void
- power(char *name)
- {
- uchar feature;
- print("\t%s: ", name);
- if(readc(&feature) != 1)
- return;
- if(feature & 1)
- volt("nominal");
- if(feature & 2)
- volt("min");
- if(feature & 4)
- volt("max");
- if(feature & 8)
- amps("static");
- if(feature & 0x10)
- amps("avg");
- if(feature & 0x20)
- amps("peak");
- if(feature & 0x40)
- amps("powerdown");
- print("\n");
- }
- void
- ttiming(char *name, int scale)
- {
- uchar unscaled;
- ulong scaled;
- if(readc(&unscaled) != 1)
- return;
- scaled = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
- scaled = scaled * vexp[scale];
- print("\t%s %ldns\n", name, scaled);
- }
- void
- timing(void)
- {
- uchar c, i;
- if(readc(&c) != 1)
- return;
- i = c&0x3;
- if(i != 3)
- ttiming("max wait", i);
- i = (c>>2)&0x7;
- if(i != 7)
- ttiming("max ready/busy wait", i);
- i = (c>>5)&0x7;
- if(i != 7)
- ttiming("reserved wait", i);
- }
- void
- range(int asize, int lsize)
- {
- ulong address, len;
- address = getlong(asize);
- len = getlong(lsize);
- print("\t\t%lux - %lux\n", address, address+len);
- }
- char *ioaccess[4] =
- {
- " no access",
- " 8bit access only",
- " 8bit or 16bit access",
- " selectable 8bit or 8&16bit access",
- };
- int
- iospace(uchar c)
- {
- int i;
- print("\tIO space %d address lines%s\n", c&0x1f, ioaccess[(c>>5)&3]);
- if((c & 0x80) == 0)
- return -1;
- if(readc(&c) != 1)
- return -1;
- for(i = (c&0xf)+1; i; i--)
- range((c>>4)&0x3, (c>>6)&0x3);
- return 0;
- }
- void
- iospaces(void)
- {
- uchar c;
- if(readc(&c) != 1)
- return;
- iospace(c);
- }
- void
- irq(void)
- {
- uchar c;
- uchar irq1, irq2;
- ushort i, irqs;
- if(readc(&c) != 1)
- return;
- if(c & 0x10){
- if(readc(&irq1) != 1)
- return;
- if(readc(&irq2) != 1)
- return;
- irqs = irq1|(irq2<<8);
- } else
- irqs = 1<<(c&0xf);
- print("\tinterrupts%s%s%s", (c&0x20)?":level":"", (c&0x40)?":pulse":"",
- (c&0x80)?":shared":"");
- for(i = 0; i < 16; i++)
- if(irqs & (1<<i))
- print(", %d", i);
- print("\n");
- }
- void
- memspace(int asize, int lsize, int host)
- {
- ulong haddress, address, len;
- len = getlong(lsize)*256;
- address = getlong(asize)*256;
- if(host){
- haddress = getlong(asize)*256;
- print("\tmemory address range 0x%lux - 0x%lux hostaddr 0x%lux\n",
- address, address+len, haddress);
- } else
- print("\tmemory address range 0x%lux - 0x%lux\n", address, address+len);
- }
- void
- misc(void)
- {
- }
- void
- tentry(int ttype, int len)
- {
- uchar c, i, feature;
- char *tname;
- char buf[16];
- USED(ttype, len);
- if(readc(&c) != 1)
- return;
- print("configuration %d%s\n", c&0x3f, (c&0x40)?" (default)":"");
- if(c & 0x80){
- if(readc(&i) != 1)
- return;
- tname = intrname[i & 0xf];
- if(tname == 0){
- tname = buf;
- sprint(buf, "type %d", i & 0xf);
- }
- print("\t%s device, %s%s%s%s\n", tname,
- (i&0x10)?" Battery status active":"",
- (i&0x20)?" Write Protect active":"",
- (i&0x40)?" Ready/Busy active":"",
- (i&0x80)?" Memory Wait required":"");
- }
- if(readc(&feature) != 1)
- return;
- switch(feature&0x3){
- case 1:
- power("Vcc");
- break;
- case 2:
- power("Vcc");
- power("Vpp");
- break;
- case 3:
- power("Vcc");
- power("Vpp1");
- power("Vpp2");
- break;
- }
- if(feature&0x4)
- timing();
- if(feature&0x8)
- iospaces();
- if(feature&0x10)
- irq();
- switch((feature>>5)&0x3){
- case 1:
- memspace(0, 2, 0);
- break;
- case 2:
- memspace(2, 2, 0);
- break;
- case 3:
- if(readc(&c) != 1)
- return;
- for(i = 0; i <= (c&0x7); i++)
- memspace((c>>5)&0x3, (c>>3)&0x3, c&0x80);
- break;
- }
- if(feature&0x80)
- misc();
- }
|