~kris/9p

9hist

83cbbe5909226b38e19b19fc7cb9ac5852655ae9 — David du Colombier 28 years ago 2c32344
Plan 9 from Bell Labs 1998-03-12
5 files changed, 207 insertions(+), 199 deletions(-)

M pc/devi82365.c
M pc/ether589.c
M pc/memory.c
M pc/pci.c
M pc/vgaclgd542x.c
M pc/devi82365.c => pc/devi82365.c +39 -54
@@ 356,7 356,7 @@ pcmmap(int slotno, ulong offset, int len, int attr)
			umbfree(m->isa, m->len);
			m->len = 0;
		}
		m->isa = umbmalloc(0, len, Mgran)&~KZERO;
		m->isa = PADDR(umbmalloc(0, len, Mgran));
		if(m->isa == 0){
			print("pcmmap: out of isa space\n");
			unlock(&pp->mlock);


@@ 515,12 515,12 @@ static char *chipname[] =
static I82365*
i82386probe(int x, int d, int dev)
{
	uchar c;
	uchar c, id;
	I82365 *cp;

	outb(x, Rid + (dev<<7));
	c = inb(d);
	if((c & 0xf0) != 0x80)
	id = inb(d);
	if((id & 0xf0) != 0x80)
		return 0;		/* not this family */

	cp = xalloc(sizeof(I82365));


@@ 530,9 530,10 @@ i82386probe(int x, int d, int dev)
	cp->type = Ti82365;
	cp->nslot = 2;

	switch(c){
	switch(id){
	case 0x82:
	case 0x83:
	case 0x84:
		/* could be a cirrus */
		outb(x, Rchipinfo + (dev<<7));
		outb(d, 0);


@@ 559,7 560,8 @@ i82386probe(int x, int d, int dev)
		outb(d, c|0xC0);
		outb(x, Rid + (dev<<7));
		c = inb(d);
		print("ctlr id %uX\n", c & 0xFF);
		if(c != id && !(c & 0x08))
			print("#y%d: id %uX changed to %uX\n", ncontroller, id, c);
		if(c & 0x08)
			cp->type = Tvg46x;
		outb(x, 0x3A + (dev<<7));


@@ 567,8 569,7 @@ i82386probe(int x, int d, int dev)
		outb(d, c & ~0xC0);
	}

	print("pcmcia controller%d is a %d slot %s\n", ncontroller, cp->nslot,
		chipname[cp->type]);
	print("#y%d: %d slot %s\n", ncontroller, cp->nslot, chipname[cp->type]);

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


@@ 712,7 713,6 @@ pcmread(int slotno, int attr, void *a, long n, ulong offset)
{
	int i, len;
	PCMmap *m;
	ulong ka;
	uchar *ac;
	Slot *pp;



@@ 738,8 738,7 @@ pcmread(int slotno, int attr, void *a, long n, ulong offset)
			i = m->cea - offset;
		else
			i = len;
		ka = KZERO|(m->isa + offset - m->ca);
		memmoveb(ac, (void*)ka, i);
		memmoveb(ac, KADDR(m->isa + offset - m->ca), i);
		pcmunmap(pp->slotno, m);
		offset += i;
		ac += i;


@@ 752,50 751,42 @@ pcmread(int slotno, int attr, void *a, long n, ulong offset)
static long
i82365read(Chan *c, void *a, long n, ulong offset)
{
	char *cp, buf[2048];
	ulong p;
	char *p;
	int len;
	Slot *pp;

	p = TYPE(c);
	switch(p){
	switch(TYPE(c)){
	case Qdir:
		return devdirread(c, a, n, 0, 0, pcmgen);
	case Qmem:
	case Qattr:
		return pcmread(SLOTNO(c), p==Qattr, a, n, offset);
		return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, offset);
	case Qctl:
		cp = buf;
		p = malloc(READSTR);
		len = 0;
		pp = slot + SLOTNO(c);

		if(pp->occupied)
			cp += sprint(cp, "occupied\n");
			len += snprint(p+len, READSTR-len, "occupied\n");
		if(pp->enabled)
			cp += sprint(cp, "enabled\n");
			len += snprint(p+len, READSTR-len, "enabled\n");
		if(pp->powered)
			cp += sprint(cp, "powered\n");
			len += snprint(p+len, READSTR-len, "powered\n");
		if(pp->configed)
			cp += sprint(cp, "configed\n");
			len += snprint(p+len, READSTR-len, "configed\n");
		if(pp->wrprot)
			cp += sprint(cp, "write protected\n");
			len += snprint(p+len, READSTR-len, "write protected\n");
		if(pp->busy)
			cp += sprint(cp, "busy\n");
		cp += sprint(cp, "battery lvl %d\n", pp->battery);
{
	int i;
			len += snprint(p+len, READSTR-len, "busy\n");
		snprint(p+len, READSTR-len, "battery lvl %d\n", pp->battery);

	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");
}
		*cp = 0;
		return readstr(offset, a, n, buf);
	default:
		n=0;
		break;
		n = readstr(offset, a, n, p);
		free(p);

		return n;
	}
	return n;
	error(Ebadarg);
	return -1;	/* not reached */
}

static long


@@ 803,7 794,6 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset)
{
	int i, len;
	PCMmap *m;
	ulong ka;
	uchar *ac;
	Slot *pp;



@@ 829,8 819,7 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset)
			i = m->cea - offset;
		else
			i = len;
		ka = KZERO|(m->isa + offset - m->ca);
		memmoveb((void*)ka, ac, i);
		memmoveb(KADDR(m->isa + offset - m->ca), ac, i);
		pcmunmap(pp->slotno, m);
		offset += i;
		ac += i;


@@ 843,12 832,10 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset)
static long
i82365write(Chan *c, void *a, long n, ulong offset)
{
	ulong p;
	Slot *pp;
	char buf[32];

	p = TYPE(c);
	switch(p){
	switch(TYPE(c)){
	case Qctl:
		if(n >= sizeof(buf))
			n = sizeof(buf) - 1;


@@ 861,20 848,19 @@ i82365write(Chan *c, void *a, long n, ulong offset)
		/* set vpp on card */
		if(strncmp(buf, "vpp", 3) == 0)
			wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena);
		break;
		return n;
	case Qmem:
	case Qattr:
		pp = slot + SLOTNO(c);
		if(pp->occupied == 0 || pp->enabled == 0)
			error(Eio);
		n = pcmwrite(pp->slotno, p == Qattr, a, n, offset);
		n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, offset);
		if(n < 0)
			error(Eio);
		break;
	default:
		error(Ebadusefd);
		return n;
	}
	return n;
	error(Ebadarg);
	return -1;	/* not reached */
}

Dev i82365devtab = {


@@ 1000,7 986,7 @@ pcmio(int slotno, ISAConf *isa)
	if(pp->cpresent & (1<<Rconfig)){
		/*  Reset adapter */
		m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
		p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca));
		p = KADDR(m->isa + pp->caddr + Rconfig - m->ca);

		/* set configuration and interrupt type */
		x = ct->index;


@@ 1056,7 1042,7 @@ cisread(Slot *pp)
	m = pcmmap(pp->slotno, 0, 0, 1);
	if(m == 0)
		return;
	pp->cisbase = (uchar*)(KZERO|m->isa);
	pp->cisbase = KADDR(m->isa);
	pp->cispos = 0;

	/* loop through all the tuples */


@@ 1381,4 1367,3 @@ tvers1(Slot *pp, int ttype)
	}
	pp->verstr[i] = 0;
}


