~kris/9p

9hist

23038bbb7f87b4fa696f4f86f3f8a05a40ccb53e — David du Colombier 35 years ago a942d7a
Plan 9 from Bell Labs 1991-07-31
M gnot/trap.c => gnot/trap.c +2 -47
@@ 233,52 233,7 @@ noted(Ureg *ur, ulong arg0)
	}
}

#undef	CHDIR	/* BUG */
#include "/sys/src/libc/9syscall/sys.h"

typedef long Syscall(ulong*);
Syscall	sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, sysdeath, syswait;
Syscall	sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat;
Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate;
Syscall	sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysalarm;
Syscall syssegattach, syssegdetach, syssegfree, syssegflush, syssegbrk;

Syscall *systab[]={
	sysr1,
	syserrstr,
	sysbind,
	syschdir,
	sysclose,
	sysdup,
	sysalarm,
	sysexec,
	sysexits,
	sysfork,
	sysforkpgrp,
	sysfstat,
	syssegbrk,
	sysmount,
	sysopen,
	sysread,
	sysseek,
	syssleep,
	sysstat,
	syswait,
	syswrite,
	syspipe,
	syscreate,
	sysdeath,
	sysbrk_,
	sysremove,
	syswstat,
	sysfwstat,
	sysnotify,
	sysnoted,
	syssegattach,
	syssegdetach,
	syssegfree,
	syssegflush,
};
#include "../port/systab.h"

long
syscall(Ureg *aur)


@@ 314,7 269,7 @@ syscall(Ureg *aur)
	u->nerrlab = 0;
	ret = -1;
	if(!waserror()){
		if(r0 >= sizeof systab/BY2WD){
		if(r0 >= sizeof systab/sizeof systab[0]){
			pprint("bad sys call number %d pc %lux\n", r0, ((Ureg*)UREGADDR)->pc);
			msg = "sys: bad sys call";
	    Bad:

M pc/devfloppy.c => pc/devfloppy.c +246 -126
@@ 29,7 29,7 @@ enum
	 Fwrite=	 0x47,	/* write cmd */
	 Fmulti=	 0x80,	/* or'd with Fread or Fwrite for multi-head */

	Nfloppy=	4,	/* floppies/controller */
	Ndrive=	4,	/* floppies/controller */

	DMAchan=	2,	/* floppy dma channel */



@@ 46,8 46,8 @@ enum

	/* file types */
	Qdir=		0,
	Qdata=		16,
	Qstruct=	32,
	Qdata=		1,
	Qstruct=	2,
};

/*


@@ 62,23 62,41 @@ struct Type
	int	steps;		/* steps per cylinder */
	int	tracks;		/* tracks/disk */
	int	gpl;		/* intersector gap length for read/write */	
	int	fgpl;		/* intersector gap length for format */	
	int	fgpl;		/* intersector gap length for format */

	/*
	 *  these depend on previous entries and are set filled in
	 *  by floppyinit
	 */
	int	bcode;		/* coded version of bytes for the controller */
	long	cap;		/* drive capacity in bytes */
};
Type floppytype[] =
{
 { "MF2HD",	S512,	18,	2,	1,	80,	0x1B,	0x54,	512*2*18*80 },
 { "MF2DD",	S512,	9,	2,	1,	80,	0x1B,	0x54,	512*2*9*80 },
 { "F2HD",	S512,	15,	2,	1,	80,	0x2A,	0x50,	512*15*2*80 },
 { "F2DD",	S512,	8,	2,	1,	40,	0x2A,	0x50,	512*8*2*40 },
 { "F1DD",	S512,	8,	1,	1,	40,	0x2A,	0x50,	512*8*1*40 },
	{ "MF2HD",	512,	18,	2,	1,	80,	0x1B,	0x54, },
	{ "MF2DD",	512,	9,	2,	1,	80,	0x1B,	0x54, },
	{ "F2HD",	512,	15,	2,	1,	80,	0x2A,	0x50, },
	{ "F2DD",	512,	8,	2,	2,	40,	0x2A,	0x50, },
	{ "F1DD",	512,	8,	1,	2,	40,	0x2A,	0x50, },
};
#define NTYPES (sizeof(floppytype)/sizeof(Type))

/*
 *  bytes/sector encoding for the controller, index is (bytes per sector/128)
 */
static int b2c[] =
{
[1]	0,
[2]	1,
[4]	2,
[8]	3,
};
static int secbytes[] =
static int c2b[] =
{
	128,
	256,
	512,
	1024
	1024,
};

/*


@@ 86,7 104,8 @@ static int secbytes[] =
 */
struct Drive
{
	QLock;
	QLock;			/* exclusive access to the drive */

	Type	*t;
	int	dev;



@@ 99,10 118,10 @@ struct Drive
	int	tcyl;		/* target cylinder */
	int	thead;		/* target head */
	int	tsec;		/* target sector */
	long	len;
	long	len;		/* size of xfer */

	int	busy;		/* true if drive is seeking */
	Rendez	r;		/* waiting for operation termination */
	Rendez	r;		/* waiting here for motor to spin up */
};

/*


@@ 110,30 129,133 @@ struct Drive
 */
struct Controller
{
	QLock;
	Drive	d[Nfloppy];	/* the floppy drives */
	QLock;			/* exclusive access to the contoller */

	Drive	d[Ndrive];	/* the floppy drives */
	int	busy;		/* true if a read or write in progress */
	uchar	stat[8];	/* status of an operation */
	int	confused;
	int	intr;		/* true if interrupt occured */
	Rendez	r;		/* wait here for command termination */
};

Controller	floppy;

/*
 *  predeclared
 */
static void	motoron(Drive*);
static void	motoroff(Drive*);
static void	floppykproc(void*);
static int	floppysend(int);
static int	floppyrcv(void);
static int	floppyresult(int);
static void	floppypos(Drive*);
static int	floppysense(Drive*);
static int	interrupted(void*);
static int	floppyrecal(Drive*);
static void	floppyrevive(void);
static long	floppyseek(Drive*);
static long	floppyxfer(Drive*, int, void*, long);
static void	floppyintr(Ureg*);

static int
floppygen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
{
	long l;
	Drive *dp;

	if(s >= ntab)
		return -1;
	if(c->dev >= Ndrive)
		return -1;

	tab += s;
	dp = &floppy.d[c->dev];
	if((tab->qid.path&~Mask) == Qdata)
		l = dp->t->cap;
	else
		l = 8;
	devdir(c, tab->qid, tab->name, l, tab->perm, dp);
	return 1;
}

void
floppyreset(void)
{
	Drive *dp;

	for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
		dp->dev = dp - floppy.d;
		dp->t = &floppytype[0];		/* default type */
		dp->motoron = 1;
		dp->cyl = -1;
		motoroff(dp);
	}
	setvec(Floppyvec, floppyintr);
}

void
floppyinit(void)
{
	Type *t;

	/*
	 *  init dependent parameters
	 */
	for(t = floppytype; t < &floppytype[NTYPES], t++){
		t->cap = t->bytes * t->heads * t->sectors * t->tracks;
		t->bcode = bcode[t->bytes/128];
	}

	/*
	 *  watchdog to turn off the motors
	 */
	kproc(floppykproc, 0);
}
long
floppyread(Chan *c, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;

	dp = &floppy.d[c->dev];
	for(rv = 0; rv < n; rv += i){
		i = floppyxfer(dp, Fread, aa+rv, n-rv);
		if(i <= 0)
			break;
	}
	return rv;
}

long
floppywrite(Chan *c, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;

	dp = &floppy.d[c->dev];
	for(rv = 0; rv < n; rv += i){
		i = floppyxfer(dp, Fwrite, aa+rv, n-rv);
		if(i <= 0)
			break;
	}
	return rv;
}

/*
 *  start a floppy drive's motor.  set an alarm for 1 second later to
 *  mark it as started (we get no interrupt to tell us).
 *
 *  assume the caller qlocked the drive.
 */
void
floppystart(Drive *dp)
static void
motoron(Drive *dp)
{
	int cmd;

	dp->lasttouched = m->ticks;	
	if(dp->motoron)
		return;

	cmd = (1<<(dp->dev+4)) | Fintena | Fena | dp->dev;
	outb(Fmotor, cmd);
	dp->busy = 1;


@@ 146,8 268,8 @@ floppystart(Drive *dp)
/*
 *  stop the floppy if it hasn't been used in 5 seconds
 */
void
floppystop(Drive *dp)
static void
motoroff(Drive *dp)
{
	int cmd;



@@ 155,22 277,25 @@ floppystop(Drive *dp)
	outb(Fmotor, cmd);
	dp->motoron = 0;	
}
void
floppykproc(Alarm* a)
static void
floppykproc(void *a)
{
	Drive *dp;

	for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
	for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
		if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5
		&& canqlock(dp)){
			if(TK2SEC(m->ticks - dp->lasttouched) > 5)
				floppystop(dp);
				motoroff(dp);
			qunlock(dp);
		}
	}
}

int
/*
 *  send a byte to the floppy
 */
static int
floppysend(int data)
{
	int tries;


@@ 193,7 318,10 @@ floppysend(int data)
	return -1;
}

int
/*
 *  get a byte from the floppy
 */
static int
floppyrcv(void)
{
	int tries;


@@ 215,8 343,11 @@ floppyrcv(void)
	return -1;
}

int
floppyrdstat(int n)
/*
 *  read a command result message from the floppy
 */
static int
floppyresult(int n)
{
	int i;
	int c;


@@ 230,14 361,19 @@ floppyrdstat(int n)
	return 0;
}

void
floppypos(Drive *dp, long off)
/*
 *  calculate physical address of a logical byte offset into the disk
 *
 *  truncate dp->length if it crosses a cylinder boundary
 */
static void
floppypos(Drive *dp)
{
	int lsec;
	int end;
	int cyl;

	lsec = off/secbytes[dp->t->bytes];
	lsec = dp->off/dp->t->bytes;
	dp->tcyl = lsec/(dp->t->sectors*dp->t->heads);
	dp->tsec = (lsec % dp->t->sectors) + 1;
	dp->thead = (lsec/dp->t->sectors) % dp->t->heads;


@@ 246,16 382,20 @@ floppypos(Drive *dp, long off)
	 *  can't read across cylinder boundaries.
	 *  if so, decrement the bytes to be read.
	 */
	lsec = (off+dp->len)/secbytes[dp->t->bytes];
	lsec = (dp->off+dp->len)/dp->t->bytes;
	cyl = lsec/(dp->t->sectors*dp->t->heads);
	if(cyl != dp->tcyl){
		dp->len -= (lsec % dp->t->sectors)*secbytes[dp->t->bytes];
		dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*secbytes[dp->t->bytes]
		dp->len -= (lsec % dp->t->sectors)*dp->t->bytes;
		dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*dp->t->bytes
				*dp->t->sectors;
	}
}

int
/*
 *  get the interrupt cause from the floppy.  we need to do this
 *  after seeks and recalibrations since they don't return results.
 */
static int
floppysense(Drive *dp)
{
	/*


@@ 265,7 405,7 @@ floppysense(Drive *dp)
		floppy.confused = 1;
		return -1;
	}
	if(floppyrdstat(2) < 0){
	if(floppyresult(2) < 0){
		floppy.confused = 1;
		dp->confused = 1;
		return -1;


@@ 282,7 422,19 @@ floppysense(Drive *dp)
	return 0;
}

int
/*
 *  return true if interrupt occurred
 */
static int
interrupted(void *a)
{
	return floppy.intr;
}

/*
 *  we've lost the floppy position, go to cylinder 0.
 */
static int
floppyrecal(Drive *dp)
{
	floppy.intr = 0;


@@ 291,7 443,7 @@ floppyrecal(Drive *dp)
		floppy.confused = 0;
		return -1;
	}
	floppywait();
	sleep(&floppy.r, interrupted, 0);

	/*
	 *  get return values


@@ 323,33 475,17 @@ floppyrecal(Drive *dp)
	return 0;
}

/*
 *  if the controller or a specific drive is in a confused state,
 *  reset it and get back to a kown state
 */
void
floppyreset(void)
{
	Drive *dp;

	for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
		dp->dev = dp - floppy.d;
		dp->t = &floppytype[0];		/* default type */
		dp->motoron = 1;
		dp->cyl = -1;
		floppystop(dp);
	}
}

void
floppyinit(void)
{
	kproc(floppykproc, 0);
}

void
floppyreset(void)
floppyrevive(void)
{
	Drive *dp;

	/*
	 *  reset the floppy if'n it's confused
	 *  reset the floppy if it's confused
	 */
	if(floppy.confused){
		/* reset controller and turn all motors off */


@@ 359,18 495,18 @@ floppyreset(void)
		delay(1);
		outb(Fmotor, Fintena|Fena);
		spllo();
		for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
		for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
			dp->motoron = 0;
			dp->confused = 1;
		}
		floppywait();
		sleep(&floppy.r, interrupted, 0);
		floppy.confused = 0;
	}

	/*
	 *  recalibrate any confused drives
	 */
	for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Nfloppy]; dp++){
	for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Ndrive]; dp++){
		if(dp->confused == 0)
			floppyrecal(dp);



@@ 378,19 514,9 @@ floppyreset(void)

}

long
floppyseek(int dev, long off)
static long
floppyseek(Drive *dp)
{
	Drive *dp;

	dp = &floppy.d[dev];

	if(floppy.confused || dp->confused)
		floppyreset();

	floppystart(dp);

	floppypos(dp, off);
	if(dp->cyl == dp->tcyl){
		dp->offset = off;
		return off;


@@ 400,7 526,7 @@ floppyseek(int dev, long off)
	 *  tell floppy to seek
	 */
	if(floppysend(Fseek) < 0
	|| floppysend((dp->thead<<2) | dev) < 0
	|| floppysend((dp->thead<<2) | dp->dev) < 0
	|| floppysend(dp->tcyl * dp->t->steps) < 0){
		print("seek cmd failed\n");
		floppy.confused = 1;


@@ 410,7 536,7 @@ floppyseek(int dev, long off)
	/*
	 *  wait for interrupt
	 */
	floppywait();
	sleep(&floppy.r, interrupted, 0);

	/*
	 *  get floppy status


@@ 441,42 567,47 @@ floppyseek(int dev, long off)
	return dp->offset;
}

long
static long
floppyxfer(Drive *dp, int cmd, void *a, long n)
{
	int dev;
	ulong addr;
	long offset;

	addr = (ulong)a;
	dev = dp - floppy.d;

	qlock(&floppy);
	qlock(dp);
	if(waserror){
		qunlock(&floppy);
		qunlock(dp);
	}

	/*
	 *  dma can't cross 64 k boundaries
	 *  get floppy reset and spinning
	 */
	if((addr & 0xffff0000) != ((addr+n) & 0xffff0000))
		n -= (addr+n)&0xffff;
	if(floppy.confused || dp->confused)
		floppyrevive();
	if(!dp->motoron)
		motoron(dp);

	/*
	 *  calculate new position and seek to it (dp->len may be trimmed)
	 */
	dp->len = n;
	floppyseek(dev, dp->offset);
	floppypos(dp);
	if(floppyseek(dp) < 0)
		errors("seeking floppy");

/*	print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
		dp->tcyl, dp->thead, dp->tsec, addr, n);/**/

	/*
	 *  set up the dma
	 *  set up the dma (dp->len may be trimmed)
	 */
	outb(DMAmode1, cmd==Fread ? 0x46 : 0x4a);
	outb(DMAmode0, cmd==Fread ? 0x46 : 0x4a);
	outb(DMAaddr, addr);
	outb(DMAaddr, addr>>8);
	outb(DMAtop, addr>>16);
	outb(DMAcount, n-1);
	outb(DMAcount, (n-1)>>8);
	outb(DMAinit, 2);
	dp->len = dmasetup(2, a, dp->len, cmd==Fread);

	/*
	 *  tell floppy to go
	 *  start operation
	 */
	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
	if(floppysend(cmd) < 0


@@ 484,64 615,53 @@ floppyxfer(Drive *dp, int cmd, void *a, long n)
	|| floppysend(dp->tcyl * dp->t->steps) < 0
	|| floppysend(dp->thead) < 0
	|| floppysend(dp->tsec) < 0
	|| floppysend(dp->t->bytes) < 0
	|| floppysend(dp->t->bcode) < 0
	|| floppysend(dp->t->sectors) < 0
	|| floppysend(dp->t->gpl) < 0
	|| floppysend(0xFF) < 0){
		print("xfer cmd failed\n");
		floppy.confused = 1;
		return -1;
		errors("floppy command failed");
	}

	floppywait();
	sleep(&floppy.r, interrupted, 0);

	/*
	 *  get status
 	 */
	if(floppyrdstat(7) < 0){
		print("xfer status failed\n");
	if(floppyresult(7) < 0){
print("xfer status failed\n");
		floppy.confused = 1;
		return -1;
		errors("floppy result failed");
	}

	if((floppy.stat[0] & Codemask)!=0 || floppy.stat[1] || floppy.stat[2]){
print("xfer failed %lux %lux %lux\n", floppy.stat[0],
			floppy.stat[1], floppy.stat[2]);
		dp->confused = 1;
		return -1;
		errors("floppy drive lost");
	}

	offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4];
	offset = offset*dp->t->sectors + floppy.stat[5] - 1;
	offset = offset * secbytes[floppy.stat[6]];
	offset = offset * c2b[floppy.stat[6]];
	if(offset != dp->offset+n){
		print("new offset %d instead of %d\n", offset, dp->offset+dp->len);
print("new offset %d instead of %d\n", offset, dp->offset+dp->len);
		dp->confused = 1;
		return -1;/**/
		errors("floppy drive lost");
	}

	qunlock(&floppy);
	qunlock(dp);
	poperror();

	dp->offset += dp->len;
	return dp->len;
}

long
floppyread(int dev, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;

	dp = &floppy.d[dev];
	for(rv = 0; rv < n; rv += i){
		i = floppyxfer(dp, Fread, aa+rv, n-rv);
		if(i <= 0)
			break;
	}
	return rv;
}

void
static void
floppyintr(Ureg *ur)
{
	floppy.intr = 1;
	wakeup(&floppy.r);
}

M pc/fns.h => pc/fns.h +0 -26
@@ 18,32 18,6 @@ void	fprestore(FPsave*);
ulong	getcr2(void);
void	idle(void);
int	inb(int);
void	intr0(void);
void	intr1(void);
void	intr2(void);
void	intr3(void);
void	intr4(void);
void	intr5(void);
void	intr6(void);
void	intr7(void);
void	intr8(void);
void	intr9(void);
void	intr10(void);
void	intr11(void);
void	intr12(void);
void	intr13(void);
void	intr14(void);
void	intr15(void);
void	intr16(void);
void	intr17(void);
void	intr18(void);
void	intr19(void);
void	intr20(void);
void	intr21(void);
void	intr22(void);
void	intr23(void);
void	intr64(void);
void	intrbad(void);
void	kbdinit(void);
void	kbdintr(Ureg*);
void	mmuinit(void);

M pc/headland.c => pc/headland.c +17 -0
@@ 13,6 13,20 @@ enum
	Head=		0x92,		/* control port */
	 Reset=		(1<<0),		/* reset the 386 */
	 A20ena=	(1<<1),		/* enable address line 20 */

	/*
	 *  the byte registers for DMA0 are all one byte apart
	 */
	Dma0=		0x00,
	Dma0status=	Dma0+0x8,	/* status port */
	Dma0reset=	Dma0+0xD,	/* reset port */

	/*
	 *  the byte registers for DMA1 are all two bytes apart (why?)
	 */
	Dma1=		0xC0,
	Dma1status=	Dma1+2*0x8,	/* status port */
	Dma1reset=	Dma1+2*0xD,	/* reset port */
};

/*


@@ 96,6 110,9 @@ exit(void)
 *
 *  we assume BIOS has set up the command register before we
 *  are booted.
 *
 *  return the updated transfer length (we can't transfer across 64k
 *  boundaries)
 */
long
dmasetup(int chan, void *va, long len, int isread)

M pc/io.h => pc/io.h +10 -25
@@ 1,31 1,16 @@
/*
 *  programmable interrupt vectors (for the 8259)
 *  programmable interrupt vectors (for the 8259's)
 */
enum
{
	Faultvec=	14,		/* page fault */
	Int0vec=	16,		/* first interrupt vector used by the 8259 */
	Clockvec=	Int0vec+0,	/* clock interrupts */
	Kbdvec=		Int0vec+1,	/* keyboard interrupts */
	Mousevec=	Int0vec+12,	/* mouse interrupt */
};

/*
 *  8237 dma controllers
 */
enum
{
	/*
	 *  the byte registers for DMA0 are all one byte apart
	 */
	Dma0=		0x00,
	Dma0status=	Dma0+0x8,	/* status port */
	Dma0reset=	Dma0+0xD,	/* reset port */

	/*
	 *  the byte registers for DMA1 are all two bytes apart (why?)
	 */
	Dma1=		0xC0,
	Dma1status=	Dma1+2*0x8,	/* status port */
	Dma1reset=	Dma1+2*0xD,	/* reset port */
	Int0vec=	16,		/* first 8259 */
	 Clockvec=	Int0vec+0,	/*  clock interrupts */
	 Kbdvec=	Int0vec+1,	/*  keyboard interrupts */
	 ComBvec=	Int0vec+3,	/*  inerrupt from uart b */
	 ComAvec=	Int0vec+4,	/*  inerrupt from uart a */
	 Floppyvec=	Int0vec+6,	/*  floppy interrupts */
	Int1vec=	Int0vec+8,	/* second 8259 */
	 Mousevec=	Int1vec+4,	/*  mouse interrupt */
	 Hardvec=	Int1vec+6,	/*  hard disk */
};

M pc/kbd.c => pc/kbd.c +129 -48
@@ 5,6 5,10 @@
#include	"fns.h"
#include	"io.h"

#include	<libg.h>
#include	<gnot.h>
#include	"screen.h"

enum {
	Data=		0x60,	/* data port */



@@ 16,7 20,7 @@ enum {
	 Inhibit=	0x10,	/*  keyboard/mouse inhibited */
	 Minready=	0x20,	/*  mouse character ready */
	 Rtimeout=	0x40,	/*  general timeout */
	 Parity=	0x80,	/*  1 == error */
	 Parity=	0x80,

	Cmd=		0x64,	/* command port (write only) */



@@ 24,7 28,7 @@ enum {

	PF=	Spec|0x20,	/* num pad function key */
	View=	Spec|0x00,	/* view (shift window up) */
	F=	Spec|0x40,	/* function key */
	KF=	Spec|0x40,	/* function key */
	Shift=	Spec|0x60,
	Break=	Spec|0x61,
	Ctrl=	Spec|0x62,


@@ 33,16 37,16 @@ enum {
	Num=	Spec|0x65,
	No=	Spec|0x7F,	/* no mapping */

	Home=	F|13,
	Up=	F|14,
	Pgup=	F|15,
	Print=	F|16,
	Home=	KF|13,
	Up=	KF|14,
	Pgup=	KF|15,
	Print=	KF|16,
	Left=	View,
	Right=	View,
	End=	'\r',
	Down=	View,
	Pgdown=	View,
	Ins=	F|20,
	Ins=	KF|20,
	Del=	0x7F,
};



@@ 55,11 59,11 @@ uchar kbtab[] =
[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	No,
[0x38]	Latin,	' ',	Caps,	F|1,	F|2,	F|3,	F|4,	F|5,
[0x40]	F|6,	F|7,	F|8,	F|9,	F|10,	Num,	F|12,	Home,
[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
[0x50]	No,	No,	No,	No,	No,	No,	No,	F|11,
[0x58]	F|12,	No,	No,	No,	No,	No,	No,	No,
[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
};

uchar kbtabshift[] =


@@ 71,11 75,11 @@ uchar kbtabshift[] =
[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	No,
[0x38]	Latin,	' ',	Caps,	F|1,	F|2,	F|3,	F|4,	F|5,
[0x40]	F|6,	F|7,	F|8,	F|9,	F|10,	Num,	F|12,	Home,
[0x38]	Latin,	' ',	Caps,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	KF|12,	Home,
[0x48]	No,	No,	No,	No,	No,	No,	No,	No,
[0x50]	No,	No,	No,	No,	No,	No,	No,	F|11,
[0x58]	F|12,	No,	No,	No,	No,	No,	No,	No,
[0x50]	No,	No,	No,	No,	No,	No,	No,	KF|11,
[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
};

uchar kbtabesc1[] =


@@ 236,45 240,110 @@ latin1(int k1, int k2)
	return 0;
}

static void
mousecmd(int cmd, int arg)
{
	unsigned int c;

	do {
		while(inb(Status) & Outbusy)
			;
		outb(Cmd, 0xD4);
		while(inb(Status) & Outbusy)
			;
		outb(Data, cmd);
		if(arg >= 0){
			while(inb(Status) & Outbusy)
				;
			outb(Data, arg);
		}
		while(!(inb(Status) & Inready))
			;
		c = inb(Data);
	} while(c == 0xFE);
	if(c != 0xFA)
		print("mouse command returns bad status %lux", c);
}

void
kbdinit(void)
{
	uchar c;
	int c, s;

	initq(&kbdq);
	setvec(Kbdvec, kbdintr);
	initq(&mouseq);
	setvec(Mousevec, kbdintr);

	/* wait for a quiescent controller */
	while((c = inb(Status)) & (Outbusy | Inready))
		if(c & Inready)
			inb(Data);

	/* read controller command byte */
	outb(Cmd, 0x20);
	while(!(inb(Status) & Inready))
		;
	c = inb(Data);
print("input completed\n");
delay(5000);

	/* enable mouse and mouse interupts */
	c = (c&~0x20) | 0x02;
	/* enable kbd/mouse xfers and interrupts */
	outb(Cmd, 0x60);
	while(inb(Status) & Outbusy)
		;
	outb(Data, c);
print("mouse enabled\n");
	outb(Data, 0x47);
	while(inb(Status) & Outbusy)
		;
	outb(Cmd, 0xA8);

	/* make mouse streaming (and enabled) */
	mousecmd(0xEA, -1);
	mousecmd(0xF4, -1);

	/* resolution */
	mousecmd(0xE8, 0x03);
print("res set\n");
delay(5000);
}

	initq(&mouseq);
	setvec(Mousevec, kbdintr);
/*
 *  mouse message is three bytes
 *
 *	byte 0 -	0 0 SDY SDX 1 M R L
 *	byte 1 -	DX
 *	byte 2 -	DY
 */
static void
mymouseputc(int c)
{
	static short msg[3];
	static int nb;
	static uchar b[] = {0, 4, 1, 5, 2, 6, 3, 7};
	static lastdx, lastdy;
	int diff;
	extern Mouseinfo mouse;

	/* 
	 *  check byte 0 for consistency
	 */
	if(nb==0 && (c&0xc8)!=0x08)
		return;

	msg[nb] = c;
	if(++nb == 3){
		nb = 0;
		if(msg[0] & 0x10)
			msg[1] |= 0xFF00;
		if(msg[0] & 0x20)
			msg[2] |= 0xFF00;

		mouse.newbuttons = b[msg[0]&7];
		mouse.dx = msg[1];
		mouse.dy = -msg[2];
print("%d %d\n", mouse.dx, mouse.dy);
		mouse.track = 1;
		mouseclock();
	}
}

/*
 *  keyboard interrupt
 */
void
kbdintr(Ureg *ur)
int
kbdintr0(void)
{
	int s, c, nc;
	static int esc1, esc2;


@@ 286,18 355,23 @@ kbdintr(Ureg *ur)
	int keyup;

	/*
	 *  get status and character
	 *  get status
	 */
	s = inb(Status);
	if(!(s&Inready))
		return -1;

	/*
	 *  get the character
	 */
	c = inb(Data);

	/*
	 *  if it's the mouse...
	 */
	if(s & Minready){
print("mousechar\n");
		mouseputc(&mouseq, c);
		return;
		mymouseputc(c);
		return 0;
	}

	keyup = c&0x80;


@@ 305,7 379,7 @@ print("mousechar\n");
	if(c > sizeof kbtab){
		print("unknown key %ux\n", c|keyup);
		kbdputc(&kbdq, k1);
		return;
		return 0;
	}

	/*


@@ 313,10 387,10 @@ print("mousechar\n");
	 */
	if(c == 0xe0){
		esc1 = 1;
		return;
		return 0;
	} else if(c == 0xe1){
		esc2 = 2;
		return;
		return 0;
	}

	if(esc1){


@@ 324,7 398,7 @@ print("mousechar\n");
		esc1 = 0;
	} else if(esc2){
		esc2--;
		return;
		return 0;
	} else if(shift)
		c = kbtabshift[c];
	else


@@ 345,7 419,7 @@ print("mousechar\n");
			ctl = 0;
			break;
		}
		return;
		return 0;
	}

	/*


@@ 358,7 432,7 @@ print("mousechar\n");
		case 1:
			k1 = c;
			lstate = 2;
			return;
			return 0;
		case 2:
			k2 = c;
			lstate = 0;


@@ 375,21 449,28 @@ print("mousechar\n");
		switch(c){
		case Caps:
			caps ^= 1;
			return;
			return 0;
		case Num:
			num ^= 1;
			return;
			return 0;
		case Shift:
			shift = 1;
			return;
			return 0;
		case Latin:
			lstate = 1;
			return;
			return 0;
		case Ctrl:
			ctl = 1;
			return;
			return 0;
		}
	}
	kbdputc(&kbdq, c);
	return;
	return 0;
}

void
kbdintr(Ureg *ur)
{
	while(kbdintr0() == 0)
		;
}

M pc/l.s => pc/l.s +32 -0
@@ 347,6 347,38 @@ TEXT	intr23(SB),$0
	PUSHL	$0
	PUSHL	$23
	JMP	intrcommon
TEXT	intr24(SB),$0
	PUSHL	$0
	PUSHL	$24
	JMP	intrcommon
TEXT	intr25(SB),$0
	PUSHL	$0
	PUSHL	$25
	JMP	intrcommon
TEXT	intr26(SB),$0
	PUSHL	$0
	PUSHL	$26
	JMP	intrcommon
TEXT	intr27(SB),$0
	PUSHL	$0
	PUSHL	$27
	JMP	intrcommon
TEXT	intr28(SB),$0
	PUSHL	$0
	PUSHL	$28
	JMP	intrcommon
TEXT	intr29(SB),$0
	PUSHL	$0
	PUSHL	$29
	JMP	intrcommon
TEXT	intr30(SB),$0
	PUSHL	$0
	PUSHL	$30
	JMP	intrcommon
TEXT	intr31(SB),$0
	PUSHL	$0
	PUSHL	$31
	JMP	intrcommon
TEXT	intr64(SB),$0
	PUSHL	$0
	PUSHL	$64

M pc/trap.c => pc/trap.c +67 -55
@@ 10,6 10,17 @@
void	noted(Ureg*, ulong);
void	notify(Ureg*);

void	intr0(void), intr1(void), intr2(void), intr3(void);
void	intr4(void), intr5(void), intr6(void), intr7(void);
void	intr8(void), intr9(void), intr10(void), intr11(void);
void	intr12(void), intr13(void), intr14(void), intr15(void);
void	intr16(void), intr17(void), intr18(void), intr19(void);
void	intr20(void), intr21(void), intr22(void), intr23(void);
void	intr24(void), intr25(void), intr26(void), intr27(void);
void	intr28(void), intr29(void), intr30(void), intr31(void);
void	intr64(void);
void	intrbad(void);

/*
 *  8259 interrupt controllers
 */


@@ 23,8 34,8 @@ enum
	EOI=		0x20,		/* non-specific end of interrupt */
};

int	int0mask = 7;		/* interrupts enabled for first 8259 */
int	int1mask = 7;		/* interrupts enabled for second 8259 */
int	int0mask = 0xff;	/* interrupts enabled for first 8259 */
int	int1mask = 0xff;		/* interrupts enabled for second 8259 */

/*
 *  trap/interrupt gates


@@ 50,6 61,9 @@ setvec(int v, void (*r)(Ureg*))
	if((v&~0x7) == Int0vec){
		int0mask &= ~(1<<(v&7));
		outb(Int0aux, int0mask);
	} else if((v&~0x7) == Int1vec){
		int1mask &= ~(1<<(v&7));
		outb(Int1aux, int1mask);
	}
}



@@ 62,6 76,12 @@ trapinit(void)
	int i;

	/*
	 *  set all interrupts to panics
	 */
	for(i = 32; i < 256; i++)
		sethvec(i, intrbad, SEGIG, 0);

	/*
	 *  set the standard traps
	 */
	sethvec(0, intr0, SEGIG, 0);


@@ 80,6 100,10 @@ trapinit(void)
	sethvec(13, intr13, SEGIG, 0);
	sethvec(14, intr14, SEGIG, 0);
	sethvec(15, intr15, SEGIG, 0);

	/*
	 *  set the standard devices
	 */
	sethvec(16, intr16, SEGIG, 0);
	sethvec(17, intr17, SEGIG, 0);
	sethvec(18, intr18, SEGIG, 0);


@@ 88,12 112,14 @@ trapinit(void)
	sethvec(21, intr21, SEGIG, 0);
	sethvec(22, intr22, SEGIG, 0);
	sethvec(23, intr23, SEGIG, 0);

	/*
	 *  set all others to unknown interrupts
	 */
	for(i = 24; i < 256; i++)
		sethvec(i, intrbad, SEGIG, 0);
	sethvec(24, intr24, SEGIG, 0);
	sethvec(25, intr25, SEGIG, 0);
	sethvec(26, intr26, SEGIG, 0);
	sethvec(27, intr27, SEGIG, 0);
	sethvec(28, intr28, SEGIG, 0);
	sethvec(29, intr29, SEGIG, 0);
	sethvec(30, intr30, SEGIG, 0);
	sethvec(31, intr31, SEGIG, 0);

	/*
	 *  system calls


@@ 115,8 141,26 @@ trapinit(void)
	outb(Int0ctl, 0x11);		/* ICW1 - edge triggered, master,
					   ICW4 will be sent */
	outb(Int0aux, Int0vec);		/* ICW2 - interrupt vector offset */
	outb(Int0aux, 0x04);		/* ICW3 - master level 2 */
	outb(Int0aux, 0x04);		/* ICW3 - have slave on level 2 */
	outb(Int0aux, 0x01);		/* ICW4 - 8086 mode, not buffered */

	/*
	 *  Set up the second 8259 interrupt processor.
	 *  Make 8259 interrupts start at CPU vector Int0vec.
	 *  Set the 8259 as master with edge triggered
	 *  input with fully nested interrupts.
	 */
	outb(Int1ctl, 0x11);		/* ICW1 - edge triggered, master,
					   ICW4 will be sent */
	outb(Int1aux, Int1vec);		/* ICW2 - interrupt vector offset */
	outb(Int1aux, 0x02);		/* ICW3 - I am a slave on level 2 */
	outb(Int1aux, 0x01);		/* ICW4 - 8086 mode, not buffered */

	/*
	 *  pass #2 8259 interrupts to #1
	 */
	int0mask &= ~0x04;
	outb(Int0aux, int0mask);
}

/*


@@ 125,19 169,28 @@ trapinit(void)
void
trap(Ureg *ur)
{
	if(ur->trap>=256 || ivec[ur->trap] == 0)
		panic("bad trap type %d %lux\n", ur->trap, ur->pc);
	int v;
	int c;

	v = ur->trap;
	if(v>=256 || ivec[v] == 0)
		panic("bad trap type %d %lux\n", v, ur->pc);

	/*
	 *  call the trap routine
	 */
	(*ivec[ur->trap])(ur);
	(*ivec[v])(ur);

	/*
	 *  tell the 8259 that we're done with the
	 *  highest level interrupt
	 */
	outb(Int0ctl, EOI);
	c = v&~0x7;
	if(c==Int0vec || c==Int1vec){
		outb(Int0ctl, EOI);
		if(c == Int1vec)
			outb(Int1ctl, EOI);
	}
}

/*


@@ 173,48 226,7 @@ execpc(ulong entry)
/*
 *  system calls
 */
#undef	CHDIR	/* BUG */
#include "/sys/src/libc/9syscall/sys.h"

typedef long Syscall(ulong*);
Syscall	sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, sysdeath, syswait;
Syscall	sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat;
Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate;
Syscall	sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysalarm;

Syscall *systab[]={
	sysr1,
	syserrstr,
	sysbind,
	syschdir,
	sysclose,
	sysdup,
	sysalarm,
	sysexec,
	sysexits,
	sysfork,
	sysforkpgrp,
	sysfstat,
	sysdeath,
	sysmount,
	sysopen,
	sysread,
	sysseek,
	syssleep,
	sysstat,
	syswait,
	syswrite,
	syspipe,
	syscreate,
	sysdeath,
	sysbrk_,
	sysremove,
	syswstat,
	sysfwstat,
	sysnotify,
	sysnoted,
	sysdeath,	/* sysfilsys */
};
#include "../port/systab.h"

long
syscall(Ureg *ur)

M pc/vga.c => pc/vga.c +1 -1
@@ 240,7 240,7 @@ getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
	ulong ans;

	/*
	 * The magnum monochrome says 0 is black (zero intensity)
	 * The safari monochrome says 0 is black (zero intensity)
	 */
	if(p == 0)
		ans = 0;

M port/devbit.c => port/devbit.c +7 -2
@@ 1133,12 1133,17 @@ void
Cursortocursor(Cursor *c)
{
	int i;
	uchar *p;

	lock(&cursor);
	memmove(&cursor, c, sizeof(Cursor));
	for(i=0; i<16; i++){
		setbits[i] = (c->set[2*i]<<24) + (c->set[2*i+1]<<16);
		clrbits[i] = (c->clr[2*i]<<24) + (c->clr[2*i+1]<<16);
		p = (uchar*)&setbits[i];
		*p = c->set[2*i];
		*(p+1) = c->set[2*i+1];
		p = (uchar*)&clrbits[i];
		*p = c->clr[2*i];
		*(p+1) = c->clr[2*i+1];
	}
	unlock(&cursor);
}

M port/portdat.h => port/portdat.h +1 -1
@@ 582,7 582,7 @@ enum {
	Streambhi= 32,			/* block count high water mark */
};

#define MAXSYSARG	6		/* for mount(fd, mpt, flag, arg, srv, authfd) */
#define MAXSYSARG	6		/* for mount(fd, mpt, flag, arg, srv) */
#define	PRINTSIZE	256
#define	NUMSIZE		12		/* size of formatted number */


M port/segment.c => port/segment.c +1 -1
@@ 442,7 442,7 @@ segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
			errors("segments overlap");
	}

	for(ps = physseg; *(ps->name); ps++)
	for(ps = physseg; ps->name; ps++)
		if(strcmp(name, ps->name) == 0)
			goto found;


A port/systab.h => port/systab.h +47 -0
@@ 0,0 1,47 @@
#undef	CHDIR	/* BUG */
#include "/sys/src/libc/9syscall/sys.h"

typedef long Syscall(ulong*);
Syscall sysbind, sysbrk_, syschdir, sysclose, syscreate, sysdeath;
Syscall	sysdup, syserrstr, sysexec, sysexits, sysfork, sysforkpgrp;
Syscall	sysfstat, sysfwstat, sysgetpid, sysmount, sysnoted;
Syscall	sysnotify, sysopen, syspipe, sysr1, sysread, sysremove, sysseek;
Syscall syssleep, sysstat, syswait, syswrite, syswstat, sysalarm, syssegbrk;
Syscall syssegattach, syssegdetach, syssegfree, syssegflush;

Syscall *systab[]={
	[SYSR1]		sysr1,
	[ERRSTR]	syserrstr,
	[BIND]		sysbind,
	[CHDIR]		syschdir,
	[CLOSE]		sysclose,
	[DUP]		sysdup,
	[ALARM]		sysalarm,
	[EXEC]		sysexec,
	[EXITS]		sysexits,
	[FORK]		sysfork,
	[FORKPGRP]	sysforkpgrp,
	[FSTAT]		sysfstat,
	[SEGBRK]	syssegbrk,
	[MOUNT]		sysmount,
	[OPEN]		sysopen,
	[READ]		sysread,
	[SEEK]		sysseek,
	[SLEEP]		syssleep,
	[STAT]		sysstat,
	[WAIT]		syswait,
	[WRITE]		syswrite,
	[PIPE]		syspipe,
	[CREATE]	syscreate,
	[___USERSTR___]	sysdeath,
	[BRK_]		sysbrk_,
	[REMOVE]	sysremove,
	[WSTAT]		syswstat,
	[FWSTAT]	sysfwstat,
	[NOTIFY]	sysnotify,
	[NOTED]		sysnoted,
	[SEGATTACH]	syssegattach,
	[SEGDETACH]	syssegdetach,
	[SEGFREE]	syssegfree,
	[SEGFLUSH]	syssegflush,
};

M power/segment.h => power/segment.h +1 -1
@@ 12,7 12,7 @@ struct Physseg
	Page	*(*pgalloc)(ulong);	/* Allocation if we need it */
	void	(*pgfree)(Page*);
}physseg[] = {
	{ SG_SHARED,	"lock",		0,	1024*BY2PG,	&lkpage,	&lkpgfree },
	{ SG_PHYSICAL,	"lock",		0,	1024*BY2PG,	&lkpage,	&lkpgfree },
	{ SG_SHARED,	"shared",	0,	SEGMAXSIZE,	&snewpage, 	&putpage },
	{ SG_PHYSICAL,	"kmem",		KZERO,	SEGMAXSIZE,	0,		0 	},
	{ SG_BSS,	"memory",	0,	SEGMAXSIZE,	&snewpage,	&putpage },

M power/trap.c => power/trap.c +2 -48
@@ 461,53 461,7 @@ noted(Ureg **urp, ulong arg0)
}


