M bitsy/dat.h => bitsy/dat.h +2 -0
@@ 236,6 236,8 @@ struct PCMslot
uchar occupied; /* card in the slot */
uchar configed; /* card configured */
+ Dev *dev; /* set in ctlwrite `configure' */
+
/* cis info */
int cisread; /* set when the cis has been read */
char verstr[512]; /* version string */
M bitsy/devether.c => bitsy/devether.c +19 -66
@@ 10,7 10,6 @@
#include "etherif.h"
-static Ether noether;
static volatile Ether *etherxx[MaxEther];
static struct {
@@ 33,14 32,17 @@ addethercard(char* t, int (*r)(Ether*))
void
etherpower(int on)
{
+ int i;
+ Ether *ether;
/* Power all ether cards on or off */
+print("etherpower %d\n", on);
for (i = 0; i < MaxEther; i++){
ether = etherxx[i];
if (ether == nil)
continue;
if(on){
- if (ether->write == 0){
+ if (ether->writer == 0){
print("etherpower: already powered up\n");
continue;
}
@@ 49,17 51,12 @@ etherpower(int on)
wunlock(ether);
/* Unlock when power restored */
}else{
- if (ether->write != 0){
+ if (ether->writer != 0){
print("etherpower: already powered down\n");
continue;
}
/* Keep locked until power goes back on */
wlock(ether);
- if (ether == &noether){
- /* Locked an unconfigured card, undo */
- wunlock(ether);
- continue;
- }
if (ether->power)
ether->power(ether, on);
}
@@ 77,33 74,10 @@ etherconfig(int on, char *spec, DevConf *cf)
ctlrno = atoi(spec);
sprint(name, "ether%d", ctlrno);
- if(on == 0){
- ether = etherxx[ctlrno];
- if(ether == nil || ether == &noether)
- return -1;
-print("unconfigure\n");
- wlock(ether);
- if(waserror()) {
- wunlock(ether);
- nexterror();
- }
- if(ether == &noether)
- error(Enodev);
-
- if(ether->detach)
- ether->detach(ether);
-
- if(ether->interrupt != nil)
- intrdisable(ether->itype, ether->intnum, ether->interrupt, ether, name);
-
- etherxx[ctlrno] = &noether;
- wunlock(ether);
- poperror();
-print("unconfigure: done\n");
- return 0;
- }
+ if(on == 0)
+ return -1;
- if(etherxx[ctlrno] != nil && etherxx[ctlrno] != &noether)
+ if(etherxx[ctlrno] != nil)
return -1;
ether = malloc(sizeof(Ether));
@@ 178,15 152,13 @@ etherattach(char* spec)
error(Ebadarg);
}
ether = etherxx[ctlrno];
- if(ether == 0 || ether == &noether)
+ if(ether == 0)
error(Enodev);
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
- if(etherxx[ctlrno] == &noether)
- error(Enodev);
chan = devattach('l', spec);
chan->dev = ctlrno;
if(ether->attach)
@@ 208,8 180,6 @@ etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
q = netifwalk(ether, chan, nchan, name, nname);
poperror();
runlock(ether);
@@ 228,8 198,6 @@ etherstat(Chan* chan, uchar* dp, int n)
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
s = netifstat(ether, chan, dp, n);
poperror();
runlock(ether);
@@ 248,8 216,6 @@ etheropen(Chan* chan, int omode)
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
c = netifopen(ether, chan, omode);
poperror();
runlock(ether);
@@ 272,8 238,6 @@ etherclose(Chan* chan)
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
netifclose(ether, chan);
poperror();
runlock(ether);
@@ 284,6 248,7 @@ etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
+ long r;
ether = etherxx[chan->dev];
rlock(ether);
@@ 291,24 256,23 @@ etherread(Chan* chan, void* buf, long n, vlong off)
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
- if(NETTYPE(chan->qid.path) == Nifstatqid)
- n = ether->ifstat(ether, buf, n, offset);
- else if(NETTYPE(chan->qid.path) == Nstatqid){
- ether->ifstat(ether, buf, 0, offset);
- n = netifread(ether, chan, buf, n, offset);
+ if(NETTYPE(chan->qid.path) == Nifstatqid){
+ r = ether->ifstat(ether, buf, n, offset);
+ goto out;
}
- }else
- n = netifread(ether, chan, buf, n, offset);
+ if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+ r = netifread(ether, chan, buf, n, offset);
+out:
poperror();
runlock(ether);
- return n;
+ return r;
}
static Block*
@@ 318,14 282,11 @@ etherbread(Chan* chan, long n, ulong offset)
Ether *ether;
ether = etherxx[chan->dev];
- error(Enodev);
rlock(ether);
if(waserror()) {
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
b = netifbread(ether, chan, n, offset);
poperror();
runlock(ether);
@@ 343,8 304,6 @@ etherwstat(Chan* chan, uchar* dp, int n)
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
n = netifwstat(ether, chan, dp, n);
poperror();
runlock(ether);
@@ 501,8 460,6 @@ etherwrite(Chan* chan, void* buf, long n, vlong)
runlock(ether);
nexterror();
}
- if(ether == &noether)
- error(Enodev);
if(NETTYPE(chan->qid.path) != Ndataqid) {
l = netifwrite(ether, chan, buf, n);
if(l >= 0)
@@ 553,10 510,6 @@ etherbwrite(Chan* chan, Block* bp, ulong)
runlock(ether);
nexterror();
}
- if(ether == &noether){
- freeb(bp);
- error(Enodev);
- }
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
M bitsy/devpcmcia.c => bitsy/devpcmcia.c +50 -7
@@ 108,13 108,15 @@ bitno(ulong x)
/*
* power up/down pcmcia
*/
-static void
-pcmciapower(int up)
+void
+pcmciapower(int on)
{
+ PCMslot *sp;
+
/* if there's no pcmcia sleave, no interrupts */
if(gpioregs->level & GPIO_OPT_IND_i)
return;
- if (up){
+ if (on){
/* set timing to the default, 300 */
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
@@ 123,10 125,38 @@ pcmciapower(int up)
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");
+ 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);
+ }
+ }
}else{
+ 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);
}
}
@@ 140,7 170,17 @@ pcmciareset(void)
slotmap(0, PHYSPCM0REGS, PYHSPCM0ATTR, PYHSPCM0MEM);
slotmap(1, PHYSPCM1REGS, PYHSPCM1ATTR, PYHSPCM1MEM);
- pcmciapower(1);
+ /* 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");
}
static Chan*
@@ 356,6 396,8 @@ pcmctlwrite(char *p, long n, ulong, PCMslot *sp)
cf.intnum = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
if(devtab[dtx]->config(1, p, &cf) < 0)
error("couldn't configure device");
+ sp->dev = devtab[dtx];
+print("pcmctlwrite: configure %s: 0x%p\n", cmd->f[1], sp->dev);
wunlock(sp);
poperror();
@@ 431,6 473,7 @@ Dev pcmciadevtab = {
devbwrite,
devremove,
devwstat,
+ pcmciapower,
};
/* see what's there */
M bitsy/etherif.h => bitsy/etherif.h +1 -1
@@ 21,7 21,7 @@ struct Ether {
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
- long (*power)(Ether*, int); /* power on/off */
+ void (*power)(Ether*, int); /* power on/off */
void *ctlr;
Queue* oq;
M bitsy/fns.h => bitsy/fns.h +1 -0
@@ 76,6 76,7 @@ void outb(ulong, uchar);
void outs(ulong, ushort);
void outss(ulong, void*, int);
void outl(ulong, ulong);
+void pcmciapower(int);
void pcmcisread(PCMslot*);
int pcmcistuple(int, int, int, void*, int);
PCMmap* pcmmap(int, ulong, int, int);
M bitsy/power.c => bitsy/power.c +2 -0
@@ 172,6 172,7 @@ deepsleep(void) {
xlink = getcallerpc(&xlink);
/* Power down */
+ pcmciapower(0);
irpower(0);
audiopower(0);
screenpower(0);
@@ 216,6 217,7 @@ deepsleep(void) {
// audiopower(1);
µcpower(1);
screenpower(1);
+ pcmciapower(1);
splx(power_pl);
return;
}
M bitsy/trap.c => bitsy/trap.c +0 -4
@@ 127,8 127,6 @@ irqenable(int irq, IntrHandler *f, void* a, char *name)
if(irq >= nelem(vctl) || irq < 0)
panic("intrenable");
- print("irqenable %s, handler 0x%p\n", name, f);
-
v = malloc(sizeof(Vctl));
v->f = f;
v->a = a;
@@ 184,8 182,6 @@ intrenable(int type, int which, IntrHandler *f, void* a, char *name)
return;
}
- print("intrenable %s, handler 0x%p\n", name, f);
-
/* from here down, it must be a GPIO edge interrupt */
irq = which;
if(which >= nelem(gpiovctl) || which < 0)
M pc/sdata.c => pc/sdata.c +1 -1
@@ 476,7 476,7 @@ atadmamode(Drive* drive)
dma = drive->info[Imwdma] & 0x0707;
drive->dma = (dma>>8) & dma;
if(drive->dma == 0 && (drive->info[Ivalid] & 0x04)){
- dma = drive->info[Iudma] & 0x1F1F;
+ dma = drive->info[Iudma] & 0x3F3F;
drive->dma = (dma>>8) & dma;
if(drive->dma)
drive->dma |= 'U'<<16;
M pc/wavelan.c => pc/wavelan.c +39 -15
@@ 471,7 471,7 @@ w_txstart(Ether* ether)
Block *bp;
int len, off;
- if((ctlr = ether->ctlr) == nil || ctlr->attached == 0 || ctlr->txbusy)
+ if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) == 0 || ctlr->txbusy)
return;
if((bp = qget(ether->oq)) == nil)
@@ 558,7 558,10 @@ w_intr(Ether *ether)
int rc, txid;
Ctlr* ctlr = (Ctlr*) ether->ctlr;
- if (ctlr->attached == 0){
+ if ((ctlr->state & Power) == 0)
+ return;
+
+ if ((ctlr->state & Attached) == 0){
csr_ack(ctlr, 0xffff);
csr_outs(ctlr, WR_IntEna, 0);
return;
@@ 609,17 612,13 @@ w_timer(void* arg)
Ether* ether = (Ether*) arg;
Ctlr* ctlr = (Ctlr*)ether->ctlr;
- if (waserror()){
- print("timerporc dying\n");
- pexit("aaargh!", 0);
- }
ctlr->timerproc = up;
for(;;){
tsleep(&ctlr->timer, return0, 0, 50);
ctlr = (Ctlr*)ether->ctlr;
if (ctlr == 0)
break;
- if (ctlr->attached == 0)
+ if ((ctlr->state & Attached) == 0)
continue;
ctlr->ticks++;
@@ 660,7 659,6 @@ w_timer(void* arg)
}
iunlock(ctlr);
}
- poperror();
pexit("terminated", 0);
}
@@ 682,12 680,12 @@ w_attach(Ether* ether)
snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
ctlr = (Ctlr*) ether->ctlr;
- if (ctlr->attached == 0){
+ if ((ctlr->state & Attached) == 0){
ilock(ctlr);
rc = w_enable(ether);
iunlock(ctlr);
if(rc == 0){
- ctlr->attached = 1;
+ ctlr->state |= Attached;
kproc(name, w_timer, ether);
} else
print("#l%d: enable failed\n",ether->ctlrno);
@@ 705,7 703,7 @@ w_detach(Ether* ether)
snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
ctlr = (Ctlr*) ether->ctlr;
- if (ctlr->attached){
+ if (ctlr->state & Attached){
ilock(ctlr);
w_intdis(ctlr);
if (ctlr->timerproc){
@@ 713,11 711,34 @@ w_detach(Ether* ether)
print("timerproc note not posted\n");
print("w_detach, killing 0x%p\n", ctlr->timerproc);
}
- ctlr->attached = 0;
+ ctlr->state &= ~Attached;
iunlock(ctlr);
}
}
+void
+w_power(Ether* ether, int on)
+{
+ Ctlr *ctlr;
+
+ ctlr = (Ctlr*) ether->ctlr;
+ ilock(ctlr);
+ if (on){
+ if ((ctlr->state & Power) == 0){
+ if (ctlr->state & Attached)
+ w_enable(ether);
+ ctlr->state |= Power;
+ }
+ }else{
+ if (ctlr->state & Power){
+ if (ctlr->state & Attached)
+ w_intdis(ctlr);
+ ctlr->state &= ~Power;
+ }
+ }
+ iunlock(ctlr);
+}
+
#define PRINTSTAT(fmt,val) l += snprint(p+l, READSTR-l, (fmt), (val))
#define PRINTSTR(fmt) l += snprint(p+l, READSTR-l, (fmt))
@@ 760,8 781,10 @@ w_ifstat(Ether* ether, void* a, long n, ulong offset)
PRINTSTAT("WatchDogs: %lud\n", ctlr->nwatchdogs);
PRINTSTAT("Ticks: %ud\n", ctlr->ticks);
PRINTSTAT("TickIntr: %ud\n", ctlr->tickintr);
- k = ((ctlr->attached) ? "attached" : "not attached");
+ k = ((ctlr->state & Attached) ? "attached" : "not attached");
PRINTSTAT("Card %s", k);
+ k = ((ctlr->state & Power) ? "on" : "off");
+ PRINTSTAT("PCardower %s", k);
k = ((ctlr->txbusy)? ", txbusy" : "");
PRINTSTAT("%s\n", k);
@@ 967,7 990,7 @@ w_ctl(Ether* ether, void* buf, long n)
if((ctlr = ether->ctlr) == nil)
error(Enonexist);
- if(ctlr->attached == 0)
+ if((ctlr->state & Attached) == 0)
error(Eshutdown);
ilock(ctlr);
@@ 1006,7 1029,7 @@ w_promiscuous(void* arg, int on)
if (ctlr == nil)
error("card not found");
- if (ctlr->attached == 0)
+ if ((ctlr->state & Attached) == 0)
error("card not attached");
ilock(ctlr);
ltv_outs(ctlr, WTyp_Prom, (on?1:0));
@@ 1088,6 1111,7 @@ wavelanreset(Ether* ether, Ctlr *ctlr)
ether->transmit = w_transmit;
ether->ifstat = w_ifstat;
ether->ctl = w_ctl;
+ ether->power = w_power;
ether->promiscuous = w_promiscuous;
ether->multicast = w_multicast;
ether->arg = ether;
M pc/wavelan.h => pc/wavelan.h +6 -1
@@ 238,12 238,17 @@ struct Stats
int noise;
};
+enum {
+ Attached = 0x01,
+ Power = 0x02,
+};
+
struct Ctlr
{
Lock;
Rendez timer;
- int attached;
+ int state; // Attached | Power
int slot;
int iob;
int createibss;
M port/portdat.h => port/portdat.h +1 -1
@@ 202,7 202,7 @@ struct Dev
void (*remove)(Chan*);
int (*wstat)(Chan*, uchar*, int);
void (*power)(int); /* power mgt: power(1) => on, power (0) => off */
- int (*config)(int, char*, DevConf*);
+ int (*config)(int, char*, DevConf*); // returns nil on error
};
struct Dirtab