180ee5cbfSDavid du Colombier #include "u.h"
280ee5cbfSDavid du Colombier #include "../port/lib.h"
380ee5cbfSDavid du Colombier #include "mem.h"
480ee5cbfSDavid du Colombier #include "dat.h"
580ee5cbfSDavid du Colombier #include "fns.h"
680ee5cbfSDavid du Colombier #include "../port/error.h"
780ee5cbfSDavid du Colombier #include "io.h"
880ee5cbfSDavid du Colombier
9*15174232SDavid du Colombier enum{
10*15174232SDavid du Colombier Linktarget = 0x13,
11*15174232SDavid du Colombier };
12*15174232SDavid du Colombier
1380ee5cbfSDavid du Colombier /*
1480ee5cbfSDavid du Colombier * read and crack the card information structure enough to set
1580ee5cbfSDavid du Colombier * important parameters like power
1680ee5cbfSDavid du Colombier */
179a747e4fSDavid du Colombier /* cis memory walking */
189a747e4fSDavid du Colombier typedef struct Cisdat {
199a747e4fSDavid du Colombier uchar *cisbase;
209a747e4fSDavid du Colombier int cispos;
219a747e4fSDavid du Colombier int cisskip;
229a747e4fSDavid du Colombier int cislen;
239a747e4fSDavid du Colombier } Cisdat;
249a747e4fSDavid du Colombier
2580ee5cbfSDavid du Colombier static void tcfig(PCMslot*, Cisdat*, int);
2680ee5cbfSDavid du Colombier static void tentry(PCMslot*, Cisdat*, int);
2780ee5cbfSDavid du Colombier static void tvers1(PCMslot*, Cisdat*, int);
28*15174232SDavid du Colombier static void tlonglnkmfc(PCMslot*, Cisdat*, int);
2980ee5cbfSDavid du Colombier
3080ee5cbfSDavid du Colombier static int
readc(Cisdat * cis,uchar * x)319a747e4fSDavid du Colombier readc(Cisdat *cis, uchar *x)
3280ee5cbfSDavid du Colombier {
339a747e4fSDavid du Colombier if(cis->cispos >= cis->cislen)
3480ee5cbfSDavid du Colombier return 0;
359a747e4fSDavid du Colombier *x = cis->cisbase[cis->cisskip*cis->cispos];
369a747e4fSDavid du Colombier cis->cispos++;
3780ee5cbfSDavid du Colombier return 1;
3880ee5cbfSDavid du Colombier }
3980ee5cbfSDavid du Colombier
4080ee5cbfSDavid du Colombier static int
xcistuple(int slotno,int tuple,int subtuple,void * v,int nv,int attr)4180ee5cbfSDavid du Colombier xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
4280ee5cbfSDavid du Colombier {
4380ee5cbfSDavid du Colombier PCMmap *m;
4480ee5cbfSDavid du Colombier Cisdat cis;
4580ee5cbfSDavid du Colombier int i, l;
4680ee5cbfSDavid du Colombier uchar *p;
4780ee5cbfSDavid du Colombier uchar type, link, n, c;
4880ee5cbfSDavid du Colombier int this, subtype;
4980ee5cbfSDavid du Colombier
5080ee5cbfSDavid du Colombier m = pcmmap(slotno, 0, 0, attr);
5180ee5cbfSDavid du Colombier if(m == 0)
5280ee5cbfSDavid du Colombier return -1;
5380ee5cbfSDavid du Colombier
5480ee5cbfSDavid du Colombier cis.cisbase = KADDR(m->isa);
5580ee5cbfSDavid du Colombier cis.cispos = 0;
5680ee5cbfSDavid du Colombier cis.cisskip = attr ? 2 : 1;
5780ee5cbfSDavid du Colombier cis.cislen = m->len;
5880ee5cbfSDavid du Colombier
5980ee5cbfSDavid du Colombier /* loop through all the tuples */
6080ee5cbfSDavid du Colombier for(i = 0; i < 1000; i++){
6180ee5cbfSDavid du Colombier this = cis.cispos;
6280ee5cbfSDavid du Colombier if(readc(&cis, &type) != 1)
6380ee5cbfSDavid du Colombier break;
6480ee5cbfSDavid du Colombier if(type == 0xFF)
6580ee5cbfSDavid du Colombier break;
6680ee5cbfSDavid du Colombier if(readc(&cis, &link) != 1)
6780ee5cbfSDavid du Colombier break;
6880ee5cbfSDavid du Colombier if(link == 0xFF)
6980ee5cbfSDavid du Colombier break;
7080ee5cbfSDavid du Colombier
7180ee5cbfSDavid du Colombier n = link;
7280ee5cbfSDavid du Colombier if(link > 1 && subtuple != -1){
7380ee5cbfSDavid du Colombier if(readc(&cis, &c) != 1)
7480ee5cbfSDavid du Colombier break;
7580ee5cbfSDavid du Colombier subtype = c;
7680ee5cbfSDavid du Colombier n--;
7780ee5cbfSDavid du Colombier }else
7880ee5cbfSDavid du Colombier subtype = -1;
7980ee5cbfSDavid du Colombier
8080ee5cbfSDavid du Colombier if(type == tuple && subtype == subtuple){
8180ee5cbfSDavid du Colombier p = v;
8280ee5cbfSDavid du Colombier for(l=0; l<nv && l<n; l++)
8380ee5cbfSDavid du Colombier if(readc(&cis, p++) != 1)
8480ee5cbfSDavid du Colombier break;
8580ee5cbfSDavid du Colombier pcmunmap(slotno, m);
8680ee5cbfSDavid du Colombier return nv;
8780ee5cbfSDavid du Colombier }
8880ee5cbfSDavid du Colombier cis.cispos = this + (2+link);
8980ee5cbfSDavid du Colombier }
9080ee5cbfSDavid du Colombier pcmunmap(slotno, m);
9180ee5cbfSDavid du Colombier return -1;
9280ee5cbfSDavid du Colombier }
9380ee5cbfSDavid du Colombier
9480ee5cbfSDavid du Colombier int
pcmcistuple(int slotno,int tuple,int subtuple,void * v,int nv)9580ee5cbfSDavid du Colombier pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
9680ee5cbfSDavid du Colombier {
9780ee5cbfSDavid du Colombier int n;
9880ee5cbfSDavid du Colombier
9980ee5cbfSDavid du Colombier /* try attribute space, then memory */
10080ee5cbfSDavid du Colombier if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
10180ee5cbfSDavid du Colombier return n;
10280ee5cbfSDavid du Colombier return xcistuple(slotno, tuple, subtuple, v, nv, 0);
10380ee5cbfSDavid du Colombier }
10480ee5cbfSDavid du Colombier
10580ee5cbfSDavid du Colombier void
pcmcisread(PCMslot * pp)10680ee5cbfSDavid du Colombier pcmcisread(PCMslot *pp)
10780ee5cbfSDavid du Colombier {
1089a747e4fSDavid du Colombier int this;
10980ee5cbfSDavid du Colombier Cisdat cis;
1109a747e4fSDavid du Colombier PCMmap *m;
1119a747e4fSDavid du Colombier uchar type, link;
11280ee5cbfSDavid du Colombier
11380ee5cbfSDavid du Colombier memset(pp->ctab, 0, sizeof(pp->ctab));
114*15174232SDavid du Colombier pp->ncfg = 0;
115*15174232SDavid du Colombier memset(pp->cfg, 0, sizeof(pp->cfg));
11680ee5cbfSDavid du Colombier pp->configed = 0;
11780ee5cbfSDavid du Colombier pp->nctab = 0;
11880ee5cbfSDavid du Colombier pp->verstr[0] = 0;
11980ee5cbfSDavid du Colombier
1209a747e4fSDavid du Colombier /*
1219a747e4fSDavid du Colombier * Read all tuples in attribute space.
1229a747e4fSDavid du Colombier */
1239a747e4fSDavid du Colombier m = pcmmap(pp->slotno, 0, 0, 1);
1249a747e4fSDavid du Colombier if(m == 0)
1259a747e4fSDavid du Colombier return;
12680ee5cbfSDavid du Colombier
1279a747e4fSDavid du Colombier cis.cisbase = KADDR(m->isa);
1289a747e4fSDavid du Colombier cis.cispos = 0;
1299a747e4fSDavid du Colombier cis.cisskip = 2;
1309a747e4fSDavid du Colombier cis.cislen = m->len;
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier /* loop through all the tuples */
1339a747e4fSDavid du Colombier for(;;){
1349a747e4fSDavid du Colombier this = cis.cispos;
1359a747e4fSDavid du Colombier if(readc(&cis, &type) != 1)
1369a747e4fSDavid du Colombier break;
1379a747e4fSDavid du Colombier if(type == 0xFF)
1389a747e4fSDavid du Colombier break;
1399a747e4fSDavid du Colombier if(readc(&cis, &link) != 1)
1409a747e4fSDavid du Colombier break;
1419a747e4fSDavid du Colombier
1429a747e4fSDavid du Colombier switch(type){
1439a747e4fSDavid du Colombier default:
1449a747e4fSDavid du Colombier break;
145*15174232SDavid du Colombier case 6:
146*15174232SDavid du Colombier tlonglnkmfc(pp, &cis, type);
147*15174232SDavid du Colombier break;
1489a747e4fSDavid du Colombier case 0x15:
1499a747e4fSDavid du Colombier tvers1(pp, &cis, type);
1509a747e4fSDavid du Colombier break;
1519a747e4fSDavid du Colombier case 0x1A:
1529a747e4fSDavid du Colombier tcfig(pp, &cis, type);
1539a747e4fSDavid du Colombier break;
1549a747e4fSDavid du Colombier case 0x1B:
1559a747e4fSDavid du Colombier tentry(pp, &cis, type);
1569a747e4fSDavid du Colombier break;
15780ee5cbfSDavid du Colombier }
1589a747e4fSDavid du Colombier
1599a747e4fSDavid du Colombier if(link == 0xFF)
1609a747e4fSDavid du Colombier break;
1619a747e4fSDavid du Colombier cis.cispos = this + (2+link);
16280ee5cbfSDavid du Colombier }
1639a747e4fSDavid du Colombier pcmunmap(pp->slotno, m);
16480ee5cbfSDavid du Colombier }
16580ee5cbfSDavid du Colombier
16680ee5cbfSDavid du Colombier static ulong
getlong(Cisdat * cis,int size)16780ee5cbfSDavid du Colombier getlong(Cisdat *cis, int size)
16880ee5cbfSDavid du Colombier {
16980ee5cbfSDavid du Colombier uchar c;
17080ee5cbfSDavid du Colombier int i;
17180ee5cbfSDavid du Colombier ulong x;
17280ee5cbfSDavid du Colombier
17380ee5cbfSDavid du Colombier x = 0;
17480ee5cbfSDavid du Colombier for(i = 0; i < size; i++){
17580ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
17680ee5cbfSDavid du Colombier break;
17780ee5cbfSDavid du Colombier x |= c<<(i*8);
17880ee5cbfSDavid du Colombier }
17980ee5cbfSDavid du Colombier return x;
18080ee5cbfSDavid du Colombier }
18180ee5cbfSDavid du Colombier
18280ee5cbfSDavid du Colombier static void
tcfig(PCMslot * pp,Cisdat * cis,int)18380ee5cbfSDavid du Colombier tcfig(PCMslot *pp, Cisdat *cis, int )
18480ee5cbfSDavid du Colombier {
18580ee5cbfSDavid du Colombier uchar size, rasize, rmsize;
18680ee5cbfSDavid du Colombier uchar last;
18780ee5cbfSDavid du Colombier
18880ee5cbfSDavid du Colombier if(readc(cis, &size) != 1)
18980ee5cbfSDavid du Colombier return;
19080ee5cbfSDavid du Colombier rasize = (size&0x3) + 1;
19180ee5cbfSDavid du Colombier rmsize = ((size>>2)&0xf) + 1;
19280ee5cbfSDavid du Colombier if(readc(cis, &last) != 1)
19380ee5cbfSDavid du Colombier return;
194*15174232SDavid du Colombier
195*15174232SDavid du Colombier if(pp->ncfg >= 8){
196*15174232SDavid du Colombier print("tcfig: too many configuration registers\n");
197*15174232SDavid du Colombier return;
198*15174232SDavid du Colombier }
199*15174232SDavid du Colombier
200*15174232SDavid du Colombier pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
201*15174232SDavid du Colombier pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
202*15174232SDavid du Colombier pp->ncfg++;
20380ee5cbfSDavid du Colombier }
20480ee5cbfSDavid du Colombier
20580ee5cbfSDavid du Colombier static ulong vexp[8] =
20680ee5cbfSDavid du Colombier {
20780ee5cbfSDavid du Colombier 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
20880ee5cbfSDavid du Colombier };
20980ee5cbfSDavid du Colombier static ulong vmant[16] =
21080ee5cbfSDavid du Colombier {
21180ee5cbfSDavid du Colombier 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
21280ee5cbfSDavid du Colombier };
21380ee5cbfSDavid du Colombier
21480ee5cbfSDavid du Colombier static ulong
microvolt(Cisdat * cis)21580ee5cbfSDavid du Colombier microvolt(Cisdat *cis)
21680ee5cbfSDavid du Colombier {
21780ee5cbfSDavid du Colombier uchar c;
21880ee5cbfSDavid du Colombier ulong microvolts;
21980ee5cbfSDavid du Colombier ulong exp;
22080ee5cbfSDavid du Colombier
22180ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
22280ee5cbfSDavid du Colombier return 0;
22380ee5cbfSDavid du Colombier exp = vexp[c&0x7];
22480ee5cbfSDavid du Colombier microvolts = vmant[(c>>3)&0xf]*exp;
22580ee5cbfSDavid du Colombier while(c & 0x80){
22680ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
22780ee5cbfSDavid du Colombier return 0;
22880ee5cbfSDavid du Colombier switch(c){
22980ee5cbfSDavid du Colombier case 0x7d:
23080ee5cbfSDavid du Colombier break; /* high impedence when sleeping */
23180ee5cbfSDavid du Colombier case 0x7e:
23280ee5cbfSDavid du Colombier case 0x7f:
23380ee5cbfSDavid du Colombier microvolts = 0; /* no connection */
23480ee5cbfSDavid du Colombier break;
23580ee5cbfSDavid du Colombier default:
23680ee5cbfSDavid du Colombier exp /= 10;
23780ee5cbfSDavid du Colombier microvolts += exp*(c&0x7f);
23880ee5cbfSDavid du Colombier }
23980ee5cbfSDavid du Colombier }
24080ee5cbfSDavid du Colombier return microvolts;
24180ee5cbfSDavid du Colombier }
24280ee5cbfSDavid du Colombier
24380ee5cbfSDavid du Colombier static ulong
nanoamps(Cisdat * cis)24480ee5cbfSDavid du Colombier nanoamps(Cisdat *cis)
24580ee5cbfSDavid du Colombier {
24680ee5cbfSDavid du Colombier uchar c;
24780ee5cbfSDavid du Colombier ulong nanoamps;
24880ee5cbfSDavid du Colombier
24980ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
25080ee5cbfSDavid du Colombier return 0;
25180ee5cbfSDavid du Colombier nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
25280ee5cbfSDavid du Colombier while(c & 0x80){
25380ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
25480ee5cbfSDavid du Colombier return 0;
25580ee5cbfSDavid du Colombier if(c == 0x7d || c == 0x7e || c == 0x7f)
25680ee5cbfSDavid du Colombier nanoamps = 0;
25780ee5cbfSDavid du Colombier }
25880ee5cbfSDavid du Colombier return nanoamps;
25980ee5cbfSDavid du Colombier }
26080ee5cbfSDavid du Colombier
26180ee5cbfSDavid du Colombier /*
26280ee5cbfSDavid du Colombier * only nominal voltage (feature 1) is important for config,
26380ee5cbfSDavid du Colombier * other features must read card to stay in sync.
26480ee5cbfSDavid du Colombier */
26580ee5cbfSDavid du Colombier static ulong
power(Cisdat * cis)26680ee5cbfSDavid du Colombier power(Cisdat *cis)
26780ee5cbfSDavid du Colombier {
26880ee5cbfSDavid du Colombier uchar feature;
26980ee5cbfSDavid du Colombier ulong mv;
27080ee5cbfSDavid du Colombier
27180ee5cbfSDavid du Colombier mv = 0;
27280ee5cbfSDavid du Colombier if(readc(cis, &feature) != 1)
27380ee5cbfSDavid du Colombier return 0;
27480ee5cbfSDavid du Colombier if(feature & 1)
27580ee5cbfSDavid du Colombier mv = microvolt(cis);
27680ee5cbfSDavid du Colombier if(feature & 2)
27780ee5cbfSDavid du Colombier microvolt(cis);
27880ee5cbfSDavid du Colombier if(feature & 4)
27980ee5cbfSDavid du Colombier microvolt(cis);
28080ee5cbfSDavid du Colombier if(feature & 8)
28180ee5cbfSDavid du Colombier nanoamps(cis);
28280ee5cbfSDavid du Colombier if(feature & 0x10)
28380ee5cbfSDavid du Colombier nanoamps(cis);
28480ee5cbfSDavid du Colombier if(feature & 0x20)
28580ee5cbfSDavid du Colombier nanoamps(cis);
28680ee5cbfSDavid du Colombier if(feature & 0x40)
28780ee5cbfSDavid du Colombier nanoamps(cis);
28880ee5cbfSDavid du Colombier return mv/1000000;
28980ee5cbfSDavid du Colombier }
29080ee5cbfSDavid du Colombier
29180ee5cbfSDavid du Colombier static ulong mantissa[16] =
29280ee5cbfSDavid du Colombier { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
29380ee5cbfSDavid du Colombier
29480ee5cbfSDavid du Colombier static ulong exponent[8] =
29580ee5cbfSDavid du Colombier { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
29680ee5cbfSDavid du Colombier
29780ee5cbfSDavid du Colombier static ulong
ttiming(Cisdat * cis,int scale)29880ee5cbfSDavid du Colombier ttiming(Cisdat *cis, int scale)
29980ee5cbfSDavid du Colombier {
30080ee5cbfSDavid du Colombier uchar unscaled;
30180ee5cbfSDavid du Colombier ulong nanosecs;
30280ee5cbfSDavid du Colombier
30380ee5cbfSDavid du Colombier if(readc(cis, &unscaled) != 1)
30480ee5cbfSDavid du Colombier return 0;
30580ee5cbfSDavid du Colombier nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
30680ee5cbfSDavid du Colombier nanosecs = nanosecs * vexp[scale];
30780ee5cbfSDavid du Colombier return nanosecs;
30880ee5cbfSDavid du Colombier }
30980ee5cbfSDavid du Colombier
31080ee5cbfSDavid du Colombier static void
timing(Cisdat * cis,PCMconftab * ct)31180ee5cbfSDavid du Colombier timing(Cisdat *cis, PCMconftab *ct)
31280ee5cbfSDavid du Colombier {
31380ee5cbfSDavid du Colombier uchar c, i;
31480ee5cbfSDavid du Colombier
31580ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
31680ee5cbfSDavid du Colombier return;
31780ee5cbfSDavid du Colombier i = c&0x3;
31880ee5cbfSDavid du Colombier if(i != 3)
31980ee5cbfSDavid du Colombier ct->maxwait = ttiming(cis, i); /* max wait */
32080ee5cbfSDavid du Colombier i = (c>>2)&0x7;
32180ee5cbfSDavid du Colombier if(i != 7)
32280ee5cbfSDavid du Colombier ct->readywait = ttiming(cis, i); /* max ready/busy wait */
32380ee5cbfSDavid du Colombier i = (c>>5)&0x7;
32480ee5cbfSDavid du Colombier if(i != 7)
32580ee5cbfSDavid du Colombier ct->otherwait = ttiming(cis, i); /* reserved wait */
32680ee5cbfSDavid du Colombier }
32780ee5cbfSDavid du Colombier
32880ee5cbfSDavid du Colombier static void
iospaces(Cisdat * cis,PCMconftab * ct)32980ee5cbfSDavid du Colombier iospaces(Cisdat *cis, PCMconftab *ct)
33080ee5cbfSDavid du Colombier {
33180ee5cbfSDavid du Colombier uchar c;
33280ee5cbfSDavid du Colombier int i, nio;
33380ee5cbfSDavid du Colombier
33480ee5cbfSDavid du Colombier ct->nio = 0;
33580ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
33680ee5cbfSDavid du Colombier return;
33780ee5cbfSDavid du Colombier
33880ee5cbfSDavid du Colombier ct->bit16 = ((c>>5)&3) >= 2;
33980ee5cbfSDavid du Colombier if(!(c & 0x80)){
34080ee5cbfSDavid du Colombier ct->io[0].start = 0;
34180ee5cbfSDavid du Colombier ct->io[0].len = 1<<(c&0x1f);
34280ee5cbfSDavid du Colombier ct->nio = 1;
34380ee5cbfSDavid du Colombier return;
34480ee5cbfSDavid du Colombier }
34580ee5cbfSDavid du Colombier
34680ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
34780ee5cbfSDavid du Colombier return;
34880ee5cbfSDavid du Colombier
3499a747e4fSDavid du Colombier /*
3509a747e4fSDavid du Colombier * For each of the range descriptions read the
3519a747e4fSDavid du Colombier * start address and the length (value is length-1).
3529a747e4fSDavid du Colombier */
35380ee5cbfSDavid du Colombier nio = (c&0xf)+1;
35480ee5cbfSDavid du Colombier for(i = 0; i < nio; i++){
35580ee5cbfSDavid du Colombier ct->io[i].start = getlong(cis, (c>>4)&0x3);
3569a747e4fSDavid du Colombier ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
35780ee5cbfSDavid du Colombier }
35880ee5cbfSDavid du Colombier ct->nio = nio;
35980ee5cbfSDavid du Colombier }
36080ee5cbfSDavid du Colombier
36180ee5cbfSDavid du Colombier static void
irq(Cisdat * cis,PCMconftab * ct)36280ee5cbfSDavid du Colombier irq(Cisdat *cis, PCMconftab *ct)
36380ee5cbfSDavid du Colombier {
36480ee5cbfSDavid du Colombier uchar c;
36580ee5cbfSDavid du Colombier
36680ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
36780ee5cbfSDavid du Colombier return;
36880ee5cbfSDavid du Colombier ct->irqtype = c & 0xe0;
36980ee5cbfSDavid du Colombier if(c & 0x10)
37080ee5cbfSDavid du Colombier ct->irqs = getlong(cis, 2);
37180ee5cbfSDavid du Colombier else
37280ee5cbfSDavid du Colombier ct->irqs = 1<<(c&0xf);
37380ee5cbfSDavid du Colombier ct->irqs &= 0xDEB8; /* levels available to card */
37480ee5cbfSDavid du Colombier }
37580ee5cbfSDavid du Colombier
37680ee5cbfSDavid du Colombier static void
memspace(Cisdat * cis,int asize,int lsize,int host)37780ee5cbfSDavid du Colombier memspace(Cisdat *cis, int asize, int lsize, int host)
37880ee5cbfSDavid du Colombier {
37980ee5cbfSDavid du Colombier ulong haddress, address, len;
38080ee5cbfSDavid du Colombier
38180ee5cbfSDavid du Colombier len = getlong(cis, lsize)*256;
38280ee5cbfSDavid du Colombier address = getlong(cis, asize)*256;
38380ee5cbfSDavid du Colombier USED(len, address);
38480ee5cbfSDavid du Colombier if(host){
38580ee5cbfSDavid du Colombier haddress = getlong(cis, asize)*256;
38680ee5cbfSDavid du Colombier USED(haddress);
38780ee5cbfSDavid du Colombier }
38880ee5cbfSDavid du Colombier }
38980ee5cbfSDavid du Colombier
39080ee5cbfSDavid du Colombier static void
tentry(PCMslot * pp,Cisdat * cis,int)39180ee5cbfSDavid du Colombier tentry(PCMslot *pp, Cisdat *cis, int )
39280ee5cbfSDavid du Colombier {
39380ee5cbfSDavid du Colombier uchar c, i, feature;
39480ee5cbfSDavid du Colombier PCMconftab *ct;
39580ee5cbfSDavid du Colombier
39680ee5cbfSDavid du Colombier if(pp->nctab >= nelem(pp->ctab))
39780ee5cbfSDavid du Colombier return;
39880ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
39980ee5cbfSDavid du Colombier return;
40080ee5cbfSDavid du Colombier ct = &pp->ctab[pp->nctab++];
40180ee5cbfSDavid du Colombier
40280ee5cbfSDavid du Colombier /* copy from last default config */
40380ee5cbfSDavid du Colombier if(pp->def)
40480ee5cbfSDavid du Colombier *ct = *pp->def;
40580ee5cbfSDavid du Colombier
40680ee5cbfSDavid du Colombier ct->index = c & 0x3f;
40780ee5cbfSDavid du Colombier
40880ee5cbfSDavid du Colombier /* is this the new default? */
40980ee5cbfSDavid du Colombier if(c & 0x40)
41080ee5cbfSDavid du Colombier pp->def = ct;
41180ee5cbfSDavid du Colombier
41280ee5cbfSDavid du Colombier /* memory wait specified? */
41380ee5cbfSDavid du Colombier if(c & 0x80){
41480ee5cbfSDavid du Colombier if(readc(cis, &i) != 1)
41580ee5cbfSDavid du Colombier return;
41680ee5cbfSDavid du Colombier if(i&0x80)
41780ee5cbfSDavid du Colombier ct->memwait = 1;
41880ee5cbfSDavid du Colombier }
41980ee5cbfSDavid du Colombier
42080ee5cbfSDavid du Colombier if(readc(cis, &feature) != 1)
42180ee5cbfSDavid du Colombier return;
42280ee5cbfSDavid du Colombier switch(feature&0x3){
42380ee5cbfSDavid du Colombier case 1:
42480ee5cbfSDavid du Colombier ct->vpp1 = ct->vpp2 = power(cis);
42580ee5cbfSDavid du Colombier break;
42680ee5cbfSDavid du Colombier case 2:
42780ee5cbfSDavid du Colombier power(cis);
42880ee5cbfSDavid du Colombier ct->vpp1 = ct->vpp2 = power(cis);
42980ee5cbfSDavid du Colombier break;
43080ee5cbfSDavid du Colombier case 3:
43180ee5cbfSDavid du Colombier power(cis);
43280ee5cbfSDavid du Colombier ct->vpp1 = power(cis);
43380ee5cbfSDavid du Colombier ct->vpp2 = power(cis);
43480ee5cbfSDavid du Colombier break;
43580ee5cbfSDavid du Colombier default:
43680ee5cbfSDavid du Colombier break;
43780ee5cbfSDavid du Colombier }
43880ee5cbfSDavid du Colombier if(feature&0x4)
43980ee5cbfSDavid du Colombier timing(cis, ct);
44080ee5cbfSDavid du Colombier if(feature&0x8)
44180ee5cbfSDavid du Colombier iospaces(cis, ct);
44280ee5cbfSDavid du Colombier if(feature&0x10)
44380ee5cbfSDavid du Colombier irq(cis, ct);
44480ee5cbfSDavid du Colombier switch((feature>>5)&0x3){
44580ee5cbfSDavid du Colombier case 1:
44680ee5cbfSDavid du Colombier memspace(cis, 0, 2, 0);
44780ee5cbfSDavid du Colombier break;
44880ee5cbfSDavid du Colombier case 2:
44980ee5cbfSDavid du Colombier memspace(cis, 2, 2, 0);
45080ee5cbfSDavid du Colombier break;
45180ee5cbfSDavid du Colombier case 3:
45280ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
45380ee5cbfSDavid du Colombier return;
45480ee5cbfSDavid du Colombier for(i = 0; i <= (c&0x7); i++)
45580ee5cbfSDavid du Colombier memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
45680ee5cbfSDavid du Colombier break;
45780ee5cbfSDavid du Colombier }
45880ee5cbfSDavid du Colombier pp->configed++;
45980ee5cbfSDavid du Colombier }
46080ee5cbfSDavid du Colombier
46180ee5cbfSDavid du Colombier static void
tvers1(PCMslot * pp,Cisdat * cis,int)46280ee5cbfSDavid du Colombier tvers1(PCMslot *pp, Cisdat *cis, int )
46380ee5cbfSDavid du Colombier {
46480ee5cbfSDavid du Colombier uchar c, major, minor, last;
46580ee5cbfSDavid du Colombier int i;
46680ee5cbfSDavid du Colombier
46780ee5cbfSDavid du Colombier if(readc(cis, &major) != 1)
46880ee5cbfSDavid du Colombier return;
46980ee5cbfSDavid du Colombier if(readc(cis, &minor) != 1)
47080ee5cbfSDavid du Colombier return;
47180ee5cbfSDavid du Colombier last = 0;
47280ee5cbfSDavid du Colombier for(i = 0; i < sizeof(pp->verstr)-1; i++){
47380ee5cbfSDavid du Colombier if(readc(cis, &c) != 1)
47480ee5cbfSDavid du Colombier return;
47580ee5cbfSDavid du Colombier if(c == 0)
47680ee5cbfSDavid du Colombier c = ';';
47780ee5cbfSDavid du Colombier if(c == '\n')
47880ee5cbfSDavid du Colombier c = ';';
47980ee5cbfSDavid du Colombier if(c == 0xff)
48080ee5cbfSDavid du Colombier break;
48180ee5cbfSDavid du Colombier if(c == ';' && last == ';')
48280ee5cbfSDavid du Colombier continue;
48380ee5cbfSDavid du Colombier pp->verstr[i] = c;
48480ee5cbfSDavid du Colombier last = c;
48580ee5cbfSDavid du Colombier }
48680ee5cbfSDavid du Colombier pp->verstr[i] = 0;
48780ee5cbfSDavid du Colombier }
488*15174232SDavid du Colombier
489*15174232SDavid du Colombier static void
tlonglnkmfc(PCMslot * pp,Cisdat * cis,int)490*15174232SDavid du Colombier tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
491*15174232SDavid du Colombier {
492*15174232SDavid du Colombier int i, npos, opos;
493*15174232SDavid du Colombier uchar nfn, space, expect, type, this, link;
494*15174232SDavid du Colombier
495*15174232SDavid du Colombier readc(cis, &nfn);
496*15174232SDavid du Colombier for(i = 0; i < nfn; i++){
497*15174232SDavid du Colombier readc(cis, &space);
498*15174232SDavid du Colombier npos = getlong(cis, 4);
499*15174232SDavid du Colombier opos = cis->cispos;
500*15174232SDavid du Colombier cis->cispos = npos;
501*15174232SDavid du Colombier expect = Linktarget;
502*15174232SDavid du Colombier
503*15174232SDavid du Colombier while(1){
504*15174232SDavid du Colombier this = cis->cispos;
505*15174232SDavid du Colombier if(readc(cis, &type) != 1)
506*15174232SDavid du Colombier break;
507*15174232SDavid du Colombier if(type == 0xFF)
508*15174232SDavid du Colombier break;
509*15174232SDavid du Colombier if(readc(cis, &link) != 1)
510*15174232SDavid du Colombier break;
511*15174232SDavid du Colombier
512*15174232SDavid du Colombier if(expect && expect != type){
513*15174232SDavid du Colombier print("tlonglnkmfc: expected %X found %X\n",
514*15174232SDavid du Colombier expect, type);
515*15174232SDavid du Colombier break;
516*15174232SDavid du Colombier }
517*15174232SDavid du Colombier expect = 0;
518*15174232SDavid du Colombier
519*15174232SDavid du Colombier switch(type){
520*15174232SDavid du Colombier default:
521*15174232SDavid du Colombier break;
522*15174232SDavid du Colombier case 0x15:
523*15174232SDavid du Colombier tvers1(pp, cis, type);
524*15174232SDavid du Colombier break;
525*15174232SDavid du Colombier case 0x1A:
526*15174232SDavid du Colombier tcfig(pp, cis, type);
527*15174232SDavid du Colombier break;
528*15174232SDavid du Colombier case 0x1B:
529*15174232SDavid du Colombier tentry(pp, cis, type);
530*15174232SDavid du Colombier break;
531*15174232SDavid du Colombier }
532*15174232SDavid du Colombier
533*15174232SDavid du Colombier if(link == 0xFF)
534*15174232SDavid du Colombier break;
535*15174232SDavid du Colombier cis->cispos = this + (2+link);
536*15174232SDavid du Colombier }
537*15174232SDavid du Colombier cis->cispos = opos;
538*15174232SDavid du Colombier }
539*15174232SDavid du Colombier }
540