Chinaunix首页 | 论坛 | 博客
  • 博客访问: 624062
  • 博文数量: 144
  • 博客积分: 5037
  • 博客等级: 大校
  • 技术积分: 1581
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-30 21:49
文章存档

2010年(16)

2009年(128)

分类: LINUX

2009-09-01 15:11:30

S3C4510b的BDMA有Bug,会在某些情況下挂掉,按三星自己的说法,「MAC controller is hanged after receive heavy short frame from 100 Mbps network.」。这样造成网路通信中断,只有重新ifconfig eth0 down/up一下才可以恢复。Mac Wang写的驱动好像没有有这方面的处理。

朋友们帮我测下,下面的驱动是不是解决了这个问题。谢谢。。。

/* s3c4510b.c
 * linux/deriver/net/s3c4510.c
 * Ethernet driver for Samsung 4510B
 * Copyright (C) 2002 Mac Wang
 *
 *     Version 0.2 (Liu Tao ):
 *     - Zero-copy transmit and receive.
 *     - Code clean up.
 */

/*
 * -Version 0.2.01
 * -modified by liuyanguo in Aug 20th 2009 *
 *
 */


#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/sockios.h>        //do_ioctl --int cmd --
#include <linux/if.h>            //do_ioctl --struct ifreq
#include <asm/irq.h>
#include <asm/hardware.h>
#include "s3c4510.h"

#define DRV_NAME    "S3C4510 ether driver"
#define DRV_VERSION    "v0.2.01 (test10)"
#define DRV_RELDATE    "20-Aug-2009"

static char version[] __devinitdata =
DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";

#define RX_RING_SIZE    64
#define TX_RING_SIZE    32
#define PKT_BUF_SZ    1536

#define RX_REFILL_CNT    32
#define TX_TIMEOUT    (4*HZ)

/* Register values. */
enum {
    gMACCON = FullDup,
    gMACTXCON = EnComp | TxEn,
    gMACRXCON = RxEn | StripCRC,
    gBDMATXCON = BTxBRST | BTxMSL110 | BTxSTSKO | BTxEn,
    gBDMARXCON = BRxDIE | BRxEn | BRxLittle | BRxMAINC | BRxBRST | BRxSTSKO | BRxWA10 | BRxNOIE,
    gCAMCON = CompEn | BroadAcc
};

/* The Rx and Tx buffer descriptors. */
struct netdev_desc {
    u32 data_ptr;
    u32 misc_ctl;
    u32 stat_len;
    u32 next_ptr;
};

/*-----------------------*
 * MII reg_data *
 *-----------------------*/

struct mii_data{
    u16 phy_reg0;
    u16 phy_reg1;
    u16 phy_id1;
    u16 phy_id2;
};

/*-----------------------*
 * MII support functions *
 *-----------------------*/

void MiiStationWrite(u32 PhyInAddr, u32 PhyAddr, u32 PhyWrData)
{
    CSR_WRITE(REG_STADATA, PhyWrData);
    CSR_WRITE(REG_STACON, PhyInAddr | PhyAddr | MiiBusy | PHYREGWRITE);
    while( (CSR_READ(REG_STACON) & MiiBusy) ) ;
    delay_physet() ;
}
u32 MiiStationRead(u32 PhyInAddr, u32 PhyAddr)
{
    u32    PhyRdData ;
    CSR_WRITE(REG_STACON, PhyInAddr | PhyAddr | MiiBusy);
    while( (CSR_READ(REG_STACON) & MiiBusy) ) ;
    PhyRdData = CSR_READ(REG_STADATA);
    return PhyRdData ;
}

void delay_physet(void)
{
    int i = 1000 ;
    while(i--) ;
}

/* Device private data. */
struct netdev_private {
    struct netdev_desc rx_ring_buf[RX_RING_SIZE];
    struct netdev_desc tx_ring_buf[TX_RING_SIZE];
    
    struct sk_buff *rx_skbuff[RX_RING_SIZE];
    struct sk_buff *tx_skbuff[TX_RING_SIZE];

    spinlock_t lock;        //spinlock

    unsigned int cur_rx, dirty_rx;
    volatile struct netdev_desc *rx_ring;
    
    unsigned int cur_tx, dirty_tx;
    volatile struct netdev_desc *tx_ring;

    struct tasklet_struct rx_tasklet;
    struct net_device_stats stats;
} __attribute__((aligned (L1_CACHE_BYTES)));


static inline void invalidate_cache(void *addr, u32 len);
static inline void wbflush(void);
static void init_ring(struct net_device *dev);
static void rx_intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
static void tx_intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
static void refill_rx(unsigned long data);
static int start_tx(struct sk_buff *skb, struct net_device *dev);
static int netdev_open(struct net_device *dev);
static int netdev_close(struct net_device *dev);
static struct net_device_stats *get_stats(struct net_device *dev);
//add......
static int netdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);

/* Invalidate buffer cache, buf len should <= 8K byte. */
static inline void invalidate_cache(void *addr, u32 len)
{
    /* Invalidate buffer cache. */
    u32 entry;

    entry = ((u32)addr >> 4) & 0xff;
    len = (len + 15) >> 4;

    while (len--) {
        ((u32 *)(TAG_BASE))[entry] = 0;
        entry = (entry + 1) & 0xff;
    }
}

/* Write buffer flush. */
static inline void wbflush(void)
{
    volatile unsigned int i;

    i = CSR_READ(NOCACHE_BIT);
}

/* Initialize descriptor rings. */
static void init_ring(struct net_device *dev)
{
    struct netdev_private *np = (struct netdev_private *)dev->priv;
    int i;

    /* Initialize descriptor pointers. */
    np->rx_ring = (struct netdev_desc *)((u32)np->rx_ring_buf | NOCACHE_BIT);
    np->tx_ring = (struct netdev_desc *)((u32)np->tx_ring_buf | NOCACHE_BIT);
    np->cur_rx = np->dirty_rx = 0;
    np->cur_tx = np->dirty_tx = 0;

    /* Initialize all Rx descriptors. */
    for (i = 0; i < RX_RING_SIZE; i++) {
        np->rx_ring[i].data_ptr = 0;
        np->rx_ring[i].misc_ctl = 0;
        np->rx_ring[i].stat_len = 0;
        np->rx_ring[i].next_ptr = (u32)(np->rx_ring + ((i + 1) % RX_RING_SIZE));
        np->rx_skbuff[i] = NULL;
    }

    /* Initialize all Tx descriptors. */
    for (i = 0; i < TX_RING_SIZE; i++) {
        np->tx_ring[i].data_ptr = 0;
        np->tx_ring[i].misc_ctl = 0;
        np->tx_ring[i].stat_len = 0;
        np->tx_ring[i].next_ptr = (u32)(np->tx_ring + ((i + 1) % TX_RING_SIZE));
        np->tx_skbuff[i] = NULL;
    }

    /* Fill in the Rx buffers. */
    for (i = 0; i < RX_RING_SIZE - 1; i++) {
        struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
        if (skb == NULL)
            break;
        np->rx_skbuff[i] = skb;
        np->rx_ring[i].data_ptr = (u32)skb->data | BDMA_OWNER;
        skb->dev = dev;
        skb_reserve(skb, 2);
    }
    np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);

    /* Write descriptor base addresses to controller. */
    CSR_WRITE(BDMARXPTR, (u32)(np->rx_ring));
    CSR_WRITE(BDMATXPTR, (u32)(np->tx_ring));
}

