Module Name:    src
Committed By:   phx
Date:           Tue Mar  8 19:00:39 UTC 2011

Modified Files:
        src/sys/arch/sandpoint/stand/altboot: stg.c

Log Message:
Driver seems to work now. Successfully booted a kernel via BOOTP and NFS on
an ST1023-compatible IC+ IP1000A chip.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/sandpoint/stand/altboot/stg.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sandpoint/stand/altboot/stg.c
diff -u src/sys/arch/sandpoint/stand/altboot/stg.c:1.1 src/sys/arch/sandpoint/stand/altboot/stg.c:1.2
--- src/sys/arch/sandpoint/stand/altboot/stg.c:1.1	Sun Mar  6 13:55:12 2011
+++ src/sys/arch/sandpoint/stand/altboot/stg.c	Tue Mar  8 19:00:38 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: stg.c,v 1.1 2011/03/06 13:55:12 phx Exp $ */
+/* $NetBSD: stg.c,v 1.2 2011/03/08 19:00:38 phx Exp $ */
 
 /*-
  * Copyright (c) 2011 Frank Wille.
@@ -52,17 +52,15 @@
 #define ALLOC(T,A)		(T *)allocaligned(sizeof(T),(A))
 
 struct desc {
-	uint64_t xd0, xd1, xd2;
+	uint64_t xd0, xd1, xd2, dummy;
 };
-/* xd1 */
-#define RXLEN(x)		((x) & 0xffff)
-#define RXERRORMASK		0x3f0000LL
-#define TXNOALIGN		(1ULL << 16)
-#define TXFRAGCOUNT(x)		(((uint64_t)((x) & 0xf)) << 48)
-#define DONE			(1ULL << 31)
-/* xd2 */
-#define FRAGADDR(x)		((uint64_t)(x))
-#define FRAGLEN(x)		(((uint64_t)((x) & 0xffff)) << 48)
+#define T1_EMPTY		(1U << 31)	/* no Tx frame available */
+#define T1_NOALIGN		(03 << 16)	/* allow any Tx alignment */
+#define T1_CNTSHIFT		24		/* Tx fragment count */
+#define T2_LENSHIFT		48		/* Tx frame length */
+#define R1_DONE			(1U << 31)	/* desc has a Rx frame */
+#define R1_FL_MASK		0xffff		/* Rx frame length */
+#define R1_ER_MASK		0x3f0000	/* Rx error indication */
 
 #define STGE_DMACtrl		0x00
 #define  DMAC_RxDMAComplete	(1U << 3)
@@ -73,6 +71,7 @@
 #define STGE_TFDListPtrHi	0x14
 #define STGE_RFDListPtrLo	0x1c
 #define STGE_RFDListPtrHi	0x20
+#define STGE_DebugCtrl		0x2c
 #define STGE_AsicCtrl		0x30
 #define  AC_PhyMedia		(1U << 7)
 #define  AC_GlobalReset		(1U << 16)
@@ -93,6 +92,8 @@
 #define  EC_EepromBusy		(1U << 15)
 #define STGE_IntEnable		0x5c
 #define STGE_MACCtrl		0x6c
+#define  MC_DuplexSelect	(1U << 5)
+#define  MC_StatisticsDisable	(1U << 22)
 #define  MC_TxEnable		(1U << 24)
 #define  MC_RxEnable		(1U << 27)
 #define STGE_PhyCtrl		0x76
@@ -110,18 +111,17 @@
 #define STGE_StationAddress0	0x78
 #define STGE_StationAddress1	0x7a
 #define STGE_StationAddress2	0x7c
+#define STGE_MaxFrameSize	0x84
+#define STGE_ReceiveMode	0x88
+#define  RM_ReceiveUnicast	(1U << 0)
+#define  RM_ReceiveMulticast	(1U << 1)
+#define  RM_ReceiveBroadcast	(1U << 2)
+#define  RM_ReceiveAllFrames	(1U << 3)
+#define  RM_ReceiveMulticastHash (1U << 4)
+#define  RM_ReceiveIPMulticast	(1U << 5)
 
 #define STGE_EEPROM_SA0		0x10
 
-#define MII_PSSR		0x11	/* MAKPHY status register */
-#define  PSSR_DUPLEX		0x2000	/* FDX */
-#define  PSSR_RESOLVED		0x0800	/* speed and duplex resolved */
-#define  PSSR_LINK		0x0400  /* link indication */
-#define  PSSR_SPEED(x)		(((x) >> 14) & 0x3)
-#define  SPEED10		0
-#define  SPEED100		1
-#define  SPEED1000 		2
-
 #define FRAMESIZE	1536
 
 struct local {
@@ -162,7 +162,7 @@
 	struct desc *txd, *rxd;
 	uint8_t *en;
 	unsigned i;
-	uint32_t reg;
+	uint32_t macctl, reg;
 
 	l = ALLOC(struct local, 32);		/* desc alignment */
 	memset(l, 0, sizeof(struct local));
@@ -231,6 +231,43 @@
 	DPRINTF(("PHY %d (%04x.%04x)\n", l->phy,
 	    mii_read(l, l->phy, 2), mii_read(l, l->phy, 3)));
 
+	/* setup descriptors */
+	txd = &l->txd[0];
+	txd[0].xd0 = htole64(VTOPHYS(&txd[1]));
+	txd[0].xd1 = htole64(T1_EMPTY);
+	txd[1].xd0 = htole64(VTOPHYS(&txd[0]));
+	txd[1].xd1 = htole64(T1_EMPTY);
+	rxd = &l->rxd[0];
+	rxd[0].xd0 = htole64(VTOPHYS(&rxd[1]));
+	rxd[0].xd2 = htole64((uint64_t)VTOPHYS(l->rxstore[0]) |
+	    ((uint64_t)FRAMESIZE << 48));
+	rxd[1].xd0 = htole64(VTOPHYS(&rxd[0]));
+	rxd[1].xd2 = htole64((uint64_t)VTOPHYS(l->rxstore[1]) |
+	    ((uint64_t)FRAMESIZE << 48));
+	wbinv(l, sizeof(struct local));
+
+	CSR_WRITE_2(l, STGE_IntEnable, 0);
+	CSR_WRITE_2(l, STGE_ReceiveMode, RM_ReceiveUnicast |
+	    RM_ReceiveBroadcast | RM_ReceiveAllFrames | RM_ReceiveMulticast);
+	CSR_WRITE_4(l, STGE_TFDListPtrHi, 0);
+	CSR_WRITE_4(l, STGE_TFDListPtrLo, VTOPHYS(txd));
+	CSR_WRITE_4(l, STGE_RFDListPtrHi, 0);
+	CSR_WRITE_4(l, STGE_RFDListPtrLo, VTOPHYS(rxd));
+	CSR_WRITE_2(l, STGE_MaxFrameSize, FRAMESIZE);
+	CSR_WRITE_4(l, STGE_MACCtrl, 0);	/* do IFSSelect(0) first */
+	macctl = MC_StatisticsDisable | MC_TxEnable | MC_RxEnable;
+
+	if ((pcicfgread(tag, PCI_CLASS_REG) & 0xff) >= 6) {
+		/* some workarounds for revisions >= 6 */
+		CSR_WRITE_2(l, STGE_DebugCtrl,
+		    CSR_READ_2(l, STGE_DebugCtrl) | 0x0200);
+		CSR_WRITE_2(l, STGE_DebugCtrl,
+		    CSR_READ_2(l, STGE_DebugCtrl) | 0x0010);
+		CSR_WRITE_2(l, STGE_DebugCtrl,
+		    CSR_READ_2(l, STGE_DebugCtrl) | 0x0020);
+	}
+
+	/* auto negotiation, set the current media */
 	mii_dealan(l, 5);
 
 	reg = CSR_READ_1(l, STGE_PhyCtrl);
@@ -245,34 +282,13 @@
 		printf("10Mbps");
 		break;
 	}
