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