|
@@ -7,15 +7,7 @@
|
|
|
#include "io.h"
|
|
|
|
|
|
/*
|
|
|
- * Support for up to 4 Slot card slots. Generalizing above that is hard
|
|
|
- * since addressing is not obvious. - presotto
|
|
|
- *
|
|
|
- * WARNING: This has never been tried with more than one card slot.
|
|
|
- */
|
|
|
-
|
|
|
-/*
|
|
|
- * Intel 82365SL PCIC controller for the PCMCIA or
|
|
|
- * Cirrus Logic PD6710/PD6720 which is mostly register compatible
|
|
|
+ * Intel 82365SL PCIC controller and compatibles.
|
|
|
*/
|
|
|
enum
|
|
|
{
|
|
@@ -84,10 +76,6 @@ enum
|
|
|
Moffhi= 0x5, /* Card memory offset address high byte */
|
|
|
Fregactive= (1<<6), /* attribute memory */
|
|
|
|
|
|
- Mbits= 13, /* msb of Mchunk */
|
|
|
- Mchunk= 1<<Mbits, /* logical mapping granularity */
|
|
|
- Nmap= 4, /* max number of maps to use */
|
|
|
-
|
|
|
/*
|
|
|
* configuration registers - they start at an offset in attribute
|
|
|
* memory found in the CIS.
|
|
@@ -95,8 +83,12 @@ enum
|
|
|
Rconfig= 0,
|
|
|
Creset= (1<<7), /* reset device */
|
|
|
Clevel= (1<<6), /* level sensitive interrupt line */
|
|
|
-
|
|
|
- Maxctab= 8, /* maximum configuration table entries */
|
|
|
+ Cirq= (1<<2), /* IRQ enable */
|
|
|
+ Cdecode= (1<<1), /* address decode */
|
|
|
+ Cfunc= (1<<0), /* function enable */
|
|
|
+ Riobase0= 5,
|
|
|
+ Riobase1= 6,
|
|
|
+ Riosize= 9,
|
|
|
};
|
|
|
|
|
|
static int pcmcia_pcmspecial(char *, ISAConf *);
|
|
@@ -105,9 +97,7 @@ static void pcmcia_pcmspecialclose(int);
|
|
|
#define MAP(x,o) (Rmap + (x)*0x8 + o)
|
|
|
|
|
|
typedef struct I82365 I82365;
|
|
|
-typedef struct Slot Slot;
|
|
|
-typedef struct Conftab Conftab;
|
|
|
-typedef struct Cisdat Cisdat;
|
|
|
+
|
|
|
/* a controller */
|
|
|
enum
|
|
|
{
|
|
@@ -127,96 +117,29 @@ struct I82365
|
|
|
};
|
|
|
static I82365 *controller[4];
|
|
|
static int ncontroller;
|
|
|
-
|
|
|
-/* configuration table entry */
|
|
|
-struct Conftab
|
|
|
-{
|
|
|
- int index;
|
|
|
- ushort irqs; /* legal irqs */
|
|
|
- uchar irqtype;
|
|
|
- uchar bit16; /* true for 16 bit access */
|
|
|
- struct {
|
|
|
- ulong start;
|
|
|
- ulong len;
|
|
|
- } io[16];
|
|
|
- int nio;
|
|
|
- uchar vpp1;
|
|
|
- uchar vpp2;
|
|
|
- uchar memwait;
|
|
|
- ulong maxwait;
|
|
|
- ulong readywait;
|
|
|
- ulong otherwait;
|
|
|
-};
|
|
|
-
|
|
|
-/* cis memory walking */
|
|
|
-struct Cisdat
|
|
|
-{
|
|
|
- uchar *cisbase;
|
|
|
- int cispos;
|
|
|
- int cisskip;
|
|
|
- int cislen;
|
|
|
-};
|
|
|
-
|
|
|
-/* a card slot */
|
|
|
-struct Slot
|
|
|
-{
|
|
|
- Lock;
|
|
|
- int ref;
|
|
|
-
|
|
|
- I82365 *cp; /* controller for this slot */
|
|
|
- long memlen; /* memory length */
|
|
|
- uchar base; /* index register base */
|
|
|
- uchar slotno; /* slot number */
|
|
|
-
|
|
|
- /* status */
|
|
|
- uchar special; /* in use for a special device */
|
|
|
- uchar already; /* already inited */
|
|
|
- uchar occupied;
|
|
|
- uchar battery;
|
|
|
- uchar wrprot;
|
|
|
- uchar powered;
|
|
|
- uchar configed;
|
|
|
- uchar enabled;
|
|
|
- uchar busy;
|
|
|
-
|
|
|
- /* cis info */
|
|
|
- char verstr[512]; /* version string */
|
|
|
- uchar cpresent; /* config registers present */
|
|
|
- ulong caddr; /* relative address of config registers */
|
|
|
- int nctab; /* number of config table entries */
|
|
|
- Conftab ctab[Maxctab];
|
|
|
- Conftab *def; /* default conftab */
|
|
|
-
|
|
|
- /* for walking through cis */
|
|
|
- Cisdat;
|
|
|
-
|
|
|
- /* memory maps */
|
|
|
- Lock mlock; /* lock down the maps */
|
|
|
- int time;
|
|
|
- PCMmap mmap[Nmap]; /* maps, last is always for the kernel */
|
|
|
-};
|
|
|
-static Slot *slot;
|
|
|
-static Slot *lastslot;
|
|
|
+static PCMslot *slot;
|
|
|
+static PCMslot *lastslot;
|
|
|
static nslot;
|
|
|
|
|
|
-static void cisread(Slot*);
|
|
|
static void i82365intr(Ureg*, void*);
|
|
|
static void i82365reset(void);
|
|
|
static int pcmio(int, ISAConf*);
|
|
|
-static long pcmread(int, int, void*, long, vlong);
|
|
|
-static long pcmwrite(int, int, void*, long, vlong);
|
|
|
|
|
|
-static void i82365dump(Slot*);
|
|
|
+static void i82365dump(PCMslot*);
|
|
|
|
|
|
void
|
|
|
devi82365link(void)
|
|
|
{
|
|
|
static int already;
|
|
|
+ char *p;
|
|
|
|
|
|
if(already)
|
|
|
return;
|
|
|
already = 1;
|
|
|
|
|
|
+ if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
|
|
|
+ return;
|
|
|
+
|
|
|
if (_pcmspecial)
|
|
|
return;
|
|
|
|
|
@@ -228,23 +151,23 @@ devi82365link(void)
|
|
|
* reading and writing card registers
|
|
|
*/
|
|
|
static uchar
|
|
|
-rdreg(Slot *pp, int index)
|
|
|
+rdreg(PCMslot *pp, int index)
|
|
|
{
|
|
|
- outb(pp->cp->xreg, pp->base + index);
|
|
|
- return inb(pp->cp->dreg);
|
|
|
+ outb(((I82365*)pp->cp)->xreg, pp->base + index);
|
|
|
+ return inb(((I82365*)pp->cp)->dreg);
|
|
|
}
|
|
|
static void
|
|
|
-wrreg(Slot *pp, int index, uchar val)
|
|
|
+wrreg(PCMslot *pp, int index, uchar val)
|
|
|
{
|
|
|
- outb(pp->cp->xreg, pp->base + index);
|
|
|
- outb(pp->cp->dreg, val);
|
|
|
+ outb(((I82365*)pp->cp)->xreg, pp->base + index);
|
|
|
+ outb(((I82365*)pp->cp)->dreg, val);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* get info about card
|
|
|
*/
|
|
|
static void
|
|
|
-slotinfo(Slot *pp)
|
|
|
+slotinfo(PCMslot *pp)
|
|
|
{
|
|
|
uchar isr;
|
|
|
|
|
@@ -254,6 +177,7 @@ slotinfo(Slot *pp)
|
|
|
pp->battery = (isr & 3) == 3;
|
|
|
pp->wrprot = isr & (1<<4);
|
|
|
pp->busy = isr & (1<<5);
|
|
|
+ //pp->msec = TK2MS(MACHP(0)->ticks);
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -273,7 +197,7 @@ vcode(int volt)
|
|
|
* enable the slot card
|
|
|
*/
|
|
|
static void
|
|
|
-slotena(Slot *pp)
|
|
|
+slotena(PCMslot *pp)
|
|
|
{
|
|
|
if(pp->enabled)
|
|
|
return;
|
|
@@ -289,7 +213,7 @@ slotena(Slot *pp)
|
|
|
/* get configuration */
|
|
|
slotinfo(pp);
|
|
|
if(pp->occupied){
|
|
|
- cisread(pp);
|
|
|
+ pcmcisread(pp);
|
|
|
pp->enabled = 1;
|
|
|
} else
|
|
|
wrreg(pp, Rpc, Fautopower);
|
|
@@ -299,7 +223,7 @@ slotena(Slot *pp)
|
|
|
* disable the slot card
|
|
|
*/
|
|
|
static void
|
|
|
-slotdis(Slot *pp)
|
|
|
+slotdis(PCMslot *pp)
|
|
|
{
|
|
|
wrreg(pp, Rpc, 0); /* turn off card power */
|
|
|
wrreg(pp, Rwe, 0); /* no windows */
|
|
@@ -313,7 +237,7 @@ static void
|
|
|
i82365intr(Ureg *, void *)
|
|
|
{
|
|
|
uchar csc, was;
|
|
|
- Slot *pp;
|
|
|
+ PCMslot *pp;
|
|
|
|
|
|
if(slot == 0)
|
|
|
return;
|
|
@@ -342,7 +266,7 @@ enum
|
|
|
PCMmap*
|
|
|
pcmmap(int slotno, ulong offset, int len, int attr)
|
|
|
{
|
|
|
- Slot *pp;
|
|
|
+ PCMslot *pp;
|
|
|
uchar we, bit;
|
|
|
PCMmap *m, *nm;
|
|
|
int i;
|
|
@@ -362,7 +286,7 @@ pcmmap(int slotno, ulong offset, int len, int attr)
|
|
|
we = rdreg(pp, Rwe);
|
|
|
bit = 1;
|
|
|
nm = 0;
|
|
|
- for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){
|
|
|
+ for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
|
|
|
if((we & bit))
|
|
|
if(m->attr == attr)
|
|
|
if(offset >= m->ca && e <= m->cea){
|
|
@@ -422,7 +346,7 @@ pcmmap(int slotno, ulong offset, int len, int attr)
|
|
|
void
|
|
|
pcmunmap(int slotno, PCMmap* m)
|
|
|
{
|
|
|
- Slot *pp;
|
|
|
+ PCMslot *pp;
|
|
|
|
|
|
pp = slot + slotno;
|
|
|
lock(&pp->mlock);
|
|
@@ -431,7 +355,7 @@ pcmunmap(int slotno, PCMmap* m)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-increfp(Slot *pp)
|
|
|
+increfp(PCMslot *pp)
|
|
|
{
|
|
|
lock(pp);
|
|
|
if(pp->ref++ == 0)
|
|
@@ -440,7 +364,7 @@ increfp(Slot *pp)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-decrefp(Slot *pp)
|
|
|
+decrefp(PCMslot *pp)
|
|
|
{
|
|
|
lock(pp);
|
|
|
if(pp->ref-- == 1)
|
|
@@ -454,7 +378,7 @@ decrefp(Slot *pp)
|
|
|
static int
|
|
|
pcmcia_pcmspecial(char *idstr, ISAConf *isa)
|
|
|
{
|
|
|
- Slot *pp;
|
|
|
+ PCMslot *pp;
|
|
|
extern char *strstr(char*, char*);
|
|
|
int enabled;
|
|
|
|
|
@@ -472,9 +396,11 @@ pcmcia_pcmspecial(char *idstr, ISAConf *isa)
|
|
|
}
|
|
|
|
|
|
if(pp->occupied) {
|
|
|
- if(strstr(pp->verstr, idstr)) {
|
|
|
- if (!enabled)
|
|
|
+ if(strstr(pp->verstr, idstr)){
|
|
|
+ if (!enabled){
|
|
|
+ enabled = 1;
|
|
|
increfp(pp);
|
|
|
+ }
|
|
|
if(isa == 0 || pcmio(pp->slotno, isa) == 0){
|
|
|
pp->special = 1;
|
|
|
return pp->slotno;
|
|
@@ -491,7 +417,7 @@ pcmcia_pcmspecial(char *idstr, ISAConf *isa)
|
|
|
static void
|
|
|
pcmcia_pcmspecialclose(int slotno)
|
|
|
{
|
|
|
- Slot *pp;
|
|
|
+ PCMslot *pp;
|
|
|
|
|
|
print("pcmspecialclose called\n");
|
|
|
if(slotno >= nslot)
|
|
@@ -520,7 +446,9 @@ i82365probe(int x, int d, int dev)
|
|
|
outb(x, Rid + (dev<<7));
|
|
|
id = inb(d);
|
|
|
if((id & 0xf0) != 0x80)
|
|
|
- return 0; /* not this family */
|
|
|
+ return 0; /* not a memory & I/O card */
|
|
|
+ if((id & 0x0f) == 0x00)
|
|
|
+ return 0; /* no revision number, not possible */
|
|
|
|
|
|
cp = xalloc(sizeof(I82365));
|
|
|
cp->xreg = x;
|
|
@@ -556,18 +484,22 @@ i82365probe(int x, int d, int dev)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ /* if it's not a Cirrus, it could be a Vadem... */
|
|
|
if(cp->type == Ti82365){
|
|
|
+ /* unlock the Vadem extended regs */
|
|
|
outb(x, 0x0E + (dev<<7));
|
|
|
outb(x, 0x37 + (dev<<7));
|
|
|
+
|
|
|
+ /* make the id register show the Vadem id */
|
|
|
outb(x, 0x3A + (dev<<7));
|
|
|
c = inb(d);
|
|
|
outb(d, c|0xC0);
|
|
|
outb(x, Rid + (dev<<7));
|
|
|
c = inb(d);
|
|
|
- if(c != id && !(c & 0x08))
|
|
|
- print("#y%d: id %uX changed to %uX\n", ncontroller, id, c);
|
|
|
if(c & 0x08)
|
|
|
cp->type = Tvg46x;
|
|
|
+
|
|
|
+ /* go back to Intel compatible id */
|
|
|
outb(x, 0x3A + (dev<<7));
|
|
|
c = inb(d);
|
|
|
outb(d, c & ~0xC0);
|
|
@@ -592,7 +524,7 @@ i82365probe(int x, int d, int dev)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-i82365dump(Slot *pp)
|
|
|
+i82365dump(PCMslot *pp)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
@@ -615,7 +547,7 @@ i82365reset(void)
|
|
|
static int already;
|
|
|
int i, j;
|
|
|
I82365 *cp;
|
|
|
- Slot *pp;
|
|
|
+ PCMslot *pp;
|
|
|
|
|
|
if(already)
|
|
|
return;
|
|
@@ -630,9 +562,8 @@ i82365reset(void)
|
|
|
|
|
|
for(i = 0; i < ncontroller; i++)
|
|
|
nslot += controller[i]->nslot;
|
|
|
- slot = xalloc(nslot * sizeof(Slot));
|
|
|
+ slot = xalloc(nslot * sizeof(PCMslot));
|
|
|
|
|
|
- /* if the card is there turn on 5V power to keep its battery alive */
|
|
|
lastslot = slot;
|
|
|
for(i = 0; i < ncontroller; i++){
|
|
|
cp = controller[i];
|
|
@@ -644,6 +575,8 @@ i82365reset(void)
|
|
|
pp->memlen = 64*MB;
|
|
|
pp->base = (cp->dev<<7) | (j<<6);
|
|
|
pp->cp = cp;
|
|
|
+ pp->msec = ~0;
|
|
|
+ pp->verstr[0] = 0;
|
|
|
slotdis(pp);
|
|
|
|
|
|
/* interrupt on status change */
|
|
@@ -657,15 +590,15 @@ i82365reset(void)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * configure the Slot for IO. We assume very heavily that we can read
|
|
|
+ * configure the PCMslot for IO. We assume very heavily that we can read
|
|
|
* configuration info from the CIS. If not, we won't set up correctly.
|
|
|
*/
|
|
|
static int
|
|
|
pcmio(int slotno, ISAConf *isa)
|
|
|
{
|
|
|
uchar we, x, *p;
|
|
|
- Slot *pp;
|
|
|
- Conftab *ct, *et, *t;
|
|
|
+ PCMslot *pp;
|
|
|
+ PCMconftab *ct, *et, *t;
|
|
|
PCMmap *m;
|
|
|
int i, index, irq;
|
|
|
char *cp;
|
|
@@ -692,6 +625,7 @@ pcmio(int slotno, ISAConf *isa)
|
|
|
return -1;
|
|
|
ct = &pp->ctab[index];
|
|
|
}
|
|
|
+
|
|
|
if(ct == 0){
|
|
|
|
|
|
/* assume default is right */
|
|
@@ -749,7 +683,10 @@ pcmio(int slotno, ISAConf *isa)
|
|
|
x |= x<<4;
|
|
|
wrreg(pp, Rio, x);
|
|
|
|
|
|
- /* enable io port map 0 */
|
|
|
+ /*
|
|
|
+ * enable io port map 0
|
|
|
+ * the 'top' register value includes the last valid address
|
|
|
+ */
|
|
|
if(isa->port == 0)
|
|
|
isa->port = ct->io[0].start;
|
|
|
we = rdreg(pp, Rwe);
|
|
@@ -759,7 +696,7 @@ pcmio(int slotno, ISAConf *isa)
|
|
|
wrreg(pp, Riotop0lo, i);
|
|
|
wrreg(pp, Riotop0hi, i>>8);
|
|
|
we |= 1<<6;
|
|
|
- if(ct->nio == 2 && ct->io[1].start){
|
|
|
+ if(ct->nio >= 2 && ct->io[1].start){
|
|
|
wrreg(pp, Riobtm1lo, ct->io[1].start);
|
|
|
wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
|
|
|
i = ct->io[1].start+ct->io[1].len-1;
|
|
@@ -770,436 +707,36 @@ pcmio(int slotno, ISAConf *isa)
|
|
|
wrreg(pp, Rwe, we);
|
|
|
|
|
|
/* only touch Rconfig if it is present */
|
|
|
- if(pp->cpresent & (1<<Rconfig)){
|
|
|
+ m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1);
|
|
|
+ p = KADDR(m->isa + pp->cfg[0].caddr - m->ca);
|
|
|
+ if(pp->cfg[0].cpresent & (1<<Rconfig)){
|
|
|
/* Reset adapter */
|
|
|
- m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
|
|
|
- p = KADDR(m->isa + pp->caddr + Rconfig - m->ca);
|
|
|
|
|
|
- /* set configuration and interrupt type */
|
|
|
+ /* set configuration and interrupt type.
|
|
|
+ * if level is possible on the card, use it.
|
|
|
+ */
|
|
|
x = ct->index;
|
|
|
- if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7))
|
|
|
+ if(ct->irqtype & 0x20)
|
|
|
x |= Clevel;
|
|
|
- *p = x;
|
|
|
- delay(5);
|
|
|
-
|
|
|
- pcmunmap(slotno, m);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * read and crack the card information structure enough to set
|
|
|
- * important parameters like power
|
|
|
- */
|
|
|
-static void tcfig(Slot*, Cisdat*, int);
|
|
|
-static void tentry(Slot*, Cisdat*, int);
|
|
|
-static void tvers1(Slot*, Cisdat*, int);
|
|
|
-
|
|
|
-struct {
|
|
|
- int n;
|
|
|
- void (*parse)(Slot*, Cisdat*, int);
|
|
|
-} cistab[] = {
|
|
|
- 0x15, tvers1,
|
|
|
- 0x1A, tcfig,
|
|
|
- 0x1B, tentry,
|
|
|
-};
|
|
|
-
|
|
|
-static int
|
|
|
-readc(Cisdat *pp, uchar *x)
|
|
|
-{
|
|
|
- if(pp->cispos >= pp->cislen)
|
|
|
- return 0;
|
|
|
- *x = pp->cisbase[pp->cisskip*pp->cispos];
|
|
|
- pp->cispos++;
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-xcistuple(int slotno, int tuple, void *v, int nv, int attr)
|
|
|
-{
|
|
|
- PCMmap *m;
|
|
|
- Cisdat cis;
|
|
|
- int i, l;
|
|
|
- uchar *p;
|
|
|
- uchar type, link;
|
|
|
- int this;
|
|
|
-
|
|
|
- m = pcmmap(slotno, 0, 0, attr);
|
|
|
- if(m == 0) {
|
|
|
-if(debug) print("could not map\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- cis.cisbase = KADDR(m->isa);
|
|
|
- cis.cispos = 0;
|
|
|
- cis.cisskip = attr ? 2 : 1;
|
|
|
- cis.cislen = Mchunk;
|
|
|
-
|
|
|
-if(debug) print("cis %d %d #%lux srch %x...", attr, cis.cisskip, cis.cisbase, tuple);
|
|
|
- /* loop through all the tuples */
|
|
|
- for(i = 0; i < 1000; i++){
|
|
|
- this = cis.cispos;
|
|
|
- if(readc(&cis, &type) != 1)
|
|
|
- break;
|
|
|
-if(debug) print("%2ux...", type);
|
|
|
- if(type == 0xFF)
|
|
|
- break;
|
|
|
- if(readc(&cis, &link) != 1)
|
|
|
- break;
|
|
|
- if(link == 0xFF)
|
|
|
- break;
|
|
|
- if(type == tuple) {
|
|
|
- p = v;
|
|
|
- for(l=0; l<nv && l<link; l++)
|
|
|
- if(readc(&cis, p++) != 1)
|
|
|
- break;
|
|
|
- pcmunmap(slotno, m);
|
|
|
-if(debug) print("pcm find %2.2ux %d %d\n", type, link, l);
|
|
|
- return l;
|
|
|
- }
|
|
|
- cis.cispos = this + (2+link);
|
|
|
- }
|
|
|
- pcmunmap(slotno, m);
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-int
|
|
|
-pcmcistuple(int slotno, int tuple, void *v, int nv)
|
|
|
-{
|
|
|
- int n;
|
|
|
-
|
|
|
- /* try attribute space, then memory */
|
|
|
- if((n = xcistuple(slotno, tuple, v, nv, 1)) >= 0)
|
|
|
- return n;
|
|
|
- return xcistuple(slotno, tuple, v, nv, 0);
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-cisread(Slot *pp)
|
|
|
-{
|
|
|
- uchar v[256];
|
|
|
- int i, nv;
|
|
|
- Cisdat cis;
|
|
|
-
|
|
|
- memset(pp->ctab, 0, sizeof(pp->ctab));
|
|
|
- pp->caddr = 0;
|
|
|
- pp->cpresent = 0;
|
|
|
- pp->configed = 0;
|
|
|
- pp->nctab = 0;
|
|
|
-
|
|
|
- for(i = 0; i < nelem(cistab); i++) {
|
|
|
- if((nv = pcmcistuple(pp->slotno, cistab[i].n, v, sizeof(v))) >= 0) {
|
|
|
- cis.cisbase = v;
|
|
|
- cis.cispos = 0;
|
|
|
- cis.cisskip = 1;
|
|
|
- cis.cislen = nv;
|
|
|
-
|
|
|
- (*cistab[i].parse)(pp, &cis, cistab[i].n);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static ulong
|
|
|
-getlong(Cisdat *cis, int size)
|
|
|
-{
|
|
|
- uchar c;
|
|
|
- int i;
|
|
|
- ulong x;
|
|
|
-
|
|
|
- x = 0;
|
|
|
- for(i = 0; i < size; i++){
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- break;
|
|
|
- x |= c<<(i*8);
|
|
|
- }
|
|
|
- return x;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-tcfig(Slot *pp, Cisdat *cis, int )
|
|
|
-{
|
|
|
- uchar size, rasize, rmsize;
|
|
|
- uchar last;
|
|
|
-
|
|
|
- if(readc(cis, &size) != 1)
|
|
|
- return;
|
|
|
- rasize = (size&0x3) + 1;
|
|
|
- rmsize = ((size>>2)&0xf) + 1;
|
|
|
- if(readc(cis, &last) != 1)
|
|
|
- return;
|
|
|
- pp->caddr = getlong(cis, rasize);
|
|
|
- pp->cpresent = getlong(cis, rmsize);
|
|
|
-}
|
|
|
-
|
|
|
-static ulong vexp[8] =
|
|
|
-{
|
|
|
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
|
|
|
-};
|
|
|
-static ulong vmant[16] =
|
|
|
-{
|
|
|
- 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
|
|
|
-};
|
|
|
-
|
|
|
-static ulong
|
|
|
-microvolt(Cisdat *cis)
|
|
|
-{
|
|
|
- uchar c;
|
|
|
- ulong microvolts;
|
|
|
- ulong exp;
|
|
|
-
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return 0;
|
|
|
- exp = vexp[c&0x7];
|
|
|
- microvolts = vmant[(c>>3)&0xf]*exp;
|
|
|
- while(c & 0x80){
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return 0;
|
|
|
- switch(c){
|
|
|
- case 0x7d:
|
|
|
- break; /* high impedence when sleeping */
|
|
|
- case 0x7e:
|
|
|
- case 0x7f:
|
|
|
- microvolts = 0; /* no connection */
|
|
|
- break;
|
|
|
- default:
|
|
|
- exp /= 10;
|
|
|
- microvolts += exp*(c&0x7f);
|
|
|
- }
|
|
|
- }
|
|
|
- return microvolts;
|
|
|
-}
|
|
|
-
|
|
|
-static ulong
|
|
|
-nanoamps(Cisdat *cis)
|
|
|
-{
|
|
|
- uchar c;
|
|
|
- ulong nanoamps;
|
|
|
-
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return 0;
|
|
|
- nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
|
|
|
- while(c & 0x80){
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return 0;
|
|
|
- if(c == 0x7d || c == 0x7e || c == 0x7f)
|
|
|
- nanoamps = 0;
|
|
|
- }
|
|
|
- return nanoamps;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * only nominal voltage is important for config
|
|
|
- */
|
|
|
-static ulong
|
|
|
-power(Cisdat *cis)
|
|
|
-{
|
|
|
- uchar feature;
|
|
|
- ulong mv;
|
|
|
-
|
|
|
- mv = 0;
|
|
|
- if(readc(cis, &feature) != 1)
|
|
|
- return 0;
|
|
|
- if(feature & 1)
|
|
|
- mv = microvolt(cis);
|
|
|
- if(feature & 2)
|
|
|
- microvolt(cis);
|
|
|
- if(feature & 4)
|
|
|
- microvolt(cis);
|
|
|
- if(feature & 8)
|
|
|
- nanoamps(cis);
|
|
|
- if(feature & 0x10)
|
|
|
- nanoamps(cis);
|
|
|
- if(feature & 0x20)
|
|
|
- nanoamps(cis);
|
|
|
- if(feature & 0x40)
|
|
|
- nanoamps(cis);
|
|
|
- return mv/1000000;
|
|
|
-}
|
|
|
-
|
|
|
-static ulong mantissa[16] =
|
|
|
-{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
|
|
|
-
|
|
|
-static ulong exponent[8] =
|
|
|
-{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
|
|
|
|
|
|
-static ulong
|
|
|
-ttiming(Cisdat *cis, int scale)
|
|
|
-{
|
|
|
- uchar unscaled;
|
|
|
- ulong nanosecs;
|
|
|
-
|
|
|
- if(readc(cis, &unscaled) != 1)
|
|
|
- return 0;
|
|
|
- nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
|
|
|
- nanosecs = nanosecs * vexp[scale];
|
|
|
- return nanosecs;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-timing(Cisdat *cis, Conftab *ct)
|
|
|
-{
|
|
|
- uchar c, i;
|
|
|
-
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return;
|
|
|
- i = c&0x3;
|
|
|
- if(i != 3)
|
|
|
- ct->maxwait = ttiming(cis, i); /* max wait */
|
|
|
- i = (c>>2)&0x7;
|
|
|
- if(i != 7)
|
|
|
- ct->readywait = ttiming(cis, i); /* max ready/busy wait */
|
|
|
- i = (c>>5)&0x7;
|
|
|
- if(i != 7)
|
|
|
- ct->otherwait = ttiming(cis, i); /* reserved wait */
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-iospaces(Cisdat *cis, Conftab *ct)
|
|
|
-{
|
|
|
- uchar c;
|
|
|
- int i, nio;
|
|
|
-
|
|
|
- ct->nio = 0;
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return;
|
|
|
-
|
|
|
- ct->bit16 = ((c>>5)&3) >= 2;
|
|
|
- if(!(c & 0x80)){
|
|
|
- ct->io[0].start = 0;
|
|
|
- ct->io[0].len = 1<<(c&0x1f);
|
|
|
- ct->nio = 1;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return;
|
|
|
-
|
|
|
- nio = (c&0xf)+1;
|
|
|
- for(i = 0; i < nio; i++){
|
|
|
- ct->io[i].start = getlong(cis, (c>>4)&0x3);
|
|
|
- ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
|
|
|
- }
|
|
|
- ct->nio = nio;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-irq(Cisdat *cis, Conftab *ct)
|
|
|
-{
|
|
|
- uchar c;
|
|
|
-
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return;
|
|
|
- ct->irqtype = c & 0xe0;
|
|
|
- if(c & 0x10)
|
|
|
- ct->irqs = getlong(cis, 2);
|
|
|
- else
|
|
|
- ct->irqs = 1<<(c&0xf);
|
|
|
- ct->irqs &= 0xDEB8; /* levels available to card */
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-memspace(Cisdat *cis, int asize, int lsize, int host)
|
|
|
-{
|
|
|
- ulong haddress, address, len;
|
|
|
-
|
|
|
- len = getlong(cis, lsize)*256;
|
|
|
- address = getlong(cis, asize)*256;
|
|
|
- USED(len, address);
|
|
|
- if(host){
|
|
|
- haddress = getlong(cis, asize)*256;
|
|
|
- USED(haddress);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-tentry(Slot *pp, Cisdat *cis, int )
|
|
|
-{
|
|
|
- uchar c, i, feature;
|
|
|
- Conftab *ct;
|
|
|
-
|
|
|
- if(pp->nctab >= Maxctab)
|
|
|
- return;
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return;
|
|
|
- ct = &pp->ctab[pp->nctab++];
|
|
|
-
|
|
|
- /* copy from last default config */
|
|
|
- if(pp->def)
|
|
|
- *ct = *pp->def;
|
|
|
-
|
|
|
- ct->index = c & 0x3f;
|
|
|
-
|
|
|
- /* is this the new default? */
|
|
|
- if(c & 0x40)
|
|
|
- pp->def = ct;
|
|
|
+ /* enable the device, enable address decode and
|
|
|
+ * irq enable.
|
|
|
+ */
|
|
|
+ x |= Cfunc|Cdecode|Cirq;
|
|
|
|
|
|
- /* memory wait specified? */
|
|
|
- if(c & 0x80){
|
|
|
- if(readc(cis, &i) != 1)
|
|
|
- return;
|
|
|
- if(i&0x80)
|
|
|
- ct->memwait = 1;
|
|
|
+ p[0] = x;
|
|
|
+ //delay(5);
|
|
|
+ microdelay(40);
|
|
|
}
|
|
|
|
|
|
- if(readc(cis, &feature) != 1)
|
|
|
- return;
|
|
|
- switch(feature&0x3){
|
|
|
- case 1:
|
|
|
- ct->vpp1 = ct->vpp2 = power(cis);
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- power(cis);
|
|
|
- ct->vpp1 = ct->vpp2 = power(cis);
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- power(cis);
|
|
|
- ct->vpp1 = power(cis);
|
|
|
- ct->vpp2 = power(cis);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- if(feature&0x4)
|
|
|
- timing(cis, ct);
|
|
|
- if(feature&0x8)
|
|
|
- iospaces(cis, ct);
|
|
|
- if(feature&0x10)
|
|
|
- irq(cis, ct);
|
|
|
- switch((feature>>5)&0x3){
|
|
|
- case 1:
|
|
|
- memspace(cis, 0, 2, 0);
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- memspace(cis, 2, 2, 0);
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return;
|
|
|
- for(i = 0; i <= (c&0x7); i++)
|
|
|
- memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
|
|
|
- break;
|
|
|
+ if(pp->cfg[0].cpresent & (1<<Riobase0)){
|
|
|
+ /* set up the iobase 0 */
|
|
|
+ p[Riobase0 << 1] = isa->port;
|
|
|
+ p[Riobase1 << 1] = isa->port >> 8;
|
|
|
}
|
|
|
- pp->configed++;
|
|
|
-}
|
|
|
|
|
|
-static void
|
|
|
-tvers1(Slot *pp, Cisdat *cis, int )
|
|
|
-{
|
|
|
- uchar c, major, minor;
|
|
|
- int i;
|
|
|
-
|
|
|
- if(readc(cis, &major) != 1)
|
|
|
- return;
|
|
|
- if(readc(cis, &minor) != 1)
|
|
|
- return;
|
|
|
- for(i = 0; i < sizeof(pp->verstr)-1; i++){
|
|
|
- if(readc(cis, &c) != 1)
|
|
|
- return;
|
|
|
- if(c == 0)
|
|
|
- c = '\n';
|
|
|
- if(c == 0xff)
|
|
|
- break;
|
|
|
- pp->verstr[i] = c;
|
|
|
- }
|
|
|
- pp->verstr[i] = 0;
|
|
|
+ if(pp->cfg[0].cpresent & (1<<Riosize))
|
|
|
+ p[Riosize << 1] = ct->io[0].len;
|
|
|
+ pcmunmap(slotno, m);
|
|
|
+ return 0;
|
|
|
}
|