~kris/9p

9hist

621a87403d5134a096baaf5894649b5b521b565a — David du Colombier 24 years ago 5b096d6
Plan 9 from Bell Labs 2002-06-18
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