1*8a8c2d74SCharles.Forsyth #include "u.h"
2*8a8c2d74SCharles.Forsyth #include "lib.h"
3*8a8c2d74SCharles.Forsyth #include "mem.h"
4*8a8c2d74SCharles.Forsyth #include "dat.h"
5*8a8c2d74SCharles.Forsyth #include "fns.h"
6*8a8c2d74SCharles.Forsyth #include "error.h"
7*8a8c2d74SCharles.Forsyth #include "io.h"
8*8a8c2d74SCharles.Forsyth
9*8a8c2d74SCharles.Forsyth enum{
10*8a8c2d74SCharles.Forsyth Linktarget = 0x13,
11*8a8c2d74SCharles.Forsyth };
12*8a8c2d74SCharles.Forsyth
13*8a8c2d74SCharles.Forsyth /*
14*8a8c2d74SCharles.Forsyth * read and crack the card information structure enough to set
15*8a8c2d74SCharles.Forsyth * important parameters like power
16*8a8c2d74SCharles.Forsyth */
17*8a8c2d74SCharles.Forsyth /* cis memory walking */
18*8a8c2d74SCharles.Forsyth typedef struct Cisdat {
19*8a8c2d74SCharles.Forsyth uchar *cisbase;
20*8a8c2d74SCharles.Forsyth int cispos;
21*8a8c2d74SCharles.Forsyth int cisskip;
22*8a8c2d74SCharles.Forsyth int cislen;
23*8a8c2d74SCharles.Forsyth } Cisdat;
24*8a8c2d74SCharles.Forsyth
25*8a8c2d74SCharles.Forsyth static void tcfig(PCMslot*, Cisdat*, int);
26*8a8c2d74SCharles.Forsyth static void tentry(PCMslot*, Cisdat*, int);
27*8a8c2d74SCharles.Forsyth static void tvers1(PCMslot*, Cisdat*, int);
28*8a8c2d74SCharles.Forsyth static void tlonglnkmfc(PCMslot*, Cisdat*, int);
29*8a8c2d74SCharles.Forsyth
30*8a8c2d74SCharles.Forsyth static int
readc(Cisdat * cis,uchar * x)31*8a8c2d74SCharles.Forsyth readc(Cisdat *cis, uchar *x)
32*8a8c2d74SCharles.Forsyth {
33*8a8c2d74SCharles.Forsyth if(cis->cispos >= cis->cislen)
34*8a8c2d74SCharles.Forsyth return 0;
35*8a8c2d74SCharles.Forsyth *x = cis->cisbase[cis->cisskip*cis->cispos];
36*8a8c2d74SCharles.Forsyth cis->cispos++;
37*8a8c2d74SCharles.Forsyth return 1;
38*8a8c2d74SCharles.Forsyth }
39*8a8c2d74SCharles.Forsyth
40*8a8c2d74SCharles.Forsyth static int
xcistuple(int slotno,int tuple,int subtuple,void * v,int nv,int attr)41*8a8c2d74SCharles.Forsyth xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
42*8a8c2d74SCharles.Forsyth {
43*8a8c2d74SCharles.Forsyth PCMmap *m;
44*8a8c2d74SCharles.Forsyth Cisdat cis;
45*8a8c2d74SCharles.Forsyth int i, l;
46*8a8c2d74SCharles.Forsyth uchar *p;
47*8a8c2d74SCharles.Forsyth uchar type, link, n, c;
48*8a8c2d74SCharles.Forsyth int this, subtype;
49*8a8c2d74SCharles.Forsyth
50*8a8c2d74SCharles.Forsyth m = pcmmap(slotno, 0, 0, attr);
51*8a8c2d74SCharles.Forsyth if(m == 0)
52*8a8c2d74SCharles.Forsyth return -1;
53*8a8c2d74SCharles.Forsyth
54*8a8c2d74SCharles.Forsyth cis.cisbase = KADDR(m->isa);
55*8a8c2d74SCharles.Forsyth cis.cispos = 0;
56*8a8c2d74SCharles.Forsyth cis.cisskip = attr ? 2 : 1;
57*8a8c2d74SCharles.Forsyth cis.cislen = m->len;
58*8a8c2d74SCharles.Forsyth
59*8a8c2d74SCharles.Forsyth /* loop through all the tuples */
60*8a8c2d74SCharles.Forsyth for(i = 0; i < 1000; i++){
61*8a8c2d74SCharles.Forsyth this = cis.cispos;
62*8a8c2d74SCharles.Forsyth if(readc(&cis, &type) != 1)
63*8a8c2d74SCharles.Forsyth break;
64*8a8c2d74SCharles.Forsyth if(type == 0xFF)
65*8a8c2d74SCharles.Forsyth break;
66*8a8c2d74SCharles.Forsyth if(readc(&cis, &link) != 1)
67*8a8c2d74SCharles.Forsyth break;
68*8a8c2d74SCharles.Forsyth if(link == 0xFF)
69*8a8c2d74SCharles.Forsyth break;
70*8a8c2d74SCharles.Forsyth
71*8a8c2d74SCharles.Forsyth n = link;
72*8a8c2d74SCharles.Forsyth if(link > 1 && subtuple != -1){
73*8a8c2d74SCharles.Forsyth if(readc(&cis, &c) != 1)
74*8a8c2d74SCharles.Forsyth break;
75*8a8c2d74SCharles.Forsyth subtype = c;
76*8a8c2d74SCharles.Forsyth n--;
77*8a8c2d74SCharles.Forsyth }else
78*8a8c2d74SCharles.Forsyth subtype = -1;
79*8a8c2d74SCharles.Forsyth
80*8a8c2d74SCharles.Forsyth if(type == tuple && subtype == subtuple){
81*8a8c2d74SCharles.Forsyth p = v;
82*8a8c2d74SCharles.Forsyth for(l=0; l<nv && l<n; l++)
83*8a8c2d74SCharles.Forsyth if(readc(&cis, p++) != 1)
84*8a8c2d74SCharles.Forsyth break;
85*8a8c2d74SCharles.Forsyth pcmunmap(slotno, m);
86*8a8c2d74SCharles.Forsyth return nv;
87*8a8c2d74SCharles.Forsyth }
88*8a8c2d74SCharles.Forsyth cis.cispos = this + (2+link);
89*8a8c2d74SCharles.Forsyth }
90*8a8c2d74SCharles.Forsyth pcmunmap(slotno, m);
91*8a8c2d74SCharles.Forsyth return -1;
92*8a8c2d74SCharles.Forsyth }
93*8a8c2d74SCharles.Forsyth
94*8a8c2d74SCharles.Forsyth int
pcmcistuple(int slotno,int tuple,int subtuple,void * v,int nv)95*8a8c2d74SCharles.Forsyth pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
96*8a8c2d74SCharles.Forsyth {
97*8a8c2d74SCharles.Forsyth int n;
98*8a8c2d74SCharles.Forsyth
99*8a8c2d74SCharles.Forsyth /* try attribute space, then memory */
100*8a8c2d74SCharles.Forsyth if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
101*8a8c2d74SCharles.Forsyth return n;
102*8a8c2d74SCharles.Forsyth return xcistuple(slotno, tuple, subtuple, v, nv, 0);
103*8a8c2d74SCharles.Forsyth }
104*8a8c2d74SCharles.Forsyth
105*8a8c2d74SCharles.Forsyth void
pcmcisread(PCMslot * pp)106*8a8c2d74SCharles.Forsyth pcmcisread(PCMslot *pp)
107*8a8c2d74SCharles.Forsyth {
108*8a8c2d74SCharles.Forsyth int this;
109*8a8c2d74SCharles.Forsyth Cisdat cis;
110*8a8c2d74SCharles.Forsyth PCMmap *m;
111*8a8c2d74SCharles.Forsyth uchar type, link;
112*8a8c2d74SCharles.Forsyth
113*8a8c2d74SCharles.Forsyth memset(pp->ctab, 0, sizeof(pp->ctab));
114*8a8c2d74SCharles.Forsyth pp->ncfg = 0;
115*8a8c2d74SCharles.Forsyth memset(pp->cfg, 0, sizeof(pp->cfg));
116*8a8c2d74SCharles.Forsyth pp->configed = 0;
117*8a8c2d74SCharles.Forsyth pp->nctab = 0;
118*8a8c2d74SCharles.Forsyth pp->verstr[0] = 0;
119*8a8c2d74SCharles.Forsyth
120*8a8c2d74SCharles.Forsyth /*
121*8a8c2d74SCharles.Forsyth * Read all tuples in attribute space.
122*8a8c2d74SCharles.Forsyth */
123*8a8c2d74SCharles.Forsyth m = pcmmap(pp->slotno, 0, 0, 1);
124*8a8c2d74SCharles.Forsyth if(m == 0)
125*8a8c2d74SCharles.Forsyth return;
126*8a8c2d74SCharles.Forsyth
127*8a8c2d74SCharles.Forsyth cis.cisbase = KADDR(m->isa);
128*8a8c2d74SCharles.Forsyth cis.cispos = 0;
129*8a8c2d74SCharles.Forsyth cis.cisskip = 2;
130*8a8c2d74SCharles.Forsyth cis.cislen = m->len;
131*8a8c2d74SCharles.Forsyth
132*8a8c2d74SCharles.Forsyth /* loop through all the tuples */
133*8a8c2d74SCharles.Forsyth for(;;){
134*8a8c2d74SCharles.Forsyth this = cis.cispos;
135*8a8c2d74SCharles.Forsyth if(readc(&cis, &type) != 1)
136*8a8c2d74SCharles.Forsyth break;
137*8a8c2d74SCharles.Forsyth if(type == 0xFF)
138*8a8c2d74SCharles.Forsyth break;
139*8a8c2d74SCharles.Forsyth if(readc(&cis, &link) != 1)
140*8a8c2d74SCharles.Forsyth break;
141*8a8c2d74SCharles.Forsyth
142*8a8c2d74SCharles.Forsyth switch(type){
143*8a8c2d74SCharles.Forsyth default:
144*8a8c2d74SCharles.Forsyth break;
145*8a8c2d74SCharles.Forsyth case 6:
146*8a8c2d74SCharles.Forsyth tlonglnkmfc(pp, &cis, type);
147*8a8c2d74SCharles.Forsyth break;
148*8a8c2d74SCharles.Forsyth case 0x15:
149*8a8c2d74SCharles.Forsyth tvers1(pp, &cis, type);
150*8a8c2d74SCharles.Forsyth break;
151*8a8c2d74SCharles.Forsyth case 0x1A:
152*8a8c2d74SCharles.Forsyth tcfig(pp, &cis, type);
153*8a8c2d74SCharles.Forsyth break;
154*8a8c2d74SCharles.Forsyth case 0x1B:
155*8a8c2d74SCharles.Forsyth tentry(pp, &cis, type);
156*8a8c2d74SCharles.Forsyth break;
157*8a8c2d74SCharles.Forsyth }
158*8a8c2d74SCharles.Forsyth
159*8a8c2d74SCharles.Forsyth if(link == 0xFF)
160*8a8c2d74SCharles.Forsyth break;
161*8a8c2d74SCharles.Forsyth cis.cispos = this + (2+link);
162*8a8c2d74SCharles.Forsyth }
163*8a8c2d74SCharles.Forsyth pcmunmap(pp->slotno, m);
164*8a8c2d74SCharles.Forsyth }
165*8a8c2d74SCharles.Forsyth
166*8a8c2d74SCharles.Forsyth static ulong
getlong(Cisdat * cis,int size)167*8a8c2d74SCharles.Forsyth getlong(Cisdat *cis, int size)
168*8a8c2d74SCharles.Forsyth {
169*8a8c2d74SCharles.Forsyth uchar c;
170*8a8c2d74SCharles.Forsyth int i;
171*8a8c2d74SCharles.Forsyth ulong x;
172*8a8c2d74SCharles.Forsyth
173*8a8c2d74SCharles.Forsyth x = 0;
174*8a8c2d74SCharles.Forsyth for(i = 0; i < size; i++){
175*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
176*8a8c2d74SCharles.Forsyth break;
177*8a8c2d74SCharles.Forsyth x |= c<<(i*8);
178*8a8c2d74SCharles.Forsyth }
179*8a8c2d74SCharles.Forsyth return x;
180*8a8c2d74SCharles.Forsyth }
181*8a8c2d74SCharles.Forsyth
182*8a8c2d74SCharles.Forsyth static void
tcfig(PCMslot * pp,Cisdat * cis,int)183*8a8c2d74SCharles.Forsyth tcfig(PCMslot *pp, Cisdat *cis, int )
184*8a8c2d74SCharles.Forsyth {
185*8a8c2d74SCharles.Forsyth uchar size, rasize, rmsize;
186*8a8c2d74SCharles.Forsyth uchar last;
187*8a8c2d74SCharles.Forsyth
188*8a8c2d74SCharles.Forsyth if(readc(cis, &size) != 1)
189*8a8c2d74SCharles.Forsyth return;
190*8a8c2d74SCharles.Forsyth rasize = (size&0x3) + 1;
191*8a8c2d74SCharles.Forsyth rmsize = ((size>>2)&0xf) + 1;
192*8a8c2d74SCharles.Forsyth if(readc(cis, &last) != 1)
193*8a8c2d74SCharles.Forsyth return;
194*8a8c2d74SCharles.Forsyth
195*8a8c2d74SCharles.Forsyth if(pp->ncfg >= 8){
196*8a8c2d74SCharles.Forsyth print("tcfig: too many configuration registers\n");
197*8a8c2d74SCharles.Forsyth return;
198*8a8c2d74SCharles.Forsyth }
199*8a8c2d74SCharles.Forsyth
200*8a8c2d74SCharles.Forsyth pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
201*8a8c2d74SCharles.Forsyth pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
202*8a8c2d74SCharles.Forsyth pp->ncfg++;
203*8a8c2d74SCharles.Forsyth }
204*8a8c2d74SCharles.Forsyth
205*8a8c2d74SCharles.Forsyth static ulong vexp[8] =
206*8a8c2d74SCharles.Forsyth {
207*8a8c2d74SCharles.Forsyth 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
208*8a8c2d74SCharles.Forsyth };
209*8a8c2d74SCharles.Forsyth static ulong vmant[16] =
210*8a8c2d74SCharles.Forsyth {
211*8a8c2d74SCharles.Forsyth 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
212*8a8c2d74SCharles.Forsyth };
213*8a8c2d74SCharles.Forsyth
214*8a8c2d74SCharles.Forsyth static ulong
microvolt(Cisdat * cis)215*8a8c2d74SCharles.Forsyth microvolt(Cisdat *cis)
216*8a8c2d74SCharles.Forsyth {
217*8a8c2d74SCharles.Forsyth uchar c;
218*8a8c2d74SCharles.Forsyth ulong microvolts;
219*8a8c2d74SCharles.Forsyth ulong exp;
220*8a8c2d74SCharles.Forsyth
221*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
222*8a8c2d74SCharles.Forsyth return 0;
223*8a8c2d74SCharles.Forsyth exp = vexp[c&0x7];
224*8a8c2d74SCharles.Forsyth microvolts = vmant[(c>>3)&0xf]*exp;
225*8a8c2d74SCharles.Forsyth while(c & 0x80){
226*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
227*8a8c2d74SCharles.Forsyth return 0;
228*8a8c2d74SCharles.Forsyth switch(c){
229*8a8c2d74SCharles.Forsyth case 0x7d:
230*8a8c2d74SCharles.Forsyth break; /* high impedence when sleeping */
231*8a8c2d74SCharles.Forsyth case 0x7e:
232*8a8c2d74SCharles.Forsyth case 0x7f:
233*8a8c2d74SCharles.Forsyth microvolts = 0; /* no connection */
234*8a8c2d74SCharles.Forsyth break;
235*8a8c2d74SCharles.Forsyth default:
236*8a8c2d74SCharles.Forsyth exp /= 10;
237*8a8c2d74SCharles.Forsyth microvolts += exp*(c&0x7f);
238*8a8c2d74SCharles.Forsyth }
239*8a8c2d74SCharles.Forsyth }
240*8a8c2d74SCharles.Forsyth return microvolts;
241*8a8c2d74SCharles.Forsyth }
242*8a8c2d74SCharles.Forsyth
243*8a8c2d74SCharles.Forsyth static ulong
nanoamps(Cisdat * cis)244*8a8c2d74SCharles.Forsyth nanoamps(Cisdat *cis)
245*8a8c2d74SCharles.Forsyth {
246*8a8c2d74SCharles.Forsyth uchar c;
247*8a8c2d74SCharles.Forsyth ulong nanoamps;
248*8a8c2d74SCharles.Forsyth
249*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
250*8a8c2d74SCharles.Forsyth return 0;
251*8a8c2d74SCharles.Forsyth nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
252*8a8c2d74SCharles.Forsyth while(c & 0x80){
253*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
254*8a8c2d74SCharles.Forsyth return 0;
255*8a8c2d74SCharles.Forsyth if(c == 0x7d || c == 0x7e || c == 0x7f)
256*8a8c2d74SCharles.Forsyth nanoamps = 0;
257*8a8c2d74SCharles.Forsyth }
258*8a8c2d74SCharles.Forsyth return nanoamps;
259*8a8c2d74SCharles.Forsyth }
260*8a8c2d74SCharles.Forsyth
261*8a8c2d74SCharles.Forsyth /*
262*8a8c2d74SCharles.Forsyth * only nominal voltage (feature 1) is important for config,
263*8a8c2d74SCharles.Forsyth * other features must read card to stay in sync.
264*8a8c2d74SCharles.Forsyth */
265*8a8c2d74SCharles.Forsyth static ulong
power(Cisdat * cis)266*8a8c2d74SCharles.Forsyth power(Cisdat *cis)
267*8a8c2d74SCharles.Forsyth {
268*8a8c2d74SCharles.Forsyth uchar feature;
269*8a8c2d74SCharles.Forsyth ulong mv;
270*8a8c2d74SCharles.Forsyth
271*8a8c2d74SCharles.Forsyth mv = 0;
272*8a8c2d74SCharles.Forsyth if(readc(cis, &feature) != 1)
273*8a8c2d74SCharles.Forsyth return 0;
274*8a8c2d74SCharles.Forsyth if(feature & 1)
275*8a8c2d74SCharles.Forsyth mv = microvolt(cis);
276*8a8c2d74SCharles.Forsyth if(feature & 2)
277*8a8c2d74SCharles.Forsyth microvolt(cis);
278*8a8c2d74SCharles.Forsyth if(feature & 4)
279*8a8c2d74SCharles.Forsyth microvolt(cis);
280*8a8c2d74SCharles.Forsyth if(feature & 8)
281*8a8c2d74SCharles.Forsyth nanoamps(cis);
282*8a8c2d74SCharles.Forsyth if(feature & 0x10)
283*8a8c2d74SCharles.Forsyth nanoamps(cis);
284*8a8c2d74SCharles.Forsyth if(feature & 0x20)
285*8a8c2d74SCharles.Forsyth nanoamps(cis);
286*8a8c2d74SCharles.Forsyth if(feature & 0x40)
287*8a8c2d74SCharles.Forsyth nanoamps(cis);
288*8a8c2d74SCharles.Forsyth return mv/1000000;
289*8a8c2d74SCharles.Forsyth }
290*8a8c2d74SCharles.Forsyth
291*8a8c2d74SCharles.Forsyth static ulong mantissa[16] =
292*8a8c2d74SCharles.Forsyth { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
293*8a8c2d74SCharles.Forsyth
294*8a8c2d74SCharles.Forsyth static ulong exponent[8] =
295*8a8c2d74SCharles.Forsyth { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
296*8a8c2d74SCharles.Forsyth
297*8a8c2d74SCharles.Forsyth static ulong
ttiming(Cisdat * cis,int scale)298*8a8c2d74SCharles.Forsyth ttiming(Cisdat *cis, int scale)
299*8a8c2d74SCharles.Forsyth {
300*8a8c2d74SCharles.Forsyth uchar unscaled;
301*8a8c2d74SCharles.Forsyth ulong nanosecs;
302*8a8c2d74SCharles.Forsyth
303*8a8c2d74SCharles.Forsyth if(readc(cis, &unscaled) != 1)
304*8a8c2d74SCharles.Forsyth return 0;
305*8a8c2d74SCharles.Forsyth nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
306*8a8c2d74SCharles.Forsyth nanosecs = nanosecs * vexp[scale];
307*8a8c2d74SCharles.Forsyth return nanosecs;
308*8a8c2d74SCharles.Forsyth }
309*8a8c2d74SCharles.Forsyth
310*8a8c2d74SCharles.Forsyth static void
timing(Cisdat * cis,PCMconftab * ct)311*8a8c2d74SCharles.Forsyth timing(Cisdat *cis, PCMconftab *ct)
312*8a8c2d74SCharles.Forsyth {
313*8a8c2d74SCharles.Forsyth uchar c, i;
314*8a8c2d74SCharles.Forsyth
315*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
316*8a8c2d74SCharles.Forsyth return;
317*8a8c2d74SCharles.Forsyth i = c&0x3;
318*8a8c2d74SCharles.Forsyth if(i != 3)
319*8a8c2d74SCharles.Forsyth ct->maxwait = ttiming(cis, i); /* max wait */
320*8a8c2d74SCharles.Forsyth i = (c>>2)&0x7;
321*8a8c2d74SCharles.Forsyth if(i != 7)
322*8a8c2d74SCharles.Forsyth ct->readywait = ttiming(cis, i); /* max ready/busy wait */
323*8a8c2d74SCharles.Forsyth i = (c>>5)&0x7;
324*8a8c2d74SCharles.Forsyth if(i != 7)
325*8a8c2d74SCharles.Forsyth ct->otherwait = ttiming(cis, i); /* reserved wait */
326*8a8c2d74SCharles.Forsyth }
327*8a8c2d74SCharles.Forsyth
328*8a8c2d74SCharles.Forsyth static void
iospaces(Cisdat * cis,PCMconftab * ct)329*8a8c2d74SCharles.Forsyth iospaces(Cisdat *cis, PCMconftab *ct)
330*8a8c2d74SCharles.Forsyth {
331*8a8c2d74SCharles.Forsyth uchar c;
332*8a8c2d74SCharles.Forsyth int i, nio;
333*8a8c2d74SCharles.Forsyth
334*8a8c2d74SCharles.Forsyth ct->nio = 0;
335*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
336*8a8c2d74SCharles.Forsyth return;
337*8a8c2d74SCharles.Forsyth
338*8a8c2d74SCharles.Forsyth ct->bit16 = ((c>>5)&3) >= 2;
339*8a8c2d74SCharles.Forsyth if(!(c & 0x80)){
340*8a8c2d74SCharles.Forsyth ct->io[0].start = 0;
341*8a8c2d74SCharles.Forsyth ct->io[0].len = 1<<(c&0x1f);
342*8a8c2d74SCharles.Forsyth ct->nio = 1;
343*8a8c2d74SCharles.Forsyth return;
344*8a8c2d74SCharles.Forsyth }
345*8a8c2d74SCharles.Forsyth
346*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
347*8a8c2d74SCharles.Forsyth return;
348*8a8c2d74SCharles.Forsyth
349*8a8c2d74SCharles.Forsyth /*
350*8a8c2d74SCharles.Forsyth * For each of the range descriptions read the
351*8a8c2d74SCharles.Forsyth * start address and the length (value is length-1).
352*8a8c2d74SCharles.Forsyth */
353*8a8c2d74SCharles.Forsyth nio = (c&0xf)+1;
354*8a8c2d74SCharles.Forsyth for(i = 0; i < nio; i++){
355*8a8c2d74SCharles.Forsyth ct->io[i].start = getlong(cis, (c>>4)&0x3);
356*8a8c2d74SCharles.Forsyth ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
357*8a8c2d74SCharles.Forsyth }
358*8a8c2d74SCharles.Forsyth ct->nio = nio;
359*8a8c2d74SCharles.Forsyth }
360*8a8c2d74SCharles.Forsyth
361*8a8c2d74SCharles.Forsyth static void
irq(Cisdat * cis,PCMconftab * ct)362*8a8c2d74SCharles.Forsyth irq(Cisdat *cis, PCMconftab *ct)
363*8a8c2d74SCharles.Forsyth {
364*8a8c2d74SCharles.Forsyth uchar c;
365*8a8c2d74SCharles.Forsyth
366*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
367*8a8c2d74SCharles.Forsyth return;
368*8a8c2d74SCharles.Forsyth ct->irqtype = c & 0xe0;
369*8a8c2d74SCharles.Forsyth if(c & 0x10)
370*8a8c2d74SCharles.Forsyth ct->irqs = getlong(cis, 2);
371*8a8c2d74SCharles.Forsyth else
372*8a8c2d74SCharles.Forsyth ct->irqs = 1<<(c&0xf);
373*8a8c2d74SCharles.Forsyth ct->irqs &= 0xDEB8; /* levels available to card */
374*8a8c2d74SCharles.Forsyth }
375*8a8c2d74SCharles.Forsyth
376*8a8c2d74SCharles.Forsyth static void
memspace(Cisdat * cis,int asize,int lsize,int host)377*8a8c2d74SCharles.Forsyth memspace(Cisdat *cis, int asize, int lsize, int host)
378*8a8c2d74SCharles.Forsyth {
379*8a8c2d74SCharles.Forsyth ulong haddress, address, len;
380*8a8c2d74SCharles.Forsyth
381*8a8c2d74SCharles.Forsyth len = getlong(cis, lsize)*256;
382*8a8c2d74SCharles.Forsyth address = getlong(cis, asize)*256;
383*8a8c2d74SCharles.Forsyth USED(len, address);
384*8a8c2d74SCharles.Forsyth if(host){
385*8a8c2d74SCharles.Forsyth haddress = getlong(cis, asize)*256;
386*8a8c2d74SCharles.Forsyth USED(haddress);
387*8a8c2d74SCharles.Forsyth }
388*8a8c2d74SCharles.Forsyth }
389*8a8c2d74SCharles.Forsyth
390*8a8c2d74SCharles.Forsyth static void
tentry(PCMslot * pp,Cisdat * cis,int)391*8a8c2d74SCharles.Forsyth tentry(PCMslot *pp, Cisdat *cis, int )
392*8a8c2d74SCharles.Forsyth {
393*8a8c2d74SCharles.Forsyth uchar c, i, feature;
394*8a8c2d74SCharles.Forsyth PCMconftab *ct;
395*8a8c2d74SCharles.Forsyth
396*8a8c2d74SCharles.Forsyth if(pp->nctab >= nelem(pp->ctab))
397*8a8c2d74SCharles.Forsyth return;
398*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
399*8a8c2d74SCharles.Forsyth return;
400*8a8c2d74SCharles.Forsyth ct = &pp->ctab[pp->nctab++];
401*8a8c2d74SCharles.Forsyth
402*8a8c2d74SCharles.Forsyth /* copy from last default config */
403*8a8c2d74SCharles.Forsyth if(pp->def)
404*8a8c2d74SCharles.Forsyth *ct = *pp->def;
405*8a8c2d74SCharles.Forsyth
406*8a8c2d74SCharles.Forsyth ct->index = c & 0x3f;
407*8a8c2d74SCharles.Forsyth
408*8a8c2d74SCharles.Forsyth /* is this the new default? */
409*8a8c2d74SCharles.Forsyth if(c & 0x40)
410*8a8c2d74SCharles.Forsyth pp->def = ct;
411*8a8c2d74SCharles.Forsyth
412*8a8c2d74SCharles.Forsyth /* memory wait specified? */
413*8a8c2d74SCharles.Forsyth if(c & 0x80){
414*8a8c2d74SCharles.Forsyth if(readc(cis, &i) != 1)
415*8a8c2d74SCharles.Forsyth return;
416*8a8c2d74SCharles.Forsyth if(i&0x80)
417*8a8c2d74SCharles.Forsyth ct->memwait = 1;
418*8a8c2d74SCharles.Forsyth }
419*8a8c2d74SCharles.Forsyth
420*8a8c2d74SCharles.Forsyth if(readc(cis, &feature) != 1)
421*8a8c2d74SCharles.Forsyth return;
422*8a8c2d74SCharles.Forsyth switch(feature&0x3){
423*8a8c2d74SCharles.Forsyth case 1:
424*8a8c2d74SCharles.Forsyth ct->vpp1 = ct->vpp2 = power(cis);
425*8a8c2d74SCharles.Forsyth break;
426*8a8c2d74SCharles.Forsyth case 2:
427*8a8c2d74SCharles.Forsyth power(cis);
428*8a8c2d74SCharles.Forsyth ct->vpp1 = ct->vpp2 = power(cis);
429*8a8c2d74SCharles.Forsyth break;
430*8a8c2d74SCharles.Forsyth case 3:
431*8a8c2d74SCharles.Forsyth power(cis);
432*8a8c2d74SCharles.Forsyth ct->vpp1 = power(cis);
433*8a8c2d74SCharles.Forsyth ct->vpp2 = power(cis);
434*8a8c2d74SCharles.Forsyth break;
435*8a8c2d74SCharles.Forsyth default:
436*8a8c2d74SCharles.Forsyth break;
437*8a8c2d74SCharles.Forsyth }
438*8a8c2d74SCharles.Forsyth if(feature&0x4)
439*8a8c2d74SCharles.Forsyth timing(cis, ct);
440*8a8c2d74SCharles.Forsyth if(feature&0x8)
441*8a8c2d74SCharles.Forsyth iospaces(cis, ct);
442*8a8c2d74SCharles.Forsyth if(feature&0x10)
443*8a8c2d74SCharles.Forsyth irq(cis, ct);
444*8a8c2d74SCharles.Forsyth switch((feature>>5)&0x3){
445*8a8c2d74SCharles.Forsyth case 1:
446*8a8c2d74SCharles.Forsyth memspace(cis, 0, 2, 0);
447*8a8c2d74SCharles.Forsyth break;
448*8a8c2d74SCharles.Forsyth case 2:
449*8a8c2d74SCharles.Forsyth memspace(cis, 2, 2, 0);
450*8a8c2d74SCharles.Forsyth break;
451*8a8c2d74SCharles.Forsyth case 3:
452*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
453*8a8c2d74SCharles.Forsyth return;
454*8a8c2d74SCharles.Forsyth for(i = 0; i <= (c&0x7); i++)
455*8a8c2d74SCharles.Forsyth memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
456*8a8c2d74SCharles.Forsyth break;
457*8a8c2d74SCharles.Forsyth }
458*8a8c2d74SCharles.Forsyth pp->configed++;
459*8a8c2d74SCharles.Forsyth }
460*8a8c2d74SCharles.Forsyth
461*8a8c2d74SCharles.Forsyth static void
tvers1(PCMslot * pp,Cisdat * cis,int)462*8a8c2d74SCharles.Forsyth tvers1(PCMslot *pp, Cisdat *cis, int )
463*8a8c2d74SCharles.Forsyth {
464*8a8c2d74SCharles.Forsyth uchar c, major, minor, last;
465*8a8c2d74SCharles.Forsyth int i;
466*8a8c2d74SCharles.Forsyth
467*8a8c2d74SCharles.Forsyth if(readc(cis, &major) != 1)
468*8a8c2d74SCharles.Forsyth return;
469*8a8c2d74SCharles.Forsyth if(readc(cis, &minor) != 1)
470*8a8c2d74SCharles.Forsyth return;
471*8a8c2d74SCharles.Forsyth last = 0;
472*8a8c2d74SCharles.Forsyth for(i = 0; i < sizeof(pp->verstr)-1; i++){
473*8a8c2d74SCharles.Forsyth if(readc(cis, &c) != 1)
474*8a8c2d74SCharles.Forsyth return;
475*8a8c2d74SCharles.Forsyth if(c == 0)
476*8a8c2d74SCharles.Forsyth c = ';';
477*8a8c2d74SCharles.Forsyth if(c == '\n')
478*8a8c2d74SCharles.Forsyth c = ';';
479*8a8c2d74SCharles.Forsyth if(c == 0xff)
480*8a8c2d74SCharles.Forsyth break;
481*8a8c2d74SCharles.Forsyth if(c == ';' && last == ';')
482*8a8c2d74SCharles.Forsyth continue;
483*8a8c2d74SCharles.Forsyth pp->verstr[i] = c;
484*8a8c2d74SCharles.Forsyth last = c;
485*8a8c2d74SCharles.Forsyth }
486*8a8c2d74SCharles.Forsyth pp->verstr[i] = 0;
487*8a8c2d74SCharles.Forsyth }
488*8a8c2d74SCharles.Forsyth
489*8a8c2d74SCharles.Forsyth static void
tlonglnkmfc(PCMslot * pp,Cisdat * cis,int)490*8a8c2d74SCharles.Forsyth tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
491*8a8c2d74SCharles.Forsyth {
492*8a8c2d74SCharles.Forsyth int i, npos, opos;
493*8a8c2d74SCharles.Forsyth uchar nfn, space, expect, type, this, link;
494*8a8c2d74SCharles.Forsyth
495*8a8c2d74SCharles.Forsyth readc(cis, &nfn);
496*8a8c2d74SCharles.Forsyth for(i = 0; i < nfn; i++){
497*8a8c2d74SCharles.Forsyth readc(cis, &space);
498*8a8c2d74SCharles.Forsyth npos = getlong(cis, 4);
499*8a8c2d74SCharles.Forsyth opos = cis->cispos;
500*8a8c2d74SCharles.Forsyth cis->cispos = npos;
501*8a8c2d74SCharles.Forsyth expect = Linktarget;
502*8a8c2d74SCharles.Forsyth
503*8a8c2d74SCharles.Forsyth while(1){
504*8a8c2d74SCharles.Forsyth this = cis->cispos;
505*8a8c2d74SCharles.Forsyth if(readc(cis, &type) != 1)
506*8a8c2d74SCharles.Forsyth break;
507*8a8c2d74SCharles.Forsyth if(type == 0xFF)
508*8a8c2d74SCharles.Forsyth break;
509*8a8c2d74SCharles.Forsyth if(readc(cis, &link) != 1)
510*8a8c2d74SCharles.Forsyth break;
511*8a8c2d74SCharles.Forsyth
512*8a8c2d74SCharles.Forsyth if(expect && expect != type){
513*8a8c2d74SCharles.Forsyth print("tlonglnkmfc: expected %X found %X\n",
514*8a8c2d74SCharles.Forsyth expect, type);
515*8a8c2d74SCharles.Forsyth break;
516*8a8c2d74SCharles.Forsyth }
517*8a8c2d74SCharles.Forsyth expect = 0;
518*8a8c2d74SCharles.Forsyth
519*8a8c2d74SCharles.Forsyth switch(type){
520*8a8c2d74SCharles.Forsyth default:
521*8a8c2d74SCharles.Forsyth break;
522*8a8c2d74SCharles.Forsyth case 0x15:
523*8a8c2d74SCharles.Forsyth tvers1(pp, cis, type);
524*8a8c2d74SCharles.Forsyth break;
525*8a8c2d74SCharles.Forsyth case 0x1A:
526*8a8c2d74SCharles.Forsyth tcfig(pp, cis, type);
527*8a8c2d74SCharles.Forsyth break;
528*8a8c2d74SCharles.Forsyth case 0x1B:
529*8a8c2d74SCharles.Forsyth tentry(pp, cis, type);
530*8a8c2d74SCharles.Forsyth break;
531*8a8c2d74SCharles.Forsyth }
532*8a8c2d74SCharles.Forsyth
533*8a8c2d74SCharles.Forsyth if(link == 0xFF)
534*8a8c2d74SCharles.Forsyth break;
535*8a8c2d74SCharles.Forsyth cis->cispos = this + (2+link);
536*8a8c2d74SCharles.Forsyth }
537*8a8c2d74SCharles.Forsyth cis->cispos = opos;
538*8a8c2d74SCharles.Forsyth }
539*8a8c2d74SCharles.Forsyth }
540