~kris/9p

9hist

005c4a8c265d4856271d391d48985c822480f6ed — David du Colombier 31 years ago 7c2e4ad
Plan 9 from Bell Labs 1995-05-17
5 files changed, 141 insertions(+), 5 deletions(-)

M pc/dat.h
M pc/ether509.c
M pc/fns.h
M pc/io.h
A pc/pci.c
M pc/dat.h => pc/dat.h +1 -0
@@ 7,6 7,7 @@ typedef struct MMU	MMU;
typedef struct Mach	Mach;
typedef struct Notsave	Notsave;
typedef struct PCArch	PCArch;
typedef struct PCIcfg	PCIcfg;
typedef struct PCMmap	PCMmap;
typedef struct Page	Page;
typedef struct PMMU	PMMU;

M pc/ether509.c => pc/ether509.c +49 -4
@@ 369,8 369,9 @@ interrupt(Ureg *ur, void *arg)

typedef struct Adapter Adapter;
struct Adapter {
	Adapter	*next;
	ulong	port;
	Adapter*	next;
	ulong		port;
	PCIcfg*		pcicfg;
};
static Adapter *adapter;



@@ 562,6 563,37 @@ tcm579(Ether *ether)
	return 0;
}

static PCIcfg*
tcm590(Ether *ether)
{
	PCIcfg* pcicfg;
	static uchar devno = 0;
	ulong port;
	Adapter *ap;

	pcicfg = malloc(sizeof(PCIcfg));
	while(devno < 16){
		pcicfg->vid = 0x10B7;
		pcicfg->did = 0;
		if(pcimatch(0, devno++, pcicfg) == 0)
			continue;

		port = pcicfg->baseaddr[0] & ~0x01;
		if(ether->port == 0 || ether->port == port)
			return pcicfg;

		ap = malloc(sizeof(Adapter));
		ap->pcicfg = pcicfg;
		pcicfg = malloc(sizeof(PCIcfg));
		ap->port = port;
		ap->next = adapter;
		adapter = ap;
	}
	free(pcicfg);

	return 0;
}

/*
 * Get configuration parameters.
 */


@@ 573,6 605,7 @@ ether509reset(Ether *ether)
	ushort x, acr;
	ulong port;
	Adapter *ap, **app;
	PCIcfg *pcicfg;

	/*
	 * Any adapter matches if no ether->port is supplied,


@@ 583,9 616,11 @@ ether509reset(Ether *ether)
	 * and finally for a PCMCIA card.
	 */
	port = 0;
	pcicfg = 0;
	for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){
		if(ether->port == 0 || ether->port == ap->port){
			port = ap->port;
			pcicfg = ap->pcicfg;
			*app = ap->next;
			free(ap);
			break;


@@ 593,6 628,8 @@ ether509reset(Ether *ether)
	}
	if(strcmp(ether->type, "3C589") == 0)
		port = ether->port;
	if(port == 0 && (pcicfg = tcm590(ether)))
		port = pcicfg->baseaddr[0] & ~0x01;
	if(port == 0)
		port = tcm579(ether);
	if(port == 0)


@@ 606,7 643,7 @@ ether509reset(Ether *ether)
	 * The EEPROM command is 8 bits, the lower 6 bits being
	 * the address offset.
	 */
	if(strcmp(ether->type, "3C589") != 0)
	if(strcmp(ether->type, "3C589") != 0 && pcicfg == 0)
		ether->irq = (ins(port+ResourceConfig)>>12) & 0x0F;
	for(eax = 0, i = 0; i < 3; i++, eax += 2){
		while(ins(port+EEPROMcmd) & 0x8000)


@@ 618,7 655,15 @@ ether509reset(Ether *ether)
		ea[eax] = (x>>8) & 0xFF;
		ea[eax+1] = x & 0xFF;
	}
	acr = ins(port+AddressConfig);
	if(pcicfg == 0)
		acr = ins(port+AddressConfig);
	else{
		ether->irq = pcicfg->irq;
		acr = Xcvr10BaseT;
		COMMAND(port, SelectWindow, 3);
		print("internal config = 0x%8.8luX\n", inl(port+0x00));
		free(pcicfg);
	}

	/*
	 * Finished with window 0. Now set the ethernet address

M pc/fns.h => pc/fns.h +2 -1
@@ 62,7 62,8 @@ void	outs(int, ushort);
void	outss(int, void*, int);
void	outl(int, ulong);
void	outsl(int, void*, int);
void	pcicreset(void);
void	pcicfgr(uchar, uchar, uchar, uchar, void*, int);
int	pcimatch(uchar, uchar, PCIcfg*);
PCMmap*	pcmmap(int, ulong, int, int);
int	pcmspecial(char*, ISAConf*);
void	pcmspecialclose(int);

M pc/io.h => pc/io.h +37 -0
@@ 33,3 33,40 @@ enum {
	MaxEISA		= 16,
	EISAconfig	= 0xC80,
};

/*
 * PCI Local Bus support.
 * Quick hack until we figure out how to
 * deal with EISA, PCI, PCMCIA, PnP, etc.
 */
enum {					/* configuration mechanism #1 */
	PCIaddr		= 0xCF8,	/* CONFIG_ADDRESS */
	PCIdata		= 0xCFC,	/* CONFIG_DATA */

					/* configuration mechanism #2 */
	PCIcse		= 0xCF8,	/* configuration space enable */
	PCIforward	= 0xCFA,	/* which bus */
};

typedef struct PCIcfg {
	ushort	vid;			/* vendor ID */
	ushort	did;			/* device ID */
	ushort	command;	
	ushort	status;	
	uchar	rid;			/* revision ID */
	uchar	loclass;		/* specific register-level programming interface */
	uchar	subclass;	
	uchar	baseclass;	
	uchar	clsize;			/* cache line size */
	uchar	latency;		/* latency timer */
	uchar	header;			/* header type */
	uchar	bist;			/* built-in self-test */
	ulong	baseaddr[6];		/* memory or I/O base address registers */
	ulong	reserved28[2];	
	ulong	romaddr;		/* expansion ROM base address */
	ulong	reserved34[2];	
	uchar	irq;			/* interrupt line */
	uchar	irp;			/* interrupt pin */
	uchar	mingnt;			/* burst period length */
	uchar	maxlat;			/* maximum latency between bursts */
} PCIcfg;

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

static Lock pcicfglock;

/*
 * Read a chunk of PCI configuration space.
 * Assumes arguments are within limits and regno and
 * nbytes are DWORD aligned.
 */
void
pcicfgr(uchar busno, uchar devno, uchar funcno, uchar regno, void* data, int nbytes)
{
	ulong base, *p;
	int len;

	lock(&pcicfglock);
	outb(PCIcse, 0x80|((funcno & 0x07)<<1));
	outb(PCIforward, busno);

	base = (0xC000|(devno<<8)) + regno;
	p = data;
	for(len = nbytes/sizeof(ulong); len > 0; len--){
		*p = inl(base);
		p++;
		base += sizeof(ulong);
	}

	outb(PCIcse, 0x00);
	unlock(&pcicfglock);
}

int
pcimatch(uchar busno, uchar devno, PCIcfg* pcicfg)
{
	ulong l;

	l = 0;
	pcicfgr(busno, devno, 0, 0, &l, sizeof(ulong));
	if((l & 0xFFFF) != pcicfg->vid)
		return 0;
	if(pcicfg->did && ((l>>16) & 0xFFFF) != pcicfg->did)
		return 0;
	pcicfgr(busno, devno, 0, 0, pcicfg, sizeof(PCIcfg));

	return 1;
}