mirror of https://github.com/hak5/openwrt.git
179 lines
6.0 KiB
C
179 lines
6.0 KiB
C
/**************************************************************************
|
|
*
|
|
* BRIEF MODULE DESCRIPTION
|
|
* Definitions for IDT RC32434 on-chip ethernet controller.
|
|
*
|
|
* Copyright 2004 IDT Inc. (rischelp@idt.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*
|
|
**************************************************************************
|
|
* May 2004 rkt, neb
|
|
*
|
|
* Initial Release
|
|
*
|
|
* Aug 2004
|
|
*
|
|
* Added NAPI
|
|
*
|
|
**************************************************************************
|
|
*/
|
|
|
|
|
|
#include <asm/rc32434/rc32434.h>
|
|
#include <asm/rc32434/dma_v.h>
|
|
#include <asm/rc32434/eth_v.h>
|
|
|
|
#define CONFIG_IDT_USE_NAPI 1
|
|
#define RC32434_DEBUG 2
|
|
//#define RC32434_PROC_DEBUG
|
|
#undef RC32434_DEBUG
|
|
|
|
#ifdef RC32434_DEBUG
|
|
|
|
/* use 0 for production, 1 for verification, >2 for debug */
|
|
static int rc32434_debug = RC32434_DEBUG;
|
|
#define ASSERT(expr) \
|
|
if(!(expr)) { \
|
|
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
|
|
#expr,__FILE__,__FUNCTION__,__LINE__); }
|
|
#define DBG(lvl, format, arg...) if (rc32434_debug > lvl) printk(KERN_INFO "%s: " format, dev->name , ## arg)
|
|
#else
|
|
#define ASSERT(expr) do {} while (0)
|
|
#define DBG(lvl, format, arg...) do {} while (0)
|
|
#endif
|
|
|
|
#define INFO(format, arg...) printk(KERN_INFO "%s: " format, dev->name , ## arg)
|
|
#define ERR(format, arg...) printk(KERN_ERR "%s: " format, dev->name , ## arg)
|
|
#define WARN(format, arg...) printk(KERN_WARNING "%s: " format, dev->name , ## arg)
|
|
|
|
/* the following must be powers of two */
|
|
#ifdef CONFIG_IDT_USE_NAPI
|
|
#define RC32434_NUM_RDS 64 /* number of receive descriptors */
|
|
#define RC32434_NUM_TDS 64 /* number of transmit descriptors */
|
|
#else
|
|
#define RC32434_NUM_RDS 128 /* number of receive descriptors */
|
|
#define RC32434_NUM_TDS 128 /* number of transmit descriptors */
|
|
#endif
|
|
|
|
#define RC32434_RBSIZE 1536 /* size of one resource buffer = Ether MTU */
|
|
#define RC32434_RDS_MASK (RC32434_NUM_RDS-1)
|
|
#define RC32434_TDS_MASK (RC32434_NUM_TDS-1)
|
|
#define RD_RING_SIZE (RC32434_NUM_RDS * sizeof(struct DMAD_s))
|
|
#define TD_RING_SIZE (RC32434_NUM_TDS * sizeof(struct DMAD_s))
|
|
|
|
#define RC32434_TX_TIMEOUT HZ * 100
|
|
|
|
#define rc32434_eth0_regs ((ETH_t)(ETH0_VirtualAddress))
|
|
#define rc32434_eth1_regs ((ETH_t)(ETH1_VirtualAddress))
|
|
|
|
enum status { filled, empty};
|
|
#define IS_DMA_FINISHED(X) (((X) & (DMAD_f_m)) != 0)
|
|
#define IS_DMA_DONE(X) (((X) & (DMAD_d_m)) != 0)
|
|
|
|
|
|
/* Information that need to be kept for each board. */
|
|
struct rc32434_local {
|
|
ETH_t eth_regs;
|
|
DMA_Chan_t rx_dma_regs;
|
|
DMA_Chan_t tx_dma_regs;
|
|
volatile DMAD_t td_ring; /* transmit descriptor ring */
|
|
volatile DMAD_t rd_ring; /* receive descriptor ring */
|
|
|
|
struct sk_buff* tx_skb[RC32434_NUM_TDS]; /* skbuffs for pkt to trans */
|
|
struct sk_buff* rx_skb[RC32434_NUM_RDS]; /* skbuffs for pkt to trans */
|
|
|
|
#ifndef CONFIG_IDT_USE_NAPI
|
|
struct tasklet_struct * rx_tasklet;
|
|
#endif
|
|
struct tasklet_struct * tx_tasklet;
|
|
|
|
int rx_next_done;
|
|
int rx_chain_head;
|
|
int rx_chain_tail;
|
|
enum status rx_chain_status;
|
|
|
|
int tx_next_done;
|
|
int tx_chain_head;
|
|
int tx_chain_tail;
|
|
enum status tx_chain_status;
|
|
int tx_count;
|
|
int tx_full;
|
|
|
|
struct timer_list mii_phy_timer;
|
|
unsigned long duplex_mode;
|
|
|
|
int rx_irq;
|
|
int tx_irq;
|
|
int ovr_irq;
|
|
int und_irq;
|
|
|
|
struct net_device_stats stats;
|
|
spinlock_t lock;
|
|
|
|
/* debug /proc entry */
|
|
struct proc_dir_entry *ps;
|
|
int dma_halt_cnt; int dma_run_cnt;
|
|
};
|
|
|
|
extern unsigned int idt_cpu_freq;
|
|
|
|
/* Index to functions, as function prototypes. */
|
|
static int rc32434_open(struct net_device *dev);
|
|
static int rc32434_send_packet(struct sk_buff *skb, struct net_device *dev);
|
|
static void rc32434_mii_handler(unsigned long data);
|
|
static irqreturn_t rc32434_und_interrupt(int irq, void *dev_id);
|
|
static irqreturn_t rc32434_rx_dma_interrupt(int irq, void *dev_id);
|
|
static irqreturn_t rc32434_tx_dma_interrupt(int irq, void *dev_id);
|
|
#ifdef RC32434_REVISION
|
|
static irqreturn_t rc32434_ovr_interrupt(int irq, void *dev_id);
|
|
#endif
|
|
static int rc32434_close(struct net_device *dev);
|
|
static struct net_device_stats *rc32434_get_stats(struct net_device *dev);
|
|
static void rc32434_multicast_list(struct net_device *dev);
|
|
static int rc32434_init(struct net_device *dev);
|
|
static void rc32434_tx_timeout(struct net_device *dev);
|
|
|
|
static void rc32434_tx_tasklet(unsigned long tx_data_dev);
|
|
#ifdef CONFIG_IDT_USE_NAPI
|
|
static int rc32434_poll(struct net_device *rx_data_dev, int *budget);
|
|
#else
|
|
static void rc32434_rx_tasklet(unsigned long rx_data_dev);
|
|
#endif
|
|
static void rc32434_cleanup_module(void);
|
|
|
|
|
|
static inline void rc32434_abort_dma(struct net_device *dev, DMA_Chan_t ch)
|
|
{
|
|
if (__raw_readl(&ch->dmac) & DMAC_run_m) {
|
|
__raw_writel(0x10, &ch->dmac);
|
|
|
|
while (!(__raw_readl(&ch->dmas) & DMAS_h_m))
|
|
dev->trans_start = jiffies;
|
|
|
|
__raw_writel(0, &ch->dmas);
|
|
}
|
|
|
|
__raw_writel(0, &ch->dmadptr);
|
|
__raw_writel(0, &ch->dmandptr);
|
|
}
|