📄 dm90x0.c
字号:
/**************************************************************************** * drivers/net/dm9x.c * * Copyright (C) 2007 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * References: Davicom data sheets (DM9000-DS-F03-041906.pdf, * DM9010-DS-F01-103006.pdf) and looking at lots of other DM90x0 * drivers. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************//**************************************************************************** * Included Files ****************************************************************************/#include <nuttx/config.h>#if defined(CONFIG_NET) && defined(CONFIG_NET_DM90x0)/* Only one hardware interface supported at present (although there are * hooks throughout the design to that extending the support to multiple * interfaces should not be that difficult) */#undef CONFIG_DM9X_NINTERFACES#define CONFIG_DM9X_NINTERFACES 1#include <time.h>#include <string.h>#include <debug.h>#include <wdog.h>#include <errno.h>#include <nuttx/irq.h>#include <nuttx/arch.h>#include <net/ethernet.h>#include <net/uip/uip.h>#include <net/uip/uip-arp.h>#include <net/uip/uip-arch.h>/**************************************************************************** * Definitions ****************************************************************************//* DM90000 and DM9010 register offets */#define DM9X_NETC 0x00 /* Network control register */#define DM9X_NETS 0x01 /* Network Status register */#define DM9X_TXC 0x02 /* TX control register */#define DM9X_TXS1 0x03 /* TX status register 1 */#define DM9X_TXS2 0x03 /* TX status register 2 */#define DM9X_RXC 0x05 /* RX control register */#define DM9X_RXS 0x06 /* RX status register */#define DM9X_RXOVF 0x07 /* Receive overflow counter register */#define DM9X_BPTHRES 0x08 /* Back pressure threshold register */#define DM9X_FCTHRES 0x09 /* Flow control threshold register */#define DM9X_FC 0x0a /* RX/TX flow control register */#define DM9X_EEPHYC 0x0b /* EEPROM & PHY control register */#define DM9X_EEPHYA 0x0c /* EEPROM & PHY address register */#define DM9X_EEPHYDL 0x0d /* EEPROM & PHY data register (lo) */#define DM9X_EEPHYDH 0x0e /* EEPROM & PHY data register (hi) */#define DM9X_WAKEUP 0x0f /* Wake-up control register */#define DM9X_PAB0 0x10 /* Physical address register (byte 0) */#define DM9X_PAB1 0x11 /* Physical address register (byte 1) */#define DM9X_PAB2 0x12 /* Physical address register (byte 2) */#define DM9X_PAB3 0x13 /* Physical address register (byte 3) */#define DM9X_PAB4 0x14 /* Physical address register (byte 4) */#define DM9X_PAB5 0x15 /* Physical address register (byte 5) */#define DM9X_MAB0 0x16 /* Multicast address register (byte 0) */#define DM9X_MAB1 0x17 /* Multicast address register (byte 1) */#define DM9X_MAB2 0x18 /* Multicast address register (byte 2) */#define DM9X_MAB3 0x19 /* Multicast address register (byte 3) */#define DM9X_MAB4 0x1a /* Multicast address register (byte 4) */#define DM9X_MAB5 0x1b /* Multicast address register (byte 5) */#define DM9X_MAB6 0x1c /* Multicast address register (byte 6) */#define DM9X_MAB7 0x1d /* Multicast address register (byte 7) */#define DM9X_GPC 0x1e /* General purpose control register */#define DM9X_GPD 0x1f /* General purpose register */#define DM9X_TRPAL 0x22 /* TX read pointer address (lo) */#define DM9X_TRPAH 0x23 /* TX read pointer address (hi) */#define DM9X_RWPAL 0x24 /* RX write pointer address (lo) */#define DM9X_RWPAH 0x25 /* RX write pointer address (hi) */#define DM9X_VIDL 0x28 /* Vendor ID (lo) */#define DM9X_VIDH 0x29 /* Vendor ID (hi) */#define DM9X_PIDL 0x2a /* Product ID (lo) */#define DM9X_PIDH 0x2b /* Product ID (hi) */#define DM9X_CHIPR 0x2c /* Product ID (lo) */#define DM9X_TXC2 0x2d /* Transmit control register 2 (dm9010) */#define DM9X_OTC 0x2e /* Operation test control register (dm9010) */#define DM9X_SMODEC 0x2f /* Special mode control register */#define DM9X_ETXCSR 0x30 /* Early transmit control/status register (dm9010) */#define DM9X_TCCR 0x31 /* Transmit checksum control register (dm9010) */#define DM9X_RCSR 0x32 /* Receive checksum control/status register (dm9010) */#define DM9X_EPHYA 0x33 /* External PHY address register (dm9010) */#define DM9X_GPC2 0x34 /* General purpose control register 2 (dm9010) */#define DM9X_GPD2 0x35 /* General purpose register 2 */#define DM9X_GPC3 0x36 /* General purpose control register 3 (dm9010) */#define DM9X_GPD3 0x37 /* General purpose register 3 */#define DM9X_PBUSC 0x38 /* Processor bus control register (dm9010) */#define DM9X_IPINC 0x39 /* INT pin control register (dm9010) */#define DM9X_MON1 0x40 /* Monitor register 1 (dm9010) */#define DM9X_MON2 0x41 /* Monitor register 2 (dm9010) */#define DM9X_SCLKC 0x50 /* System clock turn ON control register (dm9010) */#define DM9X_SCLKR 0x51 /* Resume system clock control register (dm9010) */#define DM9X_MRCMDX 0xf0 /* Memory data pre-fetch read command without address increment */#define DM9X_MRCMDX1 0xf1 /* memory data read command without address increment (dm9010) */#define DM9X_MRCMD 0xf2 /* Memory data read command with address increment */#define DM9X_MDRAL 0xf4 /* Memory data read address register (lo) */#define DM9X_MDRAH 0xf5 /* Memory data read address register (hi) */#define DM9X_MWCMDX 0xf6 /* Memory data write command without address increment */#define DM9X_MWCMD 0xf8 /* Memory data write command with address increment */#define DM9X_MDWAL 0xfa /* Memory data write address register (lo) */#define DM9X_MDWAH 0xfb /* Memory data write address register (lo) */#define DM9X_TXPLL 0xfc /* Memory data write address register (lo) */#define DM9X_TXPLH 0xfd /* Memory data write address register (hi) */#define DM9X_ISR 0xfe /* Interrupt status register */#define DM9X_IMR 0xff /* Interrupt mask register *//* Network control register bit definitions */#define DM9X_NETC_RST (1 << 0) /* Software reset */#define DM9X_NETC_LBKM (3 << 1) /* Loopback mode mask */#define DM9X_NETC_LBK0 (0 << 1) /* 0: Normal */#define DM9X_NETC_LBK1 (1 << 1) /* 1: MAC internal loopback */#define DM9X_NETC_LBK2 (2 << 1) /* 2: Internal PHY 100M mode loopback */#define DM9X_NETC_FDX (1 << 3) /* Full dupliex mode */#define DM9X_NETC_FCOL (1 << 4) /* Force collision mode */#define DM9X_NETC_WAKEEN (1 << 6) /* Wakeup event enable */#define DM9X_NETC_EXTPHY (1 << 7) /* Select external PHY *//* Network status bit definitions */#define DM9X_NETS_RXOV (1 << 1) /* RX Fifo overflow */#define DM9X_NETS_TX1END (1 << 2) /* TX packet 1 complete status */#define DM9X_NETS_TX2END (1 << 3) /* TX packet 2 complete status */#define DM9X_NETS_WAKEST (1 << 5) /* Wakeup event status */#define DM9X_NETS_LINKST (1 << 6) /* Link status */#define DM9X_NETS_SPEED (1 << 7) /* Media speed *//* IMR/ISR bit definitions */#define DM9X_INT_PR (1 << 0) /* Packet received interrupt */#define DM9X_INT_PT (1 << 1) /* Packet transmitted interrupt */#define DM9X_INT_RO (1 << 2) /* Receive overflow interrupt */#define DM9X_INT_ROO (1 << 3) /* Receive overflow counter overflow int */#define DM9X_INT_UDRUN (1 << 4) /* Transmit underrun interrupt */#define DM9X_INT_LNKCHG (1 << 5) /* Link status change interrupt */#define DM9X_INT_ALL (0x3f)#define DM9X_IMR_UNUSED (1 << 6) /* (not used) */#define DM9X_IMR_PAR (1 << 7) /* Enable auto R/W pointer reset */#define DM9X_ISR_IOMODEM (3 << 6) /* IO mode mask */#define DM9X_ISR_IOMODE8 (2 << 6) /* IO mode = 8 bit */#define DM9X_ISR_IOMODE16 (0 << 6) /* IO mode = 16 bit */#define DM9X_ISR_IOMODE32 (1 << 6) /* IO mode = 32 bit */#define DM9X_IMRENABLE (DM9X_INT_PR|DM9X_INT_PT|DM9X_INT_LNKCHG|DM9X_IMR_PAR)#define DM9X_IMRRXDISABLE (DM9X_INT_PT|DM9X_INT_LNKCHG|DM9X_IMR_PAR)#define DM9X_IMRDISABLE (DM9X_IMR_PAR)/* EEPROM/PHY control regiser bits */#define DM9X_EEPHYC_ERRE (1 << 0) /* EEPROM (vs PHY) access status */#define DM9X_EEPHYC_ERPRW (1 << 1) /* EEPROM/PHY write access */#define DM9X_EEPHYC_ERPRR (1 << 2) /* EEPROM/PHY read access */#define DM9X_EEPHYC_EPOS (1 << 3) /* EEPROM/PHY operation select */#define DM9X_EEPHYC_WEP (1 << 4) /* Write EEPROM enable */#define DM9X_EEPHYC_REEP (1 << 5) /* Reload EEPROM *//* Supported values from the vendor and product ID register */#define DM9X_DAVICOMVID 0x0a46#define DM9X_DM9000PID 0x9000#define DM9X_DM9010PID 0x9010/* RX control register bit settings */#define DM9X_RXC_RXEN (1 << 0) /* RX enable */#define DM9X_RXC_PRMSC (1 << 1) /* Promiscuous mode */#define DM9X_RXC_RUNT (1 << 2) /* Pass runt packet */#define DM9X_RXC_ALL (1 << 3) /* Pass all multicast */#define DM9X_RXC_DISCRC (1 << 4) /* Discard CRC error packets */#define DM9X_RXC_DISLONG (1 << 5) /* Discard long packets */#define DM9X_RXC_WTDIS (1 << 6) /* Disable watchdog timer */#define DM9X_RXC_HASHALL (1 << 7) /* Filter all addresses in hash table */#define DM9X_RXCSETUP (DM9X_RXC_DISCRC|DM9X_RXC_DISLONG)/* EEPHY bit settings */#define DM9X_EEPHYA_EROA 0x40 /* PHY register address 0x01 */#define DM9X_PKTRDY 0x01 /* Packet ready to receive *//* The RX interrupt will be disabled if more than the following RX * interrupts are received back-to-back. */#define DM9X_CRXTHRES 10/* All access is via an index register and a data regist. Select accecss * according to user supplied base address and bus width. */#if defined(CONFIG_DM9X_BUSWIDTH8)# define DM9X_INDEX *(volatile uint8*)(CONFIG_DM9X_BASE)# define DM9X_DATA *(volatile uint8*)(CONFIG_DM9X_BASE + 2)#elif defined(CONFIG_DM9X_BUSWIDTH16)# define DM9X_INDEX *(volatile uint16*)(CONFIG_DM9X_BASE)# define DM9X_DATA *(volatile uint16*)(CONFIG_DM9X_BASE + 2)#elif defined(CONFIG_DM9X_BUSWIDTH32)# define DM9X_INDEX *(volatile uint32*)(CONFIG_DM9X_BASE)# define DM9X_DATA *(volatile uint32*)(CONFIG_DM9X_BASE + 2)#endif/* Phy operating mode. Default is AUTO, but this setting can be overridden * in the NuttX configuration file. */#define DM9X_MODE_AUTO 0#define DM9X_MODE_10MHD 1#define DM9X_MODE_100MHD 2#define DM9X_MODE_10MFD 3#define DM9X_MODE_100MFD 4#ifndef CONFIG_DM9X_MODE# define CONFIG_DM9X_MODE DM9X_MODE_AUTO#endif/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */#define DM6X_WDDELAY (1*CLK_TCK)#define DM6X_POLLHSEC (1*2)/* TX timeout = 1 minute */#define DM6X_TXTIMEOUT (60*CLK_TCK)/* This is a helper pointer for accessing the contents of the Ethernet header */#define BUF ((struct uip_eth_hdr *)dm9x->dm_dev.d_buf)/**************************************************************************** * Private Types ****************************************************************************/union rx_desc_u{ uint8 rx_buf[4]; struct { uint8 rx_byte; uint8 rx_status; uint16 rx_len; } desc;};/* The dm9x_driver_s encapsulates all DM90x0 state information for a single * DM90x0 hardware interface */struct dm9x_driver_s{ boolean dm_bifup; /* TRUE:ifup FALSE:ifdown */ boolean dm_b100M; /* TRUE:speed == 100M; FALSE:speed == 10M */ WDOG_ID dm_txpoll; /* TX poll timer */ WDOG_ID dm_txtimeout; /* TX timeout timer */ uint8 dm_ntxpending; /* Count of packets pending transmission */ uint8 ncrxpackets; /* Number of continuous rx packets */ /* Mode-dependent function to move data in 8/16/32 I/O modes */ void (*dm_read)(uint8 *ptr, int len); void (*dm_write)(const uint8 *ptr, int len); void (*dm_discard)(int len);#if defined(CONFIG_DM9X_STATS) uint32 dm_ntxpackets; /* Count of packets sent */ uint32 dm_ntxbytes; /* Count of bytes sent */ uint32 dm_ntxerrors; /* Count of TX errors */ uint32 dm_nrxpackets; /* Count of packets received */ uint32 dm_nrxbytes; /* Count of bytes received */ uint32 dm_nrxfifoerrors; /* Count of RX FIFO overflow errors */ uint32 dm_nrxcrcerrors; /* Count of RX CRC errors */ uint32 dm_nrxlengtherrors; /* Count of RX length errors */ uint32 dm_nphyserrors; /* Count of physical layer errors */ uint32 dm_nresets; /* Counts number of resets */ uint32 dm_ntxtimeouts; /* Counts resets caused by TX timeouts */#endif /* This holds the information visible to uIP/NuttX */ struct uip_driver_s dm_dev;};/**************************************************************************** * Private Data ****************************************************************************//* At present, only a single DM90x0 device is supported. */static struct dm9x_driver_s g_dm9x[CONFIG_DM9X_NINTERFACES];/**************************************************************************** * Private Function Prototypes ****************************************************************************//* Utility functions */static uint8 getreg(int reg);static void putreg(int reg, uint8 value);static void read8(uint8 *ptr, int len);static void read16(uint8 *ptr, int len);static void read32(uint8 *ptr, int len);static void discard8(int len);static void discard16(int len);static void discard32(int len);static void write8(const uint8 *ptr, int len);static void write16(const uint8 *ptr, int len);static void write32(const uint8 *ptr, int len);/* static uint16 dm9x_readsrom(struct dm9x_driver_s *dm9x, int offset); */static uint16 dm9x_phyread(struct dm9x_driver_s *dm9x, int reg);static void dm9x_phywrite(struct dm9x_driver_s *dm9x, int reg, uint16 value);#if defined(CONFIG_DM9X_STATS)static void dm9x_resetstatistics(struct dm9x_driver_s *dm9x);#else# define dm9x_resetstatistics(dm9x)#endif#if defined(CONFIG_DM9X_STATS) && defined(CONFIG_DEBUG)static void dm9x_dumpstatistics(struct dm9x_driver_s *dm9x);#else# define dm9x_dumpstatistics(dm9x)#endif#if defined(CONFIG_DM9X_CHECKSUM)static boolean dm9x_rxchecksumready(uint8);#else# define dm9x_rxchecksumready(a) ((a) == 0x01)#endif/* Common TX logic */static int dm9x_transmit(struct dm9x_driver_s *dm9x);static int dm9x_uiptxpoll(struct uip_driver_s *dev);/* Interrupt handling */static void dm9x_receive(struct dm9x_driver_s *dm9x);static void dm9x_txdone(struct dm9x_driver_s *dm9x);static int dm9x_interrupt(int irq, FAR void *context);/* Watchdog timer expirations */static void dm9x_polltimer(int argc, uint32 arg, ...);static void dm9x_txtimeout(int argc, uint32 arg, ...);/* NuttX callback functions */static int dm9x_ifup(struct uip_driver_s *dev);static int dm9x_ifdown(struct uip_driver_s *dev);static int dm9x_txavail(struct uip_driver_s *dev);/* Initialization functions */static void dm9x_bringup(struct dm9x_driver_s *dm9x);static void dm9x_reset(struct dm9x_driver_s *dm9x);/**************************************************************************** * Private Functions ****************************************************************************//**************************************************************************** * Function: getreg and setreg * * Description: * Access to memory-mapped DM90x0 8-bit registers * * Parameters: * reg - Register number * value - Value to write to the register (setreg only) * * Returned Value: * Value read from the register (getreg only) * * Assumptions: * ****************************************************************************/static uint8 getreg(int reg){ DM9X_INDEX = reg; return DM9X_DATA & 0xff;}static void putreg(int reg, uint8 value){ DM9X_INDEX = reg; DM9X_DATA = value & 0xff;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -