|
|
|
@ -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 ---------------- */ |
|
|
|
@ -60,9 +75,21 @@ TODO: Homerun NIC and longrun NIC are not functional, only internal at the |
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_DM9000_DEBUG |
|
|
|
|
#define DM9000_DBG(fmt,args...) printf(fmt, ##args) |
|
|
|
|
#else /* */ |
|
|
|
|
#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,38 +551,18 @@ 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"); |
|
|
|
|
struct board_info *db = &dm9000_info; |
|
|
|
|
|
|
|
|
|
/* Move data to DM9000 TX RAM */ |
|
|
|
|
data_ptr = (char *) packet; |
|
|
|
|
DM9000_outb(DM9000_MWCMD, DM9000_IO); |
|
|
|
|
DM9000_DMP_PACKET("eth_send", packet, length); |
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_DM9000_USE_8BIT |
|
|
|
|
/* Byte mode */ |
|
|
|
|
for (i = 0; i < length; i++) |
|
|
|
|
DM9000_outb((data_ptr[i] & 0xff), DM9000_DATA); |
|
|
|
|
DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */ |
|
|
|
|
|
|
|
|
|
#endif /* */ |
|
|
|
|
#ifdef CONFIG_DM9000_USE_16BIT |
|
|
|
|
tmplen = (length + 1) / 2; |
|
|
|
|
for (i = 0; i < tmplen; i++) |
|
|
|
|
DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA); |
|
|
|
|
|
|
|
|
|
#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); |
|
|
|
@ -418,12 +573,15 @@ eth_send(volatile void *packet, int length) |
|
|
|
|
|
|
|
|
|
/* 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,65 +610,46 @@ 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; |
|
|
|
|
|
|
|
|
|
DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */ |
|
|
|
|
|
|
|
|
|
/* There is _at least_ 1 package in the fifo, read them all */ |
|
|
|
|
for (;;) { |
|
|
|
|
DM9000_ior(DM9000_MRCMDX); /* Dummy read */ |
|
|
|
|
|
|
|
|
|
/* Get most updated data,
|
|
|
|
|
only look at bits 0:1, See application notes DM9000 */ |
|
|
|
|
rxbyte = DM9000_inb(DM9000_DATA) & 0x03; |
|
|
|
|
|
|
|
|
|
/* Status check: this byte must be 0 or 1 */ |
|
|
|
|
if (rxbyte > 1) { |
|
|
|
|
if (rxbyte > DM9000_PKT_RDY) { |
|
|
|
|
DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */ |
|
|
|
|
DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */ |
|
|
|
|
DM9000_DBG("rx status check: %d\n", rxbyte); |
|
|
|
|
printf("DM9000 error: status check fail: 0x%x\n", |
|
|
|
|
rxbyte); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
DM9000_DBG("receiving packet\n"); |
|
|
|
|
|
|
|
|
|
/* A packet ready now & Get status/length */ |
|
|
|
|
DM9000_outb(DM9000_MRCMD, DM9000_IO); |
|
|
|
|
|
|
|
|
|
#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); |
|
|
|
|
if (rxbyte != DM9000_PKT_RDY) |
|
|
|
|
return 0; /* No packet received, ignore */ |
|
|
|
|
|
|
|
|
|
#endif /* */ |
|
|
|
|
#ifdef CONFIG_DM9000_USE_16BIT |
|
|
|
|
RxStatus = DM9000_inw(DM9000_DATA); |
|
|
|
|
RxLen = DM9000_inw(DM9000_DATA); |
|
|
|
|
DM9000_DBG("receiving packet\n"); |
|
|
|
|
|
|
|
|
|
#endif /* */ |
|
|
|
|
#ifdef CONFIG_DM9000_USE_32BIT |
|
|
|
|
tmpdata = DM9000_inl(DM9000_DATA); |
|
|
|
|
RxStatus = tmpdata; |
|
|
|
|
RxLen = tmpdata >> 16; |
|
|
|
|
/* A packet ready now & Get status/length */ |
|
|
|
|
(db->rx_status)(&RxStatus, &RxLen); |
|
|
|
|
|
|
|
|
|
#endif /* */ |
|
|
|
|
DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen); |
|
|
|
|
|
|
|
|
|
/* 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); |
|
|
|
|
(db->inblk)(rdptr, RxLen); |
|
|
|
|
|
|
|
|
|
#endif /* */ |
|
|
|
|
#ifdef CONFIG_DM9000_USE_16BIT |
|
|
|
|
tmplen = (RxLen + 1) / 2; |
|
|
|
|
for (i = 0; i < tmplen; i++) |
|
|
|
|
((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA); |
|
|
|
|
|
|
|
|
|
#endif /* */ |
|
|
|
|
#ifdef CONFIG_DM9000_USE_32BIT |
|
|
|
|
tmplen = (RxLen + 3) / 4; |
|
|
|
|
for (i = 0; i < tmplen; i++) |
|
|
|
|
((u32 *) rdptr)[i] = DM9000_inl(DM9000_DATA); |
|
|
|
|
|
|
|
|
|
#endif /* */ |
|
|
|
|
if ((RxStatus & 0xbf00) || (RxLen < 0x40) |
|
|
|
|
|| (RxLen > DM9000_PKT_MAX)) { |
|
|
|
|
if (RxStatus & 0x100) { |
|
|
|
@ -527,11 +666,11 @@ eth_rx(void) |
|
|
|
|
dm9000_reset(); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
DM9000_DMP_PACKET("eth_rx", rdptr, RxLen); |
|
|
|
|
|
|
|
|
|
/* Pass to upper layer */ |
|
|
|
|
DM9000_DBG("passing packet to upper layer\n"); |
|
|
|
|
NetReceive(NetRxPackets[0], RxLen); |
|
|
|
|
return RxLen; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -597,7 +736,7 @@ phy_read(int reg) |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -617,6 +756,5 @@ phy_write(int reg, u16 value) |
|
|
|
|
DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */ |
|
|
|
|
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 */ |
|
|
|
|