Browse Source

Plan 9 from Bell Labs 2010-10-28

David du Colombier 13 years ago
parent
commit
71272542b6

+ 2 - 0
lib/face/48x48x4/.dict

@@ -1,4 +1,5 @@
 FACEDOM/glenda g/glenda.1
+9grid.fr/djc d/djc.1
 acm.org/wkj w/wkj.1
 acsnet/piers p/piers.1
 aes.org/unknown u/unknown.aes.org
@@ -99,6 +100,7 @@ fas.harvard.edu/rcox r/rsc.1
 fas.harvard.edu/wjosephs w/wkj.1
 free.fr/xigh x/xigh.1
 ghs.com/unknown u/unknown.ghs.com
+gmail.com/0intro d/djc.1
 gmail.com/howard.trickey h/howard.1
 gmail.com/mirtchovski a/andrey.1
 gmail.com/presotto p/presotto.1

BIN
lib/face/48x48x4/d/djc.1


+ 2 - 2
sys/src/9/omap/beagle

@@ -27,7 +27,7 @@ dev
 	dss
 	kbmap
 	kbin
-#	mouse
+	mouse
 
 	uart
 #	usb
@@ -59,7 +59,7 @@ misc
 	rdb
 	coproc
 	dma
-#	mouse
+	mouse
 #	sdaoe		sdscsi
 	softfpu
 	syscall

+ 12 - 12
sys/src/9/omap/devdss.c

@@ -24,7 +24,7 @@ enum {
 };
 
 extern OScreen oscreen;
-extern OScreen settings[];
+extern Settings settings[];
 extern Omap3fb *framebuf;
 
 static QLock dsslck;
@@ -86,20 +86,20 @@ getchans(char *p)
 }
 
 static long
-settingswrite(OScreen *setting, char *p)
+settingswrite(OScreen *scr, char *p)
 {
 	if (strncmp("800x600", p, 7) == 0) {
 		p += 7;
-		*setting = settings[Res800x600];
+		scr->settings = &settings[Res800x600];
 	} else if (strncmp("1024x768", p, 8) == 0) {
 		p += 8;
-		*setting = settings[Res1024x768];
+		scr->settings = &settings[Res1024x768];
 	} else if (strncmp("1280x1024", p, 9) == 0) {
 		p += 9;
-		*setting = settings[Res1280x1024];
+		scr->settings = &settings[Res1280x1024];
 	} else
 		return -1;
-	setting->chan = getchans(p);
+	scr->settings->chan = getchans(p);
 	return 1;
 }
 
@@ -108,27 +108,27 @@ screenread(Chan *c, void *a, long n, vlong off)
 {
 	int len, depth;
 	char *p;
-	OScreen *scr;
+	Settings *set;
 
 	switch ((ulong)c->qid.path) {
 	case Qdir:
 		return devdirread(c, a, n, dsstab, nelem(dsstab), devgen);
 	case Qdss:
-		scr = &oscreen;
+		set = oscreen.settings;
 		p = malloc(READSTR);
 		if(waserror()){
 			free(p);
 			nexterror();
 		}
-		if (scr->chan == RGB16)
+		if (set->chan == RGB16)
 			depth = 16;
-		else if (scr->chan == RGB24)
+		else if (set->chan == RGB24)
 			depth = 24;
 		else
 			depth = 0;
 		len = snprint(p, READSTR, "size %dx%dx%d @ %d Hz\n"
-			"addr %#p size %ud\n", scr->wid, scr->ht, depth,
-			scr->freq, framebuf, sizeof *framebuf);
+			"addr %#p size %ud\n", set->wid, set->ht, depth,
+			set->freq, framebuf, sizeof *framebuf);
 		USED(len);
 		n = readstr(off, a, n, p);
 		poperror();

+ 1 - 1
sys/src/9/omap/mkfile

@@ -110,7 +110,7 @@ fpi.$O fpiarm.$O fpimem.$O: fpi.h
 l.$O lexception.$O lproc.$O mmu.$O: arm.s arm.h mem.h
 l.$O rebootcode.$O: cache.v7.s
 main.$O: errstr.h init.h reboot.h
-devmouse.$O mouse.$O screen.$O: screen.h
+devdss.$O devmouse.$O mouse.$O screen.$O: screen.h
 devusb.$O: usb.h
 usbehci.$O usbohci.$O usbuhci.$O: usb.h usbehci.h uncached.h
 

+ 199 - 27
sys/src/9/omap/screen.c

@@ -42,8 +42,6 @@ enum {
 
 	Tft	= 0x60,
 
-//	Pcd	= HOWMANY(432000, pixelclock),	/* a bit too magic */
-
 	Loadmode = 2 << 1,
 	Fifosize = 0x400,
 
@@ -160,13 +158,11 @@ Cursor	arrow = {
 };
 
 OScreen oscreen;
-OScreen settings[] = {
-[Res800x600]   { 0,  800,  600, 60, RGB16,  40000,
-		 	 87<<20, 39<<8, 127, 23<<20, 1<<8, 4, },
-[Res1024x768]  { 0, 1024,  768, 60, RGB16,  65000,
-			159<<20, 23<<8, 135, 29<<20, 3<<8, 6, },
-[Res1280x1024] { 0, 1280, 1024, 60, RGB16, 108000,
-			247<<20, 47<<8, 111, 38<<20, 1<<8, 3, },
+Settings settings[] = {
+[Res800x600]   {  800,  600, 60, RGB16,  40000,	 88, 40, 128,	23, 1, 5, },
+[Res1024x768]  { 1024,  768, 60, RGB16,  65000,	160, 24, 136,	29, 3, 7, },
+[Res1280x1024] { 1280, 1024, 60, RGB16, 108000,	248, 48, 112,	38, 1, 4, },
+[Res1400x1050] { 1400, 1050, 50, RGB16, 108000, 248, 48, 112,	38, 1, 4, }, // TODO
 };
 Omap3fb *framebuf;
 Memimage *gscreen;
@@ -209,6 +205,24 @@ static	ulong	rep(ulong, int);
 static	void	screenputc(char *buf);
 static	void	screenwin(void);
 
+/*
+ * Software cursor. 
+ */
+int	swvisible;	/* is the cursor visible? */
+int	swenabled;	/* is the cursor supposed to be on the screen? */
+Memimage*	swback;	/* screen under cursor */
+Memimage*	swimg;	/* cursor image */
+Memimage*	swmask;	/* cursor mask */
+Memimage*	swimg1;
+Memimage*	swmask1;
+
+Point	swoffset;
+Rectangle	swrect;	/* screen rectangle in swback */
+Point	swpt;	/* desired cursor location */
+Point	swvispt;	/* actual cursor location */
+int	swvers;	/* incremented each time cursor image changes */
+int	swvisvers;	/* the version on the screen */
+
 static void
 lcdoff(void)
 {
@@ -235,9 +249,13 @@ dssstart(void)
 	coherence();
 }
 
+/* see spruf98i §15.6.7.4.2 */
 static void
 configdispc(void)
 {
+	Settings *sp;
+
+	sp = oscreen.settings;
 	dss->ctrl &= 0x78;		/* choose dss clock */
 	dispc->sysconf = Midlemode | Sidlemode | EnableWakeup | Autoidle;
 	dispc->config = Loadmode;
@@ -249,13 +267,15 @@ configdispc(void)
 	dispc->transcolor[0] = 0;	/* set transparency to full */
 	dispc->transcolor[1] = 0;
 
-	dispc->timing_h = oscreen.hbp | oscreen.hfp | oscreen.hsw;
-	dispc->timing_v = oscreen.vbp | oscreen.vfp | oscreen.vsw;
+	dispc->timing_h = (sp->hbp-1) << 20 | (sp->hfp-1) << 8 |
+			(sp->hsw-1);
+	dispc->timing_v = sp->vbp << 20 | sp->vfp << 8 |
+			(sp->vsw-1);
 
 	dispc->pol_req = Ipc | Ihs | Ivs | Acb;
-	dispc->divisor = 1 << 16 | HOWMANY(432000, oscreen.pixelclock);
+	dispc->divisor = 1 << 16 | HOWMANY(432000, sp->pixelclock);
 
-	dispc->lcdsize = (oscreen.ht - 1) << 16 | (oscreen.wid - 1);
+	dispc->lcdsize = (sp->ht - 1) << 16 | (sp->wid - 1);
 	coherence();
 
 	dispc->base[0] = PADDR(framebuf->pixel);
@@ -263,7 +283,7 @@ configdispc(void)
 
 	dispc->pos = 0;			/* place screen in the left corner */
 	/* use the whole screen */
-	dispc->size = (oscreen.ht - 1) << 16 | (oscreen.wid - 1);
+	dispc->size = (sp->ht - 1) << 16 | (sp->wid - 1);
 
 	/* what mode does plan 9 use for fb? */
 	dispc->attrib = Burstsize | Format | Gfxenable;
@@ -326,25 +346,174 @@ screenpower(int on)
 	blankscreen(on == 0);
 }
 
+/*
+ * called with drawlock locked for us, most of the time.
+ * kernel prints at inopportune times might mean we don't
+ * hold the lock, but memimagedraw is now reentrant so
+ * that should be okay: worst case we get cursor droppings.
+ */
+void
+swcursorhide(void)
+{
+	if(swvisible == 0)
+		return;
+	if(swback == nil)
+		return;
+	swvisible = 0;
+	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
+	flushmemscreen(swrect);
+}
+
+void
+swcursoravoid(Rectangle r)
+{
+	if(swvisible && rectXrect(r, swrect))
+		swcursorhide();
+}
+
+void
+swcursordraw(void)
+{
+	if(swvisible)
+		return;
+	if(swenabled == 0)
+		return;
+	if(swback == nil || swimg1 == nil || swmask1 == nil)
+		return;
+//	assert(!canqlock(&drawlock));		// assertion fails on omap
+	swvispt = swpt;
+	swvisvers = swvers;
+	swrect = rectaddpt(Rect(0,0,16,16), swvispt);
+	memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
+	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
+	flushmemscreen(swrect);
+	swvisible = 1;
+}
+
+int
+cursoron(int dolock)
+{
+	if (dolock)
+		lock(&oscreen);
+	cursoroff(0);
+	swcursordraw();
+	if (dolock)
+		unlock(&oscreen);
+	return 0;
+}
+
+void
+cursoroff(int dolock)
+{
+	if (dolock)
+		lock(&oscreen);
+	swcursorhide();
+	if (dolock)
+		unlock(&oscreen);
+}
+
+void
+swload(Cursor *curs)
+{
+	uchar *ip, *mp;
+	int i, j, set, clr;
+
+	if(!swimg || !swmask || !swimg1 || !swmask1)
+		return;
+	/*
+	 * Build cursor image and mask.
+	 * Image is just the usual cursor image
+	 * but mask is a transparent alpha mask.
+	 * 
+	 * The 16x16x8 memimages do not have
+	 * padding at the end of their scan lines.
+	 */
+	ip = byteaddr(swimg, ZP);
+	mp = byteaddr(swmask, ZP);
+	for(i=0; i<32; i++){
+		set = curs->set[i];
+		clr = curs->clr[i];
+		for(j=0x80; j; j>>=1){
+			*ip++ = set&j ? 0x00 : 0xFF;
+			*mp++ = (clr|set)&j ? 0xFF : 0x00;
+		}
+	}
+	swoffset = curs->offset;
+	swvers++;
+	memimagedraw(swimg1,  swimg1->r,  swimg,  ZP, memopaque, ZP, S);
+	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
+}
+
+/* called from devmouse */
+void
+setcursor(Cursor* curs)
+{
+	cursoroff(1);
+	oscreen.Cursor = *curs;
+	swload(curs);
+	cursoron(1);
+}
+
 int
-cursoron(int)		// TODO
+swmove(Point p)
 {
+	swpt = addpt(p, swoffset);
 	return 0;
 }
 
 void
-cursoroff(int)
+swcursorclock(void)
 {
+	int x;
+
+	if(!swenabled)
+		return;
+	swmove(mousexy());
+	if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
+		return;
+
+	x = splhi();
+	if(swenabled)
+	if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
+	if(canqlock(&drawlock)){
+		swcursorhide();
+		swcursordraw();
+		qunlock(&drawlock);
+	}
+	splx(x);
 }
 
 void
-setcursor(Cursor* curs)	// TODO
+swcursorinit(void)
 {
-//	VGAscr *scr;
+	static int init;
+
+	if(!init){
+		init = 1;
+		addclock0link(swcursorclock, 10);
+	}
+	if(swback){
+		freememimage(swback);
+		freememimage(swmask);
+		freememimage(swmask1);
+		freememimage(swimg);
+		freememimage(swimg1);
+	}
+
+	swback  = allocmemimage(Rect(0,0,32,32), gscreen->chan);
+	swmask  = allocmemimage(Rect(0,0,16,16), GREY8);
+	swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
+	swimg   = allocmemimage(Rect(0,0,16,16), GREY8);
+	swimg1  = allocmemimage(Rect(0,0,16,16), GREY1);
+	if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
+		print("software cursor: allocmemimage fails\n");
+		return;
+	}
 
-	USED(curs);
-//	scr = &vgascreen[0];
-//	cursorload(scr, curs);
+	memfillcolor(swmask, DOpaque);
+	memfillcolor(swmask1, DOpaque);
+	memfillcolor(swimg, DBlack);
+	memfillcolor(swimg1, DBlack);
 }
 
 /* called from main and possibly later from devdss to change resolution */
@@ -355,7 +524,7 @@ screeninit(void)
 
 	if (first) {
 		iprint("screeninit...");
-		oscreen = settings[Res1280x1024];
+		oscreen.settings = &settings[Res1280x1024];
 
 		lcdstop();
 		if (framebuf)
@@ -382,19 +551,22 @@ screeninit(void)
 	gscreen->width = Wid * (Depth / BI2BY) / BY2WD;
 	flushmemscreen(gscreen->r);
 
+	blanktime = 3;				/* minutes */
+
 	if (first) {
 		iprint("on: blue for 3 seconds...");
 		delay(3*1000);
 		iprint("\n");
-	}
-
-	blanktime = 3;				/* minutes */
 
-	if (first) {
 		screenwin();		/* draw border & top orange bar */
 		screenputs = omapscreenputs;
 		iprint("screen: frame buffer at %#p for %dx%d\n",
-			framebuf, oscreen.wid, oscreen.ht);
+			framebuf, oscreen.settings->wid, oscreen.settings->ht);
+
+		swenabled = 1;
+		swcursorinit();		/* needs gscreen set */
+		setcursor(&arrow);
+
 		first = 0;
 	}
 }

+ 50 - 56
sys/src/9/omap/screen.h

@@ -2,7 +2,7 @@ typedef struct Cursor Cursor;
 typedef struct Cursorinfo	Cursorinfo;
 typedef struct OScreen OScreen;
 typedef struct Omap3fb Omap3fb;
-typedef struct Scr	Scr;
+typedef struct Settings Settings;
 
 struct Cursorinfo
 {
@@ -11,19 +11,40 @@ struct Cursorinfo
 };
 
 extern Cursor	arrow;
-extern ulong	blanktime;
 extern Cursorinfo cursor;
 
-extern void	cursoroff(int);
-extern int	cursoron(int);
+/* devmouse.c */
+extern void mousetrack(int, int, int, int);
+extern Point mousexy(void);
+
 extern void	mouseaccelerate(int);
 extern void	mouseresize(void);
-extern void	mousetrack(int, int, int, int);
-extern void	setcursor(Cursor* curs);
 
-extern uchar*	attachscreen(Rectangle*, ulong*, int*, int*, int*);
-extern void	blankscreen(int);
+/* screen.c */
+extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
 extern void	flushmemscreen(Rectangle);
+extern int	cursoron(int);
+extern void	cursoroff(int);
+extern void	setcursor(Cursor*);
+extern int	screensize(int, int, int, ulong);
+extern int	screenaperture(int, int);
+extern Rectangle physgscreenr;	/* actual monitor size */
+extern void	blankscreen(int);
+
+extern void swcursorinit(void);
+extern void swcursorhide(void);
+extern void swcursoravoid(Rectangle);
+extern void swcursorunhide(void);
+
+/* devdraw.c */
+extern void	deletescreenimage(void);
+extern void	resetscreenimage(void);
+extern int		drawhasclients(void);
+extern ulong	blanktime;
+extern void	setscreenimageclipr(Rectangle);
+extern void	drawflush(void);
+extern int drawidletime(void);
+extern QLock	drawlock;
 
 #define ishwimage(i)	0		/* for ../port/devdraw.c */
 
@@ -47,27 +68,34 @@ enum {
 	Res800x600	= 0,
 	Res1024x768,
 	Res1280x1024,
+	Res1400x1050,
 };
 
-struct OScreen {
-	int	open;
-	uint	wid;
-	uint	ht;
-	uint	freq;
-	uint	chan;
+struct Settings {
+	uint	wid;		/* width in pixels */
+	uint	ht;		/* height in pixels */
+	uint	freq;		/* refresh frequency; only printed */
+	uint	chan;		/* draw chan */
 
 	/* shouldn't be needed? */
 	uint	pixelclock;
-	uint	hbp;
-	uint	hfp;
-	uint	hsw;
 
-	uint	vbp;
-	uint	vfp;
-	uint	vsw;
+	/* horizontal timing */
+	uint	hbp;		/* back porch: pixel clocks before scan line */
+	uint	hfp;		/* front porch: pixel clocks after scan line */
+	uint	hsw;		/* sync pulse width: more hfp */
 
-//	Lock;
-//	Cursor;
+	/* vertical timing */
+	uint	vbp;		/* back porch: line clocks before frame */
+	uint	vfp;		/* front porch: line clocks after frame */
+	uint	vsw;		/* sync pulse width: more vfp */
+};
+
+struct OScreen {
+	Lock;
+	Cursor;
+	Settings *settings;
+	int	open;
 };
 
 struct Omap3fb {		/* frame buffer for 24-bit active color */
@@ -75,37 +103,3 @@ struct Omap3fb {		/* frame buffer for 24-bit active color */
 	/* pixel data, even; base type's width must match Depth */
 	ushort	pixel[Wid*Ht];
 };
-
-struct Scr {
-	Lock	devlock;
-//	VGAdev*	dev;
-//	Pcidev*	pci;
-
-//	VGAcur*	cur;
-	ulong	storage;
-	Cursor;
-
-	int	useflush;
-
-	ulong	paddr;		/* frame buffer */
-	void*	vaddr;
-	int	apsize;
-
-	ulong	io;			/* device specific registers */
-	ulong	*mmio;
-	
-	ulong	colormap[Pcolours][3];
-	int	palettedepth;
-
-	Memimage* gscreen;
-	Memdata* gscreendata;
-	Memsubfont* memdefont;
-
-	int	(*fill)(Scr*, Rectangle, ulong);
-	int	(*scroll)(Scr*, Rectangle, Rectangle);
-	void	(*blank)(Scr*, int);
-
-	ulong	id;	/* internal identifier for driver use */
-	int	isblank;
-	int	overlayinit;
-};

+ 15 - 10
sys/src/9/pc/etherigbe.c

@@ -34,16 +34,17 @@ enum {
 	i82544ei	= (0x1008<<16)|0x8086,
 	i82544eif	= (0x1009<<16)|0x8086,
 	i82544gc	= (0x100d<<16)|0x8086,
-	i82547ei	= (0x1019<<16)|0x8086,
 	i82540em	= (0x100E<<16)|0x8086,
 	i82540eplp	= (0x101E<<16)|0x8086,
 	i82545em	= (0x100F<<16)|0x8086,
 	i82545gmc	= (0x1026<<16)|0x8086,
+	i82547ei	= (0x1019<<16)|0x8086,
 	i82547gi	= (0x1075<<16)|0x8086,
+	i82541ei	= (0x1013<<16)|0x8086,
 	i82541gi	= (0x1076<<16)|0x8086,
 	i82541gi2	= (0x1077<<16)|0x8086,
-	i82546gb	= (0x1079<<16)|0x8086,
 	i82541pi	= (0x107c<<16)|0x8086,
+	i82546gb	= (0x1079<<16)|0x8086,
 	i82546eb	= (0x1010<<16)|0x8086,
 };
 
@@ -903,9 +904,9 @@ igbetxinit(Ctlr* ctlr)
 	case i82544ei:
 	case i82544eif:
 	case i82544gc:
-	case i82547ei:
 	case i82540em:
 	case i82540eplp:
+	case i82541ei:
 	case i82541gi:
 	case i82541gi2:
 	case i82541pi:
@@ -913,6 +914,7 @@ igbetxinit(Ctlr* ctlr)
 	case i82545gmc:
 	case i82546gb:
 	case i82546eb:
+	case i82547ei:
 	case i82547gi:
 		r = 8;
 		break;
@@ -1486,10 +1488,11 @@ igbemii(Ctlr* ctlr)
 	case i82544ei:
 	case i82544eif:
 	case i82544gc:
-	case i82547ei:
 	case i82540em:
 	case i82540eplp:
+	case i82547ei:
 	case i82547gi:
+	case i82541ei:
 	case i82541gi:
 	case i82541gi2:
 	case i82541pi:
@@ -1656,17 +1659,18 @@ at93c46r(Ctlr* ctlr)
 	default:
 		areq = 0;
 		break;
-	case i82541gi:
-	case i82547gi:
 	case i82540em:
 	case i82540eplp:
-	case i82541pi:
+	case i82541ei:
+	case i82541gi:
 	case i82541gi2:
+	case i82541pi:
 	case i82545em:
 	case i82545gmc:
 	case i82546gb:
 	case i82546eb:
 	case i82547ei:
+	case i82547gi:
 		areq = 1;
 		csr32w(ctlr, Eecd, eecd|Areq);
 		for(i = 0; i < 1000; i++){
@@ -1747,11 +1751,11 @@ igbedetach(Ctlr* ctlr)
 	case i82540em:
 	case i82540eplp:
 	case i82541gi:
-	case i82541pi:
-	case i82547gi:
 	case i82541gi2:
+	case i82541pi:
 	case i82545em:
 	case i82545gmc:
+	case i82547gi:
 	case i82546gb:
 	case i82546eb:
 		r = csr32r(ctlr, Manc);
@@ -1928,10 +1932,11 @@ igbepci(void)
 		case i82544eif:
 		case i82544gc:
 		case i82547ei:
+		case i82547gi:
 		case i82540em:
 		case i82540eplp:
+		case i82541ei:
 		case i82541gi:
-		case i82547gi:
 		case i82541gi2:
 		case i82541pi:
 		case i82545em:

+ 14 - 9
sys/src/boot/pc/etherigbe.c

@@ -39,16 +39,17 @@ enum {
 	i82544ei	= (0x1008<<16)|0x8086,
 	i82544eif	= (0x1009<<16)|0x8086,
 	i82544gc	= (0x100d<<16)|0x8086,
-	i82547ei	= (0x1019<<16)|0x8086,
 	i82540em	= (0x100E<<16)|0x8086,
 	i82540eplp	= (0x101E<<16)|0x8086,
 	i82545em	= (0x100F<<16)|0x8086,
 	i82545gmc	= (0x1026<<16)|0x8086,
+	i82547ei	= (0x1019<<16)|0x8086,
 	i82547gi	= (0x1075<<16)|0x8086,
+	i82541ei	= (0x1013<<16)|0x8086,
 	i82541gi	= (0x1076<<16)|0x8086,
 	i82541gi2	= (0x1077<<16)|0x8086,
-	i82546gb	= (0x1079<<16)|0x8086,
 	i82541pi	= (0x107c<<16)|0x8086,
+	i82546gb	= (0x1079<<16)|0x8086,
 	i82546eb	= (0x1010<<16)|0x8086,
 };
 
@@ -903,15 +904,16 @@ igbeinit(Ether* edev)
 	case i82544ei:
 	case i82544eif:
 	case i82544gc:
-	case i82547ei:
 	case i82540em:
 	case i82540eplp:
+	case i82541ei:
 	case i82541gi:
 	case i82541gi2:
 	case i82541pi:
 	case i82546gb:
 	case i82546eb:
 	case i82547gi:
+	case i82547ei:
 	case i82545em:
 	case i82545gmc:
 		r = 8;
@@ -948,13 +950,13 @@ igbeinit(Ether* edev)
 	case i82540em:
 	case i82540eplp:
 	case i82547gi:
-	case i82541pi:
 	case i82545em:
 	case i82545gmc:
 	case i82546gb:
 	case i82546eb:
 	case i82541gi:
 	case i82541gi2:
+	case i82541pi:
 		r = csr32r(ctlr, Txdctl);
 		r &= ~WthreshMASK;
 		r |= Gran|(4<<WthreshSHIFT);
@@ -1180,9 +1182,9 @@ igbemii(Ctlr* ctlr)
 	case i82544ei:
 	case i82544eif:
 	case i82544gc:
-	case i82547ei:
 	case i82540em:
 	case i82540eplp:
+	case i82547ei:
 	case i82547gi:
 	case i82541gi:
 	case i82541gi2:
@@ -1356,14 +1358,16 @@ at93c46r(Ctlr* ctlr)
 		break;
 	case i82540em:
 	case i82540eplp:
+	case i82541ei:
 	case i82541gi:
 	case i82541gi2:
+	case i82541pi:
 	case i82545em:
 	case i82545gmc:
-	case i82541pi:
-	case i82547gi:
 	case i82546gb:
 	case i82546eb:
+	case i82547ei:
+	case i82547gi:
 		areq = 1;
 		csr32w(ctlr, Eecd, eecd|Areq);
 		for(i = 0; i < 1000; i++){
@@ -1442,9 +1446,9 @@ detach(Ctlr *ctlr)
 	case i82540eplp:
 	case i82541gi:
 	case i82541gi2:
+	case i82541pi:
 	case i82545em:
 	case i82545gmc:
-	case i82541pi:
 	case i82547gi:
 	case i82546gb:
 	case i82546eb:
@@ -1635,9 +1639,10 @@ igbepci(void)
 		case i82544eif:
 		case i82544gc:
 		case i82547ei:
+		case i82547gi:
 		case i82540em:
 		case i82540eplp:
-		case i82547gi:
+		case i82541ei:
 		case i82541gi:
 		case i82541gi2:
 		case i82541pi:

+ 40 - 11
sys/src/cmd/5c/txt.c

@@ -561,7 +561,8 @@ void
 gmove(Node *f, Node *t)
 {
 	int ft, tt, a;
-	Node nod;
+	Node nod, nod1;
+	Prog *p1;
 
 	ft = f->type->etype;
 	tt = t->type->etype;
@@ -690,21 +691,53 @@ gmove(Node *f, Node *t)
 		}
 		break;
 	case TUINT:
-	case TINT:
 	case TULONG:
+		if(tt == TFLOAT || tt == TDOUBLE) {
+			// ugly and probably longer than necessary,
+			// but vfp has a single instruction for this,
+			// so hopefully it won't last long.
+			//
+			//	tmp = f
+			//	tmp1 = tmp & 0x80000000
+			//	tmp ^= tmp1
+			//	t = float(int32(tmp))
+			//	if(tmp1)
+			//		t += 2147483648.
+			//
+			regalloc(&nod, f, Z);
+			regalloc(&nod1, f, Z);
+			gins(AMOVW, f, &nod);
+			gins(AMOVW, &nod, &nod1);
+			gins(AAND, nodconst(0x80000000), &nod1);
+			gins(AEOR, &nod1, &nod);
+			if(tt == TFLOAT)
+				gins(AMOVWF, &nod, t);
+			else
+				gins(AMOVWD, &nod, t);
+			gins(ACMP, nodconst(0), Z);
+			raddr(&nod1, p);
+			gins(ABEQ, Z, Z);
+			regfree(&nod);
+			regfree(&nod1);
+			p1 = p;
+			regalloc(&nod, t, Z);
+			gins(AMOVF, nodfconst(2147483648.), &nod);
+			gins(AADDF, &nod, t);
+			regfree(&nod);
+			patch(p1, pc);
+			return;
+		}
+		// fall through
+
+	case TINT:
 	case TLONG:
 	case TIND:
 		switch(tt) {
 		case TDOUBLE:
-		case TVLONG:
 			gins(AMOVWD, f, t);
-			if(ft == TULONG) {
-			}
 			return;
 		case TFLOAT:
 			gins(AMOVWF, f, t);
-			if(ft == TULONG) {
-			}
 			return;
 		case TINT:
 		case TUINT:
@@ -722,7 +755,6 @@ gmove(Node *f, Node *t)
 	case TSHORT:
 		switch(tt) {
 		case TDOUBLE:
-		case TVLONG:
 			regalloc(&nod, f, Z);
 			gins(AMOVH, f, &nod);
 			gins(AMOVWD, &nod, t);
@@ -752,7 +784,6 @@ gmove(Node *f, Node *t)
 	case TUSHORT:
 		switch(tt) {
 		case TDOUBLE:
-		case TVLONG:
 			regalloc(&nod, f, Z);
 			gins(AMOVHU, f, &nod);
 			gins(AMOVWD, &nod, t);
@@ -782,7 +813,6 @@ gmove(Node *f, Node *t)
 	case TCHAR:
 		switch(tt) {
 		case TDOUBLE:
-		case TVLONG:
 			regalloc(&nod, f, Z);
 			gins(AMOVB, f, &nod);
 			gins(AMOVWD, &nod, t);
@@ -812,7 +842,6 @@ gmove(Node *f, Node *t)
 	case TUCHAR:
 		switch(tt) {
 		case TDOUBLE:
-		case TVLONG:
 			regalloc(&nod, f, Z);
 			gins(AMOVBU, f, &nod);
 			gins(AMOVWD, &nod, t);