~kris/9p

9hist

83744fafb874d5bbc56e7894036cd724ac706efb — David du Colombier 33 years ago 234f179
Plan 9 from Bell Labs 1993-09-07
M carrera/io.h => carrera/io.h +11 -7
@@ 4,7 4,7 @@
enum
{
	Devicephys	= 0x80000000,
	Eisaphys	= 0x90000000,
	Eisaphys	= 0x90000000,	/* IO port physical */
	Devicevirt	= 0xE0000000,
	Dmabase		= 0xE0000000,	
	Sonicbase	= 0xE0001000,    	


@@ 19,17 19,21 @@ enum
	NvramRW		= 0xE000A000,
	NvramRO		= 0xE000B000,
	 Enetoffset	= 0,
	KeyboardIO	= 0xE0005000,	
	KeyboardIO	= 0xE0005000,
	 Keyctl		= 6,
	 Keydat		= 7,	
	MouseIO		= 0xE0005000,  	
	SoundIO		= 0xE000C000,
	EisaLatch	= 0xE000E000,
	Diag		= 0xE000F000,
	EisaControl	= 0xE0010000,	/* Second 64K Page from Devicevirt */
	VideoCTL	= 0x60000000,	
	VideoMEM	= 0x40000000, 	
	I386ack		= 0xE000023f,
	EisaControl	= 0xE0010000,	/* Second 64K Page from Devicevirt */
	Eisamphys	= 0x91000000,
	Eisamvirt	= 0xE0300000,	/* Second 1M page entry from Intctl */
	Intctlphys	= 0xF0000000,	
	Intctlvirt	= 0xE0040000,
	Intctlvirt	= 0xE0200000,
	  Uart1int	= (1<<9),
	  Uart0int	= (1<<8),
	  Mouseint	= (1<<7),


@@ 40,8 44,8 @@ enum
	  Soundint	= (1<<2),
	  Floppyint	= (1<<1),
	  Parallelint	= (1<<0),
	Intenareg	= 0xE0040004,	/* Device interrupt enable */
	Intcause	= 0xE0040007,	/* Decice interrupt cause register */
	Intenareg	= 0xE0200004,	/* Device interrupt enable */
	Intcause	= 0xE0200007,	/* Decice interrupt cause register */

	Ttbr		= 0x8000001C,	/* Translation table base address */
	Tlrb		= 0x80000024,	/* Translation table limit address */


@@ 61,6 65,6 @@ struct Tte
#define CACHELINE(type, v)	(type*)(((ulong)(v)+127)&~127)
#define UNCACHED(type, v)	(type*)((ulong)(v)|0xA0000000)

#define EISAUNCACHED(v)		(0xA0000000|0x10000000|(v))
#define EISA(v)			(Eisamvirt+(v))
#define EISAOUTB(port, v)	*(uchar*)((EisaControl+(port))^7) = v
#define EISAINB(port)		(*(uchar*)((EisaControl+(port))^7))

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

#include	"devtab.h"

enum
{
	/*
	 *  commands
	 */
	Krdcmd=		0x20,	/* read command byte */
	Kwrcmd=		0x60,	/* write command byte */
	Kselftest=	0xAA,	/* self test */
	Ktest=		0xAB,	/* keyboard test */
	Kdisable=	0xAD,	/* disable keyboard */
	Kenable=	0xAE,	/* enable keyboard */
	Krdin=		0xC0,	/* read input port */
	Krdout=		0xD0,	/* read output port */
	Kwrout=		0xD1,	/* write output port */
	Krdtest=	0xE0,	/* read test inputs */
	Kwrlights=	0xED,	/* set lights */
	Kreset=		0xF0,	/* soft reset */
	/*
	 *  magic characters
	 */
	Msetscan=	0xF0,	/* set scan type (0 == unix) */
	Menable=	0xF4,	/* enable the keyboard */
	Mdisable=	0xF5,	/* disable the keyboard */
	Mdefault=	0xF6,	/* set defaults */
	Mreset=		0xFF,	/* reset the keyboard */
	/*
	 *  responses from keyboard
	 */
	Rok=		0xAA,		/* self test OK */
	Recho=		0xEE,		/* ??? */
	Rack=		0xFA,		/* command acknowledged */
	Rfail=		0xFC,		/* self test failed */
	Rresend=	0xFE,		/* ??? */
	Rovfl=		0xFF,		/* input overflow */
	/*
	 *  command register bits
	 */
	Cintena=	1<<0,	/* enable output interrupt */
	Csystem=	1<<2,	/* set system */
	Cinhibit=	1<<3,	/* inhibit override */
	Cdisable=	1<<4,	/* disable keyboard */
	/*
	 *  output port bits
	 */
	Osoft=		1<<0,	/* soft reset bit (must be 1?) */
	Oparity=	1<<1,	/* force bad parity */
	Omemtype=	1<<2,	/* simm type (1 = 4Mb, 0 = 1Mb)	*/
	Obigendian=	1<<3,	/* big endian */
	Ointena=	1<<4,	/* enable interrupt */
	Oclear=		1<<5,	/* clear expansion slot interrupt */
	/*
	 *  status bits
	 */
	Sobf=		1<<0,	/* output buffer full */
	Sibf=		1<<1,	/* input buffer full */
	Ssys=		1<<2,	/* set by self-test */
	Slast=		1<<3,	/* last access was to data */
	Senabled=	1<<4,	/* keyboard is enabled */
	Stxtimeout=	1<<5,	/* transmit to kybd has timed out */
	Srxtimeout=	1<<6,	/* receive from kybd has timed out */
	Sparity=	1<<7,	/* parity on byte was even */
	/*
	 *  light bits
	 */
	L1=		1<<0,	/* light 1, network activity */
	L2=		1<<2,	/* light 2, caps lock */
	L3=		1<<1,	/* light 3, no label */
};

#define KBDCTL	(*(uchar*)(KeyboardIO+Keyctl))
#define KBDDAT	(*(uchar*)(KeyboardIO+Keydat))
#define OUTWAIT	while(KBDCTL & Sibf); kdbdly(1)
#define INWAIT	while(!(KBDCTL & Sobf)); kdbdly(1)
#define ACKWAIT INWAIT ; if(KBDDAT != Rack) print("bad response\n"); kdbdly(1)

enum
{
	Spec=	0x80,

	PF=	Spec|0x20,	/* num pad function key */
	View=	Spec|0x00,	/* view (shift window up) */
	F=	Spec|0x40,	/* function key */
	Shift=	Spec|0x60,
	Break=	Spec|0x61,
	Ctrl=	Spec|0x62,
	Latin=	Spec|0x63,
	Up=	Spec|0x70,	/* key has come up */
	No=	Spec|0x7F,	/* no mapping */

	Tmask=	Spec|0x60,
};

uchar keymap[] = {
[0]	No,	No,	No,	No,	No,	No,	No,	F|1,
	'\033',	No,	No,	No,	No,	'\t',	'`',	F|2,
[0x10]	No,	Ctrl,	Shift,	Shift,	Shift,	'q',	'1',	F|3,
	No,	Shift,	'z',	's',	'a',	'w',	'2',	F|4,
[0x20]	No,	'c',	'x',	'd',	'e',	'4',	'3',	F|5,
	No,	' ',	'v',	'f',	't',	'r',	'5',	F|6,
[0x30]	No,	'n',	'b',	'h',	'g',	'y',	'6',	F|7,
	No,	View,	'm',	'j',	'u',	'7',	'8',	F|8,
[0x40]	No,	',',	'k',	'i',	'o',	'0',	'9',	F|9,
	No,	'.',	'/',	'l',	';',	'p',	'-',	F|10,
[0x50]	No,	No,	'\'',	No,	'[',	'=',	F|11,	'\r',
	Latin,	Shift,	'\n',	']',	'\\',	No,	F|12,	Break,
[0x60]	View,	View,	Break,	Shift,	'\177',	No,	'\b',	No,
	No,	'1',	View,	'4',	'7',	',',	No,	No,
[0x70]	'0',	'.',	'2',	'5',	'6',	'8',	PF|1,	PF|2,
	No,	'\n',	'3',	No,	PF|4,	'9',	PF|3,	No,
[0x80]	No,	No,	No,	No,	'-',	No,	No,	No,
};

uchar skeymap[] = {
[0]	No,	No,	No,	No,	No,	No,	No,	F|1,
	'\033',	No,	No,	No,	No,	'\t',	'~',	F|2,
[0x10]	No,	Ctrl,	Shift,	Shift,	Shift,	'Q',	'!',	F|3,
	No,	Shift,	'Z',	'S',	'A',	'W',	'@',	F|4,
[0x20]	No,	'C',	'X',	'D',	'E',	'$',	'#',	F|5,
	No,	' ',	'V',	'F',	'T',	'R',	'%',	F|6,
[0x30]	No,	'N',	'B',	'H',	'G',	'Y',	'^',	F|7,
	No,	View,	'M',	'J',	'U',	'&',	'*',	F|8,
[0x40]	No,	'<',	'K',	'I',	'O',	')',	'(',	F|9,
	No,	'>',	'?',	'L',	':',	'P',	'_',	F|10,
[0x50]	No,	No,	'"',	No,	'{',	'+',	F|11,	'\r',
	Latin,	Shift,	'\n',	'}',	'|',	No,	F|12,	Break,
[0x60]	View,	View,	Break,	Shift,	'\177',	No,	'\b',	No,
	No,	'1',	View,	'4',	'7',	',',	No,	No,
[0x70]	'0',	'.',	'2',	'5',	'6',	'8',	PF|1,	PF|2,
	No,	'\n',	'3',	No,	PF|4,	'9',	PF|3,	No,
[0x80]	No,	No,	No,	No,	'-',	No,	No,	No,
};


struct Kbd
{
	Lock;
	int l;
} kbd;

void
kdbdly(int l)
{
	int i;

	l *= 21;
	for(i=0; i<l; i++)
		;
}

/*
 *  wait for a keyboard event (or some max time)
 */
int
kbdwait(void)
{
	int tries;

	for(tries = 0; tries < 2000; tries++){
		if(KBDCTL & Sobf){
			kdbdly(1);
			return 1;
		}
		kdbdly(1);
	}
	return 0;
}

/*
 *  wait for a keyboard acknowledge (or some max time)
 */
int
kbdackwait(void)
{
	if(kbdintr())
		return KBDDAT;
	return 0;
}

int
kbdintr(void)
{
	int c, i, nk;
	uchar ch, code;
	static uchar kc[5];
	static int shifted, ctrled, lstate;

	kbdwait();
	code = KBDDAT;

	/*
	 *  key has gone up
	 */
	if(code == Up) {
		kbdwait();
		ch = keymap[KBDDAT];
		if(ch == Ctrl)
			ctrled = 0;
		else if(ch == Shift)
			shifted = 0;
		return 0;
	}

	if(code > 0x87)
		return 1;

	/*
	 *  convert
	 */
	if(shifted)
		ch = skeymap[code];
	else
		ch = keymap[code];
iprint("code %d %d\n", code, ch);
	/*
 	 *  normal character
	 */
	if(!(ch & Spec)){
		if(ctrled)
			ch &= 0x1f;
		switch(lstate){
		case 1:
			kc[0] = ch;
			lstate = 2;
			if(ch == 'X')
				lstate = 3;
			break;
		case 2:
			kc[1] = ch;
			c = latin1(kc);
			nk = 2;
		putit:
			lstate = 0;
			if(c != -1)
				kbdputc(kbdq, c);
			else {
				for(i=0; i<nk; i++)
					kbdputc(kbdq, kc[i]);
			}
			break;
		case 3:
		case 4:
		case 5:
			kc[lstate-2] = ch;
			lstate++;
			break;
		case 6:
			kc[4] = ch;
			c = unicode(kc);
			nk = 5;
			goto putit;
		default:
			kbdputc(kbdq, ch);
			break;
		}
		return 0;
	}

	/*
	 *  filter out function keys
	 */
	if((Tmask&ch) == (Spec|F))
		return 0;

	/*
	 *  special character
	 */
	switch(ch){
	case Shift:
		shifted = 1;
		break;
	case Break:
		break;
	case Ctrl:
		ctrled = 1;
		break;
	case Latin:
		lstate = 1;
		break;
	default:
		kbdputc(kbdq, ch);
	}
	return 0;
}

void
lights(int l)
{
	int s;
	int tries;

	s = splhi();
	for(tries = 0; tries < 2000 && (KBDCTL & Sibf); tries++)
		;
	kdbdly(1);
	KBDDAT = Kwrlights;
	kbdackwait();
	for(tries = 0; tries < 2000 && (KBDCTL & Sibf); tries++)
		;
	kdbdly(1);
	KBDDAT = kbd.l = l;
	kbdackwait();
	splx(s);
}

static void
empty(void)
{
	int i;

	/*
	 *  empty the buffer
	 */
	kdbdly(20);
	while(KBDCTL & Sobf){
		i = KBDDAT;
		USED(i);
		kdbdly(1);
	}
}

int
kbdinit(void)
{
	int i;

	/*
	 *  empty the buffer
	 */
	while(KBDCTL & Sobf){
		i = KBDDAT;
		USED(i);
	}


	/*
	 *  disable the interface
	 */
	OUTWAIT;
	KBDCTL = Kwrcmd;
	OUTWAIT;
	KBDDAT = Csystem | Cinhibit | Cdisable | Cintena;

	/*
	 *  set unix scan on the keyboard
	 */
	OUTWAIT;
	KBDDAT = Mdisable;
	INWAIT;
	if(KBDDAT != Rack)
		return 0;
	OUTWAIT;
	KBDDAT = Msetscan;
	ACKWAIT;
	OUTWAIT;
	KBDDAT = 0;
	ACKWAIT;
	OUTWAIT;
	KBDDAT = Menable;

	/*
	 *  enable the interface
	 */
	OUTWAIT;
	KBDCTL = Kwrcmd;
	OUTWAIT;
	KBDDAT = Csystem | Cinhibit | Cintena;
	OUTWAIT;
	KBDCTL = Kenable;
	empty();

	return 1;
}

M carrera/l.s => carrera/l.s +24 -8
@@ 738,12 738,13 @@ tas1:
 *  we avoid using R4, R5, R6, and R7 so gotopc can call us without saving them
 */
TEXT	icflush(SB), $-4			/* icflush(virtaddr, count) */

