📄 pcmcia.c
字号:
#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;voidfatal(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);}intreadc(void *x){ int rv; seek(fd, 2*pos, 0); pos++; rv = read(fd, x, 1); if(hex) print("%2.2ux ", *(uchar*)x); return rv;}inttuple(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;}voidmain(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",};ulonggetlong(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;}voidtdevice(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); }}voidtlonglnkmfc(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",};voidtfuncid(int, int){ uchar func; readc(&func); print("Function %s\n", (func >= nelem(funcids))? "unknown function": funcids[func]);}voidtvers1(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); }}voidtcfig(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,};voidvolt(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);}voidamps(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);}voidpower(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");}voidttiming(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);}voidtiming(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);}voidrange(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",};intiospace(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;}voidiospaces(void){ uchar c; if(readc(&c) != 1) return; iospace(c);}voidirq(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");}voidmemspace(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);}voidmisc(void){}voidtentry(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();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -