Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/alphapc/arch164.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname alphapc/arch164.c 1999/0415
## diff -e /dev/null /n/emeliedump/1999/0415/sys/src/brazil/alphapc/arch164.c
0a
/*
 *	EB164 and similar
 *	CPU:	21164
 *	Core Logic: 21172 CIA or 21174 PYXIS
  */
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"

static ulong *core;
static ulong *wind;

static ulong windsave[16];
static ulong coresave[1];

ulong	iobase0;
ulong	iobase1;
#define	iobase(p)	(iobase0+(p))

static int
ident(void)
{
	return 0;	/* bug! */
}

static void *
kmapio(ulong space, ulong offset, int size)
{
	return kmapv(((uvlong)space<<32LL)|offset, size);
}

static void
coreinit(void)
{
	int i;

	core = kmapio(0x87, 0x40000000, 0x10000);
	wind = kmapio(0x87, 0x60000000, 0x1000);

	iobase0 = (ulong)kmapio(0x89, 0, 0x20000);

	/* hae_io = core[0x440/4];
	iobase1 = (ulong)kmapio(0x89, hae_io, 0x10000); */

	/* save critical parts of hardware memory mapping */
	for (i = 4; i < 8; i++) {
		windsave[4*(i-4)+0] = wind[(i*0x100+0x00)/4];
		windsave[4*(i-4)+1] = wind[(i*0x100+0x40)/4];
		windsave[4*(i-4)+2] = wind[(i*0x100+0x80)/4];
	}
	coresave[0] = core[0x140/4];

	/* direct map bottom 2G PCI target space to KZERO in window 1 */
	wind[0x500/4] = KZERO|1;
	wind[0x540/4] = 0x7ff00000;
	wind[0x580/4] = 0;

	/* disable other windows */
	wind[0x400/4] = 0;
	wind[0x600/4] = 0;
	wind[0x700/4] = 0;

	/* clear error state */
	core[0x8200/4] = 0x7ff;

	/* set config: byte/word enable, no monster window, etc. */
	core[0x140/4] = 1;

	/* turn off mcheck on master abort.  now we can probe PCI space. */
	core[0x8280/4] &= ~(1<<7);

	/* set up interrupts. */
	i8259init();
	cserve(52, 4);		/* enable SIO interrupt */
}

static void
corehello(void)
{
	print("cpu%d: CIA revision %d; cnfg %lux cntrl %lux\n",
			0,	/* BUG */
			core[0x80/4] & 0x7f, core[0x140/4], core[0x100/4]);
	print("cpu%d: HAE_IO %lux\n", 0, core[0x440/4]);
	print("\n");
}

static void
coredetach(void)
{
	int i;

	for (i = 4; i < 8; i++) {
		wind[(i*0x100+0x00)/4] = windsave[4*(i-4)+0];
		wind[(i*0x100+0x40)/4] = windsave[4*(i-4)+1];
		wind[(i*0x100+0x80)/4] = windsave[4*(i-4)+2];
	}
	core[0x140/4] = coresave[0];
/*	for (i = 0; i < 4; i++)
		if (i != 4)
			cserve(53, i);		/* disable interrupts */
}

static Lock	pcicfgl;
static ulong	pcimap[256];

static void*
pcicfg2117x(int tbdf, int rno)
{
	int space, bus;
	ulong base;

	bus = BUSBNO(tbdf);
	lock(&pcicfgl);
	base = pcimap[bus];
	if (base == 0) {
		if(bus)
			space = 0x8B;
		else
			space = 0x8A;
		pcimap[bus] = base = (ulong)kmapio(space, MKBUS(0, bus, 0, 0), (1<<16));
	}
	unlock(&pcicfgl);
	return (void*)(base + BUSDF(tbdf) + rno);
}

static void*
pcimem2117x(int addr, int len)
{
	return kmapio(0x88, addr, len);
}

/*
 *	interrupts -- adapted from PC, needs work.
 */

static Lock irqctllock;
static Irqctl *irqctl[256];
static char irqmask[3];

static void
intr164(Ureg *ur)
{
	int i, v;
	Irqctl *ctl;
	Irq *irq;
	Mach *mach;

	v = (ulong)ur->a1>>4;
	if (v < 0x80) {
		iprint("unknown device intr v %d\n", v);
		return;
	}
	v -= 0x80;
	if(v < 256 && (ctl = irqctl[v])){
		if(ctl->isintr){
			m->intr++;
			if(ctl->isr)
				ctl->isr(v);
/*				if(v >= VectorPIC && v <= MaxVectorPIC)
				m->lastintr = v-VectorPIC; */
		}

		for(irq = ctl->irq; irq; irq = irq->next)
			irq->f(ur, irq->a);

		if(ctl->eoi)
			ctl->eoi(v);
	}
	else if(v >= VectorPIC && v <= MaxVectorPIC){
		/*
		 * An unknown interrupt.
		 * Check for a default IRQ7. This can happen when
		 * 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.
		 */
		iprint("cpu%d: spurious interrupt %d, last %d",
			m->machno, v-VectorPIC, 0 /*m->lastintr*/);
		for(i = 0; i < 32; i++){
			if(!(active.machs & (1<<i)))
				continue;
			mach = MACHP(i);
			if(m->machno == mach->machno)
				continue;
			iprint(": cpu%d: last %d", mach->machno, 0 /*mach->lastintr*/);
		}
		iprint("\n");
/*			m->spuriousintr++; */
		return;
	}
	else{
		dumpregs(ur);
		panic("unknown intr: %d\n", v); /* */
	}
}

static int
intrenable164(int v, void (*f)(Ureg*, void*), void*a, int tbdf)
{
	Irq * irq;
	Irqctl *ctl;

	lock(&irqctllock);
	if(irqctl[v] == 0){
		ctl = xalloc(sizeof(Irqctl));
/* this is all wrong; FIXME! */
		if(BUSTYPE(tbdf) == BusPCI)
			cserve(52, v-VectorPCI);
		else if(v >= VectorPIC && i8259enable(v, tbdf, ctl) == -1){
			unlock(&irqctllock);
			iprint("intrenable: didn't find v %d, tbdf 0x%uX\n", v, tbdf);
			xfree(ctl);
			return -1;
		}
		irqctl[v] = ctl;
	}
	ctl = irqctl[v];
	irq = xalloc(sizeof(Irq));
	irq->f = f;
	irq->a = a;
	irq->next = ctl->irq;
	ctl->irq = irq;
	unlock(&irqctllock);
	return 0;
}

/*
 *	I have a function pointer in PCArch for every one of these, because on
 *	some Alphas we have to use sparse mode, but on others we can use
 *	MOVB et al.  Additionally, the PC164 documentation threatened us
 *	with the lie that the SIO is in region B, but everything else in region A.
 *	This turned out not to be the case.  Given the cost of this solution, it
 *	may be better just to use sparse mode for I/O space on all platforms.
 */
int
inb2117x(int port)
{
	mb();
	return *(uchar*)(iobase(port));
}

ushort
ins2117x(int port)
{
	mb();
	return *(ushort*)(iobase(port));
}

ulong
inl2117x(int port)
{
	mb();
	return *(ulong*)(iobase(port));
}

void
outb2117x(int port, int val)
{
	mb();
	*(uchar*)(iobase(port)) = val;
}

void
outs2117x(int port, ushort val)
{
	mb();
	*(ushort*)(iobase(port)) = val;
}

void
outl2117x(int port, ulong val)
{
	mb();
	*(ulong*)(iobase(port)) = val;
}

void
insb2117x(int port, void *buf, int len)
{
	int i;
	uchar *p, *q;

	p = (uchar*)iobase(port);
	q = buf;
	for(i = 0; i < len; i++){
		mb();
		*q++ = *p;
	}
}

void
inss2117x(int port, void *buf, int len)
{
	int i;
	ushort *p, *q;

	p = (ushort*)iobase(port);
	q = buf;
	for(i = 0; i < len; i++){
		mb();
		*q++ = *p;
	}
}

void
insl2117x(int port, void *buf, int len)
{
	int i;
	ulong *p, *q;

	p = (ulong*)iobase(port);
	q = buf;
	for(i = 0; i < len; i++){
		mb();
		*q++ = *p;
	}
}

void
outsb2117x(int port, void *buf, int len)
{
	int i;
	uchar *p, *q;

	p = (uchar*)iobase(port);
	q = buf;
	for(i = 0; i < len; i++){
		mb();
		*p = *q++;
	}
}

void
outss2117x(int port, void *buf, int len)
{
	int i;
	ushort *p, *q;

	p = (ushort*)iobase(port);
	q = buf;
	for(i = 0; i < len; i++){
		mb();
		*p = *q++;
	}
}

void
outsl2117x(int port, void *buf, int len)
{
	int i;
	ulong *p, *q;

	p = (ulong*)iobase(port);
	q = buf;
	for(i = 0; i < len; i++){
		mb();
		*p = *q++;
	}
}

PCArch arch164 = {
	"EB164",
	ident,
	coreinit,
	corehello,
	coredetach,
	pcicfg2117x,
	pcimem2117x,
	intr164,
	intrenable164,

	inb2117x,
	ins2117x,
	inl2117x,
	outb2117x,
	outs2117x,
	outl2117x,
	insb2117x,
	inss2117x,
	insl2117x,
	outsb2117x,
	outss2117x,
	outsl2117x,
};
.
## diffname alphapc/arch164.c 1999/0423
## diff -e /n/emeliedump/1999/0415/sys/src/brazil/alphapc/arch164.c /n/emeliedump/1999/0423/sys/src/brazil/alphapc/arch164.c
279a
	mb();
.
272a
	mb();
.
265a
	mb();
.
65a
#endif /* notdef */
.
57,59c
#ifdef notdef
	/* direct map bottom 1G PCI target space to KZERO in window 1 */
	wind[0x500/4] = PCIWINDOW|1;
	wind[0x540/4] = 0x3ff00000;
.
## diffname alphapc/arch164.c 1999/0424
## diff -e /n/emeliedump/1999/0423/sys/src/brazil/alphapc/arch164.c /n/emeliedump/1999/0424/sys/src/brazil/alphapc/arch164.c
63,67c
sginit();
.
57c
	/* disable windows */
	wind[0x400/4] = 0;
	wind[0x500/4] = 0;
	wind[0x600/4] = 0;
	wind[0x700/4] = 0;

.
29a
static uvlong* sgmap;

static void
sginit(void)
{
	ulong pa;
	uvlong *pte;

	sgmap = xspanalloc(BY2PG, BY2PG, 0);
	memset(sgmap, 0, BY2PG);

	pte = sgmap;
	for(pa = 0; pa < 8*1024*1024; pa += BY2PG)
		*pte++ = ((pa>>PGSHIFT)<<1)|1;

	wind[0x400/4] = ISAWINDOW|2;
	wind[0x440/4] = 0x00700000;
	wind[0x480/4] = PADDR(sgmap);
}

.
## diffname alphapc/arch164.c 1999/0501
## diff -e /n/emeliedump/1999/0424/sys/src/brazil/alphapc/arch164.c /n/emeliedump/1999/0501/sys/src/brazil/alphapc/arch164.c
101a
}

void
ciaerror(void)
{
	print("cia error 0x%luX\n", core[0x8200/4]);
.
94c
	core[0x140/4] = 0x21;
.
45c
	wind[0x400/4] = ISAWINDOW|4|2|1;
.
## diffname alphapc/arch164.c 1999/0507
## diff -e /n/emeliedump/1999/0501/sys/src/brazil/alphapc/arch164.c /n/emeliedump/1999/0507/sys/src/brazil/alphapc/arch164.c
113c
	print("cpu%d: CIA revision %ld; cnfg %lux cntrl %lux\n",
.
47c
	wind[0x480/4] = PADDR(sgmap)>>2;

	wind[0x100/4] = 3;	/* invalidate tlb cache */
.
45c
	wind[0x400/4] = ISAWINDOW|2|1;
.
## diffname alphapc/arch164.c 1999/0511
## diff -e /n/emeliedump/1999/0507/sys/src/brazil/alphapc/arch164.c /n/emeliedump/1999/0511/sys/src/brazil/alphapc/arch164.c
49c
	wind[0x100/4] = 3;			/* invalidate tlb cache */
.
47c
	wind[0x480/4] = PADDR(sgmap)>>2;	/* why the shift? */
.
## diffname alphapc/arch164.c 2000/0401
## diff -e /n/emeliedump/1999/0511/sys/src/brazil/alphapc/arch164.c /n/emeliedump/2000/0401/sys/src/9/alphapc/arch164.c
408d
253,260c
	return vec;
.
250,251d
204,248c
	else {
		vec = irq+VectorPIC;
		if(i8259enable(irq, v->tbdf, v) == -1)
.
188,202c
	if(BUSTYPE(v->tbdf) == BusPCI) {
		vec = irq+VectorPCI;
		cserve(52, irq);
.
183,186c
	irq = v->irq;
	if(irq > MaxIrqPIC) {
		print("intrenable: irq %d out of range\n", v->irq);
		return -1;
.
178,181c
	int vec, irq;
.
167,176c
static int
intrenable164(Vctl *v)
.
## diffname alphapc/arch164.c 2000/0515
## diff -e /n/emeliedump/2000/0401/sys/src/9/alphapc/arch164.c /n/emeliedump/2000/0515/sys/src/9/alphapc/arch164.c
89,90d
85c
	sginit();

	/*
	 * Set up a map for PCI DMA accesses to physical memory.
	 * Addresses presented by a PCI device between PCIWINDOW
	 * and PCIWINDOW+1GB will be translated to between 0 and
	 * 0+1GB of physical memory.
	 */
.
45,47c
	/*
	 * Set up a map for ISA DMA accesses to physical memory.
	 * Addresses presented by an ISA device between ISAWINDOW
	 * and ISAWINDOW+8MB will be translated to between 0 and
	 * 0+8MB of physical memory.
	 */
	wind[0x400/4] = ISAWINDOW|2|1;		/* window base */
	wind[0x440/4] = 0x00700000;		/* window mask */
	wind[0x480/4] = PADDR(sgmap)>>2;	/* <33:10> of sg map */
.
40a
	/*
	 * Prepare scatter-gather map for 0-8MB.
	 */
.
## diffname alphapc/arch164.c 2001/1023
## diff -e /n/emeliedump/2000/0515/sys/src/9/alphapc/arch164.c /n/emeliedump/2001/1023/sys/src/9/alphapc/arch164.c
348a
	nil,
	nil,
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].