~kris/9p

9hist

1efdb88a07a90b8d224da51a6422ea3bac8a7fa0 — David du Colombier 34 years ago 3623085
Plan 9 from Bell Labs 1992-08-07
M gnot/dat.h => gnot/dat.h +1 -0
@@ 68,6 68,7 @@ struct Conf
{
	int	nmach;		/* processors */
	int	nproc;		/* processes */
	int	monitor;	/* has display */
	ulong	npage0;		/* total physical pages of memory, bank 0 */
	ulong	npage1;		/* total physical pages of memory, bank 1 */
	ulong	npage;

M gnot/main.c => gnot/main.c +1 -0
@@ 308,6 308,7 @@ confinit(void)
	conf.nmach = 1;
	if(conf.nmach > MAXMACH)
		panic("confinit");
	conf.monitor = 1;
	bank[0] = banksize(0);
	bank[1] = banksize(16);
	conf.npage0 = (bank[0]*MB)/BY2PG;

M pc/dat.h => pc/dat.h +1 -0
@@ 64,6 64,7 @@ struct Conf
{
	ulong	nmach;		/* processors */
	ulong	nproc;		/* processes */
	ulong	monitor;	/* has monitor? */
	ulong	npage0;		/* total physical pages of memory */
	ulong	npage1;		/* total physical pages of memory */
	ulong	topofmem;	/* highest physical address + 1 */

M pc/main.c => pc/main.c +1 -0
@@ 246,6 246,7 @@ confinit(void)
	/* for meminit() */
	conf.topofmem = i*MB;

	conf.monitor = 1;
	conf.nproc = 30 + i*5;
	conf.nswap = conf.nproc*80;
	conf.nimage = 50;

M port/devbit.c => port/devbit.c +26 -0
@@ 247,6 247,8 @@ bitreset(void)
	ulong r;
	Arena *a;

	if(!conf.monitor)
		return;
	bit.map = smalloc(DMAP*sizeof(GBitmap*));
	bit.nmap = DMAP;
	getcolor(0, &r, &r, &r);


@@ 286,6 288,8 @@ bitreset(void)
void
bitinit(void)
{
	if(!conf.monitor)
		return;
	if(gscreen.ldepth > 3)
		cursorback.ldepth = 0;
	else{


@@ 298,12 302,16 @@ bitinit(void)
Chan*
bitattach(char *spec)
{
	if(!conf.monitor)
		error(Egreg);
	return devattach('b', spec);
}

Chan*
bitclone(Chan *c, Chan *nc)
{
	if(!conf.monitor)
		error(Egreg);
	nc = devclone(c, nc);
	if(c->qid.path != CHDIR)
		incref(&bit);


@@ 313,12 321,16 @@ bitclone(Chan *c, Chan *nc)
int
bitwalk(Chan *c, char *name)
{
	if(!conf.monitor)
		error(Egreg);
	return devwalk(c, name, bitdir, NBIT, devgen);
}

void
bitstat(Chan *c, char *db)
{
	if(!conf.monitor)
		error(Egreg);
	devstat(c, db, bitdir, NBIT, devgen);
}



@@ 327,6 339,8 @@ bitopen(Chan *c, int omode)
{
	GBitmap *b;

	if(!conf.monitor)
		error(Egreg);
	switch(c->qid.path){
	case CHDIR:
		if(omode != OREAD)


@@ 378,6 392,8 @@ bitopen(Chan *c, int omode)
void
bitcreate(Chan *c, char *name, int omode, ulong perm)
{
	if(!conf.monitor)
		error(Egreg);
	USED(c, name, omode, perm);
	error(Eperm);
}


@@ 385,6 401,8 @@ bitcreate(Chan *c, char *name, int omode, ulong perm)
void
bitremove(Chan *c)
{
	if(!conf.monitor)
		error(Egreg);
	USED(c);
	error(Eperm);
}


@@ 392,6 410,8 @@ bitremove(Chan *c)
void
bitwstat(Chan *c, char *db)
{
	if(!conf.monitor)
		error(Egreg);
	USED(c, db);
	error(Eperm);
}


@@ 403,6 423,8 @@ bitclose(Chan *c)
	BSubfont *s, **sp, **esp;
	GFont *f, **fp, **efp;

	if(!conf.monitor)
		error(Egreg);
	if(c->qid.path!=CHDIR && (c->flag&COPEN)){
		lock(&bit);
		if(c->qid.path == Qmouse)


@@ 447,6 469,8 @@ bitread(Chan *c, void *va, long n, ulong offset)
	GBitmap *src;
	BSubfont *s;

	if(!conf.monitor)
		error(Egreg);
	if(c->qid.path & CHDIR)
		return devdirread(c, va, n, bitdir, NBIT, devgen);



@@ 729,6 753,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	GFont *ff, **ffp;
	GCacheinfo *gc;

	if(!conf.monitor)
		error(Egreg);
	USED(offset);

	if(c->qid.path == CHDIR)

M port/tcpinput.c => port/tcpinput.c +6 -3
@@ 11,10 11,12 @@ int tcpdbg = 0;
#define DPRINT	if(tcpdbg) print
#define LPRINT  if(tcpdbg) print

char *tcpstate[] = {
char *tcpstate[] =
{
	"Closed", 	"Listen", 	"Syn_sent", "Syn_received",
	"Established", 	"Finwait1",	"Finwait2", "Close_wait",
	"Closing", 	"Last_ack", 	"Time_wait" };
	"Closing", 	"Last_ack", 	"Time_wait"
};

void
reset(Ipaddr source, Ipaddr dest, char tos, ushort length, Tcp *seg)


@@ 379,7 381,8 @@ tcp_input(Ipifc *ifc, Block *bp)
		if(length == 0){
			if(bp)
				freeb(bp);
		} else {
		}
		else {
			switch(tcb->state){
			default:
				/* Ignore segment text */

M port/tcptimer.c => port/tcptimer.c +2 -3
@@ 115,6 115,7 @@ tcpflow(void *x)

	ifc = x;
	etab = &ifc->conv[Nipconv];

	for(;;) {
		sleep(&tcpflowr, return0, 0);



@@ 122,9 123,7 @@ tcpflow(void *x)
			cp = *p;
			if(cp == 0)
				break;
			if(cp->readq)
			if(cp->ref != 0)
			if(!QFULL(cp->readq->next)) {
			if(cp->readq && cp->ref != 0 && !QFULL(cp->readq->next)) {
				tcprcvwin(cp);
				tcp_acktimer(cp);
			}

M ss/clock.c => ss/clock.c +2 -0
@@ 61,6 61,8 @@ clock(Ureg *ur)
	mouseclock();
	sccclock();
	kproftimer(ur->pc);
	if(m->fpunsafe)
		return;
	if((ur->psr&SPL(0xF))==0 && p && p->state==Running){
		if(anyready()){
			if(p->hasspin)

M ss/dat.h => ss/dat.h +55 -1
@@ 7,6 7,9 @@ typedef struct Lancemem	Lancemem;
typedef struct Label	Label;
typedef struct Lock	Lock;
typedef struct PMMU	PMMU;
typedef struct Scsi	Scsi;
typedef struct Scsibuf	Scsibuf;
typedef struct Scsidata	Scsidata;
typedef struct Mach	Mach;
typedef struct Ureg	Ureg;
typedef struct User	User;


@@ 65,7 68,13 @@ struct Conf
{
	int	nmach;		/* processors */
	int	nproc;		/* processes */
	int	ss2;		/* is a sparcstation 2 */
	char	ss2;		/* is a sparcstation 2 */
	char	ss2cachebug;	/* has sparcstation2 cache bug */
	char	monitor;	/* has graphics monitor */
	int	ncontext;	/* in mmu */
	int	npmeg;
	int	vacsize;	/* size of virtual address cache, in bytes */
	int	vaclinesize;	/* size of cache line */
	ulong	npage0;		/* total physical pages of memory, bank 0 */
	ulong	npage1;		/* total physical pages of memory, bank 1 */
	ulong	base0;		/* base of bank 0 */


@@ 205,3 214,48 @@ struct
	short	machs;
	short	exiting;
}active;

enum
{
	ScsiTestunit	= 0x00,
	ScsiExtsens	= 0x03,
	ScsiModesense	= 0x1a,
	ScsiGetcap	= 0x25,
	ScsiRead	= 0x08,
	ScsiWrite	= 0x0a,

	/*
	 * data direction
	 */
	ScsiIn		= 1,
	ScsiOut		= 0,
};

struct Scsibuf
{
	void	*virt;
	void	*phys;
	Scsibuf	*next;
};

struct Scsidata
{
	uchar	*base;
	uchar	*lim;
	uchar	*ptr;
};

struct Scsi
{
	QLock;
	ulong	pid;
	ushort	target;
	ushort	lun;
	ushort	rflag;
	ushort	status;
	Scsidata cmd;
	Scsidata data;
	Scsibuf	*b;
	uchar	*save;
	uchar	cmdblk[16];
};

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

#include	"io.h"

/*
 * Mostek MK48T12-15 Zeropower/Timekeeper
 * This driver is actually portable.
 */
typedef struct Rtc	Rtc;
struct Rtc
{
	int	sec;
	int	min;
	int	hour;
	int	wday;
	int	mday;
	int	mon;
	int	year;
};
ulong	rtc2sec(Rtc *);
void	sec2rtc(ulong, Rtc *);

static struct
{
	uchar	*ram;
	RTCdev	*rtc;
}nvr;


enum{
	Qrtc = 1,
	Qnvram,
};

QLock	rtclock;		/* mutex on clock operations */

static Dirtab rtcdir[]={
	"rtc",		{Qrtc, 0},	0,	0666,
	"nvram",	{Qnvram, 0},	0,	0666,
};
#define	NRTC	(sizeof(rtcdir)/sizeof(rtcdir[0]))
void	setrtc(Rtc*);
long	rtctime(void);

void
rtcreset(void)
{
}

void
rtcinit(void)
{
	KMap *k;

	k = kmappa(NVRAM, PTENOCACHE|PTEIO);
	nvr.ram = (uchar*)k->va;
	nvr.rtc = (RTCdev*)(k->va+RTCOFF);
}

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

Chan*
rtcclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

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

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

Chan*
rtcopen(Chan *c, int omode)
{
	return devopen(c, omode, rtcdir, NRTC, devgen);
}

void	 
rtccreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void	 
rtcclose(Chan *c)
{
	USED(c);
}

long	 
rtcread(Chan *c, void *buf, long n, ulong offset)
{
	ulong t, ot;

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

	switch(c->qid.path){
	case Qrtc:
		qlock(&rtclock);
		t = rtctime();
		do{
			ot = t;
			t = rtctime();	/* make sure there's no skew */
		}while(t != ot);
		qunlock(&rtclock);
		n = readnum(offset, buf, n, t, 12);
		return n;
	case Qnvram:
		if(offset > NVREAD)
			return 0;
		if(n > NVREAD - offset)
			n = NVREAD - offset;
		qlock(&rtclock);
		memmove(buf, nvr.ram+offset, n);
		qunlock(&rtclock);
		return n;
	}
	error(Egreg);
	return 0;		/* not reached */
}

long	 
rtcwrite(Chan *c, void *buf, long n, ulong offset)
{
	Rtc rtc;
	ulong secs;
	char *cp, *ep;

	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);
		/*
		 *  convert to bcd
		 */
		sec2rtc(secs, &rtc);
		/*
		 * write it
		 */
		qlock(&rtclock);
		setrtc(&rtc);
		qunlock(&rtclock);
		return n;
	case Qnvram:
		if(offset > NVWRITE)
			return 0;
		if(n > NVWRITE - offset)
			n = NVWRITE - offset;
		qlock(&rtclock);
		memmove(nvr.ram+offset, buf, n);
		qunlock(&rtclock);
		return n;
	}
	error(Egreg);
	return 0;		/* not reached */
}

void	 
rtcremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void	 
rtcwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

#define bcd2dec(bcd)	(((((bcd)>>4) & 0x0F) * 10) + ((bcd) & 0x0F))
#define dec2bcd(dec)	((((dec)/10)<<4)|((dec)%10))

void
setrtc(Rtc *rtc)
{
	struct RTCdev *dev;

	dev = nvr.rtc;
	dev->control |= RTCWRITE;
	wbflush();
	dev->year = dec2bcd(rtc->year % 100);
	dev->mon = dec2bcd(rtc->mon);
	dev->mday = dec2bcd(rtc->mday);
	dev->hour = dec2bcd(rtc->hour);
	dev->min = dec2bcd(rtc->min);
	dev->sec = dec2bcd(rtc->sec);
	wbflush();
	dev->control &= ~RTCWRITE;
	wbflush();
}

long
rtctime(void)
{
	struct RTCdev *dev;
	Rtc rtc;

	dev = nvr.rtc;
	dev->control |= RTCREAD;
	wbflush();
	rtc.sec = bcd2dec(dev->sec) & 0x7F;
	rtc.min = bcd2dec(dev->min & 0x7F);
	rtc.hour = bcd2dec(dev->hour & 0x3F);
	rtc.mday = bcd2dec(dev->mday & 0x3F);
	rtc.mon = bcd2dec(dev->mon & 0x3F);
	rtc.year = bcd2dec(dev->year);
	dev->control &= ~RTCREAD;
	wbflush();

	if (rtc.mon < 1 || rtc.mon > 12)
		return 0;
	/*
	 *  the world starts Jan 1 1970
	 */
	if(rtc.year < 70)
		rtc.year += 2000;
	else
		rtc.year += 1900;

	return rtc2sec(&rtc);
}

#define SEC2MIN 60L
#define SEC2HOUR (60L*SEC2MIN)
#define SEC2DAY (24L*SEC2HOUR)

/*
 *  days per month plus days/year
 */
static	int	dmsize[] =
{
	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static	int	ldmsize[] =
{
	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

/*
 *  return the days/month for the given year
 */
int *
yrsize(int yr)
{
	if((yr % 4) == 0)
		return ldmsize;
	else
		return dmsize;
}

/*
 *  compute seconds since Jan 1 1970
 */
ulong
rtc2sec(Rtc *rtc)
{
	ulong secs;
	int i;
	int *d2m;

	secs = 0;

	/*
	 *  seconds per year
	 */
	for(i = 1970; i < rtc->year; i++){
		d2m = yrsize(i);
		secs += d2m[0] * SEC2DAY;
	}

	/*
	 *  seconds per month
	 */
	d2m = yrsize(rtc->year);
	for(i = 1; i < rtc->mon; i++)
		secs += d2m[i] * SEC2DAY;

	secs += (rtc->mday-1) * SEC2DAY;
	secs += rtc->hour * SEC2HOUR;
	secs += rtc->min * SEC2MIN;
	secs += rtc->sec;

	return secs;
}

/*
 *  compute rtc from seconds since Jan 1 1970
 */
void
sec2rtc(ulong secs, Rtc *rtc)
{
	int d;
	long hms, day;
	int *d2m;

	/*
	 * break initial number into days
	 */
	hms = secs % SEC2DAY;
	day = secs / SEC2DAY;
	if(hms < 0) {
		hms += SEC2DAY;
		day -= 1;
	}

	/*
	 * generate hours:minutes:seconds
	 */
	rtc->sec = hms % 60;
	d = hms / 60;
	rtc->min = d % 60;
	d /= 60;
	rtc->hour = d;

	/*
	 * year number
	 */
	if(day >= 0)
		for(d = 1970; day >= *yrsize(d); d++)
			day -= *yrsize(d);
	else
		for (d = 1970; day < 0; d--)
			day += *yrsize(d-1);
	rtc->year = d;

	/*
	 * generate month
	 */
	d2m = yrsize(rtc->year);
	for(d = 1; day >= d2m[d]; d++)
		day -= d2m[d];
	rtc->mday = day + 1;
	rtc->mon = d;

	return;
}

M ss/fns.h => ss/fns.h +22 -3
@@ 21,7 21,6 @@ void	fpsave(FPsave*);
int	fptrap(void);
int	getfpq(ulong*);
ulong	getfsr(void);
ulong	(*getsysspace)(ulong);
void	intrinit(void);
void	ioinit(void);
int	kbdstate(IOQ*, int);


@@ 46,18 45,26 @@ void	printinit(void);
#define	procsave(p)
#define	procsetup(x)	((p)->fpstate = FPinit)
void	putcxsegm(int, ulong, int);
void	(*putenab)(ulong);
void	putpmeg(ulong, ulong);
void	putsegm(ulong, int);
void	(*putsysspace)(ulong, ulong);
void	putstr(char*);
void	putstrn(char*, long);
void	puttbr(ulong);
void	putw4(ulong, ulong);	/* needed only at boot time */
void	systemreset(void);
void	restfpregs(FPsave*, ulong);
void	screeninit(void);
void	screenputc(int);
void	screenputs(char*, int);
Scsibuf	*scsialloc(ulong);
int	scsibread(int, Scsibuf*, long, long, long);
int	scsibwrite(int, Scsibuf*, long, long, long);
Scsibuf	*scsibuf(void);
int	scsicap(int, void*);
void	scsifree(Scsibuf*);
void	scsiintr(void);
int	scsiready(int);
int	scsisense(int, void *);
void	spldone(void);
ulong	tas(ulong*);
void	touser(ulong);


@@ 66,3 73,15 @@ void	trapinit(void);
#define	wbflush()	/* mips compatibility */
#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define getcallerpc(x)	(*(ulong*)(x))

/*
 * compiled entry points
 */
extern	void	(*putcontext)(ulong);
extern	void	(*putenab)(ulong);
extern	ulong	(*getenab)(void);
extern	void	(*putpmegspace)(ulong, ulong);
extern	void	(*putsysspace)(ulong, ulong);
extern	ulong	(*getsysspace)(ulong);
extern	ulong	(*flushcx)(ulong);
extern	ulong	(*flushpg)(ulong);

M ss/io.h => ss/io.h +106 -0
@@ 4,6 4,9 @@
#define	CLOCKFREQ	1000000		/* one microsecond increments */
#define	KMDUART		0xF0000000	/* keyboard A, mouse B */
#define	EIADUART	0xF1000000	/* serial ports */
#define	NVRAM		0xF2000000	/* non-volatile RAM */
#define DMA		0xF8400000	/* DMA registers */
#define SCSI		0xF8800000	/* NCR53C90 registers */
#define	ETHER		0xF8C00000	/* RDP, RAP */
#define	EEPROM		0xF2000000
#define	INTRREG		0xF5000000	/* interrupt register, IO space */


@@ 23,3 26,106 @@ struct SCCdev

#define KMFREQ	10000000	/* crystal frequency for kbd/mouse 8530 */
#define EIAFREQ	5000000		/* crystal frequency for serial port 8530 */

/*
 *  non-volatile ram
 */
#define NVREAD	(2048-8)	/* minus RTC */
#define NVWRITE	(2048-8-32)	/* minus RTC, minus ID prom */

/*
 * real-time clock (every 4th location)
 */
typedef struct RTCdev	RTCdev;
struct RTCdev
{
	uchar	control;		/* read or write the device */
	uchar	sec;
	uchar	min;
	uchar	hour;
	uchar	wday;
	uchar	mday;
	uchar	mon;
	uchar	year;
};
#define RTCOFF		0x7F8
#define RTCREAD		(0x40)
#define RTCWRITE	(0x80)

/*
 * dma
 */
typedef struct DMAdev DMAdev;
struct DMAdev {
	ulong	csr;			/* Control/Status */
	ulong	addr;			/* address in 16Mb segment */
	ulong	count;			/* transfer byte count */
	ulong	diag;
};

enum {
	Int_pend	= 0x00000001,	/* interrupt pending */
	Err_pend	= 0x00000002,	/* error pending */
	Pack_cnt	= 0x0000000C,	/* pack count (mask) */
	Int_en		= 0x00000010,	/* interrupt enable */
	Dma_Flush	= 0x00000020,	/* flush pack end error */
	Drain		= 0x00000040,	/* drain pack to memory */
	Dma_Reset	= 0x00000080,	/* hardware reset (sticky) */
	Write		= 0x00000100,	/* set for device to memory (!) */
	En_dma		= 0x00000200,	/* enable DMA */
	Req_pend	= 0x00000400,	/* request pending */
	Byte_addr	= 0x00001800,	/* next byte addr (mask) */
	En_cnt		= 0x00002000,	/* enable count */
	Tc		= 0x00004000,	/* terminal count */
	Ilacc		= 0x00008000,	/* which ether chip */
	Dev_id		= 0xF0000000,	/* device ID */
};

/*
 *  NCR53C90 SCSI controller (every 4th location)
 */
typedef struct SCSIdev	SCSIdev;
struct SCSIdev {
	uchar	countlo;		/* byte count, low bits */
	uchar	pad1[3];
	uchar	counthi;		/* byte count, hi bits */
	uchar	pad2[3];
	uchar	fifo;			/* data fifo */
	uchar	pad3[3];
	uchar	cmd;			/* command byte */
	uchar	pad4[3];
	union {
		struct {		/* read only... */
			uchar	status;		/* status */
			uchar	pad05[3];
			uchar	intr;		/* interrupt status */
			uchar	pad06[3];
			uchar	step;		/* sequence step */
			uchar	pad07[3];
			uchar	fflags;		/* fifo flags */
			uchar	pad08[3];
			uchar	config;		/* configuration */
			uchar	pad09[3];
			uchar	Reserved1;
			uchar	pad0A[3];
			uchar	Reserved2;
			uchar	pad0B[3];
		};
		struct {		/* write only... */
			uchar	destid;		/* destination id */
			uchar	pad15[3];
			uchar	timeout;	/* during selection */
			uchar	pad16[3];
			uchar	syncperiod;	/* synchronous xfr period */
			uchar	pad17[3];
			uchar	syncoffset;	/* synchronous xfr offset */
			uchar	pad18[3];
			uchar	XXX;
			uchar	pad19[3];
			uchar	clkconf;
			uchar	pad1A[3];
			uchar	test;	
			uchar	pad1B[3];
		};
	};
};

M ss/l.s => ss/l.s +10 -1
@@ 22,6 22,9 @@ TEXT	start(SB), $-4

TEXT	startvirt(SB), $-4

	MOVW	$romvec(SB), R7
	MOVW	R8, (R7)	/* romvec passed in %i0==R8 */

	MOVW	$BOOTSTACK, R1

	MOVW	$(SPL(0xF)|PSREF|PSRSUPER), R7


@@ 324,10 327,16 @@ TEXT	putcxsegm(SB), $0
	MOVW	R7, R8			/* context */
	MOVW	4(FP), R9		/* segment addr */
	MOVW	8(FP), R10		/* segment value */
	MOVW	$PUTCXSEGM, R7
	MOVW	$romputcxsegm(SB), R7
	MOVW	(R7), R7
	JMPL	(R7)
	RETURN

TEXT	putw4(SB), $0
	MOVW	4(FP), R8
	MOVW	R8, (R7, 4)
	RETURN

TEXT	getpsr(SB), $0

	MOVW	PSR, R7

M ss/main.c => ss/main.c +105 -14
@@ 9,7 9,13 @@
#include	<libg.h>
#include	<gnot.h>

uchar *intrreg;
uchar	*intrreg;
int	model;
uchar	idprom[32];
ulong	romvec;		/* open boot rom vector */
int	cpuserver;
ulong	romputcxsegm;
ulong	bank[2];

void
main(void)


@@ 23,12 29,15 @@ main(void)
	confinit();
	xinit();
	mmuinit();
	screeninit();
	if(conf.monitor)
		screeninit();
	printinit();
	pageinit();
	trapinit();
	kmapinit();
	ioinit();
	if(!conf.monitor)
		sccspecial(2, &printq, &kbdq, 9600);
	pageinit();
	cacheinit();
	intrinit();
	procinit0();


@@ 54,7 63,7 @@ void
systemreset(void)
{
	delay(100);
	putb2(ENAB, ENABRESET);
	putenab(ENABRESET);
}




@@ 98,6 107,7 @@ init0(void)
	u->p->mach = m;
	spllo();

	print("bank 0: %dM  1: %dM\n", bank[0], bank[1]);
	u->slash = (*devtab[0].attach)(0);
	u->dot = clone(u->slash, 0);



@@ 194,42 204,123 @@ exit(void)
	systemreset();
}

int
banksize(ulong addr, ulong nbytes)
{
	int i;
	ulong min, max, t;
	ulong va, pa;
	ulong nmeg;

	nmeg = nbytes/MB;
	va = 1*MB-2*BY2PG;
	for(i=0; i<nmeg; i++){
		pa = addr+i*MB;
		putw4(va, PPN(pa)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEWRITE|PTEMAINMEM);
		*(ulong*)va = pa;
	}
	min = ~0;
	max = 0;
	for(i=0; i<nmeg; i++){
		pa = addr+i*MB;
		putw4(va, PPN(pa)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEWRITE|PTEMAINMEM);
		t = *(ulong*)va;
		if(min > t)
			min = t;
		if(max < t)
			max = t;
	}
	putw4(va, INVALIDPTE);
	return (max-min)/MB+1;
}

Conf	conf;

void
confinit(void)
{
	int mul;
	ulong ktop;
	ulong i;
	ulong ktop, va, mbytes;

	conf.nmach = 1;
	if(conf.nmach > MAXMACH)
		panic("confinit");

	conf.ss2 = 0;
	conf.npage0 = (4*1024*1024)/BY2PG;	/* BUG */
	conf.npage1 = (4*1024*1024)/BY2PG;	/* BUG */
	conf.base0 = 0;
	conf.base1 = 32*1024*1024;
	conf.npage = conf.npage0+conf.npage1;
	/* map id prom */
	va = 1*MB-BY2PG;
	putw4(va, PPN(EEPROM)|PTEVALID|PTEKERNEL|PTENOCACHE|PTEIO);
	memmove(idprom, (char*)(va+0x7d8), 32);
	if(idprom[0]!=1 || (idprom[1]&0xF0)!=0x50)
		*(ulong*)va = 0;
	putw4(va, INVALIDPTE);

	switch(idprom[1]){
	case 0x51:		/* sparcstation 1 */
	case 0x54:		/* slc */
	default:
		conf.ss2 = 0;
		conf.vacsize = 65536;
		conf.vaclinesize = 16;
		conf.ncontext = 8;
		conf.npmeg = 128;
		conf.ss2cachebug = 0;
		conf.monitor = 1;		/* BUG */
		conf.base0 = 0;
		conf.base1 = 32*MB;
		break;

	case 0x55:		/* sparcstation 2 */
		conf.ss2 = 1;
		conf.vacsize = 65536;
		conf.vaclinesize = 32;
		conf.ncontext = 16;
		conf.npmeg = 256;
		conf.ss2cachebug = 1;
		conf.monitor = 0;		/* BUG */
		conf.base0 = 0;
		conf.base1 = 16*MB;
		break;
	}

	bank[0] = banksize(conf.base0, 16*MB);
	bank[1] = banksize(conf.base1, 16*MB);
	conf.npage0 = (bank[0]*MB)/BY2PG;
	conf.npage1 = (bank[1]*MB)/BY2PG;

	conf.upages = 1400;
	romputcxsegm = *(ulong*)(romvec+260);

	conf.npage = conf.npage0+conf.npage1;
	conf.upages = (conf.npage*70)/100;
	if(cpuserver){
		i = conf.npage-conf.upages;
		if(i > (6*MB)/BY2PG)
			conf.upages +=  i - ((6*MB)/BY2PG);
	}

	ktop = PGROUND((ulong)end);
	ktop = PADDR(ktop);
	conf.npage0 -= ktop/BY2PG;
	conf.base0 += ktop;

	mul = conf.upages/700;
	mbytes = (conf.npage*BY2PG)>>20;
	mul = 1 + (mbytes+11)/12;
	if(mul > 2)
		mul = 2;

	conf.nproc = 50*mul;
	conf.nswap = 4096;
	if(cpuserver)
		conf.nswap = conf.npage*2;
	else
		conf.nswap = 4096;
	conf.nimage = 50;
	conf.copymode = 0;		/* copy on write */
	conf.ipif = 8;
	conf.ip = 64;
	conf.arp = 32;
	conf.frag = 32;
	if(cpuserver)
		conf.nproc = 500;
}

/*

M ss/mem.h => ss/mem.h +6 -16
@@ 56,20 56,19 @@
 */

#define	VAMASK		0x3FFFFFFF
#define	NPMEG		(1<<12)
#define	BY2SEGM		(1<<18)
#define	PG2SEGM		(1<<6)
#define	NTLBPID		(1+NCONTEXT)	/* TLBPID 0 is unallocated */
#define	NCONTEXT	8
#define	NTLBPID		(1+MAXCONTEXT)	/* TLBPID 0 is unallocated */
#define	MAXCONTEXT	16
#define	CONTEXT		0x30000000	/* in ASI 2 */

/*
 * MMU regions
 */
#define	INVALIDSEGM	0xFFFC0000	/* highest seg of VA reserved as invalid */
#define	INVALIDPMEG	0x7F
#define	INVALIDPMEG	(conf.npmeg-1)
#define	SCREENSEGM	0xFFF80000
#define	SCREENPMEG	0x7E
#define	SCREENPMEG	(conf.npmeg-2)
#define	ROMSEGM		0xFFE80000
#define	ROMEND		0xFFEC0000
#define	PG2ROM		((ROMEND-ROMSEGM)/BY2PG)


@@ 110,10 109,9 @@
#define	ASER		0x60000008		/* ASI 2 */
#define	ASEVAR		0x6000000C		/* ASI 2 */
#define	ENAB		0x40000000		/* ASI 2 */
#define	ENABCACHE	0x10
#define	ENABRESET	0x04
#define	VACLINESZ	16			/* cache line size */
#define	VACSIZE		(1<<16)			/* total cache size */
#define	ENABCACHE	0x10
#define ENABDMA		0x20

/*
 * Virtual addresses


@@ 122,14 120,8 @@
#define	VPN(va)		((va>>13)&0x1FF)

/*
 * Rom addresses
 */
#define	PUTCXSEGM	0xFFE80118

/*
 * Address spaces
 */

#define	UZERO	0x00000000		/* base of user address space */
#define	UTZERO	(UZERO+BY2PG)		/* first address in user text */
#define	TSTKTOP	0x10000000		/* end of new stack in sysexec */


@@ 140,5 132,3 @@
#define	USTKSIZE	(4*1024*1024)	/* size of user stack */

#define	MACHSIZE	4096

#define isphys(x) (((ulong)(x)&0xF0000000) == KZERO)

M ss/mmu.c => ss/mmu.c +12 -17
@@ 89,13 89,15 @@ mmurelease(Proc *p)
int
newpid(Proc *p)
{
	int i, j;
	int i, j, nc;
	ulong t;
	Proc *sp;

	t = ~0;
	i = 1+((m->ticks)&(NCONTEXT-1));	/* random guess */
	for(j=1; t && j<NTLBPID; j++)
	nc = conf.ncontext;
	i = 1+((m->ticks)&(nc-1));	/* random guess */
	nc++;
	for(j=1; t && j<nc; j++)
		if(pidtime[j] < t){
			i = j;
			t = pidtime[j];


@@ 132,7 134,7 @@ flushcontext(void)
	a = 0;
	do
		a = flushcx(a);
	while(a < VACSIZE);
	while(a < conf.vacsize);
}

void


@@ 156,7 158,7 @@ mmuinit(void)
	 * First map lots of memory as kernel addressable in all contexts
	 */
	i = 0;		/* used */
	for(c=0; c<NCONTEXT; c++)
	for(c=0; c<conf.ncontext; c++)
		for(i=0; i < ktop/BY2SEGM; i++)
			putcxsegm(c, KZERO+i*BY2SEGM, i);



@@ 177,7 179,7 @@ mmuinit(void)
	for(i=0; i<PG2SEGM; i++)
		putpmeg(INVALIDSEGM+i*BY2PG, INVALIDPTE);

	for(c=0; c<NCONTEXT; c++){
	for(c=0; c<conf.ncontext; c++){
		putcontext(c);
		putsegm(INVALIDSEGM, INVALIDPMEG);
		/*


@@ 274,13 276,6 @@ putpmeg(ulong virt, ulong phys)

	virt &= VAMASK;
	virt &= ~(BY2PG-1);
#ifdef asdf
	if(conf.ss2)
		putw6(virt, 0);
	else
		for(i=0; i<BY2PG; i+=16*VACLINESZ)
			putwD16(virt+i, 0);
#endif
	/*
	 * Flush old entries from cache
	 */


@@ 319,7 314,7 @@ cacheinit(void)
	 * Initialize cache by clearing the valid bit
	 * (along with the others) in all cache entries
	 */
	for(i=0; i<VACSIZE; i+=VACLINESZ)
	for(i=0; i<conf.vacsize; i+=conf.vaclinesize)
		putsysspace(CACHETAGS+i, 0);

	/*


@@ 438,10 433,10 @@ compile(void)
	getsysspace = compileldaddr(LDA, 2);
	if(conf.ss2){
		flushpg = compile1(BY2PG, 6);
		flushcx = compile16(VACLINESZ, 7);
		flushcx = compile16(conf.vaclinesize, 7);
	}else{
		flushpg = compile16(VACLINESZ, 0xD);
		flushcx = compile16(VACLINESZ, 0xE);
		flushpg = compile16(conf.vaclinesize, 0xD);
		flushcx = compile16(conf.vaclinesize, 0xE);
	}
}


A ss/rom.h => ss/rom.h +55 -0
@@ 0,0 1,55 @@
typedef struct ROM	ROM;
typedef struct ROMconf	ROMconf;

struct ROM
{
	uint	magic;
	uint	version;
	uint	plugversion;
	uint	monid;
	uint	pad1[3];
	ROMconf	*conf;
	uint	pad2[17];
	void	(*boot)(void*);
	uint	pad3[1];
	void	(*enter)(void);
	int	*msec;
	void	(*exit)(void);
	void	(**callback)(void);
	uint	(*interpret)(void*);
	uint	pad4[2];	
	char	**bootpath;
	char	**bootargs;
	uint	*stdin;
	uint	*stdout;
	uint	(*phandle)(uint);
	uint	(*alloc)(void*, uint);
	void	(*free)(void*);
	uint	(*map)(void*, uint, uint, uint);
	void	(*unmap)(void*, uint);
	uint	(*open)(char*);
	uint	(*close)(uint);
	uint	(*read)(uint, void*, int);
	uint	(*write)(uint, void*, int);
	uint	(*seek)(uint, uint, uint);
	void	(*chain)(void*, uint, void*, void*, uint);
	void	(*release)(void*, uint);
	uint	pad5[16];
	int	(*startcpu)(uint, uint, uint, uint);
	int	(*stopcpu)(uint);
	int	(*idlecpu)(uint);
	int	(*resumecpu)(uint);
};

struct ROMconf
{
	uint	(*next)(uint);
	uint	(*child)(uint);
	int	(*getproplen)(uint, void*);
	int	(*getprop)(uint, void*, void*);
	void*	(*nextprop)(uint, void*);	
};

#define	ROMMAGIC	0x10010407

extern	ROM	*rom;

M ss/screen.c => ss/screen.c +6 -0
@@ 38,6 38,8 @@ Lock screenlock;
void
screeninit(void)
{
	if(!conf.monitor)
		return;
	defont = &defont0;
	gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, 0);
	out.pos.x = MINX;


@@ 48,6 50,8 @@ screeninit(void)
void
screenputnl(void)
{
	if(!conf.monitor)
		return;
	out.pos.x = MINX;
	out.pos.y += defont0.height;
	if(out.pos.y > gscreen.r.max.y-defont0.height)


@@ 63,6 67,8 @@ screenputs(char *s, int n)
	int i;
	char buf[4];

	if(!conf.monitor)
		return;
	lock(&screenlock);
	while(n > 0){
		i = chartorune(&r, s);

A ss/scsi.c => ss/scsi.c +297 -0
@@ 0,0 1,297 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"devtab.h"
#include	"io.h"

static int	ownid = 7;

Scsibuf *
scsialloc(ulong n)
{
	Scsibuf *b;
	KMap *k;
	ulong pa, va;
	int i, j;

	b = xalloc(sizeof(Scsibuf));

	/*
	 * Allocate space in host memory for the io buffer.
	 * Allocate a block and kmap it page by page.  kmap's are initially
	 * in reverse order so rearrange them.
	 * NOTE: dma mustn't cross a 16Mb boundary.
	 */
	i = (n+(BY2PG-1))/BY2PG;
	pa = (ulong)xspanalloc(i*BY2PG, BY2PG, 16*1024*1024) & ~KZERO;
	va = 0;
	k = 0;
	for(j=i-1; j>=0; j--){
		k = kmappa(pa+j*BY2PG, PTEMAINMEM|PTENOCACHE);
		if(va && va != k->va+BY2PG)
			panic("scsialloc va unordered\n");
		va = k->va;
	}
	/*
	 * k->va is the base of the region
	 */
	b->virt = (void*)k->va;
	b->phys = (void*)k->pa;

	return b;
}

/*
 *	NCR 53C90 commands
 */

enum
{
	Dma		= 0x80,
	Nop		= 0x00,
	Flush		= 0x01,
	Reset		= 0x02,
	Busreset	= 0x03,
	Select		= 0x41,
	Transfer	= 0x10,
	Cmdcomplete	= 0x11,
	Msgaccept	= 0x12
};

static QLock	scsilock;	/* access to device */
static Rendez	scsirendez;	/* sleep/wakeup for requesting process */
static Scsi *	curcmd;		/* currently executing command */

struct {
	DMAdev *dma;
	SCSIdev *scsi;
} ioaddr;

void
resetscsi(void)
{
	SCSIdev *dev;
	DMAdev *dma;
	KMap *k;

	k = kmappa(DMA, PTENOCACHE|PTEIO);
	ioaddr.dma = (DMAdev*)k->va;
	k = kmappa(SCSI, PTENOCACHE|PTEIO);
	ioaddr.scsi = (SCSIdev*)k->va;

	dev = ioaddr.scsi;
	dma = ioaddr.dma;

	dev->cmd = Reset;
	dev->cmd = Nop;
	dev->countlo = 0;
	dev->counthi = 0;
	dev->timeout = 146;
	dev->syncperiod = 0;
	dev->syncoffset = 0;
	dev->config = 0x10|(ownid&7);
	dev->cmd = Dma|Nop;

	dma->csr = Dma_Reset;
	delay(1);
	dma->csr = Int_en;
	dma->count = 0;

	putenab(getenab()|ENABDMA); /**/
}

void
initscsi(void)
{
}

static int
scsidone(void *arg)
{
	USED(arg);
	return (curcmd == 0);
}

int
scsiexec(Scsi *p, int rflag)
{
	SCSIdev *dev = ioaddr.scsi;
	DMAdev *dma = ioaddr.dma;
	long n;

	qlock(&scsilock);

	if(waserror()){
		qunlock(&scsilock);
		nexterror();
	}
	p->rflag = rflag;
	p->status = 0;

	dma->csr = Dma_Flush|Int_en;
	dma->addr = (ulong)p->data.ptr;

	dev->counthi = 0;
	dev->countlo = 0;
	dev->cmd = Dma|Nop;
	dev->cmd = Flush;			/* clear scsi fifo */

	while (p->cmd.ptr < p->cmd.lim)
		dev->fifo = *(p->cmd.ptr)++;

	dev->destid = p->target&7;
	n = p->data.lim - p->data.ptr;
	dev->counthi = n>>8;
	dev->countlo = n;
	dev->cmd = Dma|Nop;

	dma->csr = Int_en;

	curcmd = p;
	dev->cmd = Select;

	sleep(&scsirendez, scsidone, 0);
	poperror();
	qunlock(&scsilock);
	return p->status;
}


void
scsibusreset(void)
{
	SCSIdev *dev = ioaddr.scsi;
	int s;

	s = splhi();
	dev->cmd = Nop;
	dev->cmd = Busreset;
	dev->cmd = Nop;
	splx(s);
}

static void
scsimoan(char *msg, int status, int intr, int dmastat)
{
	print("scsiintr: %s:", msg);
	print(" status=%2.2ux step/intr=%3.3ux", status, intr);
	print(" dma=%8.8ux cmd status=%4.4ux\n",
		dmastat, curcmd ? curcmd->status : 0xffff);
}

void
scsiintr(void)
{
	SCSIdev *dev = ioaddr.scsi;
	DMAdev *dma = ioaddr.dma;
	Scsi *p = curcmd;
	int status, step, intr, n;
	ulong m, csr;

	csr = dma->csr;

	status = dev->status;
	step = dev->step;
	intr = dev->intr;

	intr |= ((step&7)<<8);

	if(p == 0 || (intr & 0x80)) {	/* SCSI bus reset */
		dev->cmd = Nop;
		goto Done;
	}

	switch(p->status>>8){
	case 0x00:		/* Select was issued */
		switch(intr){
		default:
			scsimoan("bad case", status, intr, csr);
			print("cmd = #%2.2ux\n", dev->cmd);
			resetscsi();
			scsibusreset();
			goto Done;
		case 0x020:	/* arbitration complete, selection timed out */
			goto Done;
		case 0x218:	/* selection complete, no command phase */
			p->status = 0x1000;
			scsimoan("no cmd phase", status, intr, csr);
			resetscsi();
			scsibusreset();
			goto Done;
		case 0x318:	/* command phase ended prematurely */
			n = (p->cmd.lim - p->cmd.base) - (dev->fflags & 0x1f);
			p->status = (0x30+n)<<8;
			scsimoan("short cmd phase", status, intr, csr);
			resetscsi();
			scsibusreset();
			goto Done;
		case 0x418:	/* select sequence complete */
			p->status = 0x4100;
			if((status & 0x07) == p->rflag){
				dma->csr = p->rflag ? En_dma|Write|Int_en : En_dma|Int_en;
				dev->cmd = Dma|Transfer;
				return;
			}else if((status & 0x07) != 3){
				scsimoan("weird phase after cmd",
					status, intr, csr);
				goto Done;
			}
			/* else fall through */
		}

	case 0x41:	/* data transfer, if any, is finished */
		p->status = 0x4600;
		p->data.ptr = p->data.lim - ((dev->counthi<<8)|dev->countlo);
		if((status & 0x07) != 3){
			scsimoan("weird phase after xfr",
				status, intr, csr);
			goto Done;
		}

		if(p->rflag)
			while(dma->csr & Pack_cnt)
				;

		dev->cmd = Cmdcomplete;
		return;

	case 0x46:	/* Cmdcomplete was issued */
		p->status = 0x6000|dev->fifo;
		m = dev->fifo;
		dev->cmd = Msgaccept;
		return;

	case 0x60:	/* Msgaccept was issued */
		goto Done;
	}
Done:
	curcmd = 0;
	wakeup(&scsirendez);
}

#ifdef notdef
void
scsidump(void)
{
	SCSIdev *dev = ioaddr.scsi;
	DMAdev *dma = ioaddr.dma;

	print("\nscsi:\n");
	print("	countlo=0x%2.2ux\n", dev->countlo);
	print("	counthi=0x%2.2ux\n", dev->counthi);
	print("	cmd    =0x%2.2ux\n", dev->cmd);
	print("	status =0x%2.2ux\n", dev->status);
	print("	intr   =0x%2.2ux\n", dev->intr);
	print("	step   =0x%2.2ux\n", dev->step);
	print("	fflags =0x%2.2ux\n", dev->countlo);
	print("	config =0x%2.2ux\n", dev->config);
	print("dma:\n");
	print("	csr    =0x%8.8ux\n", dma->csr);
	print("	addr   =0x%8.8ux\n", dma->addr);
	print("	count  =0x%4.4ux\n", dma->count);
	print("	diag   =0x%8.8ux\n", dma->diag);
}
#endif

M ss/trap.c => ss/trap.c +6 -3
@@ 109,8 109,8 @@ trap(Ureg *ur)
	user = !(ur->psr&PSRPSUPER);
	tbr = (ur->tbr&0xFFF)>>4;
	/* SS2 bug: flush cache line holding trap entry in table */
	if(conf.ss2)
		putsysspace(CACHETAGS+((TRAPS+16*tbr)&(VACSIZE-1)), 0);
	if(conf.ss2cachebug)
		putsysspace(CACHETAGS+((TRAPS+16*tbr)&(conf.vacsize-1)), 0);
	if(tbr > 16){			/* interrupt */
		if(u && u->p->state==Running){
			/* if active, FPop at head of Q is probably an excep */


@@ 133,6 133,9 @@ trap(Ureg *ur)
		case 5:				/* lance */
			lanceintr();
			break;
		case 3:				/* lance */
			scsiintr();
			break;
		default:
			goto Error;
		}


@@ 521,7 524,7 @@ syscall(Ureg *aur)

	/* SS2 bug: flush cache line holding trap entry in table */
	if(conf.ss2)
		putsysspace(CACHETAGS+((TRAPS+16*128)&(VACSIZE-1)), 0);
		putsysspace(CACHETAGS+((TRAPS+16*128)&(conf.vacsize-1)), 0);

	if(u->p->fpstate == FPactive) {
		fpquiet();