~kris/9p

9hist

e0713310098dcaefec6f6f18683381b39464558b — David du Colombier 25 years ago 5d2faf7
Plan 9 from Bell Labs 2001-06-21
6 files changed, 132 insertions(+), 443 deletions(-)

M bitsy/devµc.c
M bitsy/l.s
M bitsy/power.c
M bitsy/screen.c
M bitsy/trap.c
M port/lib.h
M bitsy/devµc.c => bitsy/devµc.c +12 -0
@@ 15,6 15,7 @@ enum{
	Qkbdin,
	Qled,
	Qversion,
	Qsuspend,

	/* command types */
	BLversion=	0,


@@ 57,6 58,7 @@ Dirtab µcdir[]={
	"kbdin",		{ Qkbdin, 0 },		0,	0664,
	"led",		{ Qled, 0 },			0,	0664,
	"version",		{ Qversion, 0 },		0,	0664,
	"suspend",	{ Qsuspend, 0 },	0,	0222,
};

static struct µcontroller


@@ 344,6 346,8 @@ static long
	char str[64];
	int i, j;
	Rune r;
	extern Rendez	powerr;
	extern ulong	powerflag;

	if(c->qid.path == Qkbdin){
		if(n >= sizeof(str))


@@ 356,6 360,14 @@ static long
		}
		return n;
	}
	if(c->qid.path == Qsuspend){
		if(!iseve())
			error(Eperm);
		if(strncmp(a, "suspend", 7) != 0)
			error(Ebadarg);
		powerflag = 1;
		wakeup(&powerr);
	}

	cmd = parsecmd(a, n);
	if(cmd->nf > 15)

M bitsy/l.s => bitsy/l.s +87 -79
@@ 48,20 48,20 @@ TEXT mmuinvalidateaddr(SB), $-4
TEXT cacheflush(SB), $-4
	/* splhi */
	MOVW	CPSR, R3
	ORR	$(PsrDirq), R3, R1
	ORR		$(PsrDirq), R3, R1
	MOVW	R1, CPSR

	/* write back any dirty data */
	MOVW	$0xe0000000,R0
	ADD	$(8*1024),R0,R1
	ADD		$(8*1024),R0,R1
_cfloop:
	MOVW.P	32(R0),R2
	CMP.S	R0,R1
	BGE	_cfloop
	
	/* drain write buffer and invalidate i cache contents */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x5), 0
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0x5), 0

	/* drain prefetch */
	MOVW	R0,R0						


@@ 78,12 78,12 @@ TEXT cachewb(SB), $-4
	/* write back any dirty data */
_cachewb:
	MOVW	$0xe0000000,R0
	ADD	$(8*1024),R0,R1
	ADD		$(8*1024),R0,R1
_cwbloop:
	MOVW.P	32(R0),R2
	CMP.S	R0,R1
	BGE	_cwbloop
	

	/* drain write buffer */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	RET


@@ 413,6 413,14 @@ TEXT spsrr(SB), $-4
	MOVW	SPSR, R0
	RET

TEXT getsp(SB), $-4
	MOVW	R13, R0
	RET

TEXT getlink(SB), $-4
	MOVW	R14, R0
	RET

TEXT getcallerpc(SB), $-4
	MOVW	0(R13), R0
	RET


@@ 448,81 456,81 @@ TEXT gotolabel(SB), $-4
TEXT setpowerlabel(SB), $-4
	MOVW	$power_resume+0(SB), R0
	/* svc */				/* power_resume[]: what */
	MOVW		R1, 0(R0)
	MOVW		R2, 4(R0)
	MOVW		R3, 8(R0)
	MOVW		R4, 12(R0)
	MOVW		R5, 16(R0)
	MOVW		R6, 20(R0)
	MOVW		R7, 24(R0)
	MOVW		R8, 28(R0)
	MOVW		R9, 32(R0)
	MOVW		R10,36(R0)
	MOVW		R11,40(R0)
	MOVW		R12,44(R0)
	MOVW		R13,48(R0)
	MOVW		R14,52(R0)
	MOVW		SPSR, R1
	MOVW		R1, 56(R0)
	MOVW		CPSR, R2
	MOVW		R2, 60(R0)
	MOVW	R1, 0(R0)
	MOVW	R2, 4(R0)
	MOVW	R3, 8(R0)
	MOVW	R4, 12(R0)
	MOVW	R5, 16(R0)
	MOVW	R6, 20(R0)
	MOVW	R7, 24(R0)
	MOVW	R8, 28(R0)
	MOVW	R9, 32(R0)
	MOVW	R10,36(R0)
	MOVW	R11,40(R0)
	MOVW	R12,44(R0)
	MOVW	R13,48(R0)
	MOVW	R14,52(R0)
	MOVW	SPSR, R1
	MOVW	R1, 56(R0)
	MOVW	CPSR, R2
	MOVW	R2, 60(R0)
	/* copro */
	MRC		CpMMU, 0, R3, C(CpDAC), C(0x0)
	MOVW		R3, 144(R0)
	MOVW	R3, 144(R0)
	MRC		CpMMU, 0, R3, C(CpTTB), C(0x0)
	MOVW		R3, 148(R0)
	MOVW	R3, 148(R0)
	MRC		CpMMU, 0, R3, C(CpControl), C(0x0)
	MOVW		R3, 152(R0)
	MOVW	R3, 152(R0)
	MRC		CpMMU, 0, R3, C(CpFSR), C(0x0)
	MOVW		R3, 156(R0)
	MOVW	R3, 156(R0)
	MRC		CpMMU, 0, R3, C(CpFAR), C(0x0)
	MOVW		R3, 160(R0)
	MOVW	R3, 160(R0)
	MRC		CpMMU, 0, R3, C(CpPID), C(0x0)
	MOVW		R3, 164(R0)
	MOVW	R3, 164(R0)
	/* irq */
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMirq), R3
	MOVW		R3, CPSR
	MOVW		SPSR, R11
	MOVW		R11, 64(R0)
	MOVW		R12, 68(R0)
	MOVW		R13, 72(R0)
	MOVW		R14, 76(R0)
	MOVW	R3, CPSR
	MOVW	SPSR, R11
	MOVW	R11, 64(R0)
	MOVW	R12, 68(R0)
	MOVW	R13, 72(R0)
	MOVW	R14, 76(R0)
	/* und */
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMund), R3
	MOVW		R3, CPSR
	MOVW		SPSR, R11
	MOVW		R11, 80(R0)
	MOVW		R12, 84(R0)
	MOVW		R13, 88(R0)
	MOVW		R14, 92(R0)
	MOVW	R3, CPSR
	MOVW	SPSR, R11
	MOVW	R11, 80(R0)
	MOVW	R12, 84(R0)
	MOVW	R13, 88(R0)
	MOVW	R14, 92(R0)
	/* abt */
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMabt), R3
	MOVW		R3, CPSR
	MOVW		SPSR, R11
	MOVW		R11, 96(R0)
	MOVW		R12, 100(R0)
	MOVW		R13, 104(R0)
	MOVW		R14, 108(R0)
	MOVW	R3, CPSR
	MOVW	SPSR, R11
	MOVW	R11, 96(R0)
	MOVW	R12, 100(R0)
	MOVW	R13, 104(R0)
	MOVW	R14, 108(R0)
	/* fiq */
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMfiq), R3
	MOVW		R3, CPSR
	MOVW		SPSR, R7
	MOVW		R7, 112(R0)
	MOVW		R8, 116(R0)
	MOVW		R9, 120(R0)
	MOVW		R10,124(R0)
	MOVW		R11,128(R0)
	MOVW		R12,132(R0)
	MOVW		R13,136(R0)
	MOVW		R14,140(R0)
	MOVW	R3, CPSR
	MOVW	SPSR, R7
	MOVW	R7, 112(R0)
	MOVW	R8, 116(R0)
	MOVW	R9, 120(R0)
	MOVW	R10,124(R0)
	MOVW	R11,128(R0)
	MOVW	R12,132(R0)
	MOVW	R13,136(R0)
	MOVW	R14,140(R0)
	/* done */
	MOVW		R2, CPSR
	MOVW		R1, SPSR
	MOVW		$0, R0
	MOVW	R2, CPSR
	MOVW	R1, SPSR
	MOVW	$0, R0
	RET

/* Entered after a resume from suspend state.


@@ 534,7 542,7 @@ TEXT sa1100_power_resume(SB), $-4
	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
	MOVW	R1, CPSR
	/* flush caches */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
	/* drain prefetch */
	MOVW	R0,R0						
	MOVW	R0,R0


@@ 548,22 556,22 @@ TEXT sa1100_power_resume(SB), $-4
	MOVW	56(R0), R1		/* R1: SPSR, R2: CPSR */
	MOVW	60(R0), R2
	/* copro */
	MOVW		148(R0), R3
	MOVW	148(R0), R3
	MCR		CpMMU, 0, R3, C(CpTTB), C(0x0)
	MOVW		144(R0), R3
	MOVW	144(R0), R3
	MCR		CpMMU, 0, R3, C(CpDAC), C(0x0)
	MOVW		152(R0), R3
	MOVW	152(R0), R3
	MCR		CpMMU, 0, R3, C(CpControl), C(0x0)
	MOVW		156(R0), R3
	MOVW	156(R0), R3
	MCR		CpMMU, 0, R3, C(CpFSR), C(0x0)
	MOVW		160(R0), R3
	MOVW	160(R0), R3
	MCR		CpMMU, 0, R3, C(CpFAR), C(0x0)
	MOVW		164(R0), R3
	MOVW	164(R0), R3
	MCR		CpMMU, 0, R3, C(CpPID), C(0x0)
	MCR		CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
	/* irq */
	BIC	$(PsrMask), R2, R3
	ORR	$(PsrDirq|PsrMirq), R3
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMirq), R3
	MOVW	R3, CPSR
	MOVW	64(R0), R11
	MOVW	68(R0), R12


@@ 571,8 579,8 @@ TEXT sa1100_power_resume(SB), $-4
	MOVW	76(R0), R14
	MOVW	R11, SPSR
	/* und */
	BIC	$(PsrMask), R2, R3
	ORR	$(PsrDirq|PsrMund), R3
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMund), R3
	MOVW	R3, CPSR
	MOVW	80(R0), R11
	MOVW	84(R0), R12


@@ 580,8 588,8 @@ TEXT sa1100_power_resume(SB), $-4
	MOVW	92(R0), R14
	MOVW	R11, SPSR
	/* abt */
	BIC	$(PsrMask), R2, R3
	ORR	$(PsrDirq|PsrMabt), R3
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMabt), R3
	MOVW	R3, CPSR
	MOVW	96(R0), R11
	MOVW	100(R0), R12


@@ 589,8 597,8 @@ TEXT sa1100_power_resume(SB), $-4
	MOVW	108(R0), R14
	MOVW	R11, SPSR
	/* fiq */
	BIC	$(PsrMask), R2, R3
	ORR	$(PsrDirq|PsrMfiq), R3
	BIC		$(PsrMask), R2, R3
	ORR		$(PsrDirq|PsrMfiq), R3
	MOVW	R3, CPSR
	MOVW	112(R0), R7
	MOVW	116(R0), R8


@@ 622,7 630,7 @@ TEXT sa1100_power_resume(SB), $-4
	MOVW	52(R0),R14
	RET
loop:
	B	loop
	B		loop

/* The first MCR instruction of this function needs to be on a cache-line
 * boundary; to make this happen, it will be copied (in trap.c).


@@ 639,7 647,7 @@ TEXT _doze(SB), $-4
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MCR     CpPWR, 0, R0, C(CpTest), C(0x2), 2
	MCR   	CpPWR, 0, R0, C(CpTest), C(0x2), 2
	MOVW	(R1), R0
	MCR     CpPWR, 0, R0, C(CpTest), C(0x8), 2
	MCR  	CpPWR, 0, R0, C(CpTest), C(0x8), 2
	RET

M bitsy/power.c => bitsy/power.c +26 -28
@@ 142,18 142,17 @@ deepsleep(void) {
	static int power_pl;

	power_pl = splhi();

	/* flush cache */
	cachewb();
	delay(500);

	/* Save state and setjmp */
	if (setpowerlabel()) {
		/* return from longjmp, turn everything back on */
		mmuinvalidate();
		mmuenable();
		cacheflush();
		trapresume();
		rs232power(1);
		irpower(1);
		audiopower(1);
		clockpower(1);
		gpclkregs->r0 = 1<<0;
		gpiocpy(gpioregs, &savedgpioregs);
		intrcpy(intrregs, &savedintrregs);


@@ 162,15 161,27 @@ deepsleep(void) {
			gpioregs->edgestatus = (1<<IRQgpio0);
			intrregs->icip = (1<<IRQgpio0);
		}
		uartpower(1);
		µcpower(1);
		screenpower(1);
		iprint("\nresuming execution\n");
//		dumpitall();
		delay(800);
		splx(power_pl);
		return;
	}
	/* Power down */
	iprint("entering suspend mode\n");
	gpiocpy(&savedgpioregs, gpioregs);
	intrcpy(&savedintrregs, intrregs);
	uartpower(0);
	delay(400);
	clockpower(0);
	irpower(0);
	audiopower(0);
	screenpower(0);
	µcpower(0);
	rs232power(0);
	sa1100_power_off();
	/* no return */
}


@@ 178,39 189,26 @@ deepsleep(void) {
void
powerkproc(void*)
{
	static int power_pl;
	void *xsp, *xlink;

	for(;;){
		while(powerflag == 0)
			sleep(&powerr, powerdown, 0);
		iprint("starting power down\n");
		powerflag = 0;

		power_pl = splhi();

//		irpower(0);
//		audiopower(0);
		screenpower(0);
		µcpower(0);
		clockpower(0);
		powerflag = 0;

		rs232power(0);
		uartpower(0);
		xsp = getsp();
		xlink = getlink();
		iprint("starting power down, sp = %lux, link = %lux\n", xsp, xlink);
		delay(1000);

		deepsleep();

		rs232power(1);
		uartpower(1);

		clockpower(1);
		µcpower(1);
		screenpower(1);
//		audiopower(1);
//		irpower(1);

		splx(power_pl);
		delay(1000);
		xsp = getsp();
		xlink = getlink();
		iprint("power restored, sp = %lux, link = %lux\n", xsp, xlink);

		iprint("power restored\n");
	}
}


M bitsy/screen.c => bitsy/screen.c +1 -333
@@ 151,336 151,4 @@ Point		curpos;
int			h, w;
int			drawdebug;

static	ulong	rep(ulong, int);
static	void	screenwin(void);
static	void	screenputc(char *buf);
static	void	bitsyscreenputs(char *s, int n);
static	void	scroll(void);

static void
lcdstop(void) {
	lcd->lccr0 &= ~(0<<LEN);	/* disable the LCD */
	while((lcd->lcsr & LDD) == 0)
		delay(10);
	lcdpower(0);
}

static void
lcdinit(void)
{
	/* the following line works because main memory is direct mapped */
	lcd->dbar1 = framebuf->palette;
	lcd->lccr3 = pcd<<PCD | 0<<ACB | 0<<API | 1<<VSP | 1<<HSP | 0<<PCP | 0<<OEP;
	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;
}

void
flipscreen(int ls) {
	if (ls == landscape)
		return;
	if (ls) {
		gscreen->r = Rect(0, 0, Ht, Wid);
		gscreen->clipr = gscreen->r;
		xgdata.bdata = (uchar *)framebuf->pixel;
	} else {
		gscreen->r = Rect(0, 0, Wid, Ht);
		gscreen->clipr = gscreen->r;
		xgdata.bdata = (uchar *)vscreen;
	}
	landscape = ls;
}

void
lcdtweak(Cmdbuf *cmd)
{
	if(cmd->nf < 4)
		return;
	if(*cmd->f[0] == 'h')
		lcd->lccr1 = ((Ht-16)<<PPL)
			| (atoi(cmd->f[1])<<HSW)
			| (atoi(cmd->f[2])<<ELW)
			| (atoi(cmd->f[3])<<BLW);
	if(*cmd->f[0] == 'v')
		lcd->lccr2 = ((Wid-1)<<LPP)
			| (atoi(cmd->f[1])<<VSW)
			| (atoi(cmd->f[2])<<EFW)
			| (atoi(cmd->f[3])<<BFW);
}

void
screenpower(int on)
{
	if (on == 0){
		memmove(savedpalette, framebuf->palette, sizeof framebuf->palette);
		blankscreen(1);
	} else {
		memmove(framebuf->palette, savedpalette, sizeof framebuf->palette);
		blankscreen(0);
	}
}

void
screeninit(void)
{
	int i;

	/* map the lcd regs into the kernel's virtual space */
	lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));;

	framebuf = xspanalloc(sizeof *framebuf, 0x100, 0);

	vscreen = xalloc(sizeof(ushort)*Wid*Ht);

	framebuf->palette[0] = Pal0;

	lcdpower(1);
	lcdinit();

	gscreen = &xgscreen;
	xgdata.ref = 1;
	i = 0;
	if (landscape) {
		xgdata.bdata = (uchar *)framebuf->pixel;
		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 */
	} else {
		xgdata.bdata = (uchar *)vscreen;
		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();

	out.pos.x = MINX;
	out.pos.y = 0;
	out.bwid = memdefont->info[' '].width;

	blanktime = 3;	/* minutes */

	screenwin();
	screenputs = bitsyscreenputs;
}

void
flushmemscreen(Rectangle r)
{
	int x, y;
	ulong start, end;

	if (landscape == 0) {
		if (r.min.x <   0) r.min.x = 0;
		if (r.max.x > Wid) r.max.x = Wid;
		if (r.min.y <   0) r.min.y = 0;
		if (r.max.y >  Ht) r.max.y = Ht;
		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-1-y] = gamma[vscreen[y*Wid+x]];
		start = (ulong)&framebuf->pixel[(r.min.x+1)*Ht-1-(r.max.y-1)];
		end = (ulong)&framebuf->pixel[(r.max.x-1+1)*Ht-1-(r.min.y)];
	} else {
		start = (ulong)&framebuf->pixel[r.min.y*Ht + r.min.x];
		end = (ulong)&framebuf->pixel[(r.max.y-1)*Ht + r.max.x - 1];
	}
	cachewbregion(start, end-start);
}

/*
 * export screen to devdraw
 */
uchar*
attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
{
	*r = gscreen->r;
	*d = gscreen->depth;
	*chan = gscreen->chan;
	*width = gscreen->width;
	*softscreen = (landscape == 0);

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

void
getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
{
	USED(p, pr, pg, pb);
}

int
setcolor(ulong p, ulong r, ulong g, ulong b)
{
	USED(p,r,g,b);
	return 0;
}

void
blankscreen(int blank)
{
	if (blank) {
		lcdpower(0);
	} else {
		lcdpower(1);
		lcdinit();
	}
}

static void
bitsyscreenputs(char *s, int n)
{
	int i;
	Rune r;
	char buf[4];

	if(!islo()) {
		/* don't deadlock trying to print in interrupt */
		if(!canlock(&screenlock))
			return;	
	}
	else
		lock(&screenlock);

	while(n > 0){
		i = chartorune(&r, s);
		if(i == 0){
			s++;
			--n;
			continue;
		}
		memmove(buf, s, i);
		buf[i] = 0;
		n -= i;
		s += i;
		screenputc(buf);
	}
	unlock(&screenlock);
}

static void
screenwin(void)
{
	Point p, q;
	char *greet;
	Memimage *orange;
	Rectangle r;

	memsetchan(gscreen, RGB16);

	back = memwhite;
	conscol = memblack;

	orange = allocmemimage(Rect(0,0,1,1), RGB16);
	orange->flags |= Frepl;
	orange->clipr = gscreen->r;
	orange->data->bdata[0] = 0x40;
	orange->data->bdata[1] = 0xfd;

	w = memdefont->info[' '].width;
	h = memdefont->height;

	r = insetrect(gscreen->r, 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,
			window.max.x, window.min.y+h+5+6), orange, ZP, nil, ZP);
	freememimage(orange);
	window = insetrect(window, 5);

	greet = " Plan 9 Console ";
	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;
}

static void
screenputc(char *buf)
{
	Point p;
	int w, pos;
	Rectangle r;
	static int *xp;
	static int xbuf[256];

	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
		xp = xbuf;

	switch(buf[0]) {
	case '\n':
		if(curpos.y+h >= window.max.y)
			scroll();
		curpos.y += h;
		screenputc("\r");
		break;
	case '\r':
		xp = xbuf;
		curpos.x = window.min.x;
		break;
	case '\t':
		p = memsubfontwidth(memdefont, " ");
		w = p.x;
		if(curpos.x >= window.max.x-4*w)
			screenputc("\n");

		pos = (curpos.x-window.min.x)/w;
		pos = 4-(pos%4);
		*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':
		if(xp <= xbuf)
			break;
		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':
		break;
	default:
		p = memsubfontwidth(memdefont, buf);
		w = p.x;

		if(curpos.x >= window.max.x-w)
			screenputc("\n");

		*xp++ = curpos.x;
		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;
	}
}

static void
scroll(void)
{
	int o;
	Point p;
	Rectangle r;

	o = 8*h;
	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;
}
static	ulong	rep(u

M bitsy/trap.c => bitsy/trap.c +3 -3
@@ 98,7 98,7 @@ trapinit(void)
void
trapdump(char *tag)
{
	print("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
	iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
		tag, intrregs->icip, intrregs->icmr, intrregs->iclr,
		intrregs->iccr, intrregs->icfp);
}


@@ 121,7 121,7 @@ warnregs(Ureg *ur, char *tag)
		ur->r8, ur->r9, ur->r10, ur->r11);
	seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
		ur->r12, ur->r13, ur->r14);
	print("%s", buf);
	iprint("%s", buf);
}

/*


@@ 764,7 764,7 @@ _dumpstack(Ureg *ureg)
		return;
	}

	print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
	iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
	i = 0;
	for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){
		v = *(ulong*)l;

M port/lib.h => port/lib.h +3 -0
@@ 74,6 74,9 @@ extern	int	print(char*, ...);
 */
extern	char*	cleanname(char*);
extern	ulong	getcallerpc(void*);
extern	void*	getsp(void);
extern	void*	getlink(void);

extern	long	strtol(char*, char**, int);
extern	ulong	strtoul(char*, char**, int);
extern	vlong	strtoll(char*, char**, int);