#undef	CHDIR	/* BUG */
#include "/sys/src/libc/9syscall/sys.h"

typedef long Syscall(ulong*);
Syscall sysbind, sysbrk_, syschdir, sysclose, syscreate, sysdeath;
Syscall	sysdup, syserrstr, sysexec, sysexits, sysfork, sysforkpgrp;
Syscall	sysfstat, sysfwstat, sysgetpid, sysmount, sysnoted;
Syscall	sysnotify, sysopen, syspipe, sysr1, sysread, sysremove, sysseek;
Syscall syssleep, sysstat, syswait, syswrite, syswstat, sysalarm, syssegbrk;
Syscall syssegattach, syssegdetach, syssegfree, syssegflush;

Syscall *systab[]={
	[SYSR1]		sysr1,
	[ERRSTR]	syserrstr,
	[BIND]		sysbind,
	[CHDIR]		syschdir,
	[CLOSE]		sysclose,
	[DUP]		sysdup,
	[ALARM]		sysalarm,
	[EXEC]		sysexec,
	[EXITS]		sysexits,
	[FORK]		sysfork,
	[FORKPGRP]	sysforkpgrp,
	[FSTAT]		sysfstat,
	[SEGBRK]	syssegbrk,
	[MOUNT]		sysmount,
	[OPEN]		sysopen,
	[READ]		sysread,
	[SEEK]		sysseek,
	[SLEEP]		syssleep,
	[STAT]		sysstat,
	[WAIT]		syswait,
	[WRITE]		syswrite,
	[PIPE]		syspipe,
	[CREATE]	syscreate,
	[___USERSTR___]	sysdeath,
	[BRK_]		sysbrk_,
	[REMOVE]	sysremove,
	[WSTAT]		syswstat,
	[FWSTAT]	sysfwstat,
	[NOTIFY]	sysnotify,
	[NOTED]		sysnoted,
	[SEGATTACH]	syssegattach,
	[SEGDETACH]	syssegdetach,
	[SEGFREE]	syssegfree,
	[SEGFLUSH]	syssegflush,
};
#include "../port/systab.h"

long
syscall(Ureg *aur)


@@ 543,7 497,7 @@ syscall(Ureg *aur)
	u->nerrlab = 0;
	ret = -1;
	if(!waserror()){
		if(r1 >= sizeof systab/BY2WD){
		if(r1 >= sizeof systab/sizeof systab[0]){
			pprint("bad sys call number %d pc %lux\n", r1, ((Ureg*)UREGADDR)->pc);
			msg = "sys: bad sys call";
	    Bad:

M ss/trap.c => ss/trap.c +1 -42
@@ 306,48 306,7 @@ noted(Ureg **urp, ulong arg0)
	}
}

#undef	CHDIR	/* BUG */
#include "/sys/src/libc/9syscall/sys.h"

typedef long Syscall(ulong*);
Syscall	sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, sysdeath, syswait;
Syscall	sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat;
Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate;
Syscall	sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysalarm;

Syscall *systab[]={
	sysr1,
	syserrstr,
	sysbind,
	syschdir,
	sysclose,
	sysdup,
	sysalarm,
	sysexec,
	sysexits,
	sysfork,
	sysforkpgrp,
	sysfstat,
	sysdeath,
	sysmount,
	sysopen,
	sysread,
	sysseek,
	syssleep,
	sysstat,
	syswait,
	syswrite,
	syspipe,
	syscreate,
	sysdeath,
	sysbrk_,
	sysremove,
	syswstat,
	sysfwstat,
	sysnotify,
	sysnoted,
	sysdeath,	/* sysfilsys */
};
#include "../port/systab.h"

long
syscall(Ureg *aur)