~kris/9p

9hist

551d878a4d92a0f60889d81b0ca8b228a8781d79 — David du Colombier 27 years ago 8c13714
Plan 9 from Bell Labs 1999-01-21
M carrera/l.s => carrera/l.s +1 -0
@@ 103,6 103,7 @@ TEXT	splhi(SB), $0

TEXT	splx(SB), $0
	MOVW	R31, 12(R(MACH))	/* save PC in m->splpc */
	/* fall though */

TEXT	splxpc(SB), $0			/* for iunlock */
	MOVW	M(STATUS), R2

A mpc/clock.c => mpc/clock.c +152 -0
@@ 0,0 1,152 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"

typedef struct Clock0link Clock0link;
typedef struct Clock0link {
	void		(*clock)(void);
	Clock0link*	link;
} Clock0link;

static Clock0link *clock0link;
static Lock clock0lock;
ulong	clkrelinq;
void	(*kproftick)(ulong);	/* set by devkprof.c when active */
long	clkvv;
ulong	clkhigh;

void
addclock0link(void (*clock)(void))
{
	Clock0link *lp;

	if((lp = malloc(sizeof(Clock0link))) == 0){
		print("addclock0link: too many links\n");
		return;
	}
	ilock(&clock0lock);
	lp->clock = clock;
	lp->link = clock0link;
	clock0link = lp;
	iunlock(&clock0lock);
}

void
delay(int l)
{
	ulong i, j;

	j = m->delayloop;
	while(l-- > 0)
		for(i=0; i < j; i++)
			;
}

void
microdelay(int l)
{
	ulong i;

	l *= m->delayloop;
	l /= 1000;
	if(l <= 0)
		l = 1;
	for(i = 0; i < l; i++)
		;
}

enum {
	Timebase = 4,	/* system clock cycles per time base cycle */
};

static	ulong	clkreload;

void
clockinit(void)
{
	long x, est;

	est = m->cpuhz/1000;	/* initial estimate */
	m->delayloop = est;
	do {
		x = gettbl();
		delay(10);
		x = gettbl() - x;
	} while(x < 0);

	/*
	 *  fix count
	 */
	m->delayloop = (m->delayloop*10*est)/(x*Timebase);
	if(m->delayloop == 0)
		m->delayloop = 1;

	clkreload = (m->clockgen/Timebase)/HZ-1;
	putdec(clkreload);
}

void
clockintr(Ureg *ur)
{
	Clock0link *lp;
	long v;

	v = (clkvv = -getdec());
	if(v > clkreload)
		clkhigh++;
	if(v > clkreload/2){
		if(v > clkreload)
			m->ticks += v/clkreload;
		v = 0;
	}
	putdec(clkreload-v);

	m->ticks++;
	if(m->ticks%MS2TK(1000) == 0)
		m->bcsr[4] ^= DisableLamp;

	if(up)
		up->pc = ur->pc;

	checkalarms();
	if(m->machno == 0) {
		if(kproftick != nil)
			(*kproftick)(ur->pc);
		lock(&clock0lock);
		for(lp = clock0link; lp; lp = lp->link)
			lp->clock();
		unlock(&clock0lock);
	}

	if(up && up->state == Running){
//		if(up->type == Interp && tready())
//			ur->cr |= 1<<(31-31);
		if(nrdy > 0)
			sched();
	}
}

void
clockcheck(void)
{
	/* called by ../port/taslock.c: reset watchdog here, if it's enabled */
}

void
clkprint(void)
{
	print("clkr=%ld clkvv=%ld clkhigh=%lud\n", clkreload, clkvv, clkhigh);
	print("\n");
}

uvlong
fastticks(uvlong *hz)
{
	if(hz)
		*hz = HZ;
	return m->ticks;
}

A mpc/cpm.c => mpc/cpm.c +563 -0
@@ 0,0 1,563 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"

enum {
	BDSIZE=	1024,	/* IO memory reserved for buffer descriptors */
	CPMSIZE=	1024,	/* IO memory reserved for other uses */
};

static	Map	bdmapv[BDSIZE/sizeof(BD)];
static	RMap	bdmap = {"buffer descriptors"};

static	Map	cpmmapv[CPMSIZE/sizeof(ulong)];
static	RMap	cpmmap = {"CPM memory"};

static	Lock	cpmlock;

static struct {
	Lock;
	ulong	avail;
} brgens;

static struct {
	Lock;
	ulong	clash;	/* disable bits for mutually-exclusive options */
	ulong	active;	/* disable bit for current owner, or 0 */
	void	(*stop)(void*);
	void*	arg;
} scc2owner;

static	void	i2cspireloc(void);

/*
 * initialise the communications processor module
 * and associated device registers
 */
void
cpminit(void)
{
	IMM *io;

	io = m->iomem;
	io->rccr = 0;
	io->rmds = 0;
	io->lccr &= ~1;	/* disable LCD */
	io->sdcr = 1;
	io->pcint = 0;	/* disable all port C interrupts */
	io->pcso = 0;
	io->pcdir =0;
	io->pcpar = 0;
	io->papar = 0;
	io->padir = 0;
	io->pbpar = 0;
	io->pbdir = 0;
	io->tgcr = 0x2222;	/* reset timers, low-power stop */
	eieio();

	for(io->cpcr = 0x8001; io->cpcr & 1;)	/* reset all CPM channels */
		eieio();

	mapinit(&bdmap, bdmapv, sizeof(bdmapv));
	mapfree(&bdmap, DPBASE, BDSIZE);
	mapinit(&cpmmap, cpmmapv, sizeof(cpmmapv));
	mapfree(&cpmmap, DPBASE+BDSIZE, CPMSIZE);

	if(m->cputype == 0x50 && (getimmr() & 0xFFFF) <= 0x2001)
		brgens.avail = 0x3;
	else
		brgens.avail = 0xF;

	scc2owner.clash = DisableEther|DisableIR|DisableRS232b;

	i2cspireloc();
}

/*
 * issue a request to a CPM device
 */
void
cpmop(int op, int cno, int param)
{
	IMM *io;

	ilock(&cpmlock);
	io = m->iomem;
	while(io->cpcr & 1)
		eieio();
	io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
	eieio();
	while(io->cpcr & 1)
		eieio();
	iunlock(&cpmlock);
}

/*
 * lock the shared IO memory and return a reference to it
 */
IMM*
ioplock(void)
{
	ilock(&cpmlock);
	return m->iomem;
}

/*
 * release the lock on the shared IO memory
 */
void
iopunlock(void)
{
	eieio();
	iunlock(&cpmlock);
}

/*
 * connect SCCx clocks in NSMI mode (x=1 for USB)
 */
void
sccnmsi(int x, int rcs, int tcs)
{
	IMM *io;
	ulong v;
	int sh;

	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
	v = (((rcs&7)<<3) | (tcs&7)) << sh;
	io = ioplock();
	io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
	iopunlock();
}

/*
 * request or grab (if force!=0) the use of SCC2
 * for the mode (uart, ether, etc) defined by the enable bits.
 * the `stop' function is invoked with the given argument
 * when the device is lost to another driver.
 */
int
scc2claim(int force, ulong enable, void (*stop)(void*), void *arg)
{
	ulong clash;

	clash = scc2owner.clash & ~enable;
	ilock(&scc2owner);
	if(~m->bcsr[1] & clash){
		if(!force){
			iunlock(&scc2owner);
			return 0;
		}
		/* notify current owner */
		if(scc2owner.stop)
			scc2owner.stop(scc2owner.arg);
		m->bcsr[1] |= clash;
	}
	scc2owner.stop = stop;
	scc2owner.arg = arg;
	scc2owner.active = enable;
	m->bcsr[1] &= ~enable;	/* the bits are active low */
	iunlock(&scc2owner);
	/* beware: someone else can claim it during the `successful' return */
	return 1;
}

/*
 * if SCC2 is currently enabled, shut it down
 */
void
scc2stop(void *a)
{
	SCC *scc;

	scc = a;
	if(scc->gsmrl & (3<<4)){
		cpmop(GracefulStopTx, SCC2ID, 0);
		cpmop(CloseRxBD, SCC2ID, 0);
		delay(1);
		scc->gsmrl &= ~(3<<4);	/* disable current use */
		m->bcsr[1] |= scc2owner.clash;
	}
}

/*
 * yield up control of SCC2
 */
void
scc2free(void)
{
	ilock(&scc2owner);
	m->bcsr[1] |= scc2owner.active;
	scc2owner.active = 0;
	iunlock(&scc2owner);
}

/*
 * allocate a buffer descriptor
 */
BD *
bdalloc(int n)
{
	ulong a;

	a = rmapalloc(&bdmap, 0, n*sizeof(BD), sizeof(BD));
	if(a == 0)
		panic("bdalloc");
	return KADDR(a);
}

/*
 * free a buffer descriptor
 */
void
bdfree(BD *b, int n)
{
	if(b){
		eieio();
		mapfree(&bdmap, PADDR(b), n*sizeof(BD));
	}
}

/*
 * allocate memory from the shared IO memory space
 */
void *
cpmalloc(int n, int align)
{
	ulong a;

	a = rmapalloc(&cpmmap, 0, n, align);
	if(a == 0)
		panic("cpmalloc");
	return KADDR(a);
}

/*
 * free previously allocated shared memory
 */
void
cpmfree(void *p, int n)
{
	if(p != nil && n > 0){
		eieio();
		mapfree(&cpmmap, PADDR(p), n);
	}
}

/*
 * allocate a baud rate generator, returning its index
 * (or -1 if none is available)
 */
int
brgalloc(void)
{
	int n;

	lock(&brgens);
	for(n=0; brgens.avail!=0; n++)
		if(brgens.avail & (1<<n)){
			brgens.avail &= ~(1<<n);
			unlock(&brgens);
			return n;
		}
	unlock(&brgens);
	return -1;
}

/*
 * free a previously allocated baud rate generator
 */
void
brgfree(int n)
{
	if(n >= 0){
		if(n > 3 || brgens.avail & (1<<n))
			panic("brgfree");
		lock(&brgens);
		brgens.avail |= 1 << n;
		unlock(&brgens);
	}
}

/*
 * return a value suitable for loading into a baud rate
 * generator to produce the given rate if the generator
 * is prescaled by the given amount (typically 16).
 * the value must be or'd with BaudEnable to start the generator.
 */
ulong
baudgen(int rate, int scale)
{
	int d;

	rate *= scale;
	d = (2*m->cpuhz+rate)/(2*rate) - 1;
	if(d < 0)
		d = 0;
	if(d >= (1<<12))
		return ((d+15)>>(4-1))|1;	/* divider too big: enable prescale by 16 */
	return d<<1;
}

/*
 * initialise receive and transmit buffer rings.
 */
int
ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
{
	int i, x;

	/* the ring entries must be aligned on sizeof(BD) boundaries */
	r->nrdre = nrdre;
	if(r->rdr == nil)
		r->rdr = bdalloc(nrdre);
	if(r->rrb == nil)
		r->rrb = malloc(nrdre*bufsize);
	dcflush(r->rrb, nrdre*bufsize);
	if(r->rdr == nil || r->rrb == nil)
		return -1;
	x = PADDR(r->rrb);
	for(i = 0; i < nrdre; i++){
		r->rdr[i].length = 0;
		r->rdr[i].addr = x;
		r->rdr[i].status = BDEmpty|BDInt;
		x += bufsize;
	}
	r->rdr[i-1].status |= BDWrap;
	r->rdrx = 0;

	r->ntdre = ntdre;
	if(r->tdr == nil)
		r->tdr = bdalloc(ntdre);
	if(r->txb == nil)
		r->txb = malloc(ntdre*sizeof(Block*));
	if(r->tdr == nil || r->txb == nil)
		return -1;
	for(i = 0; i < ntdre; i++){
		r->txb[i] = nil;
		r->tdr[i].addr = 0;
		r->tdr[i].length = 0;
		r->tdr[i].status = 0;
	}
	r->tdr[i-1].status |= BDWrap;
	r->tdrh = 0;
	r->tdri = 0;
	r->ntq = 0;
	return 0;
}

/*
 * Allocate a new parameter block for I2C or SPI,
 * and plant a pointer to it for the microcode,
 * returning the kernel address.
 * See motorola errata and microcode package:
 * the design botch is that the parameters for the SCC2 ethernet overlap the
 * SPI/I2C parameter space; this compensates by relocating the latter.
 * This routine may be used iff i2cspireloc is used (and it is, above).
 */
void*
cpmparam(ulong olda, int nb)
{
	void *p;

	if(olda < INTMEM)
		olda += INTMEM;
	if(olda != SPIP && olda != I2CP)
		return KADDR(olda);
	p = cpmalloc(nb, 32);	/* ``RPBASE must be multiple of 32'' */
	if(p == nil)
		return p;
	*(ushort*)KADDR(olda+0x2C) = PADDR(p);	/* set RPBASE */
	eieio();
	return p;
}

/*
 * I2C/SPI microcode package from Motorola
 * (to relocate I2C/SPI parameters), which was distributed
 * on their web site in S-record format.
 *
 *	May 1998
 */

/*S00600004844521B*/
static	ulong	ubase1 = 0x2000;
static	ulong	ucode1[] = {
 /* #02202000 */ 0x7FFFEFD9,
 /* #02202004 */ 0x3FFD0000,
 /* #02202008 */ 0x7FFB49F7,
 /* #0220200C */ 0x7FF90000,
 /* #02202010 */ 0x5FEFADF7,
 /* #02202014 */ 0x5F89ADF7,
 /* #02202018 */ 0x5FEFAFF7,
 /* #0220201C */ 0x5F89AFF7,
 /* #02202020 */ 0x3A9CFBC8,
 /* #02202024 */ 0xE7C0EDF0,
 /* #02202028 */ 0x77C1E1BB,
 /* #0220202C */ 0xF4DC7F1D,
 /* #02202030 */ 0xABAD932F,
 /* #02202034 */ 0x4E08FDCF,
 /* #02202038 */ 0x6E0FAFF8,
 /* #0220203C */ 0x7CCF76CF,
 /* #02202040 */ 0xFD1FF9CF,
 /* #02202044 */ 0xABF88DC6,
 /* #02202048 */ 0xAB5679F7,
 /* #0220204C */ 0xB0937383,
 /* #02202050 */ 0xDFCE79F7,
 /* #02202054 */ 0xB091E6BB,
 /* #02202058 */ 0xE5BBE74F,
 /* #0220205C */ 0xB3FA6F0F,
 /* #02202060 */ 0x6FFB76CE,
 /* #02202064 */ 0xEE0DF9CF,
 /* #02202068 */ 0x2BFBEFEF,
 /* #0220206C */ 0xCFEEF9CF,
 /* #02202070 */ 0x76CEAD24,
 /* #02202074 */ 0x90B2DF9A,
 /* #02202078 */ 0x7FDDD0BF,
 /* #0220207C */ 0x4BF847FD,
 /* #02202080 */ 0x7CCF76CE,
 /* #02202084 */ 0xCFEF7E1F,
 /* #02202088 */ 0x7F1D7DFD,
 /* #0220208C */ 0xF0B6EF71,
 /* #02202090 */ 0x7FC177C1,
 /* #02202094 */ 0xFBC86079,
 /* #02202098 */ 0xE722FBC8,
 /* #0220209C */ 0x5FFFDFFF,
 /* #022020A0 */ 0x5FB2FFFB,
 /* #022020A4 */ 0xFBC8F3C8,
 /* #022020A8 */ 0x94A67F01,
 /* #022020AC */ 0x7F1D5F39,
 /* #022020B0 */ 0xAFE85F5E,
 /* #022020B4 */ 0xFFDFDF96,
 /* #022020B8 */ 0xCB9FAF7D,
 /* #022020BC */ 0x5FC1AFED,
 /* #022020C0 */ 0x8C1C5FC1,
 /* #022020C4 */ 0xAFDD5FC3,
 /* #022020C8 */ 0xDF9A7EFD,
 /* #022020CC */ 0xB0B25FB2,
 /* #022020D0 */ 0xFFFEABAD,
 /* #022020D4 */ 0x5FB2FFFE,
 /* #022020D8 */ 0x5FCE600B,
 /* #022020DC */ 0xE6BB600B,
 /* #022020E0 */ 0x5FCEDFC6,
 /* #022020E4 */ 0x27FBEFDF,
 /* #022020E8 */ 0x5FC8CFDE,
 /* #022020EC */ 0x3A9CE7C0,
 /* #022020F0 */ 0xEDF0F3C8,
 /* #022020F4 */ 0x7F0154CD,
 /* #022020F8 */ 0x7F1D2D3D,
 /* #022020FC */ 0x363A7570,
 /* #02202100 */ 0x7E0AF1CE,
 /* #02202104 */ 0x37EF2E68,
 /* #02202108 */ 0x7FEE10EC,
 /* #0220210C */ 0xADF8EFDE,
 /* #02202110 */ 0xCFEAE52F,
 /* #02202114 */ 0x7D0FE12B,
 /* #02202118 */ 0xF1CE5F65,
 /* #0220211C */ 0x7E0A4DF8,
 /* #02202120 */ 0xCFEA5F72,
 /* #02202124 */ 0x7D0BEFEE,
 /* #02202128 */ 0xCFEA5F74,
 /* #0220212C */ 0xE522EFDE,
 /* #02202130 */ 0x5F74CFDA,
 /* #02202134 */ 0x0B627385,
 /* #02202138 */ 0xDF627E0A,
 /* #0220213C */ 0x30D8145B,
 /* #02202140 */ 0xBFFFF3C8,
 /* #02202144 */ 0x5FFFDFFF,
 /* #02202148 */ 0xA7F85F5E,
 /* #0220214C */ 0xBFFE7F7D,
 /* #02202150 */ 0x10D31450,
 /* #02202154 */ 0x5F36BFFF,
 /* #02202158 */ 0xAF785F5E,
 /* #0220215C */ 0xBFFDA7F8,
 /* #02202160 */ 0x5F36BFFE,
 /* #02202164 */ 0x77FD30C0,
 /* #02202168 */ 0x4E08FDCF,
 /* #0220216C */ 0xE5FF6E0F,
 /* #02202170 */ 0xAFF87E1F,
 /* #02202174 */ 0x7E0FFD1F,
 /* #02202178 */ 0xF1CF5F1B,
 /* #0220217C */ 0xABF80D5E,
 /* #02202180 */ 0x5F5EFFEF,
 /* #02202184 */ 0x79F730A2,
 /* #02202188 */ 0xAFDD5F34,
 /* #0220218C */ 0x47F85F34,
 /* #02202190 */ 0xAFED7FDD,
 /* #02202194 */ 0x50B24978,
 /* #02202198 */ 0x47FD7F1D,
 /* #0220219C */ 0x7DFD70AD,
 /* #022021A0 */ 0xEF717EC1,
 /* #022021A4 */ 0x6BA47F01,
 /* #022021A8 */ 0x2D267EFD,
 /* #022021AC */ 0x30DE5F5E,
 /* #022021B0 */ 0xFFFD5F5E,
 /* #022021B4 */ 0xFFEF5F5E,
 /* #022021B8 */ 0xFFDF0CA0,
 /* #022021BC */ 0xAFED0A9E,
 /* #022021C0 */ 0xAFDD0C3A,
 /* #022021C4 */ 0x5F3AAFBD,
 /* #022021C8 */ 0x7FBDB082,
 /* #022021CC */ 0x5F8247F8,
};

/*S00600004844521B*/
static	ulong	ubase2 = 0x2F00;
static	ulong	ucode2[] = {
 /* #02202F00 */ 0x3E303430,
 /* #02202F04 */ 0x34343737,
 /* #02202F08 */ 0xABF7BF9B,
 /* #02202F0C */ 0x994B4FBD,
 /* #02202F10 */ 0xBD599493,
 /* #02202F14 */ 0x349FFF37,
 /* #02202F18 */ 0xFB9B177D,
 /* #02202F1C */ 0xD9936956,
 /* #02202F20 */ 0xBBFDD697,
 /* #02202F24 */ 0xBDD2FD11,
 /* #02202F28 */ 0x31DB9BB3,
 /* #02202F2C */ 0x63139637,
 /* #02202F30 */ 0x93733693,
 /* #02202F34 */ 0x193137F7,
 /* #02202F38 */ 0x331737AF,
 /* #02202F3C */ 0x7BB9B999,
 /* #02202F40 */ 0xBB197957,
 /* #02202F44 */ 0x7FDFD3D5,
 /* #02202F48 */ 0x73B773F7,
 /* #02202F4C */ 0x37933B99,
 /* #02202F50 */ 0x1D115316,
 /* #02202F54 */ 0x99315315,
 /* #02202F58 */ 0x31694BF4,
 /* #02202F5C */ 0xFBDBD359,
 /* #02202F60 */ 0x31497353,
 /* #02202F64 */ 0x76956D69,
 /* #02202F68 */ 0x7B9D9693,
 /* #02202F6C */ 0x13131979,
 /* #02202F70 */ 0x79376935,
};

/*
 * compensate for chip design botch by installing
 * microcode to relocate I2C and SPI parameters away
 * from the ethernet parameters
 */
static void
i2cspireloc(void)
{
	IMM *io;
	static int done;

	if(done)
		return;
	io = m->iomem;
	io->rccr &= ~3;
	memmove((uchar*)m->iomem+ubase1, ucode1, sizeof(ucode1));
	memmove((uchar*)m->iomem+ubase2, ucode2, sizeof(ucode2));
	io->rctr1 = 0x802a;	/* relocate SPI */
	io->rctr2 = 0x8028;	/* relocate SPI */
	io->rctr3 = 0x802e;	/* relocate I2C */
	io->rctr4 = 0x802c;	/* relocate I2C */
	io->rccr |= 1;
	done = 1;
}

A mpc/dat.h => mpc/dat.h +217 -0
@@ 0,0 1,217 @@
typedef struct Conf	Conf;
typedef struct FPsave	FPsave;
typedef struct IMM	IMM;
typedef struct Irqctl	Irqctl;
typedef struct ISAConf	ISAConf;
typedef struct Label	Label;
typedef struct Lock	Lock;
typedef struct Mach	Mach;
typedef struct Notsave	Notsave;
typedef struct PMMU	PMMU;
typedef struct Map	Map;
typedef struct PCArch	PCArch;
typedef struct Proc	Proc;
typedef struct RMap RMap;
typedef struct Ureg	Ureg;

#define	MACHP(n)	(n==0? &mach0 : *(Mach**)0)

/*
 *  parameters for sysproc.c
 */
#define AOUT_MAGIC	(Q_MAGIC)


struct	Lock
{
	ulong	key;
	ulong	pc;
	ulong	sr;
	Proc	*p;
	ushort	isilock;
};

struct	Label
{
	ulong	sp;
	ulong	pc;
};

/*
 *  things saved in the Proc structure during a notify
 */
struct Notsave
{
	ulong	UNUSED;
};

/*
 *  MMU stuff in proc
 */
#define NCOLOR 1
struct PMMU
{
	ulong	UNUSED;
};

/*
 * FPsave.status
 */
enum
{
	FPinit,
	FPactive,
	FPinactive,
};

/*
 * This structure must agree with fpsave and fprestore asm routines
 */
struct	FPsave
{
	double	fpreg[32];
	union {
		double	fpscrd;
		struct {
			ulong	pad;
			ulong	fpscr;
		};
	};
	int	fpistate;	/* emulated fp */
	ulong	emreg[32][3];	/* emulated fp */
};

struct Conf
{
	ulong	nmach;		/* processors */
	ulong	nproc;		/* processes */
	ulong	npage0;		/* total physical pages of memory */
	ulong	npage1;		/* total physical pages of memory */
	ulong	npage;		/* total physical pages of memory */
	ulong	upages;		/* user page pool */
	ulong	nimage;		/* number of page cache image headers */
	ulong	nswap;		/* number of swap pages */
	int	nswppo;		/* max # of pageouts per segment pass */
	ulong	base0;		/* base of bank 0 */
	ulong	base1;		/* base of bank 1 */
	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
	ulong	ialloc;		/* max interrupt time allocation in bytes */
	ulong	interps;	/* number of interpreter processes */
	ulong	pipeqsize;	/* size in bytes of pipe queues */
};

#include "../port/portdat.h"

/*
 *  machine dependent definitions not used by ../port/dat.h
 */

struct Mach
{
	/* OFFSETS OF THE FOLLOWING KNOWN BY l.s */
	int	machno;			/* physical id of processor (unused) */
	ulong	splpc;			/* pc of last caller to splhi (unused) */
	int	mmask;			/* 1<<m->machno (unused) */

	/* ordering from here on irrelevant */
	ulong	ticks;			/* of the clock since boot time */
	Proc	*proc;			/* current process on this processor */
	Label	sched;			/* scheduler wakeup */
	Lock	alarmlock;		/* access to alarm list */
	void	*alarm;			/* alarms bound to this clock */
	int	nrdy;
	int	speed;	/* general system clock in MHz */
	long	oscclk;	/* oscillator frequency (MHz) */
	long	cpuhz;	/* general system clock (cycles) */
	long	clockgen;	/* clock generator frequency (cycles) */
	int	cputype;
	ulong	delayloop;
	ulong*	bcsr;
	IMM*	iomem;	/* MPC8xx internal i/o control memory */

	ulong	fairness;		/* for runproc */

	int	tlbfault;
	int	tlbpurge;
	int	pfault;
	int	cs;
	int	syscall;
	int	load;
	int	intr;
	vlong	fastclock;		/* last sampled value */
	int	flushmmu;		/* make current proc flush it's mmu state */

	/* MUST BE LAST */
	int	stack[1];
};
extern	Mach	mach0;

/*
 * Fake kmap
 */
typedef void		KMap;
#define	VA(k)		((ulong)(k))
#define	kmap(p)		(KMap*)((p)->pa)
#define	kunmap(k)

/*
 *  routines for things outside the PowerPC model
 */
struct PCArch
{
	char*	id;
	int	(*ident)(void);		/* this should be in the model */
	void	(*reset)(void);		/* this should be in the model */
	int	(*serialpower)(int);	/* 1 == on, 0 == off */
	int	(*modempower)(int);	/* 1 == on, 0 == off */

	void	(*intrinit)(void);
	int	(*intrenable)(int, int, Irqctl*);

	void	(*clockenable)(void);
};

/*
 *  a parsed .ini line
 */
#define ISAOPTLEN	16
#define NISAOPT		8

struct ISAConf {
	char	type[NAMELEN];
	ulong	port;
	ulong	irq;
	ulong	mem;
	int	dma;
	ulong	size;
	ulong	freq;
	uchar	bus;

	int	nopt;
	char	opt[NISAOPT][ISAOPTLEN];
};

struct Map {
	int	size;
	ulong	addr;
};

struct RMap {
	char*	name;
	Map*	map;
	Map*	mapend;

	Lock;
};

struct
{
	Lock;
	short	machs;
	short	exiting;
	short	ispanic;
}active;

extern register Mach	*m;
extern register Proc	*up;


A mpc/devether.c => mpc/devether.c +447 -0
@@ 0,0 1,447 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"

#include "etherif.h"

static Ether *etherxx[MaxEther];

void ethermediumlink(void);

Chan*
etherattach(char* spec)
{
	ulong ctlrno;
	char *p;
	Chan *chan;

	ctlrno = 0;
	if(spec && *spec){
		ctlrno = strtoul(spec, &p, 0);
		if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
			error(Ebadarg);
	}
	if(etherxx[ctlrno] == 0)
		error(Enodev);

	chan = devattach('l', spec);
	chan->dev = ctlrno;
	if(etherxx[ctlrno]->attach)
		etherxx[ctlrno]->attach(etherxx[ctlrno]);
	return chan;
}

static void
etherdetach(void)
{
	Ether **ether;

	ether = etherxx;
	while(*ether){
		if((*ether)->detach)
			(*ether)->detach(*ether);
		ether++;
	}
}

static int
etherwalk(Chan* chan, char* name)
{
	return netifwalk(etherxx[chan->dev], chan, name);
}

static void
etherstat(Chan* chan, char* dp)
{
	netifstat(etherxx[chan->dev], chan, dp);
}

static Chan*
etheropen(Chan* chan, int omode)
{
	return netifopen(etherxx[chan->dev], chan, omode);
}

static void
ethercreate(Chan*, char*, int, ulong)
{
}

static void
etherclose(Chan* chan)
{
	Ether *ether;

	ether = etherxx[chan->dev];
	netifclose(ether, chan);
	if(ether->closed)
		ether->closed(ether);
}

static long
etherread(Chan* chan, void* buf, long n, vlong offset)
{
	Ether *ether;

	ether = etherxx[chan->dev];
	if((chan->qid.path & CHDIR) == 0 && ether->ifstat){
		/*
		 * With some controllers it is necessary to reach
		 * into the chip to extract statistics.
		 */
		if(NETTYPE(chan->qid.path) == Nifstatqid)
			return ether->ifstat(ether, buf, n, offset);
		else if(NETTYPE(chan->qid.path) == Nstatqid)
			ether->ifstat(ether, buf, 0, offset);
	}

	return netifread(ether, chan, buf, n, offset);
}

static Block*
etherbread(Chan* chan, long n, ulong offset)
{
	return netifbread(etherxx[chan->dev], chan, n, offset);
}

static void
etherremove(Chan*)
{
}

static void
etherwstat(Chan* chan, char* dp)
{
	netifwstat(etherxx[chan->dev], chan, dp);
}

static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
	int i, n;
	Block *bp;

	if(qwindow(f->in) <= 0)
		return;
	if(len > 64)
		n = 64;
	else
		n = len;
	bp = iallocb(n);
	if(bp == 0)
		return;
	memmove(bp->wp, pkt->d, n);
	i = TK2MS(MACHP(0)->ticks);
	bp->wp[58] = len>>8;
	bp->wp[59] = len;
	bp->wp[60] = i>>24;
	bp->wp[61] = i>>16;
	bp->wp[62] = i>>8;
	bp->wp[63] = i;
	bp->wp += 64;
	qpass(f->in, bp);
}

Block*
etheriq(Ether* ether, Block* bp, int freebp)
{
	Etherpkt *pkt;
	ushort type;
	int len;
	Netfile **ep, *f, **fp, *fx;
	Block *xbp;

	ether->inpackets++;

	pkt = (Etherpkt*)bp->rp;
	len = BLEN(bp);
	type = (pkt->type[0]<<8)|pkt->type[1];
	fx = 0;
	ep = &ether->f[Ntypes];

	/* check for valid multcast addresses */
	if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
		if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
			if(freebp){
				freeb(bp);
				bp = 0;
			}
			return bp;
		}
	}

	/*
	 * Multiplex the packet to all the connections which want it.
	 * If the packet is not to be used subsequently (freebp != 0),
	 * attempt to simply pass it into one of the connections, thereby
	 * saving a copy of the data (usual case hopefully).
	 */
	for(fp = ether->f; fp < ep; fp++){
		if((f = *fp) && (f->type == type || f->type < 0)){
			if(f->type > -2){
				if(freebp && fx == 0)
					fx = f;
				else if(xbp = iallocb(len)){
					memmove(xbp->wp, pkt, len);
					xbp->wp += len;
					qpass(f->in, xbp);
				}
				else
					ether->soverflows++;
			}
			else
				etherrtrace(f, pkt, len);
		}
	}

	if(fx){
		qpass(fx->in, bp);
		return 0;
	}
	if(freebp){
		freeb(bp);
		return 0;
	}

	return bp;
}

static int
etheroq(Ether* ether, Block* bp)
{
	int len, loopback, s;
	Etherpkt *pkt;

	ether->outpackets++;

	/*
	 * Check if the packet has to be placed back onto the input queue,
	 * i.e. if it's a loopback or broadcast packet or the interface is
	 * in promiscuous mode.
	 * If it's a loopback packet indicate to etheriq that the data isn't
	 * needed and return, etheriq will pass-on or free the block.
	 */
	pkt = (Etherpkt*)bp->rp;
	len = BLEN(bp);
	loopback = (memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0);
	if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
		s = splhi();
		etheriq(ether, bp, loopback);
		splx(s);
	}

	if(!loopback){
		qbwrite(ether->oq, bp);
		ether->transmit(ether);
	}

	return len;
}

static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
	Ether *ether;
	Block *bp;

	ether = etherxx[chan->dev];
	if(NETTYPE(chan->qid.path) != Ndataqid)
		return netifwrite(ether, chan, buf, n);

	if(n > ETHERMAXTU)
		error(Etoobig);
//	if(n < ETHERMINTU)
//		error(Etoosmall);

	bp = allocb(n);
	if(waserror()){
		freeb(bp);
		nexterror();
	}
	memmove(bp->rp, buf, n);
	memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
	poperror();
	bp->wp += n;

	return etheroq(ether, bp);
}

static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
	Ether *ether;
	long n;

	n = BLEN(bp);

	ether = etherxx[chan->dev];
	if(NETTYPE(chan->qid.path) != Ndataqid){
		n = netifwrite(ether, chan, bp->rp, n);
		freeb(bp);
		return n;
	}

	if(n > ETHERMAXTU){
		freeb(bp);
		error(Ebadarg);
	}

	return etheroq(ether, bp);
}

static struct {
	char*	type;
	int	(*reset)(Ether*);
} cards[MaxEther+1];

void
addethercard(char* t, int (*r)(Ether*))
{
	static int ncard;

	if(ncard == MaxEther)
		panic("too many ether cards");
	cards[ncard].type = t;
	cards[ncard].reset = r;
	ncard++;
}

int
parseether(uchar *to, char *from)
{
	char nip[4];
	char *p;
	int i;

	p = from;
	for(i = 0; i < 6; i++){
		if(*p == 0)
			return -1;
		nip[0] = *p++;
		if(*p == 0)
			return -1;
		nip[1] = *p++;
		nip[2] = 0;
		to[i] = strtoul(nip, 0, 16);
		if(*p == ':')
			p++;
	}
	return 0;
}

static void
etherreset(void)
{
	Ether *ether;
	int i, n, ctlrno;
	char name[NAMELEN], buf[128];

	//ethermediumlink();
	for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
		if(ether == 0)
			ether = malloc(sizeof(Ether));
		memset(ether, 0, sizeof(Ether));
		ether->ctlrno = ctlrno;
		ether->tbdf = BUSUNKNOWN;
		ether->mbps = 10;
		if(isaconfig("ether", ctlrno, ether) == 0)
			continue;
		for(n = 0; cards[n].type; n++){
			if(cistrcmp(cards[n].type, ether->type))
				continue;
			for(i = 0; i < ether->nopt; i++){
				if(strncmp(ether->opt[i], "ea=", 3))
					continue;
				if(parseether(ether->ea, &ether->opt[i][3]) == -1)
					memset(ether->ea, 0, Eaddrlen);
			}	
			if(cards[n].reset(ether))
				break;

			intrenable(ether->irq, ether->interrupt, ether, ether->tbdf);

			i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
				ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
			if(ether->mem)
				i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
			if(ether->size)
				i += sprint(buf+i, " size 0x%luX", ether->size);
			i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",
				ether->ea[0], ether->ea[1], ether->ea[2],
				ether->ea[3], ether->ea[4], ether->ea[5]);
			sprint(buf+i, "\n");
			print(buf);

			snprint(name, sizeof(name), "ether%d", ctlrno);
			if(ether->mbps == 100){
				netifinit(ether, name, Ntypes, 256*1024);
				if(ether->oq == 0)
					ether->oq = qopen(256*1024, 1, 0, 0);
			}
			else{
				netifinit(ether, name, Ntypes, 32*1024);
				if(ether->oq == 0)
					ether->oq = qopen(64*1024, 1, 0, 0);
			}
			if(ether->oq == 0)
				panic("etherreset %s", name);
			ether->alen = Eaddrlen;
			memmove(ether->addr, ether->ea, Eaddrlen);
			memset(ether->bcast, 0xFF, Eaddrlen);

			etherxx[ctlrno] = ether;
			ether = 0;
			break;
		}
	}
	if(ether)
		free(ether);
}

#define POLY 0xedb88320

/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
	int i, j;
	ulong crc, b;

	crc = 0xffffffff;
	for(i = 0; i < len; i++){
		b = *p++;
		for(j = 0; j < 8; j++){
			crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
			b >>= 1;
		}
	}
	return crc;
}

Dev etherdevtab = {
	'l',
	"ether",

	etherreset,
	devinit,
	etherattach,
	/*etherdetach,*/
	devclone,
	etherwalk,
	etherstat,
	etheropen,
	ethercreate,
	etherclose,
	etherread,
	etherbread,
	etherwrite,
	etherbwrite,
	etherremove,
	etherwstat,
};

A mpc/devrtc.c => mpc/devrtc.c +180 -0
@@ 0,0 1,180 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

#include	"io.h"

/*
 * MPC8xx real time clock
 * FADS board option switch
 * interrupt statistics
 */

enum{
	Qrtc = 1,
	Qswitch,
	Qintstat,

	/* sccr */
	RTDIV=	1<<24,
	RTSEL=	1<<23,

	/* rtcsc */
	RTE=	1<<0,
	R38K=	1<<4,
};

static	QLock	rtclock;		/* mutex on clock operations */

static Dirtab rtcdir[]={
	"rtc",		{Qrtc, 0},	12,	0666,
	"switch",	{Qswitch, 0}, 0, 0444,
	"intstat",	{Qintstat, 0}, 0, 0444,
};
#define	NRTC	(sizeof(rtcdir)/sizeof(rtcdir[0]))

static void
rtcreset(void)
{
	IMM *io;
	int n;

	io = m->iomem;
	io->rtcsck = KEEP_ALIVE_KEY;
	n = (RTClevel<<8)|RTE;
	if(m->oscclk == 5)
		n |= R38K;
	io->rtcsc = n;
	io->rtcsck = ~KEEP_ALIVE_KEY;
print("sccr=#%8.8lux plprcr=#%8.8lux\n", io->sccr, io->plprcr);
}

static Chan*
rtcattach(char *spec)
{
	return devattach('r', spec);
}

static int	 
rtcwalk(Chan *c, char *name)
{
	return devwalk(c, name, rtcdir, NRTC, devgen);
}

static void	 
rtcstat(Chan *c, char *dp)
{
	devstat(c, dp, rtcdir, NRTC, devgen);
}

static Chan*
rtcopen(Chan *c, int omode)
{
	omode = openmode(omode);
	switch(c->qid.path){
	case Qrtc:
		if(strcmp(up->user, eve)!=0 && omode!=OREAD)
			error(Eperm);
		break;
	case Qswitch:
	case Qintstat:
		if(omode!=OREAD)
			error(Eperm);
		break;
	}
	return devopen(c, omode, rtcdir, NRTC, devgen);
}

static void	 
rtcclose(Chan*)
{
}

static long	 
rtcread(Chan *c, void *buf, long n, vlong offset)
{
	ulong t;
	char *b;

	if(c->qid.path & CHDIR)
		return devdirread(c, buf, n, rtcdir, NRTC, devgen);

	switch(c->qid.path){
	case Qrtc:
		t = m->iomem->rtc;
		n = readnum(offset, buf, n, t, 12);
		return n;
	case Qswitch:
		return readnum(offset, buf, n, (m->bcsr[2]>>19)&0xF, 12);
	}
	error(Egreg);
	return 0;		/* not reached */
}

static long	 
rtcwrite(Chan *c, void *buf, long n, vlong offset)
{
	ulong secs;
	char *cp, *ep;
	IMM *io;

	switch(c->qid.path){
	case Qrtc:
		if(offset!=0)
			error(Ebadarg);
		/*
		 *  read the time
		 */
		cp = ep = buf;
		ep += n;
		while(cp < ep){
			if(*cp>='0' && *cp<='9')
				break;
			cp++;
		}
		secs = strtoul(cp, 0, 0);
		/*
		 * set it
		 */
		io = ioplock();
		io->rtck = KEEP_ALIVE_KEY;
		io->rtc = secs;
		io->rtck = ~KEEP_ALIVE_KEY;
		iopunlock();
		return n;
	case Qswitch:
		return 0;
	}
	error(Egreg);
	return 0;		/* not reached */
}

long
rtctime(void)
{
	return m->iomem->rtc;
}

Dev rtcdevtab = {
	'r',
	"rtc",

	rtcreset,
	devinit,
	rtcattach,
	devclone,
	rtcwalk,
	rtcstat,
	rtcopen,
	devcreate,
	rtcclose,
	rtcread,
	devbread,
	rtcwrite,
	devbwrite,
	devremove,
	devwstat,
};

A mpc/etherif.h => mpc/etherif.h +28 -0
@@ 0,0 1,28 @@
enum {
	MaxEther	= 24,
	Ntypes		= 8,
};

typedef struct Ether Ether;
struct Ether {
	ISAConf;			/* hardware info */
	int	ctlrno;
	int	tbdf;			/* type+busno+devno+funcno */
	int	mbps;			/* Mbps */
	uchar	ea[Eaddrlen];

	void	(*attach)(Ether*);	/* filled in by reset routine */
	void	(*closed)(Ether*);
	void	(*detach)(Ether*);
	void	(*transmit)(Ether*);
	void	(*interrupt)(Ureg*, void*);
	long	(*ifstat)(Ether*, void*, long, ulong);
	void	*ctlr;

	Queue*	oq;

	Netif;
};

extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));

A mpc/fns.h => mpc/fns.h +91 -0
@@ 0,0 1,91 @@
#include "../port/portfns.h"

void	archinit(void);
int	brgalloc(void);
void	brgfree(int);
ulong	baudgen(int, int);
int	cistrcmp(char*, char*);
int	cistrncmp(char*, char*, int);
void	clockcheck(void);
void	clockinit(void);
void	clockintr(Ureg*);
void	clrfptrap(void);
#define coherence()		// not need on signle processor machines
void	cpminit(void);
int	cpuidentify(void);
void	cpuidprint(void);
void	dcflush(void*, ulong);
void	delay(int);
ulong	draminit(ulong*);
void	dtlbmiss(void);
void	dumpregs(Ureg*);
void	eieio(void);
void	evenaddr(ulong);
void	faultpower(Ureg*);
void	firmware(int);
void	fpinit(void);
int	fpipower(Ureg*);
void	fpoff(void);
ulong	fpstatus(void);
char*	getconf(char*);
ulong	getdar(void);
ulong	getdec(void);
ulong	getdepn(void);
ulong	getdsisr(void);
ulong	getimmr(void);
ulong	getmsr(void);
ulong	getpvr(void);
ulong	gettbl(void);
ulong	gettbu(void);
void	gotopc(ulong);
void	icflush(void*, ulong);
void	idle(void);
int	iprint(char*, ...);
void	intr(Ureg*);
void	intrenable(int, void (*)(Ureg*, void*), void*, int);
int	intrstats(char*, int);
void	intrvec(void);
void	itlbmiss(void);
int	isaconfig(char*, int, ISAConf*);
void	kbdinit(void);
void	kbdreset(void);
void	links(void);
void	mapfree(RMap*, ulong, int);
void	mapinit(RMap*, Map*, int);
void	mathinit(void);
void	mmuinit(void);
ulong*	mmuwalk(ulong*, ulong, int);
#define	procrestore(p)
void	procsave(Proc*);
void	procsetup(Proc*);
void	putdec(ulong);
void	putmsr(ulong);
ulong	rmapalloc(RMap*, ulong, int, int);
void	screeninit(void);
void	setpanic(void);
int	screenprint(char*, ...);			/* debugging */
#define screenputs(x, y)		// no screen
ulong	sdraminit(ulong*);
int	segflush(void*, ulong);
void	spireset(void);
long	spioutin(void*, long, void*);
int	tas(void*);
void	trapinit(void);
void	trapvec(void);
void	uartinstall(void);
void	uartwait(void);	/* debugging */
void	wbflush(void);

#define	waserror()	(up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
ulong	getcallerpc(void*);

// identity map between kernel physical and virtual addresses
#define KADDR(a)	((void*)(a))
#define PADDR(a)	((ulong)(a))

/* IBM bit field order */
#define	IBIT(b)		((ulong)1<<(31-(b)))
#define	SIBIT(n)	((ushort)1<<(15-(n)))

/* compatibility with inf2.1 */
#define	bpenumenv(n)	((char*)0)

A mpc/io.h => mpc/io.h +556 -0
@@ 0,0 1,556 @@
typedef struct BD BD;
typedef struct Ring Ring;
typedef struct GTimer GTimer;

enum
{
	/* interrupt vectors (SIU and CPM) */
	VectorPIC= 0,	/* level 0 to level 7, assigned by software */
		/* vector assignments are determined by the assignments here */
		PITlevel=	2,
		CPIClevel=	4,
		PCMCIAlevel=	6,
		RTClevel=	7,
	VectorIRQ=	VectorPIC+8,	/* IRQ0 to IRQ7 */
	VectorCPIC=	VectorIRQ+8,	/* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
};

/*
 * these are defined to keep the interface compatible with other
 * architectures, but only BUSUNKNOWN is currently used
 */
#define MKBUS(t,b,d,f)	(((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
#define BUSFNO(tbdf)	(((tbdf)>>8)&0x07)
#define BUSDNO(tbdf)	(((tbdf)>>11)&0x1F)
#define BUSBNO(tbdf)	(((tbdf)>>16)&0xFF)
#define BUSTYPE(tbdf)	((tbdf)>>24)
#define BUSBDF(tbdf)	((tbdf)&0x00FFFF00)
#define BUSUNKNOWN	(-1)

/*
 * Buffer Descriptors and IO Rings
 */

struct BD {
	ushort	status;
	ushort	length;
	ulong	addr;
};

BD*	bdalloc(int);
void	bdfree(BD*, int);

enum {
	/* Rx BDs, bits common to all protocols */
	BDEmpty=	1<<15,
	BDWrap=		1<<13,
	BDInt=		1<<12,
	BDLast=		1<<11,
	BDFirst=		1<<10,

	/* Tx BDs */
	BDReady=		1<<15,
	/* BDWrap, BDInt, BDLast */
};


struct Ring {
	BD*	rdr;				/* receive descriptor ring */
	void*	rrb;				/* receive ring buffers */
	int	rdrx;				/* index into rdr */
	int	nrdre;			/* length of rdr */

	BD*	tdr;				/* transmit descriptor ring */
	Block**	txb;				/* corresponding transmit ring buffers */
	int	tdrh;				/* host index into tdr */
	int	tdri;				/* interface index into tdr */
	int	ntdre;			/* length of tdr */
	int	ntq;				/* pending transmit requests */
};

#define NEXT(x, l)	(((x)+1)%(l))
#define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
#define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
#define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))

int	ioringinit(Ring*, int, int, int);

/*
 * CPM
 */
enum {
	/* commands */
	InitRxTx =	0,
	InitRx =		1,
	InitTx =		2,
	EnterHunt=	3,
	StopTx=		4,
	GracefulStopTx = 5,
	InitIDMA =	5,
	RestartTx =	6,
	CloseRxBD =	7,
	SetGroupAddr = 8,
	SetTimer =	8,
	GCITimeout =	9,
	GCIAbort =	10,
	StopIDMA =	11,
	StartDSP = 	12,
	ArmIDMA =	13,
	InitDSP =		13,
	USBCmd =	15,

	/* channel IDs */
	SCC1ID=	0,
	USBID=	0,
	I2CID=	1,
	IDMA1ID= 1,
	SCC2ID=	4,
	SPIID=	5,
	IDMA2ID= 5,
	TIMERID=	5,
	SCC3ID=	8,
	SMC1ID=	9,
	DSP1ID=9,
	SCC4ID=	12,
	SMC2ID=	13,
	DSP2ID=	13,

	/* bgcr */
	BaudEnable = 1<<16,

	/* sicr */
	CLK1 = 4,		/* SCC1,2 */
	CLK2 = 5,
	CLK3 = 6,
	CLK4 = 7,
	CLK5 = CLK1,	/* SCC3,4 */
	CLK6 = CLK2,
	CLK7 = CLK3,
	CLK8 = CLK4,
};

void	cpmop(int, int, int);
void*	cpmalloc(int, int);
void	cpmfree(void*, int);
void*	cpmparam(ulong, int);
IMM*	ioplock(void);
void	iopunlock(void);
void	sccnmsi(int, int, int);
int	scc2claim(int, ulong, void(*)(void*), void*);
void	scc2stop(void*);

/*
 * CPM timers
 */
enum {
	/* timer modes */
	CaptureRise=	1<<6,
	CaptureFall=	2<<6,
	CaptureEdge=	3<<6,
	TimerToggle=	1<<5,	/* toggle TOUTx* pin */
	TimerORI=	1<<4,	/* Output Reference Interrupt */
	TimerRestart=	1<<3,
	TimerSclk=	1<<1,
	TimerSclk16=	2<<1,
	TimerTIN=	3<<1,	/* clock by falling edge of TINx */
	TimerGate=	1<<0,	/* TGATE1* controls timer */

	/* timer events */
	TimerREF=	1<<1,
	TimerCAP=	1<<0
};

struct GTimer{
	int	x;
	int	inuse;
	int	event;
	ushort*	tmr;
	ushort*	trr;
	ushort*	tcr;
	ushort*	tcn;
	ushort*	ter;
	void*	arg;
	void	(*interrupt)(Ureg*, void*, GTimer*);
};
GTimer*	gtimer(ushort, ushort, void (*)(Ureg*,void*,GTimer*), void*);
void	gtimerset(GTimer*, ushort, int);
void	gtimerstart(GTimer*);
void	gtimerstop(GTimer*);
void	gtimerfree(GTimer*);

enum {
	/* BCSR1 bits */
	DisableFlash=	IBIT(0),
	DisableDRAM=	IBIT(1),
	DisableEther=	IBIT(2),
	DisableIR=	IBIT(3),
	DisableRS232a=	IBIT(7),
	DisablePCMCIA=	IBIT(8),
	PCCVCCMask=	IBIT(9)|IBIT(15),
	PCCVPPMask=	IBIT(10)|IBIT(11),
	DisableRS232b=	IBIT(13),
	EnableSDRAM=	IBIT(14),

	PCCVCC0V=	IBIT(15)|IBIT(9),
	PCCVCC5V=	IBIT(9),	/* active low */
	PCCVCC3V=	IBIT(15),	/* active low */
	PCCVPP0V=	IBIT(10)|IBIT(11),	/* active low */
	PCCVPP5V=	IBIT(10),	/* active low */
	PCCVPP12V=	IBIT(11),	/* active low */
	PCCVPPHiZ=	IBIT(10)|IBIT(11),

	/* BCSR4 bits */
	DisableTPDuplex=	IBIT(1),
	DisableLamp=	IBIT(3),
	DisableUSB=	IBIT(4),
	USBFullSpeed=	IBIT(5),
	DisableUSBVcc=	IBIT(6),
	DisableVideoLamp=	IBIT(8),
	EnableVideoClock=	IBIT(9),
	EnableVideoPort=	IBIT(10),
	DisableModem=	IBIT(11),
};

/*
 * everything in this file follows a hardware/firmware layout in the 8xx manuals:
 * mind the data types, offsets and alignment
 */

/*
 * basic IO controller parameters (SMC and SCC)
 */
typedef struct IOCparam IOCparam;
struct IOCparam {
	ushort	rbase;
	ushort	tbase;
	uchar	rfcr;
	uchar	tfcr;
	ushort	mrblr;
	ulong	rstate;
	ulong	rxidp;
	ushort	rbptr;
	ushort	rxibc;
	ulong	rxtemp;
	ulong	tstate;
	ulong	txidp;
	ushort	tbptr;
	ushort	txibc;
	ulong	txtemp;
};

typedef struct SCCparam SCCparam;
struct SCCparam {
	IOCparam;
	ulong	rcrc;
	ulong	tcrc;
};

typedef struct SCC SCC;
struct SCC {
	ulong	gsmrl;
	ulong	gsmrh;
	ushort	psmr;
	uchar	rsvscc0[2];
	ushort	todr;
	ushort	dsr;
	ushort	scce;
	uchar	rsvscc1[2];
	ushort	sccm;
	uchar	rsvscc3;
	uchar	sccs;
	ushort	irmode;
	ushort	irsip;
};

typedef struct SMC SMC;
struct SMC {
	uchar	pad1[2];
	ushort	smcmr;
	uchar	pad2[2];
	uchar	smce;
	uchar	pad3[3];
	uchar	smcm;
	uchar	pad4[5];
};

typedef struct SPI SPI;
struct SPI {
	ushort	spmode;
	uchar	res1[4];
	uchar	spie;
	uchar	res2[3];
	uchar	spim;
	uchar	res3[2];
	uchar	spcom;
	uchar	res4[10];
};

typedef struct USB USB;
struct USB {
	uchar	usmod;
	uchar	usadr;
	uchar	uscom;
	uchar	rsvu1;
	ushort	usep[4];
	uchar	rsvu2[4];
	ushort	usber;
	uchar	rsvu3[2];
	ushort	usbmr;
	uchar	rsvu4;
	uchar	usbs;
	uchar	rsvu5[8];
};

typedef struct IMM IMM;
struct IMM {
	struct {	/* general SIU */
		ulong	siumcr;
		ulong	sypcr;
		uchar	rsv0[0xE-0x8];
		ushort	swsr;
		ulong	sipend;
		ulong	simask;
		ulong	siel;
		uchar	sivec;
		uchar	padv[3];
		ulong	tesr;
		uchar	rsv1[0x30-0x24];
		ulong	sdcr;
		uchar	rsv2[0x80-0x34];
	};
	struct {	/* PCMCIA */
		struct {
			ulong	base;
			ulong	option;
		} pcmr[8];
		uchar	rsv3[0xe0-0xc0];
		ulong	pgcra;
		ulong	pgcrb;
		ulong	pscr;
		uchar	rsv4[0xf0-0xec];
		ulong	pipr;
		uchar	rsv5[4];
		ulong	per;
		uchar	rsv6[4];
	};
	struct {	/* MEMC */
		struct {
			ulong	base;
			ulong	option;
		} memc[8];
		uchar	rsv7a[0x24];
		ulong	mar;
		ulong	mcr;
		uchar	rsv7b[4];
		ulong	mamr;
		ulong	mbmr;
		ushort	mstat;
		ushort	mptpr;
		ulong	mdr;
		uchar	rsv7c[0x80];
	};
	struct {	/* system integration timers */
		ushort	tbscr;
		uchar	rsv8a[2];
		ulong	tbrefu;
		ulong	tbrefl;
		uchar	rsv8b[0x14];
		ushort	rtcsc;
		uchar	rsv8c[2];
		ulong	rtc;
		ulong	rtsec;
		ulong	rtcal;
		uchar	rsv8d[0x10];
		ushort	piscr;
		ushort	rsv8e;
		ulong	pitc;
		ulong	pitr;
		uchar	rsv8f[0x34];
	};
	struct {	/* 280: clocks and resets */
		ulong	sccr;
		ulong	plprcr;
		ulong	rsr;
		uchar	rsv9[0x300-0x28c];
	};
	struct {	/* 300: system integration timers keys */
		ulong	tbscrk;
		ulong	tbrefuk;
		ulong	tbreflk;
		ulong	tbk;
		uchar	rsv10a[0x10];
		ulong	rtcsck;
		ulong	rtck;
		ulong	rtseck;
		ulong	rtcalk;
		uchar	rsv10b[0x10];
		ulong	piscrk;
		ulong	pitck;
		uchar	rsv10c[0x38];
	};
	struct {	/* 380: clocks and resets keys */
		ulong	sccrk;
		ulong	plprcrk;
		ulong	rsrk;
		uchar	rsv11[0x800-0x38C];
	};
	struct {	/* 800: video controller */
		ushort	vccr;
		ushort	pad11a;
		uchar	vsr;
		uchar	pad11b;
		uchar	vcmr;
		uchar	pad11c;
		ulong	vbcb;
		ulong	pad11d;
		ulong	vfcr0;
		ulong	vfaa0;
		ulong	vfba0;
		ulong	vfcr1;
		ulong	vfaa1;
		ulong	vfba1;
		uchar	rsv11a[0x840-0x828];
	};
	struct {	/* 840: LCD */
		ulong	lccr;
		ulong	lchcr;
		ulong	lcvcr;
		ulong	rsv11b;
		ulong	lcfaa;
		ulong	lcfba;
		uchar	lcsr;
		uchar	rsv11c[0x860-0x859];
	};
	struct {	/* 860: I2C */
		uchar	i2mod;
		uchar	rsv12a[3];
		uchar	i2add;
		uchar	rsv12b[3];
		uchar	i2brg;
		uchar	rsv12c[3];
		uchar	i2com;
		uchar	rsv12d[3];
		uchar	i2cer;
		uchar	rsv12e[3];
		uchar	i2cmr;
		uchar	rsv12[0x900-0x875];
	};
	struct {	/* 900: DMA */
		uchar	rsv13[4];
		ulong	sdar;
		uchar	sdsr;
		uchar	pad1[3];
		uchar	sdmr;
		uchar	pad2[3];
		uchar	idsr1;
		uchar	pad3[3];
		uchar	idmr1;
		uchar	pad4[3];
		uchar	idsr2;
		uchar	pad5[3];
		uchar	idmr2;
		uchar	pad6[0x930-0x91D];
	};
	struct {	/* CPM interrupt control */
		ushort	civr;
		uchar	pad7[0x940-0x932];
		ulong	cicr;
		ulong	cipr;
		ulong	cimr;
		ulong	cisr;
	};
	struct {	/* input/output port */
		ushort	padir;
		ushort	papar;
		ushort	paodr;
		ushort	padat;
		uchar	pad8[8];
		ushort	pcdir;
		ushort	pcpar;
		ushort	pcso;
		ushort	pcdat;
		ushort	pcint;
		uchar	pad9[6];
		ushort	pddir;
		ushort	pdpar;
		ushort	rsv14a;
		ushort	pddat;
		uchar	rsv14[0x980-0x978];
	};
	struct {	/* CPM timers */
		ushort	tgcr;
		uchar	rsv15a[0x990-0x982];
		ushort	tmr1;
		ushort	tmr2;
		ushort	trr1;
		ushort	trr2;
		ushort	tcr1;
		ushort	tcr2;
		ushort	tcn1;
		ushort	tcn2;
		ushort	tmr3;
		ushort	tmr4;
		ushort	trr3;
		ushort	trr4;
		ushort	tcr3;
		ushort	tcr4;
		ushort	tcn3;
		ushort	tcn4;
		ushort	ter1;
		ushort	ter2;
		ushort	ter3;
		ushort	ter4;
		uchar	rsv15[0x9C0-0x9B8];
	};
	struct {	/* CPM */
		ushort	cpcr;
		uchar	res0[2];
		ushort	rccr;
		uchar	res1;
		uchar	rmds;
		uchar	res2a[4];
		ushort	rctr1;
		ushort	rctr2;
		ushort	rctr3;
		ushort	rctr4;
		uchar	res2[2];
		ushort	rter;
		uchar	res3[2];
		ushort	rtmr;
		uchar	rsv16[0x9F0-0x9DC];
	};
	union {	/* BRG */
		struct {
			ulong	brgc1;
			ulong	brgc2;
			ulong	brgc3;
			ulong	brgc4;
		};
		ulong	brgc[4];
	};
	uchar	skip0[0xAB2-0xA00];	/* USB, SCC, SMC, SPI: address using IOREGS in fns.h */
	struct {	/* PIP */
		ushort	pipc;		/* not 823 */
		ushort	ptpr;		/* not 823 */
		ulong	pbdir;
		ulong	pbpar;
		uchar	pad10[2];
		ushort	pbodr;
		ulong	pbdat;
		uchar	pad11[0xAE0-0xAC8];
	};
	struct {	/* SI */
		ulong	simode;
		uchar	sigmr;
		uchar	pad12;
		uchar	sistr;
		uchar	sicmr;
		uchar	pad13[4];
		ulong	sicr;
		ulong	sirp;
		uchar	pad14[0xB00-0xAF4];
	};
	uchar	vcram[256];
	uchar	siram[512];
	ushort	lcdmap[256];
};

A mpc/l.s => mpc/l.s +663 -0
@@ 0,0 1,663 @@
#include	"mem.h"

/*
 * common ppc special purpose registers
 */
#define DSISR	18
#define DAR	19	/* Data Address Register */
#define DEC	22	/* Decrementer */
#define SRR0	26	/* Saved Registers (exception) */
#define SRR1	27
#define SPRG0	272	/* Supervisor Private Registers */
#define SPRG1	273
#define SPRG2	274
#define SPRG3	275
#define TBRU	269	/* Time base Upper/Lower (Reading) */
#define TBRL	268
#define TBWU	285	/* Time base Upper/Lower (Writing) */
#define TBWL	284
#define PVR	287	/* Processor Version */

/*
 * mpc8xx-specific special purpose registers of interest here
 */
#define EIE		80
#define EID		81
#define NRI		82
#define IMMR		638
#define IC_CST		560
#define IC_ADR		561
#define IC_DAT		562
#define DC_CST		568
#define DC_ADR		569
#define DC_DAT		570
#define MI_CTR		784
#define MI_AP		786
#define MI_EPN		787
#define MI_TWC		789
#define MI_RPN		790
#define MI_DBCAM	816
#define MI_DBRAM0	817
#define MI_DBRAM1	818
#define MD_CTR		792
#define M_CASID		793
#define MD_AP		794
#define MD_EPN		795
#define M_TWB		796
#define MD_TWC		797
#define MD_RPN		798
#define	M_TW		799
#define	MD_DBCAM	824
#define	MD_DBRAM0	825
#define	MD_DBRAM1	826

/* use of SPRG registers in save/restore */
#define	SAVER0	SPRG0
#define	SAVER1	SPRG1
#define	SAVELR	SPRG2
#define	SAVEXX	SPRG3

/* special instruction definitions */
#define	BDNZ	BC	16,0,
#define	BDNE	BC	0,2,
#define	TLBIA	WORD	$(31<<26)
#define	MFTB(tbr,d)	WORD	$((31<<26)|((d)<<21)|((tbr&0x1f)<<16)|(((tbr>>5)&0x1f)<<11)|(371<<1))

/* on some models mtmsr doesn't synchronise enough (eg, 603e) */
#define	MSRSYNC	SYNC; ISYNC

#define	UREGSPACE	(UREGSIZE+8)

	TEXT start(SB), $-4

	/* turn off interrupts but enable traps */
	MOVW	MSR, R3
	MOVW	$~(MSR_EE|MSR_FP), R4
	AND	R4, R3
	OR	$(MSR_IP|MSR_ME), R3
	ISYNC
	MOVW	R3, MSR
	MSRSYNC

	MOVW	$0, R0	/* except during trap handling, R0 is zero from now on */
	MOVW	$setSB(SB), R2

/*
 * reset the caches and disable them for now
 */
	MOVW	SPR(IC_CST), R4	/* read and clear */
	MOVW	$(5<<25), R4
	MOVW	R4, SPR(IC_CST)	/* unlock all */
	ISYNC
	MOVW	$(6<<25), R4
	MOVW	R4, SPR(IC_CST)	/* invalidate all */
	ISYNC
	MOVW	$(2<<25), R4
	MOVW	R4, SPR(IC_CST)	/* disable i-cache */
	ISYNC

	SYNC
	MOVW	SPR(DC_CST), R4	/* read and clear */
	MOVW	$(10<<24), R4
	SYNC
	MOVW	R4, SPR(DC_CST)	/* unlock all */
	ISYNC
	MOVW	$(12<<24), R4
	SYNC
	MOVW	R4, SPR(DC_CST)	/* invalidate all */
	ISYNC
	MOVW	$(4<<24), R4
	SYNC
	MOVW	R4, SPR(DC_CST)	/* disable d-cache */
	ISYNC

	MOVW	$7, R4
	MOVW	R4, SPR(158)		/* cancel `show cycle' for normal instruction execution */
	ISYNC

/*
 * set other system configuration values
 */
	MOVW	$INTMEM, R4
	MOVW	R4, SPR(IMMR)		/* set internal memory base */

	MOVW	$mach0(SB), R(MACH)
	ADD	$(MACHSIZE-8), R(MACH), R1
	SUB	$4, R(MACH), R3
	ADD	$4, R1, R4
clrmach:
	MOVWU	R0, 4(R3)
	CMP	R3, R4
	BNE	clrmach

	MOVW	R0, R(USER)
	MOVW	R0, 0(R(MACH))

	MOVW	$edata(SB), R3
	MOVW	$end(SB), R4
	ADD	$4, R4
	SUB	$4, R3
clrbss:
	MOVWU	R0, 4(R3)
	CMP	R3, R4
	BNE	clrbss

	BL	main(SB)
	BR	0(PC)

TEXT	kernelmmu(SB), $0
	TLBIA
	ISYNC

	MOVW	$0, R4
	MOVW	R4, SPR(M_CASID)	/* set supervisor space */
	MOVW	$(0<<29), R4		/* allow i-cache when IR=0 */
	MOVW	R4, SPR(MI_CTR)	/* i-mmu control */
	ISYNC
	MOVW	$((1<<29)|(1<<28)), R4	/* cache inhibit when DR=0, write-through */
	SYNC
	MOVW	R4, SPR(MD_CTR)	/* d-mmu control */
	ISYNC
	TLBIA

	/* map various things 1:1 */
	MOVW	$tlbtab-KZERO(SB), R4
	MOVW	$tlbtabe-KZERO(SB), R5
	SUB	R4, R5
	MOVW	$(3*4), R6
	DIVW	R6, R5
	SUB	$4, R4
	MOVW	R5, CTR
ltlb:
	MOVWU	4(R4), R5
	MOVW	R5, SPR(MD_EPN)
	MOVW	R5, SPR(MI_EPN)
	MOVWU	4(R4), R5
	MOVW	R5, SPR(MI_TWC)
	MOVW	R5, SPR(MD_TWC)
	MOVWU	4(R4), R5
	MOVW	R5, SPR(MD_RPN)
	MOVW	R5, SPR(MI_RPN)
	BDNZ	ltlb

	MOVW	$(1<<25), R4
	MOVW	R4, SPR(IC_CST)	/* enable i-cache */
	ISYNC

	MOVW	$(1<<24), R4
	SYNC
	MOVW	R4, SPR(DC_CST)	/* force write through mode */
	MOVW	$(1<<25), R4
	SYNC
	MOVW	R4, SPR(DC_CST)	/* enable d-cache */
	ISYNC

	/* enable MMU and set kernel PC to virtual space */
	MOVW	$((0<<29)|(1<<28)), R4	/* cache when DR=0, write-through */
	SYNC
	MOVW	R4, SPR(MD_CTR)	/* d-mmu control */
	MOVW	LR, R3
	OR	$KZERO, R3
	MOVW	R3, SPR(SRR0)
	MOVW	MSR, R4
	OR	$(MSR_ME|MSR_IR|MSR_DR), R4	/* had ME|FPE|FE0|FE1 */
	MOVW	R4, SPR(SRR1)
	RFI	/* resume in kernel mode in caller */

TEXT	splhi(SB), $0
	MOVW	MSR, R3
	RLWNM	$0, R3, $~MSR_EE, R4
	SYNC
	MOVW	R4, MSR
	MSRSYNC
	MOVW	LR, R31
	MOVW	R31, 4(R(MACH))	/* save PC in m->splpc */
	RETURN

TEXT	splx(SB), $0
	/* fall though */

TEXT	splxpc(SB), $0
	MOVW	MSR, R4
	RLWMI	$0, R3, $MSR_EE, R4
	RLWNMCC	$0, R3, $MSR_EE, R5
	BNE	splx0
	MOVW	LR, R31
	MOVW	R31, 4(R(MACH))	/* save PC in m->splpc */
splx0:
	SYNC
	MOVW	R4, MSR
	MSRSYNC
	RETURN

TEXT	spllo(SB), $0
	MFTB(TBRL, 3)
	MOVW	R3, spltbl(SB)
	MOVW	MSR, R3
	OR	$MSR_EE, R3, R4
	SYNC
	MOVW	R4, MSR
	MSRSYNC
	RETURN

TEXT	spldone(SB), $0
	RETURN

TEXT	islo(SB), $0
	MOVW	MSR, R3
	RLWNM	$0, R3, $MSR_EE, R3
	RETURN

TEXT	setlabel(SB), $-4
	MOVW	LR, R31
	MOVW	R1, 0(R3)
	MOVW	R31, 4(R3)
	MOVW	$0, R3
	RETURN

TEXT	gotolabel(SB), $-4
	MOVW	4(R3), R31
	MOVW	R31, LR
	MOVW	0(R3), R1
	MOVW	$1, R3
	RETURN

/*
 * enter with stack set and mapped.
 * on return, SB (R2) has been set, and R3 has the Ureg*,
 * the MMU has been re-enabled, kernel text and PC are in KSEG,
 * R(MACH) has been set, and R0 contains 0.
 *
 * this can be simplified in the Inferno regime
 */
TEXT	saveureg(SB), $-4
/*
 * save state
 */
	MOVMW	R2, 48(R1)	/* r2:r31 */
	MOVW	$setSB(SB), R2
	MOVW	SPR(SAVER1), R4
	MOVW	R4, 44(R1)
	MOVW	SPR(SAVER0), R5
	MOVW	R5, 40(R1)
	MOVW	CTR, R6
	MOVW	R6, 36(R1)
	MOVW	XER, R4
	MOVW	R4, 32(R1)
	MOVW	CR, R5
	MOVW	R5, 28(R1)
	MOVW	SPR(SAVELR), R6	/* LR */
	MOVW	R6, 24(R1)
	/* pad at 20(R1) */
	/* old PC(16) and status(12) saved earlier */
	MOVW	SPR(SAVEXX), R0
	MOVW	R0, 8(R1)	/* cause/vector */
	ADD	$8, R1, R3	/* Ureg* */
	STWCCC	R3, (R1)	/* break any pending reservations */
	MOVW	$0, R0	/* compiler/linker expect R0 to be zero */

	MOVW	MSR, R5
	OR	$(MSR_IR|MSR_DR), R5	/* enable MMU */
	MOVW	R5, SPR(SRR1)
	MOVW	LR, R31
	OR	$KZERO, R31	/* return PC in KSEG0 */
	MOVW	R31, SPR(SRR0)
	SYNC
	ISYNC
	RFI	/* returns to trap handler */

TEXT	icflush(SB), $-4	/* icflush(virtaddr, count) */
	MOVW	n+4(FP), R4
	RLWNM	$0, R3, $~(CACHELINESZ-1), R5
	SUB	R5, R3
	ADD	R3, R4
	ADD		$(CACHELINESZ-1), R4
	SRAW	$CACHELINELOG, R4
	MOVW	R4, CTR
icf0:	ICBI	(R5)
	ADD	$CACHELINESZ, R5
	BDNZ	icf0
	ISYNC
	RETURN

TEXT	dcflush(SB), $-4	/* dcflush(virtaddr, count) */
	SYNC
	MOVW	n+4(FP), R4
	RLWNM	$0, R3, $~(CACHELINESZ-1), R5
	CMP	R4, $0
	BLE	dcf1
	SUB	R5, R3
	ADD	R3, R4
	ADD		$(CACHELINESZ-1), R4
	SRAW	$CACHELINELOG, R4
	MOVW	R4, CTR
dcf0:	DCBF	(R5)
	ADD	$CACHELINESZ, R5
	BDNZ	dcf0
	SYNC
	ISYNC
dcf1:
	RETURN

TEXT	tas(SB), $0
	SYNC
	MOVW	R3, R4
	MOVW	$0xdeaddead,R5
tas1:
	DCBF	(R4)	/* fix for 603x bug */
	LWAR	(R4), R3
	CMP	R3, $0
	BNE	tas0
	STWCCC	R5, (R4)
	BNE	tas1
tas0:
	SYNC
	ISYNC
	RETURN

TEXT	gettbl(SB), $0
	MFTB(TBRL, 3)
	RETURN

TEXT	gettbu(SB), $0
	MOVW	SPR(TBRU), R3
	RETURN

TEXT	getpvr(SB), $0
	MOVW	SPR(PVR), R3
	RETURN

TEXT	getimmr(SB), $0
	MOVW	SPR(IMMR), R3
	RETURN

TEXT	getdec(SB), $0
	MOVW	SPR(DEC), R3
	RETURN

TEXT	putdec(SB), $0
	MOVW	R3, SPR(DEC)
	RETURN

TEXT	getcallerpc(SB), $-4
	MOVW	0(R1), R3
	RETURN

TEXT getdar(SB), $0
	MOVW	SPR(DAR), R3
	RETURN

TEXT getdsisr(SB), $0
	MOVW	SPR(DSISR), R3
	RETURN

TEXT	getdepn(SB), $0
	MOVW	SPR(MD_EPN), R3
	RETURN

TEXT	getmsr(SB), $0
	MOVW	MSR, R3
	RETURN

TEXT	putmsr(SB), $0
	SYNC
	MOVW	R3, MSR
	MSRSYNC
	RETURN

TEXT	eieio(SB), $0
	EIEIO
	RETURN

TEXT	gotopc(SB), $0
	MOVW	R3, CTR
	MOVW	LR, R31	/* for trace back */
	BR	(CTR)

TEXT	firmware(SB), $0
	MOVW	MSR, R3
	MOVW	$(MSR_EE|MSR_ME), R4
	ANDN	R4, R3
	OR	$(MSR_IP), R3
	ISYNC
	MOVW	R3, MSR	/* turn off interrupts and machine checks */
	MSRSYNC
	MOVW	$(MSR_RI|MSR_IR|MSR_DR|MSR_ME), R4
	ANDN	R4, R3
	MOVW	R3, SPR(SRR1)
	MOVW	$(0xFF00<<16), R4
	MOVW	R4, SPR(IMMR)
	MOVW	$(0x0800<<16), R4
	MOVW	R4, SPR(SRR0)	/* force bad address */
	MOVW	R0, SPR(149)	/* ensure checkstop on machine check */
	MOVW	R0, R1
	MOVW	R0, R2
	EIEIO
	ISYNC
	RFI

/*
 * byte swapping of arrays of long and short;
 * could possibly be avoided with more changes to drivers
 */
TEXT	swabl(SB), $0
	MOVW	v+4(FP), R4
	MOVW	n+8(FP), R5
	SRAW	$2, R5, R5
	MOVW	R5, CTR
	SUB	$4, R4
	SUB	$4, R3
swabl1:
	ADD	$4, R3
	MOVWU	4(R4), R7
	MOVWBR	R7, (R3)
	BDNZ	swabl1
	RETURN

TEXT	swabs(SB), $0
	MOVW	v+4(FP), R4
	MOVW	n+8(FP), R5
	SRAW	$1, R5, R5
	MOVW	R5, CTR
	SUB	$2, R4
	SUB	$2, R3
swabs1:
	ADD	$2, R3
	MOVHZU	2(R4), R7
	MOVHBR	R7, (R3)
	BDNZ	swabs1
	RETURN

TEXT	legetl(SB), $0
	MOVWBR	(R3), R3
	RETURN

TEXT	lesetl(SB), $0
	MOVW	v+4(FP), R4
	MOVWBR	R4, (R3)
	RETURN

TEXT	legets(SB), $0
	MOVHBR	(R3), R3
	RETURN

TEXT	lesets(SB), $0
	MOVW	v+4(FP), R4
	MOVHBR	R4, (R3)
	RETURN

/*
 * ITLB miss
 *	avoid references that might need the right SB value;
 *	IR and DR are off.
 */
TEXT	itlbmiss(SB), $-4
	MOVW	R1, SPR(M_TW)
	MOVW	SPR(SRR0), R1	/* instruction miss address */
	MOVW	R1, SPR(MD_EPN)
	MOVW	SPR(M_TWB), R1	/* level one pointer */
	MOVW	(R1), R1
	MOVW	R1, SPR(MI_TWC)	/* save level one attributes */
	MOVW	R1, SPR(MD_TWC)	/* save base and attributes */
	MOVW	SPR(MD_TWC), R1	/* level two pointer */
	MOVW	(R1), R1	/* level two entry */
	MOVW	R1, SPR(MI_RPN)	/* write TLB */
	MOVW	SPR(M_TW), R1
	RFI

/*
 * DTLB miss
 *	avoid references that might need the right SB value;
 *	IR and DR are off.
 */
TEXT	dtlbmiss(SB), $-4
	MOVW	R1, SPR(M_TW)
	MOVW	SPR(M_TWB), R1	/* level one pointer */
	MOVW	(R1), R1	/* level one entry */
	MOVW	R1, SPR(MD_TWC)	/* save base and attributes */
	MOVW	SPR(MD_TWC), R1	/* level two pointer */
	MOVW	(R1), R1	/* level two entry */
	MOVW	R1, SPR(MD_RPN)	/* write TLB */
	MOVW	SPR(M_TW), R1
	RFI

/*
 * traps force memory mapping off.
 * this code goes to too much effort (for the Inferno environment) to restore it.
 */
TEXT	trapvec(SB), $-4
traps:
	MOVW	LR, R0

pagefault:

/*
 * map data virtually and make space to save
 */
	MOVW	R0, SPR(SAVEXX)	/* vector */
	MOVW	R1, SPR(SAVER1)
	SYNC
	ISYNC
	MOVW	MSR, R0
	OR	$(MSR_DR|MSR_ME), R0		/* make data space usable */
	SYNC
	MOVW	R0, MSR
	MSRSYNC
	SUB	$UREGSPACE, R1

	MOVW	SPR(SRR0), R0	/* save SRR0/SRR1 now, since DLTB might be missing stack page */
	MOVW	R0, LR
	MOVW	SPR(SRR1), R0
	MOVW	R0, 12(R1)	/* save status: could take DLTB miss here */
	MOVW	LR, R0
	MOVW	R0, 16(R1)	/* old PC */
	BL	saveureg(SB)
	BL	trap(SB)
	BR	restoreureg

TEXT	intrvec(SB), $-4
	MOVW	LR, R0

/*
 * map data virtually and make space to save
 */
	MOVW	R0, SPR(SAVEXX)	/* vector */
	MOVW	R1, SPR(SAVER1)
	SYNC
	ISYNC
	MOVW	MSR, R0
	OR	$MSR_DR, R0		/* make data space usable */
	SYNC
	MOVW	R0, MSR
	MSRSYNC
	SUB	$UREGSPACE, R1

	MFTB(TBRL, 0)
	MOVW	R0, intrtbl(SB)

	MOVW	SPR(SRR0), R0
	MOVW	R0, LR
	MOVW	SPR(SRR1), R0
	MOVW	R0, 12(R1)
	MOVW	LR, R0
	MOVW	R0, 16(R1)
	BL	saveureg(SB)

	MFTB(TBRL, 5)
	MOVW	R5, isavetbl(SB)

	BL	intr(SB)

/*
 * restore state from Ureg and return from trap/interrupt
 */
restoreureg:
	MOVMW	48(R1), R2	/* r2:r31 */
	/* defer R1 */
	MOVW	40(R1), R0
	MOVW	R0, SPR(SAVER0)
	MOVW	36(R1), R0
	MOVW	R0, CTR
	MOVW	32(R1), R0
	MOVW	R0, XER
	MOVW	28(R1), R0
	MOVW	R0, CR	/* CR */
	MOVW	24(R1), R0
	MOVW	R0, SPR(SAVELR)	/* LR */
	/* pad, skip */
	MOVW	16(R1), R0
	MOVW	R0, SPR(SRR0)	/* old PC */
	MOVW	12(R1), R0
	MOVW	R0, SPR(SRR1)	/* old MSR */
	/* cause, skip */
	MOVW	44(R1), R1	/* old SP */
	MOVW	SPR(SAVELR), R0
	MOVW	R0, LR
	MOVW	SPR(SAVER0), R0
	RFI

TEXT	powerdownled(SB), $0

	MOVW	$0x10002200,R11
	MOVW	$0,R7
	MOVW	R7,0(R11)
	RETURN

TEXT	powerupled(SB), $0

	MOVW	$0x10002200,R11
	MOVW	$2,R7
	MOVW	R7,0(R11)
	RETURN

TEXT	reset(SB), $-4
	MOVW	$0,R4
	MOVW	0(R4), R5
loop:
	BR	loop


GLOBL	mach0+0(SB), $MACHSIZE
GLOBL	spltbl+0(SB), $4
GLOBL	intrtbl+0(SB), $4
GLOBL	isavetbl+0(SB), $4

/*
 * TLB prototype entries, loaded once-for-all at startup,
 * remaining unchanged thereafter.
 * Limit the table to at most 8 entries to ensure
 * it works on the 823 (other 8xx processors allow up to 32 TLB entries).
 */
#define	TLBE(epn,rpn,twc)	WORD	$(epn);  WORD	$(twc); WORD	$(rpn)

TEXT	tlbtab(SB), $-4

	/* epn, rpn, twc */
/*	TLBE(KZERO|DRAMMEM|TLBVALID, DRAMMEM|PTEWRITE|PTELPS|PTESH|PTEVALID, PTE8MB|PTEWT|PTEVALID)	/* DRAM, 8M */
/*	TLBE(KZERO|BCSRMEM|TLBVALID, BCSRMEM|PTEWRITE|PTESH|PTECI|PTEVALID, PTE4K|PTEWT|PTEVALID)	/* Board CSR, 4K */
/*	TLBE(KZERO|INTMEM|TLBVALID, INTMEM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE4K|PTEWT|PTEVALID)	/* IMMR, 16K */
/*	TLBE(KZERO|FLASHMEM|TLBVALID, FLASHMEM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE8MB|PTEWT|PTEVALID)	/* Flash, 8M */
/*	TLBE(KZERO|SDRAMMEM|TLBVALID, SDRAMMEM|PTEWRITE|PTELPS|PTESH|PTEVALID, PTE8MB|PTEWT|PTEVALID)	/* SDRAM, 8M */
/*	TLBE(KZERO|PCMCIAMEM|TLBVALID, PCMCIAMEM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE8MB|PTEWT|PTEVALID)	/* PCMCIA, 8M */
TEXT	tlbtabe(SB), $-4
	RETURN

A mpc/main.c => mpc/main.c +190 -0
@@ 0,0 1,190 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"init.h"
#include	"pool.h"

#define MAXCONF 1000

char *confname[MAXCONF];
char *confval[MAXCONF];
int nconf;

Conf	conf;

void
main(void)
{
	machinit();
}

void
machinit(void)
{
	IMM *io;
	int mf, osc;

	memset(m, 0, sizeof(*m));
	m->delayloop = 20000;
	m->cputype = getpvr()>>16;
	m->iomem = KADDR(INTMEM);

	io = m->iomem;
	osc = 5;
	mf = io->plprcr >> 20;
	m->oscclk = osc;
	m->speed = osc*(mf+1);
}

void
exit(int ispanic)
{
	int ms, once;

	lock(&active);
	if(ispanic)
		active.ispanic = ispanic;
	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
		active.ispanic = 0;
	once = active.machs & (1<<m->machno);
	active.machs &= ~(1<<m->machno);
	active.exiting = 1;
	unlock(&active);

	if(once)
		print("cpu%d: exiting\n", m->machno);
	spllo();
	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
		delay(TK2MS(2));
		if(active.machs == 0 && consactive() == 0)
			break;
	}

	if(active.ispanic && m->machno == 0){
		if(cpuserver)
			delay(10000);
		else
			for(;;);
	}
	else
		delay(1000);

//	arch->reset();
}

/*
 *  set up floating point for a new process
 */
void
procsetup(Proc *p)
{
	USED(p);
}

/*
 *  Save the mach dependent part of the process state.
 */
void
procsave(Proc *p)
{
	USED(p);
}

// print without using interrupts
int
iprint(char *fmt, ...)
{
	char buf[PRINTSIZE];
	int n;
	va_list arg;

	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

	print("%s", buf);

	return n;
}


int
isaconfig(char *class, int ctlrno, ISAConf *isa)
{
	char cc[NAMELEN], *p, *q, *r;
	int n;

	sprint(cc, "%s%d", class, ctlrno);
	for(n = 0; n < nconf; n++){
		if(strncmp(confname[n], cc, NAMELEN))
			continue;
		isa->nopt = 0;
		p = confval[n];
		while(*p){
			while(*p == ' ' || *p == '\t')
				p++;
			if(*p == '\0')
				break;
			if(strncmp(p, "type=", 5) == 0){
				p += 5;
				for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
					if(*p == '\0' || *p == ' ' || *p == '\t')
						break;
					*q = *p++;
				}
				*q = '\0';
			}
			else if(strncmp(p, "port=", 5) == 0)
				isa->port = strtoul(p+5, &p, 0);
			else if(strncmp(p, "irq=", 4) == 0)
				isa->irq = strtoul(p+4, &p, 0);
			else if(strncmp(p, "mem=", 4) == 0)
				isa->mem = strtoul(p+4, &p, 0);
			else if(strncmp(p, "size=", 5) == 0)
				isa->size = strtoul(p+5, &p, 0);
			else if(strncmp(p, "freq=", 5) == 0)
				isa->freq = strtoul(p+5, &p, 0);
			else if(strncmp(p, "dma=", 4) == 0)
				isa->dma = strtoul(p+4, &p, 0);
			else if(isa->nopt < NISAOPT){
				r = isa->opt[isa->nopt];
				while(*p && *p != ' ' && *p != '\t'){
					*r++ = *p++;
					if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
						break;
				}
				*r = '\0';
				isa->nopt++;
			}
			while(*p && *p != ' ' && *p != '\t')
				p++;
		}
		return 1;
	}
	return 0;
}

