This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
91c111 NIC support.
- From: Mark Salter <msalter at redhat dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: Fri, 16 Aug 2002 09:15:26 -0400
- Subject: 91c111 NIC support.
Added 91c111 support to lan91cxxx. Also allow platform include file to
override default register access routines. I won't mention the horrible
unspeakable things I had to do to get the register access right on the
hw I'm working with.
--Mark
Index: devs/eth/smsc/lan91cxx/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/ChangeLog,v
retrieving revision 1.9
diff -u -p -5 -r1.9 ChangeLog
--- devs/eth/smsc/lan91cxx/current/ChangeLog 14 Jun 2002 22:01:49 -0000 1.9
+++ devs/eth/smsc/lan91cxx/current/ChangeLog 16 Aug 2002 13:09:11 -0000
@@ -1,5 +1,12 @@
+2002-08-16 Mark Salter <msalter@redhat.com>
+
+ * src/if_lan91cxx.c: Add support for 91C111. Platform-specific
+ include file is now included from within smsc_lan91cxx.h so
+ that register access functions may be overridden if necessary.
+ * src/smsc_lan91cxx.h: Ditto.
+
2002-06-14 Gary Thomas <gary@chez-thomas.org>
* src/if_lan91cxx.c:
Need to include <pkgconf/io_eth_drivers.h> for proper configuration
of stand-alone (polled) vs. system (interrupt driven) mode.
Index: devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c,v
retrieving revision 1.8
diff -u -p -5 -r1.8 if_lan91cxx.c
--- devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 14 Jun 2002 22:01:50 -0000 1.8
+++ devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 16 Aug 2002 13:09:12 -0000
@@ -124,11 +124,17 @@ int lan91cxx_txfifo_bad = 0;
#else
#define INCR_STAT( _x_ ) CYG_EMPTY_STATEMENT
#endif
#include "smsc_lan91cxx.h"
-#include CYGDAT_DEVS_ETH_SMSC_LAN91CXX_INL
+
+#ifdef LAN91CXX_IS_LAN91C111
+static void lan91cxx_write_phy(struct eth_drv_sc *sc, cyg_uint8 phyaddr,
+ cyg_uint8 phyreg, cyg_uint16 value);
+static cyg_uint16 lan91cxx_read_phy(struct eth_drv_sc *sc, cyg_uint8 phyaddr,
+ cyg_uint8 phyreg);
+#endif
static void lan91cxx_poll(struct eth_drv_sc *sc);
static cyg_interrupt lan91cxx_interrupt;
static cyg_handle_t lan91cxx_interrupt_handle;
@@ -343,28 +349,58 @@ lan91cxx_stop(struct eth_drv_sc *sc)
// the hardware ready to send/receive packets.
//
static void
lan91cxx_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
{
+ cyg_uint16 intr;
+#ifdef LAN91CXX_IS_LAN91C111
+ cyg_uint16 phy_ctl;
+ int delay;
+#endif
#ifdef CYGPKG_NET
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#endif
DEBUG_FUNCTION();
+
+#ifdef LAN91CXX_IS_LAN91C111
+ // 91C111 Errata. Internal PHY comes up disabled. Must enable here.
+ phy_ctl = lan91cxx_read_phy(sc, 0, LAN91CXX_PHY_CTRL);
+ phy_ctl &= ~LAN91CXX_PHY_CTRL_MII_DIS;
+ lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, phy_ctl);
+
+ // Start auto-negotiation
+ put_reg(sc, LAN91CXX_RPCR,
+ LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK | LAN91CXX_RPCR_ANEG);
+
+ // wait for auto-negotiation to finish.
+ // give it ~5 seconds before giving up (no cable?)
+ delay = 50;
+ while (!(lan91cxx_read_phy(sc, 0, LAN91CXX_PHY_STAT) & 0x20)) {
+ if (--delay <= 0)
+ break;
+ HAL_DELAY_US(100000);
+ }
+#endif
+
+ put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu);
+
put_reg(sc, LAN91CXX_INTERRUPT, 0); // disable interrupts
- put_reg(sc, LAN91CXX_INTERRUPT, // ack old interrupts
- LAN91CXX_INTERRUPT_TX_INT | LAN91CXX_INTERRUPT_TX_EMPTY_INT |
- LAN91CXX_INTERRUPT_RX_OVRN_INT | LAN91CXX_INTERRUPT_ERCV_INT);
+ intr = get_reg(sc, LAN91CXX_INTERRUPT);
+ put_reg(sc, LAN91CXX_INTERRUPT, intr & // ack old interrupts
+ (LAN91CXX_INTERRUPT_TX_INT | LAN91CXX_INTERRUPT_TX_EMPTY_INT |
+ LAN91CXX_INTERRUPT_RX_OVRN_INT | LAN91CXX_INTERRUPT_ERCV_INT));
put_reg(sc, LAN91CXX_RCR,
#ifdef RCR_HAS_ABORT_ENB // 91C96 does not - page 46.
LAN91CXX_RCR_ABORT_ENB |
#endif
LAN91CXX_RCR_STRIP_CRC |
LAN91CXX_RCR_RXEN | LAN91CXX_RCR_ALMUL);
put_reg(sc, LAN91CXX_TCR, LAN91CXX_TCR_TXENA | LAN91CXX_TCR_PAD_EN);
put_reg(sc, LAN91CXX_CONTROL, 0);
put_reg(sc, LAN91CXX_INTERRUPT, // enable interrupts
LAN91CXX_INTERRUPT_RCV_INT_M);
+
#ifdef CYGPKG_NET
if (( 0
#ifdef ETH_DRV_FLAGS_PROMISC_MODE
!= (flags & ETH_DRV_FLAGS_PROMISC_MODE)
#endif
@@ -586,18 +622,22 @@ lan91cxx_control(struct eth_drv_sc *sc,
static int
lan91cxx_can_send(struct eth_drv_sc *sc)
{
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
- unsigned short stat;
int tcr;
DEBUG_FUNCTION();
- stat = get_reg(sc, LAN91CXX_EPH_STATUS);
- if ((stat & LAN91CXX_STATUS_LINK_OK) == 0) {
+
+#ifndef LAN91CXX_IS_LAN91C111
+ // LINK_OK on 91C111 is just a general purpose input and may not
+ // have anything to do with the link.
+ if ((get_reg(sc, LAN91CXX_EPH_STATUS) & LAN91CXX_STATUS_LINK_OK) == 0) {
+ diag_printf("no link\n");
return false; // Link not connected
}
+#endif
CYG_ASSERT( cpd->within_send < 10, "can_send: Excess send recursions" );
cpd->within_send++;
tcr = get_reg(sc, LAN91CXX_TCR);
@@ -668,12 +708,16 @@ lan91cxx_send(struct eth_drv_sc *sc, str
CYG_ASSERT( plen == total_len, "sg data length mismatch" );
// Alloc new TX packet
do {
- put_reg(sc, LAN91CXX_MMU_COMMAND,
- LAN91CXX_MMU_alloc_for_tx | ((plen >> 8) & 0x07));
+ put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_alloc_for_tx
+#ifndef LAN91CXX_IS_LAN91C111
+ | ((plen >> 8) & 0x07)
+#endif
+ );
+
i = 1024 * 1024;
do {
status = get_reg(sc, LAN91CXX_INTERRUPT);
} while (0 == (status & LAN91CXX_INTERRUPT_ALLOC_INT) && (--i > 0) );
if ( i )
@@ -740,15 +784,13 @@ lan91cxx_send(struct eth_drv_sc *sc, str
// Enqueue the packet
put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_enq_packet);
// Ack TX empty int and unmask it.
- ints = get_reg(sc, LAN91CXX_INTERRUPT);
- ints |= LAN91CXX_INTERRUPT_TX_SET_ACK;
- put_reg(sc, LAN91CXX_INTERRUPT, ints);
- ints |= LAN91CXX_INTERRUPT_TX_SET_M;
- put_reg(sc, LAN91CXX_INTERRUPT, ints);
+ ints = get_reg(sc, LAN91CXX_INTERRUPT) & 0xff00;
+ put_reg(sc, LAN91CXX_INTERRUPT, ints | LAN91CXX_INTERRUPT_TX_SET_ACK);
+ put_reg(sc, LAN91CXX_INTERRUPT, ints | LAN91CXX_INTERRUPT_TX_SET_M);
#if DEBUG & 1
ints = get_reg(sc, LAN91CXX_INTERRUPT);
diag_printf("%s:END: ints at TX: %04x\n", __FUNCTION__, ints);
#endif
@@ -765,13 +807,12 @@ lan91cxx_TxEvent(struct eth_drv_sc *sc,
DEBUG_FUNCTION();
INCR_STAT( tx_complete );
// Ack and mask TX interrupt set
- ints = get_reg(sc, LAN91CXX_INTERRUPT);
- ints &=~LAN91CXX_INTERRUPT_TX_FIFO_ACK; // Do NOT ACK this one here.
- ints |= LAN91CXX_INTERRUPT_TX_SET_ACK; // Also ACKs other sources!
+ ints = get_reg(sc, LAN91CXX_INTERRUPT) & 0xff00;
+ ints |= LAN91CXX_INTERRUPT_TX_SET_ACK;
ints &= ~LAN91CXX_INTERRUPT_TX_SET_M;
put_reg(sc, LAN91CXX_INTERRUPT, ints);
// Get number of completed packet and read the status word
packet = get_reg(sc, LAN91CXX_FIFO_PORTS);
@@ -824,16 +865,10 @@ lan91cxx_TxEvent(struct eth_drv_sc *sc,
success = 0; // And treat this as an error...
}
packet &= 0xff;
- // Ack the TX int which is supposed to clear the packet from the TX
- // completion queue.
- ints = get_reg(sc, LAN91CXX_INTERRUPT);
- ints |= LAN91CXX_INTERRUPT_TX_FIFO_ACK;
- put_reg(sc, LAN91CXX_INTERRUPT, ints);
-
// It certainly appears that occasionally the tx fifo tells lies; we
// get the wrong packet number. Freeing the one we allocated seems to
// give correct operation.
#ifdef CYGPKG_INFRA_DEBUG
// Then we log, OOI, the number of times we get a bad packet number
@@ -848,10 +883,16 @@ lan91cxx_TxEvent(struct eth_drv_sc *sc,
#endif
// and then free the packet
put_reg(sc, LAN91CXX_PNR, cpd->txpacket);
put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_rel_packet);
+ // Ack the TX int which is supposed to clear the packet from the TX
+ // completion queue.
+ ints = get_reg(sc, LAN91CXX_INTERRUPT) & 0xff00;
+ ints |= LAN91CXX_INTERRUPT_TX_FIFO_ACK;
+ put_reg(sc, LAN91CXX_INTERRUPT, ints);
+
#if DEBUG & 1
// Hm... The free doesn't seem to have the desired effect?!?
ints = get_reg(sc, LAN91CXX_INTERRUPT);
packet = get_reg(sc, LAN91CXX_FIFO_PORTS);
diag_printf("%s:END: fifo %04x ints %04x\n", __FUNCTION__, packet, ints);
@@ -874,21 +915,25 @@ lan91cxx_TxEvent(struct eth_drv_sc *sc,
static void
lan91cxx_RxEvent(struct eth_drv_sc *sc)
{
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
- unsigned short stat, len, controlbyte;
+ unsigned short stat, len;
DEBUG_FUNCTION();
stat = get_reg(sc, LAN91CXX_FIFO_PORTS);
#if DEBUG & 1
diag_printf("RxEvent - FIFOs: 0x%04x\n", stat);
#endif
- if ( 0x8000 & stat )
+ if ( 0x8000 & stat ) {
// Then the Rx FIFO is empty
+#if DEBUG & 4
+ diag_printf("#####RxEvent with empty fifo\n");
+#endif
return;
+ }
INCR_STAT( rx_count );
#if DEBUG & 4
diag_printf("#####Rx packet allocated %x (previous %x)\n",
@@ -900,28 +945,25 @@ lan91cxx_RxEvent(struct eth_drv_sc *sc)
// Read status and (word) length
put_reg(sc, LAN91CXX_POINTER, (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |
LAN91CXX_POINTER_AUTO_INCR | 0x0000));
stat = get_data(sc);
len = get_data(sc) - 6; // minus header/footer words
- // Read control byte at end of packet to get last bit of length
- put_reg(sc, LAN91CXX_POINTER, (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |
- LAN91CXX_POINTER_AUTO_INCR | (len + 4)));
- controlbyte = get_data(sc);
#ifdef KEEP_STATISTICS
if ( stat & LAN91CXX_RX_STATUS_ALIGNERR ) INCR_STAT( rx_align_errors );
//if ( stat & LAN91CXX_RX_STATUS_BCAST ) INCR_STAT( );
if ( stat & LAN91CXX_RX_STATUS_BADCRC ) INCR_STAT( rx_crc_errors );
if ( stat & LAN91CXX_RX_STATUS_TOOLONG ) INCR_STAT( rx_too_long_frames );
if ( stat & LAN91CXX_RX_STATUS_TOOSHORT ) INCR_STAT( rx_short_frames );
//if ( stat & LAN91CXX_RX_STATUS_MCAST ) INCR_STAT( );
#endif // KEEP_STATISTICS
- if (controlbyte & LAN91CXX_CONTROLBYTE_RX) {
+ if ((stat & LAN91CXX_RX_STATUS_BAD) == 0) {
INCR_STAT( rx_good );
// Then it's OK
- if (controlbyte & LAN91CXX_CONTROLBYTE_ODD)
+
+ if (stat & LAN91CXX_RX_STATUS_ODDFRM)
len++;
#if DEBUG & 1
diag_printf("RxEvent good rx - stat: 0x%04x, len: 0x%04x\n", stat, len);
#endif
@@ -936,22 +978,11 @@ lan91cxx_RxEvent(struct eth_drv_sc *sc)
return;
}
// Not OK for one reason or another...
#if DEBUG & 1
- diag_printf("RxEvent - No RX bit: stat: 0x%04x, len: 0x%04x, control'byte' 0x%04x\n",
- stat, len, controlbyte);
-#endif
-
-#if DEBUG & 4
- stat = get_reg(sc, LAN91CXX_FIFO_PORTS);
- if ( 0x8000 & stat ) // Then the Rx FIFO is empty
- diag_printf("#####Rx packet (bad controlbyte) NOT freed, stat is %x (expected %x)\n",
- stat, cpd->rxpacket );
- else
- diag_printf("#####Rx packet (bad controlbyte) freed %x (expected %x)\n",
- 0xff & (stat >> 8), cpd->rxpacket );
+ diag_printf("RxEvent - bad rx: stat: 0x%04x, len: 0x%04x\n", stat, len);
#endif
// Free packet
put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame);
}
@@ -977,12 +1008,14 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
DEBUG_FUNCTION();
INCR_STAT( rx_deliver );
put_reg(sc, LAN91CXX_POINTER, (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |
- LAN91CXX_POINTER_AUTO_INCR | 0x0002));
- // Status is skipped by starting at 2 above.
+ LAN91CXX_POINTER_AUTO_INCR));
+ // Skip status word
+ (void)get_data(sc);
+
plen = get_data(sc) - 6; // packet length (minus header/footer)
for (i = 0; i < sg_len; i++) {
data = (unsigned short *)sg_list[i].buf;
mlen = sg_list[i].len;
@@ -1063,17 +1096,175 @@ lan91cxx_poll(struct eth_drv_sc *sc)
else
#endif
if (event & LAN91CXX_INTERRUPT_TX_SET) {
lan91cxx_TxEvent(sc, event);
}
- else if (event & LAN91CXX_INTERRUPT_RCV_INT) {
+ if (event & LAN91CXX_INTERRUPT_RCV_INT) {
lan91cxx_RxEvent(sc);
}
- else {
+ if (event & ~(LAN91CXX_INTERRUPT_TX_SET | LAN91CXX_INTERRUPT_RCV_INT))
diag_printf("%s: Unknown interrupt: 0x%04x\n",
- __FUNCTION__, event);
- }
+ __FUNCTION__, event);
+ }
+}
+
+#ifdef LAN91CXX_IS_LAN91C111
+
+static cyg_uint16
+lan91cxx_read_phy(struct eth_drv_sc *sc, cyg_uint8 phyaddr, cyg_uint8 phyreg)
+{
+ int i, mask, input_idx, clk_idx = 0;
+ cyg_uint16 mii_reg, value;
+ cyg_uint8 bits[64];
+
+ // 32 consecutive ones on MDO to establish sync
+ for (i = 0; i < 32; ++i)
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+ // Start code <01>
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+ // Read command <10>
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+
+ // Output the PHY address, msb first
+ for (mask = 0x10; mask; mask >>= 1) {
+ if (phyaddr & mask)
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+ else
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ }
+
+ // Output the phy register number, msb first
+ for (mask = 0x10; mask; mask >>= 1) {
+ if (phyreg & mask)
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+ else
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ }
+
+ // Tristate and turnaround (1 bit times)
+ bits[clk_idx++] = 0;
+
+ // Input starts at this bit time
+ input_idx = clk_idx;
+
+ // Will input 16 bits
+ for (i = 0; i < 16; ++i)
+ bits[clk_idx++] = 0;
+
+ // Final clock bit
+ bits[clk_idx++] = 0;
+
+ // Get the current MII register value
+ mii_reg = get_reg(sc, LAN91CXX_MGMT);
+
+ // Turn off all MII Interface bits
+ mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK |
+ LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO);
+
+ // Clock all 64 cycles
+ for (i = 0; i < sizeof(bits); ++i) {
+ // Clock Low - output data
+ put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i]);
+ HAL_DELAY_US(50);
+
+ // Clock Hi - input data
+ put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);
+ HAL_DELAY_US(50);
+
+ bits[i] |= get_reg(sc, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;
+ }
+
+ // Return to idle state
+ put_reg(sc, LAN91CXX_MGMT, mii_reg);
+ HAL_DELAY_US(50);
+
+ // Recover input data
+ for (value = 0, i = 0; i < 16; ++i) {
+ value <<= 1;
+ if (bits[input_idx++] & LAN91CXX_MGMT_MDI)
+ value |= 1;
}
+ return value;
}
+static void
+lan91cxx_write_phy(struct eth_drv_sc *sc, cyg_uint8 phyaddr,
+ cyg_uint8 phyreg, cyg_uint16 value)
+{
+ int i, mask, clk_idx = 0;
+ cyg_uint16 mii_reg;
+ cyg_uint8 bits[65];
+
+ // 32 consecutive ones on MDO to establish sync
+ for (i = 0; i < 32; ++i)
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+ // Start code <01>
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+ // Write command <01>
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+
+ // Output the PHY address, msb first
+ for (mask = 0x10; mask; mask >>= 1) {
+ if (phyaddr & mask)
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+ else
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ }
+
+ // Output the phy register number, msb first
+ for (mask = 0x10; mask; mask >>= 1) {
+ if (phyreg & mask)
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+ else
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ }
+
+ // Tristate and turnaround (2 bit times)
+ bits[clk_idx++] = 0;
+ bits[clk_idx++] = 0;
+
+ // Write out 16 bits of data, msb first
+ for (mask = 0x8000; mask; mask >>= 1) {
+ if (value & mask)
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MDO;
+ else
+ bits[clk_idx++] = LAN91CXX_MGMT_MDOE;
+ }
+
+ // Final clock bit (tristate)
+ bits[clk_idx++] = 0;
+
+ // Get the current MII register value
+ mii_reg = get_reg(sc, LAN91CXX_MGMT);
+
+ // Turn off all MII Interface bits
+ mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK |
+ LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO);
+
+ // Clock all cycles
+ for (i = 0; i < sizeof(bits); ++i) {
+ // Clock Low - output data
+ put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i]);
+ HAL_DELAY_US(50);
+
+ // Clock Hi - input data
+ put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);
+ HAL_DELAY_US(50);
+
+// bits[i] |= get_reg(sc, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;
+ }
+
+ // Return to idle state
+ put_reg(sc, LAN91CXX_MGMT, mii_reg);
+ HAL_DELAY_US(50);
+}
+#endif // LAN91CXX_IS_LAN91C111
// EOF if_lan91cxx.c
Index: devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h,v
retrieving revision 1.5
diff -u -p -5 -r1.5 smsc_lan91cxx.h
--- devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h 23 May 2002 23:00:48 -0000 1.5
+++ devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h 16 Aug 2002 13:09:12 -0000
@@ -68,11 +68,12 @@
#define LAN91CXX_TCR 0x00
#define LAN91CXX_EPH_STATUS 0x01
#define LAN91CXX_RCR 0x02
#define LAN91CXX_COUNTER 0x03
#define LAN91CXX_MIR 0x04
-#define LAN91CXX_MCR 0x05
+#define LAN91CXX_MCR 0x05 // Other than 91C111
+#define LAN91CXX_RPCR 0x05 // 91C111 only
#define LAN91CXX_RESERVED_0 0x06
#define LAN91CXX_BS 0x07
#define LAN91CXX_CONFIG 0x08
#define LAN91CXX_BASE_REG 0x09
#define LAN91CXX_IA01 0x0a
@@ -204,11 +205,15 @@
#define LAN91CXX_RX_STATUS_ODDFRM 0x1000
#define LAN91CXX_RX_STATUS_TOOLONG 0x0800
#define LAN91CXX_RX_STATUS_TOOSHORT 0x0400
#define LAN91CXX_RX_STATUS_HASHVALMASK 0x007e // MASK
#define LAN91CXX_RX_STATUS_MCAST 0x0001
-
+#define LAN91CXX_RX_STATUS_BAD \
+ (LAN91CXX_RX_STATUS_ALIGNERR | \
+ LAN91CXX_RX_STATUS_BADCRC | \
+ LAN91CXX_RX_STATUS_TOOLONG | \
+ LAN91CXX_RX_STATUS_TOOSHORT)
// Attribute memory registers in PCMCIA mode
#define LAN91CXX_ECOR 0x8000
#define LAN91CXX_ECOR_RESET (1<<7)
#define LAN91CXX_ECOR_LEVIRQ (1<<6)
@@ -218,10 +223,51 @@
#define LAN91CXX_ECSR 0x8002
#define LAN91CXX_ECSR_IOIS8 (1<<5)
#define LAN91CXX_ECSR_PWRDWN (1<<2)
#define LAN91CXX_ECSR_INTR (1<<1)
+// These are for manipulating the MII interface
+#define LAN91CXX_MGMT_MDO 0x0001
+#define LAN91CXX_MGMT_MDI 0x0002
+#define LAN91CXX_MGMT_MCLK 0x0004
+#define LAN91CXX_MGMT_MDOE 0x0008
+
+// Internal PHY registers (91c111)
+#define LAN91CXX_PHY_CTRL 0
+#define LAN91CXX_PHY_STAT 1
+#define LAN91CXX_PHY_ID1 2
+#define LAN91CXX_PHY_ID2 3
+#define LAN91CXX_PHY_AUTO_AD 4
+#define LAN91CXX_PHY_AUTO_CAP 5
+#define LAN91CXX_PHY_CONFIG1 16
+#define LAN91CXX_PHY_CONFIG2 17
+#define LAN91CXX_PHY_STATUS_OUT 18
+#define LAN91CXX_PHY_MASK 19
+
+// PHY control bits
+#define LAN91CXX_PHY_CTRL_COLTST (1 << 7)
+#define LAN91CXX_PHY_CTRL_DPLX (1 << 8)
+#define LAN91CXX_PHY_CTRL_ANEG_RST (1 << 9)
+#define LAN91CXX_PHY_CTRL_MII_DIS (1 << 10)
+#define LAN91CXX_PHY_CTRL_PDN (1 << 11)
+#define LAN91CXX_PHY_CTRL_ANEG_EN (1 << 12)
+#define LAN91CXX_PHY_CTRL_SPEED (1 << 13)
+#define LAN91CXX_PHY_CTRL_LPBK (1 << 14)
+#define LAN91CXX_PHY_CTRL_RST (1 << 15)
+
+#define LAN91CXX_RPCR_LEDA_LINK (0 << 2)
+#define LAN91CXX_RPCR_LEDA_TXRX (4 << 2)
+#define LAN91CXX_RPCR_LEDA_RX (6 << 2)
+#define LAN91CXX_RPCR_LEDA_TX (7 << 2)
+#define LAN91CXX_RPCR_LEDB_LINK (0 << 5)
+#define LAN91CXX_RPCR_LEDB_TXRX (4 << 5)
+#define LAN91CXX_RPCR_LEDB_RX (6 << 5)
+#define LAN91CXX_RPCR_LEDB_TX (7 << 5)
+#define LAN91CXX_RPCR_ANEG (1 << 11)
+#define LAN91CXX_RPCR_DPLX (1 << 12)
+#define LAN91CXX_RPCR_SPEED (1 << 13)
+
// ------------------------------------------------------------------------
#ifdef KEEP_STATISTICS
struct smsc_lan91cxx_stats {
@@ -278,10 +324,13 @@ typedef struct lan91cxx_priv_data {
#endif
} lan91cxx_priv_data;
// ------------------------------------------------------------------------
+#include CYGDAT_DEVS_ETH_SMSC_LAN91CXX_INL
+
+#ifndef SMSC_PLATFORM_DEFINED_GET_REG
static __inline__ unsigned short
get_reg(struct eth_drv_sc *sc, int regno)
{
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
@@ -292,11 +341,13 @@ get_reg(struct eth_drv_sc *sc, int regno
#if DEBUG & 2
diag_printf("read reg %d val 0x%04x\n", regno, val);
#endif
return val;
}
+#endif // SMSC_PLATFORM_DEFINED_GET_REG
+#ifndef SMSC_PLATFORM_DEFINED_PUT_REG
static __inline__ void
put_reg(struct eth_drv_sc *sc, int regno, unsigned short val)
{
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
@@ -306,11 +357,13 @@ put_reg(struct eth_drv_sc *sc, int regno
#if DEBUG & 2
diag_printf("write reg %d val 0x%04x\n", regno, val);
#endif
}
+#endif // SMSC_PLATFORM_DEFINED_PUT_REG
+#ifndef SMSC_PLATFORM_DEFINED_PUT_DATA
// ------------------------------------------------------------------------
// Assumes bank2 has been selected
static __inline__ void
put_data(struct eth_drv_sc *sc, unsigned short val)
{
@@ -321,11 +374,13 @@ put_data(struct eth_drv_sc *sc, unsigned
#if DEBUG & 2
diag_printf("write data 0x%04x\n", val);
#endif
}
+#endif // SMSC_PLATFORM_DEFINED_PUT_DATA
+#ifndef SMSC_PLATFORM_DEFINED_GET_DATA
// Assumes bank2 has been selected
static __inline__ unsigned short
get_data(struct eth_drv_sc *sc)
{
unsigned short val;
@@ -337,10 +392,11 @@ get_data(struct eth_drv_sc *sc)
#if DEBUG & 2
diag_printf("read data 0x%04x\n", val);
#endif
return val;
}
+#endif // SMSC_PLATFORM_DEFINED_GET_DATA
// ------------------------------------------------------------------------
// Read the bank register (this one is bank-independent)
static __inline__ unsigned short
get_banksel(struct eth_drv_sc *sc)
@@ -349,11 +405,11 @@ get_banksel(struct eth_drv_sc *sc)
(struct lan91cxx_priv_data *)sc->driver_private;
unsigned short val;
HAL_READ_UINT16(cpd->base+(LAN91CXX_BS << cpd->addrsh), val);
#if DEBUG & 2
- diag_printf("read bank val 0x%04x\n", regno, val);
+ diag_printf("read bank val 0x%04x\n", val);
#endif
return val;
}
@@ -388,7 +444,7 @@ get_att(struct eth_drv_sc *sc, int offs)
return val;
}
#endif // #if CYGINT_DEVS_ETH_SMSC_LAN91CXX_PCMCIA_MODE
// ------------------------------------------------------------------------
-#endif CYGONCE_DEVS_ETH_SMSC_LAN91CXX_LAN91CXX_H
+#endif // CYGONCE_DEVS_ETH_SMSC_LAN91CXX_LAN91CXX_H
// EOF smsc_lan91cxx.h