/* Interrupt handlers. */
static void rx_intr_handler(int irq, void *dev_instance, struct pt_regs *regs)
{
    struct net_device *dev = (struct net_device *)dev_instance;
    struct netdev_private *np = (struct netdev_private *)dev->priv;
    volatile struct netdev_desc *desc;
    unsigned int entry, count;
    struct sk_buff *skb;
    int pkt_len;
    u32 stat;

    count = 0;
    entry = np->cur_rx % RX_RING_SIZE;
    desc = np->rx_ring + entry;
    
    while ((u32)desc != CSR_READ(BDMARXPTR)) {
        stat = (desc->stat_len >> 16) & 0xffff;
        if(stat & Good){
            pkt_len = (desc->stat_len & 0xffff);    /* Chip omits the CRC. */
            skb = np->rx_skbuff[entry];
            skb_put(skb, pkt_len);
            skb->protocol = eth_type_trans(skb, dev);
            invalidate_cache(skb->data, pkt_len);
            netif_rx(skb);
            np->rx_skbuff[entry] = NULL;
            np->stats.rx_packets++;
            np->stats.rx_bytes += pkt_len;
        } else {
            np->stats.rx_errors++;
            if(stat & LongErr)
                np->stats.rx_length_errors++;
            if(stat & OvMax)
                np->stats.rx_over_errors++;
            if(stat & CRCErr)
                np->stats.rx_crc_errors++;
            if(stat & AlignErr)
                np->stats.rx_frame_errors++;
            if(stat & Overflow)
                np->stats.rx_fifo_errors++;
        }

        count++;
        entry = (entry + 1) % RX_RING_SIZE;
        desc = np->rx_ring + entry;
    }
    np->cur_rx += count;

    CSR_WRITE(BDMASTAT, S_BRxRDF);    /* Enable interrupt report. */

    if (np->cur_rx - np->dirty_rx > RX_REFILL_CNT)
        tasklet_schedule(&np->rx_tasklet);
    else
        CSR_WRITE(BDMARXCON, gBDMARXCON);
}

static void tx_intr_handler(int irq, void *dev_instance, struct pt_regs *regs)
{
    struct net_device *dev = (struct net_device *)dev_instance;
    struct netdev_private *np = (struct netdev_private *)dev->priv;
    volatile struct netdev_desc *desc;
    unsigned int entry, count;
    u32 stat;

    count = 0;
    entry = np->dirty_tx % TX_RING_SIZE;
    desc = np->tx_ring + entry;

    while ((u32)desc != CSR_READ(BDMATXPTR)) {
        stat = (desc->stat_len >> 16) & 0xffff;
        if(stat & Comp) {
            np->stats.tx_packets++;
        } else {
            np->stats.tx_errors++;
            if(stat & TxPar)
                np->stats.tx_aborted_errors++;
            if(stat & NCarr)
                np->stats.tx_carrier_errors++;
            if(stat & Under)
                np->stats.tx_fifo_errors++;
            if(stat & LateColl)
                np->stats.tx_window_errors++;
            if(stat & ExColl)
                np->stats.collisions++;
        }
        dev_kfree_skb_irq(np->tx_skbuff[entry]);
        np->tx_skbuff[entry] = NULL;
        
        count++;
        entry = (entry + 1) % TX_RING_SIZE;
        desc = np->tx_ring + entry;
    }
    np->dirty_tx += count;

    if (netif_queue_stopped(dev))
        netif_wake_queue(dev);

    /* Fix me: enable BDMA rx (if it dies). */
    CSR_WRITE(BDMASTAT, S_BRxRDF);
    CSR_WRITE(BDMARXCON, gBDMARXCON);
}

static void refill_rx(unsigned long data)
{
    struct net_device *dev = (struct net_device *)data;
    struct netdev_private *np = (struct netdev_private *)dev->priv;
    struct sk_buff *skb;
    unsigned int entry;
    int i, count;
    
    /* Sub one to avoid RXPTR run ahead of cur_rx one loop. */
    count = np->cur_rx - np->dirty_rx - 1;
    entry = np->dirty_rx % RX_RING_SIZE;
    for (i = 0; i < count; i++, entry = (entry + 1) % RX_RING_SIZE) {
        if (np->rx_skbuff[entry]) {
            np->rx_ring[entry].data_ptr |= BDMA_OWNER;
            continue;
        }

        skb = dev_alloc_skb(PKT_BUF_SZ);
        if (skb == NULL)
            break;            /* Better luck next round. */
        
        np->rx_skbuff[entry] = skb;
        np->rx_ring[entry].data_ptr = (u32)skb->data | BDMA_OWNER;
        skb->dev = dev;
        skb_reserve(skb, 2);
    }
    np->dirty_rx += i;

    wbflush();
    CSR_WRITE(BDMASTAT, S_BRxRDF);
    CSR_WRITE(BDMARXCON, gBDMARXCON);
}

static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
    struct netdev_private *np = (struct netdev_private *)dev->priv;
    volatile struct netdev_desc *desc;
    unsigned int entry, align;

    entry = np->cur_tx % TX_RING_SIZE;
    desc = np->tx_ring + entry;

    align = (u32)skb->data % sizeof(u32);

    np->tx_skbuff[entry] = skb;
    desc->misc_ctl = (Padding | CRCMode | FrameDataPtrInc | LittleEndian | MACTxIntEn | (align << 5));
    desc->stat_len = (skb->len & 0xffff);
    desc->data_ptr = ((u32)(skb->data) - align) | BDMA_OWNER;
    
    wbflush();
    CSR_WRITE(BDMATXCON, gBDMATXCON);
    CSR_WRITE(MACTXCON, gMACTXCON);

    np->cur_tx++;
    /* Sub one to avoid TXPTR run ahead of dirty_tx one loop. */
    if (np->cur_tx - np->dirty_tx >= TX_RING_SIZE - 1)
        netif_stop_queue(dev);

    dev->trans_start = jiffies;

    return 0;
}

static int netdev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
   //struct netdev_private *np = (struct netdev_private *)dev->priv;
    struct mii_data *data = (struct mii_data *)&ifr->ifr_data;
    u16 value = MiiStationRead(REGN0, REGADD);

    switch(cmd)
    {
        case SIOCGMIIREG:        //Read the specified of the MII register

            data->phy_reg0 = MiiStationRead(REGN0, REGADD);    // 0X20

            data->phy_reg1 = MiiStationRead(REGN1, REGADD);
            data->phy_id1 = MiiStationRead(REGN2, REGADD);
            data->phy_id2 = MiiStationRead(REGN3, REGADD);
            return 0;
        case SIOCSMIIREG:
            if((value & 0xffff) != (data->phy_reg0 & 0xffff))
            {
                value = (data->phy_reg0 & 0xffff);
                
                MiiStationWrite(REGN0, REGADD, value);
                printk(KERN_INFO, "after phy config\n");
            }
            printk(KERN_INFO, "before phy config\n");
            return 0;
        default:
            return -EOPNOTSUPP;
    }
}