int
cistrcmp(char *a, char *b)
{
	int ac, bc;

	for(;;){
		ac = *a++;
		bc = *b++;
	
		if(ac >= 'A' && ac <= 'Z')
			ac = 'a' + (ac - 'A');
		if(bc >= 'A' && bc <= 'Z')
			bc = 'a' + (bc - 'A');
		ac -= bc;
		if(ac)
			return ac;
		if(bc == 0)
			break;
	}
	return 0;
}

A mpc/mem.h => mpc/mem.h +156 -0
@@ 0,0 1,156 @@
/*
 * Memory and machine-specific definitions.  Used in C and assembler.
 */

/*
 * Sizes
 */

#define	BI2BY		8			/* bits per byte */
#define BI2WD		32			/* bits per word */
#define	BY2WD		4			/* bytes per word */
#define	BY2V		8			/* bytes per double word */
#define	BY2PG		4096			/* bytes per page */
#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
#define	PGSHIFT		12			/* log(BY2PG) */
#define ROUND(s, sz)	(((s)+((sz)-1))&~((sz)-1))
#define PGROUND(s)	ROUND(s, BY2PG)
#define	CACHELINELOG	4
#define CACHELINESZ	(1<<CACHELINELOG)

#define	MAXMACH		1			/* max # cpus system can run */
#define	MACHSIZE	BY2PG
#define KSTACK		4096			/* Size of kernel stack */

/*
 * Time
 */
#define HZ		100			/* clock frequency */
#define	MS2HZ		(1000/HZ)		/* millisec per clock tick */
#define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
#define	TK2MS(t)	((t)*MS2HZ)		/* ticks to milliseconds */
#define	MS2TK(t)	((t)/MS2HZ)		/* milliseconds to ticks */

/* Bit encodings for Machine State Register (MSR) */
#define MSR_POW		(1<<18)		/* Enable Power Management */
#define MSR_TGPR	(1<<17)		/* TLB Update registers in use */
#define MSR_ILE		(1<<16)		/* Interrupt Little-Endian enable */
#define MSR_EE		(1<<15)		/* External Interrupt enable */
#define MSR_PR		(1<<14)		/* Supervisor/User privelege */
#define MSR_FP		(1<<13)		/* Floating Point enable */
#define MSR_ME		(1<<12)		/* Machine Check enable */
#define MSR_SE		(1<<10)		/* Single Step */
#define MSR_BE		(1<<9)		/* Branch Trace */
#define MSR_IP		(1<<6)		/* Exception prefix 0x000/0xFFF */
#define MSR_IR		(1<<5)		/* Instruction MMU enable */
#define MSR_DR		(1<<4)		/* Data MMU enable */
#define MSR_RI		(1<<1)		/* Recoverable Exception */
#define MSR_LE		(1<<0)		/* Little-Endian enable */

/*
 * Traps
 */

/*
 * Magic registers
 */

#define	MACH		30		/* R30 is m-> */
#define	USER		29		/* R29 is up-> */

/*
 * Fundamental addresses
 */
#define	MACHADDR	((long)&mach0)

#define	UREGSIZE	((8+32)*4)

/*
 *  virtual MMU
 */
#define PTEMAPMEM	(1024*1024)	
#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
#define SEGMAPSIZE	1984
#define SSEGMAPSIZE	16
#define PPN(x)		((x)&~(BY2PG-1))

/*
 * MMU
 */

/* L1 table entry and Mx_TWC flags */
#define PTEVALID	(1<<0)
#define PTEWT		(1<<1)	/* write through */
#define PTE4K		(0<<2)
#define PTE512K		(1<<2)
#define PTE8MB		(3<<2)
#define PTEG		(1<<4)	/* guarded */

/* L2 table entry and Mx_RPN flags (also PTEVALID) */
#define PTECI		(1<<1)	/*  cache inhibit */
#define PTESH		(1<<2)	/* page is shared; ASID ignored */
#define PTELPS		(1<<3)	/* large page size */
#define PTEWRITE	0x9F0

/*
 *  physical MMU - bogus at the momement
 */
#define	PTEUNCACHED	(1<<4)
#define	PTERONLY	(0<<1)
#define	PTEKERNEL	(0<<2)
#define	PTEUSER		(1<<2)
#define PTESIZE		(1<<7)

/* TLB and MxEPN flag */
#define	TLBVALID	(1<<9)

#define	TLBSETS	32	/* number of tlb sets */

/*
 *  Address spaces
 *
 *  User is at 0-2GB
 *  Kernel is at 2GB-4GB
 */
#define	UZERO		0			/* base of user address space */
#define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
#define	KZERO		0x80000000		/* base of kernel address space */
#define	KTZERO		0xff000000		/* first address in kernel text */
#define	USTKTOP		(KZERO-BY2PG)		/* byte just beyond user stack */
#define	USTKSIZE	(16*1024*1024)		/* size of user stack */
#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
#define TSTKSIZ 	100

/*
 * atlas board registers
 */
#define	INTMEM		0x80000000
#define NIMMEM		0x80100000
#define	FLASH0MEM	0x80200000
#define	FLASH1MEM	0x80400000
#define	SDRAMMEM	0x03000000
#define DRAMMEM		0xff000000		// to 0xffffffff: 16 Meg

#define	SIRAM	(INTMEM+0xC00)
#define	LCDCOLR	(INTMEM+0xE00)
#define	DPRAM	(INTMEM+0x2000)
#define	DPLEN1	0x200
#define	DPLEN2	0x400
#define	DPLEN3	0x800
#define	DPBASE	(DPRAM+DPLEN1)

#define	SCC1P	(INTMEM+0x3C00)
#define	I2CP	(INTMEM+0x3C80)
#define	MISCP	(INTMEM+0x3CB0)
#define	IDMA1P	(INTMEM+0x3CC0)
#define	SCC2P	(INTMEM+0x3D00)
#define	SPIP	(INTMEM+0x3D80)
#define	TIMERP	(INTMEM+0x3DB0)
#define	SMC1P	(INTMEM+0x3E80)
#define	DSP1P	(INTMEM+0x3EC0)
#define	SMC2P	(INTMEM+0x3F80)
#define	DSP2P	(INTMEM+0x3FC0)

#define KEEP_ALIVE_KEY 0x55ccaa33	/* clock and rtc register key */

#define getpgcolor(a)	0

A mpc/mmu.c => mpc/mmu.c +68 -0
@@ 0,0 1,68 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"


static void
taskswitch(ulong pdb, ulong stack)
{
	USED(pdb, stack);
}

void
mmuinit(void)
{
}

void
flushmmu(void)
{
}

static void
mmuptefree(Proc* proc)
{
	USED(proc);
}

void
mmuswitch(Proc* proc)
{
	USED(proc);
}

void
mmurelease(Proc* proc)
{
	USED(proc);
}

static Page*
mmupdballoc(void)
{
}

void
putmmu(ulong va, ulong pa, Page*)
{
	USED(va, pa);
}

static Lock mmukmaplock;

int
mmukmapsync(ulong va)
{
	USED(va);
	return 0;
}

ulong
mmukmap(ulong pa, ulong va, int size)
{
	USED(pa, va, size);
	return 0;
}

A mpc/rmap.c => mpc/rmap.c +106 -0
@@ 0,0 1,106 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"

void
mapinit(RMap *rmap, Map *map, int size)
{
	lock(rmap);
	rmap->map = map;
	rmap->mapend = map+(size/sizeof(Map));
	unlock(rmap);
}

void
mapfree(RMap* rmap, ulong addr, int size)
{
	Map *mp;
	ulong t;

	if(size <= 0)
		return;

	lock(rmap);
	for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
		;

	if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
		(mp-1)->size += size;
		if(addr+size == mp->addr){
			(mp-1)->size += mp->size;
			while(mp->size){
				mp++;
				(mp-1)->addr = mp->addr;
				(mp-1)->size = mp->size;
			}
		}
	}
	else{
		if(addr+size == mp->addr && mp->size){
			mp->addr -= size;
			mp->size += size;
		}
		else do{
			if(mp >= rmap->mapend){
				print("mapfree: %s: losing 0x%uX, %d\n",
					rmap->name, addr, size);
				break;
			}
			t = mp->addr;
			mp->addr = addr;
			addr = t;
			t = mp->size;
			mp->size = size;
			mp++;
		}while(size = t);
	}
	unlock(rmap);
}

ulong
rmapalloc(RMap* rmap, ulong addr, int size, int align)
{
	Map *mp;
	ulong maddr, oaddr;

	lock(rmap);
	for(mp = rmap->map; mp->size; mp++){
		maddr = mp->addr;

		if(addr){
			if(maddr > addr)
				break;
			if(maddr+mp->size < addr)
				continue;
			if(addr+size > maddr+mp->size)
				break;
			maddr = addr;
		}

		if(align > 0)
			maddr = ((maddr+align-1)/align)*align;
		if(mp->addr+mp->size-maddr < size)
			continue;

		oaddr = mp->addr;
		mp->addr = maddr+size;
		mp->size -= maddr-oaddr+size;
		if(mp->size == 0){
			do{
				mp++;
				(mp-1)->addr = mp->addr;
			}while((mp-1)->size = mp->size);
		}

		unlock(rmap);
		if(oaddr != maddr)
			mapfree(rmap, oaddr, maddr-oaddr);

		return maddr;
	}
	unlock(rmap);

	return 0;
}

A mpc/segment.h => mpc/segment.h +8 -0
@@ 0,0 1,8 @@
/*
 * Attach segment types
 */
static Physseg physseg[10] = {
	{ SG_SHARED,	"shared",	0,	SEGMAXSIZE,	0, 	0 },
	{ SG_BSS,	"memory",	0,	SEGMAXSIZE,	0,	0 },
	{ 0,		0,		0,	0,		0,	0 },
};

A mpc/trap.c => mpc/trap.c +133 -0
@@ 0,0 1,133 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"
#include	"../port/error.h"

/* Give enough context in the ureg to produce a kernel stack for
 * a sleeping process
 */
void
setkernur(Ureg* ureg, Proc* p)
{
	ureg->pc = p->sched.pc;
	ureg->sp = p->sched.sp+4;
}

/* This routine must save the values of registers the user is not permitted to write
 * from devproc and then restore the saved values before returning
 */
void
setregisters(Ureg* ureg, char* pureg, char* uva, int n)
{
	USED(ureg, pureg, uva, n);
	panic("not done");
}

void
dumpregs(Ureg* ureg)
{
	USED(ureg);
	panic("not done");
}

void
dumpstack(void)
{
	panic("not done");
}

ulong
userpc(void)
{
	Ureg *ureg;

	ureg = (Ureg*)up->dbgreg;
	return ureg->pc;
}

ulong
dbgpc(Proc *p)
{
	Ureg *ureg;

	ureg = p->dbgreg;
	if(ureg == 0)
		return 0;

	return ureg->pc;
}

static void
linkproc(void)
{
	spllo();
	up->kpfun(up->kparg);
}

void
kprocchild(Proc* p, void (*func)(void*), void* arg)
{
	p->sched.pc = (ulong)linkproc;
	p->sched.sp = (ulong)p->kstack+KSTACK;

	p->kpfun = func;
	p->kparg = arg;
}

void
forkchild(Proc *p, Ureg *ureg)
{
	USED(p, ureg);
}

/*
 * called in sysfile.c
 */
void
evenaddr(ulong addr)
{
	if(addr & 3){
		postnote(up, 1, "sys: odd address", NDebug);
		error(Ebadarg);
	}
}

long
execregs(ulong entry, ulong ssize, ulong nargs)
{
	ulong *sp;
	Ureg *ureg;

	sp = (ulong*)(USTKTOP - ssize);
	*--sp = nargs;

	ureg = up->dbgreg;
	ureg->usp = (ulong)sp;
	ureg->pc = entry;
	return USTKTOP-BY2WD;		/* address of user-level clock */
}

void
trap(Ureg *ur)
{
	USED(ur);
}

/*
 * called directly by l.s:/intrvec
 */
void
intr(Ureg *ur)
{
	USED(ur);
}

void
intrenable(int v, void (*r)(Ureg*, void*), void *arg, int)
{
	USED(v, r, arg);
}