	MOVW	M(STATUS), R10
	WAIT
	MOVW	4(FP), R9
	MOVW	$0, M(STATUS)
	WAIT
	WAIT
	WAIT
	ADDU	R1, R9			/* R9 = last address */
	MOVW	$(~0x3f), R8
	AND	R1, R8			/* R8 = first address, rounded down */


@@ 764,22 765,37 @@ icflush1:			/* primary cache line size is 16 bytes */
	BGTZ	R9, icflush1
	MOVW	R10, M(STATUS)
	WAIT
	WAIT
	WAIT
	RET

TEXT	dcinvalidate(SB), $-4	/* dcinvalidate(virtaddr, count) */
TEXT	icdirty(SB), $-4			/* icdirty(virtaddr, count) */

	MOVW	M(STATUS), R10
	WAIT
	MOVW	$0, M(STATUS)
	WAIT
	WAIT
	MOVW	4(FP), R9
dcinval:			/* secondary cache line size is 128 bytes */
	CACHE	SD+HWBI, 0x00(R1)
	SUBU	$128, R9
	ADDU	$128, R1
	BGTZ	R9, dcinval
	MOVW	$0, M(STATUS)
	WAIT
	ADDU	R1, R9			/* R9 = last address */
	MOVW	$(~0x3f), R8
	AND	R1, R8			/* R8 = first address, rounded down */
	ADD	$0x3f, R9
	AND	$(~0x3f), R9		/* round last address up */
	SUB	R8, R9			/* R9 = revised count */
icdirty1:			/* primary cache line size is 16 bytes */
	CACHE	PI+HI, 0x00(R8)
	CACHE	PI+HI, 0x10(R8)
	CACHE	PI+HI, 0x20(R8)
	CACHE	PI+HI, 0x30(R8)
	SUB	$0x40, R9
	ADD	$0x40, R8
	BGTZ	R9, icdirty1
	MOVW	R10, M(STATUS)
	WAIT
	WAIT
	WAIT
	RET

TEXT	cleancache(SB), $-4

M carrera/main.c => carrera/main.c +9 -12
@@ 47,6 47,7 @@ main(void)
	serialinit();
	vecinit();
	iprint("\n\nBrazil\n");
/*screeninit();*/
	pageinit();
	procinit0();
	initseg();


@@ 54,7 55,6 @@ main(void)
	rootfiles();
	swapinit();
	userinit();
screeninit();
	schedinit();
}



@@ 155,6 155,8 @@ serialinit(void)
{
	NS16552setup(Uart1, UartFREQ);
	NS16552special(0, 9600, &kbdq, &printq, kbdcr2nl);

	kbdinit();
}

/*


@@ 163,7 165,7 @@ serialinit(void)
void
ioinit(void)
{
	ulong devphys, isaphys, intphys;
	ulong devphys, isaphys, intphys, isamphys;

	/*
	 * Map devices and the Eisa control space


@@ 174,10 176,12 @@ ioinit(void)
	puttlbx(1, Devicevirt, devphys, isaphys, PGSZ64K);

	/*
	 * Map Interrupt control
	 * Map Interrupt control & Eisa memory
	 */
	intphys = PPN(Intctlphys)|PTEGLOBL|PTEVALID|PTEWRITE|PTEUNCACHED;
	puttlbx(2, Intctlvirt, intphys, PTEGLOBL, PGSZ4K);
	isamphys = PPN(Eisamphys)|PTEGLOBL|PTEVALID|PTEWRITE|PTEUNCACHED;

	puttlbx(2, Intctlvirt, intphys, isamphys, PGSZ1M);

	/* Enable all devce interrupt */
	IO(ushort, Intenareg) = 0xffff;


@@ 268,8 272,6 @@ init0(void)
	touser((uchar*)(USTKTOP-sizeof(argbuf)));
}

FPsave	initfp;

void
userinit(void)
{


@@ 370,7 372,7 @@ confinit(void)
	conf.arp = 32;
	conf.frag = 32;

	conf.monitor = 1;
	conf.monitor = 0;

	conf.copymode = 0;		/* copy on write */
}


@@ 379,11 381,6 @@ confinit(void)
/*
 *  for the sake of devcons
 */
void
lights(int v)
{
	USED(v);
}

void
buzz(int f, int d)

M carrera/mem.h => carrera/mem.h +1 -0
@@ 104,6 104,7 @@
#define PGSZ4K		(0x00<<13)
#define PGSZ64K		(0x0F<<13)
#define PGSZ256K	(0x3F<<13)
#define PGSZ1M		(0xFF<<13)
	
#define	KUSEG	0x00000000
#define KSEG0	0x80000000

M carrera/screen.c => carrera/screen.c +72 -18
@@ 43,6 43,20 @@ struct VGAmode
	uchar	graphics[9];
	uchar	attribute[0x15];
	uchar	special[12];
	struct {
		uchar viden;
		uchar sr6;
		uchar sr7;
		uchar ar16;
		uchar ar17;
		uchar crt31;
		uchar crt32;
		uchar crt33;
		uchar crt34;
		uchar crt35;
		uchar crt36;
		uchar crt37;
	} tseng;
};

void	setmode(VGAmode*);


@@ 86,7 100,7 @@ Lock	screenlock;

