~kris/9p

9hist

86f7d85b9917d3f1629f356e283a4fa4281deab0 — David du Colombier 31 years ago 9baa62e
Plan 9 from Bell Labs 1995-02-23
4 files changed, 234 insertions(+), 92 deletions(-)

M pc/dat.h
M pc/devi82365.c
A pc/ether4100.c
M pc/trap.c
M pc/dat.h => pc/dat.h +6 -1
@@ 177,6 177,9 @@ struct PCArch
	int	(*extvga)(int);		/* 1 == external, 0 == internal */
};

/*
 *  a parsed plan9.ini line
 */
struct ISAConf {
	char	type[NAMELEN];
	ulong	port;


@@ 187,11 190,13 @@ struct ISAConf {
	uchar	ea[6];
};

/*
 *  SCSI bus
 */
enum {
	MaxScsi		= 4,
	NTarget		= 8,
};

struct Target {
	int	ctlrno;
	int	target;

M pc/devi82365.c => pc/devi82365.c +126 -84
@@ 92,6 92,8 @@ enum
	Rconfig=	0,
	 Creset=	 (1<<7),	/*  reset device */
	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */

	Maxctab=	8,		/* maximum configuration table entries */
};

#define MAP(x,o)	(Rmap + (x)*0x8 + o)


@@ 99,6 101,7 @@ enum
typedef struct I82365	I82365;
typedef struct Slot	Slot;
typedef struct PCMmap	PCMmap;
typedef struct Conftab	Conftab;

/* maps between ISA memory space and the card memory space */
struct PCMmap


@@ 128,7 131,23 @@ struct I82365
static I82365 *controller[4];
static int ncontroller;

/* a Slot slot */
/* 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 */
struct Slot
{
	Lock;


@@ 142,7 161,6 @@ struct Slot
	/* 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;


@@ 153,25 171,21 @@ struct Slot

	/* cis info */
	char	verstr[512];	/* version string */
	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 */
	int	nctab;		/* number of config table entries */
	Conftab	ctab[Maxctab];
	Conftab	*def;		/* default conftab */

	/* for walking through cis */
	int	cispos;		/* current position scanning cis */
	uchar	*cisbase;
	ulong	maxwait;
	ulong	readywait;
	ulong	otherwait;

	/* memory maps */
	QLock	mlock;		/* lock down the maps */
	int	time;
	PCMmap	mmap[Nmap];
	PCMmap	mmap[Nmap];	/* maps, last is always for the kernel */
	int	nmap;		/* number of maps */
};
static Slot	*slot;
static Slot	*lastslot;


@@ 234,27 248,21 @@ slotena(Slot *pp)
	if(pp->enabled)
		return;

	/* enable the card */
	wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena);
	delay(300);	/* give the card time to sit up and take notice */
	/* power up and reset, wait's are empirical (???) */
	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
	delay(300);
	wrreg(pp, Rigc, 0);
	delay(100);
	wrreg(pp, Rigc, Fnotreset);
	delay(100);
	wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena);
	delay(500);

	/* display status */
	/* get configuration */
	slotinfo(pp);
	if(pp->occupied){
		cisread(pp);

		/* set real power values if we configured successfully */
		if(pp->configed)
			wrreg(pp, Rpc, vcode(pp->vpp1)|Fautopower|Foutena|Fcardena);

		pp->enabled = 1;
	} else
		wrreg(pp, Rpc, vcode(5)|Fautopower);
	pp->enabled = 1;
		wrreg(pp, Rpc, Fautopower);
}

/*


@@ 263,8 271,7 @@ slotena(Slot *pp)
static void
slotdis(Slot *pp)
{
	wrreg(pp, Rmisc2, Flowpow);	 	/* low power mode */
	wrreg(pp, Rpc, vcode(5)|Fautopower);			/* turn off card */
	wrreg(pp, Rpc, Fautopower);		/* turn off card */
	wrreg(pp, Rwe, 0);			/* no windows */
	pp->enabled = 0;
}


