123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- #include "u.h"
- #include "lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "error.h"
- #include "io.h"
- enum{
- Linktarget = 0x13,
- };
-
- /*
- * read and crack the card information structure enough to set
- * important parameters like power
- */
- /* cis memory walking */
- typedef struct Cisdat {
- uchar *cisbase;
- int cispos;
- int cisskip;
- int cislen;
- } Cisdat;
- static void tcfig(PCMslot*, Cisdat*, int);
- static void tentry(PCMslot*, Cisdat*, int);
- static void tvers1(PCMslot*, Cisdat*, int);
- static void tlonglnkmfc(PCMslot*, Cisdat*, int);
- static int
- readc(Cisdat *cis, uchar *x)
- {
- if(cis->cispos >= cis->cislen)
- return 0;
- *x = cis->cisbase[cis->cisskip*cis->cispos];
- cis->cispos++;
- return 1;
- }
- static int
- xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
- {
- PCMmap *m;
- Cisdat cis;
- int i, l;
- uchar *p;
- uchar type, link, n, c;
- int this, subtype;
- m = pcmmap(slotno, 0, 0, attr);
- if(m == 0)
- return -1;
- cis.cisbase = KADDR(m->isa);
- cis.cispos = 0;
- cis.cisskip = attr ? 2 : 1;
- cis.cislen = m->len;
- /* loop through all the tuples */
- for(i = 0; i < 1000; i++){
- this = cis.cispos;
- if(readc(&cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(&cis, &link) != 1)
- break;
- if(link == 0xFF)
- break;
- n = link;
- if(link > 1 && subtuple != -1){
- if(readc(&cis, &c) != 1)
- break;
- subtype = c;
- n--;
- }else
- subtype = -1;
- if(type == tuple && subtype == subtuple){
- p = v;
- for(l=0; l<nv && l<n; l++)
- if(readc(&cis, p++) != 1)
- break;
- pcmunmap(slotno, m);
- return nv;
- }
- cis.cispos = this + (2+link);
- }
- pcmunmap(slotno, m);
- return -1;
- }
- int
- pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
- {
- int n;
- /* try attribute space, then memory */
- if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
- return n;
- return xcistuple(slotno, tuple, subtuple, v, nv, 0);
- }
- void
- pcmcisread(PCMslot *pp)
- {
- int this;
- Cisdat cis;
- PCMmap *m;
- uchar type, link;
- memset(pp->ctab, 0, sizeof(pp->ctab));
- pp->ncfg = 0;
- memset(pp->cfg, 0, sizeof(pp->cfg));
- pp->configed = 0;
- pp->nctab = 0;
- pp->verstr[0] = 0;
- /*
- * Read all tuples in attribute space.
- */
- m = pcmmap(pp->slotno, 0, 0, 1);
- if(m == 0)
- return;
- cis.cisbase = KADDR(m->isa);
- cis.cispos = 0;
- cis.cisskip = 2;
- cis.cislen = m->len;
- /* loop through all the tuples */
- for(;;){
- this = cis.cispos;
- if(readc(&cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(&cis, &link) != 1)
- break;
- switch(type){
- default:
- break;
- case 6:
- tlonglnkmfc(pp, &cis, type);
- break;
- case 0x15:
- tvers1(pp, &cis, type);
- break;
- case 0x1A:
- tcfig(pp, &cis, type);
- break;
- case 0x1B:
- tentry(pp, &cis, type);
- break;
- }
- if(link == 0xFF)
- break;
- cis.cispos = this + (2+link);
- }
- pcmunmap(pp->slotno, m);
- }
- static ulong
- getlong(Cisdat *cis, int size)
- {
- uchar c;
- int i;
- ulong x;
- x = 0;
- for(i = 0; i < size; i++){
- if(readc(cis, &c) != 1)
- break;
- x |= c<<(i*8);
- }
- return x;
- }
- static void
- tcfig(PCMslot *pp, Cisdat *cis, int )
- {
- uchar size, rasize, rmsize;
- uchar last;
- if(readc(cis, &size) != 1)
- return;
- rasize = (size&0x3) + 1;
- rmsize = ((size>>2)&0xf) + 1;
- if(readc(cis, &last) != 1)
- return;
- if(pp->ncfg >= 8){
- print("tcfig: too many configuration registers\n");
- return;
- }
-
- pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
- pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
- pp->ncfg++;
- }
- static ulong vexp[8] =
- {
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
- };
- static ulong vmant[16] =
- {
- 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
- };
- static ulong
- microvolt(Cisdat *cis)
- {
- uchar c;
- ulong microvolts;
- ulong exp;
- if(readc(cis, &c) != 1)
- return 0;
- exp = vexp[c&0x7];
- microvolts = vmant[(c>>3)&0xf]*exp;
- while(c & 0x80){
- if(readc(cis, &c) != 1)
- return 0;
- switch(c){
- case 0x7d:
- break; /* high impedence when sleeping */
- case 0x7e:
- case 0x7f:
- microvolts = 0; /* no connection */
- break;
- default:
- exp /= 10;
- microvolts += exp*(c&0x7f);
- }
- }
- return microvolts;
- }
- static ulong
- nanoamps(Cisdat *cis)
- {
- uchar c;
- ulong nanoamps;
- if(readc(cis, &c) != 1)
- return 0;
- nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
- while(c & 0x80){
- if(readc(cis, &c) != 1)
- return 0;
- if(c == 0x7d || c == 0x7e || c == 0x7f)
- nanoamps = 0;
- }
- return nanoamps;
- }
- /*
- * only nominal voltage (feature 1) is important for config,
- * other features must read card to stay in sync.
- */
- static ulong
- power(Cisdat *cis)
- {
- uchar feature;
- ulong mv;
- mv = 0;
- if(readc(cis, &feature) != 1)
- return 0;
- if(feature & 1)
- mv = microvolt(cis);
- if(feature & 2)
- microvolt(cis);
- if(feature & 4)
- microvolt(cis);
- if(feature & 8)
- nanoamps(cis);
- if(feature & 0x10)
- nanoamps(cis);
- if(feature & 0x20)
- nanoamps(cis);
- if(feature & 0x40)
- nanoamps(cis);
- return mv/1000000;
- }
- static ulong mantissa[16] =
- { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
- static ulong exponent[8] =
- { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
- static ulong
- ttiming(Cisdat *cis, int scale)
- {
- uchar unscaled;
- ulong nanosecs;
- if(readc(cis, &unscaled) != 1)
- return 0;
- nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
- nanosecs = nanosecs * vexp[scale];
- return nanosecs;
- }
- static void
- timing(Cisdat *cis, PCMconftab *ct)
- {
- uchar c, i;
- if(readc(cis, &c) != 1)
- return;
- i = c&0x3;
- if(i != 3)
- ct->maxwait = ttiming(cis, i); /* max wait */
- i = (c>>2)&0x7;
- if(i != 7)
- ct->readywait = ttiming(cis, i); /* max ready/busy wait */
- i = (c>>5)&0x7;
- if(i != 7)
- ct->otherwait = ttiming(cis, i); /* reserved wait */
- }
- static void
- iospaces(Cisdat *cis, PCMconftab *ct)
- {
- uchar c;
- int i, nio;
- ct->nio = 0;
- if(readc(cis, &c) != 1)
- return;
- ct->bit16 = ((c>>5)&3) >= 2;
- if(!(c & 0x80)){
- ct->io[0].start = 0;
- ct->io[0].len = 1<<(c&0x1f);
- ct->nio = 1;
- return;
- }
- if(readc(cis, &c) != 1)
- return;
- /*
- * For each of the range descriptions read the
- * start address and the length (value is length-1).
- */
- nio = (c&0xf)+1;
- for(i = 0; i < nio; i++){
- ct->io[i].start = getlong(cis, (c>>4)&0x3);
- ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
- }
- ct->nio = nio;
- }
- static void
- irq(Cisdat *cis, PCMconftab *ct)
- {
- uchar c;
- if(readc(cis, &c) != 1)
- return;
- ct->irqtype = c & 0xe0;
- if(c & 0x10)
- ct->irqs = getlong(cis, 2);
- else
- ct->irqs = 1<<(c&0xf);
- ct->irqs &= 0xDEB8; /* levels available to card */
- }
- static void
- memspace(Cisdat *cis, int asize, int lsize, int host)
- {
- ulong haddress, address, len;
- len = getlong(cis, lsize)*256;
- address = getlong(cis, asize)*256;
- USED(len, address);
- if(host){
- haddress = getlong(cis, asize)*256;
- USED(haddress);
- }
- }
- static void
- tentry(PCMslot *pp, Cisdat *cis, int )
- {
- uchar c, i, feature;
- PCMconftab *ct;
- if(pp->nctab >= nelem(pp->ctab))
- return;
- if(readc(cis, &c) != 1)
- return;
- ct = &pp->ctab[pp->nctab++];
- /* copy from last default config */
- if(pp->def)
- *ct = *pp->def;
- ct->index = c & 0x3f;
- /* is this the new default? */
- if(c & 0x40)
- pp->def = ct;
- /* memory wait specified? */
- if(c & 0x80){
- if(readc(cis, &i) != 1)
- return;
- if(i&0x80)
- ct->memwait = 1;
- }
- if(readc(cis, &feature) != 1)
- return;
- switch(feature&0x3){
- case 1:
- ct->vpp1 = ct->vpp2 = power(cis);
- break;
- case 2:
- power(cis);
- ct->vpp1 = ct->vpp2 = power(cis);
- break;
- case 3:
- power(cis);
- ct->vpp1 = power(cis);
- ct->vpp2 = power(cis);
- break;
- default:
- break;
- }
- if(feature&0x4)
- timing(cis, ct);
- if(feature&0x8)
- iospaces(cis, ct);
- if(feature&0x10)
- irq(cis, ct);
- switch((feature>>5)&0x3){
- case 1:
- memspace(cis, 0, 2, 0);
- break;
- case 2:
- memspace(cis, 2, 2, 0);
- break;
- case 3:
- if(readc(cis, &c) != 1)
- return;
- for(i = 0; i <= (c&0x7); i++)
- memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
- break;
- }
- pp->configed++;
- }
- static void
- tvers1(PCMslot *pp, Cisdat *cis, int )
- {
- uchar c, major, minor, last;
- int i;
- if(readc(cis, &major) != 1)
- return;
- if(readc(cis, &minor) != 1)
- return;
- last = 0;
- for(i = 0; i < sizeof(pp->verstr)-1; i++){
- if(readc(cis, &c) != 1)
- return;
- if(c == 0)
- c = ';';
- if(c == '\n')
- c = ';';
- if(c == 0xff)
- break;
- if(c == ';' && last == ';')
- continue;
- pp->verstr[i] = c;
- last = c;
- }
- pp->verstr[i] = 0;
- }
- static void
- tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
- {
- int i, npos, opos;
- uchar nfn, space, expect, type, this, link;
- readc(cis, &nfn);
- for(i = 0; i < nfn; i++){
- readc(cis, &space);
- npos = getlong(cis, 4);
- opos = cis->cispos;
- cis->cispos = npos;
- expect = Linktarget;
- while(1){
- this = cis->cispos;
- if(readc(cis, &type) != 1)
- break;
- if(type == 0xFF)
- break;
- if(readc(cis, &link) != 1)
- break;
- if(expect && expect != type){
- print("tlonglnkmfc: expected %X found %X\n",
- expect, type);
- break;
- }
- expect = 0;
- switch(type){
- default:
- break;
- case 0x15:
- tvers1(pp, cis, type);
- break;
- case 0x1A:
- tcfig(pp, cis, type);
- break;
- case 0x1B:
- tentry(pp, cis, type);
- break;
- }
- if(link == 0xFF)
- break;
- cis->cispos = this + (2+link);
- }
- cis->cispos = opos;
- }
- }
|