## diffname bitsy/devpcmcia.c 2000/1118
## diff -e /dev/null /n/emeliedump/2000/1118/sys/src/9/bitsy/devpcmcia.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"
static PCMslot slot[2];
int nslot = 2;
struct {
Ref;
} pcmcia;
enum
{
Qdir,
Qmem,
Qattr,
Qctl,
Nents = 3,
};
#define SLOTNO(c) ((c->qid.path>>8)&0xff)
#define TYPE(c) (c->qid.path&0xff)
#define QID(s,t) (((s)<<8)|(t))
static int
pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
{
int slotno;
Qid qid;
long len;
PCMslot *pp;
char name[NAMELEN];
if(i == DEVDOTDOT){
devdir(c, (Qid){CHDIR, 0}, "#y", 0, eve, 0555, dp);
return 1;
}
if(i >= Nents*nslot)
return -1;
slotno = i/Nents;
pp = slot + slotno;
len = 0;
switch(i%Nents){
case 0:
qid.path = QID(slotno, Qmem);
sprint(name, "pcm%dmem", slotno);
len = pp->memlen;
break;
case 1:
qid.path = QID(slotno, Qattr);
sprint(name, "pcm%dattr", slotno);
len = pp->memlen;
break;
case 2:
qid.path = QID(slotno, Qctl);
sprint(name, "pcm%dctl", slotno);
break;
}
qid.vers = 0;
devdir(c, qid, name, len, eve, 0660, dp);
return 1;
}
static void
slotinfo(void)
{
ulong x = gpioregs->level;
if(x & GPIO_OPT_IND_i){
/* no expansion pack */
slot[0].occupied = 0;
slot[1].occupied = 0;
} else {
slot[0].occupied = (x & GPIO_CARD_IND0_i) == 0;
slot[1].occupied = (x & GPIO_CARD_IND1_i) == 0;
}
}
static void
increfp(PCMslot *pp)
{
if(incref(&pcmcia) == 1)
exppackpower(1);
lock(pp);
if(pp->ref++ == 0)
;
unlock(pp);
slotinfo();
}
static void
decrefp(PCMslot *pp)
{
slotinfo();
lock(pp);
if(pp->ref-- == 1)
;
unlock(pp);
if(decref(&pcmcia) == 0)
exppackpower(0);
}
/*
* get a map for pc card region, return corrected len
*/
PCMmap*
pcmmap(int slotno, ulong, int, int attr)
{
if(slotno > nslot)
panic("pcmmap");
if(attr)
return &slot[slotno].attrmap;
else
return &slot[slotno].memmap;
}
void
pcmunmap(int, PCMmap*)
{
}
/*
* map in the space for the cards
*/
static void
pcmciareset(void)
{
int j;
PCMslot *pp;
for(j = 0; j < nslot; j++){
pp = &slot[j];
pp->slotno = j;
pp->memlen = 64*OneMeg;
pp->msec = ~0;
pp->verstr[0] = 0;
pp->mem = mapmem(j == 0 ? PYHSPCM0MEM : PYHSPCM1MEM, 64*OneMeg);
pp->memmap.ca = 0;
pp->memmap.cea = 64*MB;
pp->memmap.isa = (ulong)pp->mem;
pp->memmap.len = 64*OneMeg;
pp->memmap.attr = 0;
pp->attr = mapmem(j == 0 ? PYHSPCM0ATTR : PYHSPCM1ATTR, OneMeg);
pp->attrmap.ca = 0;
pp->attrmap.cea = 64*MB;
pp->attrmap.isa = (ulong)pp->attr;
pp->attrmap.len = OneMeg;
pp->attrmap.attr = 1;
pp->regs = mapspecial(j == 0 ? PHYSPCM0REGS : PHYSPCM1REGS, 32*1024);
}
}
static Chan*
pcmciaattach(char *spec)
{
return devattach('y', spec);
}
static int
pcmciawalk(Chan *c, char *name)
{
return devwalk(c, name, 0, 0, pcmgen);
}
static void
pcmciastat(Chan *c, char *db)
{
devstat(c, db, 0, 0, pcmgen);
}
static Chan*
pcmciaopen(Chan *c, int omode)
{
if(c->qid.path == CHDIR){
if(omode != OREAD)
error(Eperm);
} else
increfp(slot + SLOTNO(c));
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
return c;
}
static void
pcmciaclose(Chan *c)
{
if(c->flag & COPEN)
if(c->qid.path != CHDIR)
decrefp(slot+SLOTNO(c));
}
/* a memmove using only bytes */
static void
memmoveb(uchar *to, uchar *from, int n)
{
while(n-- > 0)
*to++ = *from++;
}
/* 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++;
}
}
static long
pcmread(void *a, long n, ulong off, uchar *start, ulong len)
{
if(off > len)
return 0;
if(off + n > len)
n = len - off;
memmoves(a, start+off, n);
return n;
}
static long
pcmctlread(void *a, long n, ulong off, PCMslot *pp)
{
char *p, *buf, *e;
buf = p = malloc(READSTR);
if(waserror()){
free(buf);
nexterror();
}
e = p + READSTR;
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);
}
USED(p);
n = readstr(off, a, n, buf);
free(buf);
poperror();
return n;
}
static long
pcmciaread(Chan *c, void *a, long n, vlong off)
{
PCMslot *pp;
ulong offset = off;
pp = slot + SLOTNO(c);
switch(TYPE(c)){
case Qdir:
return devdirread(c, a, n, 0, 0, pcmgen);
case Qmem:
if(!pp->occupied)
error(Eio);
return pcmread(a, n, offset, pp->mem, 64*OneMeg);
case Qattr:
if(!pp->occupied)
error(Eio);
return pcmread(a, n, offset, pp->attr, OneMeg);
case Qctl:
return pcmctlread(a, n, offset, pp);
}
error(Ebadarg);
return -1; /* not reached */
}
static long
pcmwrite(void *a, long n, ulong off, uchar *start, ulong len)
{
if(off > len)
error(Eio);
if(off + n > len)
error(Eio);
memmoveb(start+off, a, n);
return n;
}
static long
pcmctlwrite(char *p, long n, ulong off, PCMslot *pp)
{
/* nothing yet */
USED(p, n, off, pp);
error(Ebadarg);
return 0;
}
static long
pcmciawrite(Chan *c, void *a, long n, vlong off)
{
PCMslot *pp;
ulong offset = off;
pp = slot + SLOTNO(c);
switch(TYPE(c)){
case Qmem:
if(!pp->occupied)
error(Eio);
return pcmwrite(a, n, offset, pp->mem, 64*OneMeg);
case Qattr:
if(!pp->occupied)
error(Eio);
return pcmwrite(a, n, offset, pp->attr, OneMeg);
case Qctl:
if(!pp->occupied)
error(Eio);
return pcmctlwrite(a, n, offset, pp);
}
error(Ebadarg);
return -1; /* not reached */
}
Dev pcmciadevtab = {
'y',
"pcmcia",
pcmciareset,
devinit,
pcmciaattach,
devclone,
pcmciawalk,
pcmciastat,
pcmciaopen,
devcreate,
pcmciaclose,
pcmciaread,
devbread,
pcmciawrite,
devbwrite,
devremove,
devwstat,
};
.
## diffname bitsy/devpcmcia.c 2000/1121
## diff -e /n/emeliedump/2000/1118/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1121/sys/src/9/bitsy/devpcmcia.c
355a
/* see what's there */
static void
slotinfo(void)
{
ulong x = gpioregs->level;
if(x & GPIO_OPT_IND_i){
/* no expansion pack */
slot[0].occupied = 0;
slot[1].occupied = 0;
} else {
slot[0].occupied = (x & GPIO_CARD_IND0_i) == 0;
slot[1].occupied = (x & GPIO_CARD_IND1_i) == 0;
}
}
/* use reference card to turn cards on and off */
static void
increfp(PCMslot *pp)
{
if(incref(&pcmcia) == 1){
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
egpiobits(EGPIO_pcmcia_reset, 0);
delay(100); /* time to power up */
}
incref(pp);
slotinfo();
}
static void
decrefp(PCMslot *pp)
{
slotinfo();
decref(pp);
if(decref(&pcmcia) == 0)
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
}
/*
* the regions are staticly mapped
*/
static void
slotmap(int slotno, ulong regs, ulong attr, ulong mem)
{
PCMslot *pp;
pp = &slot[slotno];
pp->slotno = slotno;
pp->memlen = 64*OneMeg;
pp->msec = ~0;
pp->verstr[0] = 0;
pp->mem = mapmem(mem, 64*OneMeg, 0);
pp->memmap.ca = 0;
pp->memmap.cea = 64*MB;
pp->memmap.isa = (ulong)pp->mem;
pp->memmap.len = 64*OneMeg;
pp->memmap.attr = 0;
pp->attr = mapmem(attr, OneMeg, 0);
pp->attrmap.ca = 0;
pp->attrmap.cea = MB;
pp->attrmap.isa = (ulong)pp->attr;
pp->attrmap.len = OneMeg;
pp->attrmap.attr = 1;
pp->regs = mapspecial(regs, 32*1024);
}
PCMmap*
pcmmap(int slotno, ulong, int, int attr)
{
if(slotno > nslot)
panic("pcmmap");
if(attr)
return &slot[slotno].attrmap;
else
return &slot[slotno].memmap;
}
void
pcmunmap(int, PCMmap*)
{
}
/*
* setup card timings
* times are in ns
* count = ceiling[access-time/(2*3*T)] - 1, where T is a processor cycle
*
*/
static int
ns2count(int ns)
{
ulong y;
/* get 100 times cycle time */
y = 100000000/(conf.hz/1000);
/* get 10 times ns/(cycle*6) */
y = (1000*ns)/(6*y);
/* round up */
y += 9;
y /= 10;
/* subtract 1 */
return y-1;
}
static void
slottiming(int slotno, int tio, int tattr, int tmem, int fast)
{
ulong x;
x = 0;
if(fast)
x |= 1<<MECR_fast0;
x |= ns2count(tio) << MECR_io0;
x |= ns2count(tattr) << MECR_attr0;
x |= ns2count(tmem) << MECR_mem0;
if(slotno == 0){
x |= memconfregs->mecr & 0xffff0000;
} else {
x <<= 16;
x |= memconfregs->mecr & 0xffff;
}
memconfregs->mecr = x;
}
.
234c
memmoveb(a, start+off, n);
.
136,158c
/* set timing to the default, 300 */
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
.
133,134c
/* staticly map the whole area */
slotmap(0, PHYSPCM0REGS, PYHSPCM0ATTR, PYHSPCM0MEM);
slotmap(1, PHYSPCM1REGS, PYHSPCM1ATTR, PYHSPCM1MEM);
.
112,129d
110c
* set up the cards, default timing is 300 ns
.
71,108d
29a
static void increfp(PCMslot*);
static void decrefp(PCMslot*);
static void slotmap(int, ulong, ulong, ulong);
static void slottiming(int, int, int, int, int);
.
## diffname bitsy/devpcmcia.c 2000/1122
## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1122/sys/src/9/bitsy/devpcmcia.c
321d
314,315c
if(pp->occupied && pp->cisread == 0)
pcmcisread(pp);
.
312d
310c
delay(200); /* time to power up */
.
306a
slotinfo(nil, nil);
.
298,299c
if(!slot[0].occupied && (x & GPIO_CARD_IND0_i)){
slot[0].occupied = 1;
slot[0].cisread = 0;
}
if(!slot[1].occupied && (x & GPIO_CARD_IND1_i)){
slot[1].occupied = 1;
slot[0].cisread = 0;
}
.
289c
slotinfo(Ureg*, void*)
.
88a
/* interrupt on card insertion */
gpiointrenable(
.
## diffname bitsy/devpcmcia.c 2000/1128
## diff -e /n/emeliedump/2000/1122/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1128/sys/src/9/bitsy/devpcmcia.c
330c
decref(&pp->ref);
.
322c
incref(&pp->ref);
.
90,91c
/* interrupt on card insertion/removal */
gpiointrenable(GPIO_CARD_IND1_i, GPIOboth, slotinfo, nil, "pcmcia slot1 status");
gpiointrenable(GPIO_CARD_IND0_i, GPIOboth, slotinfo, nil, "pcmcia slot0 status");
.
33a
static void slotinfo(Ureg*, void*);
.
## diffname bitsy/devpcmcia.c 2000/1130
## diff -e /n/emeliedump/2000/1128/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1130/sys/src/9/bitsy/devpcmcia.c
318d
## diffname bitsy/devpcmcia.c 2000/1201
## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1201/sys/src/9/bitsy/devpcmcia.c
360c
pp->attrmap.isa = (ulong)attr;
.
353c
pp->memmap.isa = (ulong)mem;
.
309c
slot[1].cisread = 0;
.
307c
if(x & GPIO_CARD_IND1_i){
slot[1].occupied = 0;
slot[1].cisread = 0;
} else if(slot[1].occupied == 0){
.
303c
if(x & GPIO_CARD_IND0_i){
slot[0].occupied = 0;
slot[0].cisread = 0;
} else if(slot[0].occupied == 0){
.
## diffname bitsy/devpcmcia.c 2000/1205
## diff -e /n/emeliedump/2000/1201/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1205/sys/src/9/bitsy/devpcmcia.c
370c
sp->regs = mapspecial(regs, 32*1024);
.
363,368c
sp->attr = mapmem(attr, OneMeg, 0);
sp->attrmap.ca = 0;
sp->attrmap.cea = MB;
sp->attrmap.isa = (ulong)attr;
sp->attrmap.len = OneMeg;
sp->attrmap.attr = 1;
.
356,361c
sp->mem = mapmem(mem, 64*OneMeg, 0);
sp->memmap.ca = 0;
sp->memmap.cea = 64*MB;
sp->memmap.isa = (ulong)mem;
sp->memmap.len = 64*OneMeg;
sp->memmap.attr = 0;
.
350,354c
sp = &slot[slotno];
sp->slotno = slotno;
sp->memlen = 64*OneMeg;
sp->verstr[0] = 0;
.
348c
PCMslot *sp;
.
343c
* the regions are staticly masped
.
337c
decref(&sp->ref);
.
335c
decrefp(PCMslot *sp)
.
329,331c
incref(&sp->ref);
slotinfo(nil, nil);
if(sp->occupied && sp->cisread == 0)
pcmcisread(sp);
wunlock(sp);
poperror();
.
327c
delay(500);
.
325a
delay(200);
egpiobits(EGPIO_pcmcia_reset, 1);
delay(100);
.
323a
wlock(sp);
if(waserror()){
wunlock(sp);
nexterror();
}
.
322c
increfp(PCMslot *sp)
.
315d
313c
} else {
if(slot[1].occupied == 0)
slot[1].cisread = 0;
.
308d
306c
} else {
if(slot[0].occupied == 0)
slot[0].cisread = 0;
.
265c
return pcmctlwrite(a, n, offset, sp);
.
263c
if(!sp->occupied)
.
261c
return pcmwrite(a, n, offset, sp, sp->attr, OneMeg);
.
259c
if(!sp->occupied)
.
257c
return pcmwrite(a, n, offset, sp, sp->mem, 64*OneMeg);
.
255c
if(!sp->occupied)
.
251c
sp = slot + SLOTNO(c);
.
248c
PCMslot *sp;
.
239,241c
Cmdbuf *cmd;
uchar *cp;
int index, i, dtx;
Rune r;
DevConf cf;
cmd = parsecmd(p, n);
if(strcmp(cmd->f[0], "configure") == 0){
wlock(sp);
if(waserror()){
wunlock(sp);
nexterror();
}
/* see if driver exists and is configurable */
if(cmd->nf < 3)
error(Ebadarg);
p = cmd->f[1];
if(*p++ != '#')
error(Ebadarg);
p += chartorune(&r, p);
dtx = devno(r, 1);
if(dtx < 0)
error("no such device type");
if(devtab[dtx]->config == nil)
error("not a dynamicly configurable device");
/* set pcmcia card configuration */
index = 0;
if(sp->def != nil)
index = sp->def->index;
if(cmd->nf > 3){
i = atoi(cmd->f[3]);
if(i < 0 || i >= sp->nctab)
error("bad configuration index");
index = i;
}
if(sp->cpresent & (1<<Rconfig)){
cp = sp->attr;
cp += sp->caddr + Rconfig;
print("writing configuration register (%lux) with index %d\n", cp, index);
*cp = index;
}
/* configure device */
strncpy(cf.type, cmd->f[2], sizeof(cf.type)-1);
cf.type[sizeof(cf.type)-1] = 0;
cf.mem = (ulong)sp->mem;
cf.port = (ulong)sp->regs;
cf.itype = GPIOfalling;
cf.interrupt = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
cf.size = 0;
if(devtab[dtx]->config(1, p, &cf) < 0)
error("couldn't configure device");
wunlock(sp);
poperror();
/* don't let the power turn off */
increfp(sp);
}
free(cmd);
.
237c
pcmctlwrite(char *p, long n, ulong, PCMslot *sp)
.
232a
poperror();
runlock(sp);
.
227a
rlock(sp);
if(waserror()){
runlock(sp);
nexterror();
}
.
226c
pcmwrite(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
.
219c
return pcmctlread(a, n, offset, sp);
.
217c
return pcmread(a, n, offset, sp, sp->attr, OneMeg);
.
215c
if(!sp->occupied)
.
213c
return pcmread(a, n, offset, sp, sp->mem, 64*OneMeg);
.
211c
if(!sp->occupied)
.
205c
sp = slot + SLOTNO(c);
.
202c
PCMslot *sp;
.
188,189c
if(sp->verstr[0])
p = seprint(p, e, "version %s\n", sp->verstr);
.
186c
if(sp->occupied){
.
174c
pcmctlread(void *a, long n, ulong off, PCMslot *sp)
.
169a
runlock(sp);
poperror();
.
164a
rlock(sp);
if(waserror()){
runlock(sp);
nexterror();
}
.
163c
pcmread(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
.
91,93c
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i)
return;
/* sleave there, interrupt on card removal */
intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
.
76a
static int
bitno(ulong x)
{
int i;
for(i = 0; i < 8*sizeof(x); i++)
if((1<<i) & x)
break;
return i;
}
.
65c
len = sp->memlen;
.
60c
len = sp->memlen;
.
54c
sp = slot + slotno;
.
42c
PCMslot *sp;
.
25a
enum
{
/*
* 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 */
};
.
## diffname bitsy/devpcmcia.c 2000/1206
## diff -e /n/emeliedump/2000/1205/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1206/sys/src/9/bitsy/devpcmcia.c
319d
## diffname bitsy/devpcmcia.c 2001/0529
## diff -e /n/emeliedump/2000/1206/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0529/sys/src/9/bitsy/devpcmcia.c
377d
323,324c
kstrdup(&cf.type, cmd->f[2]);
.
158c
if((c->qid.type & QTDIR) == 0)
.
143c
if(c->qid.type & QTDIR){
.
137c
return devstat(c, db, n, 0, 0, pcmgen);
.
134,135c
static int
pcmciastat(Chan *c, uchar *db, int n)
.
131c
return devwalk(c, nc, name, nname, 0, 0, pcmgen);
.
128,129c
static Walkqid*
pcmciawalk(Chan *c, Chan *nc, char **name, int nname)
.
84c
devdir(c, qid, up->genbuf, len, eve, 0660, dp);
.
80c
snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
.
75c
snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
.
70c
snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
.
57c
mkqid(&qid, Qdir, 0, QTDIR);
devdir(c, qid, "#y", 0, eve, 0555, dp);
.
54d
48c
pcmgen(Chan *c, char *, Dirtab * , int, int i, Dir *dp)
.
37,38c
#define SLOTNO(c) ((ulong)((c->qid.path>>8)&0xff))
#define TYPE(c) ((ulong)(c->qid.path&0xff))
.
## diffname bitsy/devpcmcia.c 2001/0616
## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0616/sys/src/9/bitsy/devpcmcia.c
440a
}
.
439c
if(sp->occupied && sp->cisread == 0) {
.
422a
print("increfp\n");
.
349c
sp = slotno(c);
.
238c
sp = slotno(c);
.
159c
decrefp(slotno(c));
.
147c
increfp(slotno(c));
.
142a
print("pcmciaopen\n");
.
79c
qid.path = PATH(slotno, Qctl);
.
74c
qid.path = PATH(slotno, Qattr);
.
69c
qid.path = PATH(slotno, Qmem);
.
46a
#define TYPE(c) (((ulong)c->qid.path)&0xff)
#define PATH(s,t) (((s)<<8)|(t))
static PCMslot*
slotno(Chan *c)
{
ulong x;
x = c->qid.path;
return slot + ((x>>8)&0xff);
}
.
37,40d
## diffname bitsy/devpcmcia.c 2001/0617
## diff -e /n/emeliedump/2001/0616/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0617/sys/src/9/bitsy/devpcmcia.c
331a
cf.type = nil;
.
## diffname bitsy/devpcmcia.c 2001/0619
## diff -e /n/emeliedump/2001/0617/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0619/sys/src/9/bitsy/devpcmcia.c
433d
359c
sp = slotof(c);
.
247c
sp = slotof(c);
.
168c
decrefp(slotof(c));
.
155,156c
} else {
slotp = slotof(c);
increfp(slotp);
}
.
151c
PCMslot *slotp;
.
91a
qid.type = QTFILE;
.
47c
slotof(Chan *c)
.
## diffname bitsy/devpcmcia.c 2001/0815
## diff -e /n/emeliedump/2001/0619/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0815/sys/src/9/bitsy/devpcmcia.c
507a
.
497a
.
## diffname bitsy/devpcmcia.c 2002/0109
## diff -e /n/emeliedump/2001/0815/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0109/sys/src/9/bitsy/devpcmcia.c
388a
devshutdown,
.
## diffname bitsy/devpcmcia.c 2002/0607
## diff -e /n/emeliedump/2002/0109/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0607/sys/src/9/bitsy/devpcmcia.c
350a
}else if(strcmp(cmd->f[0], "remove") == 0){
wlock(sp);
if(waserror()){
wunlock(sp);
nexterror();
}
wunlock(sp);
poperror();
.
118,128c
pcmciapower(1);
.
108a
* power up/down pcmcia
*/
static void
pcmciapower(int up)
{
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i)
return;
if (up){
/* set timing to the default, 300 */
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i)
return;
/* sleave there, interrupt on card removal */
intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
}else{
}
}
/*
.
## diffname bitsy/devpcmcia.c 2002/0613
## diff -e /n/emeliedump/2002/0607/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0613/sys/src/9/bitsy/devpcmcia.c
359a
wunlock(&cf);
.
357d
351c
memset(&cf, 0, sizeof cf);
wlock(&cf);
.
## diffname bitsy/devpcmcia.c 2002/0614
## diff -e /n/emeliedump/2002/0613/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0614/sys/src/9/bitsy/devpcmcia.c
374,376c
/* let the power turn off */
decrefp(sp);
.
368,372c
/* see if driver exists and is configurable */
if(cmd->nf != 2)
error(Ebadarg);
p = cmd->f[1];
if(*p++ != '#')
error(Ebadarg);
p += chartorune(&r, p);
dtx = devno(r, 1);
if(dtx < 0)
error("no such device type");
if(devtab[dtx]->config == nil)
error("not a dynamicly configurable device");
if(devtab[dtx]->config(0, p, nil) < 0)
error("couldn't unconfigure device");
.
360d
352d
## diffname bitsy/devpcmcia.c 2002/0615
## diff -e /n/emeliedump/2002/0614/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0615/sys/src/9/bitsy/devpcmcia.c
356c
cf.intnum = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
.
## diffname bitsy/devpcmcia.c 2002/0618
## diff -e /n/emeliedump/2002/0615/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0618/sys/src/9/bitsy/devpcmcia.c
433a
pcmciapower,
.
358a
sp->dev = devtab[dtx];
print("pcmctlwrite: configure %s: 0x%p\n", cmd->f[1], sp->dev);
.
143c
/* set timing to the default, 300 */
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i)
return;
/* sleave there, interrupt on card removal */
intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
.
129a
for (sp = slot; sp < slot + nslot; sp++){
if (sp->occupied == 0)
continue;
if (sp->dev){
print("pcmciapower: dev 0x%p", sp->dev);
print(", power 0x%p\n", sp->dev->power);
if (sp->dev->power)
sp->dev->power(on);
}
}
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
.
126,128c
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
delay(200);
egpiobits(EGPIO_pcmcia_reset, 1);
delay(100);
egpiobits(EGPIO_pcmcia_reset, 0);
delay(500);
slotinfo(nil, nil); // See what's there
for (sp = slot; sp < slot + nslot; sp++){
if (sp->occupied == 0)
continue;
if(sp->cisread == 0)
pcmcisread(sp);
if (sp->dev){
print("pcmciapower: dev 0x%p", sp->dev);
print(", power 0x%p\n", sp->dev->power);
if (sp->dev->power)
sp->dev->power(on);
}
}
.
117c
if (on){
.
113a
PCMslot *sp;
.
111,112c
void
pcmciapower(int on)
.
## diffname bitsy/devpcmcia.c 2002/0619
## diff -e /n/emeliedump/2002/0618/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0619/sys/src/9/bitsy/devpcmcia.c
400,401d
153,154d
142,145c
// if (sp->dev->power)
// sp->dev->power(on);
.
## diffname bitsy/devpcmcia.c 2002/0626
## diff -e /n/emeliedump/2002/0619/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0626/sys/src/9/bitsy/devpcmcia.c
540c
* the regions are staticly mapped
.
536a
}
.
535c
if(decref(&pcmcia) == 0){
iprint("increfp power down\n");
.
533a
iprint("decrefp %ld\n", sp - slot);
.
513a
iprint("increfp full power\n");
.
512a
iprint("increfp %ld\n", sp - slot);
.
450a
/*
* power up/down pcmcia
*/
void
pcmciapower(int on)
{
PCMslot *sp;
/* if there's no pcmcia sleave, no interrupts */
iprint("pcmciapower %d\n", on);
if (on){
/* set timing to the default, 300 */
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i){
iprint("pcmciapower: no sleeve\n");
return;
}
for (sp = slot; sp < slot + nslot; sp++){
if (sp->dev){
increfp(sp);
iprint("pcmciapower: %s\n", sp->verstr);
if (sp->dev->power)
sp->dev->power(on);
}
}
}else{
if(gpioregs->level & GPIO_OPT_IND_i){
iprint("pcmciapower: no sleeve\n");
return;
}
for (sp = slot; sp < slot + nslot; sp++){
if (sp->dev){
if (sp->dev->power)
sp->dev->power(on);
decrefp(sp);
}
sp->occupied = 0;
sp->cisread = 0;
}
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
}
}
.
109,159d
## diffname bitsy/devpcmcia.c 2002/0702
## diff -e /n/emeliedump/2002/0626/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0702/sys/src/9/bitsy/devpcmcia.c
425a
delay(10000);
.
## diffname bitsy/devpcmcia.c 2002/0703
## diff -e /n/emeliedump/2002/0702/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0703/sys/src/9/bitsy/devpcmcia.c
341c
cf.irq = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
.
## diffname bitsy/devpcmcia.c 2002/1112
## diff -e /n/emeliedump/2002/0703/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/1112/sys/src/9/bitsy/devpcmcia.c
630a
}
/* For compat with ../pc devices. Don't use it for the bitsy
*/
int
pcmspecial(char*, ISAConf*)
{
return -1;
.
498a
if (inserted(nil))
wakeup(&pcmcia.event);
.
496a
}
.
495c
if(slot[1].occupied == 0){
slot[1].inserted = 1;
.
492c
slot[1].occupied = slot[1].inserted = 0;
.
488a
}
.
487c
if(slot[0].occupied == 0){
slot[0].inserted = 1;
.
484c
slot[0].occupied = slot[0].inserted = 0;
.
480,481c
slot[0].occupied = slot[0].inserted = 0;
slot[1].occupied = slot[1].inserted = 0;
.
390a
case Qevs:
break;
.
341c
cf.intnum = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
.
339c
cf.ports = &port;
cf.ports[0].port = (ulong)sp->regs;
cf.ports[0].size = 0;
cf.nports = 1;
.
296a
port_t port;
.
263a
case Qevs:
return pcmevsread(a, n, offset);
.
245a
pcmevsread(void *a, long n, ulong off)
{
int i;
char *buf = nil;
char *e;
if (pcmcia.evreader)
error("At most one reader");
off = 0;
pcmcia.evreader++;
if (waserror()){
free(buf);
pcmcia.evreader--;
nexterror();
}
while((i = inserted(nil)) == 0){
slotinfo(nil, nil);
tsleep(&pcmcia.event, inserted, nil, 500);
}
pcmcia.evreader--;
slot[i-1].inserted = 0;
buf = malloc(READSTR);
e = buf + READSTR;
buf[0] = 0;
seprint(buf, e, "#y/pcm%dctl\n", i-1);
n = readstr(off, a, n, buf);
free(buf);
poperror();
return n;
}
static long
.
244a
static int
inserted(void *)
{
if (slot[0].inserted)
return 1;
if (slot[1].inserted)
return 2;
return 0;
}
.
90a
found:
.
70a
if(i == Nents*nslot){
len = 0;
qid.path = PATH(0, Qevs);
snprint(up->genbuf, sizeof up->genbuf, "pcmevs");
goto found;
}
.
69c
if(i >= Nents*nslot + 1)
.
21a
Qevs,
.
13a
Rendez event; // where to wait for card events
int evreader; // there's a reader for events
.
8a
/*
* BUG: insertion events are detected by polling.
* Should look into the compaq docs to see if
* there's an interrupt for card insertion
* there's probably one.
*/
.
|