This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]