~kris/9p

9hist

0079dc2c0e85b12a9d9cbd953a7aa13be1d65419 — David du Colombier 25 years ago 98fa67b
Plan 9 from Bell Labs 2000-11-04
M bitsy/devpenmouse.c => bitsy/devpenmouse.c +3 -3
@@ 22,10 22,10 @@ struct Calibration
	long	transx;
	long	transy;
} calibration = {
	-23540,
	-16858,
	342,
	252
	23540,
	252,
	342
};

struct Mousestate

M bitsy/devuda1341.c => bitsy/devuda1341.c +31 -559
@@ 125,12 125,39 @@ struct	Buf
	ulong	phys;
	Buf*	next;
};

struct	AQueue
{
	Lock;
	Buf*	first;
	Buf*	last;
};

static	struct
{
	QLock;
	Rendez	vous;
	int	bufinit;	/* boolean if buffers allocated */
	int	curcount;	/* how much data in current buffer */
	int	active;		/* boolean dma running */
	int	intr;		/* boolean an interrupt has happened */
	int	amode;		/* Aclosed/Aread/Awrite for /audio */
	int	rivol[Nvol];		/* right/left input/output volumes */
	int	livol[Nvol];
	int	rovol[Nvol];
	int	lovol[Nvol];
	int	major;		/* SB16 major version number (sb 4) */
	int	minor;		/* SB16 minor version number */
	ulong	totcount;	/* how many bytes processed since open */
	vlong	tottime;	/* time at which totcount bytes were processed */

	Buf	buf[Nbuf];	/* buffers and queues */
	AQueue	empty;
	AQueue	full;
	Buf*	current;
	Buf*	filling;
} input, output;

static	struct
{
	QLock;


@@ 181,7 208,7 @@ static	struct
/*
 * Grab control of the IIC/L3 shared pins
 */
static inline void L3_acquirepins(void)
static void L3_acquirepins(void)
{
	GPSR = (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	GPDR |=  (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);


@@ 190,7 217,7 @@ static inline void L3_acquirepins(void)
/*
 * Release control of the IIC/L3 shared pins
 */
static inline void L3_releasepins(void)
static void L3_releasepins(void)
{
	GPDR &= ~(GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
	GPCR = (GPIO_L3_SCLK_o | GPIO_L3_SDA_io);


@@ 211,7 238,7 @@ static void __init L3_init(void)
 * Get a bit. The clock is high on entry and on exit. Data is read after
 * the clock low time has expired.
 */
static inline int L3_getbit(void)
static int L3_getbit(void)
{
	int data;



@@ 230,7 257,7 @@ static inline int L3_getbit(void)
 * Send a bit. The clock is high on entry and on exit. Data is sent only
 * when the clock is low (I2C compatibility).
 */
static inline void L3_sendbit(int bit)
static void L3_sendbit(int bit)
{
	GPCR = GPIO_L3_SCLK_o;



@@ 358,182 385,9 @@ static int L3_read(char addr, char * data, int len)
	return bytes;
}

static	void	swab(uchar*);

static	char	Emajor[]	= "soundblaster not responding/wrong version";
static	char	Emode[]		= "illegal open mode";
static	char	Evolume[]	= "illegal volume specifier";

static	int
sbcmd(int val)
{
	int i, s;

	for(i=1<<16; i!=0; i--) {
		s = inb(blaster.wstatus);
		if((s & 0x80) == 0) {
			outb(blaster.write, val);
			return 0;
		}
	}
/*	print("#A: sbcmd (0x%.2x) timeout\n", val);	/**/
	return 1;
}

static	int
sbread(void)
{
	int i, s;

	for(i=1<<16; i!=0; i--) {
		s = inb(blaster.rstatus);
		if((s & 0x80) != 0) {
			return inb(blaster.read);
		}
	}
/*	print("#A: sbread did not respond\n");	/**/
	return -1;
}

static int
ess1688w(int reg, int val)
{
	if(sbcmd(reg) || sbcmd(val))
		return 1;

	return 0;
}

static int
ess1688r(int reg)
{
	if(sbcmd(0xC0) || sbcmd(reg))
		return -1;

	return sbread();
}

static	int
mxcmd(int addr, int val)
{

	outb(blaster.mixaddr, addr);
	outb(blaster.mixdata, val);
	return 1;
}

static	int
mxread(int addr)
{
	int s;

	outb(blaster.mixaddr, addr);
	s = inb(blaster.mixdata);
	return s;
}

static	void
mxcmds(int s, int v)
{

	if(v > 100)
		v = 100;
	if(v < 0)
		v = 0;
	mxcmd(s, (v*255)/100);
}

static	void
mxcmdt(int s, int v)
{

	if(v > 100)
		v = 100;
	if(v <= 0)
		mxcmd(s, 0);
	else
		mxcmd(s, 255-100+v);
}

static	void
mxcmdu(int s, int v)
{

	if(v > 100)
		v = 100;
	if(v <= 0)
		v = 0;
	mxcmd(s, 128-50+v);
}

static	void
mxvolume(void)
{
	int *left, *right;
	int source;

	if(audio.amode == Aread){
		left = audio.livol;
		right = audio.rivol;
	}else{
		left = audio.lovol;
		right = audio.rovol;
	}

	ilock(&blaster);

	mxcmd(0x30, 255);		/* left master */
	mxcmd(0x31, 255);		/* right master */
	mxcmd(0x3f, 0);		/* left igain */
	mxcmd(0x40, 0);		/* right igain */
	mxcmd(0x41, 0);		/* left ogain */
	mxcmd(0x42, 0);		/* right ogain */

	mxcmds(0x32, left[Vaudio]);
	mxcmds(0x33, right[Vaudio]);

	mxcmds(0x34, left[Vsynth]);
	mxcmds(0x35, right[Vsynth]);

	mxcmds(0x36, left[Vcd]);
	mxcmds(0x37, right[Vcd]);

	mxcmds(0x38, left[Vline]);
	mxcmds(0x39, right[Vline]);

	mxcmds(0x3a, left[Vmic]);
	mxcmds(0x3b, left[Vspeaker]);

	mxcmdu(0x44, left[Vtreb]);
	mxcmdu(0x45, right[Vtreb]);

	mxcmdu(0x46, left[Vbass]);
	mxcmdu(0x47, right[Vbass]);

	source = 0;
	if(left[Vsynth])
		source |= 1<<6;
	if(right[Vsynth])
		source |= 1<<5;
	if(left[Vaudio])
		source |= 1<<4;
	if(right[Vaudio])
		source |= 1<<3;
	if(left[Vcd])
		source |= 1<<2;
	if(right[Vcd])
		source |= 1<<1;
	if(left[Vmic])
		source |= 1<<0;
	if(audio.amode == Aread)
		mxcmd(0x3c, 0);		/* output switch */
	else
		mxcmd(0x3c, source);
	mxcmd(0x3d, source);		/* input left switch */
	mxcmd(0x3e, source);		/* input right switch */
	iunlock(&blaster);
}

static	Buf*
getbuf(AQueue *q)
{


@@ 562,388 416,6 @@ putbuf(AQueue *q, Buf *b)
	iunlock(q);
}

/*
 * move the dma to the next buffer
 */
static	void
contindma(void)
{
	Buf *b;

	if(!audio.active)
		goto shutdown;

	b = audio.current;
	if(audio.amode == Aread) {
		if(b)	/* shouldn't happen */
			putbuf(&audio.full, b);
		b = getbuf(&audio.empty);
	} else {
		if(b)	/* shouldn't happen */
			putbuf(&audio.empty, b);
		b = getbuf(&audio.full);
	}
	audio.current = b;
	if(b == 0)
		goto shutdown;

	if(dmasetup(blaster.dma, b->virt, Bufsize, audio.amode == Aread) >= 0)
		return;
	print("#A: dmasetup fail\n");
	putbuf(&audio.empty, b);

shutdown:
	dmaend(blaster.dma);
	sbcmd(0xd9);				/* exit at end of count */
	sbcmd(0xd5);				/* pause */
	audio.curcount = 0;
	audio.active = 0;
}

/*
 * cause sb to get an interrupt per buffer.
 * start first dma
 */
static	void
sb16startdma(void)
{
	ulong count;
	int speed;

	ilock(&blaster);
	dmaend(blaster.dma);
	if(audio.amode == Aread) {
		sbcmd(0x42);			/* input sampling rate */
		speed = audio.livol[Vspeed];
	} else {
		sbcmd(0x41);			/* output sampling rate */
		speed = audio.lovol[Vspeed];
	}
	sbcmd(speed>>8);
	sbcmd(speed);

	count = (Bufsize >> 1) - 1;
	if(audio.amode == Aread)
		sbcmd(0xbe);			/* A/D, autoinit */
	else
		sbcmd(0xb6);			/* D/A, autoinit */
	sbcmd(0x30);				/* stereo, 16 bit */
	sbcmd(count);
	sbcmd(count>>8);

	audio.active = 1;
	audio.tottime = todget(nil);
	contindma();
	iunlock(&blaster);
}

static int
ess1688reset(void)
{
	int i;

	outb(blaster.reset, 3);
	delay(1);			/* >3 υs */
	outb(blaster.reset, 0);
	delay(1);

	i = sbread();
	if(i != 0xAA) {
		print("#A: no response 0x%.2x\n", i);
		return 1;
	}

	if(sbcmd(0xC6)){		/* extended mode */
		print("#A: barf 3\n");
		return 1;
	}

	return 0;
}

static	void
ess1688startdma(void)
{
	ulong count;
	int speed, x;

	ilock(&blaster);
	dmaend(blaster.dma);

	if(audio.amode == Awrite)
		ess1688reset();
	if(audio.amode == Aread)
		sbcmd(0xD3);			/* speaker off */

	/*
	 * Set the speed.
	 */
	if(audio.amode == Aread)
		speed = audio.livol[Vspeed];
	else
		speed = audio.lovol[Vspeed];
	if(speed < 4000)
		speed = 4000;
	else if(speed > 48000)
		speed = 48000;

	if(speed > 22000)
		  x = 0x80|(256-(795500+speed/2)/speed);
	else
		  x = 128-(397700+speed/2)/speed;
	ess1688w(0xA1, x & 0xFF);

	speed = (speed * 9) / 20;
	x = 256 - 7160000 / (speed * 82);
	ess1688w(0xA2, x & 0xFF);

	if(audio.amode == Aread)
		ess1688w(0xB8, 0x0E);		/* A/D, autoinit */
	else
		ess1688w(0xB8, 0x04);		/* D/A, autoinit */
	x = ess1688r(0xA8) & ~0x03;
	ess1688w(0xA8, x|0x01);			/* 2 channels */
	ess1688w(0xB9, 2);			/* demand mode, 4 bytes per request */

	if(audio.amode == Awrite)
		ess1688w(0xB6, 0);
	ess1688w(0xB7, 0x71);
	ess1688w(0xB7, 0xBC);

	x = ess1688r(0xB1) & 0x0F;
	ess1688w(0xB1, x|0x50);
	x = ess1688r(0xB2) & 0x0F;
	ess1688w(0xB2, x|0x50);
	if(audio.amode == Awrite)
		sbcmd(0xD1);			/* speaker on */

	count = -Bufsize;
	ess1688w(0xA4, count & 0xFF);
	ess1688w(0xA5, (count>>8) & 0xFF);
	x = ess1688r(0xB8);
	ess1688w(0xB8, x|0x05);

	audio.active = 1;
	audio.tottime = todget(nil);
	contindma();
	iunlock(&blaster);
}

/*
 * if audio is stopped,
 * start it up again.
 */
static	void
pokeaudio(void)
{
	if(!audio.active)
		blaster.startdma();
}

static void
sb16intr(void)
{
	int stat, dummy;

	stat = mxread(0x82) & 7;		/* get irq status */
	if(stat) {
		dummy = 0;
		if(stat & 2) {
			ilock(&blaster);
			dummy = inb(blaster.clri16);
			audio.totcount += Bufsize;
			audio.tottime = todget(nil);
			contindma();
			iunlock(&blaster);
			audio.intr = 1;
			wakeup(&audio.vous);
		}
		if(stat & 1) {
			dummy = inb(blaster.clri8);
		}
		if(stat & 4) {
			dummy = inb(blaster.clri401);
		}
		USED(dummy);
	}
}

static void
ess1688intr(void)
{
	int dummy;

	if(audio.active){
		ilock(&blaster);
		audio.totcount += Bufsize;
		audio.tottime = todget(nil);
		contindma();
		dummy = inb(blaster.clri8);
		iunlock(&blaster);
		audio.intr = 1;
		wakeup(&audio.vous);
		USED(dummy);
	}
	else
		print("#A: unexpected ess1688 interrupt\n");
}

void
audiosbintr(void)
{
	/*
	 * Carrera interrupt interface.
	 */
	blaster.intr();
}

static void
pcaudiosbintr(Ureg*, void*)
{
	/*
	 * x86 interrupt interface.
	 */
	blaster.intr();
}

void
audiodmaintr(void)
{
/*	print("#A: dma interrupt\n");	/**/
}

static int
anybuf(void*)
{
	return audio.intr;
}

/*
 * wait for some output to get
 * empty buffers back.
 */
static void
waitaudio(void)
{

	audio.intr = 0;
	pokeaudio();
	tsleep(&audio.vous, anybuf, 0, 10*1000);
	if(audio.intr == 0) {
/*		print("#A: audio timeout\n");	/**/
		audio.active = 0;
		pokeaudio();
	}
}

static void
sbbufinit(void)
{
	int i;
	void *p;

	for(i=0; i<Nbuf; i++) {
		p = xspanalloc(Bufsize, CACHELINESZ, 64*1024);
		dcflush(p, Bufsize);
		audio.buf[i].virt = UNCACHED(uchar, p);
		audio.buf[i].phys = (ulong)PADDR(p);
	}
}

static	void
setempty(void)
{
	int i;

	ilock(&blaster);
	audio.empty.first = 0;
	audio.empty.last = 0;
	audio.full.first = 0;
	audio.full.last = 0;
	audio.current = 0;
	audio.filling = 0;
	for(i=0; i<Nbuf; i++)
		putbuf(&audio.empty, &audio.buf[i]);
	audio.totcount = 0;
	audio.tottime = 0LL;
	iunlock(&blaster);
}

static	void
resetlevel(void)
{
	int i;

	for(i=0; volumes[i].name; i++) {
		audio.lovol[i] = volumes[i].ilval;
		audio.rovol[i] = volumes[i].irval;
		audio.livol[i] = volumes[i].ilval;
		audio.rivol[i] = volumes[i].irval;
	}
}

static int
ess1688(ISAConf* sbconf)
{
	int i, major, minor;

	/*
	 * Try for ESS1688.
	 */
	sbcmd(0xE7);			/* get version */
	major = sbread();
	minor = sbread();
	if(major != 0x68 || minor != 0x8B){
		print("#A: model 0x%.2x 0x%.2x; not ESS1688 compatible\n", major, minor);
		return 1;
	}

	ess1688reset();

	switch(sbconf->irq){
	case 2:
	case 9:
		i = 0x50|(0<<2);
		break;
	case 5:
		i = 0x50|(1<<2);
		break;
	case 7:
		i = 0x50|(2<<2);
		break;
	case 10:
		i = 0x50|(3<<2);
		break;
	default:
		print("#A: bad ESS1688 irq %lud\n", sbconf->irq);
		return 1;
	}
	ess1688w(0xB1, i);

	switch(sbconf->dma){
	case 0:
		i = 0x50|(1<<2);
		break;
	case 1:
		i = 0xF0|(2<<2);
		break;
	case 3:
		i = 0x50|(3<<2);
		break;
	default:
		print("#A: bad ESS1688 dma %lud\n", sbconf->dma);
		return 1;
	}
	ess1688w(0xB2, i);

	ess1688reset();

	blaster.startdma = ess1688startdma;
	blaster.intr = ess1688intr;

	return 0;
}

static void
audioinit(void)
{

M bitsy/devµc.c => bitsy/devµc.c +1 -1
@@ 137,7 137,7 @@ int
		case BLtouch:
			if(len == 4) {
				if (samseq++ > 10)
					pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
					pentrackxy((p[2]<<8)|p[3], (p[0]<<8)|p[1]);
			} else {
				samseq = 0;
				pentrackxy(-1, -1);

M bitsy/fns.h => bitsy/fns.h +6 -0
@@ 10,6 10,12 @@ int	cistrncmp(char*, char*, int);
void	clockinit(void);
#define	coherence()
void	delay(int);
void	dmainit(void);
int		dmaalloc(int, int, int, int, int, void *);
void	dmafree(int);
ulong	dmastart(int, void *, int);
ulong	dmadone(int, ulong);
void	dmawait(int, ulong);
void	evenaddr(ulong);
void	flushmmu(void);
int		fpiarm(Ureg *ur);

M bitsy/sa1110dma.c => bitsy/sa1110dma.c +43 -21
@@ 39,7 39,7 @@ enum {

struct {
	Lock;
	Rendez	r;
	Rendez	r[6];
	int		channels;
} dma;



@@ 48,9 48,9 @@ struct dmaregs {
	ulong	dcsr_set;
	ulong	dcsr_clr;
	ulong	dcsr_rd;
	ulong	dstrtA;
	void*	dstrtA;
	ulong	dxcntA;
	ulong	dstrtB;
	void*	dstrtB;
	ulong	dxcntB;
} *dmaregs;



@@ 76,7 76,7 @@ dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *
			((burstsize==8)?1:0)<<BS |
			((datumsize==2)?1:0)<<DW |
			device<<DS |
			0x80000000 | (port << 6);
			0x80000000 | ((ulong)port << 6);
		return i;
	}
	unlock(&dma);


@@ 84,9 84,7 @@ dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *
}

void
dmafree(i) {
	int i;

dmafree(int i) {
	lock(&dma);
	dma.channels &= ~(1<<i);
	unlock(&dma);


@@ 94,38 92,62 @@ dmafree(i) {

static int
dmaready(void *dcsr) {

	return = *(ulong*)dcsr & ((1<<DONEA)|(1<<DONEB));
	return *(int*)dcsr & ((1<<DONEA)|(1<<DONEB));
}

int
ulong
dmastart(int chan, void *addr, int count) {
	ulong ab;

	while ((ab = dmaready(&dma[chan].dcsr_rd)) == 0) {
		sleep(&dma.r, dmaready, &dma[chan].dcsr_rd);
	while ((ab = dmaready(&dmaregs[chan].dcsr_rd)) == 0) {
		sleep(&dma.r[chan], dmaready, &dmaregs[chan].dcsr_rd);
	}
	cachewb();
	if (ab & (1<<DONEA)) {
		dma[chan].dcsr_clr |= 1<<DONEA | 1<<STARTA;
		dma[chan].dstrtA = addr;
		dma[chan].dxcntA = count-1;
		dma[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STARTA;
		dmaregs[chan].dcsr_clr |= 1<<DONEA | 1<<STRTA;
		dmaregs[chan].dstrtA = addr;
		dmaregs[chan].dxcntA = count-1;
		dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTA;
		return 1<<DONEA;
	} else {
		dma[chan].dcsr_clr |= 1<<DONEB | 1<<STARTB;
		dma[chan].dstrtB = addr;
		dma[chan].dxcntB = count-1;
		dma[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STARTB;
		dmaregs[chan].dcsr_clr |= 1<<DONEB | 1<<STRTB;
		dmaregs[chan].dstrtB = addr;
		dmaregs[chan].dxcntB = count-1;
		dmaregs[chan].dcsr_set |= 1<<RUN | 1<<IE | 1<<STRTB;
		return 1<<DONEB;
	}
}

ulong
dmadone(int chan, ulong op) {
	ulong dcsr;

	dcsr = dmaregs[chan].dcsr_rd;
	if (dcsr & 1<<ERROR)
		pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
	return dcsr & (op | 1<<ERROR);
}

void
dmawait(int chan, ulong op) {
	ulong dcsr;

	while (((dcsr = dmaregs[chan].dcsr_rd) & (op | 1<<ERROR)) == 0)
		sleep(&dma.r[chan], dmaready, &dmaregs[chan].dcsr_rd);
	if (dcsr & 1<<ERROR)
		pprint("DMA error, chan %d, status 0x%lux\n", chan, dcsr);
}

/*
 *  interrupt routine
 */
static void
dmaintr(Ureg*, void *x)
{
	for (i = 0; i < NDMA; i++) {
	int i;

	for (i = 0; i < NDMA; i++) {
		if (dmaregs[i].dcsr_rd & (1<<DONEA | 1<<DONEB | 1<<ERROR))
			wakeup(&dma.r[i]);
	}
}

M bitsy/screen.c => bitsy/screen.c +44 -34
@@ 16,9 16,9 @@
#define	MINX	8

enum {
	Wid		= 320,
	Ht		= 240,
	Pal0		= 0x2000,	/* 16-bit pixel data in active mode (12 in passive) */
	Wid		= 240,
	Ht		= 320,
	Pal0	= 0x2000,	/* 16-bit pixel data in active mode (12 in passive) */

	hsw		= 0x00,
	elw		= 0x0e,


@@ 126,25 126,25 @@ static Memimage xgscreen =
	0,					/* flags */
};

Memimage *gscreen;
Memimage *conscol;
Memimage *back;

Memsubfont	*memdefont;

struct{
	Point	pos;
	int	bwid;
}out;

Lock	screenlock;
Memimage *gscreen;
Memimage *conscol;
Memimage *back;

Point	ZP = {0, 0};
Memsubfont	*memdefont;

Lock		screenlock;

static Rectangle window;
static Point curpos;
static int h, w;
int drawdebug;
Point		ZP = {0, 0};
ushort		*vscreen;	/* virtual screen */
Rectangle	window;
Point		curpos;
int			h, w;
int			drawdebug;

static	ulong	rep(ulong, int);
static	void	screenwin(void);


@@ 164,8 164,8 @@ lcdinit(void)
{
	lcd->dbar1 = framebuf->palette;
	lcd->lccr3 = pcd<<PCD | 0<<ACB | 0<<API | 1<<VSP | 1<<HSP | 0<<PCP | 0<<OEP;
	lcd->lccr2 = (Ht-1)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
	lcd->lccr1 = (Wid-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
	lcd->lccr2 = (Wid-1)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
	lcd->lccr1 = (Ht-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
	lcd->lccr0 = 1<<LEN | 0<<CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<DPD | 0<<PDD;
}



@@ 197,7 197,7 @@ screeninit(void)
	framebuf = xspanalloc(sizeof *framebuf, 0x100, 0);
	/* the following works because main memory is direct mapped */

iprint("framebuf %lux\n", framebuf);
	vscreen = xalloc(sizeof(ushort)*Wid*Ht);

	framebuf->palette[0] = Pal0;



@@ 205,17 205,15 @@ iprint("framebuf %lux\n", framebuf);
	lcdinit();

	gscreen = &xgscreen;
	xgdata.bdata = (uchar *)framebuf->pixel;
	xgdata.bdata = (uchar *)vscreen;
	xgdata.ref = 1;

	i = 0;
	while (i < Wid*Ht*1/3)	framebuf->pixel[i++] = 0xf800;	/* red */
	while (i < Wid*Ht*2/3)	framebuf->pixel[i++] = 0xffff;	/* white */
	while (i < Wid*Ht*3/3)	framebuf->pixel[i++] = 0x001f;	/* blue */
	for(i = 0; i < Wid*Ht; i += Wid)
		framebuf->pixel[i] = 0xffff;	/* white */
	for(i = Wid-1; i < Wid*Ht; i += Wid)
		framebuf->pixel[i] = 0x001f;	/* blue */
	while (i < Wid*Ht*1/3)	vscreen[i++] = 0xf800;	/* red */
	while (i < Wid*Ht*2/3)	vscreen[i++] = 0xffff;	/* white */
	while (i < Wid*Ht*3/3)	vscreen[i++] = 0x001f;	/* blue */

	flushmemscreen(gscreen->r);

	memimageinit();
	memdefont = getmemdefont();


@@ 228,12 226,17 @@ iprint("framebuf %lux\n", framebuf);
}

void
flushmemscreen(Rectangle)
flushmemscreen(Rectangle r)
{
	/* no-op, screen is direct mapped */
	int x, y;

	for (x = r.min.x; x < r.max.x; x++)
		for (y = r.min.y; y < r.max.y; y++)
			framebuf->pixel[(x+1)*Ht-y-1] = vscreen[y*Wid+x];
	cachewb();
}

/* 
/*
 * export screen to devdraw
 */
uchar*


@@ 243,9 246,9 @@ attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
	*d = gscreen->depth;
	*chan = gscreen->chan;
	*width = gscreen->width;
	*softscreen = 0;
	*softscreen = 1;

	return (uchar*)gscreen->data->bdata;
	return (uchar*)vscreen;
}

void


@@ 304,6 307,7 @@ screenwin(void)
	Point p, q;
	char *greet;
	Memimage *orange;
	Rectangle r;

	memsetchan(gscreen, RGB16);



@@ 320,10 324,10 @@ screenwin(void)
	w = memdefont->info[' '].width;
	h = memdefont->height;

	window = Rect(4, 4, 320-4, 240-60);
	r = Rect(4, 4, Wid-4, Ht-60);

	memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP);
	window = insetrect(window, 4);
	memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP);
	window = insetrect(r, 4);
	memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP);

	memimagedraw(gscreen, Rect(window.min.x, window.min.y,


@@ 335,6 339,7 @@ screenwin(void)
	p = addpt(window.min, Pt(10, 0));
	q = memsubfontwidth(memdefont, greet);
	memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
	flushmemscreen(r);
	window.min.y += h+6;
	curpos = window.min;
	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;


@@ 374,6 379,7 @@ screenputc(char *buf)
		*xp++ = curpos.x;
		r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min);
		flushmemscreen(r);
		curpos.x += pos*w;
		break;
	case '\b':


@@ 382,6 388,7 @@ screenputc(char *buf)
		xp--;
		r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min);
		flushmemscreen(r);
		curpos.x = *xp;
		break;
	case '\0':


@@ 397,6 404,7 @@ screenputc(char *buf)
		r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min);
		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
		flushmemscreen(r);
		curpos.x += w;
	}
}


@@ 412,8 420,10 @@ scroll(void)
	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
	p = Pt(window.min.x, window.min.y+o);
	memimagedraw(gscreen, r, gscreen, p, nil, p);
	flushmemscreen(r);
	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
	memimagedraw(gscreen, r, back, ZP, nil, ZP);
	flushmemscreen(r);

	curpos.y -= o;
}

M pc/sdmylex.c => pc/sdmylex.c +4 -1
@@ 839,7 839,10 @@ mylexprobe(int port, int irq)
	 * it isn't a compatible board or it's broken.
	 * If the controller has SCAM set this can take a while.
	 */
	outb(port+Rcontrol, Rhard|Rsbus);
	if(getconf("*noscsireset") != nil)
		outb(port+Rcontrol, Rhard);
	else
		outb(port+Rcontrol, Rhard|Rsbus);
	for(timeo = 0; timeo < 100; timeo++){
		if(inb(port+Rstatus) == (Inreq|Hardy))
			break;

M port/devcons.c => port/devcons.c +6 -7
@@ 341,12 341,11 @@ echo(char *buf, int n)
			continue;
		}

		if(ctrlt != 2){
			ctrlt = 0;
		if(ctrlt != 2)
			continue;
		}

		/* ^T escapes */
		ctrlt = 0;
		switch(*p){
		case 's':
			dumpstack();


@@ 370,9 369,10 @@ echo(char *buf, int n)
			consdebug();
			return;
		case 'p':
			x = spllo();
			procdump();
			splx(x);
			//x = spllo();
			//procdump();
			//splx(x);
print("procdump temporarily disabled\n");
			return;
		case 'q':
			scheddump();


@@ 385,7 385,6 @@ echo(char *buf, int n)
			exit(0);
			break;
		}
		ctrlt = 0;
	}

	qproduce(kbdq, buf, n);