@@ 307,22 314,11 @@ getmap(Slot *pp, ulong offset, int attr)
	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 = getisa(0, Mchunk, BY2PG);
			if(pp->mmap[i].isa == 0)
				panic("getmap");
		}
	}

	/* 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++){
	for(m = pp->mmap; m < &pp->mmap[pp->nmap]; m++){
		if((we & bit) && m->attr == attr && offset >= m->ca && offset < m->cea){
			m->time = pp->time++;
			return m;


@@ 345,7 341,7 @@ getmap(Slot *pp, ulong offset, int attr)
	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)) | Ftimer1);
	wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) /*| Ftimer1/**/);
	offset -= m->isa;
	offset &= (1<<25)-1;
	offset >>= 12;


@@ 509,6 505,10 @@ i82386probe(int x, int d, int dev)
	print("pcmcia controller%d is a %d slot %s\n", ncontroller, cp->nslot,
		chipname[cp->type]);

	/* low power mode */
	outb(x, Rmisc2 + (dev<<7));
	outb(d, Flowpow);

	controller[ncontroller++] = cp;
	return cp;
}


@@ 522,6 522,7 @@ i82365reset(void)
	static int already;
	int i, j;
	I82365 *cp;
	Slot *pp;

	if(already)
		return;


@@ 541,15 542,27 @@ i82365reset(void)
	for(i = 0; i < ncontroller; i++){
		cp = controller[i];
		for(j = 0; j < cp->nslot; j++){
			lastslot->slotno = lastslot - slot;
			lastslot->memlen = 64*MB;
			lastslot->base = (cp->dev<<7) | (j<<6);
			lastslot->cp = cp;
			slotdis(lastslot);
			lastslot++;
			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);
		}
	}

	/* 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++;
		}

	/* for card management interrupts */
	setvec(PCMCIAvec, i82365intr, 0);
}


@@ 815,6 828,7 @@ pcmio(int dev, ISAConf *isa)
{
	uchar we, x;
	Slot *pp;
	Conftab *ct;

	if(dev > nslot)
		return -1;


@@ 823,23 837,33 @@ pcmio(int dev, ISAConf *isa)
	if(!pp->occupied)
		return -1;

	/* if no io registers, assume not an io card (iffy!) */
	if(pp->nioregs == 0)
	/* 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])
		return -1;

	/* route interrupts, make sure card can use specified interrupt */
print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct->vpp1, ct->bit16, ct->nioregs);

	/* route interrupts */
	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);
	x = vcode(ct->vpp1);
	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);

	/* 16-bit data path */
	if(pp->bit16)
	if(ct->bit16)
		wrreg(pp, Rio, (1<<0)|(1<<1));

	/* enable io port map 0 */


@@ 848,8 872,8 @@ pcmio(int dev, ISAConf *isa)
	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, Riotop0lo, (isa->port+ct->nioregs));
	wrreg(pp, Riotop0hi, (isa->port+ct->nioregs)>>8);
	wrreg(pp, Rwe, we | (1<<6));

	/* only touch Rconfig if it is present */


@@ 867,7 891,10 @@ pcmio(int dev, ISAConf *isa)
		 *  configuration number 1.
		 *  Setting the configuration number enables IO port access.
		 */
		x = Clevel | 1;
		if(isa->irq > 7)
			x = Clevel | ct->index;
		else
			x = ct->index;
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig);
		delay(5);
	}


@@ 907,12 934,11 @@ cisread(Slot *pp)
	int this, i;
	PCMmap *m;

	pp->vpp1 = pp->vpp2 = 5;
	pp->bit16 = 0;
	memset(pp->ctab, 0, sizeof(pp->ctab));
	pp->caddr = 0;
	pp->cpresent = 0;
	pp->def = 0;
	pp->irqs = 0xffff;
	pp->configed = 0;
	pp->nctab = 0;

	m = getmap(pp, 0, 1);
	if(m == 0)


@@ 1062,7 1088,7 @@ ttiming(Slot *pp, int scale)
}

