~kris/9p

9hist

49ea1f800be1a7b9b314fa2db96378b5cfe977ff — David du Colombier 24 years ago 073c91c
Plan 9 from Bell Labs 2001-10-03
5 files changed, 337 insertions(+), 31 deletions(-)

M pc/devarch.c
M pc/devpccard.c
M pc/devusb.c
M pc/pci.c
M port/devproc.c
M pc/devarch.c => pc/devarch.c +26 -0
@@ 98,6 98,7 @@ addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
void
ioinit(void)
{
	char *excluded;
	int i;

	for(i = 0; i < nelem(iomap.maps)-1; i++)


@@ 109,6 110,31 @@ ioinit(void)
	ioalloc(0x10000, 1, 0, "dummy");
	ioalloc(0x0fff, 1, 0, "dummy");	// i82557 is at 0x1000, the dummy
							// entry is needed for swappable devs.

	if ((excluded = getconf("ioexclude")) != nil) {
		char *s;

		s = excluded;
		while (s && *s != '\0' && *s != '\n') {
			char *ends;
			int io_s, io_e;

			io_s = (int)strtol(s, &ends, 0);
			if (ends == nil || ends == s || *ends != '-') {
				print("ioinit: cannot parse option string\n");
				break;
			}
			s = ++ends;

			io_e = (int)strtol(s, &ends, 0);
			if (ends && *ends == ',')
				*ends++ = '\0';
			s = ends;

			ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated");
		}
	}

}

// Reserve a range to be ioalloced later.  This is in particular useful for exchangable cards, such

M pc/devpccard.c => pc/devpccard.c +32 -25
@@ 45,31 45,22 @@ static variant_t variant[] = {
/* Cardbus registers */
enum {
	SocketEvent = 0,
		SE_CCD = 3 << 1,
		SE_POWER = 1 << 3,
	SocketMask = 1,
	SocketState = 2,
		SS_CCD = 3 << 1,
		SS_POWER = 1 << 3,
		SS_PC16 = 1 << 4,
		SS_CBC = 1 << 5,
		SS_NOTCARD = 1 << 7,
		SS_BADVCC = 1 << 9,
		SS_5V = 1 << 10,
		SS_3V = 1 << 11,
	SocketForce = 3,
	SocketControl = 4,
};

enum {
	SS_CCD = 3 << 1,
	SS_POWER = 1 << 3,
	SS_PC16 = 1 << 4,
	SS_CBC = 1 << 5,
	SS_NOTCARD = 1 << 7,
	SS_BADVCC = 1 << 9,
	SS_5V = 1 << 10,
	SS_3V = 1 << 11,
};

enum {
	SC_5V = 0x22,
	SC_3V = 0x33,
};

enum {
	SE_CCD = SS_CCD,
	SE_POWER = SS_POWER,
		SC_5V = 0x22,
		SC_3V = 0x33,
};

enum {


@@ 523,9 514,14 @@ devpccardlink(void)
		cb->cb_pci = pci;
		cb->cb_variant = &variant[i];
		
		if (intl != -1 && intl != pci->intl)
			intrenable(pci->intl, interrupt, cb, pci->tbdf, "cardbus");
		intl = pci->intl;
		pcicfgw32(pci, PciCBMBR0, 0xffffffff);
		pcicfgw32(pci, PciCBMLR0, 0);
		pcicfgw32(pci, PciCBMBR1, 0xffffffff);
		pcicfgw32(pci, PciCBMLR1, 0);
		pcicfgw32(pci, PciCBIBR0, 0xffffffff);
		pcicfgw32(pci, PciCBILR0, 0);
		pcicfgw32(pci, PciCBIBR1, 0xffffffff);
		pcicfgw32(pci, PciCBILR1, 0);

		// Set up PCI bus numbers if needed.
		if (pcicfgr8(pci, PciSBN) == 0) {


@@ 545,7 541,10 @@ devpccardlink(void)
			if (pci->intl == 0xff || pci->intl == 0)
				print("#Y%d: No interrupt?\n", (int)(cb - cbslots));
		}
	
		if (intl != -1 && intl != pci->intl)
			intrenable(pci->intl, interrupt, cb, pci->tbdf, "cardbus");
		intl = pci->intl;

		if ((baddr = pcicfgr32(cb->cb_pci, PciBAR0)) == 0) {
			int align = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;



@@ 696,6 695,9 @@ configure(cb_t *cb)
		ulong size, bar;
		int memindex, ioindex;

		pcicfgw16(pci, PciPCR, 
				pcicfgr16(pci, PciPCR) & ~(PciPCR_IO|PciPCR_MEM));

		/* Treat the found device as an ordinary PCI card.  It seems that the 
		     CIS is not always present in CardBus cards.  XXX, need to support 
		     multifunction cards */


@@ 711,12 713,15 @@ configure(cb_t *cb)
					continue;
				}
				bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");

				pci->mem[i].bar = bar | 1;
				pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), 
					          pci->mem[i].bar);
				pcicfgw16(cb->cb_pci, PciCBIBR0 + ioindex * 8, bar);
				pcicfgw16(cb->cb_pci, PciCBILR0 + ioindex * 8, 
						 bar + pci->mem[i].size - 1);
				//print("ioindex[%d] %.8uX (%d)\n", 
				//	ioindex, bar, pci->mem[i].size);
				ioindex++;
				continue;
			}