-	if (reg & PC_PhyDuplexStatus)
+	if (reg & PC_PhyDuplexStatus) {
+		macctl |= MC_DuplexSelect;
 		printf("-FDX");
+	}
 	printf("\n");
+	CSR_WRITE_4(l, STGE_MACCtrl, macctl);
 
-	/* setup descriptors */
-	txd = &l->txd[0];
-	txd[0].xd0 = htole64(VTOPHYS(&txd[1]));
-	txd[0].xd1 = htole64(DONE);
-	txd[1].xd0 = htole64(VTOPHYS(&txd[0]));
-	txd[1].xd1 = htole64(DONE);
-	rxd = &l->rxd[0];
-	rxd[0].xd0 = htole64(VTOPHYS(&rxd[1]));
-	rxd[0].xd2 = htole64(FRAGADDR(VTOPHYS(l->rxstore[0])) |
-	    FRAGLEN(FRAMESIZE));
-	rxd[1].xd0 = htole64(VTOPHYS(&rxd[0]));
-	rxd[1].xd2 = htole64(FRAGADDR(VTOPHYS(l->rxstore[1])) |
-	    FRAGLEN(FRAMESIZE));
-	wbinv(l, sizeof(struct local));
-
-	CSR_WRITE_2(l, STGE_IntEnable, 0);
-	CSR_WRITE_4(l, STGE_TFDListPtrHi, 0);
-	CSR_WRITE_4(l, STGE_TFDListPtrLo, VTOPHYS(txd));
-	CSR_WRITE_4(l, STGE_RFDListPtrHi, 0);
-	CSR_WRITE_4(l, STGE_RFDListPtrLo, VTOPHYS(rxd));
-	CSR_WRITE_4(l, STGE_MACCtrl, MC_TxEnable | MC_RxEnable);
-#if 0
-	CSR_WRITE_4(l, STGE_DMACtrl, DMAC_RxDMAPollNow | DMAC_TxDMAPollNow);
-#endif
 	return l;
 }
 
@@ -285,16 +301,13 @@
 
 	wbinv(buf, len);
 	txd = &l->txd[l->tx];
-	txd->xd1 = htole64(DONE);
-	wbinv(txd, sizeof(struct desc));
-	txd->xd2 = htole64(FRAGADDR(VTOPHYS(buf)) | FRAGLEN(len));
-	txd->xd1 = htole64(DONE | TXNOALIGN | 0x400000 | TXFRAGCOUNT(1));
-	txd->xd1 = htole64(TXNOALIGN | 0x400000 | TXFRAGCOUNT(1));
+	txd->xd2 = htole64(VTOPHYS(buf) | ((uint64_t)len << 48));
+	txd->xd1 = htole64(T1_NOALIGN | (1 << 24));
 	wbinv(txd, sizeof(struct desc));
-	CSR_WRITE_4(l, STGE_DMACtrl, DMAC_TxDMAPollNow);	/* XXX ? */
+	CSR_WRITE_4(l, STGE_DMACtrl, DMAC_TxDMAPollNow);
 	loop = 100;
 	do {
-		if ((le64toh(txd->xd1) & DONE) != 0)
+		if ((le64toh(txd->xd1) & T1_EMPTY) != 0)
 			goto done;
 		DELAY(10);
 		inv(txd, sizeof(struct desc));
@@ -311,7 +324,7 @@
 {
 	struct local *l = dev;
 	volatile struct desc *rxd;
-	uint64_t sts;
+	uint32_t sts;
 	unsigned bound, len;
 	uint8_t *ptr;
 
@@ -320,21 +333,21 @@
 	rxd = &l->rxd[l->rx];
 	do {
 		inv(rxd, sizeof(struct desc));
-		sts = le64toh(rxd->xd1);
-		if ((sts & DONE) != 0)
+		sts = (uint32_t)le64toh(rxd->xd1);
+		if ((sts & R1_DONE) != 0)
 			goto gotone;
 		DELAY(1000);	/* 1 milli second */
 	} while (--bound > 0);
 	errno = 0;
 	return -1;
   gotone:
-	if ((sts & RXERRORMASK) != 0) {
+	if ((sts & R1_ER_MASK) != 0) {
 		rxd->xd1 = 0;
 		wbinv(rxd, sizeof(struct desc));
 		l->rx ^= 1;
 		goto again;
 	}
-	len = RXLEN(sts);
+	len = sts & R1_FL_MASK;
 	if (len > maxlen)
 		len = maxlen;
 	ptr = l->rxstore[l->rx];
@@ -346,64 +359,49 @@
 	return len;
 }
 
-#define MIICMD_START	1
-#define MIICMD_READ	2
-#define MIICMD_WRITE	1
-#define MIICMD_ACK	2
+#define R0110	6		/* 0110b read op */
+#define W0101	5		/* 0101b write op */
+#define A10	2		/* 10b ack turn around */
 
 /* read the MII by bitbanging STGE_PhyCtrl */
 static int
 mii_read(struct local *l, int phy, int reg)
 {
-	int data, i;
+	unsigned data;
+	int i;
 	uint8_t v;
 
 	/* initiate read access */
-	data = 0;
+	data = (R0110 << 10) | (phy << 5) | reg;
 	mii_bitbang_sync(l);
-	mii_bitbang_send(l, MIICMD_START, 2);
-	mii_bitbang_send(l, MIICMD_READ, 2);
-	mii_bitbang_send(l, phy, 5);
-	mii_bitbang_send(l, reg, 5);
+	mii_bitbang_send(l, data, 14); /* 4OP + 5PHY + 5REG */
 
 	/* switch direction to PHY->host */
 	v = l->phyctrl_saved;
 	CSR_WRITE_1(l, STGE_PhyCtrl, v);
-	DELAY(1);
-	mii_bitbang_clk(l, v);
-	if (CSR_READ_1(l, STGE_PhyCtrl) & PC_MgmtData)
-		printf("MII: read error\n");
-	mii_bitbang_clk(l, v);
 
 	/* read data */
-	for (i = 0; i < 16; i++) {
+	data = 0;
+	for (i = 0; i < 18; i++) { /* 2TA + 16DATA */
 		data <<= 1;
-		if ((CSR_READ_1(l, STGE_PhyCtrl) & PC_MgmtData) != 0)
-			data |= 1;
+		data |= !!(CSR_READ_1(l, STGE_PhyCtrl) & PC_MgmtData);
 		mii_bitbang_clk(l, v);
 	}
-	/* reset direction to host->PHY */
-	CSR_WRITE_1(l, STGE_PhyCtrl, v | PC_MgmtDir);
-	return data;
+
+	return data & 0xffff;
 }
 
 /* write the MII by bitbanging STGE_PhyCtrl */
 static void
 mii_write(struct local *l, int phy, int reg, int val)
 {
+	unsigned data;
 
-	/* initiate write access */
-	mii_bitbang_sync(l);
-	mii_bitbang_send(l, MIICMD_START, 2);
-	mii_bitbang_send(l, MIICMD_WRITE, 2);
-	mii_bitbang_send(l, phy, 5);
-	mii_bitbang_send(l, reg, 5);
-
-	/* send data */
-	mii_bitbang_send(l, MIICMD_ACK, 2);
-	mii_bitbang_send(l, val, 16);
+	data = (W0101 << 28) | (phy << 23) | (reg << 18) | (A10 << 16);
+	data |= val;
 
-	CSR_WRITE_1(l, STGE_PhyCtrl, l->phyctrl_saved | PC_MgmtDir);
+	mii_bitbang_sync(l);
+	mii_bitbang_send(l, data, 32); /* 4OP + 5PHY + 5REG + 2TA + 16DATA */
 }
 
 #define MII_BMCR	0x00	/* Basic mode control register (rw) */

Reply via email to