git: 9front

Download patch

ref: 72b7a3323632a99eee9fd9cc8cc6c0dd9233d112
parent: e17a66f7ebf080535e10042b208d5e73f398d649
parent: 126e88c194b8cb1e806520eda547df080cab2175
author: cinap_lenrek <cinap_lenrek@rei2.9hal>
date: Sun Nov 6 10:21:14 EST 2011

merge

--- a/sys/man/8/plan9.ini
+++ b/sys/man/8/plan9.ini
@@ -760,10 +760,10 @@
 .BR off .
 The first two specify differing levels of power saving;
 the third turns the monitor off completely.
-.SS \fL*vesashadow=\fP
-This enables the shadow framebuffer or softscreen of the VESA
-video driver. This is usefull on devices where access to
-the physical framebuffer is slow.
+.SS \fL*novesashadow=\fP
+This disables the shadow framebuffer or softscreen of the VESA
+video driver. This can improve performance on some graphics
+cards.
 .SS NVRAM
 .SS \fLnvram=\fIfile\fP
 .SS \fLnvrlen=\fIlength\fP
--- a/sys/src/9/omap4/arm.h
+++ b/sys/src/9/omap4/arm.h
@@ -21,6 +21,8 @@
 #define PsrDfiq		0x00000040		/* disable FIQ interrupts */
 #define PsrDirq		0x00000080		/* disable IRQ interrupts */
 
+#define PsrOK		0xF80F0000	/* user processes may touch these */
+
 #define PsrV		0x10000000		/* overflow */
 #define PsrC		0x20000000		/* carry/borrow/extend */
 #define PsrZ		0x40000000		/* zero */
--- a/sys/src/9/omap4/clock.c
+++ b/sys/src/9/omap4/clock.c
@@ -65,7 +65,7 @@
 }
 
 void
-clocktick(Ureg* ureg)
+clocktick(Ureg* ureg, void *)
 {
 	timerintr(ureg, 0);
 }
@@ -74,7 +74,7 @@
 localclockinit(void)
 {
 	local[2] = 0xFF06;
-	intenable(29, clocktick);
+	intenable(29, clocktick, nil);
 	timerset(0);
 }
 
--- a/sys/src/9/omap4/dat.h
+++ b/sys/src/9/omap4/dat.h
@@ -8,6 +8,7 @@
 typedef struct Confmem Confmem;
 typedef struct Conf Conf;
 typedef struct Proc Proc;
+typedef struct ISAConf ISAConf;
 typedef uvlong Tval;
 typedef void KMap;
 #define	VA(k)		((uintptr)(k))
@@ -142,3 +143,9 @@
 
 #define AOUT_MAGIC (E_MAGIC)
 #define NCOLOR 1
+
+struct ISAConf
+{
+	char *type;
+	ulong port, irq;
+};
--- a/sys/src/9/omap4/fns.h
+++ b/sys/src/9/omap4/fns.h
@@ -33,7 +33,9 @@
 void	links(void);
 void	globalclockinit(void);
 void	localclockinit(void);
-void	intenable(int, void(*)(Ureg*));
-void	setled(int, int);
+void	intenable(int, void(*)(Ureg*, void *), void *);
 void	uartinit(void);
-void	irqroute(int, void(*)(Ureg*));
+void	irqroute(int, void(*)(Ureg*, void *), void *);
+void	gpioinit(void);
+void	setgpio(int, int);
+void	gpiomode(int, int);
--- a/sys/src/9/omap4/l.s
+++ b/sys/src/9/omap4/l.s
@@ -51,7 +51,7 @@
 	EWAVE('n')
 
 	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
-	ORR	$(CpCmmu|CpChv|CpCsw), R1
+	ORR	$(CpCmmu|CpChv|CpCsw|CpCicache), R1
 	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
 
 	EWAVE(' ')
@@ -59,7 +59,7 @@
 	BL	_jumphi(SB)
 	
 	EWAVE('9')
-	
+
 	MOVW	$setR12(SB), R12
 	MOVW	$KTZERO, R13
 	
--- a/sys/src/9/omap4/main.c
+++ b/sys/src/9/omap4/main.c
@@ -147,6 +147,8 @@
 void
 main()
 {
+	extern int ehcidebug;
+
 	wave('f');
 	memset(edata, 0, end - edata);
 	wave('r');
@@ -153,6 +155,7 @@
 	machinit();
 	wave('o');
 	mmuinit();
+	gpioinit();
 	wave('m');
 	trapinit();
 	uartinit();
@@ -166,8 +169,9 @@
 	swapinit();
 	initseg();
 	quotefmtinstall();
-	chandevreset();
+	ehcidebug = 1;
 	links();
+	chandevreset();
 	userinit();
 	schedinit();
 }
--- a/sys/src/9/omap4/mem.h
+++ b/sys/src/9/omap4/mem.h
@@ -37,6 +37,7 @@
 #define	MAXSYSARG	7
 #define MAXMACH		2
 
+#define BI2BY		8
 #define BY2WD		4
 #define BY2V		8
 #define BY2PG		4096
--- a/sys/src/9/omap4/mkfile
+++ b/sys/src/9/omap4/mkfile
@@ -19,6 +19,7 @@
 	dev.$O\
 	edf.$O\
 	fault.$O\
+	gpio.$O\
 	mul64fract.$O\
 	rebootcmd.$O\
 	page.$O\
--- a/sys/src/9/omap4/mmu.c
+++ b/sys/src/9/omap4/mmu.c
@@ -9,7 +9,6 @@
 char iopages[NIOPAGES / 8];
 Lock iopagelock;
 uchar *periph;
-ulong *ledgpio;
 
 static int
 isfree(int i)
@@ -96,18 +95,9 @@
 }
 
 void
-setled(int n, int s)
-{
-	ulong *r;
-	
-	r = &ledgpio[0x190/4];
-	r[s != 0] = (1 << (7 + n));
-}
-
-void
 markidle(int n)
 {
-	setled(m->machno, !n);
+	setgpio(7 + m->machno, !n);
 }
 
 void
@@ -126,7 +116,6 @@
 		l2 += L2SIZ;
 	}
 	uart = vmap((ulong) uart, BY2PG);
-	ledgpio = vmap(0x4A310000, BY2PG);
 	periph = vmap(0x48240000, 2 * BY2PG);
 	memset(l1, 0, sizeof(ulong) * (IZERO / MiB));
 	l1[4095] = PRIVL2 | Coarse;
@@ -137,9 +126,6 @@
 	pl2[241] = FIRSTMACH | L2AP(Krw) | Small | Cached | Buffered;
 	flushtlb();
 	m = (Mach *) MACHADDR;
-	ledgpio[0x134/4] &= ~((1<<8)|(1<<7));
-	setled(0, 1);
-	setled(1, 1);
 }
 
 void
--- a/sys/src/9/omap4/panda
+++ b/sys/src/9/omap4/panda
@@ -22,7 +22,7 @@
 #	flash
 
 #	ether		netif
-#	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
+	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
 
 #	draw		screen
 #	dss
@@ -29,28 +29,27 @@
 #	mouse
 
 	uart
-#	usb
+	usb
 
 link
 #	archoma
-#	ethermedium
+	ethermedium
 #	flashigep
 #	loopbackmedium
-#	netdevmedium
+	netdevmedium
 
-## avoid tickling errata 3.1.1.183
-##	usbohci
-#	usbehci		usbehciomap
+#	usbohci
+	usbehci		usbehciomap
 
 ip
-#	tcp
-#	udp
-#	ipifc
-#	icmp
-#	icmp6
-#	ipmux
-#	gre
-#	esp
+	tcp
+	udp
+	ipifc
+	icmp
+	icmp6
+	ipmux
+	gre
+	esp
 
 misc
 #	rdb
--- a/sys/src/9/omap4/trap.c
+++ b/sys/src/9/omap4/trap.c
@@ -12,7 +12,8 @@
 
 extern uchar *periph;
 ulong *intc, *intd;
-void (*irqhandler[MAXMACH][256])(Ureg*);
+void (*irqhandler[MAXMACH][256])(Ureg *, void *);
+void *irqaux[MAXMACH][256];
 
 static char *trapname[] = {
 	"reset", /* wtf */
@@ -20,7 +21,6 @@
 	"supervisor call",
 	"prefetch abort",
 	"data abort",
-	"unknown trap",
 	"IRQ",
 	"FIQ",
 };
@@ -52,24 +52,28 @@
 }
 
 void
-intenable(int i, void (*fn)(Ureg *))
+intenable(int i, void (*fn)(Ureg *, void *), void *aux)
 {
 	intd[0x40 + (i / 32)] = 1 << (i % 32);
 	irqhandler[m->machno][i] = fn;
+	irqaux[m->machno][i] = aux;
 }
 
 void
-irqroute(int i, void (*fn)(Ureg *))
+irqroute(int i, void (*fn)(Ureg *, void *), void *aux)
 {
 	ulong x, y, z;
-	
-	intenable(32 + i, fn);
+
+	if(irqhandler[m->machno][i] != nil){
+		print("irqroute: irq already used: i=%d pc=%#p newfn=%#p oldfn=%#p\n", i, getcallerpc(&i), fn, irqhandler[m->machno][i]);
+		return;
+	}
+	intenable(32 + i, fn, aux);
 	x = intd[0x208 + i/4];
 	y = 0xFF << ((i%4) * 8);
 	z = 1 << (m->machno + (i%4) * 8);
 	x = (x & ~y) | z;
 	intd[0x208 + i/4] = x;
-//	intd[0x200/4 + (i+32)/32] = 1 << (i % 32);
 }
 
 void
@@ -128,12 +132,139 @@
 	tos->pid = up->pid;
 }
 
+int
+notify(Ureg *ureg)
+{
+	int l;
+	ulong s, sp;
+	Note *n;
+
+	if(up->procctl)
+		procctl(up);
+	if(up->nnote == 0)
+		return 0;
+	s = spllo();
+	qlock(&up->debug);
+	up->notepending = 0;
+	n = &up->note[0];
+	if(strncmp(n->msg, "sys:", 4) == 0){
+		l = strlen(n->msg);
+		if(l > ERRMAX-15)
+			l = ERRMAX-15;
+		sprint(n->msg + l, " pc=0x%.8lux", ureg->pc);
+	}
+	if(n->flag != NUser && (up->notified || up->notify == 0)){
+		if(n->flag == NDebug)
+			pprint("suicide: %s\n", n->msg);
+		qunlock(&up->debug);
+		pexit(n->msg, n->flag != NDebug);
+	}
+	if(up->notified){
+		qunlock(&up->debug);
+		splhi();
+		return 0;
+	}
+	if(!up->notify){
+		qunlock(&up->debug);
+		pexit(n->msg, n->flag != NDebug);
+	}
+	sp = ureg->sp;
+	sp -= 256 + sizeof(Ureg);
+	if(!okaddr((ulong)up->notify, 1, 0)
+	|| !okaddr(sp - ERRMAX - 4 * BY2WD, sizeof(Ureg) + ERRMAX + 4 * BY2WD, 1)){
+		qunlock(&up->debug);
+		pprint("suicide: bad address in notify\n");
+		pexit("Suicide", 0);
+	}
+	
+	memmove((void *) sp, ureg, sizeof(Ureg));
+	((void**)sp)[-1] = up->ureg;
+	up->ureg = (void *) sp;
+	sp -= BY2WD + ERRMAX;
+	memmove((void *) sp, up->note[0].msg, ERRMAX);
+	sp -= 3 * BY2WD;
+	((ulong*)sp)[2] = sp + 3 * BY2WD;
+	((Ureg**)sp)[1] = up->ureg;
+	((ulong*)sp)[0] = 0;
+	memset(ureg, 0, sizeof *ureg);
+	ureg->psr = PsrMusr;
+	ureg->sp = sp;
+	ureg->pc = (ulong) up->notify;
+	up->notified = 1;
+	up->nnote--;
+	memmove(&up->lastnote, &up->note[0], sizeof(Note));
+	memmove(&up->note[0], &up->note[1], up->nnote * sizeof(Note));
+	
+	qunlock(&up->debug);
+	splx(s);
+	return 1;
+}
+
 void
+noted(Ureg *ureg, ulong arg0)
+{
+	Ureg *nureg;
+	ulong oureg, sp;
+	
+	qlock(&up->debug);
+	if(arg0 != NRSTR && !up->notified){
+		qunlock(&up->debug);
+		pprint("call to noted() when not notified\n");
+		pexit("Suicide", 0);
+	}
+	up->notified = 0;
+	
+	nureg = up->ureg;
+	oureg = (ulong) nureg;
+	if(!okaddr((ulong) oureg - BY2WD, BY2WD + sizeof(Ureg), 0)){
+		qunlock(&up->debug);
+		pprint("bad ureg in noted or call to noted when not notified\n");
+		pexit("Suicide", 0);
+	}
+	nureg->psr = nureg->psr & PsrOK | ureg->psr & ~PsrOK;
+	memmove(ureg, nureg, sizeof(Ureg));
+
+	if(!okaddr(nureg->pc, 1, 0) && !okaddr(nureg->sp, BY2WD, 0)
+	&& (arg0 == NCONT || arg0 == NRSTR || arg0 == NSAVE)){
+		qunlock(&up->debug);
+		pprint("suicide: trap in noted\n");
+		pexit("Suicide", 0);
+	}
+	switch(arg0){
+	case NCONT:
+	case NRSTR:
+		up->ureg = (Ureg *) (*(ulong *)(oureg - BY2WD));
+		qunlock(&up->debug);
+		break;
+
+	case NSAVE:
+		qunlock(&up->debug);
+		sp = oureg - 4 * BY2WD - ERRMAX;
+		splhi();
+		ureg->sp = sp;
+		((ulong *) sp)[1] = oureg;
+		((ulong *) sp)[0] = 0;
+		break;
+	
+	default:
+		pprint("unknown noted arg 0x%lux\n", arg0);
+		up->lastnote.flag = NDebug;
+		/* fallthrough */
+	
+	case NDFLT:
+		qunlock(&up->debug);
+		if(up->lastnote.flag == NDebug)
+			pprint("suicide: %s\n", up->lastnote.msg);
+		pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
+	}
+}
+
+void
 trap(Ureg *ureg)
 {
 	int user, intn, x;
 	char buf[ERRMAX];
-	
+
 	user = (ureg->psr & PsrMask) == PsrMusr;
 	if(user){
 		fillureguser(ureg);
@@ -149,10 +280,13 @@
 		x = intc[3];
 		intn = x & 0x3FF;
 		if(irqhandler[m->machno][intn] != nil)
-			irqhandler[m->machno][intn](ureg);
+			irqhandler[m->machno][intn](ureg, irqaux[m->machno][intn]);
+		else
+			print("unexpected interrupt %d\n", intn);
 		intc[4] = x;
 		if(intn != 29)
 			preempted();
+		splhi();
 		if(up && up->delaysched && (intn == 29)){
 			sched();
 			splhi();
@@ -170,6 +304,8 @@
 		}
 	}
 	if(user){
+		if(up->procctl || up->nnote)
+			notify(ureg);
 		updatetos();
 		up->dbgreg = nil;
 	}
@@ -193,7 +329,6 @@
 	}
 	scall = ureg->r0;
 	up->scallnr = scall;
-//	print("%s\n", sysctab[scall]);
 	spllo();
 
 	sp = ureg->sp;
@@ -224,8 +359,16 @@
 		procctl(up);
 		splx(s);
 	}
+
 	up->insyscall = 0;
 	up->psstate = nil;
+
+	if(scall == NOTED)
+		noted(ureg, *(ulong *)(sp + BY2WD));
+	if(scall != RFORK && (up->procctl || up->nnote)){
+		splhi();
+		notify(ureg);
+	}
 	splhi();
 	if(up->delaysched){
 		sched();
--- a/sys/src/9/omap4/uartomap.c
+++ b/sys/src/9/omap4/uartomap.c
@@ -24,20 +24,23 @@
 static void
 omapkick(Uart *u)
 {
+	int x;
+	
+	x = splhi();
 	while((uart[17] & 1) == 0){
 		if(u->op >= u->oe)
-			if(uartstageoutput(u) == 0)
+			if(uartstageoutput(u) == 0){
+				uart[1] &= ~(1<<1);
 				break;
+			}
 		uart[0] = *u->op++;
-	}
-	if(u->op < u->oe || qlen(u->oq))
 		uart[1] |= (1<<1);
-	else
-		uart[1] &= ~(1<<1);
+	}
+	splx(x);
 }
 
 void
-omapinterrupt(Ureg *)
+omapinterrupt(Ureg *, void *)
 {
 	ulong st;
 
@@ -45,6 +48,12 @@
 	if((st & 1) != 0)
 		return;
 	switch((st >> 1) & 0x1F){
+	case 0:
+	case 16:
+		puart.cts = (uart[6] & (1<<4)) != 0;
+		puart.dsr = (uart[6] & (1<<5)) != 0;
+		puart.dcd = (uart[6] & (1<<7)) != 0;
+		break;
 	case 1:
 		uartkick(&puart);
 		break;
@@ -54,24 +63,165 @@
 			uartrecv(&puart, uart[0]);
 		break;
 	default:
-		print("unknown UART interrupt %d\n", (st>>1) & 0x1F);
+		print("unknown UART interrupt %uld\n", (st>>1) & 0x1F);
 		uartkick(&puart);
 	}
 }
 
 static void
-omapenable(Uart *, int ie)
+omapenable(Uart *u, int ie)
 {
 	while(uart[5] & (1<<6))
 		;
 	if(ie){
-		irqroute(74, omapinterrupt);
+		irqroute(74, omapinterrupt, u);
 		uart[1] = (1<<0);
-	//	uart[0x10] |= (1<<3);
 	}
 }
 
+static void
+omapdisable(Uart *)
+{
+	uart[1] = 0;
+}
+
+static void
+omapdobreak(Uart *, int ms)
+{
+	if(ms <= 0)
+		ms = 200;
+	
+	uart[3] |= (1<<6);
+	tsleep(&up->sleep, return0, 0, ms);
+	uart[3] &= ~(1<<6);
+}
+
 static int
+omapbaud(Uart *u, int baud)
+{
+	int val;
+
+	if(baud <= 0)
+		return -1;
+
+	val = (48000000 / 16) / baud;
+	uart[3] |= (1<<7);
+	uart[0] = val & 0xFF;
+	uart[1] = (val >> 8) & 0xFF;
+	uart[3] &= ~(1<<7);
+	u->baud = baud;
+	return 0;
+}
+
+static int
+omapbits(Uart *u, int bits)
+{
+	if(bits < 5 || bits > 8)
+		return -1;
+	
+	uart[3] = (uart[3] & ~3) | (bits - 5);
+	u->bits = bits;
+	return 0;
+}
+
+static int
+omapstop(Uart *u, int stop)
+{
+	if(stop < 1 || stop > 2)
+		return -1;
+	
+	uart[3] &= ~4;
+	if(stop == 2)
+		uart[3] |= 4;
+	u->stop = stop;
+	return 0;
+}
+
+static int
+omapparity(Uart *u, int parity)
+{
+	uart[3] &= ~0x38;
+	switch(parity){
+	case 'n':
+		break;
+	case 'o':
+		uart[3] |= (1<<3);
+	case 'e':
+		uart[3] |= (1<<3) | (1<<4);
+		break;
+	default:
+		return -1;
+	}
+	u->parity = parity;
+	return 0;
+}
+
+static void
+omapmodemctl(Uart *u, int on)
+{
+	if(on){
+		u->modem = 1;
+		u->cts = (uart[6] & (1<<4)) != 0;
+		uart[1] |= (1<<6);
+	}else{
+		u->modem = 0;
+		u->cts = 1;
+	}
+}
+
+static void
+omaprts(Uart *, int i)
+{
+	uart[4] = (uart[4] & ~2) | (i << 1);
+}
+
+static void
+omapdtr(Uart *, int i)
+{
+	uart[4] = (uart[4] & ~1) | i;
+}
+
+static long
+omapstatus(Uart* u, void* buf, long n, long offset)
+{
+	char *p;
+	ulong msr;
+
+	msr = uart[6];
+	p = malloc(READSTR);
+	snprint(p, READSTR,
+		"b%d c%d d%d e%d l%d m%d p%c r%d s%d\n"
+		"dev(%d) type(%d) framing(%d) overruns(%d) "
+		"berr(%d) serr(%d)%s%s%s%s\n",
+
+		u->baud,
+		u->hup_dcd, 
+		u->dsr,
+		u->hup_dsr,
+		u->bits,
+		u->modem,
+		u->parity,
+		(uart[3] & 2) != 0,
+		u->stop,
+
+		u->dev,
+		u->type,
+		u->ferr,
+		u->oerr,
+		u->berr,
+		u->serr,
+		(msr & (1<<4)) ? " cts": "",
+		(msr & (1<<5)) ? " dsr": "",
+		(msr & (1<<7)) ? " dcd": "",
+		(msr & (1<<6)) ? " ri": ""
+	);
+	n = readstr(offset, buf, n, p);
+	free(p);
+
+	return n;
+}
+
+static int
 omapgetc(Uart *)
 {
 	while((uart[5] & 1) == 0)
@@ -87,11 +237,6 @@
 	uart[0] = c;
 }
 
-static void
-omaprts(Uart *, int)
-{
-}
-
 PhysUart omapphysuart = {
 	.name = "omap4430 uart",
 	.pnp = omappnp,
@@ -98,8 +243,16 @@
 	.getc = omapgetc,
 	.putc = omapputc,
 	.enable = omapenable,
+	.disable = omapdisable,
 	.kick = omapkick,
 	.rts = omaprts,
+	.parity = omapparity,
+	.baud = omapbaud,
+	.bits = omapbits,
+	.stop = omapstop,
+	.modemctl = omapmodemctl,
+	.dtr = omapdtr,
+	.status = omapstatus,
 };
 
 void
--- a/sys/src/9/pc/etherbcm.c
+++ b/sys/src/9/pc/etherbcm.c
@@ -425,7 +425,7 @@
 	iunlock(&ctlr->imlock);
 }
 
-static void
+static int
 bcminit(Ether *edev)
 {
 	ulong i, j;
@@ -436,7 +436,12 @@
 	/* initialization procedure according to the datasheet */
 	csr32(ctlr, MiscHostCtl) |= MaskPCIInt | ClearIntA;
 	csr32(ctlr, SwArbitration) |= SwArbitSet1;
-	while((csr32(ctlr, SwArbitration) & SwArbitWon1) == 0);
+	for(i = 0; i < 10000 && (csr32(ctlr, SwArbitration) & SwArbitWon1) == 0; i++)
+		microdelay(100);
+	if(i == 10000){
+		iprint("bcm: arbiter failed to respond\n");
+		return -1;
+	}
 	csr32(ctlr, MemArbiterMode) |= Enable;
 	csr32(ctlr, MiscHostCtl) |= IndirectAccessEnable | EnablePCIStateRegister | EnableClockControlRegister;
 	csr32(ctlr, MemoryWindow) = 0;
@@ -452,7 +457,12 @@
 	csr32(ctlr, ModeControl) |= ByteWordSwap;
 	csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortGMII;
 	microdelay(40000);
-	while(mem32(ctlr, 0xB50) != 0xB49A89AB);
+	for(i = 0; i < 100000 && mem32(ctlr, 0xB50) != 0xB49A89AB; i++)
+		microdelay(100);
+	if(i == 100000){
+		iprint("bcm: chip failed to reset\n");
+		return -1;
+	}
 	csr32(ctlr, TLPControl) |= (1<<25) | (1<<29);
 	memset(ctlr->status, 0, 20);
 	csr32(ctlr, DMARWControl) = (csr32(ctlr, DMARWControl) & DMAWatermarkMask) | DMAWatermarkValue;
@@ -462,10 +472,20 @@
 	csr32(ctlr, MBUFHighWatermark) = 0x60;
 	csr32(ctlr, LowWatermarkMaximum) = (csr32(ctlr, LowWatermarkMaximum) & LowWatermarkMaxMask) | LowWatermarkMaxValue;
 	csr32(ctlr, BufferManMode) |= Enable | Attn;
-	while((csr32(ctlr, BufferManMode) & Enable) == 0);
+	for(i = 0; i < 100 && (csr32(ctlr, BufferManMode) & Enable) == 0; i++)
+		microdelay(100);
+	if(i == 100){
+		iprint("bcm: buffer manager failed to start\n");
+		return -1;
+	}
 	csr32(ctlr, FTQReset) = -1;
 	csr32(ctlr, FTQReset) = 0;
-	while(csr32(ctlr, FTQReset));
+	for(i = 0; i < 1000 && csr32(ctlr, FTQReset) != 0; i++)
+		microdelay(100);
+	if(i == 1000){
+		iprint("bcm: ftq failed to reset\n");
+		return -1;
+	}
 	csr32(ctlr, ReceiveBDHostAddr) = 0;
 	csr32(ctlr, ReceiveBDHostAddr + 4) = PADDR(ctlr->recvprod);
 	csr32(ctlr, ReceiveBDFlags) = RecvProdRingLen << 16;
@@ -503,7 +523,12 @@
 	csr32(ctlr, SendInitiatorMask) = 0xFFFFFF;
 	csr32(ctlr, SendInitiatorConfiguration) |= SendStats;
 	csr32(ctlr, HostCoalescingMode) = 0;
-	while(csr32(ctlr, HostCoalescingMode) != 0);
+	for(i = 0; i < 200 && csr32(ctlr, HostCoalescingMode) != 0; i++)
+		microdelay(100);
+	if(i == 200){
+		iprint("bcm: host coalescing engine failed to stop\n");
+		return -1;
+	}
 	csr32(ctlr, HostCoalescingRecvTicks) = 150;
 	csr32(ctlr, HostCoalescingSendTicks) = 150;
 	csr32(ctlr, RecvMaxCoalescedFrames) = 10;
@@ -539,7 +564,12 @@
 	csr32(ctlr, MIMode) = 0xC0000;
 	microdelay(40);
 	miiw(ctlr, PhyControl, 1<<15);
-	while(miir(ctlr, PhyControl) & (1<<15));
+	for(i = 0; i < 1000 && miir(ctlr, PhyControl) & (1<<15); i++)
+		microdelay(100);
+	if(i == 1000){
+		iprint("bcm: PHY failed to reset\n");
+		return -1;
+	}
 	miiw(ctlr, PhyAuxControl, 2);
 	miir(ctlr, PhyIntStatus);
 	miir(ctlr, PhyIntStatus);
@@ -554,6 +584,7 @@
 	csr32(ctlr, ReceiveRulesConfiguration) = 1 << 3;
 	csr32(ctlr, MSIMode) |= Enable;
 	csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA);
+	return 0;
 }
 
 static void
@@ -637,6 +668,7 @@
 {
 	Ctlr *ctlr;
 	
+again:
 	if(bcmhead == nil)
 		bcmpci();
 	
@@ -664,7 +696,10 @@
 	edev->arg = edev;
 	edev->mbps = 1000;
 	
-	bcminit(edev);
+	if(bcminit(edev) < 0){
+		edev->ctlr = nil;
+		goto again;
+	}
 	return 0;
 }
 
--- a/sys/src/9/pc/vgavesa.c
+++ b/sys/src/9/pc/vgavesa.c
@@ -162,10 +162,10 @@
 	vgalinearaddr(scr, paddr, size);
 	if(scr->apsize)
 		addvgaseg("vesascreen", scr->paddr, scr->apsize);
-	if(getconf("*vesashadow")){
-		hardscreen = scr->vaddr;
-		scr->paddr = scr->apsize = 0;
-	}
+	if(getconf("*novesashadow"))
+		return;
+	hardscreen = scr->vaddr;
+	scr->paddr = scr->apsize = 0;
 }
 
 static void
--- a/sys/src/cmd/5l/asm.c
+++ b/sys/src/cmd/5l/asm.c
@@ -77,6 +77,11 @@
 	curtext = P;
 	switch(HEADTYPE) {
 	case 0:
+		if(debug['P']){
+			OFFSET = rnd(textsize, INITRND);
+			seek(cout, OFFSET, 0);
+			break;
+		}
 	case 1:
 	case 2:
 	case 5:
--