|
@@ -36,7 +36,24 @@ v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
|
|
|
|
|
|
--------------------------------------
|
|
|
|
|
|
- 12/15/2003 Initial port to u-boot by Sascha Hauer <saschahauer@web.de>
|
|
|
+ 12/15/2003 Initial port to u-boot by
|
|
|
+ Sascha Hauer <saschahauer@web.de>
|
|
|
+
|
|
|
+ 06/03/2008 Remy Bohmer <linux@bohmer.net>
|
|
|
+ - Fixed the driver to work with DM9000A.
|
|
|
+ (check on ISR receive status bit before reading the
|
|
|
+ FIFO as described in DM9000 programming guide and
|
|
|
+ application notes)
|
|
|
+ - Added autodetect of databus width.
|
|
|
+ - Made debug code compile again.
|
|
|
+ - Adapt eth_send such that it matches the DM9000*
|
|
|
+ application notes. Needed to make it work properly
|
|
|
+ for DM9000A.
|
|
|
+ - Adapted reset procedure to match DM9000 application
|
|
|
+ notes (i.e. double reset)
|
|
|
+ - some minor code cleanups
|
|
|
+ These changes are tested with DM9000{A,EP,E} together
|
|
|
+ with a 200MHz Atmel AT91SAM92161 core
|
|
|
|
|
|
TODO: Homerun NIC and longrun NIC are not functional, only internal at the
|
|
|
moment.
|
|
@@ -47,8 +64,6 @@ TODO: Homerun NIC and longrun NIC are not functional, only internal at the
|
|
|
#include <net.h>
|
|
|
#include <asm/io.h>
|
|
|
|
|
|
-#ifdef CONFIG_DRIVER_DM9000
|
|
|
-
|
|
|
#include "dm9000x.h"
|
|
|
|
|
|
/* Board/System/Debug information/definition ---------------- */
|
|
@@ -59,10 +74,22 @@ TODO: Homerun NIC and longrun NIC are not functional, only internal at the
|
|
|
/* #define CONFIG_DM9000_DEBUG */
|
|
|
|
|
|
#ifdef CONFIG_DM9000_DEBUG
|
|
|
-#define DM9000_DBG(fmt,args...) printf(fmt ,##args)
|
|
|
-#else /* */
|
|
|
+#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
|
|
|
+#define DM9000_DMP_PACKET(func,packet,length) \
|
|
|
+ do { \
|
|
|
+ int i; \
|
|
|
+ printf(func ": length: %d\n", length); \
|
|
|
+ for (i = 0; i < length; i++) { \
|
|
|
+ if (i % 8 == 0) \
|
|
|
+ printf("\n%s: %02x: ", func, i); \
|
|
|
+ printf("%02x ", ((unsigned char *) packet)[i]); \
|
|
|
+ } printf("\n"); \
|
|
|
+ } while(0)
|
|
|
+#else
|
|
|
#define DM9000_DBG(fmt,args...)
|
|
|
-#endif /* */
|
|
|
+#define DM9000_DMP_PACKET(func,packet,length)
|
|
|
+#endif
|
|
|
+
|
|
|
enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =
|
|
|
1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO =
|
|
|
8, DM9000_1M_HPNA = 0x10
|
|
@@ -84,8 +111,11 @@ typedef struct board_info {
|
|
|
u8 device_wait_reset; /* device state */
|
|
|
u8 nic_type; /* NIC type */
|
|
|
unsigned char srom[128];
|
|
|
+ void (*outblk)(volatile void *data_ptr, int count);
|
|
|
+ void (*inblk)(void *data_ptr, int count);
|
|
|
+ void (*rx_status)(u16 *RxStatus, u16 *RxLen);
|
|
|
} board_info_t;
|
|
|
-board_info_t dmfe_info;
|
|
|
+static board_info_t dm9000_info;
|
|
|
|
|
|
/* For module input parameter */
|
|
|
static int media_mode = DM9000_AUTO;
|
|
@@ -124,10 +154,85 @@ dump_regs(void)
|
|
|
DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
|
|
|
DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
|
|
|
DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
|
|
|
- DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(ISR));
|
|
|
+ DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
|
|
|
DM9000_DBG("\n");
|
|
|
}
|
|
|
-#endif /* */
|
|
|
+#endif
|
|
|
+
|
|
|
+static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < count; i++)
|
|
|
+ DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
|
|
|
+}
|
|
|
+
|
|
|
+static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ u32 tmplen = (count + 1) / 2;
|
|
|
+
|
|
|
+ for (i = 0; i < tmplen; i++)
|
|
|
+ DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
|
|
|
+}
|
|
|
+static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ u32 tmplen = (count + 3) / 4;
|
|
|
+
|
|
|
+ for (i = 0; i < tmplen; i++)
|
|
|
+ DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
|
|
|
+}
|
|
|
+
|
|
|
+static void dm9000_inblk_8bit(void *data_ptr, int count)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < count; i++)
|
|
|
+ ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
|
|
|
+}
|
|
|
+
|
|
|
+static void dm9000_inblk_16bit(void *data_ptr, int count)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ u32 tmplen = (count + 1) / 2;
|
|
|
+
|
|
|
+ for (i = 0; i < tmplen; i++)
|
|
|
+ ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
|
|
|
+}
|
|
|
+static void dm9000_inblk_32bit(void *data_ptr, int count)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ u32 tmplen = (count + 3) / 4;
|
|
|
+
|
|
|
+ for (i = 0; i < tmplen; i++)
|
|
|
+ ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
|
|
|
+}
|
|
|
+
|
|
|
+static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
|
|
|
+{
|
|
|
+ u32 tmpdata;
|
|
|
+
|
|
|
+ DM9000_outb(DM9000_MRCMD, DM9000_IO);
|
|
|
+
|
|
|
+ tmpdata = DM9000_inl(DM9000_DATA);
|
|
|
+ *RxStatus = tmpdata;
|
|
|
+ *RxLen = tmpdata >> 16;
|
|
|
+}
|
|
|
+
|
|
|
+static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
|
|
|
+{
|
|
|
+ DM9000_outb(DM9000_MRCMD, DM9000_IO);
|
|
|
+
|
|
|
+ *RxStatus = DM9000_inw(DM9000_DATA);
|
|
|
+ *RxLen = DM9000_inw(DM9000_DATA);
|
|
|
+}
|
|
|
+
|
|
|
+static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
|
|
|
+{
|
|
|
+ DM9000_outb(DM9000_MRCMD, DM9000_IO);
|
|
|
+
|
|
|
+ *RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
|
|
|
+ *RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
|
|
|
+}
|
|
|
|
|
|
/*
|
|
|
Search DM9000 board, allocate space and register it
|
|
@@ -236,7 +341,7 @@ program_dm9802(void)
|
|
|
static void
|
|
|
identify_nic(void)
|
|
|
{
|
|
|
- struct board_info *db = &dmfe_info; /* Point a board information structure */
|
|
|
+ struct board_info *db = &dm9000_info;
|
|
|
u16 phy_reg3;
|
|
|
DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
|
|
|
phy_reg3 = phy_read(3);
|
|
@@ -263,9 +368,35 @@ identify_nic(void)
|
|
|
static void
|
|
|
dm9000_reset(void)
|
|
|
{
|
|
|
- DM9000_DBG("resetting\n");
|
|
|
- DM9000_iow(DM9000_NCR, NCR_RST);
|
|
|
- udelay(1000); /* delay 1ms */
|
|
|
+ DM9000_DBG("resetting DM9000\n");
|
|
|
+
|
|
|
+ /* Reset DM9000,
|
|
|
+ see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
|
|
|
+
|
|
|
+ /* DEBUG: Make all GPIO pins outputs */
|
|
|
+ DM9000_iow(DM9000_GPCR, 0x0F);
|
|
|
+ /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
|
|
|
+ DM9000_iow(DM9000_GPR, 0);
|
|
|
+ /* Step 2: Software reset */
|
|
|
+ DM9000_iow(DM9000_NCR, 3);
|
|
|
+
|
|
|
+ do {
|
|
|
+ DM9000_DBG("resetting the DM9000, 1st reset\n");
|
|
|
+ udelay(25); /* Wait at least 20 us */
|
|
|
+ } while (DM9000_ior(DM9000_NCR) & 1);
|
|
|
+
|
|
|
+ DM9000_iow(DM9000_NCR, 0);
|
|
|
+ DM9000_iow(DM9000_NCR, 3); /* Issue a second reset */
|
|
|
+
|
|
|
+ do {
|
|
|
+ DM9000_DBG("resetting the DM9000, 2nd reset\n");
|
|
|
+ udelay(25); /* Wait at least 20 us */
|
|
|
+ } while (DM9000_ior(DM9000_NCR) & 1);
|
|
|
+
|
|
|
+ /* Check whether the ethernet controller is present */
|
|
|
+ if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
|
|
|
+ (DM9000_ior(DM9000_PIDH) != 0x90))
|
|
|
+ printf("ERROR: resetting DM9000 -> not responding\n");
|
|
|
}
|
|
|
|
|
|
/* Initilize dm9000 board
|
|
@@ -274,12 +405,46 @@ int
|
|
|
eth_init(bd_t * bd)
|
|
|
{
|
|
|
int i, oft, lnk;
|
|
|
+ u8 io_mode;
|
|
|
+ struct board_info *db = &dm9000_info;
|
|
|
+
|
|
|
DM9000_DBG("eth_init()\n");
|
|
|
|
|
|
/* RESET device */
|
|
|
dm9000_reset();
|
|
|
dm9000_probe();
|
|
|
|
|
|
+ /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
|
|
|
+ io_mode = DM9000_ior(DM9000_ISR) >> 6;
|
|
|
+
|
|
|
+ switch (io_mode) {
|
|
|
+ case 0x0: /* 16-bit mode */
|
|
|
+ printf("DM9000: running in 16 bit mode\n");
|
|
|
+ db->outblk = dm9000_outblk_16bit;
|
|
|
+ db->inblk = dm9000_inblk_16bit;
|
|
|
+ db->rx_status = dm9000_rx_status_16bit;
|
|
|
+ break;
|
|
|
+ case 0x01: /* 32-bit mode */
|
|
|
+ printf("DM9000: running in 32 bit mode\n");
|
|
|
+ db->outblk = dm9000_outblk_32bit;
|
|
|
+ db->inblk = dm9000_inblk_32bit;
|
|
|
+ db->rx_status = dm9000_rx_status_32bit;
|
|
|
+ break;
|
|
|
+ case 0x02: /* 8 bit mode */
|
|
|
+ printf("DM9000: running in 8 bit mode\n");
|
|
|
+ db->outblk = dm9000_outblk_8bit;
|
|
|
+ db->inblk = dm9000_inblk_8bit;
|
|
|
+ db->rx_status = dm9000_rx_status_8bit;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* Assume 8 bit mode, will probably not work anyway */
|
|
|
+ printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
|
|
|
+ db->outblk = dm9000_outblk_8bit;
|
|
|
+ db->inblk = dm9000_inblk_8bit;
|
|
|
+ db->rx_status = dm9000_rx_status_8bit;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
/* NIC Type: FASTETHER, HOMERUN, LONGRUN */
|
|
|
identify_nic();
|
|
|
|
|
@@ -289,15 +454,22 @@ eth_init(bd_t * bd)
|
|
|
/* Set PHY */
|
|
|
set_PHY_mode();
|
|
|
|
|
|
- /* Program operating register */
|
|
|
- DM9000_iow(DM9000_NCR, 0x0); /* only intern phy supported by now */
|
|
|
- DM9000_iow(DM9000_TCR, 0); /* TX Polling clear */
|
|
|
- DM9000_iow(DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
|
|
|
- DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); /* Flow Control : High/Low Water */
|
|
|
- DM9000_iow(DM9000_FCR, 0x0); /* SH FIXME: This looks strange! Flow Control */
|
|
|
- DM9000_iow(DM9000_SMCR, 0); /* Special Mode */
|
|
|
- DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); /* clear TX status */
|
|
|
- DM9000_iow(DM9000_ISR, 0x0f); /* Clear interrupt status */
|
|
|
+ /* Program operating register, only intern phy supported by now */
|
|
|
+ DM9000_iow(DM9000_NCR, 0x0);
|
|
|
+ /* TX Polling clear */
|
|
|
+ DM9000_iow(DM9000_TCR, 0);
|
|
|
+ /* Less 3Kb, 200us */
|
|
|
+ DM9000_iow(DM9000_BPTR, 0x3f);
|
|
|
+ /* Flow Control : High/Low Water */
|
|
|
+ DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
|
|
|
+ /* SH FIXME: This looks strange! Flow Control */
|
|
|
+ DM9000_iow(DM9000_FCR, 0x0);
|
|
|
+ /* Special Mode */
|
|
|
+ DM9000_iow(DM9000_SMCR, 0);
|
|
|
+ /* clear TX status */
|
|
|
+ DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
|
|
|
+ /* Clear interrupt status */
|
|
|
+ DM9000_iow(DM9000_ISR, 0x0f);
|
|
|
|
|
|
/* Set Node address */
|
|
|
#ifndef CONFIG_AT91SAM9261EK
|
|
@@ -333,8 +505,11 @@ eth_init(bd_t * bd)
|
|
|
DM9000_DBG("\n");
|
|
|
|
|
|
/* Activate DM9000 */
|
|
|
- DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */
|
|
|
- DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */
|
|
|
+ /* RX enable */
|
|
|
+ DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
|
|
|
+ /* Enable TX/RX interrupt mask */
|
|
|
+ DM9000_iow(DM9000_IMR, IMR_PAR);
|
|
|
+
|
|
|
i = 0;
|
|
|
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
|
|
|
udelay(1000);
|
|
@@ -376,54 +551,37 @@ eth_init(bd_t * bd)
|
|
|
int
|
|
|
eth_send(volatile void *packet, int length)
|
|
|
{
|
|
|
- char *data_ptr;
|
|
|
- u32 tmplen, i;
|
|
|
int tmo;
|
|
|
- DM9000_DBG("eth_send: length: %d\n", length);
|
|
|
- for (i = 0; i < length; i++) {
|
|
|
- if (i % 8 == 0)
|
|
|
- DM9000_DBG("\nSend: 02x: ", i);
|
|
|
- DM9000_DBG("%02x ", ((unsigned char *) packet)[i]);
|
|
|
- } DM9000_DBG("\n");
|
|
|
-
|
|
|
- /* Move data to DM9000 TX RAM */
|
|
|
- data_ptr = (char *) packet;
|
|
|
- DM9000_outb(DM9000_MWCMD, DM9000_IO);
|
|
|
+ struct board_info *db = &dm9000_info;
|
|
|
|
|
|
-#ifdef CONFIG_DM9000_USE_8BIT
|
|
|
- /* Byte mode */
|
|
|
- for (i = 0; i < length; i++)
|
|
|
- DM9000_outb((data_ptr[i] & 0xff), DM9000_DATA);
|
|
|
+ DM9000_DMP_PACKET("eth_send", packet, length);
|
|
|
|
|
|
-#endif /* */
|
|
|
-#ifdef CONFIG_DM9000_USE_16BIT
|
|
|
- tmplen = (length + 1) / 2;
|
|
|
- for (i = 0; i < tmplen; i++)
|
|
|
- DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
|
|
|
+ DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
|
|
|
|
|
|
-#endif /* */
|
|
|
-#ifdef CONFIG_DM9000_USE_32BIT
|
|
|
- tmplen = (length + 3) / 4;
|
|
|
- for (i = 0; i < tmplen; i++)
|
|
|
- DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
|
|
|
+ /* Move data to DM9000 TX RAM */
|
|
|
+ DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
|
|
|
|
|
|
-#endif /* */
|
|
|
+ /* push the data to the TX-fifo */
|
|
|
+ (db->outblk)(packet, length);
|
|
|
|
|
|
/* Set TX length to DM9000 */
|
|
|
DM9000_iow(DM9000_TXPLL, length & 0xff);
|
|
|
DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
|
|
|
|
|
|
/* Issue TX polling command */
|
|
|
- DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
|
|
|
+ DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
|
|
|
|
|
|
/* wait for end of transmission */
|
|
|
tmo = get_timer(0) + 5 * CFG_HZ;
|
|
|
- while (DM9000_ior(DM9000_TCR) & TCR_TXREQ) {
|
|
|
+ while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
|
|
|
+ !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
|
|
|
if (get_timer(0) >= tmo) {
|
|
|
printf("transmission timeout\n");
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+ DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
|
|
|
+
|
|
|
DM9000_DBG("transmit done\n\n");
|
|
|
return 0;
|
|
|
}
|
|
@@ -452,86 +610,67 @@ eth_rx(void)
|
|
|
{
|
|
|
u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
|
|
|
u16 RxStatus, RxLen = 0;
|
|
|
- u32 tmplen, i;
|
|
|
-#ifdef CONFIG_DM9000_USE_32BIT
|
|
|
- u32 tmpdata;
|
|
|
-#endif
|
|
|
+ struct board_info *db = &dm9000_info;
|
|
|
|
|
|
- /* Check packet ready or not */
|
|
|
- DM9000_ior(DM9000_MRCMDX); /* Dummy read */
|
|
|
- rxbyte = DM9000_inb(DM9000_DATA); /* Got most updated data */
|
|
|
- if (rxbyte == 0)
|
|
|
+ /* Check packet ready or not, we must check
|
|
|
+ the ISR status first for DM9000A */
|
|
|
+ if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
|
|
|
return 0;
|
|
|
|
|
|
- /* Status check: this byte must be 0 or 1 */
|
|
|
- if (rxbyte > 1) {
|
|
|
- DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
|
|
|
- DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
|
|
|
- DM9000_DBG("rx status check: %d\n", rxbyte);
|
|
|
- }
|
|
|
- DM9000_DBG("receiving packet\n");
|
|
|
-
|
|
|
- /* A packet ready now & Get status/length */
|
|
|
- DM9000_outb(DM9000_MRCMD, DM9000_IO);
|
|
|
+ DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
|
|
|
|
|
|
-#ifdef CONFIG_DM9000_USE_8BIT
|
|
|
- RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
|
|
|
- RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
|
|
|
-
|
|
|
-#endif /* */
|
|
|
-#ifdef CONFIG_DM9000_USE_16BIT
|
|
|
- RxStatus = DM9000_inw(DM9000_DATA);
|
|
|
- RxLen = DM9000_inw(DM9000_DATA);
|
|
|
-
|
|
|
-#endif /* */
|
|
|
-#ifdef CONFIG_DM9000_USE_32BIT
|
|
|
- tmpdata = DM9000_inl(DM9000_DATA);
|
|
|
- RxStatus = tmpdata;
|
|
|
- RxLen = tmpdata >> 16;
|
|
|
+ /* There is _at least_ 1 package in the fifo, read them all */
|
|
|
+ for (;;) {
|
|
|
+ DM9000_ior(DM9000_MRCMDX); /* Dummy read */
|
|
|
|
|
|
-#endif /* */
|
|
|
- DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
|
|
|
+ /* Get most updated data,
|
|
|
+ only look at bits 0:1, See application notes DM9000 */
|
|
|
+ rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
|
|
|
|
|
|
- /* Move data from DM9000 */
|
|
|
- /* Read received packet from RX SRAM */
|
|
|
-#ifdef CONFIG_DM9000_USE_8BIT
|
|
|
- for (i = 0; i < RxLen; i++)
|
|
|
- rdptr[i] = DM9000_inb(DM9000_DATA);
|
|
|
-
|
|
|
-#endif /* */
|
|
|
-#ifdef CONFIG_DM9000_USE_16BIT
|
|
|
- tmplen = (RxLen + 1) / 2;
|
|
|
- for (i = 0; i < tmplen; i++)
|
|
|
- ((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA);
|
|
|
+ /* Status check: this byte must be 0 or 1 */
|
|
|
+ if (rxbyte > DM9000_PKT_RDY) {
|
|
|
+ DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
|
|
|
+ DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
|
|
|
+ printf("DM9000 error: status check fail: 0x%x\n",
|
|
|
+ rxbyte);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
-#endif /* */
|
|
|
-#ifdef CONFIG_DM9000_USE_32BIT
|
|
|
- tmplen = (RxLen + 3) / 4;
|
|
|
- for (i = 0; i < tmplen; i++)
|
|
|
- ((u32 *) rdptr)[i] = DM9000_inl(DM9000_DATA);
|
|
|
+ if (rxbyte != DM9000_PKT_RDY)
|
|
|
+ return 0; /* No packet received, ignore */
|
|
|
+
|
|
|
+ DM9000_DBG("receiving packet\n");
|
|
|
+
|
|
|
+ /* A packet ready now & Get status/length */
|
|
|
+ (db->rx_status)(&RxStatus, &RxLen);
|
|
|
+
|
|
|
+ DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
|
|
|
+
|
|
|
+ /* Move data from DM9000 */
|
|
|
+ /* Read received packet from RX SRAM */
|
|
|
+ (db->inblk)(rdptr, RxLen);
|
|
|
+
|
|
|
+ if ((RxStatus & 0xbf00) || (RxLen < 0x40)
|
|
|
+ || (RxLen > DM9000_PKT_MAX)) {
|
|
|
+ if (RxStatus & 0x100) {
|
|
|
+ printf("rx fifo error\n");
|
|
|
+ }
|
|
|
+ if (RxStatus & 0x200) {
|
|
|
+ printf("rx crc error\n");
|
|
|
+ }
|
|
|
+ if (RxStatus & 0x8000) {
|
|
|
+ printf("rx length error\n");
|
|
|
+ }
|
|
|
+ if (RxLen > DM9000_PKT_MAX) {
|
|
|
+ printf("rx length too big\n");
|
|
|
+ dm9000_reset();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
|
|
|
|
|
|
-#endif /* */
|
|
|
- if ((RxStatus & 0xbf00) || (RxLen < 0x40)
|
|
|
- || (RxLen > DM9000_PKT_MAX)) {
|
|
|
- if (RxStatus & 0x100) {
|
|
|
- printf("rx fifo error\n");
|
|
|
+ DM9000_DBG("passing packet to upper layer\n");
|
|
|
+ NetReceive(NetRxPackets[0], RxLen);
|
|
|
}
|
|
|
- if (RxStatus & 0x200) {
|
|
|
- printf("rx crc error\n");
|
|
|
- }
|
|
|
- if (RxStatus & 0x8000) {
|
|
|
- printf("rx length error\n");
|
|
|
- }
|
|
|
- if (RxLen > DM9000_PKT_MAX) {
|
|
|
- printf("rx length too big\n");
|
|
|
- dm9000_reset();
|
|
|
- }
|
|
|
- } else {
|
|
|
-
|
|
|
- /* Pass to upper layer */
|
|
|
- DM9000_DBG("passing packet to upper layer\n");
|
|
|
- NetReceive(NetRxPackets[0], RxLen);
|
|
|
- return RxLen;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
@@ -592,12 +731,12 @@ phy_read(int reg)
|
|
|
/* Fill the phyxcer register into REG_0C */
|
|
|
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
|
|
|
DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
|
|
|
- udelay(100); /* Wait read complete */
|
|
|
+ udelay(100); /* Wait read complete */
|
|
|
DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
|
|
|
val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
|
|
|
|
|
|
/* The read data keeps on REG_0D & REG_0E */
|
|
|
- DM9000_DBG("phy_read(%d): %d\n", reg, val);
|
|
|
+ DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
|
|
|
return val;
|
|
|
}
|
|
|
|
|
@@ -615,8 +754,7 @@ phy_write(int reg, u16 value)
|
|
|
DM9000_iow(DM9000_EPDRL, (value & 0xff));
|
|
|
DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
|
|
|
DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
|
|
|
- udelay(500); /* Wait write complete */
|
|
|
+ udelay(500); /* Wait write complete */
|
|
|
DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
|
|
|
- DM9000_DBG("phy_write(reg:%d, value:%d)\n", reg, value);
|
|
|
+ DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
|
|
|
}
|
|
|
-#endif /* CONFIG_DRIVER_DM9000 */
|