@@ 740,6 745,8 @@ configure(cb_t *cb)
						 pcicfgr16(cb->cb_pci, PciBCR) | 
							          (1 << (8 + memindex)));

			//print("memindex[%d] %.8uX (%d)\n", 
			//	  memindex, bar, pci->mem[i].size);
			memindex++;
		}


M pc/devusb.c => pc/devusb.c +2 -5
@@ 692,7 692,7 @@ isoxmit(Endpt *e, Block *b, int pid)
	td = e->etd;
	if (td == nil)
		panic("usb: isoxmit");
	while(td->status & Active){
	while(td->status & Active && (td->dev & 0x7ff<21) != (0x7ff<21)){
		XPRINT("isoxmit: sleep %lux\n", &e->wr);
		sleep(&e->wr, tdisready, e->etd);
		XPRINT("isoxmit: awake\n");


@@ 707,10 707,7 @@ isoxmit(Endpt *e, Block *b, int pid)
	n = BLEN(b);
	id = (e->x<<7)|(e->dev->x&0x7F);
	td->dev = ((n-1)<<21) | ((id&0x7FF)<<8) | pid;
	if ((ioc++ & 0xff) == 0)
		td->status = ErrLimit3 | Active | IsoSelect | IOC;
	else
		td->status = ErrLimit3 | Active | IsoSelect;
	td->status = ErrLimit1 | Active | IsoSelect | IOC;
	e->etd = td->next;
	return ob;
}

M pc/pci.c => pc/pci.c +276 -0
@@ 507,6 507,279 @@ pciscan(int bno, Pcidev **list)
	return ubn;
}

static uchar 
pIIx_link(Pcidev *router, uchar link)
{
	uchar pirq;

	/* link should be 0x60, 0x61, 0x62, 0x63 */
	pirq = pcicfgr8(router, link);
	return (pirq < 16)? pirq: 0;
}

static void 
pIIx_init(Pcidev *router, uchar link, uchar irq)
{
	pcicfgw8(router, link, irq);
}

static uchar 
via_link(Pcidev *router, uchar link)
{
	uchar pirq;

	/* link should be 1, 2, 3, 5 */
	pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;

	return (link & 1)? (pirq >> 4): (pirq & 15);
}

static void 
via_init(Pcidev *router, uchar link, uchar irq)
{
	uchar pirq;

	pirq = pcicfgr8(router, 0x55 + (link >> 1));
	pirq &= (link & 1)? 0x0f: 0xf0;
	pirq |= (link & 1)? (irq << 4): (irq & 15);
	pcicfgw8(router, 0x55 + (link>>1), pirq);
}

static uchar 
opti_link(Pcidev *router, uchar link)
{
	uchar pirq = 0;

	/* link should be 0x02, 0x12, 0x22, 0x32 */
	if ((link & 0xcf) == 0x02)
		pirq = pcicfgr8(router, 0xb8 + (link >> 5));
	return (link & 0x10)? (pirq >> 4): (pirq & 15);
}

static void 
opti_init(Pcidev *router, uchar link, uchar irq)
{
	uchar pirq;

	pirq = pcicfgr8(router, 0xb8 + (link >> 5));
    	pirq &= (link & 0x10)? 0x0f : 0xf0;
    	pirq |= (link & 0x10)? (irq << 4): (irq & 15);
	pcicfgw8(router, 0xb8 + (link >> 5), pirq);
}

static uchar 
ali_link(Pcidev *router, uchar link)
{
	/* No, you're not dreaming */
	static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
	uchar pirq;

	/* link should be 0x01..0x08 */
	pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
	return (link & 1)? map[pirq&15]: map[pirq>>4];
}

static void 
ali_init(Pcidev *router, uchar link, uchar irq)
{
	/* Inverse of map in ali_link */
	static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
	uchar pirq;

	pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
	pirq &= (link & 1)? 0x0f: 0xf0;
	pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
	pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
}

static uchar 
cyrix_link(Pcidev *router, uchar link)
{
	uchar pirq;

	/* link should be 1, 2, 3, 4 */
	pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
	return ((link & 1)? pirq >> 4: pirq & 15);
}

static void 
cyrix_init(Pcidev *router, uchar link, uchar irq)
{
	uchar pirq;

	pirq = pcicfgr8(router, 0x5c + (link>>1));
	pirq &= (link & 1)? 0x0f: 0xf0;
	pirq |= (link & 1)? (irq << 4): (irq & 15);
	pcicfgw8(router, 0x5c + (link>>1), pirq);
}

enum {
	Intel = 0x8086,		
		Intel_82371FB_0 = 0x122e,
		Intel_82371SB_0 = 0x7000,
		Intel_82371AB_0 = 0x7110,
		Intel_82443MX_1 = 0x7198,
		Intel_82801AA_0 = 0x2410,
		Intel_82801AB_0 = 0x2420,
		Intel_82801BA_0 = 0x2440,
		Intel_82801BAM_0 = 0x244c,
	Viatech = 0x1106,
		Via_82C586_0 = 0x0586,
		Via_82C596 = 0x0596,
		Via_82C686 = 0x0686,
	Opti = 0x1045,
		Opti_82C700 = 0xc700,
	Al = 0x10b9,
		Al_M1533 = 0x1533,
	SI = 0x1039,
		SI_503 = 0x0008,
		SI_496 = 0x0496,
	Cyrix = 0x1078,
		Cyrix_5530_Legacy = 0x0100,
};

typedef struct {
	ushort	sb_vid, sb_did;
	uchar	(*sb_translate)(Pcidev *, uchar);
	void		(*sb_initialize)(Pcidev *, uchar, uchar);	
} bridge_t;

static bridge_t southbridges[] = {
{	Intel, Intel_82371FB_0,		pIIx_link,		pIIx_init },
{	Intel, Intel_82371SB_0,		pIIx_link,		pIIx_init },
{	Intel, Intel_82371AB_0,		pIIx_link,		pIIx_init },
{	Intel, Intel_82443MX_1,		pIIx_link,		pIIx_init },
{	Intel, Intel_82801AA_0,		pIIx_link,		pIIx_init },
{	Intel, Intel_82801AB_0,		pIIx_link,		pIIx_init },
{	Intel, Intel_82801BA_0,		pIIx_link,		pIIx_init },
{	Intel, Intel_82801BAM_0,		pIIx_link,		pIIx_init },
{	Viatech, Via_82C586_0,		via_link,		via_init },
{	Viatech, Via_82C596,		via_link,		via_init },
{	Viatech, Via_82C686,		via_link,		via_init },
{	Opti, Opti_82C700,			opti_link,		opti_init },
{	Al, Al_M1533,				ali_link,		ali_init },
{	SI, SI_503,				pIIx_link,		pIIx_init },
{	SI, SI_496,				pIIx_link,		pIIx_init },
{	Cyrix, Cyrix_5530_Legacy,	cyrix_link,	cyrix_init }
};

typedef struct {
	uchar	e_bus;			// Pci bus number
	uchar	e_dev;			// Pci device number
	uchar	e_maps[12];		// Avoid structs!  Link and mask.
	uchar	e_slot;			// Add-in/built-in slot
	uchar	e_reserved;
} slot_t;

typedef struct {
	uchar	rt_signature[4];	// Routing table signature
	uchar	rt_version[2];		// Version number
	uchar	rt_size[2];			// Total table size
	uchar	rt_bus;			// Interrupt router bus number
	uchar	rt_devfn;			// Router's devfunc
	uchar	rt_pciirqs[2];		// Exclusive PCI irqs
	uchar	rt_compat[4];		// Compatible PCI interrupt router
	uchar	rt_miniport[4];		// Miniport data
	uchar	rt_reserved[11];
	uchar	rt_checksum;
} router_t;

static ushort pciirqs;			// Exclusive PCI irqs
static bridge_t *southbridge;	// Which southbridge to use.

static void
pcirouting(void)
{
	uchar *p, pin, irq;
	ulong tbdf, vdid;
	ushort vid, did;
	router_t *r;
	slot_t *e;
	int size, i, fn;
	Pcidev *sbpci, *pci;

	// Peek in the BIOS
	for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
		if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
			break;

	if (p >= (uchar *)KADDR(0xfffff))
		return;

	r = (router_t *)p;

	// print("PCI interrupt routing table version %d.%d at %.6uX\n",
	// 	r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff);

	tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8);
	vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
	vid = vdid;
	did = vdid >> 16;

	for (i = 0; i != nelem(southbridges); i++)
		if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did)
			break;

	if (i == nelem(southbridges)) {
		print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did);
		return;
	}
	southbridge = &southbridges[i];

	if ((sbpci = pcimatch(nil, vid, did)) == nil) {
		print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n",
			  vid, did);
		return;
	}
	
	pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0];

	size = (r->rt_size[1] << 8)|r->rt_size[0];
	for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) {
		// print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot);
		// for (i = 0; i != 4; i++) {
		// 	uchar *m = &e->e_maps[i * 3];
		// 	print("[%d] %.2uX %.4uX ",
		// 		i, m[0], (m[2] << 8)|m[1]);
		// }
		// print("\n");

		for (fn = 0; fn != 8; fn++) {
			uchar *m;

			// Retrieve the did and vid through the devfn before
			// obtaining the Pcidev structure.
			tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8);
			vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
			if (vdid == 0xFFFFFFFF || vdid == 0) 
				continue;

			vid = vdid;
			did = vdid >> 16;
	
			pci = nil;
			while ((pci = pcimatch(pci, vid, did)) != nil) {

				if (pci->intl != 0 && pci->intl != 0xFF)
					continue;

				pin = pcicfgr8(pci, PciINTP);
				if (pin == 0 || pin == 0xff) 
					continue;
	
				m = &e->e_maps[(pin - 1) * 3];
				irq = southbridge->sb_translate(sbpci, m[0]);
				if (irq) {
					print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n", 
						  vid, did, pin, irq);
					pcicfgw8(pci, PciINTL, irq);
					pci->intl = irq;
				}
			}
		}
	}
}

static void
pcicfginit(void)
{


@@ 610,6 883,9 @@ pcicfginit(void)
		qunlock(&pcicfginitlock);
		return;
	}

	pcirouting();

out:
	qunlock(&pcicfginitlock);
}

M port/devproc.c => port/devproc.c +1 -1
@@ 943,7 943,7 @@ procstopwait(Proc *p, int ctl)

	if(p->pdbg)
		error(Einuse);
	if(procstopped(p))
	if(procstopped(p) || p->state == Broken)
		return;

	if(ctl != 0)