M pc/ether589.c => pc/ether589.c +93 -44
@@ 1,3 1,10 @@
/*
 * 3C589 and 3C562.
 * To do:
 *	check xcvr10Base2 still works (is GlobalReset necessary?).
 *	pull the station address out of the card space for the 3C562,
 *	it has no EEPROM.
 */
#include "u.h"
#include "../port/lib.h"
#include "mem.h"


@@ 9,58 16,100 @@

#include "etherif.h"

enum {
	GlobalReset	= 0x00,		/* Global Reset */
	SelectWindow	= 0x01,		/* SelectWindow command */

	Command		= 0x0E,		/* all windows */
	Status		= 0x0E,

	XcvrTypeMask	= 0xC000,	/* Transceiver Type Select */
	Xcvr10BaseT	= 0x0000,
	XcvrAUI		= 0x4000,
	XcvrBNC		= 0xC000,

	ManufacturerID	= 0x00,		/* window 0 */
	ProductID	= 0x02,
	ConfigControl	= 0x04,
	AddressConfig	= 0x06,
	ResourceConfig	= 0x08,
	EEPROMcmd	= 0x0A,
	EEPROMdata	= 0x0C,

	FIFOdiag	= 0x04,		/* window 4 */
	MediaStatus	= 0x0A,

					/* MediaStatus bits */
	JabberEna	= 0x0040,	/* Jabber Enabled (writeable) */
	LinkBeatEna	= 0x0080,	/* Link Beat Enabled (writeable) */
	LinkBeatOk	= 0x0800,	/* Valid link beat detected (ro) */
enum {						/* all windows */
	CommandR		= 0x000E,
	IntStatusR		= 0x000E,
};

#define COMMAND(port, cmd, a)	outs(port+Command, ((cmd)<<11)|(a))
enum {						/* Commands */
	GlobalReset		= 0x0000,
	SelectRegisterWindow	= 0x0001,
	RxReset			= 0x0005,
	TxReset			= 0x000B,
	AcknowledgeInterrupt	= 0x000D,
};

enum {						/* IntStatus bits */
	commandInProgress	= 0x1000,
};

#define COMMAND(port, cmd, a)	outs((port)+CommandR, ((cmd)<<11)|(a))
#define STATUS(port)		ins((port)+IntStatusR)

enum {						/* Window 0 - setup */
	Wsetup			= 0x0000,
						/* registers */
	ManufacturerID		= 0x0000,	/* 3C5[08]*, 3C59[27] */
	ProductID		= 0x0002,	/* 3C5[08]*, 3C59[27] */
	ConfigControl		= 0x0004,	/* 3C5[08]*, 3C59[27] */
	AddressConfig		= 0x0006,	/* 3C5[08]*, 3C59[27] */
	ResourceConfig		= 0x0008,	/* 3C5[08]*, 3C59[27] */
	EepromCommand		= 0x000A,
	EepromData		= 0x000C,
						/* AddressConfig Bits */
	autoSelect9		= 0x0080,
	xcvrMask9		= 0xC000,
						/* ConfigControl bits */
	Ena			= 0x0001,
	base10TAvailable9	= 0x0200,
	coaxAvailable9		= 0x1000,
	auiAvailable9		= 0x2000,
						/* EepromCommand bits */
	EepromReadRegister	= 0x0080,
	EepromBusy		= 0x8000,
};

enum {						/* Window 1 - operating set */
	Wop			= 0x0001,
};

enum {						/* Window 3 - FIFO management */
	Wfifo			= 0x0003,
						/* registers */
	InternalConfig		= 0x0000,	/* 3C509B, 3C589, 3C59[0257] */
						/* InternalConfig bits */
	xcvr10BaseT		= 0x00000000,
	xcvr10Base2		= 0x00300000,
};

enum {						/* Window 4 - diagnostic */
	Wdiagnostic		= 0x0004,
						/* registers */
	MediaStatus		= 0x000A,
						/* MediaStatus bits */
	linkBeatDetect		= 0x0800,
};

extern int etherelnk3reset(Ether*);

static int
configASIC(Ether *ether, int port, int xcvr)
configASIC(Ether* ether, int port, int xcvr)
{
	int x;

	/* set Window 0 configuration registers */
	COMMAND(port, SelectWindow, 0);
	outs(port+ConfigControl, 1);
	COMMAND(port, SelectRegisterWindow, Wsetup);
	outs(port+ConfigControl, Ena);

	/* IRQ must be 3 on 3C589/3C562 */
	outs(port + ResourceConfig, 0x3F00);

	/* ROM size & base - must be set before we can access ROM */
	/* transceiver type is 2 for 'figure it out'  */
	outs(port + AddressConfig, xcvr);
	x = ins(port+AddressConfig) & ~xcvrMask9;
	x |= (xcvr>>20)<<14;
	outs(port+AddressConfig, x);

	COMMAND(port, TxReset, 0);
	while(STATUS(port) & commandInProgress)
		;
	COMMAND(port, RxReset, 0);
	while(STATUS(port) & commandInProgress)
		;

	return etherelnk3reset(ether);
}

static int
reset(Ether *ether)
reset(Ether* ether)
{
	int slot;
	int port;


@@ 74,27 123,27 @@ reset(Ether *ether)
	if((slot = pcmspecial(ether->type, ether)) < 0)
		return -1;

	/* try configuring as a 10baseT */
	if(configASIC(ether, port, Xcvr10BaseT) < 0){
	/* try configuring as a 10BaseT */
	if(configASIC(ether, port, xcvr10BaseT) < 0){
		pcmspecialclose(slot);
		return -1;
	}
	delay(100);
	COMMAND(port, SelectWindow, 4);
	if(ins(port+MediaStatus) & LinkBeatOk){
		/* reselect window 1 for normal operation */
		COMMAND(port, SelectWindow, 1);
		print("10baseT %s\n", ether->type);
	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
	if(ins(port+MediaStatus) & linkBeatDetect){
		COMMAND(port, SelectRegisterWindow, Wop);
		print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, ether->type);
		return 0;
	}

	/* try configuring as a 10base2 */
	COMMAND(port, GlobalReset, 0);
	if(configASIC(ether, port, XcvrBNC) < 0){
	if(configASIC(ether, port, xcvr10Base2) < 0){
		pcmspecialclose(slot);
		return -1;
	}
	print("BNC %s\n", ether->type);
	print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, ether->type);

	return 0;
}


M pc/memory.c => pc/memory.c +3 -2
@@ 223,7 223,7 @@ umbscan(void)
	 * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
	 * for grabs; check anyway.
	 */
	p = KADDR(0xC8000);
	p = KADDR(0xC0000);
	while(p < (uchar*)KADDR(0xE0000)){
		p[0] = 0xCC;
		p[2*KB-1] = 0xCC;


@@ 235,7 235,8 @@ umbscan(void)
				p += p[2]*512;
				continue;
			}
			mapfree(&rmapumb, PADDR(p), 2*KB);
			if(p[0] == 0xFF && p[1] == 0xFF)
				mapfree(&rmapumb, PADDR(p), 2*KB);
		}
		else
			mapfree(&rmapumbrw, PADDR(p), 2*KB);

M pc/pci.c => pc/pci.c +70 -97
@@ 31,8 31,6 @@ static Pcidev* pciroot;
static Pcidev* pcilist;
static Pcidev* pcitail;

static int pcicfgrw8(int, int, int, int);
static int pcicfgrw16(int, int, int, int);
static int pcicfgrw32(int, int, int, int);

static int


@@ 40,7 38,7 @@ pciscan(int bno, Pcidev** list)
{
	ulong v;
	Pcidev *p, *head, *tail;
	int dno, fno, i, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
	int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;

	maxubn = bno;
	head = nil;


@@ 70,19 68,51 @@ pciscan(int bno, Pcidev** list)
				pcilist = p;
			pcitail = p;

			p->intl = pcicfgrw8(tbdf, PciINTL, 0, 1);
			p->ccru = pcicfgrw16(tbdf, PciCCRu, 0, 1);

			rno = PciBAR0 - 4;
			for(i = 0; i < nelem(p->mem); i++) {
				rno += 4;
				p->mem[i].bar = pcicfgrw32(tbdf, rno, 0, 1);
				if(i > 0 && p->ccru == ((0x06<<8)|0x04))
					continue;
				pcicfgrw32(tbdf, rno, -1, 0);
				v = pcicfgrw32(tbdf, rno, 0, 1);
				pcicfgrw32(tbdf, rno, p->mem[i].bar, 0);
				p->mem[i].size = -(v & ~0xF);
			p->intl = pcicfgr8(p, PciINTL);
			p->ccru = pcicfgr16(p, PciCCRu);

			/*
			 * If the device is a multi-function device adjust the
			 * loop count so all possible functions are checked.
			 */
			hdt = pcicfgr8(p, PciHDT);
			if(hdt & 0x80)
				maxfno = MaxFNO;

			/*
			 * If appropriate, read the base address registers
			 * and work out the sizes.
			 */
			switch(p->ccru>>8){

			case 0x01:		/* mass storage controller */
			case 0x02:		/* network controller */
			case 0x03:		/* display controller */
			case 0x04:		/* multimedia device */
			case 0x07:		/* simple communication controllers */
			case 0x08:		/* base system peripherals */
			case 0x09:		/* input devices */
			case 0x0A:		/* docking stations */
			case 0x0B:		/* processors */
			case 0x0C:		/* serial bus controllers */
				if((hdt & 0x7F) != 0)
					break;
				rno = PciBAR0 - 4;
				for(i = 0; i < nelem(p->mem); i++){
					rno += 4;
					p->mem[i].bar = pcicfgr32(p, rno);
					pcicfgw32(p, rno, -1);
					v = pcicfgr32(p, rno);
					pcicfgw32(p, rno, p->mem[i].bar);
					p->mem[i].size = -(v & ~0xF);
				}
				break;

			case 0x00:
			case 0x05:		/* memory controller */
			case 0x06:		/* bridge device */
			default:
				break;
			}

			if(head != nil)


@@ 90,34 120,14 @@ pciscan(int bno, Pcidev** list)
			else
				head = p;
			tail = p;

			/*
			 * If the device is a multi-function device adjust the
			 * loop count so all possible functions are checked.
			 */
			l = pcicfgrw8(tbdf, PciHDT, 0, 1);
			if(l & 0x80)
				maxfno = MaxFNO;
		}
	}

	*list = head;
	for(p = head; p != nil; p = p->link){
		/*
		 * Find bridges and recursively descend the tree.
		 * Special case the Intel 82454GX Host-to-PCI bridge,
		 * there can be two of them.
		 * Otherwise, only descend PCI-to-PCI bridges.
		 * Find PCI-PCI bridges and recursively descend the tree.
		 */
		if(p->ccru == ((0x06<<8)|0) && p->vid == 0x8086 && p->did == 0x84C4){
			tbdf = p->tbdf;
			if((sbn = pcicfgrw8(tbdf, 0x4A, 0, 1)) == 0)
				continue;
			ubn = pcicfgrw8(tbdf, 0x4B, 0, 1);
			maxubn = ubn;
			pciscan(sbn, &p->bridge);
			continue;
		}
		if(p->ccru != ((0x06<<8)|0x04))
			continue;



@@ 129,9 139,8 @@ pciscan(int bno, Pcidev** list)
		 * buses are behind this one; the final value is set on the way
		 * back up.
		 */
		tbdf = p->tbdf;
		sbn = pcicfgrw8(tbdf, PciSBN, 0, 1);
		ubn = pcicfgrw8(tbdf, PciUBN, 0, 1);
		sbn = pcicfgr8(p, PciSBN);
		ubn = pcicfgr8(p, PciUBN);
		if(sbn == 0 || ubn == 0){
			sbn = maxubn+1;
			/*


@@ 142,13 151,13 @@ pciscan(int bno, Pcidev** list)
			 *
			 * Initialisation of the bridge should be done here.
			 */
			pcicfgrw32(tbdf, PciPCR, 0xFFFF0000, 0);
			pcicfgw32(p, PciPCR, 0xFFFF0000);
			l = (MaxUBN<<16)|(sbn<<8)|bno;
			pcicfgrw32(tbdf, PciPBN, l, 0);
			pcicfgrw16(tbdf, PciSPSR, 0xFFFF, 0);
			pcicfgw32(p, PciPBN, l);
			pcicfgw16(p, PciSPSR, 0xFFFF);
			maxubn = pciscan(sbn, &p->bridge);
			l = (maxubn<<16)|(sbn<<8)|bno;
			pcicfgrw32(tbdf, PciPBN, l, 0);
			pcicfgw32(p, PciPBN, l);
		}
		else{
			maxubn = ubn;


@@ 162,6 171,10 @@ pciscan(int bno, Pcidev** list)
static void
pcicfginit(void)
{
	char *p;
	int bno;
	Pcidev **list;

	lock(&pcicfginitlock);
	if(pcicfgmode == -1){
		/*


@@ 169,7 182,7 @@ pcicfginit(void)
		 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
		 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
		 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
		 * a device behind theses addresses so if Mode2 accesses fail try
		 * a device behind these addresses so if Mode2 accesses fail try
		 * for Mode1 (which is preferred, Mode2 is deprecated).
		 */
		outb(PciCSE, 0);


@@ 185,8 198,18 @@ pcicfginit(void)
			}
		}
	
		if(pcicfgmode > 0)
			pciscan(0, &pciroot);
		if(pcicfgmode > 0){
			if(p = getconf("*pcimaxdno"))
				pcimaxdno = strtoul(p, 0, 0);

			list = &pciroot;
			for(bno = 0; bno < 256; bno++){
				bno = pciscan(bno, list);
				while(*list && (*list)->link)
					list = &(*list)->link;
			}
				
		}
	}
	unlock(&pcicfginitlock);
}


@@ 361,19 384,6 @@ pcicfgw32(Pcidev* pcidev, int rno, int data)
	pcicfgrw32(pcidev->tbdf, rno, data, 0);
}