static void
timing(Slot *pp)
timing(Slot *pp, Conftab *ct)
{
	uchar c, i;



@@ 1070,27 1096,27 @@ timing(Slot *pp)
		return;
	i = c&0x3;
	if(i != 3)
		pp->maxwait = ttiming(pp, i);		/* max wait */
		ct->maxwait = ttiming(pp, i);		/* max wait */
	i = (c>>2)&0x7;
	if(i != 7)
		pp->readywait = ttiming(pp, i);		/* max ready/busy wait */
		ct->readywait = ttiming(pp, i);		/* max ready/busy wait */
	i = (c>>5)&0x7;
	if(i != 7)
		pp->otherwait = ttiming(pp, i);		/* reserved wait */
		ct->otherwait = ttiming(pp, i);		/* reserved wait */
}

void
iospaces(Slot *pp)
iospaces(Slot *pp, Conftab *ct)
{
	uchar c;
	int i;
	ulong address, len;
	ulong len;

	if(readc(pp, &c) != 1)
		return;

	pp->nioregs = 1<<(c&0x1f);
	pp->bit16 = ((c>>5)&3) >= 2;
	ct->nioregs = 1<<(c&0x1f);
	ct->bit16 = ((c>>5)&3) >= 2;
	if((c & 0x80) == 0)
		return;



@@ 1098,23 1124,23 @@ iospaces(Slot *pp)
		return;

	for(i = (c&0xf)+1; i; i--){
		address = getlong(pp, (c>>4)&0x3);
		ct->port = getlong(pp, (c>>4)&0x3);
		len = getlong(pp, (c>>6)&0x3);
		USED(address, len);
		USED(len);
	}
}

static void
irq(Slot *pp)
irq(Slot *pp, Conftab *ct)
{
	uchar c;

	if(readc(pp, &c) != 1)
		return;
	if(c & 0x10)
		pp->irqs = getlong(pp, 2);
		ct->irqs = getlong(pp, 2);
	else
		pp->irqs = 1<<(c&0xf);
		ct->irqs = 1<<(c&0xf);
}

static void


@@ 1135,42 1161,58 @@ void
tentry(Slot *pp, int ttype)
{
	uchar c, i, feature;
	Conftab *ct;

	USED(ttype);

	if(pp->nctab >= Maxctab)
		return;
	if(readc(pp, &c) != 1)
		return;
	if(c&0x40)
		pp->def = 1;
	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? */
	if(c & 0x80){
		if(readc(pp, &i) != 1)
			return;
		if(i&0x80)
			pp->memwait = 1;
			ct->memwait = 1;
	}

	if(readc(pp, &feature) != 1)
		return;
	switch(feature&0x3){
	case 1:
		pp->vpp1 = pp->vpp2 = power(pp);
		ct->vpp1 = ct->vpp2 = power(pp);
		break;
	case 2:
		power(pp);
		pp->vpp1 = pp->vpp2 = power(pp);
		ct->vpp1 = ct->vpp2 = power(pp);
		break;
	case 3:
		power(pp);
		pp->vpp1 = power(pp);
		pp->vpp2 = power(pp);
		ct->vpp1 = power(pp);
		ct->vpp2 = power(pp);
		break;
	default:
		break;
	}
	if(feature&0x4)
		timing(pp);
		timing(pp, ct);
	if(feature&0x8)
		iospaces(pp);
		iospaces(pp, ct);
	if(feature&0x10)
		irq(pp);
		irq(pp, ct);
	switch(feature&0x3){
	case 1:
		memspace(pp, 0, 2, 0);

A pc/ether4100.c => pc/ether4100.c +94 -0
@@ 0,0 1,94 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"

#include "etherif.h"

/*
 * Driver written for the 'national pcmcia ether adapter',
 * The manual says NE2000 compatible.
 * The interface appears to be pretty well described in the National
 * Semiconductor Local Area Network Databook (1992) as one of the
 * AT evaluation cards.
 *
 * The NE2000 is really just a DP8390[12] plus a data port
 * and a reset port.
 */
enum {
	Data		= 0x10,		/* offset from I/O base of data port */
	Misc		= 0x18,		/* offset from I/O base of miscellaneous port */
	Reset		= 0x1f,		/* offset from I/O base of reset port */
};


static int
reset(Ether *ether)
{
	Dp8390 *dp8390;
	ulong port;
	int i, slot;
	uchar x;

	/*
	 * Set up the software configuration.
	 * Use defaults for port, irq, mem and size
	 * if not specified.
	 */
	if(ether->port == 0)
		ether->port = 0x320;
	if(ether->irq == 0)
		ether->irq = 10;
	if(ether->irq == 2)
		ether->irq = 9;
	if(ether->mem == 0)
		ether->mem = 0x4000;
	if(ether->size == 0)
		ether->size = 16*1024;
	port = ether->port;

	ether->private = malloc(sizeof(Dp8390));
	dp8390 = ether->private;
	dp8390->bit16 = 1;
	dp8390->ram = 0;

	dp8390->dp8390 = port;
	dp8390->data = port+Data;

	dp8390->tstart = HOWMANY(ether->mem, Dp8390BufSz);
	dp8390->pstart = dp8390->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
	dp8390->pstop = dp8390->tstart + HOWMANY(ether->size, Dp8390BufSz);

	/* see if there's a pcmcia card that looks right */
	slot = pcmspecial("PC-NIC", ether);
	if(slot < 0)
		return -1;

	/* reset ST-NIC */
	x = inb(ether->port+Reset);
	delay(2);
	outb(ether->port+Reset, x);

	/* enable interrupts */
	outb(ether->port + Misc, 1<<6);

	/* Init the (possible) chip. */
	dp8390reset(ether);

	/* set the ether address */
	for(i = 0; i < sizeof(ether->ea); i++)
		pcmread(slot, 1, &ether->ea[i], 1, 0xff0+2*i);
	dp8390setea(ether);

	return 0;
}

void
ether4100link(void)
{
	addethercard("NE4100", reset);
}

M pc/trap.c => pc/trap.c +8 -7
@@ 259,7 259,7 @@ trap(Ureg *ur)
	char buf[ERRLEN];
	Handler *h;
	static int iret_traps;
	uchar isr0, isr1;
	ushort isr;

	v = ur->trap;



@@ 279,12 279,12 @@ trap(Ureg *ur)
	 *  off at this point)
	 */
	c = v&~0x7;
	isr0 = isr1 = 0x00;
	isr = 0;
	if(c==Int0vec || c==Int1vec){
		isr0 = inb(Int0ctl);
		isr = inb(Int0ctl);
		outb(Int0ctl, EOI);
		if(c == Int1vec){
			isr1 = inb(Int1ctl);
			isr |= inb(Int1ctl)<<8;
			outb(Int1ctl, EOI);
		}
	}


@@ 308,7 308,7 @@ for(;;);
			}
		}

		if(v >= Int0vec || v < Int0vec+16){
		if(v >= Int0vec && v < Int0vec+16){
			/* an unknown interrupt */
			v -= Int0vec;
			/*


@@ 316,13 316,14 @@ for(;;);
			 * the IRQ input goes away before the acknowledge.
			 * In this case, a 'default IRQ7' is generated, but
			 * the corresponding bit in the ISR isn't set.
			 * In fact, just ignore all such interrupts.
			 */
			if(v == 7 && (isr0 & 0x80) == 0)
			if((isr & (1<<v)) == 0)
				goto out;
			if(badintr[v]++ == 0 || (badintr[v]%100000) == 0){
				print("unknown interrupt %d pc=0x%lux: total %d\n", v,
					ur->pc, badintr[v]);
				print("isr0 = 0x%2.2ux, isr1 = 0x%2.2ux\n", isr0, isr1);
				print("isr = 0x%4.4ux\n", isr);
			}
		} else {
			/* unimplemented traps */