Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic apply changes from Robert Sprowson in PR 47765 an...



details:   https://anonhg.NetBSD.org/src/rev/194ea7fdf25f
branches:  trunk
changeset: 789780:194ea7fdf25f
user:      chs <chs%NetBSD.org@localhost>
date:      Sat Sep 07 18:55:29 2013 +0000

description:
apply changes from Robert Sprowson in PR 47765 and PR 47788:
 - make sure we wait long enough after resetting the chip.
 - add the necessary delay after changing the FIFO pointer.
 - add a missing interrupt ACK.
 - fix padding of short and odd-length packets.

and a few more changes from me:
 - do 2-byte writes in most places even if SMC91CXX_NO_BYTE_WRITE
   is not defined.  the only ones still conditionalized are
   writing to the interrupt ack/mask registers.
 - the only big-endian front-end of this driver (on mac68k) uses
   a bus_space that does all the byte-swapping in that layer,
   so remove the explicit byte-swapping in the MI part.

tested on mac68k.

diffstat:

 sys/dev/ic/smc91cxx.c |  183 ++++++++++++++++++-------------------------------
 1 files changed, 66 insertions(+), 117 deletions(-)

diffs (truncated from 493 to 300 lines):

diff -r d1799c2ef2e2 -r 194ea7fdf25f sys/dev/ic/smc91cxx.c
--- a/sys/dev/ic/smc91cxx.c     Sat Sep 07 18:17:35 2013 +0000
+++ b/sys/dev/ic/smc91cxx.c     Sat Sep 07 18:55:29 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: smc91cxx.c,v 1.84 2013/06/11 16:57:05 msaitoh Exp $    */
+/*     $NetBSD: smc91cxx.c,v 1.85 2013/09/07 18:55:29 chs Exp $        */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.84 2013/06/11 16:57:05 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.85 2013/09/07 18:55:29 chs Exp $");
 
 #include "opt_inet.h"
 
@@ -126,7 +126,7 @@
 /* XXX Hardware padding doesn't work yet(?) */
 #define        SMC91CXX_SW_PAD
 
-const char *smc91cxx_idstrs[] = {
+static const char *smc91cxx_idstrs[] = {
        NULL,                           /* 0 */
        NULL,                           /* 1 */
        NULL,                           /* 2 */
@@ -146,7 +146,7 @@
 };
 
 /* Supported media types. */
-const int smc91cxx_media[] = {
+static const int smc91cxx_media[] = {
        IFM_ETHER|IFM_10_T,
        IFM_ETHER|IFM_10_5,
 };
@@ -158,7 +158,7 @@
 u_int32_t smc91cxx_mii_bitbang_read(device_t);
 void smc91cxx_mii_bitbang_write(device_t, u_int32_t);
 
-const struct mii_bitbang_ops smc91cxx_mii_bitbang_ops = {
+static const struct mii_bitbang_ops smc91cxx_mii_bitbang_ops = {
        smc91cxx_mii_bitbang_read,
        smc91cxx_mii_bitbang_write,
        {
@@ -208,12 +208,8 @@
 {
        KDASSERT((mask & IM_ERCV_INT) == 0);
 #ifdef SMC91CXX_NO_BYTE_WRITE
-#if BYTE_ORDER == LITTLE_ENDIAN
        bus_space_write_2(bst, bsh, INTR_STAT_REG_B, mask << 8);
 #else
-       bus_space_write_2(bst, bsh, INTR_STAT_REG_B, mask);
-#endif
-#else
        bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
 #endif
        KDASSERT(!(bus_space_read_1(bst, bsh, INTR_MASK_REG_B) & IM_ERCV_INT));
@@ -221,18 +217,12 @@
 
 static inline void
 smc91cxx_intr_ack_write(bus_space_tag_t bst, bus_space_handle_t bsh,
-       uint8_t mask)
+       uint8_t ack, uint8_t mask)
 {
 #ifdef SMC91CXX_NO_BYTE_WRITE
-#if BYTE_ORDER == LITTLE_ENDIAN
-       bus_space_write_2(bst, bsh, INTR_ACK_REG_B,
-           mask | (bus_space_read_2(bst, bsh, INTR_ACK_REG_B) & 0xff00));
+       bus_space_write_2(bst, bsh, INTR_ACK_REG_B, ack | (mask << 8));
 #else
-       bus_space_write_2(bst, bsh, INTR_ACK_REG_B,
-           (mask << 8) | (bus_space_read_2(bst, bsh, INTR_ACK_REG_B) & 0xff));
-#endif
-#else
-       bus_space_write_1(bst, bsh, INTR_ACK_REG_B, mask);
+       bus_space_write_1(bst, bsh, INTR_ACK_REG_B, ack);
 #endif
        KDASSERT(!(bus_space_read_1(bst, bsh, INTR_MASK_REG_B) & IM_ERCV_INT));
 }
@@ -254,7 +244,8 @@
        tmp = bus_space_read_2(bst, bsh, BANK_SELECT_REG_W);
        /* check magic number */
        if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
-               aprint_error_dev(sc->sc_dev, "failed to detect chip, bsr=%04x\n", tmp);
+               aprint_error_dev(sc->sc_dev,
+                    "failed to detect chip, bsr=%04x\n", tmp);
                return;
        }
 
@@ -285,7 +276,8 @@
                scale = MIR_SCALE_91C111;
        }
        memsize = bus_space_read_2(bst, bsh, MEM_INFO_REG_W) & MIR_TOTAL_MASK;
-       if (memsize == 255) memsize++;
+       if (memsize == 255)
+               memsize++;
        memsize *= scale * mult;
 
        format_bytes(pbuf, sizeof(pbuf), memsize);
@@ -344,7 +336,8 @@
                if (tmp & CR_MII_SELECT) {
                        aprint_normal("default media MII");
                        if (sc->sc_chipid == CHIP_91C111) {
-                               aprint_normal(" (%s PHY)\n", (tmp & CR_AUI_SELECT) ?
+                               aprint_normal(" (%s PHY)\n",
+                                   (tmp & CR_AUI_SELECT) ?
                                    "external" : "internal");
                                sc->sc_internal_phy = !(tmp & CR_AUI_SELECT);
                        } else
@@ -373,7 +366,8 @@
                }
                /*FALLTHROUGH*/
        default:
-               aprint_normal("default media %s\n", (aui = (tmp & CR_AUI_SELECT)) ?
+               aprint_normal("default media %s\n",
+                   (aui = (tmp & CR_AUI_SELECT)) ?
                    "AUI" : "UTP");
                for (i = 0; i < NSMC91CxxMEDIA; i++)
                        ifmedia_add(ifm, smc91cxx_media[i], 0, NULL);
@@ -494,16 +488,14 @@
 
        /*
         * This resets the registers mostly to defaults, but doesn't
-        * affect the EEPROM.  After the reset cycle, we pause briefly
-        * for the chip to recover.
-        *
-        * XXX how long are we really supposed to delay?  --thorpej
+        * affect the EEPROM.  The longest reset recovery time of those devices
+        * supported is the 91C111. Section 7.8 of its datasheet asks for 50ms.
         */
        SMC_SELECT_BANK(sc, 0);
        bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
-       delay(100);
+       delay(5);
        bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
-       delay(200);
+       delay(50000);
 
        bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
 
@@ -654,20 +646,21 @@
         */
        for (len = 0; m != NULL; m = m->m_next)
                len += m->m_len;
-       pad = (len & 1);
 
        /*
         * We drop packets that are too large.  Perhaps we should
         * truncate them instead?
         */
-       if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
-               printf("%s: large packet discarded\n", device_xname(sc->sc_dev));
+       if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
+               printf("%s: large packet discarded\n",
+                   device_xname(sc->sc_dev));
                ifp->if_oerrors++;
                IFQ_DEQUEUE(&ifp->if_snd, m);
                m_freem(m);
                goto readcheck;
        }
 
+       pad = 0;
 #ifdef SMC91CXX_SW_PAD
        /*
         * Not using hardware padding; pad to ETHER_MIN_LEN.
@@ -709,7 +702,7 @@
        if (packetno & ARR_FAILED || timo == 0) {
                /*
                 * No transmit memory is available.  Record the number
-                * of requestd pages and enable the allocation completion
+                * of requested pages and enable the allocation completion
                 * interrupt.  Set up the watchdog timer in case we miss
                 * the interrupt.  Mark the interface as active so that
                 * no one else attempts to transmit while we're allocating
@@ -726,7 +719,7 @@
        /*
         * We have a packet number - set the data window.
         */
-       bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
+       bus_space_write_2(bst, bsh, PACKET_NUM_REG_B, packetno);
 
        /*
         * Point to the beginning of the packet.
@@ -747,24 +740,17 @@
        IFQ_DEQUEUE(&ifp->if_snd, m);
 
        /*
-        * Push the packet out to the card.
+        * Push the packet out to the card.  The copying function only does
+        * whole words and returns the straggling byte (if any).
         */
        oddbyte = smc91cxx_copy_tx_frame(sc, m);
 
 #ifdef SMC91CXX_SW_PAD
-#ifdef SMC91CXX_NO_BYTE_WRITE
-#if BYTE_ORDER == LITTLE_ENDIAN
        if (pad > 1 && (pad & 1)) {
-               bus_space_write_2(bst, bsh, DATA_REG_W, oddbyte << 0);
+               bus_space_write_2(bst, bsh, DATA_REG_W, oddbyte);
                oddbyte = 0;
+               pad -= 1;
        }
-#else
-       if (pad > 1 && (pad & 1)) {
-               bus_space_write_2(bst, bsh, DATA_REG_W, oddbyte << 8);
-               oddbyte = 0;
-       }
-#endif
-#endif
 
        /*
         * Push out padding.
@@ -775,23 +761,13 @@
        }
 #endif
 
-#ifdef SMC91CXX_NO_BYTE_WRITE
        /*
         * Push out control byte and unused packet byte.  The control byte
-        * is 0, meaning the packet is even lengthed and no special
-        * CRC handling is necessary.
+        * denotes whether this is an odd or even length packet, and that
+        * no special CRC handling is necessary.
         */
-#if BYTE_ORDER == LITTLE_ENDIAN
        bus_space_write_2(bst, bsh, DATA_REG_W,
-           oddbyte | (pad ? (CTLB_ODD << 8) : 0));
-#else
-       bus_space_write_2(bst, bsh, DATA_REG_W,
-           (oddbyte << 8) | (pad ? CTLB_ODD : 0));
-#endif
-#else
-       if (pad)
-               bus_space_write_1(bst, bsh, DATA_REG_B, 0);
-#endif
+           oddbyte | ((length & 1) ? (CTLB_ODD << 8) : 0));
 
        /*
         * Enable transmit interrupts and let the chip go.  Set a watchdog
@@ -812,7 +788,7 @@
 
  readcheck:
        /*
-        * Check for incoming pcakets.  We don't want to overflow the small
+        * Check for incoming packets.  We don't want to overflow the small
         * RX FIFO.  If nothing has arrived, attempt to queue another
         * transmit packet.
         */
@@ -894,10 +870,7 @@
                        panic("smc91cxx_copy_tx_frame: p != lim");
 #endif
        }
-#ifndef SMC91CXX_NO_BYTE_WRITE
-       if (leftover)
-               bus_space_write_1(bst, bsh, DATA_REG_B, dbuf);
-#endif
+
        return dbuf;
 }
 
@@ -913,9 +886,7 @@
        bus_space_handle_t bsh = sc->sc_bsh;
        u_int8_t mask, interrupts, status;
        u_int16_t packetno, tx_status, card_stats;
-#ifdef SMC91CXX_NO_BYTE_WRITE
        u_int16_t v;
-#endif
 
        if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 ||
            !device_is_active(sc->sc_dev))
@@ -926,30 +897,15 @@
        /*
         * Obtain the current interrupt status and mask.
         */
-#ifdef SMC91CXX_NO_BYTE_WRITE
        v = bus_space_read_2(bst, bsh, INTR_STAT_REG_B);
 
        /*
         * Get the set of interrupt which occurred and eliminate any
         * which are not enabled.
         */
-#if BYTE_ORDER == LITTLE_ENDIAN
        mask = v >> 8;
        interrupts = v & 0xff;
-#else
-       interrupts = v >> 8;
-       mask = v & 0xff;
-#endif
        KDASSERT(mask == sc->sc_intmask);
-#else
-       mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
-
-       /*
-        * Get the set of interrupt which occurred and eliminate any
-        * which are not enabled.
-        */
-       interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
-#endif
        status = interrupts & mask;



Home | Main Index | Thread Index | Old Index