static int netdev_open(struct net_device *dev)
{
    int i;
    
    MOD_INC_USE_COUNT;

    /* Disable interrupt. */
    disable_irq(INT_BDMATX);
    disable_irq(INT_BDMARX);
    disable_irq(INT_MACTX);
    disable_irq(INT_MACRX);

    /* Request IRQ. */
    if (request_irq(INT_BDMARX, &rx_intr_handler, SA_INTERRUPT, dev->name, dev)) {
        printk(KERN_ERR "%s: Request irq %d failed.\n", dev->name, INT_BDMARX);
        return -EAGAIN;
    }
    if (request_irq(INT_MACTX, &tx_intr_handler, SA_INTERRUPT, dev->name, dev)) {
        printk(KERN_ERR "%s: Request irq %d failed.\n", dev->name, INT_MACTX);
        return -EAGAIN;
    }

    /* Reset BDMA and MAC. */
    CSR_WRITE(BDMARXCON, BRxRS);
    CSR_WRITE(BDMATXCON, BTxRS);
    CSR_WRITE(MACON, Reset);
    CSR_WRITE(BDMARXLSZ, PKT_BUF_SZ);
    CSR_WRITE(MACON, gMACCON);

    /* Configure CAM. */
    for(i = 0; i < (int)dev->addr_len-2; i++)
        CAM_Reg(0) = (CAM_Reg(0) << 8) | dev->dev_addr[i];
    for(i = (int)dev->addr_len-2; i < (int)dev->addr_len; i++)
        CAM_Reg(1) = (CAM_Reg(1) << 8) | dev->dev_addr[i];
    CAM_Reg(1) = (CAM_Reg(1) << 16);
    CSR_WRITE(CAMEN, 0x0001);
    CSR_WRITE(CAMCON, gCAMCON);

    /* Init Rx/Tx descriptors. */
    init_ring(dev);

    /* Enable interrupt. */
    enable_irq(INT_BDMARX);
    enable_irq(INT_MACTX);

    /* Enable BDMA and MAC. */
    wbflush();
    CSR_WRITE(BDMATXCON, gBDMATXCON);
    CSR_WRITE(MACTXCON, gMACTXCON);
    CSR_WRITE(BDMARXCON, gBDMARXCON);
    CSR_WRITE(MACRXCON, gMACRXCON);
    
    /* Start the transmit queue. */
    netif_start_queue(dev);
    return 0;
}

static int netdev_close(struct net_device *dev)
{
    struct netdev_private *np = dev->priv;
    struct sk_buff *skb;
    int i;

    /* Stop the transmit queue. */
    netif_stop_queue(dev);
    
    /* Stop BDMA and MAC. */
    CSR_WRITE(BDMATXCON, 0);
    CSR_WRITE(BDMARXCON, 0);
    CSR_WRITE(MACTXCON, 0);
    CSR_WRITE(MACRXCON, 0);

    /* Free irqs. */
    free_irq(INT_BDMARX, dev);
    free_irq(INT_MACTX, dev);

    /* Wait and kill tasklet. */
    tasklet_kill(&np->rx_tasklet);

    /* Free all skbuffs */
    for (i = 0; i < RX_RING_SIZE; i++) {
        skb = np->rx_skbuff[i];
        if (skb)
            dev_kfree_skb(skb);
    }
    for (i = 0; i < TX_RING_SIZE; i++) {
        skb = np->tx_skbuff[i];
        if (skb)
            dev_kfree_skb(skb);
    }

    MOD_DEC_USE_COUNT;
    return 0;
}

static struct net_device_stats *get_stats(struct net_device *dev)
{
    struct netdev_private *np = (struct netdev_private *)dev->priv;
    return &np->stats;
}

static int s3c4510_probe(struct net_device *dev)
{
    char address[12];
    char *p;
    int i;
    struct netdev_private *np;
    SET_MODULE_OWNER(dev);
    
    /* Assign some of the fields. */
    ether_setup(dev);

    /* Set net_device methods. */
    dev->open = netdev_open;
    dev->stop = netdev_close;
    dev->get_stats = get_stats;
    dev->hard_start_xmit = start_tx;
    //add ioctl function

    dev->do_ioctl = netdev_do_ioctl;

    /* Set net_device data members. */
    dev->watchdog_timeo = TX_TIMEOUT;    //100

    dev->irq = INT_BDMARX;        //17

    dev->dma = 0;

    /* Set MAC address. */
    p = (volatile char *)(0x05000000 + 0x170000);
    for(i = 0; i < 12; i++){
        address[i] = *(p + i);
    }
        
    dev->dev_addr[0] = 0x00;
    dev->dev_addr[1] = address[10];
    dev->dev_addr[2] = address[9];
    dev->dev_addr[3] = address[8];
    dev->dev_addr[4] = address[1];
    dev->dev_addr[5] = address[0];

    /* Set private data structure. */
    dev->priv = kmalloc(sizeof(*np), GFP_KERNEL);
    if(dev->priv == NULL)
        return -ENOMEM;
    np = dev->priv;
    memset(np, 0, sizeof(*np));
    spin_lock_init(&np->lock);
    tasklet_init(&np->rx_tasklet, refill_rx, (unsigned long)dev);

    /* Print banner. */
    printk(KERN_INFO "%s", version);

    return 0;
}

static struct net_device s3c4510_device = {
    init: s3c4510_probe,
};

static int __init s3c4510_init(void)
{
    return register_netdev(&s3c4510_device);
}

static void __exit s3c4510_exit(void)
{
    if (s3c4510_device.priv)
        kfree(s3c4510_device.priv);
    unregister_netdev(&s3c4510_device);

    return;
}

module_init(s3c4510_init);
module_exit(s3c4510_exit);

MODULE_DESCRIPTION("Samsung 4510B ethernet driver");
MODULE_AUTHOR("Mac Wang ");
MODULE_LICENSE("GPL");

/* s3c4510b.h */

#ifndef __S3C4510_H
#define __S3C4510_H

/* ----------------------------------------- *
 * Definitions of Samsung 4510 MAC registers *
 * ----------------------------------------- */


#define MaxRxFrameSize    (1520)

/* -------------------------------------- *
 * Buffered DMA Transmit Control Register *
 * -------------------------------------- */

#define BTxBRST        (0x0000F) /* [4:0] */
#define BTxSTSKO    (0x00020)
#define BTxCCPIE    (0x00080)
#define BTxNLIE        (0x00100)
#define BTxNOIE        (0x00200)
#define BTxEmpty    (0x00400)
//#define BTxMSL        /* [13:11] */

#define BTxMSL000    (0x00000)
#define BTxMSL001    (0x00800)
#define BTxMSL010    (0x01000)
#define BTxMSL011    (0x01800)
#define BTxMSL100    (0x02000)
#define BTxMSL101    (0x02800)
#define BTxMSL110    (0x03000)
#define BTxMSL111    (0x03800)
#define BTxEn        (0x04000)
#define BTxRS        (0x08000)

/* ------------------------------------- *
 * Buffered DMA Receive Control Register *
 * ------------------------------------- */

#define BRxBRST        (0x0000F) /* [4:0] */
#define BRxSTSKO    (0x00020)
#define BRxMAINC    (0x00040)
#define BRxDIE        (0x00080)
#define BRxNLIE        (0x00100)
#define BRxNOIE        (0x00200)
#define BRxMSOIE    (0x00400)
#define BRxLittle    (0x00800)
//#define BRxWA        /* [13:12] */

#define BRxWA01        (0x01000)
#define BRxWA10        (0x02000)
#define BRxWA11        (0x03000)
#define BRxEn        (0x04000)
#define BRxRS        (0x08000)
#define BRxEmpty    (0x10000)
#define BRxEarly    (0x20000)

/* -------------------- *
 * BDMA Status Register *
 * -------------------- */

#define S_BRxRDF    (0x00001)
#define S_BRxNL        (0x00002)
#define S_BRxNO        (0x00004)
#define S_BRxMSO    (0x00008)
#define S_BRxEmpty    (0x00010)
#define S_BRxSEarly    (0x00020)
#define S_BRxFRF    (0x00080)
#define S_BRxNFR    (0x00080)
#define S_BTxCCP    (0x10000)
#define S_BTxNL        (0x20000)
#define S_BTxNO        (0x40000)
#define S_BTxEmpty    (0x100000)

/* -------------------- *
 * MAC Control Register *
 * -------------------- */

#define HaltReq        (0x00001)
#define HaltImm        (0x00002)
#define Reset        (0x00004)
#define FullDup        (0x00008)
#define MACLoop        (0x00010)
#define MIIOFF        (0x00040)
#define Loop10        (0x00080)
#define MissRoll    (0x00400)
#define MDCOFF        (0x01000)
#define EnMissRoll    (0x02000)
#define Link10        (0x08000)

/* ----------------------------- *
 * MAC Transmit Control Register *
 * ----------------------------- */

#define TxEn        (0x0001)
#define TxHalt        (0x0002)
#define NoPad        (0x0004)
#define NoCRC        (0x0008)
#define FBack        (0x0010)
#define NoDef        (0x0020)
#define SdPause        (0x0040)
#define SQEn        (0x0080)
#define EnUnder        (0x0100)
#define EnDefer        (0x0200)
#define EnNCarr        (0x0400)
#define EnExColl    (0x0800)
#define EnLateColl    (0x1000)
#define EnTxPar        (0x2000)
#define EnComp        (0x4000)

/* ---------------------------- *
 * MAC Receive Control Register *
 * ---------------------------- */

#define RxEn        (0x0001)
#define RxHalt        (0x0002)
#define LongEn        (0x0004)
#define ShortEn        (0x0008)
#define StripCRC    (0x0010)
#define PassCtl        (0x0020)
#define IgnoreCRC    (0x0040)
//#define         (0x0080)

#define EnAlign        (0x0100)
#define EnCRCErr    (0x0200)
#define EnOver        (0x0400)
#define EnLongErr    (0x0800)
//#define         (0x1000)

#define EnRxPar        (0x2000)
#define EnGood        (0x4000)

/* -------------------- *
 * CAM Control Register *
 * -------------------- */

#define StationAcc    (0x0001)
#define GroupAcc    (0x0002)
#define BroadAcc    (0x0004)
#define NegCAM        (0x0008)
#define CompEn        (0x0010)

/* Tx & Rx Frame Descriptor Ownership bit[31](O) */
#define BDMA_OWNER    0x80000000 /* BDMA */
#define CPU_OWNER    0x00000000 /* CPU */

/* ------------------------------- *
 * Tx Frame Descriptor Description *
 * ------------------------------- */

#define Padding        (0x00)
#define NoPadding    (0x01)
#define CRCMode        (0x00)
#define NoCRCMode    (0x02)
#define MACTxIntEn    (0x04)
#define MACTxIntDis    (0x00)
#define LittleEndian    (0x08)
#define BigEndian    (0x00)
#define FrameDataPtrInc    (0x10)
#define FrameDataPtrDec    (0x00)
#define WA00        (0x00)
#define WA01        (0x20)
#define WA10        (0x40)
#define WA11        (0x60)

/* --------- *
 * Tx Status *
 * --------- */

#define TxCollCntMask    (0x000F)
#define ExColl        (0x0010)
#define TxDefer        (0x0020)
#define Paused        (0x0040)
#define IntTx        (0x0080)
#define Under        (0x0100)
#define Defer        (0x0200)
#define NCarr        (0x0400)
#define SQErr        (0x0800)
#define LateColl    (0x1000)
#define TxPar        (0x2000)
#define Comp        (0x4000)
#define TxHalted    (0x8000)

/* --------- *
 * Rx Status *
 * --------- */

#define OvMax        (0x0004)
#define CtlRcv        (0x0020)
#define IntRx        (0x0040)
#define Rx10stat    (0x0080)
#define AlignErr    (0x0100)
#define CRCErr        (0x0200)
#define Overflow    (0x0400)
#define LongErr        (0x0800)
#define RxPar        (0x2000)
#define Good        (0x4000)
#define RxHalted    (0x8000)

/* ------------- *
 * MII Registers *
 * ------------- */

#define MiiBusy        (1<<11)
#define PHYREGWRITE    (1<<10)

#define REGN0 0
#define REGN1 1
#define REGN2 2
#define REGN3 3
#define REGN4 4
#define REGN5 5
#define REGN6 6
#define REGN16 16
#define REGN17 17
#define REGN18 18
#define REGN19 19
#define REGN20 20
#define REGN21 21
#define REGN22 22
#define REGN23 23
#define REGN24 24
#define REGN25 25

#define REGADD 0x20

#endif /* __S3C4510_H */

阅读(1466) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-09-01 17:57:21

希望大家帮我测下,看还会出现,bdma is hang 吗?