GBitmap	gscreen =
{
	EISAUNCACHED(0xA0000),
	EISA(0xA0000),
	0,
	(1024*(1<<3))/32,
	3,


@@ 95,16 109,6 @@ GBitmap	gscreen =
	0
};

static GBitmap hwcursor=
{
	0,		/* base filled in by malloc when needed */
	0,
	4,
	1,
	{0, 0, 64, 64},
	{0, 0, 64, 64}
};

uchar bdata[] =
{
	0xC0,


@@ 121,9 125,6 @@ GBitmap bgrnd =
	0
};

/*
 *  a fatter than usual cursor for the safari
 */
Cursor fatarrow = {
	{ -1, -1 },
	{


@@ 182,13 183,31 @@ screenwin(void)
void
screeninit(void)
{
	int i, j;
	uchar *scr;

	setmode(&dfltmode);

	memmove(&arrow, &fatarrow, sizeof(fatarrow));

	scr = (uchar*)EISA(0xA0000);
iprint("%lux\n", scr);
*scr = 0xaa;
i = *scr;
iprint("%2.2ux\n", i);
*scr = 0x55;
i = *scr;
iprint("%2.2ux\n", i);

	for(j = 0; j < 768; j++)
		for(i = 0; i < 1024; i++)
			*(scr+i+(j*1024)) = i;

	/* save space; let bitblt do the conversion work */
	defont = &defont0;	
	defont = &defont0;
iprint("gbitblt\n");	
	gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, 0);
iprint("done\n");
	out.pos.x = MINX;
	out.pos.y = 0;
	out.bwid = defont0.info[' '].width;


@@ 363,6 382,12 @@ srout(int reg, int val)
	EISAOUTB(SR, val);
}

uchar
srin(ushort i) {
        EISAOUTB(SRX, i);
        return EISAINB(SR);
}

void
grout(int reg, int val)
{


@@ 375,7 400,8 @@ genout(int reg, int val)
{
	if(reg == 0)
		EISAOUTB(EMISCW, val);
	else if (reg == 1)
	else
	if (reg == 1)
		EISAOUTB(EFCW, val);
}



@@ 393,7 419,8 @@ arout(int reg, int val)
		junk = EISAINB(0x3DA);
		USED(junk);
		EISAOUTB(ARW, reg | 0x20);
	} else {
	}
	else {
		EISAOUTB(ARW, reg | 0x20);
		EISAOUTB(ARW, val);
	}


@@ 414,6 441,12 @@ setmode(VGAmode *v)
	/* turn screen off (to avoid damage) */
	srout(1, 0x21);

	EISAOUTB(0x3bf, 0x03);		/* hercules compatibility reg */
	EISAOUTB(0x3d8, 0xa0);		/* display mode control register */
	EISAOUTB(0x3cd, 0x00);		/* segment select */

	srout(0x00, srin(0x00) & 0xFD);	/* synchronous reset*/

	for(i = 0; i < sizeof(v->general); i++)
		genout(i, v->general[i]);



@@ 423,7 456,8 @@ setmode(VGAmode *v)
		else
			srout(i, v->sequencer[i]);

	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */
	/* allow writes to CRT registers 0-7 */
	crout(Cvre, 0);
	for(i = 0; i < sizeof(v->crt); i++)
		crout(i, v->crt[i]);



@@ 433,6 467,26 @@ setmode(VGAmode *v)
	for(i = 0; i < sizeof(v->attribute); i++)
		arout(i, v->attribute[i]);

	EISAOUTB(0x3C6, 0xFF);	/* pel mask */
	EISAOUTB(0x3C8, 0x00);	/* pel write address */
	EISAOUTB(0x3bf, 0x03);	/* hercules compatibility reg */
	EISAOUTB(0x3d8, 0xa0);	/* display mode control register */

	srout(0x06, v->tseng.sr6);
	srout(0x07, v->tseng.sr7);
	i = EISAINB(0x3da); /* reset flip-flop. inp stat 1*/
	USED(i);
	arout(0x16, v->tseng.ar16);	/* misc */
	arout(0x17, v->tseng.ar17);	/* misc 1*/
	crout(0x31, v->tseng.crt31);	/* extended start. */
	crout(0x32, v->tseng.crt32);	/* extended start. */
	crout(0x33, v->tseng.crt33);	/* extended start. */
	crout(0x34, v->tseng.crt34);	/* stub: 46ee + other bits */
	crout(0x35, v->tseng.crt35);	/* overflow bits */
	crout(0x36, v->tseng.crt36);	/* overflow bits */
	crout(0x37, v->tseng.crt37);	/* overflow bits */
	EISAOUTB(0x3c3, v->tseng.viden);/* video enable */

	/* turn screen on */
	srout(1, v->sequencer[1]);
}

M carrera/trap.c => carrera/trap.c +21 -14
@@ 244,7 244,7 @@ trap(Ureg *ur)
			postnote(up, 1, buf, NDebug);
			break;
		}
		print("kernel%d %s pc=%lux\n", m->machno, excname[ecode], ur->pc);
		print("kernel %s pc=%lux\n", excname[ecode], ur->pc);
		dumpregs(ur);
		dumpstack();
		if(m->machno == 0)


@@ 285,20 285,27 @@ intr(Ureg *ur)
	cause &= INTR7|INTR6|INTR5|INTR4|INTR3|INTR2|INTR1|INTR0;

	if(cause & INTR3) {
		devint = IO(uchar, Intcause);
		switch(devint) {
		default:
			panic("unknown devint=#%lux", devint);
		for(;;) {
			devint = IO(uchar, Intcause);
			if(devint == 0)
				break;
			switch(devint) {
			default:
				panic("unknown devint=#%lux", devint);

		case 0x28:		/* Serial 1 */
			NS16552intr(0);
			break;
		case 0x24:		/* Serial 2 */
			NS16552intr(1);
			break;
		case 0x14:
			etherintr();
			break;
			case 0x28:		/* Serial 1 */
				NS16552intr(0);
				break;
			case 0x24:		/* Serial 2 */
				NS16552intr(1);
				break;
			case 0x14:
				etherintr();
				break;
			case 0x1C:
				kbdintr();
				break;
			}
		}
		cause &= ~INTR3;
	}

M port/devbit.c => port/devbit.c +0 -18
@@ 374,8 374,6 @@ bitattach(char *spec)
Chan*
bitclone(Chan *c, Chan *nc)
{
	if(!conf.monitor)
		error(Egreg);
	nc = devclone(c, nc);
	if(c->qid.path != CHDIR)
		incref(&bit);


@@ 385,16 383,12 @@ 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);
}



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

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


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


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


@@ 487,8 475,6 @@ 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)


@@ 535,8 521,6 @@ 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);



@@ 842,8 826,6 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	GCacheinfo *gc;
	char buf[64];

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

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

M port/devmnt.c => port/devmnt.c +6 -2
@@ 516,7 516,8 @@ mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)

	m = mntchk(c);
	uba = buf;
	for(cnt = 0; n; n -= nr) {
	cnt = 0;
	for(;;) {
		r = mntralloc(c);
		if(waserror()) {
			mntfree(r);


@@ 529,6 530,8 @@ mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
		r->request.count = limit(n, m->blocksize);
		mountrpc(m, r);
		nr = r->reply.count;
		if(nr > r->request.count)
			nr = r->request.count;
		if(type == Tread)
			memmove(uba, r->reply.data, nr);
		poperror();


@@ 536,7 539,8 @@ mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
		offset += nr;
		uba += nr;
		cnt += nr;
		if(nr != r->request.count)
		n -= nr;
		if(nr != r->request.count || n == 0)
			break;
	}
	return cnt;

M port/fault.c => port/fault.c +5 -0
@@ 80,6 80,11 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
		if(pagedout(*pg))
			pio(s, addr, soff, pg);

		lkp = *pg;
		lock(lkp);
		if(lkp->image)     
			duppage(lkp);	
		unlock(lkp);
		goto done;

	case SG_BSS: