Subject: kern/10194: tlp doesn't handle Davicom DM9102
To: None <gnats-bugs@gnats.netbsd.org>
From: IWAMOTO Toshihiro <iwamoto@sat.t.u-tokyo.ac.jp>
List: netbsd-bugs
Date: 05/24/2000 09:12:18
>Number:         10194
>Category:       kern
>Synopsis:       tlp doesn't handle Davicom DM9102
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed May 24 09:13:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     IWAMOTO Toshihiro
>Release:        a week ago -current
>Organization:
	
>Environment:
	
System: NetBSD kiku.my.domain 1.4Y NetBSD 1.4Y (KIKU) #8: Wed May 24 22:31:22 JST 2000     toshii@miyuki.my.domain:/usr/src/syssrc/sys/arch/i386/compile/KIKU i386


>Description:
	Davicom's DM9102 is a tulip clone Ethernet chip.
	This PR adds support for DM9102 as a patch to the tlp driver.
>How-To-Repeat:
	Buy a PC with DM9102 but without a PCI slot, and be at a loss.
>Fix:
	Apply the following patch.
	Although this is basically a trivial patch, it should be noted
	that DM9102 can't handle a setup packet if TDCTL_Tx_FS and
	TDCTL_Tx_LS bits are set. Intel's 21143 hardware reference
	manual says that these bits should be 0 for setup packets.
	As this patch unconditionally clears these bits, this patch
	should fail with a variant of tulip which requires these bits
	to be set (if such tulip clone ever exists).
	As a further notice, FreeBSD's "dc" driver (for tulip clones)
	unconditionally sets these bits 0.
	
Index: ic/tulip.c
===================================================================
RCS file: /export/NetBSD-CVS/syssrc/sys/dev/ic/tulip.c,v
retrieving revision 1.64
diff -u -r1.64 tulip.c
--- ic/tulip.c	2000/05/18 03:02:45	1.64
+++ ic/tulip.c	2000/05/24 15:02:24
@@ -146,6 +146,7 @@
 void	tlp_2114x_preinit __P((struct tulip_softc *));
 void	tlp_2114x_mii_preinit __P((struct tulip_softc *));
 void	tlp_pnic_preinit __P((struct tulip_softc *));
+void	tlp_dm9102_preinit __P((struct tulip_softc *));
 
 void	tlp_21140_reset __P((struct tulip_softc *));
 void	tlp_21142_reset __P((struct tulip_softc *));
@@ -316,6 +317,11 @@
 		sc->sc_flags |= TULIPF_IC_FS;
 		break;
 
+	case TULIP_CHIP_DM9102:
+		sc->sc_preinit = tlp_dm9102_preinit;
+		sc->sc_tdctl_ch = TDCTL_CH;
+		sc->sc_tdctl_er = 0;
+		break;
 	default:
 		/*
 		 * Default to running in ring mode.
@@ -382,9 +388,13 @@
 	 * 4-byte aligned.  We're almost guaranteed to have to copy
 	 * the packet in that case, so we just limit ourselves to
 	 * one segment.
+	 *
+	 * For DM9102, an mbuf chain should be a single mbuf
+	 * cluster buffer.
 	 */
 	switch (sc->sc_chip) {
 	case TULIP_CHIP_X3201_3:
+	case TULIP_CHIP_DM9102:
 		sc->sc_ntxsegs = 1;
 		break;
 
@@ -617,6 +627,7 @@
 	tlp_stop(sc, 1);
 }
 
+
 /*
  * tlp_start:		[ifnet interface function]
  *
@@ -777,7 +788,7 @@
 
 #ifdef TLP_DEBUG
 		if (ifp->if_flags & IFF_DEBUG) {
-			printf("     txsoft %p trainsmit chain:\n", txs);
+			printf("     txsoft %p transmit chain:\n", txs);
 			for (seg = sc->sc_txnext;; seg = TULIP_NEXTTX(seg)) {
 				printf("     descriptor %d:\n", seg);
 				printf("       td_status:   0x%08x\n",
@@ -1397,7 +1408,7 @@
 #ifdef TLP_DEBUG
 		if (ifp->if_flags & IFF_DEBUG) {
 			int i;
-			printf("    txsoft %p trainsmit chain:\n", txs);
+			printf("    txsoft %p transmit chain:\n", txs);
 			for (i = txs->txs_firstdesc;; i = TULIP_NEXTTX(i)) {
 				printf("     descriptor %d:\n", i);
 				printf("       td_status:   0x%08x\n",
@@ -1618,6 +1629,9 @@
 		 * Note: We must *always* set these bits; a cache
 		 * alignment of 0 is RESERVED.
 		 */
+	case 0:
+		sc->sc_busmode |= BUSMODE_CAL_NONE;
+		break;
 	case 8:
 		sc->sc_busmode |= BUSMODE_CAL_8LW;
 		break;
@@ -2643,10 +2657,11 @@
 
 	sc->sc_txdescs[sc->sc_txnext].td_bufaddr1 =
 	    htole32(TULIP_CDSPADDR(sc));
+	/* 21143's document says that FS and LS should be cleared */
 	sc->sc_txdescs[sc->sc_txnext].td_ctl =
 	    htole32((TULIP_SETUP_PACKET_LEN << TDCTL_SIZE1_SHIFT) |
-	    sc->sc_filtmode | TDCTL_Tx_SET | TDCTL_Tx_FS |
-	    TDCTL_Tx_LS | TDCTL_Tx_IC | sc->sc_tdctl_ch |
+	    sc->sc_filtmode | TDCTL_Tx_SET |
+	    TDCTL_Tx_IC | sc->sc_tdctl_ch |
 	    (sc->sc_txnext == (TULIP_NTXDESC - 1) ? sc->sc_tdctl_er : 0));
 	sc->sc_txdescs[sc->sc_txnext].td_status = htole32(TDSTAT_OWN);
 	TULIP_CDTXSYNC(sc, sc->sc_txnext, txs->txs_ndescs,
@@ -3308,6 +3323,14 @@
 		 */
 		sc->sc_opmode |= OPMODE_PNIC_TBEN;
 	}
+}
+
+void
+tlp_dm9102_preinit(sc)
+	struct tulip_softc *sc;
+{
+	sc->sc_opmode |= OPMODE_MBO|OPMODE_HBD;
+	TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode);
 }
 
 /*
Index: ic/tulipreg.h
===================================================================
RCS file: /export/NetBSD-CVS/syssrc/sys/dev/ic/tulipreg.h,v
retrieving revision 1.18
diff -u -r1.18 tulipreg.h
--- ic/tulipreg.h	2000/04/04 19:22:52	1.18
+++ ic/tulipreg.h	2000/05/24 15:05:39
@@ -547,12 +547,12 @@
 #define	OPMODE_CA		0x00020000	/* capture effect enable */
 #define	OPMODE_PNIC_TBEN	0x00020000	/* Tx backoff offset enable */
 	/*
-	 * On Davicom DM9102, OPMODE_PS and OPMODE_HBD must
-	 * always be set.
+	 * On Davicom DM9102, OPMODE_HBD must always be set.
 	 */
 #define	OPMODE_PS		0x00040000	/* port select:
 						   1 = MII/SYM, 0 = SRL
-						   (21140) */
+						   (21140)
+						   1 = HomePNA (DM9102A) */
 #define	OPMODE_HBD		0x00080000	/* heartbeat disable:
 						   set in MII/SYM 100mbps,
 						   set according to PHY
Index: pci/if_tlp_pci.c
===================================================================
RCS file: /export/NetBSD-CVS/syssrc/sys/dev/pci/if_tlp_pci.c,v
retrieving revision 1.37
diff -u -r1.37 if_tlp_pci.c
--- pci/if_tlp_pci.c	2000/04/04 19:22:51	1.37
+++ pci/if_tlp_pci.c	2000/05/24 15:05:50
@@ -176,10 +176,8 @@
 	{ PCI_VENDOR_COMPEX,		PCI_PRODUCT_COMPEX_RL100ATX,
 	  TULIP_CHIP_WB89C840F },
 
-#if 0
 	{ PCI_VENDOR_DAVICOM,		PCI_PRODUCT_DAVICOM_DM9102,
 	  TULIP_CHIP_DM9102 },
-#endif
 
 	{ PCI_VENDOR_ADMTEK,		PCI_PRODUCT_ADMTEK_AL981,
 	  TULIP_CHIP_AL981 },
@@ -526,8 +524,11 @@
 	/*
 	 * Get the cacheline size.
 	 */
-	sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag,
-	    PCI_BHLC_REG));
+	if (sc->sc_chip == TULIP_CHIP_DM9102)
+		sc->sc_cacheline = 0;
+	else
+		sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag,
+		    PCI_BHLC_REG));
 
 	/*
 	 * Get PCI data moving command info.
@@ -798,6 +799,16 @@
 		/*
 		 * Winbond 89C840F has an MII attached to the SIO.
 		 */
+		sc->sc_mediasw = &tlp_sio_mii_mediasw;
+		break;
+
+	case TULIP_CHIP_DM9102:
+		/*
+		 * DM9102's Ethernet address is located
+		 * at offset 20 of its EEPROM.
+		 */
+		memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN);
+
 		sc->sc_mediasw = &tlp_sio_mii_mediasw;
 		break;
 
>Release-Note:
>Audit-Trail:
>Unformatted: