FreeBSD/Linux Kernel Cross Reference
sys/pc/devpccard.c
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
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
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
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
444 eventoccured(void)
445 {
446 return nevents > 0;
447 }
448
449 static 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
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
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
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
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
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
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
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
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
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*
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
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*
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
1240 pccardstat(Chan *c, uchar *db, int n)
1241 {
1242 return devstat(c, db, n, 0, 0, pccardgen);
1243 }
1244
1245 static void
1246 increfp(Cardbus *cb)
1247 {
1248 lock(&cb->refslock);
1249 cb->refs++;
1250 unlock(&cb->refslock);
1251 }
1252
1253 static void
1254 decrefp(Cardbus *cb)
1255 {
1256 lock(&cb->refslock);
1257 cb->refs--;
1258 unlock(&cb->refslock);
1259 }
1260
1261 static Chan*
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
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
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 buf[0] = 0;
1297 e = p + READSTR;
1298
1299 cb = &cbslots[SLOTNO(c)];
1300 lock(cb);
1301 p = seprint(p, e, "slot %ld: %s; ", cb - cbslots, states[cb->state]);
1302
1303 switch (cb->type) {
1304 case -1:
1305 seprint(p, e, "\n");
1306 break;
1307
1308 case PC32:
1309 if (cb->pci->bridge) {
1310 Pcidev *pci = cb->pci->bridge;
1311 int i;
1312
1313 while (pci) {
1314 p = seprint(p, e, "%.4uX %.4uX; irq %d\n",
1315 pci->vid, pci->did, pci->intl);
1316 for (i = 0; i != Nbars; i++)
1317 if (pci->mem[i].size)
1318 p = seprint(p, e,
1319 "\tmem[%d] %.8ulX (%.8uX)\n",
1320 i, pci->mem[i].bar,
1321 pci->mem[i].size);
1322 if (pci->rom.size)
1323 p = seprint(p, e, "\tROM %.8ulX (%.8uX)\n",
1324 pci->rom.bar, pci->rom.size);
1325 pci = pci->list;
1326 }
1327 }
1328 break;
1329
1330 case PC16:
1331 if (cb->state == SlotConfigured) {
1332 Pcminfo *pi = &cb->linfo;
1333
1334 p = seprint(p, e, "%s port %X; irq %d;\n",
1335 pi->verstr, pi->port,
1336 pi->irq);
1337 for (i = 0; i != pi->nctab; i++) {
1338 PCMconftab *ct;
1339 int j;
1340
1341 ct = &pi->ctab[i];
1342 p = seprint(p, e,
1343 "\tconfiguration[%d] irqs %.4uX; vpp %d, %d; %s\n",
1344 i, ct->irqs, ct->vpp1, ct->vpp2,
1345 (ct == pi->defctab)? "(default);": "");
1346 for (j = 0; j != ct->nio; j++)
1347 if (ct->io[j].len > 0)
1348 p = seprint(p, e, "\t\tio[%d] %.8ulX %uld\n",
1349 j, ct->io[j].start, ct->io[j].len);
1350 }
1351 }
1352 break;
1353 }
1354 unlock(cb);
1355
1356 n = readstr(offset, a, n, buf);
1357 free(buf);
1358 return n;
1359 }
1360 return 0;
1361 }
1362
1363 static long
1364 pccardwrite(Chan *c, void *v, long n, vlong)
1365 {
1366 Rune r;
1367 ulong n0;
1368 char *device;
1369 Cmdbuf *cbf;
1370 Cmdtab *ct;
1371 Cardbus *cb;
1372
1373 n0 = n;
1374 switch(TYPE(c)){
1375 case Qctl:
1376 cb = &cbslots[SLOTNO(c)];
1377
1378 cbf = parsecmd(v, n);
1379 if(waserror()){
1380 free(cbf);
1381 nexterror();
1382 }
1383 ct = lookupcmd(cbf, pccardctlmsg, nelem(pccardctlmsg));
1384 switch(ct->index){
1385 case CMdown:
1386 device = cbf->f[1];
1387 device += chartorune(&r, device);
1388 if ((n = devno(r, 1)) >= 0 && devtab[n]->config)
1389 devtab[n]->config(0, device, nil);
1390 qengine(cb, CardEjected);
1391 break;
1392 case CMpower:
1393 if ((cb->regs[SocketState] & SS_CCD) == 0)
1394 qengine(cb, CardDetected);
1395 break;
1396 }
1397 poperror();
1398 free(cbf);
1399 break;
1400 }
1401 return n0 - n;
1402 }
1403
1404 Dev pccarddevtab = {
1405 'Y',
1406 "cardbus",
1407
1408 devreset,
1409 devinit,
1410 devshutdown,
1411 pccardattach,
1412 pccardwalk,
1413 pccardstat,
1414 pccardopen,
1415 devcreate,
1416 pccardclose,
1417 pccardread,
1418 devbread,
1419 pccardwrite,
1420 devbwrite,
1421 devremove,
1422 devwstat,
1423 };
1424
1425 static PCMmap *
1426 isamap(Cardbus *cb, ulong offset, int len, int attr)
1427 {
1428 uchar we, bit;
1429 PCMmap *m, *nm;
1430 Pcminfo *pi;
1431 int i;
1432 ulong e;
1433
1434 pi = &cb->linfo;
1435
1436 /* convert offset to granularity */
1437 if(len <= 0)
1438 len = 1;
1439 e = ROUND(offset+len, Mgran);
1440 offset &= Mmask;
1441 len = e - offset;
1442
1443 /* look for a map that covers the right area */
1444 we = rdreg(cb, Rwe);
1445 bit = 1;
1446 nm = 0;
1447 for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
1448 if((we & bit))
1449 if(m->attr == attr)
1450 if(offset >= m->ca && e <= m->cea){
1451
1452 m->ref++;
1453 return m;
1454 }
1455 bit <<= 1;
1456 if(nm == 0 && m->ref == 0)
1457 nm = m;
1458 }
1459 m = nm;
1460 if(m == 0)
1461 return 0;
1462
1463 /* if isa space isn't big enough, free it and get more */
1464 if(m->len < len){
1465 if(m->isa){
1466 umbfree(m->isa, m->len);
1467 m->len = 0;
1468 }
1469 m->isa = PADDR(umbmalloc(0, len, Mgran));
1470 if(m->isa == 0){
1471 print("isamap: out of isa space\n");
1472 return 0;
1473 }
1474 m->len = len;
1475 }
1476
1477 /* set up new map */
1478 m->ca = offset;
1479 m->cea = m->ca + m->len;
1480 m->attr = attr;
1481 i = m - pi->mmap;
1482 bit = 1<<i;
1483 wrreg(cb, Rwe, we & ~bit); /* disable map before changing it */
1484 wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
1485 wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
1486 wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
1487 wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
1488 offset -= m->isa;
1489 offset &= (1<<25)-1;
1490 offset >>= Mshift;
1491 wrreg(cb, MAP(i, Mofflo), offset);
1492 wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
1493 wrreg(cb, Rwe, we | bit); /* enable map */
1494 m->ref = 1;
1495
1496 return m;
1497 }
1498
1499 static void
1500 isaunmap(PCMmap* m)
1501 {
1502 m->ref--;
1503 }
1504
1505 /*
1506 * reading and writing card registers
1507 */
1508 static uchar
1509 rdreg(Cardbus *cb, int index)
1510 {
1511 outb(cb->lindex, cb->lbase + index);
1512 return inb(cb->ldata);
1513 }
1514
1515 static void
1516 wrreg(Cardbus *cb, int index, uchar val)
1517 {
1518 outb(cb->lindex, cb->lbase + index);
1519 outb(cb->ldata, val);
1520 }
1521
1522 static int
1523 readc(Cisdat *cis, uchar *x)
1524 {
1525 if(cis->cispos >= cis->cislen)
1526 return 0;
1527 *x = cis->cisbase[cis->cisskip*cis->cispos];
1528 cis->cispos++;
1529 return 1;
1530 }
1531
1532 static ulong
1533 getlong(Cisdat *cis, int size)
1534 {
1535 uchar c;
1536 int i;
1537 ulong x;
1538
1539 x = 0;
1540 for(i = 0; i < size; i++){
1541 if(readc(cis, &c) != 1)
1542 break;
1543 x |= c<<(i*8);
1544 }
1545 return x;
1546 }
1547
1548 static void
1549 tcfig(Cardbus *cb, Cisdat *cis, int )
1550 {
1551 uchar size, rasize, rmsize;
1552 uchar last;
1553 Pcminfo *pi;
1554
1555 if(readc(cis, &size) != 1)
1556 return;
1557 rasize = (size&0x3) + 1;
1558 rmsize = ((size>>2)&0xf) + 1;
1559 if(readc(cis, &last) != 1)
1560 return;
1561
1562 pi = &cb->linfo;
1563 pi->conf_addr = getlong(cis, rasize);
1564 pi->conf_present = getlong(cis, rmsize);
1565 }
1566
1567 static void
1568 tvers1(Cardbus *cb, Cisdat *cis, int )
1569 {
1570 uchar c, major, minor, last;
1571 int i;
1572 Pcminfo *pi;
1573
1574 pi = &cb->linfo;
1575 if(readc(cis, &major) != 1)
1576 return;
1577 if(readc(cis, &minor) != 1)
1578 return;
1579 last = 0;
1580 for(i = 0; i < sizeof(pi->verstr) - 1; i++){
1581 if(readc(cis, &c) != 1)
1582 return;
1583 if(c == 0)
1584 c = ';';
1585 if(c == '\n')
1586 c = ';';
1587 if(c == 0xff)
1588 break;
1589 if(c == ';' && last == ';')
1590 continue;
1591 pi->verstr[i] = c;
1592 last = c;
1593 }
1594 pi->verstr[i] = 0;
1595 }
1596
1597 static ulong
1598 microvolt(Cisdat *cis)
1599 {
1600 uchar c;
1601 ulong microvolts;
1602 ulong exp;
1603
1604 if(readc(cis, &c) != 1)
1605 return 0;
1606 exp = exponent[c&0x7];
1607 microvolts = vmant[(c>>3)&0xf]*exp;
1608 while(c & 0x80){
1609 if(readc(cis, &c) != 1)
1610 return 0;
1611 switch(c){
1612 case 0x7d:
1613 break; /* high impedence when sleeping */
1614 case 0x7e:
1615 case 0x7f:
1616 microvolts = 0; /* no connection */
1617 break;
1618 default:
1619 exp /= 10;
1620 microvolts += exp*(c&0x7f);
1621 }
1622 }
1623 return microvolts;
1624 }
1625
1626 static ulong
1627 nanoamps(Cisdat *cis)
1628 {
1629 uchar c;
1630 ulong nanoamps;
1631
1632 if(readc(cis, &c) != 1)
1633 return 0;
1634 nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
1635 while(c & 0x80){
1636 if(readc(cis, &c) != 1)
1637 return 0;
1638 if(c == 0x7d || c == 0x7e || c == 0x7f)
1639 nanoamps = 0;
1640 }
1641 return nanoamps;
1642 }
1643
1644 /*
1645 * only nominal voltage (feature 1) is important for config,
1646 * other features must read card to stay in sync.
1647 */
1648 static ulong
1649 power(Cisdat *cis)
1650 {
1651 uchar feature;
1652 ulong mv;
1653
1654 mv = 0;
1655 if(readc(cis, &feature) != 1)
1656 return 0;
1657 if(feature & 1)
1658 mv = microvolt(cis);
1659 if(feature & 2)
1660 microvolt(cis);
1661 if(feature & 4)
1662 microvolt(cis);
1663 if(feature & 8)
1664 nanoamps(cis);
1665 if(feature & 0x10)
1666 nanoamps(cis);
1667 if(feature & 0x20)
1668 nanoamps(cis);
1669 if(feature & 0x40)
1670 nanoamps(cis);
1671 return mv/1000000;
1672 }
1673
1674 static ulong
1675 ttiming(Cisdat *cis, int scale)
1676 {
1677 uchar unscaled;
1678 ulong nanosecs;
1679
1680 if(readc(cis, &unscaled) != 1)
1681 return 0;
1682 nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
1683 nanosecs = nanosecs * exponent[scale];
1684 return nanosecs;
1685 }
1686
1687 static void
1688 timing(Cisdat *cis, PCMconftab *ct)
1689 {
1690 uchar c, i;
1691
1692 if(readc(cis, &c) != 1)
1693 return;
1694 i = c&0x3;
1695 if(i != 3)
1696 ct->maxwait = ttiming(cis, i); /* max wait */
1697 i = (c>>2)&0x7;
1698 if(i != 7)
1699 ct->readywait = ttiming(cis, i); /* max ready/busy wait */
1700 i = (c>>5)&0x7;
1701 if(i != 7)
1702 ct->otherwait = ttiming(cis, i); /* reserved wait */
1703 }
1704
1705 static void
1706 iospaces(Cisdat *cis, PCMconftab *ct)
1707 {
1708 uchar c;
1709 int i, nio;
1710
1711 ct->nio = 0;
1712 if(readc(cis, &c) != 1)
1713 return;
1714
1715 ct->bit16 = ((c>>5)&3) >= 2;
1716 if(!(c & 0x80)){
1717 ct->io[0].start = 0;
1718 ct->io[0].len = 1<<(c&0x1f);
1719 ct->nio = 1;
1720 return;
1721 }
1722
1723 if(readc(cis, &c) != 1)
1724 return;
1725
1726 /*
1727 * For each of the range descriptions read the
1728 * start address and the length (value is length-1).
1729 */
1730 nio = (c&0xf)+1;
1731 for(i = 0; i < nio; i++){
1732 ct->io[i].start = getlong(cis, (c>>4)&0x3);
1733 ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
1734 }
1735 ct->nio = nio;
1736 }
1737
1738 static void
1739 irq(Cisdat *cis, PCMconftab *ct)
1740 {
1741 uchar c;
1742
1743 if(readc(cis, &c) != 1)
1744 return;
1745 ct->irqtype = c & 0xe0;
1746 if(c & 0x10)
1747 ct->irqs = getlong(cis, 2);
1748 else
1749 ct->irqs = 1<<(c&0xf);
1750 ct->irqs &= 0xDEB8; /* levels available to card */
1751 }
1752
1753 static void
1754 memspace(Cisdat *cis, int asize, int lsize, int host)
1755 {
1756 ulong haddress, address, len;
1757
1758 len = getlong(cis, lsize)*256;
1759 address = getlong(cis, asize)*256;
1760 USED(len, address);
1761 if(host){
1762 haddress = getlong(cis, asize)*256;
1763 USED(haddress);
1764 }
1765 }
1766
1767 static void
1768 tentry(Cardbus *cb, Cisdat *cis, int )
1769 {
1770 uchar c, i, feature;
1771 PCMconftab *ct;
1772 Pcminfo *pi;
1773
1774 pi = &cb->linfo;
1775 if(pi->nctab >= nelem(pi->ctab))
1776 return;
1777 if(readc(cis, &c) != 1)
1778 return;
1779 ct = &pi->ctab[pi->nctab++];
1780
1781 /* copy from last default config */
1782 if(pi->defctab)
1783 *ct = *pi->defctab;
1784
1785 ct->index = c & 0x3f;
1786
1787 /* is this the new default? */
1788 if(c & 0x40)
1789 pi->defctab = ct;
1790
1791 /* memory wait specified? */
1792 if(c & 0x80){
1793 if(readc(cis, &i) != 1)
1794 return;
1795 if(i&0x80)
1796 ct->memwait = 1;
1797 }
1798
1799 if(readc(cis, &feature) != 1)
1800 return;
1801 switch(feature&0x3){
1802 case 1:
1803 ct->vpp1 = ct->vpp2 = power(cis);
1804 break;
1805 case 2:
1806 power(cis);
1807 ct->vpp1 = ct->vpp2 = power(cis);
1808 break;
1809 case 3:
1810 power(cis);
1811 ct->vpp1 = power(cis);
1812 ct->vpp2 = power(cis);
1813 break;
1814 default:
1815 break;
1816 }
1817 if(feature&0x4)
1818 timing(cis, ct);
1819 if(feature&0x8)
1820 iospaces(cis, ct);
1821 if(feature&0x10)
1822 irq(cis, ct);
1823 switch((feature>>5)&0x3){
1824 case 1:
1825 memspace(cis, 0, 2, 0);
1826 break;
1827 case 2:
1828 memspace(cis, 2, 2, 0);
1829 break;
1830 case 3:
1831 if(readc(cis, &c) != 1)
1832 return;
1833 for(i = 0; i <= (c&0x7); i++)
1834 memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
1835 break;
1836 }
1837 }
1838
1839 static void
1840 i82365probe(Cardbus *cb, int lindex, int ldata)
1841 {
1842 uchar c, id;
1843 int dev = 0; /* According to the Ricoh spec 00->3F _and_ 80->BF seem
1844 to be the same socket A (ditto for B). */
1845
1846 outb(lindex, Rid + (dev<<7));
1847 id = inb(ldata);
1848 if((id & 0xf0) != 0x80)
1849 return; /* not a memory & I/O card */
1850 if((id & 0x0f) == 0x00)
1851 return; /* no revision number, not possible */
1852
1853 cb->lindex = lindex;
1854 cb->ldata = ldata;
1855 cb->ltype = Ti82365;
1856 cb->lbase = (int)(cb - cbslots) * 0x40;
1857
1858 switch(id){
1859 case 0x82:
1860 case 0x83:
1861 case 0x84:
1862 /* could be a cirrus */
1863 outb(cb->lindex, Rchipinfo + (dev<<7));
1864 outb(cb->ldata, 0);
1865 c = inb(cb->ldata);
1866 if((c & 0xc0) != 0xc0)
1867 break;
1868 c = inb(cb->ldata);
1869 if((c & 0xc0) != 0x00)
1870 break;
1871 if(c & 0x20){
1872 cb->ltype = Tpd6720;
1873 } else {
1874 cb->ltype = Tpd6710;
1875 }
1876
1877 /* low power mode */
1878 outb(cb->lindex, Rmisc2 + (dev<<7));
1879 c = inb(cb->ldata);
1880 outb(cb->ldata, c & ~Flowpow);
1881 break;
1882 break;
1883 }
1884
1885 /* if it's not a Cirrus, it could be a Vadem... */
1886 if(cb->ltype == Ti82365){
1887 /* unlock the Vadem extended regs */
1888 outb(cb->lindex, 0x0E + (dev<<7));
1889 outb(cb->lindex, 0x37 + (dev<<7));
1890
1891 /* make the id register show the Vadem id */
1892 outb(cb->lindex, 0x3A + (dev<<7));
1893 c = inb(cb->ldata);
1894 outb(cb->ldata, c|0xC0);
1895 outb(cb->lindex, Rid + (dev<<7));
1896 c = inb(cb->ldata);
1897 if(c & 0x08)
1898 cb->ltype = Tvg46x;
1899
1900 /* go back to Intel compatible id */
1901 outb(cb->lindex, 0x3A + (dev<<7));
1902 c = inb(cb->ldata);
1903 outb(cb->ldata, c & ~0xC0);
1904 }
1905 }
1906
1907 static int
1908 vcode(int volt)
1909 {
1910 switch(volt){
1911 case 5:
1912 return 1;
1913 case 12:
1914 return 2;
1915 default:
1916 return 0;
1917 }
1918 }
Cache object: 10d0bb69a78ec3dcbca2de157d8867d7
|