]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/pc/devpccard.c
perms
[plan9front.git] / sys / src / boot / pc / devpccard.c
1 /*
2      cardbus and pcmcia (grmph) support.
3 */
4 #include "u.h"
5 #include "lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "error.h"
10 #include "io.h"
11
12 extern int pciscan(int, Pcidev **);
13
14 int (*_pcmspecial)(char *, ISAConf *);
15 void (*_pcmspecialclose)(int);
16
17 int
18 pcmspecial(char *idstr, ISAConf *isa)
19 {
20         return (_pcmspecial  != nil)? _pcmspecial(idstr, isa): -1;
21 }
22
23 void
24 pcmspecialclose(int a)
25 {
26         if (_pcmspecialclose != nil)
27                 _pcmspecialclose(a);
28 }
29
30 static ulong
31 ioreserve(ulong, int size, int align, char *)
32 {
33         static ulong isaend = 0x400; /*0xfd00*/
34         ulong ioaddr;
35
36         if (align)
37                 isaend = ((isaend + align - 1) / align) * align;
38         ioaddr = isaend;
39         isaend += size;
40         return ioaddr;
41 }
42
43 #define MAP(x,o)        (Rmap + (x)*0x8 + o)
44
45 enum {
46         TI_vid = 0x104c,
47         TI_1131_did = 0xAC15,
48         TI_1250_did = 0xAC16,
49         TI_1450_did = 0xAC1B,
50         TI_1251A_did = 0xAC1D,
51         TI_1420_did = 0xAC51,
52
53         Ricoh_vid = 0x1180,
54         Ricoh_475_did = 0x0475,
55         Ricoh_476_did = 0x0476,
56         Ricoh_478_did = 0x0478,
57
58         O2_vid = 0x1217,
59         O2_OZ711M3_did = 0x7134,
60
61         Nslots = 4,             /* Maximum number of CardBus slots to use */
62
63         K = 1024,
64         M = K * K,
65
66         LegacyAddr = 0x3e0,
67         NUMEVENTS = 10,
68
69         TI1131xSC = 0x80,               // system control
70                 TI122X_SC_INTRTIE       = 1 << 29,
71         TI12xxIM = 0x8c,                // 
72         TI1131xCC = 0x91,               // card control
73                 TI113X_CC_RIENB = 1 << 7,
74                 TI113X_CC_ZVENABLE = 1 << 6,
75                 TI113X_CC_PCI_IRQ_ENA = 1 << 5,
76                 TI113X_CC_PCI_IREQ = 1 << 4,
77                 TI113X_CC_PCI_CSC = 1 << 3,
78                 TI113X_CC_SPKROUTEN = 1 << 1,
79                 TI113X_CC_IFG = 1 << 0,
80         TI1131xDC = 0x92,               // device control
81 };
82
83 typedef struct Variant Variant;
84 struct Variant {
85         ushort  vid;
86         ushort  did;
87         char    *name;
88 };
89
90 static Variant variant[] = {
91 {       Ricoh_vid,      Ricoh_475_did,  "Ricoh 475 PCI/Cardbus bridge", },
92 {       Ricoh_vid,      Ricoh_476_did,  "Ricoh 476 PCI/Cardbus bridge", },
93 {       Ricoh_vid,      Ricoh_478_did,  "Ricoh 478 PCI/Cardbus bridge", },
94 {       TI_vid,         TI_1131_did,    "TI PCI-1131 Cardbus Controller", },
95 {       TI_vid,         TI_1250_did,    "TI PCI-1250 Cardbus Controller", },
96 {       TI_vid,         TI_1450_did,    "TI PCI-1450 Cardbus Controller", },
97 {       TI_vid,         TI_1251A_did,   "TI PCI-1251A Cardbus Controller", },
98 {       TI_vid,         TI_1420_did,    "TI PCI-1420 Cardbus Controller", },
99 {       O2_vid,         O2_OZ711M3_did, "O2Micro OZ711M3 MemoryCardBus", },
100 };
101
102 /* Cardbus registers */
103 enum {
104         SocketEvent = 0,
105                 SE_CCD = 3 << 1,
106                 SE_POWER = 1 << 3,
107         SocketMask = 1,
108         SocketState = 2,
109                 SS_CCD = 3 << 1,
110                 SS_POWER = 1 << 3,
111                 SS_PC16 = 1 << 4,
112                 SS_CBC = 1 << 5,
113                 SS_NOTCARD = 1 << 7,
114                 SS_BADVCC = 1 << 9,
115                 SS_5V = 1 << 10,
116                 SS_3V = 1 << 11,
117         SocketForce = 3,
118         SocketControl = 4,
119                 SC_5V = 0x22,
120                 SC_3V = 0x33,
121 };
122
123 enum {
124         PciPCR_IO = 1 << 0,
125         PciPCR_MEM = 1 << 1,
126         PciPCR_Master = 1 << 2,
127
128         PciPMC = 0xa4,
129
130         Nbars = 6,
131         Ncmd = 10,
132         CBIRQ = 9,
133
134         PC16,
135         PC32,
136 };
137
138 enum {
139         Ti82365,
140         Tpd6710,
141         Tpd6720,
142         Tvg46x,
143 };
144
145 /*
146  *  Intel 82365SL PCIC controller for the PCMCIA or
147  *  Cirrus Logic PD6710/PD6720 which is mostly register compatible
148  */
149 enum
150 {
151         /*
152          *  registers indices
153          */
154         Rid=            0x0,            /* identification and revision */
155         Ris=            0x1,            /* interface status */
156         Rpc=            0x2,            /* power control */
157          Foutena=        (1<<7),        /*  output enable */
158          Fautopower=     (1<<5),        /*  automatic power switching */
159          Fcardena=       (1<<4),        /*  PC card enable */
160         Rigc=           0x3,            /* interrupt and general control */
161          Fiocard=        (1<<5),        /*  I/O card (vs memory) */
162          Fnotreset=      (1<<6),        /*  reset if not set */ 
163          FSMIena=        (1<<4),        /*  enable change interrupt on SMI */ 
164         Rcsc=           0x4,            /* card status change */
165         Rcscic=         0x5,            /* card status change interrupt config */
166          Fchangeena=     (1<<3),        /*  card changed */
167          Fbwarnena=      (1<<1),        /*  card battery warning */
168          Fbdeadena=      (1<<0),        /*  card battery dead */
169         Rwe=            0x6,            /* address window enable */
170          Fmem16=         (1<<5),        /*  use A23-A12 to decode address */
171         Rio=            0x7,            /* I/O control */
172          Fwidth16=       (1<<0),        /*  16 bit data width */
173          Fiocs16=        (1<<1),        /*  IOCS16 determines data width */
174          Fzerows=        (1<<2),        /*  zero wait state */
175          Ftiming=        (1<<3),        /*  timing register to use */
176         Riobtm0lo=      0x8,            /* I/O address 0 start low byte */
177         Riobtm0hi=      0x9,            /* I/O address 0 start high byte */
178         Riotop0lo=      0xa,            /* I/O address 0 stop low byte */
179         Riotop0hi=      0xb,            /* I/O address 0 stop high byte */
180         Riobtm1lo=      0xc,            /* I/O address 1 start low byte */
181         Riobtm1hi=      0xd,            /* I/O address 1 start high byte */
182         Riotop1lo=      0xe,            /* I/O address 1 stop low byte */
183         Riotop1hi=      0xf,            /* I/O address 1 stop high byte */
184         Rmap=           0x10,           /* map 0 */
185
186         /*
187          *  CL-PD67xx extension registers
188          */
189         Rmisc1=         0x16,           /* misc control 1 */
190          F5Vdetect=      (1<<0),
191          Fvcc3V=         (1<<1),
192          Fpmint=         (1<<2),
193          Fpsirq=         (1<<3),
194          Fspeaker=       (1<<4),
195          Finpack=        (1<<7),
196         Rfifo=          0x17,           /* fifo control */
197          Fflush=         (1<<7),        /*  flush fifo */
198         Rmisc2=         0x1E,           /* misc control 2 */
199          Flowpow=        (1<<1),        /*  low power mode */
200         Rchipinfo=      0x1F,           /* chip information */
201         Ratactl=        0x26,           /* ATA control */
202
203         /*
204          *  offsets into the system memory address maps
205          */
206         Mbtmlo=         0x0,            /* System mem addr mapping start low byte */
207         Mbtmhi=         0x1,            /* System mem addr mapping start high byte */
208          F16bit=         (1<<7),        /*  16-bit wide data path */
209         Mtoplo=         0x2,            /* System mem addr mapping stop low byte */
210         Mtophi=         0x3,            /* System mem addr mapping stop high byte */
211          Ftimer1=        (1<<6),        /*  timer set 1 */
212         Mofflo=         0x4,            /* Card memory offset address low byte */
213         Moffhi=         0x5,            /* Card memory offset address high byte */
214          Fregactive=     (1<<6),        /*  attribute memory */
215
216         /*
217          *  configuration registers - they start at an offset in attribute
218          *  memory found in the CIS.
219          */
220         Rconfig=        0,
221          Creset=         (1<<7),        /*  reset device */
222          Clevel=         (1<<6),        /*  level sensitive interrupt line */
223 };
224
225 /*
226  *  read and crack the card information structure enough to set
227  *  important parameters like power
228  */
229 /* cis memory walking */
230 typedef struct Cisdat Cisdat;
231 struct Cisdat {
232         uchar           *cisbase;
233         int             cispos;
234         int             cisskip;
235         int             cislen;
236 };
237
238 typedef struct Pcminfo Pcminfo;
239 struct Pcminfo {
240         char            verstr[512];            /* Version string */
241         PCMmap          mmap[4];                /* maps, last is always for the kernel */
242         ulong           conf_addr;              /* Config address */
243         uchar           conf_present;           /* Config register present */
244         int             nctab;                  /* In use configuration tables */
245         PCMconftab      ctab[8];                /* Configuration tables */
246         PCMconftab      *defctab;               /* Default conftab */
247
248         int             port;                   /* Actual port usage */
249         int             irq;                    /* Actual IRQ usage */
250 };
251
252 typedef struct Cardbus Cardbus;
253 struct Cardbus {
254         Lock;
255         Variant         *variant;               /* Which CardBus chipset */
256         Pcidev          *pci;                   /* The bridge itself */
257         ulong           *regs;                  /* Cardbus registers */
258         int             ltype;                  /* Legacy type */
259         int             lindex;                 /* Legacy port index address */
260         int             ldata;                  /* Legacy port data address */
261         int             lbase;                  /* Base register for this socket */
262
263         int             state;                  /* Current state of card */
264         int             type;                   /* Type of card */
265         Pcminfo         linfo;                  /* PCMCIA slot info */
266
267         int             special;                /* card is allocated to a driver */
268
269         int             refs;                   /* Number of refs to slot */
270         Lock            refslock;               /* inc/dev ref lock */
271 };
272
273 enum {
274         Mshift= 12,
275         Mgran=  (1<<Mshift),    /* granularity of maps */
276         Mmask=  ~(Mgran-1),     /* mask for address bits important to the chip */
277 };
278
279 static Cardbus cbslots[Nslots];
280 static int nslots;
281
282 static ulong exponent[8] = { 
283         1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 
284 };
285
286 static ulong vmant[16] = {
287         10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
288 };
289
290 static ulong mantissa[16] = { 
291         0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 
292 };
293
294 static void cbint(Ureg *, void *);
295 static int powerup(Cardbus *);
296 static void configure(Cardbus *);
297 static void managecard(Cardbus *);
298 static void cardmanager(void *);
299 static void eject(Cardbus *);
300 static void interrupt(Ureg *, void *);
301 static void powerdown(Cardbus *cb);
302 static void unconfigure(Cardbus *cb);
303
304 static void i82365probe(Cardbus *cb, int lindex, int ldata);
305 static void i82365configure(Cardbus *cb);
306 static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
307 static void isaunmap(PCMmap* m);
308 static uchar rdreg(Cardbus *cb, int index);
309 static void wrreg(Cardbus *cb, int index, uchar val);
310 static int readc(Cisdat *cis, uchar *x);
311 static void tvers1(Cardbus *cb, Cisdat *cis, int );
312 static void tcfig(Cardbus *cb, Cisdat *cis, int );
313 static void tentry(Cardbus *cb, Cisdat *cis, int );
314 static int vcode(int volt);
315 static int pccard_pcmspecial(char *idstr, ISAConf *isa);
316 static void pccard_pcmspecialclose(int slotno);
317
318 enum {
319         CardDetected,
320         CardPowered,
321         CardEjected,
322         CardConfigured,
323 };
324
325 static char *messages[] = {
326 [CardDetected]          "CardDetected",
327 [CardPowered]           "CardPowered",
328 [CardEjected]           "CardEjected",
329 [CardConfigured]        "CardConfigured",
330 };
331
332 enum {
333         SlotEmpty,
334         SlotFull,
335         SlotPowered,
336         SlotConfigured,
337 };
338
339 static char *states[] = {
340 [SlotEmpty]             "SlotEmpty",
341 [SlotFull]              "SlotFull",
342 [SlotPowered]           "SlotPowered",
343 [SlotConfigured]        "SlotConfigured",
344 };
345
346 static void
347 engine(Cardbus *cb, int message)
348 {
349         // print("engine(%d): %s(%s)\n", 
350         //       (int)(cb - cbslots), states[cb->state], messages[message]);
351         switch (cb->state) {
352         case SlotEmpty:
353
354                 switch (message) {
355                 case CardDetected:
356                         cb->state = SlotFull;
357                         powerup(cb);
358                         break;
359                 case CardEjected:
360                         break;
361                 default:
362                         //print("#Y%d: Invalid message %s in SlotEmpty state\n",
363                         //      (int)(cb - cbslots), messages[message]);
364                         break;
365                 }
366                 break;
367
368         case SlotFull:
369
370                 switch (message) {
371                 case CardPowered:
372                         cb->state = SlotPowered;
373                         configure(cb);
374                         break;
375                 case CardEjected:
376                         cb->state = SlotEmpty;
377                         powerdown(cb);
378                         break;
379                 default:
380                         //print("#Y%d: Invalid message %s in SlotFull state\n",
381                         //      (int)(cb - cbslots), messages[message]);
382                         break;
383                 }
384                 break;
385
386         case SlotPowered:
387
388                 switch (message) {
389                 case CardConfigured:
390                         cb->state = SlotConfigured;
391                         break;
392                 case CardEjected:
393                         cb->state = SlotEmpty;
394                         unconfigure(cb);
395                         powerdown(cb);
396                         break;
397                 default:
398                         print("#Y%d: Invalid message %s in SlotPowered state\n",
399                                 (int)(cb - cbslots), messages[message]);
400                         break;
401                 }
402                 break;
403
404         case SlotConfigured:
405
406                 switch (message) {
407                 case CardEjected:
408                         cb->state = SlotEmpty;
409                         unconfigure(cb);
410                         powerdown(cb);
411                         break;
412                 default:
413                         //print("#Y%d: Invalid message %s in SlotConfigured state\n",
414                         //      (int)(cb - cbslots), messages[message]);
415                         break;
416                 }
417                 break;
418         }
419 }
420
421 void
422 devpccardlink(void)
423 {
424         static int initialized;
425         Pcidev *pci;
426         int i;
427         char *p;
428
429         if (initialized) 
430                 return;
431         initialized = 1;
432
433         if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
434                 return;
435
436         if(_pcmspecial)
437                 return;
438
439
440         /* Allocate legacy space */
441         if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
442                 print("#Y: WARNING: Cannot allocate legacy ports\n");
443
444         /* Find all CardBus controllers */
445         pci = nil;
446         while ((pci = pcimatch(pci, 0, 0)) != nil) {
447                 ulong baddr;
448                 uchar pin;
449                 Cardbus *cb;
450                 int slot;
451
452                 if(pci->ccrb != 6 || pci->ccru != 7)
453                         continue;
454                 for (i = 0; i != nelem(variant); i++)
455                         if (pci->vid == variant[i].vid && pci->did == variant[i].did)
456                                 break;
457                 if (i == nelem(variant))
458                         continue;
459
460                 /* initialize this slot */
461                 slot = nslots++;
462                 cb = &cbslots[slot];
463
464                 cb->pci = pci;
465                 cb->variant = &variant[i];
466
467                 // Set up PCI bus numbers if needed.
468                 if (pcicfgr8(pci, PciSBN) == 0) {
469                         static int busbase = 0x20;
470
471                         pcicfgw8(pci, PciSBN, busbase);
472                         pcicfgw8(pci, PciUBN, busbase + 2);
473                         busbase += 3;
474                 }
475
476                 // Patch up intl if needed.
477                 if ((pin = pcicfgr8(pci, PciINTP)) != 0 && 
478                     (pci->intl == 0xff || pci->intl == 0)) {
479                         pci->intl = pciipin(nil, pin);
480                         pcicfgw8(pci, PciINTL, pci->intl);
481
482                         if (pci->intl == 0xff || pci->intl == 0)
483                                 print("#Y%d: No interrupt?\n", (int)(cb - cbslots));
484                 }
485                 
486                 // Don't you love standards!
487                 if (pci->vid == TI_vid) {
488                         if (pci->did <= TI_1131_did) {
489                                 uchar cc;
490
491                                 cc = pcicfgr8(pci, TI1131xCC);
492                                 cc &= ~(TI113X_CC_PCI_IRQ_ENA |
493                                                 TI113X_CC_PCI_IREQ | 
494                                                 TI113X_CC_PCI_CSC |
495                                                 TI113X_CC_ZVENABLE);
496                                 cc |= TI113X_CC_PCI_IRQ_ENA | 
497                                                 TI113X_CC_PCI_IREQ | 
498                                                 TI113X_CC_SPKROUTEN;
499                                 pcicfgw8(pci, TI1131xCC, cc);
500
501                                 // PCI interrupts only
502                                 pcicfgw8(pci, TI1131xDC, 
503                                                 pcicfgr8(pci, TI1131xDC) & ~6);
504
505                                 // CSC ints to PCI bus.
506                                 wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
507                         }
508                         else if (pci->did == TI_1250_did) {
509                                 print("No support yet for the TI_1250_did, prod pb\n");
510                         }
511                         else if (pci->did == TI_1420_did) {
512                                 // Disable Vcc protection
513                                 pcicfgw32(cb->pci, 0x80, 
514                                         pcicfgr32(cb->pci, 0x80) | (1 << 21));
515                         }
516                         
517                         pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
518                 }
519         
520                 if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
521                         int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
522
523                         baddr = upamalloc(baddr, size, size);
524                         pcicfgw32(cb->pci, PciBAR0, baddr);
525                         cb->regs = (ulong *)KADDR(baddr);
526                 }
527                 else
528                         cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));
529                 cb->state = SlotEmpty;
530
531                 /* Don't really know what to do with this... */
532                 i82365probe(cb, LegacyAddr, LegacyAddr + 1);
533
534                 print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots, 
535                          variant[i].name, baddr, pci->intl);
536         }
537
538         if (nslots == 0)
539                 return;
540
541         _pcmspecial = pccard_pcmspecial;
542         _pcmspecialclose = pccard_pcmspecialclose;
543
544         for (i = 0; i != nslots; i++) {
545                 Cardbus *cb = &cbslots[i];
546
547                 if ((cb->regs[SocketState] & SE_CCD) == 0)
548                         engine(cb, CardDetected);
549         }
550
551         delay(500);                     /* Allow time for power up */
552
553         for (i = 0; i != nslots; i++) {
554                 Cardbus *cb = &cbslots[i];
555
556                 if (cb->regs[SocketState] & SE_POWER)
557                         engine(cb, CardPowered);
558
559                 /* Ack and enable interrupts on all events */
560                 //cb->regs[SocketEvent] = cb->regs[SocketEvent];
561                 //cb->regs[SocketMask] |= 0xF;  
562                 //wrreg(cb, Rcscic, 0xC);
563         }
564 }
565
566 static int
567 powerup(Cardbus *cb)
568 {
569         ulong state;
570         ushort bcr;
571
572         state = cb->regs[SocketState];
573         if (state & SS_PC16) {
574         
575                 // print("#Y%ld: Probed a PC16 card, powering up card\n", cb - cbslots);
576                 cb->type = PC16;
577                 memset(&cb->linfo, 0, sizeof(Pcminfo));
578
579                 /* power up and unreset, wait's are empirical (???) */
580                 wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
581                 delay(300);
582                 wrreg(cb, Rigc, 0);
583                 delay(100);
584                 wrreg(cb, Rigc, Fnotreset);
585                 delay(500);
586
587                 return 1;
588         }
589
590         if (state & SS_CCD)
591                 return 0;
592
593         if (state & SS_NOTCARD) {
594                 print("#Y%ld: No card inserted\n", cb - cbslots);
595                 return 0;
596         }
597
598         if (state & SS_BADVCC) {
599                 print("#Y%ld: Bad VCC request to card, powering down card!\n", 
600                          cb - cbslots);
601                 cb->regs[SocketControl] = 0;
602                 return 0;
603         }
604
605         if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
606                 print("#Y%ld: Unsupported voltage, powering down card!\n", 
607                         cb - cbslots);
608                 cb->regs[SocketControl] = 0;
609                 return 0;
610         }
611
612         //print("#Y%ld: card %spowered at %d volt\n", cb - cbslots, 
613         //      (state & SS_POWER)? "": "not ", 
614         //      (state & SS_3V)? 3: (state & SS_5V)? 5: -1);
615
616         /* Power up the card
617          * and make sure the secondary bus is not in reset.
618          */
619         cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
620         delay(50);
621         bcr = pcicfgr16(cb->pci, PciBCR);
622         bcr &= ~0x40;
623         pcicfgw16(cb->pci, PciBCR, bcr);
624         delay(100);
625
626         cb->type = PC32;
627
628         return 1;
629 }
630
631 static void
632 powerdown(Cardbus *cb)
633 {
634         ushort bcr;
635
636         if (cb->type == PC16) {
637
638                 wrreg(cb, Rpc, 0);      /* turn off card power */
639                 wrreg(cb, Rwe, 0);      /* no windows */
640
641                 cb->type = -1;
642                 return;
643         }
644
645         bcr = pcicfgr16(cb->pci, PciBCR);
646         bcr |= 0x40;
647         pcicfgw16(cb->pci, PciBCR, bcr);
648         cb->regs[SocketControl] = 0;
649         cb->type = -1;
650 }
651
652 static void
653 configure(Cardbus *cb)
654 {
655         Pcidev *pci;
656         ulong size, bar;
657         int i, ioindex, memindex, r;
658
659         //print("configuring slot %d (%s)\n", (int)(cb - cbslots), states[cb->state]);
660         if (cb->state == SlotConfigured)
661                 return;
662         engine(cb, CardConfigured);
663
664         delay(50);                                      /* Emperically established */
665
666         if (cb->type == PC16) {
667                 i82365configure(cb);
668                 return;
669         }
670
671         /* Scan the CardBus for new PCI devices */
672         pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
673         pci = cb->pci->bridge;
674         while (pci) {
675                 r = pcicfgr16(pci, PciPCR);
676                 r &= ~(PciPCR_IO|PciPCR_MEM);
677                 pcicfgw16(pci, PciPCR, r);
678
679                 /*
680                  * Treat the found device as an ordinary PCI card.
681                  * It seems that the CIS is not always present in
682                  * CardBus cards.
683                  * XXX, need to support multifunction cards
684                  */
685                 memindex = ioindex = 0;
686                 for (i = 0; i != Nbars; i++) {
687
688                         if (pci->mem[i].size == 0)
689                                 continue;
690                         if (pci->mem[i].bar & 1) {
691
692                                 // Allocate I/O space
693                                 if (ioindex > 1) {
694                                         print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots);
695                                         continue;
696                                 }
697                                 bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");
698                                 pci->mem[i].bar = bar | 1;
699                                 pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), 
700                                                   pci->mem[i].bar);
701                                 pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar);
702                                 pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 
703                                                  bar + pci->mem[i].size - 1);
704                                 //print("ioindex[%d] %.8uX (%d)\n", 
705                                 //      ioindex, bar, pci->mem[i].size);
706                                 ioindex++;
707                                 continue;
708                         }
709
710                         // Allocating memory space
711                         if (memindex > 1) {
712                                 print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots);
713                                 continue;
714                         }
715
716                         bar = upamalloc(0, pci->mem[i].size, BY2PG);
717                         pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);
718                         pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);
719                         pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);
720                         pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 
721                                           bar + pci->mem[i].size - 1);
722
723                         if (pci->mem[i].bar & 0x80) {
724                                 /* Enable prefetch */
725                                 r = pcicfgr16(cb->pci, PciBCR);
726                                 r |= 1 << (8 + memindex);
727                                 pcicfgw16(cb->pci, PciBCR, r);
728                         }
729
730                         //print("memindex[%d] %.8uX (%d)\n", 
731                         //        memindex, bar, pci->mem[i].size);
732                         memindex++;
733                 }
734
735                 if ((size = pcibarsize(pci, PciEBAR0)) > 0) {
736
737                         if (memindex > 1)
738                                 print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",
739                                         cb - cbslots);
740                         else {
741                                 pci->rom.bar = upamalloc(0, size, BY2PG);
742                                 pci->rom.size = size;
743
744                                 pcicfgw32(pci, PciEBAR0, pci->rom.bar);
745                                 pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8,
746                                                  pci->rom.bar);
747                                 pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 
748                                                  pci->rom.bar + pci->rom.size - 1);
749                         }
750                 }
751
752                 /* Set the basic PCI registers for the device */
753                 pci->pcr = pcicfgr16(pci, PciPCR);
754                 pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
755                 pci->cls = 8;
756                 pci->ltr = 64;
757                 pcicfgw16(pci, PciPCR, pci->pcr);
758                 pcicfgw8(pci, PciCLS, pci->cls);
759                 pcicfgw8(pci, PciLTR, pci->ltr);
760
761                 if (pcicfgr8(pci, PciINTP)) {
762                         pci->intl = pcicfgr8(cb->pci, PciINTL);
763                         pcicfgw8(pci, PciINTL, pci->intl);
764
765                         /* Route interrupts to INTA#/B# */
766                         pcicfgw16(cb->pci, PciBCR, 
767                                           pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
768                 }
769                         
770                 pci = pci->list;
771         }
772 }
773
774 static void
775 unconfigure(Cardbus *cb)
776 {
777         Pcidev *pci;
778         int i, ioindex, memindex, r;
779
780         if (cb->type == PC16) {
781                 print("#Y%d: Don't know how to unconfigure a PC16 card\n",
782                          (int)(cb - cbslots));
783
784                 memset(&cb->linfo, 0, sizeof(Pcminfo));
785                 return;
786         }
787
788         pci = cb->pci->bridge;
789         if (pci == nil) 
790                 return;         /* Not configured */
791         cb->pci->bridge = nil;          
792
793         memindex = ioindex = 0;
794         while (pci) {
795                 Pcidev *_pci;
796
797                 for (i = 0; i != Nbars; i++) {
798                         if (pci->mem[i].size == 0)
799                                 continue;
800                         if (pci->mem[i].bar & 1) {
801                                 iofree(pci->mem[i].bar & ~1);
802                                 pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, 
803                                                  (ushort)-1);
804                                 pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
805                                 ioindex++;
806                                 continue;
807                         }
808
809                         upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
810                         pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
811                         pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
812                         r = pcicfgr16(cb->pci, PciBCR);
813                         r &= ~(1 << (8 + memindex));
814                         pcicfgw16(cb->pci, PciBCR, r);
815                         memindex++;
816                 }
817
818                 if (pci->rom.bar && memindex < 2) {
819                         upafree(pci->rom.bar & ~0xF, pci->rom.size);
820                         pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
821                         pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
822                         memindex++;
823                 }
824
825                 _pci = pci->list;
826                 free(_pci);
827                 pci = _pci;
828         }
829 }
830
831 static void
832 i82365configure(Cardbus *cb)
833 {
834         int this;
835         Cisdat cis;
836         PCMmap *m;
837         uchar type, link;
838
839         /*
840          * Read all tuples in attribute space.
841          */
842         m = isamap(cb, 0, 0, 1);
843         if(m == 0)
844                 return;
845
846         cis.cisbase = KADDR(m->isa);
847         cis.cispos = 0;
848         cis.cisskip = 2;
849         cis.cislen = m->len;
850
851         /* loop through all the tuples */
852         for(;;){
853                 this = cis.cispos;
854                 if(readc(&cis, &type) != 1)
855                         break;
856                 if(type == 0xFF)
857                         break;
858                 if(readc(&cis, &link) != 1)
859                         break;
860
861                 switch(type){
862                 default:
863                         break;
864                 case 0x15:
865                         tvers1(cb, &cis, type);
866                         break;
867                 case 0x1A:
868                         tcfig(cb, &cis, type);
869                         break;
870                 case 0x1B:
871                         tentry(cb, &cis, type);
872                         break;
873                 }
874
875                 if(link == 0xFF)
876                         break;
877                 cis.cispos = this + (2+link);
878         }
879         isaunmap(m);
880 }
881
882 /*
883  *  look for a card whose version contains 'idstr'
884  */
885 static int
886 pccard_pcmspecial(char *idstr, ISAConf *isa)
887 {
888         int i, irq;
889         PCMconftab *ct, *et;
890         Pcminfo *pi;
891         Cardbus *cb;
892         uchar x, we, *p;
893
894         cb = nil;
895         for (i = 0; i != nslots; i++) {
896                 cb = &cbslots[i];
897
898                 lock(cb);
899                 if (cb->state == SlotConfigured &&
900                     cb->type == PC16 && 
901                     !cb->special &&
902                     strstr(cb->linfo.verstr, idstr)) 
903                         break;
904                 unlock(cb);
905         }
906
907         if (i == nslots) {
908                 // print("#Y: %s not found\n", idstr);
909                 return -1;
910         }
911
912         pi = &cb->linfo;
913
914         /*
915           *  configure the PCMslot for IO.  We assume very heavily that we can read
916           *  configuration info from the CIS.  If not, we won't set up correctly.
917           */
918         irq = isa->irq;
919         if(irq == 2)
920                 irq = 9;
921
922         et = &pi->ctab[pi->nctab];
923         ct = nil;
924         for(i = 0; i < isa->nopt; i++){
925                 int index;
926                 char *cp;
927
928                 if(strncmp(isa->opt[i], "index=", 6))
929                         continue;
930                 index = strtol(&isa->opt[i][6], &cp, 0);
931                 if(cp == &isa->opt[i][6] || index >= pi->nctab) {
932                         unlock(cb);
933                         print("#Y%d: Cannot find index %d in conf table\n", 
934                                  (int)(cb - cbslots), index);
935                         return -1;
936                 }
937                 ct = &pi->ctab[index];
938         }
939
940         if(ct == nil){
941                 PCMconftab *t;
942
943                 /* assume default is right */
944                 if(pi->defctab)
945                         ct = pi->defctab;
946                 else
947                         ct = pi->ctab;
948         
949                 /* try for best match */
950                 if(ct->nio == 0
951                 || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
952                         for(t = pi->ctab; t < et; t++)
953                                 if(t->nio
954                                 && t->io[0].start == isa->port
955                                 && ((1<<irq) & t->irqs)){
956                                         ct = t;
957                                         break;
958                                 }
959                 }
960                 if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
961                         for(t = pi->ctab; t < et; t++)
962                                 if(t->nio && ((1<<irq) & t->irqs)){
963                                         ct = t;
964                                         break;
965                                 }
966                 }
967                 if(ct->nio == 0){
968                         for(t = pi->ctab; t < et; t++)
969                                 if(t->nio){
970                                         ct = t;
971                                         break;
972                                 }
973                 }
974         }
975
976         if(ct == et || ct->nio == 0) {
977                 unlock(cb);
978                 print("#Y%d: No configuration?\n", (int)(cb - cbslots));
979                 return -1;
980         }
981         if(isa->port == 0 && ct->io[0].start == 0) {
982                 unlock(cb);
983                 print("#Y%d: No part or start address\n", (int)(cb - cbslots));
984                 return -1;
985         }
986
987         cb->special = 1;        /* taken */
988
989         /* route interrupts */
990         isa->irq = irq;
991         wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
992
993         /* set power and enable device */
994         x = vcode(ct->vpp1);
995         wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
996
997         /* 16-bit data path */
998         if(ct->bit16)
999                 x = Ftiming|Fiocs16|Fwidth16;
1000         else
1001                 x = Ftiming;
1002         if(ct->nio == 2 && ct->io[1].start)
1003                 x |= x<<4;
1004         wrreg(cb, Rio, x);
1005
1006         /*
1007          * enable io port map 0
1008          * the 'top' register value includes the last valid address
1009          */
1010         if(isa->port == 0)
1011                 isa->port = ct->io[0].start;
1012         we = rdreg(cb, Rwe);
1013         wrreg(cb, Riobtm0lo, isa->port);
1014         wrreg(cb, Riobtm0hi, isa->port>>8);
1015         i = isa->port+ct->io[0].len-1;
1016         wrreg(cb, Riotop0lo, i);
1017         wrreg(cb, Riotop0hi, i>>8);
1018         we |= 1<<6;
1019         if(ct->nio == 2 && ct->io[1].start){
1020                 wrreg(cb, Riobtm1lo, ct->io[1].start);
1021                 wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
1022                 i = ct->io[1].start+ct->io[1].len-1;
1023                 wrreg(cb, Riotop1lo, i);
1024                 wrreg(cb, Riotop1hi, i>>8);
1025                 we |= 1<<7;
1026         }
1027         wrreg(cb, Rwe, we);
1028
1029         /* only touch Rconfig if it is present */
1030         if(pi->conf_present & (1<<Rconfig)){
1031                 PCMmap *m;
1032
1033                 /*  Reset adapter */
1034                 m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
1035                 p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
1036
1037                 /* set configuration and interrupt type */
1038                 x = ct->index;
1039                 if((ct->irqtype & 0x20)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/)
1040                         x |= Clevel;
1041                 *p = x;
1042                 delay(5);
1043
1044                 isaunmap(m);
1045         }
1046
1047         pi->port = isa->port;
1048         pi->irq = isa->irq;
1049         unlock(cb);
1050
1051         print("#Y%d: %s irq %ld, port %lX\n", (int)(cb - cbslots), pi->verstr, isa->irq, isa->port);
1052         return (int)(cb - cbslots);
1053 }
1054
1055 static void
1056 pccard_pcmspecialclose(int slotno)
1057 {
1058         Cardbus *cb = &cbslots[slotno];
1059
1060         wrreg(cb, Rwe, 0);      /* no windows */
1061         cb->special = 0;
1062 }
1063
1064 static int
1065 xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
1066 {
1067         PCMmap *m;
1068         Cisdat cis;
1069         int i, l;
1070         uchar *p;
1071         uchar type, link, n, c;
1072         int this, subtype;
1073         Cardbus *cb = &cbslots[slotno];
1074
1075         m = isamap(cb, 0, 0, attr);
1076         if(m == 0)
1077                 return -1;
1078
1079         cis.cisbase = KADDR(m->isa);
1080         cis.cispos = 0;
1081         cis.cisskip = attr ? 2 : 1;
1082         cis.cislen = m->len;
1083
1084         /* loop through all the tuples */
1085         for(i = 0; i < 1000; i++){
1086                 this = cis.cispos;
1087                 if(readc(&cis, &type) != 1)
1088                         break;
1089                 if(type == 0xFF)
1090                         break;
1091                 if(readc(&cis, &link) != 1)
1092                         break;
1093                 if(link == 0xFF)
1094                         break;
1095
1096                 n = link;
1097                 if (link > 1 && subtuple != -1) {
1098                         if (readc(&cis, &c) != 1)
1099                                 break;
1100                         subtype = c;
1101                         n--;
1102                 } else
1103                         subtype = -1;
1104
1105                 if(type == tuple && subtype == subtuple) {
1106                         p = v;
1107                         for(l=0; l<nv && l<n; l++)
1108                                 if(readc(&cis, p++) != 1)
1109                                         break;
1110                         isaunmap(m);
1111                         return nv;
1112                 }
1113                 cis.cispos = this + (2+link);
1114         }
1115         isaunmap(m);
1116         return -1;
1117 }
1118
1119 static PCMmap *
1120 isamap(Cardbus *cb, ulong offset, int len, int attr)
1121 {
1122         uchar we, bit;
1123         PCMmap *m, *nm;
1124         Pcminfo *pi;
1125         int i;
1126         ulong e;
1127
1128         pi = &cb->linfo;
1129
1130         /* convert offset to granularity */
1131         if(len <= 0)
1132                 len = 1;
1133         e = ROUND(offset+len, Mgran);
1134         offset &= Mmask;
1135         len = e - offset;
1136
1137         /* look for a map that covers the right area */
1138         we = rdreg(cb, Rwe);
1139         bit = 1;
1140         nm = 0;
1141         for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
1142                 if((we & bit))
1143                 if(m->attr == attr)
1144                 if(offset >= m->ca && e <= m->cea){
1145
1146                         m->ref++;
1147                         return m;
1148                 }
1149                 bit <<= 1;
1150                 if(nm == 0 && m->ref == 0)
1151                         nm = m;
1152         }
1153         m = nm;
1154         if(m == 0)
1155                 return 0;
1156
1157         /* if isa space isn't big enough, free it and get more */
1158         if(m->len < len){
1159                 if(m->isa){
1160                         umbfree(m->isa, m->len);
1161                         m->len = 0;
1162                 }
1163                 m->isa = PADDR(umbmalloc(0, len, Mgran));
1164                 if(m->isa == 0){
1165                         print("isamap: out of isa space\n");
1166                         return 0;
1167                 }
1168                 m->len = len;
1169         }
1170
1171         /* set up new map */
1172         m->ca = offset;
1173         m->cea = m->ca + m->len;
1174         m->attr = attr;
1175         i = m - pi->mmap;
1176         bit = 1<<i;
1177         wrreg(cb, Rwe, we & ~bit);              /* disable map before changing it */
1178         wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
1179         wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
1180         wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
1181         wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
1182         offset -= m->isa;
1183         offset &= (1<<25)-1;
1184         offset >>= Mshift;
1185         wrreg(cb, MAP(i, Mofflo), offset);
1186         wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
1187         wrreg(cb, Rwe, we | bit);               /* enable map */
1188         m->ref = 1;
1189
1190         return m;
1191 }
1192
1193 static void
1194 isaunmap(PCMmap* m)
1195 {
1196         m->ref--;
1197 }
1198
1199 /*
1200  *  reading and writing card registers
1201  */
1202 static uchar
1203 rdreg(Cardbus *cb, int index)
1204 {
1205         outb(cb->lindex, cb->lbase + index);
1206         return inb(cb->ldata);
1207 }
1208
1209 static void
1210 wrreg(Cardbus *cb, int index, uchar val)
1211 {
1212         outb(cb->lindex, cb->lbase + index);
1213         outb(cb->ldata, val);
1214 }
1215
1216 static int
1217 readc(Cisdat *cis, uchar *x)
1218 {
1219         if(cis->cispos >= cis->cislen)
1220                 return 0;
1221         *x = cis->cisbase[cis->cisskip*cis->cispos];
1222         cis->cispos++;
1223         return 1;
1224 }
1225
1226 static ulong
1227 getlong(Cisdat *cis, int size)
1228 {
1229         uchar c;
1230         int i;
1231         ulong x;
1232
1233         x = 0;
1234         for(i = 0; i < size; i++){
1235                 if(readc(cis, &c) != 1)
1236                         break;
1237                 x |= c<<(i*8);
1238         }
1239         return x;
1240 }
1241
1242 static void
1243 tcfig(Cardbus *cb, Cisdat *cis, int )
1244 {
1245         uchar size, rasize, rmsize;
1246         uchar last;
1247         Pcminfo *pi;
1248
1249         if(readc(cis, &size) != 1)
1250                 return;
1251         rasize = (size&0x3) + 1;
1252         rmsize = ((size>>2)&0xf) + 1;
1253         if(readc(cis, &last) != 1)
1254                 return;
1255
1256         pi = &cb->linfo;
1257         pi->conf_addr = getlong(cis, rasize);
1258         pi->conf_present = getlong(cis, rmsize);
1259 }
1260
1261 static void
1262 tvers1(Cardbus *cb, Cisdat *cis, int )
1263 {
1264         uchar c, major, minor, last;
1265         int  i;
1266         Pcminfo *pi;
1267
1268         pi = &cb->linfo;
1269         if(readc(cis, &major) != 1)
1270                 return;
1271         if(readc(cis, &minor) != 1)
1272                 return;
1273         last = 0;
1274         for(i = 0; i < sizeof(pi->verstr) - 1; i++){
1275                 if(readc(cis, &c) != 1)
1276                         return;
1277                 if(c == 0)
1278                         c = ';';
1279                 if(c == '\n')
1280                         c = ';';
1281                 if(c == 0xff)
1282                         break;
1283                 if(c == ';' && last == ';')
1284                         continue;
1285                 pi->verstr[i] = c;
1286                 last = c;
1287         }
1288         pi->verstr[i] = 0;
1289 }
1290
1291 static ulong
1292 microvolt(Cisdat *cis)
1293 {
1294         uchar c;
1295         ulong microvolts;
1296         ulong exp;
1297
1298         if(readc(cis, &c) != 1)
1299                 return 0;
1300         exp = exponent[c&0x7];
1301         microvolts = vmant[(c>>3)&0xf]*exp;
1302         while(c & 0x80){
1303                 if(readc(cis, &c) != 1)
1304                         return 0;
1305                 switch(c){
1306                 case 0x7d:
1307                         break;          /* high impedence when sleeping */
1308                 case 0x7e:
1309                 case 0x7f:
1310                         microvolts = 0; /* no connection */
1311                         break;
1312                 default:
1313                         exp /= 10;
1314                         microvolts += exp*(c&0x7f);
1315                 }
1316         }
1317         return microvolts;
1318 }
1319
1320 static ulong
1321 nanoamps(Cisdat *cis)
1322 {
1323         uchar c;
1324         ulong nanoamps;
1325
1326         if(readc(cis, &c) != 1)
1327                 return 0;
1328         nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
1329         while(c & 0x80){
1330                 if(readc(cis, &c) != 1)
1331                         return 0;
1332                 if(c == 0x7d || c == 0x7e || c == 0x7f)
1333                         nanoamps = 0;
1334         }
1335         return nanoamps;
1336 }
1337
1338 /*
1339  * only nominal voltage (feature 1) is important for config,
1340  * other features must read card to stay in sync.
1341  */
1342 static ulong
1343 power(Cisdat *cis)
1344 {
1345         uchar feature;
1346         ulong mv;
1347
1348         mv = 0;
1349         if(readc(cis, &feature) != 1)
1350                 return 0;
1351         if(feature & 1)
1352                 mv = microvolt(cis);
1353         if(feature & 2)
1354                 microvolt(cis);
1355         if(feature & 4)
1356                 microvolt(cis);
1357         if(feature & 8)
1358                 nanoamps(cis);
1359         if(feature & 0x10)
1360                 nanoamps(cis);
1361         if(feature & 0x20)
1362                 nanoamps(cis);
1363         if(feature & 0x40)
1364                 nanoamps(cis);
1365         return mv/1000000;
1366 }
1367
1368 static ulong
1369 ttiming(Cisdat *cis, int scale)
1370 {
1371         uchar unscaled;
1372         ulong nanosecs;
1373
1374         if(readc(cis, &unscaled) != 1)
1375                 return 0;
1376         nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
1377         nanosecs = nanosecs * exponent[scale];
1378         return nanosecs;
1379 }
1380
1381 static void
1382 timing(Cisdat *cis, PCMconftab *ct)
1383 {
1384         uchar c, i;
1385
1386         if(readc(cis, &c) != 1)
1387                 return;
1388         i = c&0x3;
1389         if(i != 3)
1390                 ct->maxwait = ttiming(cis, i);          /* max wait */
1391         i = (c>>2)&0x7;
1392         if(i != 7)
1393                 ct->readywait = ttiming(cis, i);        /* max ready/busy wait */
1394         i = (c>>5)&0x7;
1395         if(i != 7)
1396                 ct->otherwait = ttiming(cis, i);        /* reserved wait */
1397 }
1398
1399 static void
1400 iospaces(Cisdat *cis, PCMconftab *ct)
1401 {
1402         uchar c;
1403         int i, nio;
1404
1405         ct->nio = 0;
1406         if(readc(cis, &c) != 1)
1407                 return;
1408
1409         ct->bit16 = ((c>>5)&3) >= 2;
1410         if(!(c & 0x80)){
1411                 ct->io[0].start = 0;
1412                 ct->io[0].len = 1<<(c&0x1f);
1413                 ct->nio = 1;
1414                 return;
1415         }
1416
1417         if(readc(cis, &c) != 1)
1418                 return;
1419
1420         /*
1421          * For each of the range descriptions read the
1422          * start address and the length (value is length-1).
1423          */
1424         nio = (c&0xf)+1;
1425         for(i = 0; i < nio; i++){
1426                 ct->io[i].start = getlong(cis, (c>>4)&0x3);
1427                 ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
1428         }
1429         ct->nio = nio;
1430 }
1431
1432 static void
1433 irq(Cisdat *cis, PCMconftab *ct)
1434 {
1435         uchar c;
1436
1437         if(readc(cis, &c) != 1)
1438                 return;
1439         ct->irqtype = c & 0xe0;
1440         if(c & 0x10)
1441                 ct->irqs = getlong(cis, 2);
1442         else
1443                 ct->irqs = 1<<(c&0xf);
1444         ct->irqs &= 0xDEB8;             /* levels available to card */
1445 }
1446
1447 static void
1448 memspace(Cisdat *cis, int asize, int lsize, int host)
1449 {
1450         ulong haddress, address, len;
1451
1452         len = getlong(cis, lsize)*256;
1453         address = getlong(cis, asize)*256;
1454         USED(len, address);
1455         if(host){
1456                 haddress = getlong(cis, asize)*256;
1457                 USED(haddress);
1458         }
1459 }
1460
1461 static void
1462 tentry(Cardbus *cb, Cisdat *cis, int )
1463 {
1464         uchar c, i, feature;
1465         PCMconftab *ct;
1466         Pcminfo *pi;
1467
1468         pi = &cb->linfo;
1469         if(pi->nctab >= nelem(pi->ctab))
1470                 return;
1471         if(readc(cis, &c) != 1)
1472                 return;
1473         ct = &pi->ctab[pi->nctab++];
1474
1475         /* copy from last default config */
1476         if(pi->defctab)
1477                 *ct = *pi->defctab;
1478
1479         ct->index = c & 0x3f;
1480
1481         /* is this the new default? */
1482         if(c & 0x40)
1483                 pi->defctab = ct;
1484
1485         /* memory wait specified? */
1486         if(c & 0x80){
1487                 if(readc(cis, &i) != 1)
1488                         return;
1489                 if(i&0x80)
1490                         ct->memwait = 1;
1491         }
1492
1493         if(readc(cis, &feature) != 1)
1494                 return;
1495         switch(feature&0x3){
1496         case 1:
1497                 ct->vpp1 = ct->vpp2 = power(cis);
1498                 break;
1499         case 2:
1500                 power(cis);
1501                 ct->vpp1 = ct->vpp2 = power(cis);
1502                 break;
1503         case 3:
1504                 power(cis);
1505                 ct->vpp1 = power(cis);
1506                 ct->vpp2 = power(cis);
1507                 break;
1508         default:
1509                 break;
1510         }
1511         if(feature&0x4)
1512                 timing(cis, ct);
1513         if(feature&0x8)
1514                 iospaces(cis, ct);
1515         if(feature&0x10)
1516                 irq(cis, ct);
1517         switch((feature>>5)&0x3){
1518         case 1:
1519                 memspace(cis, 0, 2, 0);
1520                 break;
1521         case 2:
1522                 memspace(cis, 2, 2, 0);
1523                 break;
1524         case 3:
1525                 if(readc(cis, &c) != 1)
1526                         return;
1527                 for(i = 0; i <= (c&0x7); i++)
1528                         memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
1529                 break;
1530         }
1531 }
1532
1533 static void
1534 i82365probe(Cardbus *cb, int lindex, int ldata)
1535 {
1536         uchar c, id;
1537         int dev = 0;    /* According to the Ricoh spec 00->3F _and_ 80->BF seem
1538                                      to be the same socket A (ditto for B). */
1539
1540         outb(lindex, Rid + (dev<<7));
1541         id = inb(ldata);
1542         if((id & 0xf0) != 0x80)
1543                 return;         /* not a memory & I/O card */
1544         if((id & 0x0f) == 0x00)
1545                 return;         /* no revision number, not possible */
1546
1547         cb->lindex = lindex;
1548         cb->ldata = ldata;
1549         cb->ltype = Ti82365;
1550         cb->lbase = (int)(cb - cbslots) * 0x40;
1551
1552         switch(id){
1553         case 0x82:
1554         case 0x83:
1555         case 0x84:
1556                 /* could be a cirrus */
1557                 outb(cb->lindex, Rchipinfo + (dev<<7));
1558                 outb(cb->ldata, 0);
1559                 c = inb(cb->ldata);
1560                 if((c & 0xc0) != 0xc0)
1561                         break;
1562                 c = inb(cb->ldata);
1563                 if((c & 0xc0) != 0x00)
1564                         break;
1565                 if(c & 0x20){
1566                         cb->ltype = Tpd6720;
1567                 } else {
1568                         cb->ltype = Tpd6710;
1569                 }
1570                 break;
1571         }
1572
1573         /* if it's not a Cirrus, it could be a Vadem... */
1574         if(cb->ltype == Ti82365){
1575                 /* unlock the Vadem extended regs */
1576                 outb(cb->lindex, 0x0E + (dev<<7));
1577                 outb(cb->lindex, 0x37 + (dev<<7));
1578
1579                 /* make the id register show the Vadem id */
1580                 outb(cb->lindex, 0x3A + (dev<<7));
1581                 c = inb(cb->ldata);
1582                 outb(cb->ldata, c|0xC0);
1583                 outb(cb->lindex, Rid + (dev<<7));
1584                 c = inb(cb->ldata);
1585                 if(c & 0x08)
1586                         cb->ltype = Tvg46x;
1587
1588                 /* go back to Intel compatible id */
1589                 outb(cb->lindex, 0x3A + (dev<<7));
1590                 c = inb(cb->ldata);
1591                 outb(cb->ldata, c & ~0xC0);
1592         }
1593 }
1594
1595 static int
1596 vcode(int volt)
1597 {
1598         switch(volt){
1599         case 5:
1600                 return 1;
1601         case 12:
1602                 return 2;
1603         default:
1604                 return 0;
1605         }
1606 }