~kris/9p

9hist

3c5e5c015fc8bce2a416e6b182b51e5f9c33ecba — David du Colombier 27 years ago c6f6d9f
Plan 9 from Bell Labs 1999-03-18
1 files changed, 66 insertions(+), 52 deletions(-)

M pc/etherelnk3.c
M pc/etherelnk3.c => pc/etherelnk3.c +66 -52
@@ 213,6 213,8 @@ enum {						/* Window 1 - operating set */

enum {						/* Window 2 - station address */
	Wstation		= 0x0002,

	ResetOp905B		= 0x000C,
};

enum {						/* Window 3 - FIFO management */


@@ 223,6 225,7 @@ enum {						/* Window 3 - FIFO management */
	RomControl		= 0x0006,	/* 3C509B, 3C59[27] */
	MacControl		= 0x0006,	/* 3C59[0257] */
	ResetOptions		= 0x0008,	/* 3C59[0257] */
	MediaOptions		= 0x0008,	/* 3C905B */
	RxFree			= 0x000A,
						/* InternalConfig bits */
	disableBadSsdDetect	= 0x00000100,


@@ 1454,75 1457,66 @@ setfullduplex(int port)
}

static int
miir(int port, int phyad, int regad)
miimdi(int port, int n)
{
	int data, i, w, x;

	w = (STATUS(port)>>13) & 0x07;
	COMMAND(port, SelectRegisterWindow, Wdiagnostic);

	port += PhysicalMgmt;
	int data, i;

	/*
	 * Taken from the Cyclone manual appendix describing
	 * how to programme the MII Management Interface.
	 */
	/*
	 * Preamble
	 * Read n bits from the MII Management Register.
	 */
	for(i = 0; i < 32; i++){
		outs(port, mgmtDir|mgmtData);
		microdelay(1);
		outs(port, mgmtDir|mgmtData|mgmtClk);
	data = 0;
	for(i = n-1; i >= 0; i--){
		if(ins(port) & mgmtData)
			data |= (1<<i);
		microdelay(1);
	}

	/*
	 * ST+OP+PHYAD+REGAD
	 */
	x = 0x1800|(phyad<<5)|regad;
	for(i = 14-1; i >= 0; i--){
		if(x & (1<<i))
			data = mgmtDir|mgmtData;
		else
			data = mgmtDir;
		outs(port, data);
		outs(port, mgmtClk);
		microdelay(1);
		outs(port, data|mgmtClk);
		outs(port, 0);
		microdelay(1);
	}

	/*
	 * "Z" cycle (turnaround) + one read (0 means there's a PHY responding).
	 */
	data = 0;
	outs(port, 0);
	microdelay(1);
	outs(port, mgmtClk);
	x = ins(port);
	if(x & mgmtData)
		data |= (1<<16);
	return data;
}

static void
miimdo(int port, int bits, int n)
{
	int i, mdo;

	/*
	 * 16 data read cycles.
	 * Write n bits to the MII Management Register.
	 */
	for(i = 16-1; i >= 0; i--){
		outs(port, 0);
	for(i = n-1; i >= 0; i--){
		if(bits & (1<<i))
			mdo = mgmtDir|mgmtData;
		else
			mdo = mgmtDir;
		outs(port, mdo);
		microdelay(1);
		outs(port, mgmtClk);
		outs(port, mdo|mgmtClk);
		microdelay(1);
		x = ins(port);
		if(x & mgmtData)
			data |= (1<<i);
		outs(port, mdo);
		microdelay(1);
	}
}

static int
miir(int port, int phyad, int regad)
{
	int data, w;

	w = (STATUS(port)>>13) & 0x07;
	COMMAND(port, SelectRegisterWindow, Wdiagnostic);
	port += PhysicalMgmt;

	/*
	 * "Z" cycle (turnaround).
	 * Preamble;
	 * ST+OP+PHYAD+REGAD;
	 * TA + 16 data bits.
	 */
	outs(port, 0);
	microdelay(1);
	outs(port, mgmtClk);
	miimdo(port, 0xFFFFFFFF, 32);
	miimdo(port, 0x1800|(phyad<<5)|regad, 14);
	data = miimdi(port, 18);

	port -= PhysicalMgmt;
	COMMAND(port, SelectRegisterWindow, w);


@@ 1763,8 1757,11 @@ etherelnk3reset(Ether* ether)
/*
 * forgive me, but i am weak
 */
if(did == 0x9055)
if(did == 0x9055){
   xcvr = xcvrMii;
   XCVRDEBUG("9055 reset ops 0x%uX\n",
	ins(port+ResetOp905B));
}
else
	if(xcvr & autoSelect)
		xcvr = autoselect(port, xcvr, rxstatus9);


@@ 1777,12 1774,29 @@ else
		scanphy(port);
		 */
		phyaddr = 24;
for(i = 0; i < 7; i++)
    XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
XCVRDEBUG("\n");

{	int phystat, timeo;
	for(timeo = 0; timeo < 30; timeo++){
		phystat = miir(port, phyaddr, 0x01);
		if(phystat & 0x20)
			break;
		XCVRDEBUG(" %2.2uX", phystat);
		delay(100);
	}
	XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
	XCVRDEBUG("\n");
}

		anar = miir(port, phyaddr, 0x04);
		anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
		anar &= anlpar;
		miir(port, phyaddr, 0x00);
		XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
			anar, anlpar, miir(port, phyaddr, 0x00), miir(port, phyaddr, 0x01));
			anar, anlpar, miir(port, phyaddr, 0x00),
			miir(port, phyaddr, 0x01));
		for(i = 0; i < ether->nopt; i++){
			if(cistrcmp(ether->opt[i], "fullduplex") == 0)
				anar |= 0x0100;