Hi all,

Many if_dc cards are still broken in RELENG_4. Can you please
try this diff if you own such a broken card ?

If you have a Conexant LANfinity MiniPCI 10/100BaseTX card, I'd like
to have feedback if full duplex mode works now too.

Thank you very much for your tests. I'd like to see all these
DEC/Intel 21143 clone cards fixed for 4.8R.

Martin

-----------------------------------------------------------------

http://people.freebsd.org/~mbr/patches/if_dc.c-MFC.diff

MFC Rev. 1.80, 1.81

Dynamically configure the width of the srom.  This code comes from
OpenBSD who got the code (or the idea) from the NetBSD tlp driver.

MFC Rev. 1.67

Fix Conexant chips which always reports carrier lost
on full duplex mode.

Index: if_dc.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_dc.c,v
retrieving revision 1.9.2.38
diff -u -r1.9.2.38 if_dc.c
--- if_dc.c     5 Feb 2003 22:10:04 -0000       1.9.2.38
+++ if_dc.c     7 Feb 2003 19:01:18 -0000
@@ -223,6 +223,7 @@
 static void dc_eeprom_getword  __P((struct dc_softc *, int, u_int16_t *));
 static void dc_eeprom_getword_pnic
                                __P((struct dc_softc *, int, u_int16_t *));
+static void dc_eeprom_width    __P((struct dc_softc *));
 static void dc_read_eeprom     __P((struct dc_softc *, caddr_t, int,
                                                        int, int));

@@ -250,6 +251,7 @@
 static int dc_list_rx_init     __P((struct dc_softc *));
 static int dc_list_tx_init     __P((struct dc_softc *));

+static void dc_read_srom       __P((struct dc_softc *, int));
 static void dc_parse_21143_srom        __P((struct dc_softc *));
 static void dc_decode_leaf_sia __P((struct dc_softc *,
                                    struct dc_eblock_sia *));
@@ -324,6 +326,70 @@
                CSR_READ_4(sc, DC_BUSCTL);
 }

+static void dc_eeprom_width(sc)
+       struct dc_softc         *sc;
+{
+       int i;
+
+       /* Force EEPROM to idle state. */
+       dc_eeprom_idle(sc);
+
+       /* Enter EEPROM access mode. */
+       CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
+       dc_delay(sc);
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+       dc_delay(sc);
+
+       for (i = 3; i--;) {
+               if (6 & (1 << i))
+                       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               else
+                       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               dc_delay(sc);
+               DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+               DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }
+
+       for (i = 1; i <= 12; i++) {
+               DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+               if (!(CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)) {
+                       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+                       dc_delay(sc);
+                       break;
+               }
+               DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }
+
+       /* Turn off EEPROM access mode. */
+       dc_eeprom_idle(sc);
+
+       if (i < 4 || i > 12)
+               sc->dc_romwidth = 6;
+       else
+               sc->dc_romwidth = i;
+
+       /* Enter EEPROM access mode. */
+       CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
+       dc_delay(sc);
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+       dc_delay(sc);
+
+       /* Turn off EEPROM access mode. */
+       dc_eeprom_idle(sc);
+}
+
 static void dc_eeprom_idle(sc)
        struct dc_softc         *sc;
 {
@@ -363,21 +429,24 @@
 {
        register int            d, i;

-       /*
-        * The AN985 has a 93C66 EEPROM on it instead of
-        * a 93C46. It uses a different bit sequence for
-        * specifying the "read" opcode.
-        */
-       if (DC_IS_CENTAUR(sc) || DC_IS_CONEXANT(sc))
-               d = addr | (DC_EECMD_READ << 2);
-       else
-               d = addr | DC_EECMD_READ;
+       d = DC_EECMD_READ >> 6;
+       for (i = 3; i--; ) {
+               if (d & (1 << i))
+                       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               else
+                       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               dc_delay(sc);
+               DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+               DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }

        /*
         * Feed in each bit and strobe the clock.
         */
-       for (i = 0x400; i; i >>= 1) {
-               if (d & i) {
+       for (i = sc->dc_romwidth; i--;) {
+               if (addr & (1 << i)) {
                        SIO_SET(DC_SIO_EE_DATAIN);
                } else {
                        SIO_CLR(DC_SIO_EE_DATAIN);
@@ -1572,6 +1641,7 @@

        m->dc_next = sc->dc_mi;
        sc->dc_mi = m;
+       free(sc->dc_srom, M_DEVBUF);

        sc->dc_pmode = DC_PMODE_SIA;

@@ -1630,6 +1700,17 @@
        return;
 }

+static void dc_read_srom(sc, bits)
+       struct dc_softc         *sc;
+       int                     bits;
+{
+       int size;
+
+       size = 2 << bits;
+       sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT);
+       dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0);
+}
+
 static void dc_parse_21143_srom(sc)
        struct dc_softc         *sc;
 {
@@ -1753,13 +1834,17 @@
        sc->dc_info = dc_devtype(dev);
        revision = pci_read_config(dev, DC_PCI_CFRV, 4) & 0x000000FF;

+       /* Get the eeprom width, but PNIC has no eeprom */
+       if (sc->dc_info->dc_did != DC_DEVICEID_82C168)
+               dc_eeprom_width(sc);
+
        switch(sc->dc_info->dc_did) {
        case DC_DEVICEID_21143:
                sc->dc_type = DC_TYPE_21143;
                sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
                sc->dc_flags |= DC_REDUCED_MII_POLL;
                /* Save EEPROM contents so we can parse them later. */
-               dc_read_eeprom(sc, (caddr_t)&sc->dc_srom, 0, 512, 0);
+               dc_read_srom(sc, sc->dc_romwidth);
                break;
        case DC_DEVICEID_DM9009:
        case DC_DEVICEID_DM9100:
@@ -1779,6 +1864,7 @@
                sc->dc_flags |= DC_TX_USE_TX_INTR;
                sc->dc_flags |= DC_TX_ADMTEK_WAR;
                sc->dc_pmode = DC_PMODE_MII;
+               dc_read_srom(sc, sc->dc_romwidth);
                break;
        case DC_DEVICEID_AN985:
        case DC_DEVICEID_EN2242:
@@ -1786,6 +1872,7 @@
                sc->dc_flags |= DC_TX_USE_TX_INTR;
                sc->dc_flags |= DC_TX_ADMTEK_WAR;
                sc->dc_pmode = DC_PMODE_MII;
+               dc_read_srom(sc, sc->dc_romwidth);
                break;
        case DC_DEVICEID_98713:
        case DC_DEVICEID_98713_CP:
@@ -1844,7 +1931,7 @@
                sc->dc_flags |= DC_TX_INTR_ALWAYS;
                sc->dc_flags |= DC_REDUCED_MII_POLL;
                sc->dc_pmode = DC_PMODE_MII;
-               dc_read_eeprom(sc, (caddr_t)&sc->dc_srom, 0, 256, 0);
+               dc_read_srom(sc, sc->dc_romwidth);
                break;
        default:
                printf("dc%d: unknown device: %x\n", sc->dc_unit,
@@ -1908,6 +1995,8 @@
                break;
        case DC_TYPE_AL981:
        case DC_TYPE_AN985:
+               bcopy(&sc->dc_srom[DC_AL_EE_NODEADDR], (caddr_t)&eaddr,
+                   ETHER_ADDR_LEN);
                dc_read_eeprom(sc, (caddr_t)&eaddr, DC_AL_EE_NODEADDR, 3, 0);
                break;
        case DC_TYPE_CONEXANT:
@@ -2468,13 +2557,13 @@
  * the list buffers.
  */

-static void dc_txeof(sc)
+static void
+dc_txeof(sc)
        struct dc_softc         *sc;
 {
        struct dc_desc          *cur_tx = NULL;
        struct ifnet            *ifp;
        int                     idx;
-       u_int32_t               errmask;

        ifp = &sc->arpcom.ac_if;

@@ -2494,7 +2583,6 @@

                if (!(cur_tx->dc_ctl & DC_TXCTL_LASTFRAG) ||
                    cur_tx->dc_ctl & DC_TXCTL_SETUP) {
-                       sc->dc_cdata.dc_tx_cnt--;
                        if (cur_tx->dc_ctl & DC_TXCTL_SETUP) {
                                /*
                                 * Yes, the PNIC is so brain damaged
@@ -2511,21 +2599,29 @@
                                }
                                sc->dc_cdata.dc_tx_chain[idx] = NULL;
                        }
+                       sc->dc_cdata.dc_tx_cnt--;
                        DC_INC(idx, DC_TX_LIST_CNT);
                        continue;
                }

-               if (sc->dc_pmode == DC_PMODE_MII) {
-                       errmask = DC_TXSTAT_ERRSUM|
-                           DC_TXSTAT_NOCARRIER|DC_TXSTAT_CARRLOST;
+               if (DC_IS_CONEXANT(sc)) {
                        /*
-                        * The Conexant chip always reports carrier lost
-                        * in full duplex modes.
+                        * For some reason Conexant chips like
+                        * setting the CARRLOST flag even when
+                        * the carrier is there. In CURRENT we
+                        * have the same problem for Xircom
+                        * cards !
                         */
-                       if (DC_IS_CONEXANT(sc) && (sc->dc_if_media & IFM_FDX)) {
-                               errmask &= ~DC_TXSTAT_CARRLOST;
-                       }
-                       if ((txstat & 0xFFFF) & ~errmask)
+                       if (/*sc->dc_type == DC_TYPE_21143 &&*/
+                           sc->dc_pmode == DC_PMODE_MII &&
+                           ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM|
+                           DC_TXSTAT_NOCARRIER)))
+                               txstat &= ~DC_TXSTAT_ERRSUM;
+               } else {
+                       if (/*sc->dc_type == DC_TYPE_21143 &&*/
+                           sc->dc_pmode == DC_PMODE_MII &&
+                           ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM|
+                           DC_TXSTAT_NOCARRIER|DC_TXSTAT_CARRLOST)))
                                txstat &= ~DC_TXSTAT_ERRSUM;
                }

@@ -2553,11 +2649,13 @@
                DC_INC(idx, DC_TX_LIST_CNT);
        }

-        if (idx != sc->dc_cdata.dc_tx_cons) {
+       if (idx != sc->dc_cdata.dc_tx_cons) {
+               /* some buffers have been freed */
                sc->dc_cdata.dc_tx_cons = idx;
-                ifp->if_flags &= ~IFF_OACTIVE;
-        }
-        ifp->if_timer = (sc->dc_cdata.dc_tx_cnt == 0) ? 0 : 5;
+               ifp->if_flags &= ~IFF_OACTIVE;
+       }
+       ifp->if_timer = (sc->dc_cdata.dc_tx_cnt == 0) ? 0 : 5;
+
        return;
 }

Index: if_dcreg.h
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_dcreg.h,v
retrieving revision 1.4.2.20
diff -u -r1.4.2.20 if_dcreg.h
--- if_dcreg.h  5 Feb 2003 22:10:04 -0000       1.4.2.20
+++ if_dcreg.h  7 Feb 2003 19:01:18 -0000
@@ -688,13 +688,14 @@
        u_int8_t                dc_pmode;
        u_int8_t                dc_link;
        u_int8_t                dc_cachesize;
+       int                     dc_romwidth;
        int                     dc_pnic_rx_bug_save;
        unsigned char           *dc_pnic_rx_buf;
        int                     dc_if_flags;
        int                     dc_if_media;
        u_int32_t               dc_flags;
        u_int32_t               dc_txthresh;
-       u_int8_t                dc_srom[1024];
+       u_int8_t                *dc_srom;
        struct dc_mediainfo     *dc_mi;
        struct dc_list_data     *dc_ldata;
        struct dc_chain_data    dc_cdata;

Martin Blapp, <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
------------------------------------------------------------------
ImproWare AG, UNIXSP & ISP, Zurlindenstrasse 29, 4133 Pratteln, CH
Phone: +41 61 826 93 00 Fax: +41 61 826 93 01
PGP: <finger -l [EMAIL PROTECTED]>
PGP Fingerprint: B434 53FC C87C FE7B 0A18 B84C 8686 EF22 D300 551E
------------------------------------------------------------------



To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-stable" in the body of the message

Reply via email to