2 #include "../port/lib.h"
6 #include "../port/error.h"
10 * Intel 82365SL PCIC controller and compatibles.
17 Rid= 0x0, /* identification and revision */
18 Ris= 0x1, /* interface status */
19 Rpc= 0x2, /* power control */
20 Foutena= (1<<7), /* output enable */
21 Fautopower= (1<<5), /* automatic power switching */
22 Fcardena= (1<<4), /* PC card enable */
23 Rigc= 0x3, /* interrupt and general control */
24 Fiocard= (1<<5), /* I/O card (vs memory) */
25 Fnotreset= (1<<6), /* reset if not set */
26 FSMIena= (1<<4), /* enable change interrupt on SMI */
27 Rcsc= 0x4, /* card status change */
28 Rcscic= 0x5, /* card status change interrupt config */
29 Fchangeena= (1<<3), /* card changed */
30 Fbwarnena= (1<<1), /* card battery warning */
31 Fbdeadena= (1<<0), /* card battery dead */
32 Rwe= 0x6, /* address window enable */
33 Fmem16= (1<<5), /* use A23-A12 to decode address */
34 Rio= 0x7, /* I/O control */
35 Fwidth16= (1<<0), /* 16 bit data width */
36 Fiocs16= (1<<1), /* IOCS16 determines data width */
37 Fzerows= (1<<2), /* zero wait state */
38 Ftiming= (1<<3), /* timing register to use */
39 Riobtm0lo= 0x8, /* I/O address 0 start low byte */
40 Riobtm0hi= 0x9, /* I/O address 0 start high byte */
41 Riotop0lo= 0xa, /* I/O address 0 stop low byte */
42 Riotop0hi= 0xb, /* I/O address 0 stop high byte */
43 Riobtm1lo= 0xc, /* I/O address 1 start low byte */
44 Riobtm1hi= 0xd, /* I/O address 1 start high byte */
45 Riotop1lo= 0xe, /* I/O address 1 stop low byte */
46 Riotop1hi= 0xf, /* I/O address 1 stop high byte */
47 Rmap= 0x10, /* map 0 */
50 * CL-PD67xx extension registers
52 Rmisc1= 0x16, /* misc control 1 */
59 Rfifo= 0x17, /* fifo control */
60 Fflush= (1<<7), /* flush fifo */
61 Rmisc2= 0x1E, /* misc control 2 */
62 Flowpow= (1<<1), /* low power mode */
63 Rchipinfo= 0x1F, /* chip information */
64 Ratactl= 0x26, /* ATA control */
67 * offsets into the system memory address maps
69 Mbtmlo= 0x0, /* System mem addr mapping start low byte */
70 Mbtmhi= 0x1, /* System mem addr mapping start high byte */
71 F16bit= (1<<7), /* 16-bit wide data path */
72 Mtoplo= 0x2, /* System mem addr mapping stop low byte */
73 Mtophi= 0x3, /* System mem addr mapping stop high byte */
74 Ftimer1= (1<<6), /* timer set 1 */
75 Mofflo= 0x4, /* Card memory offset address low byte */
76 Moffhi= 0x5, /* Card memory offset address high byte */
77 Fregactive= (1<<6), /* attribute memory */
80 * configuration registers - they start at an offset in attribute
81 * memory found in the CIS.
84 Creset= (1<<7), /* reset device */
85 Clevel= (1<<6), /* level sensitive interrupt line */
86 Cirq= (1<<2), /* IRQ enable */
87 Cdecode= (1<<1), /* address decode */
88 Cfunc= (1<<0), /* function enable */
94 #define MAP(x,o) (Rmap + (x)*0x8 + o)
96 typedef struct I82365 I82365;
111 int xreg; /* index register address */
112 int dreg; /* data register address */
115 static I82365 *controller[4];
116 static int ncontroller;
117 static PCMslot *slot;
118 static PCMslot *lastslot;
121 static void i82365intr(Ureg*, void*);
122 static int pcmio(int, ISAConf*);
123 static long pcmread(int, int, void*, long, vlong);
124 static long pcmwrite(int, int, void*, long, vlong);
126 static void i82365dump(PCMslot*);
129 * reading and writing card registers
132 rdreg(PCMslot *pp, int index)
134 outb(((I82365*)pp->cp)->xreg, pp->base + index);
135 return inb(((I82365*)pp->cp)->dreg);
138 wrreg(PCMslot *pp, int index, uchar val)
140 outb(((I82365*)pp->cp)->xreg, pp->base + index);
141 outb(((I82365*)pp->cp)->dreg, val);
145 * get info about card
148 slotinfo(PCMslot *pp)
152 isr = rdreg(pp, Ris);
153 pp->occupied = (isr & (3<<2)) == (3<<2);
154 pp->powered = isr & (1<<6);
155 pp->battery = (isr & 3) == 3;
156 pp->wrprot = isr & (1<<4);
157 pp->busy = isr & (1<<5);
158 pp->msec = TK2MS(MACHP(0)->ticks);
175 * enable the slot card
183 /* power up and unreset, wait's are empirical (???) */
184 wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
188 wrreg(pp, Rigc, Fnotreset);
191 /* get configuration */
197 wrreg(pp, Rpc, Fautopower);
201 * disable the slot card
206 wrreg(pp, Rpc, 0); /* turn off card power */
207 wrreg(pp, Rwe, 0); /* no windows */
212 * status change interrupt
215 i82365intr(Ureg *, void *)
223 for(pp = slot; pp < lastslot; pp++){
224 csc = rdreg(pp, Rcsc);
227 if(csc & (1<<3) && was != pp->occupied){
237 Mgran= (1<<Mshift), /* granularity of maps */
238 Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
242 * get a map for pc card region, return corrected len
245 pcmmap(int slotno, ulong offset, int len, int attr)
256 /* convert offset to granularity */
259 e = ROUND(offset+len, Mgran);
263 /* look for a map that covers the right area */
267 for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
270 if(offset >= m->ca && e <= m->cea){
277 if(nm == 0 && m->ref == 0)
286 /* if isa space isn't big enough, free it and get more */
289 umbfree(m->isa, m->len);
292 m->isa = PADDR(umbmalloc(0, len, Mgran));
294 print("pcmmap: out of isa space\n");
303 m->cea = m->ca + m->len;
307 wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
308 wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
309 wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
310 wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
311 wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
315 wrreg(pp, MAP(i, Mofflo), offset);
316 wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
317 wrreg(pp, Rwe, we | bit); /* enable map */
325 pcmunmap(int slotno, PCMmap* m)
354 * look for a card whose version contains 'idstr'
357 pcmcia_pcmspecial(char *idstr, ISAConf *isa)
360 extern char *strstr(char*, char*);
363 for(pp = slot; pp < lastslot; pp++){
365 continue; /* already taken */
368 * make sure we don't power on cards when we already know what's
369 * in them. We'll reread every two minutes if necessary
372 if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000){
378 if(strstr(pp->verstr, idstr)){
383 if(isa == 0 || pcmio(pp->slotno, isa) == 0){
397 pcmcia_pcmspecialclose(int slotno)
402 panic("pcmspecialclose");
418 #define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff))
419 #define TYPE(c) ((ulong)(c->qid.path&0xff))
420 #define QID(s,t) (((s)<<8)|(t))
423 pcmgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
431 mkqid(&qid, Qdir, 0, QTDIR);
432 devdir(c, qid, "#y", 0, eve, 0555, dp);
443 qid.path = QID(slotno, Qmem);
444 snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
448 qid.path = QID(slotno, Qattr);
449 snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
453 qid.path = QID(slotno, Qctl);
454 snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
459 devdir(c, qid, up->genbuf, len, eve, 0660, dp);
463 static char *chipname[] =
465 [Ti82365] "Intel 82365SL",
466 [Tpd6710] "Cirrus Logic CL-PD6710",
467 [Tpd6720] "Cirrus Logic CL-PD6720",
468 [Tvg46x] "Vadem VG-46x",
472 i82365probe(int x, int d, int dev)
479 outb(x, Rid + (dev<<7));
481 if((id & 0xf0) != 0x80)
482 return 0; /* not a memory & I/O card */
483 if((id & 0x0f) == 0x00)
484 return 0; /* no revision number, not possible */
486 cp = xalloc(sizeof(I82365));
488 print("i82365probe: out of memory\n");
501 /* could be a cirrus */
502 outb(x, Rchipinfo + (dev<<7));
505 if((c & 0xc0) != 0xc0)
508 if((c & 0xc0) != 0x00)
518 outb(x, Rmisc2 + (dev<<7));
520 outb(d, c & ~Flowpow);
524 /* if it's not a Cirrus, it could be a Vadem... */
525 if(cp->type == Ti82365){
526 /* unlock the Vadem extended regs */
527 outb(x, 0x0E + (dev<<7));
528 outb(x, 0x37 + (dev<<7));
530 /* make the id register show the Vadem id */
531 outb(x, 0x3A + (dev<<7));
534 outb(x, Rid + (dev<<7));
539 /* go back to Intel compatible id */
540 outb(x, 0x3A + (dev<<7));
545 memset(&isa, 0, sizeof(ISAConf));
546 if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
551 for(i = 0; i < isa.nopt; i++){
552 if(cistrncmp(isa.opt[i], "nslot=", 6))
554 nslot = strtol(&isa.opt[i][6], nil, 0);
555 if(nslot > 0 && nslot <= 2)
559 controller[ncontroller++] = cp;
564 i82365dump(PCMslot *pp)
568 for(i = 0; i < 0x40; i++){
570 print("\n%2.2uX: ", i);
571 print("%2.2uX ", rdreg(pp, i));
572 if(((i+1) & 0x0F) == 0x08)
579 * set up for slot cards
594 if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
600 /* look for controllers if the ports aren't already taken */
601 if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){
602 i82365probe(0x3E0, 0x3E1, 0);
603 i82365probe(0x3E0, 0x3E1, 1);
607 if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){
609 i82365probe(0x3E2, 0x3E3, 0);
610 i82365probe(0x3E2, 0x3E3, 1);
618 for(i = 0; i < ncontroller; i++)
619 nslot += controller[i]->nslot;
620 slot = xalloc(nslot * sizeof(PCMslot));
622 print("i82365link: out of memory\n");
627 _pcmspecial = pcmcia_pcmspecial;
628 _pcmspecialclose = pcmcia_pcmspecialclose;
631 for(i = 0; i < ncontroller; i++){
633 print("#y%d: %d slot %s: port 0x%uX irq %d\n",
634 i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
635 for(j = 0; j < cp->nslot; j++){
637 pp->slotno = pp - slot;
639 pp->base = (cp->dev<<7) | (j<<6);
645 /* interrupt on status change */
646 wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
650 /* for card management interrupts */
651 snprint(buf, sizeof buf, "i82365.%d", i);
652 intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf);
657 i82365attach(char *spec)
659 return devattach('y', spec);
663 i82365walk(Chan *c, Chan *nc, char **name, int nname)
665 return devwalk(c, nc, name, nname, 0, 0, pcmgen);
669 i82365stat(Chan *c, uchar *db, int n)
671 return devstat(c, db, n, 0, 0, pcmgen);
675 i82365open(Chan *c, int omode)
677 if(c->qid.type & QTDIR){
681 increfp(slot + SLOTNO(c));
682 c->mode = openmode(omode);
692 if((c->qid.type & QTDIR) == 0)
693 decrefp(slot+SLOTNO(c));
696 /* a memmove using only bytes */
698 memmoveb(uchar *to, uchar *from, int n)
704 /* a memmove using only shorts & bytes */
706 memmoves(uchar *to, uchar *from, int n)
710 if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
723 pcmread(int slotno, int attr, void *a, long n, vlong off)
732 if(pp->memlen < offset)
734 if(pp->memlen < offset + n)
735 n = pp->memlen - offset;
740 pcmunmap(pp->slotno, m);
745 for(len = n; len > 0; len -= i){
746 m = pcmmap(pp->slotno, offset, 0, attr);
748 error("cannot map PCMCIA card");
749 if(offset + len > m->cea)
753 memmoveb(ac, KADDR(m->isa + offset - m->ca), i);
754 pcmunmap(pp->slotno, m);
764 i82365read(Chan *c, void *a, long n, vlong off)
772 return devdirread(c, a, n, 0, 0, pcmgen);
775 return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off);
777 buf = p = smalloc(READSTR);
779 pp = slot + SLOTNO(c);
783 p = seprint(p, e, "occupied\n");
785 p = seprint(p, e, "version %s\n", pp->verstr);
788 p = seprint(p, e, "enabled\n");
790 p = seprint(p, e, "powered\n");
792 p = seprint(p, e, "configed\n");
794 p = seprint(p, e, "write protected\n");
796 p = seprint(p, e, "busy\n");
797 seprint(p, e, "battery lvl %d\n", pp->battery);
799 n = readstr(offset, a, n, buf);
805 return -1; /* not reached */
809 pcmwrite(int dev, int attr, void *a, long n, vlong off)
818 if(pp->memlen < offset)
820 if(pp->memlen < offset + n)
821 n = pp->memlen - offset;
826 pcmunmap(pp->slotno, m);
831 for(len = n; len > 0; len -= i){
832 m = pcmmap(pp->slotno, offset, 0, attr);
834 error("cannot map PCMCIA card");
835 if(offset + len > m->cea)
839 memmoveb(KADDR(m->isa + offset - m->ca), ac, i);
840 pcmunmap(pp->slotno, m);
850 i82365write(Chan *c, void *a, long n, vlong off)
861 pp = slot + SLOTNO(c);
865 /* set vpp on card */
866 if(strncmp(buf, "vpp", 3) == 0)
867 wrreg(pp, Rpc, vcode(strtol(buf+3, 0, 0))|Fautopower|Foutena|Fcardena);
871 pp = slot + SLOTNO(c);
872 if(pp->occupied == 0 || pp->enabled == 0)
874 n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off);
880 return -1; /* not reached */
905 * configure the PCMslot for IO. We assume very heavily that we can read
906 * configuration info from the CIS. If not, we won't set up correctly.
909 pcmio(int slotno, ISAConf *isa)
913 PCMconftab *ct, *et, *t;
929 et = &pp->ctab[pp->nctab];
932 for(i = 0; i < isa->nopt; i++){
933 if(strncmp(isa->opt[i], "index=", 6))
935 index = strtol(&isa->opt[i][6], &cp, 0);
936 if(cp == &isa->opt[i][6] || index >= pp->nctab)
938 ct = &pp->ctab[index];
942 /* assume default is right */
948 /* try for best match */
950 || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
951 for(t = pp->ctab; t < et; t++)
953 && t->io[0].start == isa->port
954 && ((1<<irq) & t->irqs)){
959 if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
960 for(t = pp->ctab; t < et; t++)
961 if(t->nio && ((1<<irq) & t->irqs)){
967 for(t = pp->ctab; t < et; t++)
975 if(ct == et || ct->nio == 0)
977 if(isa->port == 0 && ct->io[0].start == 0)
980 /* route interrupts */
982 wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
984 /* set power and enable device */
986 wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
988 /* 16-bit data path */
990 x = Ftiming|Fiocs16|Fwidth16;
993 if(ct->nio == 2 && ct->io[1].start)
998 * enable io port map 0
999 * the 'top' register value includes the last valid address
1002 isa->port = ct->io[0].start;
1003 we = rdreg(pp, Rwe);
1004 wrreg(pp, Riobtm0lo, isa->port);
1005 wrreg(pp, Riobtm0hi, isa->port>>8);
1006 i = isa->port+ct->io[0].len-1;
1007 wrreg(pp, Riotop0lo, i);
1008 wrreg(pp, Riotop0hi, i>>8);
1010 if(ct->nio >= 2 && ct->io[1].start){
1011 wrreg(pp, Riobtm1lo, ct->io[1].start);
1012 wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
1013 i = ct->io[1].start+ct->io[1].len-1;
1014 wrreg(pp, Riotop1lo, i);
1015 wrreg(pp, Riotop1hi, i>>8);
1020 /* only touch Rconfig if it is present */
1021 m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
1022 p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
1023 if(pp->cfg[0].cpresent & (1<<Rconfig)){
1026 /* set configuration and interrupt type.
1027 * if level is possible on the card, use it.
1030 if(ct->irqtype & 0x20)
1033 /* enable the device, enable address decode and
1036 x |= Cfunc|Cdecode|Cirq;
1043 if(pp->cfg[0].cpresent & (1<<Riobase0)){
1044 /* set up the iobase 0 */
1045 p[Riobase0 << 1] = isa->port;
1046 p[Riobase1 << 1] = isa->port >> 8;
1049 if(pp->cfg[0].cpresent & (1<<Riosize))
1050 p[Riosize << 1] = ct->io[0].len;
1051 pcmunmap(slotno, m);