## diffname pc/devi82365.c 1994/1209
## diff -e /dev/null /n/fornaxdump/1994/1209/sys/src/brazil/pc/devi82365.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "devtab.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 Slot or
* Cirrus Logic PD6710/PD6720 which is mostly register compatible
*/
enum
{
/*
* registers indices
*/
Rid= 0x0, /* identification and revision */
Ris= 0x1, /* interface status */
Rpc= 0x2, /* power control */
Foutena= (1<<7), /* output enable */
Fautopower= (1<<5), /* automatic power switching */
Fcardena= (1<<4), /* PC card enable */
Rigc= 0x3, /* interrupt and general control */
Fiocard= (1<<5), /* I/O card (vs memory) */
Fnotreset= (1<<6), /* reset if not set */
FSMIena= (1<<4), /* enable change interrupt on SMI */
Rcsc= 0x4, /* card status change */
Rcscic= 0x5, /* card status change interrupt config */
Fchangeena= (1<<3), /* card changed */
Fbwarnena= (1<<1), /* card battery warning */
Fbdeadena= (1<<0), /* card battery dead */
Rwe= 0x6, /* address window enable */
Fmem16= (1<<5), /* use A23-A12 to decode address */
Rio= 0x7, /* I/O control */
Riobtm0lo= 0x8, /* I/O address 0 start low byte */
Riobtm0hi= 0x9, /* I/O address 0 start high byte */
Riotop0lo= 0xa, /* I/O address 0 stop low byte */
Riotop0hi= 0xb, /* I/O address 0 stop high byte */
Riobtm1lo= 0xc, /* I/O address 1 start low byte */
Riobtm1hi= 0xd, /* I/O address 1 start high byte */
Riotop1lo= 0xe, /* I/O address 1 stop low byte */
Riotop1hi= 0xf, /* I/O address 1 stop high byte */
Rmap= 0x10, /* map 0 */
/*
* CL-PD67xx extension registers
*/
Rmisc1= 0x16, /* misc control 1 */
F5Vdetect= (1<<0),
Fvcc3V= (1<<1),
Fpmint= (1<<2),
Fpsirq= (1<<3),
Fspeaker= (1<<4),
Finpack= (1<<7),
Rfifo= 0x17, /* fifo control */
Fflush= (1<<7), /* flush fifo */
Rmisc2= 0x1E, /* misc control 2 */
Rchipinfo= 0x1F, /* chip information */
Ratactl= 0x26, /* ATA control */
/*
* offsets into the system memory address maps
*/
Mbtmlo= 0x0, /* System mem addr mapping start low byte */
Mbtmhi= 0x1, /* System mem addr mapping start high byte */
Mtoplo= 0x2, /* System mem addr mapping stop low byte */
Mtophi= 0x3, /* System mem addr mapping stop high byte */
F16bit= (1<<7), /* 16-bit wide data path */
Mofflo= 0x4, /* Card memory offset address low byte */
Moffhi= 0x5, /* Card memory offset address high byte */
Fregactive= (1<<6), /* attribute meory */
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.
*/
Rconfig= 0,
Creset= (1<<7), /* reset device */
Clevel= (1<<6), /* level sensitive interrupt line */
};
#define MAP(x,o) (Rmap + (x)*0x8 + o)
typedef struct I82365 I82365;
typedef struct Slot Slot;
typedef struct PCMmap PCMmap;
/* maps between ISA memory space and the card memory space */
struct PCMmap
{
ulong ca; /* card address */
ulong cea; /* card end address */
ulong isa; /* ISA address */
int attr; /* attribute memory */
int time;
};
/* a controller */
enum
{
Ti82365,
Tpd6710,
Tpd6720,
};
struct I82365
{
QLock;
int type;
int dev;
int nslot;
int xreg; /* index register address */
int dreg; /* data register address */
};
static I82365 *controller[4];
static int ncontroller;
/* a Slot slot */
struct Slot
{
int ref;
I82365 *cp; /* controller for this slot */
long memlen; /* memory length */
uchar base; /* index register base */
uchar dev; /* slot number */
/* status */
uchar special; /* in use for a special device */
uchar already; /* already inited */
uchar gotmem; /* already got memmap space */
uchar occupied;
uchar battery;
uchar wrprot;
uchar powered;
uchar configed;
uchar enabled;
uchar iocard;
uchar busy;
/* cis info */
uchar vpp1;
uchar vpp2;
uchar bit16;
uchar nioregs;
uchar memwait;
uchar cpresent; /* config registers present */
uchar def; /* default configuration */
ushort irqs; /* valid interrupt levels */
ulong caddr; /* relative address of config registers */
uchar *cisbase; /* base of mapped in attribute space */
uchar *cispos; /* current position scanning cis */
/* memory maps */
int time;
PCMmap mmap[Nmap];
};
static Slot *slot;
static Slot *lastslot;
static nslot;
static void cisread(Slot*);
/*
* reading and writing card registers
*/
static uchar
rdreg(Slot *pp, int index)
{
outb(pp->cp->xreg, pp->base + index);
return inb(pp->cp->dreg);
}
static void
wrreg(Slot *pp, int index, uchar val)
{
outb(pp->cp->xreg, pp->base + index);
outb(pp->cp->dreg, val);
}
/*
* get info about card
*/
static void
slotinfo(Slot *pp)
{
uchar isr;
isr = rdreg(pp, Ris);
pp->occupied = (isr & (3<<2)) == (3<<2);
pp->powered = isr & (1<<6);
pp->battery = (isr & 3) == 3;
pp->wrprot = isr & (1<<4);
pp->busy = isr & (1<<5);
isr = rdreg(pp, Rigc);
pp->iocard = isr & Fiocard;
}
static int
vcode(int volt)
{
switch(volt){
case 5:
return 1;
case 12:
return 2;
default:
return 0;
}
}
/*
* enable the slot card
*/
static void
slotena(Slot *pp)
{
int x;
if(pp->enabled)
return;
if(pp->already == 0){
pp->already = 1;
/* interrupt on card status change */
wrreg(pp, Rigc, Fnotreset);
wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena
| Fbwarnena | Fbdeadena);
}
/* display status */
slotinfo(pp);
if(pp->occupied){
/* enable the card */
wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena);
pp->enabled = 1;
cisread(pp);
/* set real power values if we configured successfully */
if(pp->configed){
x = vcode(pp->vpp1) | (vcode(pp->vpp2)<<2);
wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
}
}
}
/*
* disable the slot card
*/
static void
slotdis(Slot *pp)
{
/* disable the windows into the card */
wrreg(pp, Rwe, 0);
/* disable the card */
wrreg(pp, Rpc, 5|Fautopower);
pp->enabled = 0;
}
/*
* status change interrupt
*/
static void
i82365intr(Ureg *ur)
{
uchar csc;
Slot *pp;
USED(ur);
for(pp = slot; pp < lastslot; pp++){
csc = rdreg(pp, Rcsc);
slotinfo(pp);
if(csc & 1)
print("slot card %d battery dead\n", pp->dev);
if(csc & (1<<1))
print("slot card %d battery warning\n", pp->dev);
if(csc & (1<<3)){
if(pp->occupied && pp->ref){
print("slot card %d inserted\n", pp->dev);
slotena(pp);
} else {
print("slot card %d removed\n", pp->dev);
slotdis(pp);
}
}
}
}
/*
* get a map for pc card region, return corrected len
*/
static PCMmap*
getmap(Slot *pp, ulong offset, int attr)
{
uchar we, bit;
PCMmap *m, *lru;
int i;
if(pp->gotmem == 0){
pp->gotmem = 1;
/* grab ISA address space for memory maps */
for(i = 0; i < Nmap; i++)
pp->mmap[i].isa = isamem(Mchunk);
}
/* look for a map that starts in the right place */
we = rdreg(pp, Rwe);
bit = 1;
lru = pp->mmap;
for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){
if((we & bit) && m->attr == attr && offset >= m->ca && offset < m->cea){
m->time = pp->time++;
return m;
}
bit <<= 1;
if(lru->time > m->time)
lru = m;
}
/* use the least recently used */
m = lru;
offset &= ~(Mchunk - 1);
m->ca = offset;
m->cea = m->ca + Mchunk;
m->attr = attr;
m->time = pp->time++;
i = m - pp->mmap;
bit = 1<<i;
wrreg(pp, Rwe, we & ~bit); /* disable map before changing it */
wrreg(pp, MAP(i, Mbtmlo), m->isa>>12);
wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(12+8)) | F16bit);
wrreg(pp, MAP(i, Mtoplo), (m->isa+Mchunk-1)>>12);
wrreg(pp, MAP(i, Mtophi), (m->isa+Mchunk-1)>>(12+8));
offset -= m->isa;
offset &= (1<<25)-1;
offset >>= 12;
wrreg(pp, MAP(i, Mofflo), offset);
wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
wrreg(pp, Rwe, we | bit); /* enable map */
return m;
}
static void
increfp(Slot *pp)
{
qlock(pp->cp);
if(pp->ref++ == 0)
slotena(pp);
qunlock(pp->cp);
}
static void
decrefp(Slot *pp)
{
qlock(pp->cp);
if(pp->ref-- == 1)
slotdis(pp);
qunlock(pp->cp);
}
int
pcmspecial(int dev)
{
Slot *pp;
i82365reset();
if(dev >= nslot)
return -1;
pp = slot + dev;
if(pp->special)
return -1;
increfp(pp);
if(!pp->occupied){
decrefp(pp);
return -1;
}
pp->special = 1;
return 0;
}
void
pcmspecialclose(int dev)
{
Slot *pp;
if(dev >= nslot)
panic("pcmspecialclose");
pp = slot + dev;
pp->special = 0;
decrefp(pp);
}
enum
{
Qdir,
Qmem,
Qattr,
Qctl,
};
#define DEV(c) (c->qid.path>>8)
#define TYPE(c) (c->qid.path&0xff)
static int
pcmgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
{
int dev;
Qid qid;
long len;
Slot *pp;
char name[NAMELEN];
USED(tab, ntab);
if(i>=3*nslot)
return -1;
dev = i/3;
pp = slot + dev;
len = 0;
switch(i%3){
case 0:
qid.path = (dev<<8) | Qmem;
sprint(name, "pcm%dmem", dev);
len = pp->memlen;
break;
case 1:
qid.path = (dev<<8) | Qattr;
sprint(name, "pcm%dattr", dev);
len = pp->memlen;
break;
case 2:
qid.path = (dev<<8) | Qctl;
sprint(name, "pcm%dctl", dev);
break;
}
qid.vers = 0;
devdir(c, qid, name, len, eve, 0660, dp);
return 1;
}
static char *chipname[] =
{
[Ti82365] "Intel 82365SL",
[Tpd6710] "Cirrus Logic PD6710",
[Tpd6720] "Cirrus Logic PD6720",
};
static I82365*
i82386probe(int x, int d, int dev)
{
uchar c;
I82365 *cp;
outb(x, Rid + (dev<<7));
c = inb(d);
if((c & 0xf0) != 0x80)
return 0; /* not this family */
cp = xalloc(sizeof(I82365));
cp->xreg = x;
cp->dreg = d;
cp->dev = dev;
cp->type = Ti82365;
cp->nslot = 2;
switch(c){
case 0x82:
case 0x83:
/* could be a cirrus */
outb(x, Rchipinfo + (dev<<7));
outb(d, 0);
c = inb(d);
if((c & 0xdf) == 0xdc){
c = inb(d);
if((c & 0xdf) != 0x0c)
break;
}
if(c & 0x40){
cp->type = Tpd6720;
} else {
cp->type = Tpd6710;
cp->nslot = 1;
}
break;
}
print("pcmcia controller%d is a %d slot %s\n", ncontroller, cp->nslot,
chipname[cp->type]);
controller[ncontroller++] = cp;
return cp;
}
/*
* set up for slot cards
*/
void
i82365reset(void)
{
static int already;
int i, j;
I82365 *cp;
if(already)
return;
already = 1;
/* look for controllers */
i82386probe(0x3E0, 0x3E1, 0);
i82386probe(0x3E0, 0x3E1, 1);
for(i = 0; i < ncontroller; i++)
nslot += controller[i]->nslot;
slot = xalloc(nslot * sizeof(Slot));
/* 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];
for(j = 0; j < cp->nslot; j++){
lastslot->dev = lastslot - slot;
lastslot->memlen = 64*MB;
lastslot->base = (cp->dev<<7) | (j<<6);
lastslot->cp = cp;
wrreg(lastslot, Rpc, 5|Fautopower);
lastslot++;
}
}
}
void
i82365init(void)
{
}
Chan *
i82365attach(char *spec)
{
return devattach('y', spec);
}
Chan *
i82365clone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
i82365walk(Chan *c, char *name)
{
return devwalk(c, name, 0, 0, pcmgen);
}
void
i82365stat(Chan *c, char *db)
{
devstat(c, db, 0, 0, pcmgen);
}
Chan *
i82365open(Chan *c, int omode)
{
if(c->qid.path == CHDIR){
if(omode != OREAD)
error(Eperm);
} else
increfp(slot + DEV(c));
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
return c;
}
void
i82365create(Chan *c, char *name, int omode, ulong perm)
{
USED(c, name, omode, perm);
error(Eperm);
}
void
i82365remove(Chan *c)
{
USED(c);
error(Eperm);
}
void
i82365wstat(Chan *c, char *dp)
{
USED(c, dp);
error(Eperm);
}
void
i82365close(Chan *c)
{
USED(c);
if(c->qid.path != CHDIR)
decrefp(slot+DEV(c));
}
/* a memmove using only shorts & bytes */
static void
memmoves(uchar *to, uchar *from, int n)
{
ushort *t, *f;
if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
while(n-- > 0)
*to++ = *from++;
} else {
n = n/2;
t = (ushort*)to;
f = (ushort*)from;
while(n-- > 0)
*t++ = *f++;
}
}
long
pcmread(int dev, int attr, void *a, long n, ulong offset)
{
int i, len;
PCMmap *m;
ulong ka;
uchar *ac;
Slot *pp;
pp = slot + dev;
if(pp->memlen < offset)
return 0;
qlock(pp->cp);
ac = a;
if(pp->memlen < offset + n)
n = pp->memlen - offset;
for(len = n; len > 0; len -= i){
if(pp->occupied == 0 || pp->enabled == 0)
error(Eio);
m = getmap(pp, offset, attr);
if(offset + len > m->cea)
i = m->cea - offset;
else
i = len;
ka = KZERO|(m->isa + (offset&(Mchunk-1)));
memmoves(ac, (void*)ka, i);
offset += i;
ac += i;
}
qunlock(pp->cp);
return n;
}
long
i82365read(Chan *c, void *a, long n, ulong offset)
{
char *cp, buf[128];
ulong p;
Slot *pp;
p = TYPE(c);
switch(p){
case Qdir:
return devdirread(c, a, n, 0, 0, pcmgen);
case Qmem:
case Qattr:
n = pcmread(DEV(c), p==Qattr, a, n, offset);
break;
case Qctl:
cp = buf;
pp = slot + DEV(c);
if(pp->occupied)
cp += sprint(cp, "occupied\n");
if(pp->enabled)
cp += sprint(cp, "enabled\n");
if(pp->powered)
cp += sprint(cp, "powered\n");
if(pp->iocard)
cp += sprint(cp, "iocard\n");
if(pp->configed)
cp += sprint(cp, "configed\n");
if(pp->wrprot)
cp += sprint(cp, "write protected\n");
if(pp->busy)
cp += sprint(cp, "busy\n");
cp += sprint(cp, "battery lvl %d\n", pp->battery);
*cp = 0;
return readstr(offset, a, n, buf);
default:
n=0;
break;
}
return n;
}
long
pcmwrite(int dev, int attr, void *a, long n, ulong offset)
{
int i, len;
PCMmap *m;
ulong ka;
uchar *ac;
Slot *pp;
pp = slot + dev;
if(pp->memlen < offset)
return 0;
qlock(pp->cp);
ac = a;
if(pp->memlen < offset + n)
n = pp->memlen - offset;
for(len = n; len > 0; len -= i){
m = getmap(pp, offset, attr);
if(offset + len > m->cea)
i = m->cea - offset;
else
i = len;
ka = KZERO|(m->isa + (offset&(Mchunk-1)));
memmoves((void*)ka, ac, i);
offset += i;
ac += i;
}
qunlock(pp->cp);
return n;
}
long
i82365write(Chan *c, void *a, long n, ulong offset)
{
ulong p;
Slot *pp;
p = TYPE(c);
switch(p){
case Qmem:
case Qattr:
pp = slot + DEV(c);
if(pp->occupied == 0 || pp->enabled == 0)
error(Eio);
n = pcmwrite(pp->dev, p == Qattr, a, n, offset);
break;
default:
error(Ebadusefd);
}
return n;
}
/*
* configure the Slot for IO. We assume very heavily that we can read
* cofiguration info from the CIS. If not, we won't set up correctly.
*/
int
pcmio(int dev, ISAConf *isa)
{
uchar we, x;
Slot *pp;
if(dev > nslot)
return -1;
pp = slot + dev;
if(!pp->occupied)
return -1;
/* if no io registers, assume not an io card (iffy!) */
if(pp->nioregs == 0)
return -1;
/* route interrupts, make sure card can use specified interrupt */
if(isa->irq == 2)
isa->irq = 9;
if(((1<<isa->irq) & pp->irqs) == 0)
return -1;
wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard);
/* set power and enable device */
x = vcode(pp->vpp1) | (vcode(pp->vpp2)<<2);
wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
/* 16-bit data path */
if(pp->bit16)
wrreg(pp, Rio, (1<<0)|(1<<1));
/* enable io port map 0 */
if(isa->port == 0)
isa->port = 300;
we = rdreg(pp, Rwe);
wrreg(pp, Riobtm0lo, isa->port);
wrreg(pp, Riobtm0hi, isa->port>>8);
wrreg(pp, Riotop0lo, (isa->port+pp->nioregs));
wrreg(pp, Riotop0hi, (isa->port+pp->nioregs)>>8);
wrreg(pp, Rwe, we | (1<<6));
/* only touch Rconfig if it is present */
if(pp->cpresent & (1<<Rconfig)){
/* Reset adapter */
x = Creset;
pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig);
delay(2);
x = 0;
pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig);
delay(2);
/*
* Set level sensitive (not pulsed) interrupts and
* configuration number 1.
* Setting the configuration number enables IO port access.
*/
x = Clevel | 1;
pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig);
delay(2);
}
return 0;
}
/*
* read and crack the card information structure enough to set
* important parameters like power
*/
static void tcfig(Slot*, int);
static void tentry(Slot*, int);
static void (*parse[256])(Slot*, int) =
{
[0x1A] tcfig,
[0x1B] tentry,
};
static int
readc(Slot *pp, uchar *x)
{
uchar l, r;
ushort s;
if(pp->cispos > pp->cisbase + Mchunk)
return 0;
*x = *(pp->cispos);
pp->cispos += 2;
return 1;
}
static void
cisread(Slot *pp)
{
PCMmap *m;
uchar link;
uchar type;
uchar *this;
int i;
pp->vpp1 = pp->vpp2 = 5;
pp->bit16 = 0;
pp->caddr = 0;
pp->cpresent = 0;
pp->def = 0;
pp->irqs = 0xffff;
/* map in the attribute memory cis should be in */
m = getmap(pp, 0, 1);
pp->cispos = pp->cisbase = (uchar*)(KZERO|m->isa);
/* loop through all the tuples */
for(i = 0; i < 1000; i++){
this = pp->cispos;
if(readc(pp, &type) != 1)
break;
if(readc(pp, &link) != 1)
break;
if(parse[type])
(*parse[type])(pp, type);
if(link == 0xff)
break;
pp->cispos = this + 2*(2+link);
if(this > pp->cisbase + Mchunk)
break;
}
}
static ulong
getlong(Slot *pp, int size)
{
uchar c;
int i;
ulong x;
x = 0;
for(i = 0; i < size; i++){
if(readc(pp, &c) != 1)
break;
x |= c<<(i*8);
}
return x;
}
static void
tcfig(Slot *pp, int ttype)
{
uchar size, rasize, rmsize;
uchar last;
USED(ttype);
if(readc(pp, &size) != 1)
return;
rasize = (size&0x3) + 1;
rmsize = ((size>>2)&0xf) + 1;
if(readc(pp, &last) != 1)
return;
pp->caddr = getlong(pp, rasize);
pp->cpresent = getlong(pp, 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(Slot *pp)
{
uchar c;
ulong microvolts;
if(readc(pp, &c) != 1)
return 0;
microvolts = vexp[c&0x7]*vmant[(c>>3)&0xf];
while(c & 0x80){
if(readc(pp, &c) != 1)
return 0;
if(c == 0x7d || c == 0x7e || c == 0x7f)
microvolts = 0;
}
return microvolts;
}
static ulong
nanoamps(Slot *pp)
{
uchar c;
ulong nanoamps;
if(readc(pp, &c) != 1)
return 0;
nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
while(c & 0x80){
if(readc(pp, &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(Slot *pp)
{
uchar feature;
ulong mv;
mv = 0;
if(readc(pp, &feature) != 1)
return 0;
if(feature & 1)
mv = microvolt(pp);
if(feature & 2)
microvolt(pp);
if(feature & 4)
microvolt(pp);
if(feature & 8)
nanoamps(pp);
if(feature & 0x10)
nanoamps(pp);
if(feature & 0x20)
nanoamps(pp);
if(feature & 0x20)
nanoamps(pp);
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(Slot *pp, int scale)
{
uchar unscaled;
ulong nanosecs;
if(readc(pp, &unscaled) != 1)
return 0;
nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
nanosecs = nanosecs * vexp[scale];
return nanosecs;
}
static void
timing(Slot *pp)
{
uchar c, i;
if(readc(pp, &c) != 1)
return;
i = c&0x3;
if(i != 3)
ttiming(pp, i); /* max wait */
i = (c>>2)&0x7;
if(i != 7)
ttiming(pp, i); /* max ready/busy wait */
i = (c>>5)&0x7;
if(i != 7)
ttiming(pp, i); /* reserved wait */
}
void
iospaces(Slot *pp)
{
uchar c;
int i;
ulong address, len;
for(;;){
if(readc(pp, &c) != 1)
break;
pp->nioregs = 1<<(c&0x1f);
pp->bit16 = ((c>>5)&3) >= 2;
if((c & 0x80) == 0)
break;
if(readc(pp, &c) != 1)
break;
for(i = (c&0xf)+1; i; i--){
address = getlong(pp, (c>>4)&0x3);
len = getlong(pp, (c>>6)&0x3);
USED(address, len);
}
}
}
static void
irq(Slot *pp)
{
uchar c;
if(readc(pp, &c) != 1)
return;
if(c & 0x10)
pp->irqs = getlong(pp, 2);
else
pp->irqs = 1<<(c&0xf);
}
static void
memspace(Slot *pp, int asize, int lsize, int host)
{
ulong haddress, address, len;
len = getlong(pp, lsize)*256;
address = getlong(pp, asize)*256;
USED(len, address);
if(host){
haddress = getlong(pp, asize)*256;
USED(haddress);
}
}
void
tentry(Slot *pp, int ttype)
{
uchar c, i, feature;
USED(ttype);
if(readc(pp, &c) != 1)
return;
if(c&0x40)
pp->def = 1;
if(c & 0x80){
if(readc(pp, &i) != 1)
return;
if(i&0x80)
pp->memwait = 1;
}
if(readc(pp, &feature) != 1)
return;
switch(feature&0x3){
case 1:
pp->vpp1 = pp->vpp2 = power(pp);
break;
case 2:
power(pp);
pp->vpp1 = pp->vpp2 = power(pp);
break;
case 3:
power(pp);
pp->vpp1 = power(pp);
pp->vpp2 = power(pp);
break;
default:
break;
}
if(feature&0x4)
timing(pp);
if(feature&0x8)
iospaces(pp);
if(feature&0x10)
irq(pp);
switch(feature&0x3){
case 1:
memspace(pp, 0, 2, 0);
break;
case 2:
memspace(pp, 2, 2, 0);
break;
case 3:
if(readc(pp, &c) != 1)
return;
for(i = 0; i <= c&0x7; i++)
memspace(pp, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
break;
}
pp->configed++;
}
.
## diffname pc/devi82365.c 1994/1210
## diff -e /n/fornaxdump/1994/1209/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1994/1210/sys/src/brazil/pc/devi82365.c
319c
pp->mmap[i].isa = getisa(0, Mchunk, BY2PG);
if(pp->mmap[i].isa == 0)
panic("getmap");
.
## diffname pc/devi82365.c 1994/1211
## diff -e /n/fornaxdump/1994/1210/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1994/1211/sys/src/brazil/pc/devi82365.c
848,850d
## diffname pc/devi82365.c 1995/0107
## diff -e /n/fornaxdump/1994/1211/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0107/sys/src/brazil/pc/devi82365.c
271c
x = vcode(5) | (vcode(5)<<2);
wrreg(pp, Rpc, x|Fautopower);
.
266a
int x;
.
## diffname pc/devi82365.c 1995/0108
## diff -e /n/fornaxdump/1995/0107/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devi82365.c
764a
}
long
i82365bwrite(Chan *c, Block *bp, ulong offset)
{
return devbwrite(c, bp, offset);
.
714a
Block*
i82365bread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
.
## diffname pc/devi82365.c 1995/0111
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0111/sys/src/brazil/pc/devi82365.c
1160a
}
void
tvers1(Slot *pp, int ttype)
{
uchar c, major, minor;
int i;
USED(ttype);
if(readc(pp, &major) != 1)
return;
if(readc(pp, &minor) != 1)
return;
for(i = 0; i < sizeof(pp->verstr)-1; i++){
if(readc(&c) != 1)
return;
if(c == 0)
c = '\n';
if(c == 0xff)
break;
pp->verstr[i] = c;
}
pp->verstr[i] = 0;
.
855a
[0x15] tvers1,
.
852a
static void tvers1(Slot*, int);
.
399c
return pp->verstr;
.
396c
return 0;
.
392c
return 0;
.
389c
return 0;
.
382c
char*
.
153a
uchar verstr[512]; /* version string */
.
## diffname pc/devi82365.c 1995/0114
## diff -e /n/fornaxdump/1995/0111/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0114/sys/src/brazil/pc/devi82365.c
1074,1078c
for(i = (c&0xf)+1; i; i--){
address = getlong(pp, (c>>4)&0x3);
len = getlong(pp, (c>>6)&0x3);
USED(address, len);
.
1071,1072c
if(readc(pp, &c) != 1)
return;
.
1066,1069c
pp->nioregs = 1<<(c&0x1f);
pp->bit16 = ((c>>5)&3) >= 2;
if((c & 0x80) == 0)
return;
.
1062,1064c
if(readc(pp, &c) != 1)
return;
.
## diffname pc/devi82365.c 1995/0117
## diff -e /n/fornaxdump/1995/0114/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0117/sys/src/brazil/pc/devi82365.c
1176c
if(readc(pp, &c) != 1)
.
154c
char verstr[512]; /* version string */
.
## diffname pc/devi82365.c 1995/0118
## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0118/sys/src/brazil/pc/devi82365.c
818c
isa->port = 0x300;
.
## diffname pc/devi82365.c 1995/0131
## diff -e /n/fornaxdump/1995/0118/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0131/sys/src/brazil/pc/devi82365.c
1052c
pp->otherwait = ttiming(pp, i); /* reserved wait */
.
1049c
pp->readywait = ttiming(pp, i); /* max ready/busy wait */
.
1046c
pp->maxwait = ttiming(pp, i); /* max wait */
.
165a
ulong maxwait;
ulong readywait;
ulong otherwait;
.
## diffname pc/devi82365.c 1995/0209
## diff -e /n/fornaxdump/1995/0131/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0209/sys/src/brazil/pc/devi82365.c
769a
qunlock(&pp->mlock);
if(n < 0)
error(Eio);
.
768a
qlock(&pp->mlock);
.
752d
737d
690a
qunlock(&pp->mlock);
if(n < 0)
error(Eio);
.
689a
qlock(&pp->mlock);
.
673d
656d
383c
unlock(pp);
.
380c
lock(pp);
.
374c
unlock(pp);
.
371c
lock(pp);
.
327,328c
if(pp->mmap[i].isa == 0)
panic("getmap");
}
.
325c
for(i = 0; i < Nmap; i++){
.
170a
QLock mlock; /* lock down the maps */
.
132a
Lock;
.
120d
## diffname pc/devi82365.c 1995/0215
## diff -e /n/fornaxdump/1995/0209/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0215/sys/src/brazil/pc/devi82365.c
689a
pp = slot + DEV(c);
.
193a
microdelay(10);
.
192a
microdelay(10);
.
187a
microdelay(10);
.
186a
microdelay(10);
.
## diffname pc/devi82365.c 1995/0222
## diff -e /n/fornaxdump/1995/0215/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0222/sys/src/brazil/pc/devi82365.c
919,921c
pp->cispos = this + (2+link);
.
906c
if(m == 0)
return;
pp->cisbase = (uchar*)(KZERO|m->isa);
pp->cispos = 0;
.
904d
894,895c
int this, i;
PCMmap *m;
.
891d
882,884c
*x = pp->cisbase[2*pp->cispos];
pp->cispos++;
.
880c
if(pp->cispos >= Mchunk)
.
857c
delay(5);
.
848c
delay(5);
.
845c
delay(5);
.
823c
x = vcode(pp->vpp1);
.
788,793d
777c
n = pcmwrite(pp->slotno, p == Qattr, a, n, offset);
.
773c
pp = slot + SLOTNO(c);
.
756c
memmoveb((void*)ka, ac, i);
.
731c
return devbwrite(c, bp, offset);
.
728,729c
long
i82365bwrite(Chan *c, Block *bp, ulong offset)
.
718a
{
int i;
cp += sprint(cp, "x %x d %x b %x\n", pp->cp->xreg, pp->cp->dreg, pp->base);
for(i = 0; i < 0x40; i++){
cp += sprint(cp, "%2.2ux ", rdreg(pp, i));
if((i%8) == 7)
cp += sprint(cp, "\n");
}
if(i%8)
cp += sprint(cp, "\n");
}
.
710,711d
703c
pp = slot + SLOTNO(c);
.
696c
n = pcmread(SLOTNO(c), p==Qattr, a, n, offset);
.
694c
pp = slot + SLOTNO(c);
.
684c
char *cp, buf[2048];
.
680a
Block*
i82365bread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
.
674c
memmoveb(ac, (void*)ka, i);
.
659c
pp = slot + slotno;
.
651c
pcmread(int slotno, int attr, void *a, long n, ulong offset)
.
631a
/* a memmove using only bytes */
static void
memmoveb(uchar *to, uchar *from, int n)
{
while(n-- > 0)
*to++ = *from++;
}
.
627,629c
if(c->flag & COPEN)
if(c->qid.path != CHDIR)
decrefp(slot+SLOTNO(c));
.
596c
increfp(slot + SLOTNO(c));
.
557a
/* for card management interrupts */
setvec(PCMCIAvec, i82365intr, 0);
.
554c
slotdis(lastslot);
.
550c
lastslot->slotno = lastslot - slot;
.
540a
i82386probe(0x3E2, 0x3E3, 0);
i82386probe(0x3E2, 0x3E3, 1);
.
462,463c
qid.path = QID(slotno, Qctl);
sprint(name, "pcm%dctl", slotno);
.
457,458c
qid.path = QID(slotno, Qattr);
sprint(name, "pcm%dattr", slotno);
.
452,453c
qid.path = QID(slotno, Qmem);
sprint(name, "pcm%dmem", slotno);
.
447,448c
slotno = i/3;
pp = slot + slotno;
.
438c
int slotno;
.
432,433c
#define SLOTNO(c) ((c->qid.path>>8)&0xff)
#define TYPE(c) (c->qid.path&0xff)
#define QID(s,t) (((s)<<8)|(t))
.
419c
pp = slot + slotno;
.
417c
if(slotno >= nslot)
.
413c
pcmspecialclose(int slotno)
.
408,409c
return -1;
.
406d
398,404c
for(pp = slot; pp < lastslot; pp++){
if(pp->special)
continue; /* already taken */
increfp(pp);
if(pp->occupied)
if(strstr(pp->verstr, idstr))
if(isa == 0 || pcmio(pp->slotno, isa) == 0){
pp->special = 1;
return pp->slotno;
}
.
395a
extern char *strstr(char*, char*);
.
392,393c
/*
* look for a card whose version contains 'idstr'
*/
int
pcmspecial(char *idstr, ISAConf *isa)
.
364c
wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) | Ftimer1);
.
300,309c
if(csc & (1<<3) && was != pp->occupied){
if(pp->occupied)
print("slot%d card inserted\n", pp->slotno);
else {
print("slot%d card removed\n", pp->slotno);
.
298a
was = pp->occupied;
.
296c
USED(ur,a);
if(slot == 0)
return;
.
293c
uchar csc, was;
.
291c
i82365intr(Ureg *ur, void *a)
.
276,283c
wrreg(pp, Rmisc2, Flowpow); /* low power mode */
wrreg(pp, Rpc, vcode(5)|Fautopower); /* turn off card */
wrreg(pp, Rwe, 0); /* no windows */
.
267c
} else
wrreg(pp, Rpc, vcode(5)|Fautopower);
pp->enabled = 1;
.
262,265c
if(pp->configed)
wrreg(pp, Rpc, vcode(pp->vpp1)|Fautopower|Foutena|Fcardena);
.
256,258d
247,252d
244,245c
/* enable the card */
wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena);
delay(300); /* give the card time to sit up and take notice */
wrreg(pp, Rigc, 0);
delay(100);
wrreg(pp, Rigc, Fnotreset);
delay(100);
wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena);
.
239,240d
215,217d
197d
195d
189d
187d
179a
static void i82365intr(Ureg*, void*);
.
164,165c
int cispos; /* current position scanning cis */
uchar *cisbase;
.
150d
138c
uchar slotno; /* slot number */
.
80c
Fregactive= (1<<6), /* attribute memory */
.
77c
Ftimer1= (1<<6), /* timer set 1 */
.
74a
F16bit= (1<<7), /* 16-bit wide data path */
.
66a
Flowpow= (1<<1), /* low power mode */
.
18c
* Intel 82365SL PCIC controller for the PCMCIA or
.
## diffname pc/devi82365.c 1995/0223
## diff -e /n/fornaxdump/1995/0222/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0223/sys/src/brazil/pc/devi82365.c
1173c
irq(pp, ct);
.
1171c
iospaces(pp, ct);
.
1169c
timing(pp, ct);
.
1162,1163c
ct->vpp1 = power(pp);
ct->vpp2 = power(pp);
.
1158c
ct->vpp1 = ct->vpp2 = power(pp);
.
1154c
ct->vpp1 = ct->vpp2 = power(pp);
.
1149a
.
1148c
ct->memwait = 1;
.
1142,1143c
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;
/* memory wait specified? */
.
1139a
if(pp->nctab >= Maxctab)
return;
.
1137a
Conftab *ct;
.
1117c
ct->irqs = 1<<(c&0xf);
.
1115c
ct->irqs = getlong(pp, 2);
.
1108c
irq(Slot *pp, Conftab *ct)
.
1103c
USED(len);
.
1101c
ct->port = getlong(pp, (c>>4)&0x3);
.
1092,1093c
ct->nioregs = 1<<(c&0x1f);
ct->bit16 = ((c>>5)&3) >= 2;
.
1087c
ulong len;
.
1083c
iospaces(Slot *pp, Conftab *ct)
.
1079c
ct->otherwait = ttiming(pp, i); /* reserved wait */
.
1076c
ct->readywait = ttiming(pp, i); /* max ready/busy wait */
.
1073c
ct->maxwait = ttiming(pp, i); /* max wait */
.
1065c
timing(Slot *pp, Conftab *ct)
.
914,915c
pp->configed = 0;
pp->nctab = 0;
.
910,911c
memset(pp->ctab, 0, sizeof(pp->ctab));
.
870c
if(isa->irq > 7)
x = Clevel | ct->index;
else
x = ct->index;
.
851,852c
wrreg(pp, Riotop0lo, (isa->port+ct->nioregs));
wrreg(pp, Riotop0hi, (isa->port+ct->nioregs)>>8);
.
842c
if(ct->bit16)
.
838c
x = vcode(ct->vpp1);
.
833,834d
830c
print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct->vpp1, ct->bit16, ct->nioregs);
/* route interrupts */
.
826,827c
/* find a configuration with the right port */
for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++)
if(ct->nioregs && ct->port == isa->port)
break;
/* if non found, settle for one with the some ioregs */
if(ct == &pp->ctab[pp->nctab])
for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++)
if(ct->nioregs)
break;
if(ct == &pp->ctab[pp->nctab])
.
817a
Conftab *ct;
.
552a
/* get ISA address space for memory maps */
for(i = 0; i < Nmap; i++)
for(pp = slot; pp < lastslot; pp++){
pp->mmap[i].isa = getisa(0, Mchunk, BY2PG);
if(pp->mmap[i].isa == 0)
break;
pp->nmap++;
}
.
544,549c
pp = lastslot++;
pp->slotno = pp - slot;
pp->memlen = 64*MB;
pp->base = (cp->dev<<7) | (j<<6);
pp->cp = cp;
slotdis(pp);
/* interrupt on status change */
wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena);
.
524a
Slot *pp;
.
511a
/* low power mode */
outb(x, Rmisc2 + (dev<<7));
outb(d, Flowpow);
.
348c
wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) /*| Ftimer1/**/);
.
325c
for(m = pp->mmap; m < &pp->mmap[pp->nmap]; m++){
.
310,320d
266,267c
wrreg(pp, Rpc, Fautopower); /* turn off card */
.
256,257c
wrreg(pp, Rpc, Fautopower);
.
250,254c
pp->enabled = 1;
.
246c
/* get configuration */
.
243,244c
delay(500);
.
237,239c
/* power up and reset, wait's are empirical (???) */
wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
delay(300);
.
174c
PCMmap mmap[Nmap]; /* maps, last is always for the kernel */
int nmap; /* number of maps */
.
167,169d
164a
int nctab; /* number of config table entries */
Conftab ctab[Maxctab];
Conftab *def; /* default conftab */
/* for walking through cis */
.
162,163d
156,160d
145d
131c
/* configuration table entry */
struct Conftab
{
int index;
ushort irqs; /* legal irqs */
ushort port; /* port address */
uchar nioregs; /* number of io registers */
uchar bit16; /* true for 16 bit access */
uchar vpp1;
uchar vpp2;
uchar memwait;
ulong maxwait;
ulong readywait;
ulong otherwait;
};
/* a card slot */
.
101a
typedef struct Conftab Conftab;
.
94a
Maxctab= 8, /* maximum configuration table entries */
.
## diffname pc/devi82365.c 1995/0225
## diff -e /n/fornaxdump/1995/0223/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0225/sys/src/brazil/pc/devi82365.c
961a
pcmunmap(pp->slotno, m);
.
943c
m = pcmmap(pp->slotno, 0, 0, 1);
.
899a
pcmunmap(slotno, m);
.
897,898c
*p = ct->index;
.
895c
*p = Clevel | ct->index;
.
885,886c
*p = 0;
.
882,883c
m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca));
*p = Creset;
.
871c
isa->port = ct->port;
.
861c
/* set power and enable slotnoice */
.
854,855d
843a
}
.
841c
for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++){
.
835c
pp = slot + slotno;
.
833c
if(slotno > nslot)
.
831a
PCMmap *m;
.
829c
uchar we, x, *p;
.
826,827c
static int
pcmio(int slotno, ISAConf *isa)
.
812d
810d
793a
poperror();
.
790a
pcmunmap(pp->slotno, m);
.
789c
ka = KZERO|(m->isa + offset - m->ca);
.
784c
m = pcmmap(pp->slotno, offset, 0, attr);
if(m == 0)
error("can't map PCMCIA card");
.
782a
m = 0;
if(waserror()){
if(m)
pcmunmap(pp->slotno, m);
nexterror();
}
ac = a;
.
780d
768c
static long
.
718,724c
return pcmread(SLOTNO(c), p==Qattr, a, n, offset);
.
695a
poperror();
.
692a
pcmunmap(pp->slotno, m);
.
691c
ka = KZERO|(m->isa + offset - m->ca);
.
684,686c
m = pcmmap(pp->slotno, offset, 0, attr);
if(m == 0)
error("can't map PCMCIA card");
.
682a
m = 0;
if(waserror()){
if(m)
pcmunmap(pp->slotno, m);
nexterror();
}
ac = a;
.
680d
668c
static long
.
557,565d
353a
void
pcmunmap(int slotno, PCMmap* m)
{
Slot *pp;
pp = slot + slotno;
lock(&pp->mlock);
m->ref--;
unlock(&pp->mlock);
}
.
350a
m->ref = 1;
unlock(&pp->mlock);
.
347c
offset >>= Mshift;
.
341,344c
wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
.
337,338c
i = m-pp->mmap;
.
335c
m->cea = m->ca + m->len;
.
331,333c
/* if isa space isn't big enough, free it and get more */
if(m->len < len){
if(m->isa){
putisa(m->isa, m->len);
m->len = 0;
}
m->isa = getisa(0, len, Mgran)&~KZERO;
if(m->isa == 0){
print("pcmmap: out of isa space\n");
unlock(&pp->mlock);
return 0;
}
m->len = len;
}
/* set up new map */
.
329a
m = nm;
if(m == 0){
unlock(&pp->mlock);
return 0;
}
.
327,328c
if(nm == 0 && m->ref == 0)
nm = m;
.
320,323c
nm = 0;
for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){
if((we & bit))
if(m->attr == attr)
if(offset >= m->ca && e <= m->cea){
m->ref++;
unlock(&pp->mlock);
.
317c
pp = slot + slotno;
lock(&pp->mlock);
/* convert offset to granularity */
if(len <= 0)
len = 1;
e = ROUND(offset+len, Mgran);
offset &= Mmask;
len = e - offset;
/* look for a map that covers the right area */
.
315a
ulong e;
.
314c
PCMmap *m, *nm;
.
312a
Slot *pp;
.
310,311c
PCMmap*
pcmmap(int slotno, ulong offset, int len, int attr)
.
306a
enum
{
Mshift= 12,
Mgran= (1<<Mshift), /* granularity of maps */
Mmask= ~(Mgran-1), /* mask for address bits important to the chip */
};
.
194,195c
static void cisread(Slot*);
static void i82365intr(Ureg*, void*);
static int pcmio(int, ISAConf*);
static long pcmread(int, int, void*, long, ulong);
static long pcmwrite(int, int, void*, long, ulong);
.
188d
185c
Lock mlock; /* lock down the maps */
.
106,115d
103d
## diffname pc/devi82365.c 1995/0328
## diff -e /n/fornaxdump/1995/0225/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0328/sys/src/brazil/pc/devi82365.c
1308a
.
951a
} else i82365dump(pp);
.
941,946c
}
/* set configuration */
if(strstr(pp->verstr, "KeepInTouch") == 0){
.
936a
if(strstr(pp->verstr, "KeepInTouch") == 0){
.
783,794d
596a
*/
.
595a
if(pp == slot)i82365dump(pp);
/*
.
561a
static void
i82365dump(Slot *pp)
{
int i;
for(i = 0; i < 0x40; i++){
if((i&0x7) == 0)
print("\n%ux: ", i);
print("%ux ", rdreg(pp, i));
}
print("\n");
}
.
## diffname pc/devi82365.c 1995/0329
## diff -e /n/fornaxdump/1995/0328/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0329/sys/src/brazil/pc/devi82365.c
1274c
switch((feature>>5)&0x3){
.
1197a
ct->irqtype = c & 0xe0;
.
1124c
if(feature & 0x40)
.
1076,1077c
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);
}
.
1072c
exp = vexp[c&0x7];
microvolts = vmant[(c>>3)&0xf]*exp;
.
1068a
ulong exp;
.
955c
.
948,953c
/* set configuration and interrupt type */
x = ct->index;
if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7))
x |= Clevel;
*p = x|ct->index;
.
941,946d
932,933c
wrreg(pp, Riotop0lo, (isa->port+ct->nioregs-1));
wrreg(pp, Riotop0hi, (isa->port+ct->nioregs-1)>>8);
.
924c
x = Fiocs16|Fwidth16;
else
x = 0;
wrreg(pp, Rio, Ftiming|x);
.
918c
/* set power and enable device */
.
798a
{
int i;
for(i = 0; i < 0x40; i++){
if((i&0x7) == 0)
cp += sprint(cp, "\n%ux: ", i);
cp += sprint(cp, "%ux ", rdreg(pp, i));
}
cp += sprint(cp, "\n");
}
.
612d
609,610d
265,266c
wrreg(pp, Rwe, 0); /* no windows */
wrreg(pp, Rpc, 0); /* turn off card power */
.
256c
wrreg(pp, Rpc, 0);
.
249a
wrreg(pp, Rpc, 0);
delay(500);
wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
delay(300);
wrreg(pp, Rigc, Fnotreset);
delay(500);
.
245,246d
242c
/* power up and unreset, wait's are empirical (???) */
.
128a
uchar irqtype;
.
43a
Fwidth16= (1<<0), /* 16 bit data width */
Fiocs16= (1<<1), /* IOCS16 determines data width */
Ftiming= (1<<3), /* timing register to use */
.
## diffname pc/devi82365.c 1995/0331
## diff -e /n/fornaxdump/1995/0329/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0331/sys/src/brazil/pc/devi82365.c
1309c
for(i = 0; i <= (c&0x7); i++)
.
275,276c
wrreg(pp, Rpc, 0); /* turn off card power */
wrreg(pp, Rwe, 0); /* no windows */
.
266c
wrreg(pp, Rpc, Fautopower);
.
252,259d
248a
wrreg(pp, Rigc, 0);
delay(100);
.
## diffname pc/devi82365.c 1995/0401
## diff -e /n/fornaxdump/1995/0331/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0401/sys/src/brazil/pc/devi82365.c
1220a
ct->irqs &= 0xDEB8; /* levels available to card */
.
960c
*p = x;
.
925,927c
isa->irq = irq;
wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
.
918c
if(ct->nioregs && ((1<<irq) & ct->irqs))
.
911c
if(ct->nioregs && ct->port == isa->port && ((1<<irq) & ct->irqs))
.
901a
irq = isa->irq;
if(irq == 2)
irq = 9;
.
900a
int irq;
.
## diffname pc/devi82365.c 1995/0519
## diff -e /n/fornaxdump/1995/0401/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0519/sys/src/brazil/pc/devi82365.c
874a
case Qctl:
if(n >= sizeof(buf))
n = sizeof(buf) - 1;
strncpy(buf, a, n);
buf[n] = 0;
pp = slot + SLOTNO(c);
if(!pp->occupied)
error(Eio);
/* set vpp on card */
if(strncmp(buf, "vpp", 3) == 0)
wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena);
break;
.
871a
char buf[32];
.
## diffname pc/devi82365.c 1995/0726
## diff -e /n/fornaxdump/1995/0519/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devi82365.c
684d
682c
i82365wstat(Chan*, char*)
.
677d
675c
i82365remove(Chan*)
.
670d
668c
i82365create(Chan*, char*, int, ulong)
.
## diffname pc/devi82365.c 1995/1006
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1006/sys/src/brazil/pc/devi82365.c
298a
if(changed)
break;
delay(100);
.
287,296c
changed = 0;
for(tries = 0; tries < 5; tries++){
for(pp = slot; pp < lastslot; pp++){
csc = rdreg(pp, Rcsc);
was = pp->occupied;
slotinfo(pp);
if(csc & (1<<3) && was != pp->occupied){
changed++;
if(pp->occupied)
print("slot%d card inserted\n", pp->slotno);
else {
print("slot%d card removed\n", pp->slotno);
slotdis(pp);
}
.
279a
int tries, changed;
.
## diffname pc/devi82365.c 1995/1007
## diff -e /n/fornaxdump/1995/1006/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1007/sys/src/brazil/pc/devi82365.c
304,306d
288,301c
for(pp = slot; pp < lastslot; pp++){
csc = rdreg(pp, Rcsc);
was = pp->occupied;
slotinfo(pp);
if(csc & (1<<3) && was != pp->occupied){
if(pp->occupied)
print("slot%d card inserted\n", pp->slotno);
else {
print("slot%d card removed\n", pp->slotno);
slotdis(pp);
.
280d
## diffname pc/devi82365.c 1995/1017
## diff -e /n/fornaxdump/1995/1007/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1017/sys/src/brazil/pc/devi82365.c
937c
if(ct == et || ct->nioregs == 0)
.
935a
}
}
if(ct->nioregs == 0 || ((1<<irq) & ct->irqs) == 0){
for(t = pp->ctab; t < et; t++)
if(t->nioregs && ((1<<irq) & t->irqs)){
ct = t;
break;
}
}
if(ct->nioregs == 0){
for(t = pp->ctab; t < et; t++)
if(t->nioregs){
ct = t;
break;
}
}
.
931,934c
/* assume default is right */
if(pp->def)
ct = pp->def;
else
ct = pp->ctab;
/* try for best match */
if(ct->nioregs == 0 || ct->port != isa->port || ((1<<irq) & ct->irqs) == 0){
for(t = pp->ctab; t < et; t++)
if(t->nioregs && t->port == isa->port && ((1<<irq) & t->irqs)){
ct = t;
.
925,929c
et = &pp->ctab[pp->nctab];
.
910c
Conftab *ct, *et, *t;
.
541,546c
if((c & 0xc0) != 0xc0)
break;
c = inb(d);
if((c & 0xc0) != 0x00)
break;
if(c & 0x20){
.
## diffname pc/devi82365.c 1995/1027
## diff -e /n/fornaxdump/1995/1017/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1027/sys/src/brazil/pc/devi82365.c
297d
292,295c
if(!pp->occupied)
.
## diffname pc/devi82365.c 1995/1121
## diff -e /n/fornaxdump/1995/1027/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1121/sys/src/brazil/pc/devi82365.c
1341c
static void
.
1268c
static void
.
## diffname pc/devi82365.c 1996/0303
## diff -e /n/fornaxdump/1995/1121/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1996/0303/sys/src/brazil/pc/devi82365.c
190a
void i82365reset(void);
.
8d
## diffname pc/devi82365.c 1996/0604
## diff -e /n/fornaxdump/1996/0303/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1996/0604/sys/src/brazil/pc/devi82365.c
900c
* configuration info from the CIS. If not, we won't set up correctly.
.
613a
rdreg(pp, Rcsc);
.
569,571c
if((i&0x0F) == 0)
print("\n%2.2uX: ", i);
if(((i+1) & 0x0F) == 0x08)
print(" - ");
print("%2.2uX ", rdreg(pp, i));
.
557c
c = inb(d);
outb(d, c & ~Flowpow);
.
551a
if(cp->type == Ti82365){
outb(x, 0x0E + (dev<<7));
outb(x, 0x37 + (dev<<7));
outb(x, 0x3A + (dev<<7));
c = inb(d);
outb(d, c|0xC0);
outb(x, Rid + (dev<<7));
c = inb(d);
print("ctlr id %uX\n", c & 0xFF);
if(c & 0x08)
cp->type = Tvg46x;
outb(x, 0x3A + (dev<<7));
c = inb(d);
outb(d, c & ~0xC0);
}
.
510a
[Tvg46x] "Vadem VG-46x",
.
191a
static void i82365dump(Slot*);
.
112a
Tvg46x,
.
## diffname pc/devi82365.c 1996/0613
## diff -e /n/fornaxdump/1996/0604/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1996/0613/sys/src/brazil/pc/devi82365.c
1070a
break;
if(type == 0xFF)
.
977a
if(isa->port == 0 && ct->port == 0)
return -1;
.
968,974d
961,966c
if(ct == 0){
/* assume default is right */
if(pp->def)
ct = pp->def;
else
ct = pp->ctab;
/* try for best match */
if(ct->nioregs == 0 || ct->port != isa->port || ((1<<irq) & ct->irqs) == 0){
for(t = pp->ctab; t < et; t++)
if(t->nioregs && t->port == isa->port && ((1<<irq) & t->irqs)){
ct = t;
break;
}
}
if(ct->nioregs == 0 || ((1<<irq) & ct->irqs) == 0){
for(t = pp->ctab; t < et; t++)
if(t->nioregs && ((1<<irq) & t->irqs)){
ct = t;
break;
}
}
if(ct->nioregs == 0){
for(t = pp->ctab; t < et; t++)
if(t->nioregs){
ct = t;
break;
}
}
.
947,959c
ct = 0;
for(i = 0; i < isa->nopt; i++){
if(strncmp(isa->opt[i], "index=", 6))
continue;
index = strtol(&isa->opt[i][6], &cp, 0);
if(cp == &isa->opt[i][6] || index >= pp->nctab)
return -1;
ct = &pp->ctab[index];
.
932c
int i, index, irq;
char *cp;
.
## diffname pc/devi82365.c 1997/0327
## diff -e /n/fornaxdump/1996/0613/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devi82365.c
1255c
static void
.
920a
Dev i82365devtab = {
i82365reset,
devinit,
i82365attach,
devclone,
i82365walk,
i82365stat,
i82365open,
devcreate,
i82365close,
i82365read,
devbread,
i82365write,
devbwrite,
devremove,
devwstat,
};
.
884c
static long
.
836,841d
781,787c
static long
.
687,705c
static void
.
673c
static Chan*
.
667c
static void
.
655,661c
static int
.
644,649c
static Chan*
.
641c
intrenable(VectorPCMCIA, i82365intr, 0, BUSUNKNOWN);
.
635c
wrreg(pp, Rcscic, ((VectorPCMCIA-VectorPIC)<<4) | Fchangeena);
.
601c
static void
.
402d
359c
m->isa = umbmalloc(0, len, Mgran)&~KZERO;
.
356c
umbfree(m->isa, m->len);
.
192d
187a
static void i82365reset(void);
.
## diffname pc/devi82365.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devi82365.c
879a
'y',
"i82365",
.
## diffname pc/devi82365.c 1997/0522
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/0522/sys/src/brazil/pc/devi82365.c
640c
if(ncontroller)
intrenable(VectorPCMCIA, i82365intr, 0, BUSUNKNOWN);
.
## diffname pc/devi82365.c 1997/1101
## diff -e /n/emeliedump/1997/0522/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/1101/sys/src/brazil/pc/devi82365.c
359a
print("m->isa = 0x%uX, %d\n", m->isa, len);
.
## diffname pc/devi82365.c 1998/0221
## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0221/sys/src/brazil/pc/devi82365.c
360d
133c
ulong nioregs; /* number of io registers */
.
## diffname pc/devi82365.c 1998/0312
## diff -e /n/emeliedump/1998/0221/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0312/sys/src/brazil/pc/devi82365.c
1384d
1059c
pp->cisbase = KADDR(m->isa);
.
1003c
p = KADDR(m->isa + pp->caddr + Rconfig - m->ca);
.
877c
error(Ebadarg);
return -1; /* not reached */
.
873,875c
return n;
.
870c
n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, offset);
.
864c
return n;
.
850,851c
switch(TYPE(c)){
.
846d
832,833c
memmoveb(KADDR(m->isa + offset - m->ca), ac, i);
.
806d
792,799d
790c
error(Ebadarg);
return -1; /* not reached */
.
785,788c
n = readstr(offset, a, n, p);
free(p);
return n;
.
780,783c
len += snprint(p+len, READSTR-len, "busy\n");
snprint(p+len, READSTR-len, "battery lvl %d\n", pp->battery);
.
778c
len += snprint(p+len, READSTR-len, "write protected\n");
.
776c
len += snprint(p+len, READSTR-len, "configed\n");
.
774c
len += snprint(p+len, READSTR-len, "powered\n");
.
772c
len += snprint(p+len, READSTR-len, "enabled\n");
.
770c
len += snprint(p+len, READSTR-len, "occupied\n");
.
768a
.
767c
p = malloc(READSTR);
len = 0;
.
765c
return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, offset);
.
759,760c
switch(TYPE(c)){
.
755,756c
char *p;
int len;
.
741,742c
memmoveb(ac, KADDR(m->isa + offset - m->ca), i);
.
715d
570,571c
print("#y%d: %d slot %s\n", ncontroller, cp->nslot, chipname[cp->type]);
.
562c
if(c != id && !(c & 0x08))
print("#y%d: id %uX changed to %uX\n", ncontroller, id, c);
.
535a
case 0x84:
.
533c
switch(id){
.
522,523c
id = inb(d);
if((id & 0xf0) != 0x80)
.
518c
uchar c, id;
.
359c
m->isa = PADDR(umbmalloc(0, len, Mgran));
.
## diffname pc/devi82365.c 1998/0317
## diff -e /n/emeliedump/1998/0312/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0317/sys/src/brazil/pc/devi82365.c
642c
intrenable(vector, i82365intr, 0, BUSUNKNOWN);
.
635c
wrreg(pp, Rcscic, ((vector-VectorPIC)<<4) | Fchangeena);
.
625a
print("#y%d: %d slot %s: port 0x%uX irq %d\n",
i, cp->nslot, chipname[cp->type], cp->xreg, vector-VectorPIC);
.
612a
memset(&isa, 0, sizeof(ISAConf));
vector = VectorPCMCIA;
if(isaconfig("pcmcia", 0, &isa) && isa.irq)
vector = VectorPIC+isa.irq;
.
607a
ISAConf isa;
.
605c
int i, j, vector;
.
572,573d
## diffname pc/devi82365.c 1998/0319
## diff -e /n/emeliedump/1998/0317/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devi82365.c
1360d
1355c
tvers1(Slot *pp, int )
.
1287,1288d
1282c
tentry(Slot *pp, int )
.
1094d
1089c
tcfig(Slot *pp, int )
.
842a
ulong offset = off;
.
839c
i82365write(Chan *c, void *a, long n, vlong off)
.
762a
ulong offset = off;
.
758c
i82365read(Chan *c, void *a, long n, vlong off)
.
480,481c
if(i >= 3*nslot)
.
472c
pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
.
286d
281c
i82365intr(Ureg *, void *)
.
## diffname pc/devi82365.c 1998/0327
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0327/sys/src/brazil/pc/devi82365.c
863c
n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off);
.
842d
803a
ulong offset = off;
.
798c
pcmwrite(int dev, int attr, void *a, long n, vlong off)
.
768c
return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off);
.
721a
ulong offset = off;
.
716c
pcmread(int slotno, int attr, void *a, long n, vlong off)
.
190,191c
static long pcmread(int, int, void*, long, vlong);
static long pcmwrite(int, int, void*, long, vlong);
.
## diffname pc/devi82365.c 1998/0811
## diff -e /n/emeliedump/1998/0327/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0811/sys/src/brazil/pc/devi82365.c
484c
switch(i%Nents){
.
481c
slotno = i/Nents;
.
479c
if(i >= Nents*nslot)
.
463a
Nents = 3,
.
## diffname pc/devi82365.c 1998/0910
## diff -e /n/emeliedump/1998/0811/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0910/sys/src/brazil/pc/devi82365.c
648c
intrenable(irq, i82365intr, 0, BUSUNKNOWN);
.
641c
wrreg(pp, Rcscic, (irq<<4) | Fchangeena);
.
631c
i, cp->nslot, chipname[cp->type], cp->xreg, irq);
.
615c
irq = isa.irq;
.
613c
irq = IrqPCMCIA;
.
603c
int i, j, irq;
.
## diffname pc/devi82365.c 1999/0303
## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/0303/sys/src/brazil/pc/devi82365.c
1251a
ct->nio = nio;
.
1247,1250c
nio = (c&0xf)+1;
for(i = 0; i < nio; i++){
ct->io[i].start = getlong(pp, (c>>4)&0x3);
ct->io[0].len = getlong(pp, (c>>6)&0x3);
.
1242a
}
.
1241c
if(!(c & 0x80)){
ct->io[0].start = 0;
ct->io[0].len = 1<<(c&0x1f);
ct->nio = 1;
.
1239d
1235a
ct->nio = 0;
.
1233,1234c
int i, nio;
.
990,992c
i = isa->port+ct->io[0].len-1;
wrreg(pp, Riotop0lo, i);
wrreg(pp, Riotop0hi, i>>8);
we |= 1<<6;
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;
wrreg(pp, Riotop1lo, i);
wrreg(pp, Riotop1hi, i>>8);
we |= 1<<7;
}
wrreg(pp, Rwe, we);
.
986c
isa->port = ct->io[0].start;
.
981,982c
x = Ftiming;
if(ct->nio == 2 && ct->io[1].start)
x |= x<<4;
wrreg(pp, Rio, x);
.
979c
x = Ftiming|Fiocs16|Fwidth16;
.
966c
if(isa->port == 0 && ct->io[0].start == 0)
.
964c
if(ct == et || ct->nio == 0)
.
957c
if(t->nio){
.
955c
if(ct->nio == 0){
.
950c
if(t->nio && ((1<<irq) & t->irqs)){
.
948c
if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
.
943c
if(t->nio
&& t->io[0].start == isa->port
&& ((1<<irq) & t->irqs)){
.
941c
if(ct->nio == 0
|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
.
134a
struct {
ulong start;
ulong len;
} io[16];
int nio;
.
133d
131d
44a
Fzerows= (1<<2), /* zero wait state */
.
## diffname pc/devi82365.c 1999/0714
## diff -e /n/emeliedump/1999/0303/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devi82365.c
621,625c
/* look for controllers if the ports aren't already taken */
if(ioalloc(0x3E0, 2, 0, "i82386.0") >= 0){
i82386probe(0x3E0, 0x3E1, 0);
i82386probe(0x3E0, 0x3E1, 1);
if(ncontroller == 0)
iofree(0x3E0);
}
if(ioalloc(0x3E2, 2, 0, "i82386.1") >= 0){
i = ncontroller;
i82386probe(0x3E2, 0x3E3, 0);
i82386probe(0x3E2, 0x3E3, 1);
if(ncontroller == i)
iofree(0x3E2);
}
.
## diffname pc/devi82365.c 1999/0819
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/0819/sys/src/brazil/pc/devi82365.c
661c
intrenable(irq, i82365intr, 0, BUSUNKNOWN, "i82365");
.
## diffname pc/devi82365.c 1999/1230
## diff -e /n/emeliedump/1999/0819/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/1230/sys/src/9/pc/devi82365.c
484a
if(i == DEVDOTDOT){
devdir(c, (Qid){CHDIR, 0}, "#y", 0, eve, 0555, dp);
return 1;
}
.
## diffname pc/devi82365.c 2000/0605
## diff -e /n/emeliedump/1999/1230/sys/src/9/pc/devi82365.c /n/emeliedump/2000/0605/sys/src/9/pc/devi82365.c
1402c
if(readc(cis, &c) != 1)
.
1399c
if(readc(cis, &minor) != 1)
.
1397c
if(readc(cis, &major) != 1)
.
1392c
tvers1(Slot *pp, Cisdat *cis, int )
.
1385c
memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
.
1382c
if(readc(cis, &c) != 1)
.
1379c
memspace(cis, 2, 2, 0);
.
1376c
memspace(cis, 0, 2, 0);
.
1373c
irq(cis, ct);
.
1371c
iospaces(cis, ct);
.
1369c
timing(cis, ct);
.
1361,1363c
power(cis);
ct->vpp1 = power(cis);
ct->vpp2 = power(cis);
.
1357,1358c
power(cis);
ct->vpp1 = ct->vpp2 = power(cis);
.
1354c
ct->vpp1 = ct->vpp2 = power(cis);
.
1350c
if(readc(cis, &feature) != 1)
.
1344c
if(readc(cis, &i) != 1)
.
1328c
if(readc(cis, &c) != 1)
.
1321c
tentry(Slot *pp, Cisdat *cis, int )
.
1315c
haddress = getlong(cis, asize)*256;
.
1311,1312c
len = getlong(cis, lsize)*256;
address = getlong(cis, asize)*256;
.
1307c
memspace(Cisdat *cis, int asize, int lsize, int host)
.
1300c
ct->irqs = getlong(cis, 2);
.
1296c
if(readc(cis, &c) != 1)
.
1292c
irq(Cisdat *cis, Conftab *ct)
.
1285,1286c
ct->io[i].start = getlong(cis, (c>>4)&0x3);
ct->io[0].len = getlong(cis, (c>>6)&0x3);
.
1280c
if(readc(cis, &c) != 1)
.
1269c
if(readc(cis, &c) != 1)
.
1263c
iospaces(Cisdat *cis, Conftab *ct)
.
1259c
ct->otherwait = ttiming(cis, i); /* reserved wait */
.
1256c
ct->readywait = ttiming(cis, i); /* max ready/busy wait */
.
1253c
ct->maxwait = ttiming(cis, i); /* max wait */
.
1249c
if(readc(cis, &c) != 1)
.
1245c
timing(Cisdat *cis, Conftab *ct)
.
1237c
if(readc(cis, &unscaled) != 1)
.
1232c
ttiming(Cisdat *cis, int scale)
.
1221c
nanoamps(cis);
.
1219c
nanoamps(cis);
.
1217c
nanoamps(cis);
.
1215c
nanoamps(cis);
.
1213c
microvolt(cis);
.
1211c
microvolt(cis);
.
1209c
mv = microvolt(cis);
.
1206c
if(readc(cis, &feature) != 1)
.
1200c
power(Cisdat *cis)
.
1188c
if(readc(cis, &c) != 1)
.
1184c
if(readc(cis, &c) != 1)
.
1179c
nanoamps(Cisdat *cis)
.
1161c
if(readc(cis, &c) != 1)
.
1156c
if(readc(cis, &c) != 1)
.
1150c
microvolt(Cisdat *cis)
.
1136,1137c
pp->caddr = getlong(cis, rasize);
pp->cpresent = getlong(cis, rmsize);
.
1134c
if(readc(cis, &last) != 1)
.
1130c
if(readc(cis, &size) != 1)
.
1125c
tcfig(Slot *pp, Cisdat *cis, int )
.
1117c
if(readc(cis, &c) != 1)
.
1109c
getlong(Cisdat *cis, int size)
.
1107a
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);
}
}
}
.
1105c
pcmunmap(slotno, m);
return -1;
.
1103c
if(type == tuple) {
p = v;
for(l=0; l<nv && l<link; l++)
if(readc(&cis, p++) != 1)
break;
pcmunmap(slotno, m);
return nv;
}
cis.cispos = this + (2+link);
.
1099,1101c
if(link == 0xFF)
.
1097c
if(readc(&cis, &link) != 1)
.
1092,1093c
this = cis.cispos;
if(readc(&cis, &type) != 1)
.
1089a
cis.cisbase = KADDR(m->isa);
cis.cispos = 0;
cis.cisskip = attr ? 2 : 1;
cis.cislen = Mchunk;
.
1086,1088c
return -1;
.
1078,1084c
m = pcmmap(slotno, 0, 0, attr);
.
1076a
Cisdat cis;
int i, l;
uchar *p;
uchar type, link;
int this;
.
1073,1075d
1070,1071c
static int
xcistuple(int slotno, int tuple, void *v, int nv, int attr)
.
1065c
*x = pp->cisbase[pp->cisskip*pp->cispos];
.
1063c
if(pp->cispos >= pp->cislen)
.
1061c
readc(Cisdat *pp, uchar *x)
.
1053,1057c
struct {
int n;
void (*parse)(Slot*, Cisdat*, int);
} cistab[] = {
0x15, tvers1,
0x1A, tcfig,
0x1B, tentry,
.
1049,1051c
static void tcfig(Slot*, Cisdat*, int);
static void tentry(Slot*, Cisdat*, int);
static void tvers1(Slot*, Cisdat*, int);
.
178,179c
Cisdat;
.
146a
/* cis memory walking */
struct Cisdat
{
uchar *cisbase;
int cispos;
int cisskip;
int cislen;
};
.
106a
typedef struct Cisdat Cisdat;
.
## diffname pc/devi82365.c 2000/1005
## diff -e /n/emeliedump/2000/0605/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1005/sys/src/9/pc/devi82365.c
673,675c
/* for card management interrupts */
sprint(buf, "i82365.%d", i);
intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf);
}
.
671d
668c
wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
.
658c
i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
.
644,645c
i82365probe(0x3E2, 0x3E3, 0);
i82365probe(0x3E2, 0x3E3, 1);
.
642c
if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){
.
636,638c
if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){
i82365probe(0x3E0, 0x3E1, 0);
i82365probe(0x3E0, 0x3E1, 1);
.
630,634d
624c
char buf[NAMELEN];
.
621c
int i, j;
.
594a
memset(&isa, 0, sizeof(ISAConf));
if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
cp->irq = isa.irq;
else
cp->irq = IrqPCMCIA;
for(i = 0; i < isa.nopt; i++){
if(cistrncmp(isa.opt[i], "nslot=", 6))
continue;
nslot = strtol(&isa.opt[i][6], nil, 0);
if(nslot > 0 && nslot <= 2)
cp->nslot = nslot;
}
print("%uX/%d: nslot = %d\n", x, dev, cp->nslot);
.
537a
ISAConf isa;
int i, nslot;
.
534c
i82365probe(int x, int d, int dev)
.
455a
print("not found\n");
.
453d
447,451c
if(pp->occupied) {
print("[%s] ", pp->verstr);
if(strstr(pp->verstr, idstr))
if(isa == 0 || pcmio(pp->slotno, isa) == 0){
pp->special = 1;
print("done\n");
return pp->slotno;
}
.
441a
print("Looking for %s ...", idstr);
.
276a
print("done-");
.
268a
print("...");
.
267a
print(">");
.
266a
print("<");
.
265a
print(">");
.
264a
print("<");
.
263a
print(">");
.
261a
print("-enabling<");
.
123a
int irq;
.
## diffname pc/devi82365.c 2000/1006
## diff -e /n/emeliedump/2000/1005/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1006/sys/src/9/pc/devi82365.c
623d
468d
465c
} else
pp->special = 1;
.
462d
458d
450,451c
if (! resetdone) {
i82365reset();
resetdone++;
}
.
448a
static int resetdone;
.
285d
276d
274d
272d
270d
268d
266d
263d
## diffname pc/devi82365.c 2000/1007
## diff -e /n/emeliedump/2000/1006/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1007/sys/src/9/pc/devi82365.c
443,446c
i82365reset();
.
## diffname pc/devi82365.c 2000/1021
## diff -e /n/emeliedump/2000/1007/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1021/sys/src/9/pc/devi82365.c
1164c
if((nv = pcmcistuple(pp->slotno, cistab[i].n, -1, v, sizeof(v))) >= 0) {
.
1147c
return xcistuple(slotno, tuple, subtuple, v, nv, 0);
.
1145c
if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
.
1140c
pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
.
1127c
for(l=0; l<nv && l<n; l++)
.
1125c
n = link;
if (link > 1 && subtuple != -1) {
if (readc(&cis, &c) != 1)
break;
subtype = c;
n--;
} else
subtype = -1;
if(type == tuple && subtype == subtuple) {
.
1102,1103c
uchar type, link, n, c;
int this, subtype;
.
1096c
xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
.
## diffname pc/devi82365.c 2000/1106
## diff -e /n/emeliedump/2000/1021/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1106/sys/src/9/pc/devi82365.c
458a
print("\n");
.
452a
print(" - found\n");
.
449a
print("[%8.8s]", pp->verstr);
.
443a
print("pcmcia: looking for %s: ", idstr);
.
## diffname pc/devi82365.c 2000/1107
## diff -e /n/emeliedump/2000/1106/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1107/sys/src/9/pc/devi82365.c
682a
pp->msec = ~0;
.
462d
460c
if (enabled)
decrefp(pp);
.
451,456c
if(strstr(pp->verstr, idstr)) {
if (!enabled)
increfp(pp);
if(isa == 0 || pcmio(pp->slotno, isa) == 0){
pp->special = 1;
return pp->slotno;
}
.
448c
enabled = 0;
/* make sure we don't power on cards when we already know what's
* in them. We'll reread every two minutes if necessary
*/
if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000) {
increfp(pp);
enabled++;
}
.
444d
441c
int enabled;
.
238a
pp->msec = TK2MS(MACHP(0)->ticks);
.
180a
ulong msec; /* time of last slotinfo call */
.
## diffname pc/devi82365.c 2000/1109
## diff -e /n/emeliedump/2000/1107/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1109/sys/src/9/pc/devi82365.c
1500a
print("pcmcia: %s\n", pp->verstr);
.
## diffname pc/devi82365.c 2000/1110
## diff -e /n/emeliedump/2000/1109/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1110/sys/src/9/pc/devi82365.c
1501d
## diffname pc/devi82365.c 2000/1111
## diff -e /n/emeliedump/2000/1110/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1111/sys/src/9/pc/devi82365.c
1030c
.
## diffname pc/devi82365.c 2000/1115
## diff -e /n/emeliedump/2000/1111/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1115/sys/src/9/pc/devi82365.c
671c
i82365probe(0x3E2, 0x3E3, 0) ||
.
664c
i82365probe(0x3E0, 0x3E1, 0) ||
.
## diffname pc/devi82365.c 2000/1116
## diff -e /n/emeliedump/2000/1115/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1116/sys/src/9/pc/devi82365.c
1185a
pp->verstr[0] = 0;
.
846,847c
n = readstr(offset, a, n, buf);
free(buf);
.
843,844c
p = seprint(p, e, "busy\n");
seprint(p, e, "battery lvl %d\n", pp->battery);
.
841c
p = seprint(p, e, "write protected\n");
.
839c
p = seprint(p, e, "configed\n");
.
837c
p = seprint(p, e, "powered\n");
.
835c
p = seprint(p, e, "enabled\n");
.
832,833c
buf[0] = 0;
if(pp->occupied){
p = seprint(p, e, "occupied\n");
if(pp->verstr[0])
p = seprint(p, e, "version %s\n", pp->verstr);
}
.
828,829c
buf = p = malloc(READSTR);
e = p + READSTR;
.
816,817c
char *p, *buf, *e;
.
692a
pp->verstr[0] = 0;
.
671c
i82365probe(0x3E2, 0x3E3, 0);
.
664c
i82365probe(0x3E0, 0x3E1, 0);
.
606a
#endif asdf
.
602a
/* go back to Intel compatible id */
.
599,600d
593a
/* make the id register show the Vadem id */
.
591a
/* unlock the Vadem extended regs */
.
590a
#ifdef adsf
/* if it's not a Cirrus, it could be a Vadem... */
.
560c
return 0; /* not a memory & I/O card */
if((id & 0x0f) == 0x00)
return 0; /* no revision number, not possible */
.
461a
}
.
459,460c
if(strstr(pp->verstr, idstr)){
if (!enabled){
enabled = 1;
.
453c
enabled = 0;
if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000){
.
449,451c
/*
* make sure we don't power on cards when we already know what's
* in them. We'll reread every two minutes if necessary
.
## diffname pc/devi82365.c 2000/1118
## diff -e /n/emeliedump/2000/1116/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1118/sys/src/9/pc/devi82365.c
1096,1518d
975,976c
PCMslot *pp;
PCMconftab *ct, *et, *t;
.
968c
* configure the PCMslot for IO. We assume very heavily that we can read
.
915c
PCMslot *pp;
.
877c
PCMslot *pp;
.
830c
PCMslot *pp;
.
791c
PCMslot *pp;
.
690c
slot = xalloc(nslot * sizeof(PCMslot));
.
667c
PCMslot *pp;
.
644c
i82365dump(PCMslot *pp)
.
618d
597d
511c
PCMslot *pp;
.
482c
PCMslot *pp;
.
441c
PCMslot *pp;
.
427c
decrefp(PCMslot *pp)
.
418c
increfp(PCMslot *pp)
.
409c
PCMslot *pp;
.
349c
for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
.
329c
PCMslot *pp;
.
300c
PCMslot *pp;
.
286c
slotdis(PCMslot *pp)
.
276c
pcmcisread(pp);
.
260c
slotena(PCMslot *pp)
.
230c
slotinfo(PCMslot *pp)
.
222,223c
outb(((I82365*)pp->cp)->xreg, pp->base + index);
outb(((I82365*)pp->cp)->dreg, val);
.
220c
wrreg(PCMslot *pp, int index, uchar val)
.
216,217c
outb(((I82365*)pp->cp)->xreg, pp->base + index);
return inb(((I82365*)pp->cp)->dreg);
.
214c
rdreg(PCMslot *pp, int index)
.
208c
static void i82365dump(PCMslot*);
.
201d
128,198c
static PCMslot *slot;
static PCMslot *lastslot;
.
105,107d
98,99d
87,90d
10c
* Support for up to 4 PCMslot card slots. Generalizing above that is hard
.
## diffname pc/devi82365.c 2001/0315
## diff -e /n/emeliedump/2000/1118/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0315/sys/src/9/pc/devi82365.c
297c
print("pcmmap: %d out of isa space\n", len);
.
## diffname pc/devi82365.c 2001/0517
## diff -e /n/emeliedump/2001/0315/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0517/sys/src/9/pc/devi82365.c
591a
/* First find Ricoh controllers on the PCI bus */
p = nil;
while ((p = pcimatch(p, Ricoh_vid, 0)) != nil) {
for (i = 0; i != nelem(variant); i++)
if (p->did == variant[i].r_did)
break;
if (i == nelem(variant)) {
print("No match on %.4X/%.4X\n", p->vid, p->did);
continue;
}
print("#y: %s, intl %d\n", variant[i].r_name, p->intl);
for (i = 0; i != 0xE4 / 4; i++)
iprint("pci[%.2X] %.8ulX\n", i * 4, pcicfgr32(p, i * 4));
break;
}
.
583a
Pcidev *p;
.
99a
enum {
Ricoh_vid = 0x1180,
Ricoh_476_did = 0x476,
};
static struct {
ushort r_did;
char *r_name;
} variant[] = {
{ Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", }
};
.
## diffname pc/devi82365.c 2001/0519
## diff -e /n/emeliedump/2001/0517/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0519/sys/src/9/pc/devi82365.c
605,622d
596d
100,111d
## diffname pc/devi82365.c 2001/0527
## diff -e /n/emeliedump/2001/0519/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0527/sys/src/9/pc/devi82365.c
872d
674c
if((c->qid.type & QTDIR) == 0)
.
659c
if(c->qid.type & QTDIR){
.
653c
return devstat(c, db, n, 0, 0, pcmgen);
.
650,651c
static int
i82365stat(Chan *c, uchar *db, int n)
.
647c
return devwalk(c, nc, name, nname, 0, 0, pcmgen);
.
644,645c
static Walkqid*
i82365walk(Chan *c, Chan *nc, char **name, int nname)
.
633c
snprint(buf, sizeof buf, "i82365.%d", i);
.
587c
char buf[32];
.
462c
devdir(c, qid, up->genbuf, len, eve, 0660, dp);
.
458c
snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
.
453c
snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
.
448c
snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
.
436c
mkqid(&qid, Qdir, 0, QTDIR);
devdir(c, qid, "#y", 0, eve, 0555, dp);
.
433d
427c
pcmgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
.
422,423c
#define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff))
#define TYPE(c) ((ulong)(c->qid.path&0xff))
.
297c
print("pcmmap: out of isa space\n");
.
## diffname pc/devi82365.c 2001/0529
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0529/sys/src/9/pc/devi82365.c
423c
#define TYPE(c) ((ulong)(c->qid.path&0xff))
.
## diffname pc/devi82365.c 2001/0619
## diff -e /n/emeliedump/2001/0529/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0619/sys/src/9/pc/devi82365.c
978c
/*
* enable io port map 0
* the 'top' register value includes the last valid address
*/
.
## diffname pc/devi82365.c 2001/0627
## diff -e /n/emeliedump/2001/0619/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0627/sys/src/9/pc/devi82365.c
461a
qid.type = QTFILE;
.
## diffname pc/devi82365.c 2001/0720
## diff -e /n/emeliedump/2001/0627/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0720/sys/src/9/pc/devi82365.c
539,543d
515a
/* low power mode */
outb(x, Rmisc2 + (dev<<7));
c = inb(d);
outb(d, c & ~Flowpow);
.
## diffname pc/devi82365.c 2001/0730
## diff -e /n/emeliedump/2001/0720/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0730/sys/src/9/pc/devi82365.c
573d
570a
print("%2.2uX ", rdreg(pp, i));
.
## diffname pc/devi82365.c 2001/0731
## diff -e /n/emeliedump/2001/0730/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0731/sys/src/9/pc/devi82365.c
612d
470,471c
[Tpd6710] "Cirrus Logic CL-PD6710",
[Tpd6720] "Cirrus Logic CL-PD6720",
.
161a
print("isr %2.2uX misc1 %2.2uX\n", isr, rdreg(pp, Rmisc1));
.
15,19d
10,13c
* Intel 82365SL PCIC controller and compatibles.
.
## diffname pc/devi82365.c 2001/0801
## diff -e /n/emeliedump/2001/0731/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0801/sys/src/9/pc/devi82365.c
154d
## diffname pc/devi82365.c 2001/0905
## diff -e /n/emeliedump/2001/0801/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0905/sys/src/9/pc/devi82365.c
580a
if (!getconf("pcmcia0"))
return;
if (_pcmspecial) {
print("#y: PCMCIA and CardBus at the same time?\n");
return;
}
_pcmspecial = pcmcia_pcmspecial;
_pcmspecialclose = pcmcia_pcmspecialclose;
.
392,393c
static void
pcmcia_pcmspecialclose(int slotno)
.
351,352c
static int
pcmcia_pcmspecial(char *idstr, ISAConf *isa)
.
## diffname pc/devi82365.c 2001/0906
## diff -e /n/emeliedump/2001/0905/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0906/sys/src/9/pc/devi82365.c
872c
devreset,
.
593,595d
581a
if(already)
return;
already = 1;
.
573,574c
void
devi82365link(void)
.
358d
116d
## diffname pc/devi82365.c 2002/0109
## diff -e /n/emeliedump/2001/0906/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0109/sys/src/9/pc/devi82365.c
872a
devshutdown,
.
## diffname pc/devi82365.c 2002/0110
## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0110/sys/src/9/pc/devi82365.c
1012c
if(ct->irqtype & 0x20)
.
1010c
/* set configuration and interrupt type.
* if level is possible on the card, use it.
*/
.
## diffname pc/devi82365.c 2002/0403
## diff -e /n/emeliedump/2002/0110/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0403/sys/src/9/pc/devi82365.c
594d
587,591d
584c
if(_pcmspecial)
.
## diffname pc/devi82365.c 2002/0414
## diff -e /n/emeliedump/2002/0403/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0414/sys/src/9/pc/devi82365.c
603a
if(ncontroller == 0)
return;
_pcmspecial = pcmcia_pcmspecial;
_pcmspecialclose = pcmcia_pcmspecialclose;
.
587,589d
## diffname pc/devi82365.c 2002/0502
## diff -e /n/emeliedump/2002/0414/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0502/sys/src/9/pc/devi82365.c
582a
if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
return;
.
578c
char buf[32], *p;
.
|