ulong
pcibarsize(Pcidev* p, int rno)
{
	ulong v, size;

	v = pcicfgrw32(p->tbdf, rno, 0, 1);
	pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
	size = pcicfgrw32(p->tbdf, rno, 0, 1);
	pcicfgrw32(p->tbdf, rno, v, 0);

	return -(size & ~0x0F);
}

Pcidev*
pcimatch(Pcidev* prev, int vid, int did)
{


@@ 423,43 433,6 @@ pcihinv(Pcidev* p)
	}
}

/*
 * Hack for now to get SYMBIOS controller on-line.
 */
void*
pcimemmap(int tbdf, int rno, ulong *paddr)
{
	long size;
	ulong p, v;

	if(pcicfgmode == -1)
		pcicfginit();

	v = pcicfgrw32(tbdf, rno, 0, 1);
	if(v & 1){
		print("pcimemmap: not a memory base register\n");
		return 0;
	}
	if(v & 6){
		print("pcimemmap: only 32 bit relocs supported\n");
		return 0;
	}
	v = 0xFFFFFFFF;
	pcicfgrw32(tbdf, rno, v, 0);
	v = pcicfgrw32(tbdf, rno, 0, 1);
	/*
	 * Clear out bottom bits and negate to find size.
	 * If none can be found could try for UPA memory here.
	 */
	size = -(v & ~0x0F);
	v = umbmalloc(0, size, size);
	p = PADDR(v);
	if(paddr)
		*paddr = p;
	pcicfgrw32(tbdf, rno, p, 0);
	return (void*)v;
}

void
pcireset(void)
{

M pc/vgaclgd542x.c => pc/vgaclgd542x.c +2 -2
@@ 58,8 58,8 @@ clgd542xenable(VGAscr* scr)
	/*
	 * Disable the cursor.
	 */
	sr12 = vgaxi(Seqx, 0x12) & ~0x01;
	vgaxo(Seqx, 0x12, sr12);
	sr12 = vgaxi(Seqx, 0x12);
	vgaxo(Seqx, 0x12, sr12 & ~0x01);

	/*
	 * Cursor colours.