~kris/9p

9hist

f15aa24b2d38101e5c7f8837250ceaf388acc82f — David du Colombier 33 years ago 2db6b1b
Plan 9 from Bell Labs 1992-10-13
9 files changed, 188 insertions(+), 78 deletions(-)

M pc/archgeneric.c
M pc/devfloppy.c
M pc/devincon.c
M pc/dma.c
M pc/kbd.c
M pc/mem.h
M pc/screen.h
M pc/vga.c
M port/devbit.c
M pc/archgeneric.c => pc/archgeneric.c +1 -1
@@ 15,7 15,7 @@ genericreset(void)
PCArch generic =
{
	"generic",
	genericreset,
	i8042reset,
	0,
	0,
	0,

M pc/devfloppy.c => pc/devfloppy.c +55 -58
@@ 196,7 196,6 @@ static int	floppysense(void);
static void	floppywait(void);
static long	floppyxfer(Drive*, int, void*, long, long);
static void	floppyformat(Drive*, char*);
static long	floppythrice(Drive*, int, void*, long, long);
static int	cmddone(void*);
void Xdelay(int);



@@ 372,32 371,52 @@ islegal(ulong offset, long n, Drive *dp)
}

/*
 *  check if the floppy has been replaced under foot.  cause a read error if it has.
 *  check if the floppy has been replaced under foot.  cause
 *  an error if it has.
 *
 *  a seek and a read clears the condition.  this was determined experimentally,
 *  there has to be a better way.
 *  a seek and a read clears the condition.  this was determined
 *  experimentally, there has to be a better way.
 *
 *  if the read fails, cycle through the possible floppy
 *  density till one works or we've cycled through all
 *  possibilities.
 */
static void
changed(Chan *c, Drive *dp)
{
	ulong old;
	Type *start;

	if(inb(Pdir)&Fchange){
		setdef(dp);
	/*
	 *  if floppy has changed or first time through
	 */
	if((inb(Pdir)&Fchange) || dp->vers == 0){
		dp->vers++;
		dp->confused = 1;
		setdef(dp);
		start = dp->t;
		dp->confused = 1;	/* make floppyon recal */
		floppyon(dp);
		if(dp->cyl)
			floppythrice(dp, Fread, dp->cache, 0, dp->t->tsize);
		else
			floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize,
					dp->t->tsize);
		floppyseek(dp, dp->t->heads*dp->t->tsize);
		while(waserror()){
			while(++dp->t){
				if(dp->t == &floppytype[NTYPES])
					dp->t = floppytype;
				if(dp->dt == dp->t->dt)
					break;
			}
			floppydir[NFDIR*dp->dev].length = dp->t->cap;
			if(dp->t == start)
				nexterror();
			floppyon(dp);
		}
		floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
		poperror();
	}

	old = c->qid.vers;
	c->qid.vers = dp->vers;
	if(old && old!=dp->vers){
	if(old && old != dp->vers)
		error(Eio);
	}
}

long


@@ 443,7 462,7 @@ floppyread(Chan *c, void *a, long n, ulong offset)
			 */
			if(dp->ccyl!=cyl || dp->chead!=head){
				dp->ccyl = -1;
				i = floppythrice(dp, Fread, dp->cache,
				i = floppyxfer(dp, Fread, dp->cache,
					(cyl*dp->t->heads+head)*nn, nn);
				if(i != nn){
					if(i == 0)


@@ 494,7 513,7 @@ floppywrite(Chan *c, void *a, long n, ulong offset)
			floppypos(dp, offset+rv);
			if(dp->tcyl == dp->ccyl)
				dp->ccyl = -1;
			i = floppythrice(dp, Fwrite, aa+rv, offset+rv, n-rv);
			i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv);
			if(i < 0)
				break;
			if(i == 0)


@@ 753,6 772,7 @@ floppyrecal(Drive *dp)
	dp->cyl = fl.stat[1];
	if(dp->cyl != 0){
		DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl);
		dp->cyl = -1;
		dp->confused = 1;
		return -1;
	}


@@ 829,59 849,24 @@ floppyseek(Drive *dp, long off)
}

/*
 *  since floppies are so flakey, automaticly retry failed attempts.
 *  every 3 tries switch to a different density
 *  read or write to floppy.  try up to three times.
 */
static long
floppythrice(Drive *dp, int cmd, void *a, long off, long n)
{
	int tries;
	long rv;
	Type *start;

	start = dp->t;
	for(tries = 0; ; tries++){
		if(waserror()){
			if(cmd != Fread || strcmp(u->error, Eintr)==0)
				nexterror();

			/* walk through the compatible types */
			if(tries == 3){
				while(++dp->t){
					if(dp->t == &floppytype[NTYPES])
						dp->t = floppytype;
					if(dp->dt == Tnone)
						break;
					if(dp->dt == dp->t->dt)
						break;
				}
				floppydir[NFDIR*dp->dev].length = dp->t->cap;
				if(dp->t == start)
					nexterror();
				tries = 0;
				floppyon(dp);
			}
		} else {
			rv = floppyxfer(dp, cmd, a, off, n);
			poperror();
			return rv;
		}
	}
}

static long
floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
{
	long offset;
	int tries = 0;

	if(off >= dp->t->cap)
		return 0;
	if(off + n > dp->t->cap)
		n = dp->t->cap - off;

	/*
	 *  calculate new position and seek to it (dp->len may be trimmed)
	 */
	/* retry on error 3 times */
	while(waserror())
		if(tries++ >= 3)
			nexterror();

	dp->len = n;
	if(floppyseek(dp, off) < 0)
		error(Eio);


@@ 892,6 877,10 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
	/*
	 *  set up the dma (dp->len may be trimmed)
	 */
	if(waserror()){
		dmaend(DMAchan);
		nexterror();
	}
	dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);

	/*


@@ 919,6 908,7 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
	 */
	floppywait();
	dmaend(DMAchan);
	poperror();

	/*
	 *  check for errors


@@ 947,6 937,7 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
		dp->confused = 1;
		error(Eio);
	}
	poperror();

	dp->lasttouched = m->ticks;
	return dp->len;


@@ 1016,6 1007,10 @@ floppyformat(Drive *dp, char *params)
			*bp++ = sec;
			*bp++ = t->bcode;
		}
		if(waserror()){
			dmaend(DMAchan);
			nexterror();
		}
		dmasetup(DMAchan, buf, bp-buf, 0);

		/*


@@ 1038,6 1033,7 @@ floppyformat(Drive *dp, char *params)
		 */
		floppywait();
		dmaend(DMAchan);
		poperror();

		/*
		 *  check for errors


@@ 1055,6 1051,7 @@ floppyformat(Drive *dp, char *params)
		}
	}
	free(buf);
	dp->confused = 1;
	poperror();
}


M pc/devincon.c => pc/devincon.c +34 -7
@@ 60,7 60,7 @@ typedef struct Incon	Incon;

#define NOW (MACHP(0)->ticks*MS2HZ)

#define DPRINT if(incondebug)kprint
#define DPRINT /*if(incondebug)k*/print

static void	inconintr(Ureg *ur);



@@ 174,11 174,21 @@ Dirtab incondir[]={
};
#define NINCON	(sizeof incondir/sizeof incondir[0])

/*static void
Xdelay(int n)
{
	while(--n >= 0) ;
}
#define	SDLY	1000
*/
#define	Xdelay(n)

static void
reset(int dev)				/* hardware reset */
{
	outb(dev+Qpcr, Finitbar);
	outb(dev+Qpcr, 0);
	Xdelay(10000);
	outb(dev+Qpcr, Finitbar);
}



@@ 188,6 198,7 @@ wrctl(int dev, int data)		/* write control character */
	outb(dev+Qpcr, Finitbar);	/* no interrupts, please */
	outb(dev+Qdlr, data);
	outb(dev+Qpcr, Finitbar|Fstrobe);
	Xdelay(SDLY);
	outb(dev+Qpcr, Finitbar|Fie);
}



@@ 197,6 208,7 @@ wrdata(int dev, int data)		/* write data character */
	outb(dev+Qpcr, Finitbar|Fsi);
	outb(dev+Qdlr, data);
	outb(dev+Qpcr, Finitbar|Fsi|Fstrobe);
	Xdelay(SDLY);
	outb(dev+Qpcr, Finitbar|Fsi|Fie);
}



@@ 206,6 218,7 @@ wrcmd(int dev, int data)		/* write command */
	outb(dev+Qpcr, Finitbar|Faf);
	outb(dev+Qdlr, data);
	outb(dev+Qpcr, Finitbar|Faf|Fstrobe);
	Xdelay(SDLY);
	outb(dev+Qpcr, Finitbar|Faf|Fie);
}



@@ 219,8 232,10 @@ rdstatus(Incon *ip)			/* read status */
	outb(dev+Qpcr, Finitbar|Faf|Fsi);
	outb(dev+Qdlr, 0x01);
	outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
	Xdelay(SDLY);
	data = (inb(dev+Qpsr)&0xf8)<<2;
	outb(dev+Qpcr, Finitbar|Faf|Fsi);
	Xdelay(SDLY);
	data |= inb(dev+Qpsr)>>3;
	if(data&(OVERFLOW|CRC_ERROR)){
		if(data&OVERFLOW)


@@ 230,6 245,7 @@ rdstatus(Incon *ip)			/* read status */
	}
	outb(dev+Qdlr, 0x03);
	outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
	Xdelay(SDLY);
	outb(dev+Qpcr, Finitbar|Faf|Fsi|Fie);

	return data;


@@ 240,6 256,7 @@ iwrcmd(int dev, int data)		/* write command at interrupt level */
{
	outb(dev+Qdlr, data);
	outb(dev+Qpcr, Finitbar|Faf|Fstrobe);
	Xdelay(SDLY);
	outb(dev+Qpcr, Finitbar|Faf);
}



@@ 252,8 269,10 @@ irdstatus(Incon *ip)			/* read status at interrupt level */

	outb(dev+Qdlr, 0x01);
	outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
	Xdelay(SDLY);
	data = (inb(dev+Qpsr)&0xf8)<<2;
	outb(dev+Qpcr, Finitbar|Faf|Fsi);
	Xdelay(SDLY);
	data |= inb(dev+Qpsr)>>3;
	if(data&(OVERFLOW|CRC_ERROR)){
		if(data&OVERFLOW)


@@ 272,8 291,10 @@ irddata(int dev)			/* read data at interrupt level */

	outb(dev+Qdlr, 0x00);
	outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
	Xdelay(SDLY);
	data = (inb(dev+Qpsr)&0xf8)<<2;
	outb(dev+Qpcr, Finitbar|Faf|Fsi);
	Xdelay(SDLY);
	data |= inb(dev+Qpsr)>>3;

	return data;


@@ 285,8 306,10 @@ irdnext(int dev)			/* read next data at interrupt level */
	int data;

	outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
	Xdelay(SDLY);
	data = (inb(dev+Qpsr)&0xf8)<<2;
	outb(dev+Qpcr, Finitbar|Faf|Fsi);
	Xdelay(SDLY);
	data |= inb(dev+Qpsr)>>3;

	return data;


@@ 297,12 320,13 @@ irdnop(int dev, int pcr)		/* read nop (mux reset) */
{
	outb(dev+Qdlr, 0x03);
	outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
	Xdelay(SDLY);
	outb(dev+Qpcr, pcr);
}

/*
int		Irdnext(int);
#define	irdnext	Irdnext

*/
/*
 *  set the incon parameters
 */


@@ 415,6 439,7 @@ inconpoll(Incon *ip, int station)
			break;
		}
	}
print("poll: status 0x%.2ux\n", rdstatus(ip));
}

/*


@@ 471,7 496,7 @@ inconreset(void)
	 */
/*	inconset(&incon[0], 3, 15); /**/
	for(i=0; i<Nincon; i++){
		incon[i].dev = lptbase[i];
		incon[i].dev = lptbase[1/*i*/];
		incon[i].state = Notliving;
		reset(incon[i].dev);
		incon[i].ri = incon[i].wi = 0;


@@ 496,7 521,8 @@ inconattach(char *spec)
	int i;
	Chan *c;

	setvec(Parallelvec, inconintr);
	/*setvec(Parallelvec, inconintr);*/
setvec(Int0vec+5, inconintr);
	i = strtoul(spec, 0, 0);
	if(i >= Nincon)
		error(Ebadarg);


@@ 785,10 811,10 @@ inconoput(Queue *q, Block *bp)
		/*
		 *  spin till there is room
		 */
		for(n=0, end = NOW+1000; rdstatus(ip) & TX_FULL; n++){
		for(n=0, end = NOW+1000; (ctl=rdstatus(ip)) & TX_FULL; n++){
			nop();	/* make sure we don't optimize too much */
			if(NOW > end){
				print("incon output stuck 0\n");
				print("incon output stuck 0 %.2ux\n", ctl);
				freemsg(q, bp);
				qunlock(&ip->xmit);
				return;


@@ 1076,6 1102,7 @@ inconintr(Ureg *ur)
	int pcr;
	Incon *ip;

print("I");
	USED(ur);
	ip = &incon[0];
	pcr = inb(ip->dev+Qpcr);

M pc/dma.c => pc/dma.c +2 -1
@@ 105,7 105,8 @@ dmasetup(int chan, void *va, long len, int isread)
	 *  allocate a page for the DMA.
	 */
	pa = ((ulong)va) & ~KZERO;
	if(!isphys(va) || (pa&0xFFFF0000)!=((pa+len)&0xFFFF0000)){
	if((((ulong)va)&0xF0000000) != KZERO
	|| (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)){
		if(xp->pg == 0)
			xp->pg = newpage(1, 0, 0);
		if(len > BY2PG)

M pc/kbd.c => pc/kbd.c +10 -2
@@ 183,7 183,6 @@ mousecmd(int cmd)
void
i8042a20(void)
{
	outready();
	outb(Cmd, 0xD1);
	outready();
	outb(Data, 0xDF);


@@ 196,10 195,19 @@ i8042a20(void)
void
i8042reset(void)
{
	/*
	 *  this works for dhog
	 */
	outready();
	outb(Cmd, 0xFE);	/* pulse reset line */
	outready();
	/*
	 *  this is the old IBM way
	 */
	outready();
	outb(Cmd, 0xD1);
	outready();
	outb(Data, 0xDE);
	outb(Data, 0xDE);	/* set reset line high */
	outready();
}


M pc/mem.h => pc/mem.h +0 -1
@@ 53,7 53,6 @@

#define	MACHSIZE	4096

#define isphys(x) (((ulong)x)&KZERO)

/*
 *  known 80386 segments (in GDT) and their selectors

M pc/screen.h => pc/screen.h +3 -0
@@ 29,3 29,6 @@ extern Cursorinfo	cursor;
extern void		mouseupdate(int);

#define	hwscreenwrite(a, b)

#define	screenupdate(z)
int	islcd;

M pc/vga.c => pc/vga.c +5 -5
@@ 49,18 49,18 @@ struct VGAmode
};

/*
 *  640x480 display, 16 bit color.
 *  640x480 display, 16 bit color.  
 */
VGAmode mode12 = 
{
	/* general */
	0xe7, 0x00,
	0xe3, 0x00,
	/* sequence */
	0x03, 0x01, 0x0f, 0x00, 0x06,
	/* crt */
	0x65, 0x4f, 0x50, 0x88, 0x55, 0x9a, 0x09, 0x3e,
	0x63, 0x4f, 0x58, 0x81, 0x59, 0x81, 0x0b, 0x3e,
	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xe8, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
	0xea, 0x2c, 0xdf, 0x28, 0x00, 0xea, 0xeb, 0xe3,
	0xff,
	/* graphics */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,


@@ 68,7 68,7 @@ VGAmode mode12 =
	/* attribute */
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x3f,
	0x01, 0x10, 0x0f, 0x00, 0x00,
	0x01, 0x00, 0x0f, 0x00, 0x00,
};



M port/devbit.c => port/devbit.c +78 -3
@@ 103,6 103,7 @@ void	arenafree(Arena*);
void	bitstring(GBitmap*, Point, GFont*, uchar*, long, Fcode);
void	bitloadchar(GFont*, int, GSubfont*, int);
extern	GBitmap	gscreen;
extern	islcd;

Mouseinfo	mouse;
Cursorinfo	cursor;


@@ 746,6 747,55 @@ bitread(Chan *c, void *va, long n, ulong offset)
	return n;
}

static Rectangle mbb = {10000, 10000, -10000, -10000};

static void
mbbrect(Rectangle r)
{
	if (r.min.x < mbb.min.x)
		mbb.min.x = r.min.x;
	if (r.min.y < mbb.min.y)
		mbb.min.y = r.min.y;
	if (r.max.x > mbb.max.x)
		mbb.max.x = r.max.x;
	if (r.max.y > mbb.max.y)
		mbb.max.y = r.max.y;
}

static void
mbbpt(Point p)
{
	if (p.x < mbb.min.x)
		mbb.min.x = p.x;
	if (p.y < mbb.min.y)
		mbb.min.y = p.y;
	if (p.x >= mbb.max.x)
		mbb.max.x = p.x+1;
	if (p.y >= mbb.max.y)
		mbb.max.y = p.y+1;
}

Point
bitstrsize(GFont *f, uchar *p, int l)
{
	ushort r;
	Point s = {0,0};
	GCacheinfo *c;

	while(l > 0){
		r = BGSHORT(p);
		p += 2;
		l -= 2;
		if(r >= f->ncache)
			continue;
		c = &f->cache[r];
		if(c->bottom > s.y)
			s.y = c->bottom;
		s.x += c->width;
	}
	return s;
}

long
bitwrite(Chan *c, void *va, long n, ulong offset)
{


@@ 754,6 804,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	ulong l, nw, ws, rv, q0, q1;
	ulong *lp;
	int off, isoff, i, j, ok;
	ulong *endscreen = gaddr(&gscreen, Pt(0, gscreen.r.max.y));
	Point pt, pt1, pt2;
	Rectangle rect;
	Cursor curs;


@@ 763,6 814,7 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	BSubfont *f, *tf, **fp;
	GFont *ff, **ffp;
	GCacheinfo *gc;
	extern void screenupdate(Rectangle);

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


@@ 856,6 908,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				isoff = 1;
			}
			gbitblt(dst, pt, src, rect, fc);
			if(islcd && dst->base < endscreen)
				mbbrect(Rpt(pt, add(pt, sub(rect.max, rect.min))));
			m -= 31;
			p += 31;
			break;


@@ 1089,6 1143,10 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				isoff = 1;
			}
			gsegment(dst, pt1, pt2, t, fc);
			if(islcd && dst->base < endscreen) {
				mbbpt(pt1);
				mbbpt(pt2);
			}
			m -= 22;
			p += 22;
			break;


@@ 1188,6 1246,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				isoff = 1;
			}
			gpoint(dst, pt1, t, fc);
			if(islcd && dst->base < endscreen)
				mbbpt(pt1);
			m -= 14;
			p += 14;
			break;


@@ 1278,6 1338,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				isoff = 1;
			}
			bitstring(dst, pt, ff, p, l, fc);
			if(islcd && dst->base < endscreen)
				mbbrect(Rpt(pt, add(pt, bitstrsize(ff, p, l))));
			m -= l;
			p += l;
			break;


@@ 1315,6 1377,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				isoff = 1;
			}
			gtexture(dst, rect, src, fc);
			if(islcd && dst->base < endscreen)
				mbbrect(rect);
			m -= 23;
			p += 23;
			break;


@@ 1393,6 1457,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
				t = (t/ws)*ws;
				l = (t+dst->r.max.x+ws-1)/ws;
			}
			if(islcd && dst->base < endscreen)
				mbbrect(Rect(dst->r.min.x, miny, dst->r.max.x, maxy));
			p += 11;
			m -= 11;
			if(m < l*(maxy-miny))


@@ 1504,6 1570,10 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
	poperror();
	if(isoff)
		cursoron(1);
	if(islcd) {
		screenupdate(mbb);
		mbb = Rect(10000, 10000, -10000, -10000);
	}
	qunlock(&bit);
	return n;
}


@@ 1851,10 1921,12 @@ cursoron(int dolock)
		cursor.r.max = add(mouse.xy, Pt(16, 16));
		cursor.r = raddp(cursor.r, cursor.offset);
		gbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S);
		gbitblt(&gscreen, add(mouse.xy, cursor.offset),
		gbitblt(&gscreen, cursor.r.min,
			&clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S);
		gbitblt(&gscreen, add(mouse.xy, cursor.offset),
		gbitblt(&gscreen, cursor.r.min,
			&set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D);
		if(islcd)
			mbbrect(cursor.r);
	}
	if(dolock)
		unlock(&cursor);


@@ 1865,8 1937,11 @@ cursoroff(int dolock)
{
	if(dolock)
		lock(&cursor);
	if(--cursor.visible == 0)
	if(--cursor.visible == 0) {
		gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S);
		if(islcd)
			mbbrect(cursor.r);
	}
	if(dolock)
		unlock(&cursor);
}