shithub: riscv

Download patch

ref: a4688b03228dfdebcde34570b2a7b5c79db31c79
parent: 51550ba3d2d9a19c92ef2d3fd49cbff281064ba3
parent: a1a6f26110b774e894bfc8a152fffff81aa3dc08
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Jul 11 03:49:52 EDT 2019

merge

--- a/sys/src/9/pc/ether8169.c
+++ b/sys/src/9/pc/ether8169.c
@@ -16,8 +16,7 @@
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
-
-#include "ethermii.h"
+#include "../port/ethermii.h"
 
 enum {					/* registers */
 	Idr0		= 0x00,		/* MAC address */
--- a/sys/src/9/pc/etherdp83820.c
+++ b/sys/src/9/pc/etherdp83820.c
@@ -13,8 +13,7 @@
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
-
-#include "ethermii.h"
+#include "../port/ethermii.h"
 
 enum {					/* Registers */
 	Cr		= 0x00,		/* Command */
--- a/sys/src/9/pc/etherigbe.c
+++ b/sys/src/9/pc/etherigbe.c
@@ -25,8 +25,7 @@
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
-
-#include "ethermii.h"
+#include "../port/ethermii.h"
 
 enum {
 	i82542		= (0x1000<<16)|0x8086,
--- a/sys/src/9/pc/ethermii.c
+++ /dev/null
@@ -1,235 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-#include "../port/netif.h"
-#include "../port/etherif.h"
-
-#include "ethermii.h"
-
-int
-mii(Mii* mii, int mask)
-{
-	MiiPhy *miiphy;
-	int bit, oui, phyno, r, rmask;
-
-	/*
-	 * Probe through mii for PHYs in mask;
-	 * return the mask of those found in the current probe.
-	 * If the PHY has not already been probed, update
-	 * the Mii information.
-	 */
-	rmask = 0;
-	for(phyno = 0; phyno < NMiiPhy; phyno++){
-		bit = 1<<phyno;
-		if(!(mask & bit))
-			continue;
-		if(mii->mask & bit){
-			rmask |= bit;
-			continue;
-		}
-		if(mii->mir(mii, phyno, Bmsr) == -1)
-			continue;
-		r = mii->mir(mii, phyno, Phyidr1);
-		oui = (r & 0x3FFF)<<6;
-		r = mii->mir(mii, phyno, Phyidr2);
-		oui |= r>>10;
-		if(oui == 0xFFFFF || oui == 0)
-			continue;
-
-		if((miiphy = malloc(sizeof(MiiPhy))) == nil)
-			continue;
-
-		miiphy->mii = mii;
-		miiphy->oui = oui;
-		miiphy->phyno = phyno;
-
-		miiphy->anar = ~0;
-		miiphy->fc = ~0;
-		miiphy->mscr = ~0;
-
-		mii->phy[phyno] = miiphy;
-		if(mii->curphy == nil)
-			mii->curphy = miiphy;
-		mii->mask |= bit;
-		mii->nphy++;
-
-		rmask |= bit;
-	}
-	return rmask;
-}
-
-int
-miimir(Mii* mii, int r)
-{
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	return mii->mir(mii, mii->curphy->phyno, r);
-}
-
-int
-miimiw(Mii* mii, int r, int data)
-{
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	return mii->miw(mii, mii->curphy->phyno, r, data);
-}
-
-int
-miireset(Mii* mii)
-{
-	int bmcr;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
-	bmcr |= BmcrR;
-	mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
-	microdelay(1);
-
-	return 0;
-}
-
-int
-miiane(Mii* mii, int a, int p, int e)
-{
-	int anar, bmsr, mscr, r, phyno;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	phyno = mii->curphy->phyno;
-
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & BmsrAna))
-		return -1;
-
-	if(a != ~0)
-		anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
-	else if(mii->curphy->anar != ~0)
-		anar = mii->curphy->anar;
-	else{
-		anar = mii->mir(mii, phyno, Anar);
-		anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
-		if(bmsr & Bmsr10THD)
-			anar |= Ana10HD;
-		if(bmsr & Bmsr10TFD)
-			anar |= Ana10FD;
-		if(bmsr & Bmsr100TXHD)
-			anar |= AnaTXHD;
-		if(bmsr & Bmsr100TXFD)
-			anar |= AnaTXFD;
-	}
-	mii->curphy->anar = anar;
-
-	if(p != ~0)
-		anar |= (AnaAP|AnaP) & p;
-	else if(mii->curphy->fc != ~0)
-		anar |= mii->curphy->fc;
-	mii->curphy->fc = (AnaAP|AnaP) & anar;
-
-	if(bmsr & BmsrEs){
-		mscr = mii->mir(mii, phyno, Mscr);
-		mscr &= ~(Mscr1000TFD|Mscr1000THD);
-		if(e != ~0)
-			mscr |= (Mscr1000TFD|Mscr1000THD) & e;
-		else if(mii->curphy->mscr != ~0)
-			mscr = mii->curphy->mscr;
-		else{
-			r = mii->mir(mii, phyno, Esr);
-			if(r & Esr1000THD)
-				mscr |= Mscr1000THD;
-			if(r & Esr1000TFD)
-				mscr |= Mscr1000TFD;
-		}
-		mii->curphy->mscr = mscr;
-		mii->miw(mii, phyno, Mscr, mscr);
-	}
-	mii->miw(mii, phyno, Anar, anar);
-
-	r = mii->mir(mii, phyno, Bmcr);
-	if(!(r & BmcrR)){
-		r |= BmcrAne|BmcrRan;
-		mii->miw(mii, phyno, Bmcr, r);
-	}
-
-	return 0;
-}
-
-int
-miistatus(Mii* mii)
-{
-	MiiPhy *phy;
-	int anlpar, bmsr, p, r, phyno;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	phy = mii->curphy;
-	phyno = phy->phyno;
-
-	/*
-	 * Check Auto-Negotiation is complete and link is up.
-	 * (Read status twice as the Ls bit is sticky).
-	 */
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & (BmsrAnc|BmsrAna))) {
-		// print("miistatus: auto-neg incomplete\n");
-		return -1;
-	}
-
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & BmsrLs)){
-		// print("miistatus: link down\n");
-		phy->link = 0;
-		return -1;
-	}
-
-	phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
-	if(phy->mscr){
-		r = mii->mir(mii, phyno, Mssr);
-		if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
-			phy->speed = 1000;
-			phy->fd = 1;
-		}
-		else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
-			phy->speed = 1000;
-	}
-
-	anlpar = mii->mir(mii, phyno, Anlpar);
-	if(phy->speed == 0){
-		r = phy->anar & anlpar;
-		if(r & AnaTXFD){
-			phy->speed = 100;
-			phy->fd = 1;
-		}
-		else if(r & AnaTXHD)
-			phy->speed = 100;
-		else if(r & Ana10FD){
-			phy->speed = 10;
-			phy->fd = 1;
-		}
-		else if(r & Ana10HD)
-			phy->speed = 10;
-	}
-	if(phy->speed == 0) {
-		// print("miistatus: phy speed 0\n");
-		return -1;
-	}
-
-	if(phy->fd){
-		p = phy->fc;
-		r = anlpar & (AnaAP|AnaP);
-		if(p == AnaAP && r == (AnaAP|AnaP))
-			phy->tfc = 1;
-		else if(p == (AnaAP|AnaP) && r == AnaAP)
-			phy->rfc = 1;
-		else if((p & AnaP) && (r & AnaP))
-			phy->rfc = phy->tfc = 1;
-	}
-
-	phy->link = 1;
-
-	return 0;
-}
--- a/sys/src/9/pc/ethermii.h
+++ /dev/null
@@ -1,116 +1,0 @@
-typedef struct Mii Mii;
-typedef struct MiiPhy MiiPhy;
-
-enum {					/* registers */
-	Bmcr		= 0x00,		/* Basic Mode Control */
-	Bmsr		= 0x01,		/* Basic Mode Status */
-	Phyidr1		= 0x02,		/* PHY Identifier #1 */
-	Phyidr2		= 0x03,		/* PHY Identifier #2 */
-	Anar		= 0x04,		/* Auto-Negotiation Advertisement */
-	Anlpar		= 0x05,		/* AN Link Partner Ability */
-	Aner		= 0x06,		/* AN Expansion */
-	Annptr		= 0x07,		/* AN Next Page TX */
-	Annprr		= 0x08,		/* AN Next Page RX */
-	Mscr		= 0x09,		/* MASTER-SLAVE Control */
-	Mssr		= 0x0A,		/* MASTER-SLAVE Status */
-	Esr		= 0x0F,		/* Extended Status */
-
-	NMiiPhyr	= 32,
-	NMiiPhy		= 32,
-};
-
-enum {					/* Bmcr */
-	BmcrSs1		= 0x0040,	/* Speed Select[1] */
-	BmcrCte		= 0x0080,	/* Collision Test Enable */
-	BmcrDm		= 0x0100,	/* Duplex Mode */
-	BmcrRan		= 0x0200,	/* Restart Auto-Negotiation */
-	BmcrI		= 0x0400,	/* Isolate */
-	BmcrPd		= 0x0800,	/* Power Down */
-	BmcrAne		= 0x1000,	/* Auto-Negotiation Enable */
-	BmcrSs0		= 0x2000,	/* Speed Select[0] */
-	BmcrLe		= 0x4000,	/* Loopback Enable */
-	BmcrR		= 0x8000,	/* Reset */
-};
-
-enum {					/* Bmsr */
-	BmsrEc		= 0x0001,	/* Extended Capability */
-	BmsrJd		= 0x0002,	/* Jabber Detect */
-	BmsrLs		= 0x0004,	/* Link Status */
-	BmsrAna		= 0x0008,	/* Auto-Negotiation Ability */
-	BmsrRf		= 0x0010,	/* Remote Fault */
-	BmsrAnc		= 0x0020,	/* Auto-Negotiation Complete */
-	BmsrPs		= 0x0040,	/* Preamble Suppression Capable */
-	BmsrEs		= 0x0100,	/* Extended Status */
-	Bmsr100T2HD	= 0x0200,	/* 100BASE-T2 HD Capable */
-	Bmsr100T2FD	= 0x0400,	/* 100BASE-T2 FD Capable */
-	Bmsr10THD	= 0x0800,	/* 10BASE-T HD Capable */
-	Bmsr10TFD	= 0x1000,	/* 10BASE-T FD Capable */
-	Bmsr100TXHD	= 0x2000,	/* 100BASE-TX HD Capable */
-	Bmsr100TXFD	= 0x4000,	/* 100BASE-TX FD Capable */
-	Bmsr100T4	= 0x8000,	/* 100BASE-T4 Capable */
-};
-
-enum {					/* Anar/Anlpar */
-	Ana10HD		= 0x0020,	/* Advertise 10BASE-T */
-	Ana10FD		= 0x0040,	/* Advertise 10BASE-T FD */
-	AnaTXHD		= 0x0080,	/* Advertise 100BASE-TX */
-	AnaTXFD		= 0x0100,	/* Advertise 100BASE-TX FD */
-	AnaT4		= 0x0200,	/* Advertise 100BASE-T4 */
-	AnaP		= 0x0400,	/* Pause */
-	AnaAP		= 0x0800,	/* Asymmetrical Pause */
-	AnaRf		= 0x2000,	/* Remote Fault */
-	AnaAck		= 0x4000,	/* Acknowledge */
-	AnaNp		= 0x8000,	/* Next Page Indication */
-};
-
-enum {					/* Mscr */
-	Mscr1000THD	= 0x0100,	/* Advertise 1000BASE-T HD */
-	Mscr1000TFD	= 0x0200,	/* Advertise 1000BASE-T FD */
-};
-
-enum {					/* Mssr */
-	Mssr1000THD	= 0x0400,	/* Link Partner 1000BASE-T HD able */
-	Mssr1000TFD	= 0x0800,	/* Link Partner 1000BASE-T FD able */
-};
-
-enum {					/* Esr */
-	Esr1000THD	= 0x1000,	/* 1000BASE-T HD Capable */
-	Esr1000TFD	= 0x2000,	/* 1000BASE-T FD Capable */
-	Esr1000XHD	= 0x4000,	/* 1000BASE-X HD Capable */
-	Esr1000XFD	= 0x8000,	/* 1000BASE-X FD Capable */
-};
-
-typedef struct Mii {
-	Lock;
-	int	nphy;
-	int	mask;
-	MiiPhy*	phy[NMiiPhy];
-	MiiPhy*	curphy;
-
-	void*	ctlr;
-	int	(*mir)(Mii*, int, int);
-	int	(*miw)(Mii*, int, int, int);
-} Mii;
-
-typedef struct MiiPhy {
-	Mii*	mii;
-	int	oui;
-	int	phyno;
-
-	int	anar;
-	int	fc;
-	int	mscr;
-
-	int	link;
-	int	speed;
-	int	fd;
-	int	rfc;
-	int	tfc;
-};
-
-extern int mii(Mii*, int);
-extern int miiane(Mii*, int, int, int);
-extern int miimir(Mii*, int);
-extern int miimiw(Mii*, int, int);
-extern int miireset(Mii*);
-extern int miistatus(Mii*);
--- a/sys/src/9/pc/ethervgbe.c
+++ b/sys/src/9/pc/ethervgbe.c
@@ -30,8 +30,7 @@
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
-
-#include "ethermii.h"
+#include "../port/ethermii.h"
 
 #define DEBUG
 
--- a/sys/src/9/pc/ethervt6102.c
+++ b/sys/src/9/pc/ethervt6102.c
@@ -18,8 +18,7 @@
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
-
-#include "ethermii.h"
+#include "../port/ethermii.h"
 
 enum {
 	Par0		= 0x00,		/* Ethernet Address */
--- a/sys/src/9/pc/ethervt6105m.c
+++ b/sys/src/9/pc/ethervt6105m.c
@@ -21,8 +21,7 @@
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
-
-#include "ethermii.h"
+#include "../port/ethermii.h"
 
 enum {
 	Par0		= 0x00,			/* Ethernet Address */
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -123,13 +123,12 @@
 usbehci.$O usbehcipc.$O:	usbehci.h
 trap.$O:			/sys/include/tos.h
 uartaxp.$O:			uartaxp.i
-ethermii.$O:			ethermii.h
-ether8169.$O:			ethermii.h
-etherdp83820.$O:		ethermii.h
-etherigbe.$O:			ethermii.h
-ethervgbe.$O:			ethermii.h
-ethervt6102.$O:			ethermii.h
-ethervt6105m.$O:		ethermii.h
+ether8169.$O:			../port/ethermii.h
+etherdp83820.$O:		../port/ethermii.h
+etherigbe.$O:			../port/ethermii.h
+ethervgbe.$O:			../port/ethermii.h
+ethervt6102.$O:			../port/ethermii.h
+ethervt6105m.$O:		../port/ethermii.h
 etherm10g.$O:			etherm10g2k.i etherm10g4k.i
 etheriwl.$O:			../port/wifi.h
 etherwpi.$O:			../port/wifi.h
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -85,7 +85,7 @@
 
 
 # copies generated by the rule below
-PCHEADERS=usbehci.h screen.h ethermii.h mp.h io.h ahci.h \
+PCHEADERS=usbehci.h screen.h mp.h io.h ahci.h \
 	yukdump.h
 
 REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
@@ -124,13 +124,12 @@
 
 trap.$O:			/sys/include/tos.h
 
-ethermii.$O:			ethermii.h
-ether8169.$O:			ethermii.h
-etherdp83820.$O:		ethermii.h
-etherigbe.$O:			ethermii.h
-ethervgbe.$O:			ethermii.h
-ethervt6102.$O:			ethermii.h
-ethervt6105m.$O:		ethermii.h
+ether8169.$O:			../port/ethermii.h
+etherdp83820.$O:		../port/ethermii.h
+etherigbe.$O:			../port/ethermii.h
+ethervgbe.$O:			../port/ethermii.h
+ethervt6102.$O:			../port/ethermii.h
+ethervt6105m.$O:		../port/ethermii.h
 
 etheriwl.$O:			../port/wifi.h
 etherwpi.$O:			../port/wifi.h
--- a/sys/src/9/port/devuart.c
+++ b/sys/src/9/port/devuart.c
@@ -644,7 +644,7 @@
 {
 	Uart *p = v;
 
-	if(p->blocked)
+	if(!p->enabled || p->blocked)
 		return;
 
 	ilock(&p->tlock);
--- /dev/null
+++ b/sys/src/9/port/ethermii.c
@@ -1,0 +1,235 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+#include "../port/etherif.h"
+
+#include "ethermii.h"
+
+int
+mii(Mii* mii, int mask)
+{
+	MiiPhy *miiphy;
+	int bit, oui, phyno, r, rmask;
+
+	/*
+	 * Probe through mii for PHYs in mask;
+	 * return the mask of those found in the current probe.
+	 * If the PHY has not already been probed, update
+	 * the Mii information.
+	 */
+	rmask = 0;
+	for(phyno = 0; phyno < NMiiPhy; phyno++){
+		bit = 1<<phyno;
+		if(!(mask & bit))
+			continue;
+		if(mii->mask & bit){
+			rmask |= bit;
+			continue;
+		}
+		if(mii->mir(mii, phyno, Bmsr) == -1)
+			continue;
+		r = mii->mir(mii, phyno, Phyidr1);
+		oui = (r & 0x3FFF)<<6;
+		r = mii->mir(mii, phyno, Phyidr2);
+		oui |= r>>10;
+		if(oui == 0xFFFFF || oui == 0)
+			continue;
+
+		if((miiphy = malloc(sizeof(MiiPhy))) == nil)
+			continue;
+
+		miiphy->mii = mii;
+		miiphy->oui = oui;
+		miiphy->phyno = phyno;
+
+		miiphy->anar = ~0;
+		miiphy->fc = ~0;
+		miiphy->mscr = ~0;
+
+		mii->phy[phyno] = miiphy;
+		if(mii->curphy == nil)
+			mii->curphy = miiphy;
+		mii->mask |= bit;
+		mii->nphy++;
+
+		rmask |= bit;
+	}
+	return rmask;
+}
+
+int
+miimir(Mii* mii, int r)
+{
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	return mii->mir(mii, mii->curphy->phyno, r);
+}
+
+int
+miimiw(Mii* mii, int r, int data)
+{
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	return mii->miw(mii, mii->curphy->phyno, r, data);
+}
+
+int
+miireset(Mii* mii)
+{
+	int bmcr;
+
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
+	bmcr |= BmcrR;
+	mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
+	microdelay(1);
+
+	return 0;
+}
+
+int
+miiane(Mii* mii, int a, int p, int e)
+{
+	int anar, bmsr, mscr, r, phyno;
+
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	phyno = mii->curphy->phyno;
+
+	bmsr = mii->mir(mii, phyno, Bmsr);
+	if(!(bmsr & BmsrAna))
+		return -1;
+
+	if(a != ~0)
+		anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
+	else if(mii->curphy->anar != ~0)
+		anar = mii->curphy->anar;
+	else{
+		anar = mii->mir(mii, phyno, Anar);
+		anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
+		if(bmsr & Bmsr10THD)
+			anar |= Ana10HD;
+		if(bmsr & Bmsr10TFD)
+			anar |= Ana10FD;
+		if(bmsr & Bmsr100TXHD)
+			anar |= AnaTXHD;
+		if(bmsr & Bmsr100TXFD)
+			anar |= AnaTXFD;
+	}
+	mii->curphy->anar = anar;
+
+	if(p != ~0)
+		anar |= (AnaAP|AnaP) & p;
+	else if(mii->curphy->fc != ~0)
+		anar |= mii->curphy->fc;
+	mii->curphy->fc = (AnaAP|AnaP) & anar;
+
+	if(bmsr & BmsrEs){
+		mscr = mii->mir(mii, phyno, Mscr);
+		mscr &= ~(Mscr1000TFD|Mscr1000THD);
+		if(e != ~0)
+			mscr |= (Mscr1000TFD|Mscr1000THD) & e;
+		else if(mii->curphy->mscr != ~0)
+			mscr = mii->curphy->mscr;
+		else{
+			r = mii->mir(mii, phyno, Esr);
+			if(r & Esr1000THD)
+				mscr |= Mscr1000THD;
+			if(r & Esr1000TFD)
+				mscr |= Mscr1000TFD;
+		}
+		mii->curphy->mscr = mscr;
+		mii->miw(mii, phyno, Mscr, mscr);
+	}
+	mii->miw(mii, phyno, Anar, anar);
+
+	r = mii->mir(mii, phyno, Bmcr);
+	if(!(r & BmcrR)){
+		r |= BmcrAne|BmcrRan;
+		mii->miw(mii, phyno, Bmcr, r);
+	}
+
+	return 0;
+}
+
+int
+miistatus(Mii* mii)
+{
+	MiiPhy *phy;
+	int anlpar, bmsr, p, r, phyno;
+
+	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
+		return -1;
+	phy = mii->curphy;
+	phyno = phy->phyno;
+
+	/*
+	 * Check Auto-Negotiation is complete and link is up.
+	 * (Read status twice as the Ls bit is sticky).
+	 */
+	bmsr = mii->mir(mii, phyno, Bmsr);
+	if(!(bmsr & (BmsrAnc|BmsrAna))) {
+		// print("miistatus: auto-neg incomplete\n");
+		return -1;
+	}
+
+	bmsr = mii->mir(mii, phyno, Bmsr);
+	if(!(bmsr & BmsrLs)){
+		// print("miistatus: link down\n");
+		phy->link = 0;
+		return -1;
+	}
+
+	phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
+	if(phy->mscr){
+		r = mii->mir(mii, phyno, Mssr);
+		if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
+			phy->speed = 1000;
+			phy->fd = 1;
+		}
+		else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
+			phy->speed = 1000;
+	}
+
+	anlpar = mii->mir(mii, phyno, Anlpar);
+	if(phy->speed == 0){
+		r = phy->anar & anlpar;
+		if(r & AnaTXFD){
+			phy->speed = 100;
+			phy->fd = 1;
+		}
+		else if(r & AnaTXHD)
+			phy->speed = 100;
+		else if(r & Ana10FD){
+			phy->speed = 10;
+			phy->fd = 1;
+		}
+		else if(r & Ana10HD)
+			phy->speed = 10;
+	}
+	if(phy->speed == 0) {
+		// print("miistatus: phy speed 0\n");
+		return -1;
+	}
+
+	if(phy->fd){
+		p = phy->fc;
+		r = anlpar & (AnaAP|AnaP);
+		if(p == AnaAP && r == (AnaAP|AnaP))
+			phy->tfc = 1;
+		else if(p == (AnaAP|AnaP) && r == AnaAP)
+			phy->rfc = 1;
+		else if((p & AnaP) && (r & AnaP))
+			phy->rfc = phy->tfc = 1;
+	}
+
+	phy->link = 1;
+
+	return 0;
+}
--- /dev/null
+++ b/sys/src/9/port/ethermii.h
@@ -1,0 +1,116 @@
+typedef struct Mii Mii;
+typedef struct MiiPhy MiiPhy;
+
+enum {					/* registers */
+	Bmcr		= 0x00,		/* Basic Mode Control */
+	Bmsr		= 0x01,		/* Basic Mode Status */
+	Phyidr1		= 0x02,		/* PHY Identifier #1 */
+	Phyidr2		= 0x03,		/* PHY Identifier #2 */
+	Anar		= 0x04,		/* Auto-Negotiation Advertisement */
+	Anlpar		= 0x05,		/* AN Link Partner Ability */
+	Aner		= 0x06,		/* AN Expansion */
+	Annptr		= 0x07,		/* AN Next Page TX */
+	Annprr		= 0x08,		/* AN Next Page RX */
+	Mscr		= 0x09,		/* MASTER-SLAVE Control */
+	Mssr		= 0x0A,		/* MASTER-SLAVE Status */
+	Esr		= 0x0F,		/* Extended Status */
+
+	NMiiPhyr	= 32,
+	NMiiPhy		= 32,
+};
+
+enum {					/* Bmcr */
+	BmcrSs1		= 0x0040,	/* Speed Select[1] */
+	BmcrCte		= 0x0080,	/* Collision Test Enable */
+	BmcrDm		= 0x0100,	/* Duplex Mode */
+	BmcrRan		= 0x0200,	/* Restart Auto-Negotiation */
+	BmcrI		= 0x0400,	/* Isolate */
+	BmcrPd		= 0x0800,	/* Power Down */
+	BmcrAne		= 0x1000,	/* Auto-Negotiation Enable */
+	BmcrSs0		= 0x2000,	/* Speed Select[0] */
+	BmcrLe		= 0x4000,	/* Loopback Enable */
+	BmcrR		= 0x8000,	/* Reset */
+};
+
+enum {					/* Bmsr */
+	BmsrEc		= 0x0001,	/* Extended Capability */
+	BmsrJd		= 0x0002,	/* Jabber Detect */
+	BmsrLs		= 0x0004,	/* Link Status */
+	BmsrAna		= 0x0008,	/* Auto-Negotiation Ability */
+	BmsrRf		= 0x0010,	/* Remote Fault */
+	BmsrAnc		= 0x0020,	/* Auto-Negotiation Complete */
+	BmsrPs		= 0x0040,	/* Preamble Suppression Capable */
+	BmsrEs		= 0x0100,	/* Extended Status */
+	Bmsr100T2HD	= 0x0200,	/* 100BASE-T2 HD Capable */
+	Bmsr100T2FD	= 0x0400,	/* 100BASE-T2 FD Capable */
+	Bmsr10THD	= 0x0800,	/* 10BASE-T HD Capable */
+	Bmsr10TFD	= 0x1000,	/* 10BASE-T FD Capable */
+	Bmsr100TXHD	= 0x2000,	/* 100BASE-TX HD Capable */
+	Bmsr100TXFD	= 0x4000,	/* 100BASE-TX FD Capable */
+	Bmsr100T4	= 0x8000,	/* 100BASE-T4 Capable */
+};
+
+enum {					/* Anar/Anlpar */
+	Ana10HD		= 0x0020,	/* Advertise 10BASE-T */
+	Ana10FD		= 0x0040,	/* Advertise 10BASE-T FD */
+	AnaTXHD		= 0x0080,	/* Advertise 100BASE-TX */
+	AnaTXFD		= 0x0100,	/* Advertise 100BASE-TX FD */
+	AnaT4		= 0x0200,	/* Advertise 100BASE-T4 */
+	AnaP		= 0x0400,	/* Pause */
+	AnaAP		= 0x0800,	/* Asymmetrical Pause */
+	AnaRf		= 0x2000,	/* Remote Fault */
+	AnaAck		= 0x4000,	/* Acknowledge */
+	AnaNp		= 0x8000,	/* Next Page Indication */
+};
+
+enum {					/* Mscr */
+	Mscr1000THD	= 0x0100,	/* Advertise 1000BASE-T HD */
+	Mscr1000TFD	= 0x0200,	/* Advertise 1000BASE-T FD */
+};
+
+enum {					/* Mssr */
+	Mssr1000THD	= 0x0400,	/* Link Partner 1000BASE-T HD able */
+	Mssr1000TFD	= 0x0800,	/* Link Partner 1000BASE-T FD able */
+};
+
+enum {					/* Esr */
+	Esr1000THD	= 0x1000,	/* 1000BASE-T HD Capable */
+	Esr1000TFD	= 0x2000,	/* 1000BASE-T FD Capable */
+	Esr1000XHD	= 0x4000,	/* 1000BASE-X HD Capable */
+	Esr1000XFD	= 0x8000,	/* 1000BASE-X FD Capable */
+};
+
+typedef struct Mii {
+	Lock;
+	int	nphy;
+	int	mask;
+	MiiPhy*	phy[NMiiPhy];
+	MiiPhy*	curphy;
+
+	void*	ctlr;
+	int	(*mir)(Mii*, int, int);
+	int	(*miw)(Mii*, int, int, int);
+} Mii;
+
+typedef struct MiiPhy {
+	Mii*	mii;
+	int	oui;
+	int	phyno;
+
+	int	anar;
+	int	fc;
+	int	mscr;
+
+	int	link;
+	int	speed;
+	int	fd;
+	int	rfc;
+	int	tfc;
+};
+
+extern int mii(Mii*, int);
+extern int miiane(Mii*, int, int, int);
+extern int miimir(Mii*, int);
+extern int miimiw(Mii*, int, int);
+extern int miireset(Mii*);
+extern int miistatus(Mii*);
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -105,3 +105,4 @@
 devether.$O ethersink.$O:	../port/etherif.h ../port/netif.h
 wifi.$O:	../port/etherif.h ../port/netif.h ../port/wifi.h /sys/include/libsec.h
 wifi.$O:	../ip/ip.h ../ip/ipv6.h
+ethermii.$O:	../port/ethermii.h
--- a/sys/src/9/teg2/ether8169.c
+++ b/sys/src/9/teg2/ether8169.c
@@ -16,8 +16,7 @@
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
-
-#include "ethermii.h"
+#include "../port/ethermii.h"
 
 typedef struct Ctlr Ctlr;
 typedef struct D D;			/* Transmit/Receive Descriptor */
--- a/sys/src/9/teg2/ethermii.c
+++ /dev/null
@@ -1,235 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-#include "../port/netif.h"
-#include "../port/etherif.h"
-
-#include "ethermii.h"
-
-int
-mii(Mii* mii, int mask)
-{
-	MiiPhy *miiphy;
-	int bit, oui, phyno, r, rmask;
-
-	/*
-	 * Probe through mii for PHYs in mask;
-	 * return the mask of those found in the current probe.
-	 * If the PHY has not already been probed, update
-	 * the Mii information.
-	 */
-	rmask = 0;
-	for(phyno = 0; phyno < NMiiPhy; phyno++){
-		bit = 1<<phyno;
-		if(!(mask & bit))
-			continue;
-		if(mii->mask & bit){
-			rmask |= bit;
-			continue;
-		}
-		if(mii->mir(mii, phyno, Bmsr) == -1)
-			continue;
-		r = mii->mir(mii, phyno, Phyidr1);
-		oui = (r & 0x3FFF)<<6;
-		r = mii->mir(mii, phyno, Phyidr2);
-		oui |= r>>10;
-		if(oui == 0xFFFFF || oui == 0)
-			continue;
-
-		if((miiphy = malloc(sizeof(MiiPhy))) == nil)
-			continue;
-
-		miiphy->mii = mii;
-		miiphy->oui = oui;
-		miiphy->phyno = phyno;
-
-		miiphy->anar = ~0;
-		miiphy->fc = ~0;
-		miiphy->mscr = ~0;
-
-		mii->phy[phyno] = miiphy;
-		if(mii->curphy == nil)
-			mii->curphy = miiphy;
-		mii->mask |= bit;
-		mii->nphy++;
-
-		rmask |= bit;
-	}
-	return rmask;
-}
-
-int
-miimir(Mii* mii, int r)
-{
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	return mii->mir(mii, mii->curphy->phyno, r);
-}
-
-int
-miimiw(Mii* mii, int r, int data)
-{
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	return mii->miw(mii, mii->curphy->phyno, r, data);
-}
-
-int
-miireset(Mii* mii)
-{
-	int bmcr;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr);
-	bmcr |= BmcrR;
-	mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr);
-	microdelay(1);
-
-	return 0;
-}
-
-int
-miiane(Mii* mii, int a, int p, int e)
-{
-	int anar, bmsr, mscr, r, phyno;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	phyno = mii->curphy->phyno;
-
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & BmsrAna))
-		return -1;
-
-	if(a != ~0)
-		anar = (AnaTXFD|AnaTXHD|Ana10FD|Ana10HD) & a;
-	else if(mii->curphy->anar != ~0)
-		anar = mii->curphy->anar;
-	else{
-		anar = mii->mir(mii, phyno, Anar);
-		anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD);
-		if(bmsr & Bmsr10THD)
-			anar |= Ana10HD;
-		if(bmsr & Bmsr10TFD)
-			anar |= Ana10FD;
-		if(bmsr & Bmsr100TXHD)
-			anar |= AnaTXHD;
-		if(bmsr & Bmsr100TXFD)
-			anar |= AnaTXFD;
-	}
-	mii->curphy->anar = anar;
-
-	if(p != ~0)
-		anar |= (AnaAP|AnaP) & p;
-	else if(mii->curphy->fc != ~0)
-		anar |= mii->curphy->fc;
-	mii->curphy->fc = (AnaAP|AnaP) & anar;
-
-	if(bmsr & BmsrEs){
-		mscr = mii->mir(mii, phyno, Mscr);
-		mscr &= ~(Mscr1000TFD|Mscr1000THD);
-		if(e != ~0)
-			mscr |= (Mscr1000TFD|Mscr1000THD) & e;
-		else if(mii->curphy->mscr != ~0)
-			mscr = mii->curphy->mscr;
-		else{
-			r = mii->mir(mii, phyno, Esr);
-			if(r & Esr1000THD)
-				mscr |= Mscr1000THD;
-			if(r & Esr1000TFD)
-				mscr |= Mscr1000TFD;
-		}
-		mii->curphy->mscr = mscr;
-		mii->miw(mii, phyno, Mscr, mscr);
-	}
-	mii->miw(mii, phyno, Anar, anar);
-
-	r = mii->mir(mii, phyno, Bmcr);
-	if(!(r & BmcrR)){
-		r |= BmcrAne|BmcrRan;
-		mii->miw(mii, phyno, Bmcr, r);
-	}
-
-	return 0;
-}
-
-int
-miistatus(Mii* mii)
-{
-	MiiPhy *phy;
-	int anlpar, bmsr, p, r, phyno;
-
-	if(mii == nil || mii->ctlr == nil || mii->curphy == nil)
-		return -1;
-	phy = mii->curphy;
-	phyno = phy->phyno;
-
-	/*
-	 * Check Auto-Negotiation is complete and link is up.
-	 * (Read status twice as the Ls bit is sticky).
-	 */
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & (BmsrAnc|BmsrAna))) {
-		// print("miistatus: auto-neg incomplete\n");
-		return -1;
-	}
-
-	bmsr = mii->mir(mii, phyno, Bmsr);
-	if(!(bmsr & BmsrLs)){
-		// print("miistatus: link down\n");
-		phy->link = 0;
-		return -1;
-	}
-
-	phy->speed = phy->fd = phy->rfc = phy->tfc = 0;
-	if(phy->mscr){
-		r = mii->mir(mii, phyno, Mssr);
-		if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){
-			phy->speed = 1000;
-			phy->fd = 1;
-		}
-		else if((phy->mscr & Mscr1000THD) && (r & Mssr1000THD))
-			phy->speed = 1000;
-	}
-
-	anlpar = mii->mir(mii, phyno, Anlpar);
-	if(phy->speed == 0){
-		r = phy->anar & anlpar;
-		if(r & AnaTXFD){
-			phy->speed = 100;
-			phy->fd = 1;
-		}
-		else if(r & AnaTXHD)
-			phy->speed = 100;
-		else if(r & Ana10FD){
-			phy->speed = 10;
-			phy->fd = 1;
-		}
-		else if(r & Ana10HD)
-			phy->speed = 10;
-	}
-	if(phy->speed == 0) {
-		// print("miistatus: phy speed 0\n");
-		return -1;
-	}
-
-	if(phy->fd){
-		p = phy->fc;
-		r = anlpar & (AnaAP|AnaP);
-		if(p == AnaAP && r == (AnaAP|AnaP))
-			phy->tfc = 1;
-		else if(p == (AnaAP|AnaP) && r == AnaAP)
-			phy->rfc = 1;
-		else if((p & AnaP) && (r & AnaP))
-			phy->rfc = phy->tfc = 1;
-	}
-
-	phy->link = 1;
-
-	return 0;
-}
--- a/sys/src/9/teg2/ethermii.h
+++ /dev/null
@@ -1,116 +1,0 @@
-typedef struct Mii Mii;
-typedef struct MiiPhy MiiPhy;
-
-enum {					/* registers */
-	Bmcr		= 0x00,		/* Basic Mode Control */
-	Bmsr		= 0x01,		/* Basic Mode Status */
-	Phyidr1		= 0x02,		/* PHY Identifier #1 */
-	Phyidr2		= 0x03,		/* PHY Identifier #2 */
-	Anar		= 0x04,		/* Auto-Negotiation Advertisement */
-	Anlpar		= 0x05,		/* AN Link Partner Ability */
-	Aner		= 0x06,		/* AN Expansion */
-	Annptr		= 0x07,		/* AN Next Page TX */
-	Annprr		= 0x08,		/* AN Next Page RX */
-	Mscr		= 0x09,		/* MASTER-SLAVE Control */
-	Mssr		= 0x0A,		/* MASTER-SLAVE Status */
-	Esr		= 0x0F,		/* Extended Status */
-
-	NMiiPhyr	= 32,
-	NMiiPhy		= 32,
-};
-
-enum {					/* Bmcr */
-	BmcrSs1		= 0x0040,	/* Speed Select[1] */
-	BmcrCte		= 0x0080,	/* Collision Test Enable */
-	BmcrDm		= 0x0100,	/* Duplex Mode */
-	BmcrRan		= 0x0200,	/* Restart Auto-Negotiation */
-	BmcrI		= 0x0400,	/* Isolate */
-	BmcrPd		= 0x0800,	/* Power Down */
-	BmcrAne		= 0x1000,	/* Auto-Negotiation Enable */
-	BmcrSs0		= 0x2000,	/* Speed Select[0] */
-	BmcrLe		= 0x4000,	/* Loopback Enable */
-	BmcrR		= 0x8000,	/* Reset */
-};
-
-enum {					/* Bmsr */
-	BmsrEc		= 0x0001,	/* Extended Capability */
-	BmsrJd		= 0x0002,	/* Jabber Detect */
-	BmsrLs		= 0x0004,	/* Link Status */
-	BmsrAna		= 0x0008,	/* Auto-Negotiation Ability */
-	BmsrRf		= 0x0010,	/* Remote Fault */
-	BmsrAnc		= 0x0020,	/* Auto-Negotiation Complete */
-	BmsrPs		= 0x0040,	/* Preamble Suppression Capable */
-	BmsrEs		= 0x0100,	/* Extended Status */
-	Bmsr100T2HD	= 0x0200,	/* 100BASE-T2 HD Capable */
-	Bmsr100T2FD	= 0x0400,	/* 100BASE-T2 FD Capable */
-	Bmsr10THD	= 0x0800,	/* 10BASE-T HD Capable */
-	Bmsr10TFD	= 0x1000,	/* 10BASE-T FD Capable */
-	Bmsr100TXHD	= 0x2000,	/* 100BASE-TX HD Capable */
-	Bmsr100TXFD	= 0x4000,	/* 100BASE-TX FD Capable */
-	Bmsr100T4	= 0x8000,	/* 100BASE-T4 Capable */
-};
-
-enum {					/* Anar/Anlpar */
-	Ana10HD		= 0x0020,	/* Advertise 10BASE-T */
-	Ana10FD		= 0x0040,	/* Advertise 10BASE-T FD */
-	AnaTXHD		= 0x0080,	/* Advertise 100BASE-TX */
-	AnaTXFD		= 0x0100,	/* Advertise 100BASE-TX FD */
-	AnaT4		= 0x0200,	/* Advertise 100BASE-T4 */
-	AnaP		= 0x0400,	/* Pause */
-	AnaAP		= 0x0800,	/* Asymmetrical Pause */
-	AnaRf		= 0x2000,	/* Remote Fault */
-	AnaAck		= 0x4000,	/* Acknowledge */
-	AnaNp		= 0x8000,	/* Next Page Indication */
-};
-
-enum {					/* Mscr */
-	Mscr1000THD	= 0x0100,	/* Advertise 1000BASE-T HD */
-	Mscr1000TFD	= 0x0200,	/* Advertise 1000BASE-T FD */
-};
-
-enum {					/* Mssr */
-	Mssr1000THD	= 0x0400,	/* Link Partner 1000BASE-T HD able */
-	Mssr1000TFD	= 0x0800,	/* Link Partner 1000BASE-T FD able */
-};
-
-enum {					/* Esr */
-	Esr1000THD	= 0x1000,	/* 1000BASE-T HD Capable */
-	Esr1000TFD	= 0x2000,	/* 1000BASE-T FD Capable */
-	Esr1000XHD	= 0x4000,	/* 1000BASE-X HD Capable */
-	Esr1000XFD	= 0x8000,	/* 1000BASE-X FD Capable */
-};
-
-typedef struct Mii {
-	Lock;
-	int	nphy;
-	int	mask;
-	MiiPhy*	phy[NMiiPhy];
-	MiiPhy*	curphy;
-
-	void*	ctlr;
-	int	(*mir)(Mii*, int, int);
-	int	(*miw)(Mii*, int, int, int);
-} Mii;
-
-typedef struct MiiPhy {
-	Mii*	mii;
-	int	oui;
-	int	phyno;
-
-	int	anar;
-	int	fc;
-	int	mscr;
-
-	int	link;
-	int	speed;
-	int	fd;
-	int	rfc;
-	int	tfc;
-};
-
-extern int mii(Mii*, int);
-extern int miiane(Mii*, int, int, int);
-extern int miimir(Mii*, int);
-extern int miimiw(Mii*, int, int);
-extern int miireset(Mii*);
-extern int miistatus(Mii*);