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