⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dp83815.c

📁 linux下的DP83815网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:

/* Macros */

/*
 * SWAP_BUS_TO_CPU_XX and SWAP_CPU_TO_BUS_XX macros swap 16 and 32 bit values
 * between the PCI bus' little endian byte-order and the CPU's native
 * byte-order.
 */

#ifdef __BIG_ENDIAN
#define BUS_TO_CPU_SWAP_16(X)    swap_16(X)
#define BUS_TO_CPU_SWAP_32(X)    swap_32(X)
#define CPU_TO_BUS_SWAP_16(X)    swap_16(X)
#define CPU_TO_BUS_SWAP_32(X)    swap_32(X)
#define CPU_TO_NET_SWAP_16(X)    ((u16)(X))
#define CPU_TO_NET_SWAP_32(X)    ((u32)(X))
#define NET_TO_CPU_SWAP_16(X)    ((u16)(X))
#define NET_TO_CPU_SWAP_32(X)    ((u32)(X))
#else
#define BUS_TO_CPU_SWAP_32(X)    ((u32)(X))
#define BUS_TO_CPU_SWAP_16(X)    ((u16)(X))
#define CPU_TO_BUS_SWAP_32(X)    ((u32)(X))
#define CPU_TO_BUS_SWAP_16(X)    ((u16)(X))
#define CPU_TO_NET_SWAP_16(X)    swap_16(X)
#define CPU_TO_NET_SWAP_32(X)    swap_32(X)
#define NET_TO_CPU_SWAP_16(X)    swap_16(X)
#define NET_TO_CPU_SWAP_32(X)    swap_32(X)
#endif

/* Macros translate addresses between PCI bus and CPU */
#define BUS_TO_CPU_ADDR_XLATE(X)  BUS_TO_CPU_SWAP_32(bus_to_virt(X))
#define CPU_TO_BUS_ADDR_XLATE(X)  CPU_TO_BUS_SWAP_32(virt_to_bus(X))

/* Macros to read/write 32/16 bit data to/from DP83815 device registers. */
#define DP_REG32_WRITE(reg, val)  io_write_32 (iobase+(reg),            \
                                               CPU_TO_BUS_SWAP_32(val))
#define DP_REG32_READ(reg)        BUS_TO_CPU_SWAP_32(io_read_32 (iobase+(reg)))
#define DP_REG16_WRITE(reg, val)  io_write_16 (iobase+(reg),            \
                                               CPU_TO_BUS_SWAP_16(val))
#define DP_REG16_READ(reg)        BUS_TO_CPU_SWAP_16(io_read_16 (iobase+(reg)))
#define DP_REG32_SET(reg, val)    DP_REG32_WRITE(reg,DP_REG32_READ(reg)|(val))
#define DP_REG32_CLR(reg, val)    DP_REG32_WRITE(reg,DP_REG32_READ(reg)&~(val))
#define DP_REG16_SET(reg, val)    DP_REG16_WRITE(reg,DP_REG16_READ(reg)|(val))
#define DP_REG16_CLR(reg, val)    DP_REG16_WRITE(reg,DP_REG16_READ(reg)&~(val))

/* Debug Macros */
#define DP_DEBUG_PROBE            0x00000001
#define DP_DEBUG_OPEN             0x00000002
#define DP_DEBUG_CLOSE            0x00000004
#define DP_DEBUG_IOCTL            0x00000008
#define DP_DEBUG_TX               0x00000010
#define DP_DEBUG_RX               0x00000020
#define DP_DEBUG_MC               0x00000040
#define DP_DEBUG_ANEG             0x00000080
#define DP_DEBUG_INTR             0x00000100
#define DP_DEBUG_LOAD             0x00000200
#define DP_DEBUG_UNLOAD           0x00000400

#define DEBUG

#ifdef DEBUG
u32     dp_debug_level=0;
#define DP_DEBUG(level, X)  if (level & dp_debug_level) printk X
#else
#define DP_DEBUG(level, X)
#endif

/* data types */
typedef u32    status;                /* return status */
typedef volatile u8 * virt_addr;      /* CPU virtual address */
typedef volatile u8 * bus_addr;       /* BUS physical address */
typedef u8     bool;

#define OK        0                   /* status: OK */
#define ERROR    -1                   /* status: ERROR */
#define TRUE      1
#define FALSE     0

#ifdef LINK_AGGR
#define DP_RX_DISABLE               0 /* disable rx engine */
#define DP_RX_ENABLE                1 /* enable rx engine */
#endif

/* Default Driver Parameters */
#define DP_DEFAULT_TXQ_SIZE         32
#define DP_DEFAULT_RXQ_SIZE         30
#define DP_RX_COPY_THRESHOLD        128 /* upper limit for rx packet copy */
#define DP_POLYNOMIAL               0x04C11DB6

/* Alignment and packet sizes */
#define ETH_CRC_LEN                 4
#define ETH_MAX_PKT_SIZE            (ETH_FRAME_LEN + ETH_CRC_LEN)
#define DP_ALIGN                    4     /* word alignment */

/* Driver private descriptor macros */
#define DP_DESC_SKBPTR              0x0c  /* SKB pointer offset */
#define DP_QUEUE_ELE_SIZE           (DP_DESC_SIZE + 4)
#define DP_QUEUE_ELE_NEXT(q)                                            \
        q->cur_desc_addr = DP_QUEUE_ELE_NEXT_GET(q, q->cur_desc_addr)
#define DP_QUEUE_ELE_NEXT_GET(q, desc_addr)                                    \
        ((desc_addr) == (q)->last_desc_addr) ? (q)->first_desc_addr :        \
                                           (desc_addr) + DP_QUEUE_ELE_SIZE

/* Macros to get/set the values of the descriptor fields */
#define DP_DESC_LNK_GET(ptr)     *(u32 *)((virt_addr)ptr + DP_DESC_LNK)
#define DP_DESC_CMDSTS_GET(ptr)  *(u32 *)((virt_addr)ptr + DP_DESC_CMDSTS)
#define DP_DESC_BUFPTR_GET(ptr)  *(u32 *)((virt_addr)ptr + DP_DESC_BUFPTR)
#define DP_DESC_SKBPTR_GET(ptr)  *(u32 *)((virt_addr)ptr + DP_DESC_SKBPTR)

#define DP_DESC_LNK_SET(ptr, val)      DP_DESC_LNK_GET(ptr) = (val)
#define DP_DESC_CMDSTS_SET(ptr, val)   DP_DESC_CMDSTS_GET(ptr) = (val)
#define DP_DESC_BUFPTR_SET(ptr,val)    DP_DESC_BUFPTR_GET(ptr) = (val)
#define DP_DESC_SKBPTR_SET(ptr,val)    DP_DESC_SKBPTR_GET(ptr) = (val)

/*
 * Macros to get/set the values of descriptor fields with
 * appropriate address and byte order translations
 */
#define DP_DESC_LNK_XLATE_GET(p)    BUS_TO_CPU_ADDR_XLATE(DP_DESC_LNK_GET(p))
#define DP_DESC_CMDSTS_XLATE_GET(p)    BUS_TO_CPU_SWAP_32(DP_DESC_CMDSTS_GET(p))
#define DP_DESC_BUFPTR_XLATE_GET(p) BUS_TO_CPU_ADDR_XLATE(DP_DESC_BUFPTR_GET(p))

#define DP_DESC_LNK_XLATE_SET(p, v)                                    \
        DP_DESC_LNK_SET(p, CPU_TO_BUS_ADDR_XLATE(v))
#define DP_DESC_CMDSTS_XLATE_SET(p, v)                                 \
        DP_DESC_CMDSTS_SET(p, CPU_TO_BUS_SWAP_32(v))
#define DP_DESC_BUFPTR_XLATE_SET(p,v)                                  \
        DP_DESC_BUFPTR_SET(p, CPU_TO_BUS_ADDR_XLATE(v))

/* FIFO Drain and Fill Threshold */
#define DP_TXCFG_FLTH_VAL	0x10
#define DP_TXCFG_DRTH_VAL	0x30
#define DP_RXCFG_DRTH_VAL	0x08

/* Descriptor queue */
struct dp83815_queue {
    virt_addr  first_desc_addr;  /* descriptor array address */
    virt_addr  last_desc_addr;   /* last descriptor address */
    virt_addr  cur_desc_addr;    /* current descriptor address */
    virt_addr  read_desc_addr;   /* current reclaim desc address */
    virt_addr  qbuf;             /* allocated queue buffer */
    u16        count;            /* number of elements */
};

/* Queue types -- qtype */
#define DP_QUEUE_TYPE_TX    1    /* Transmit queue */
#define DP_QUEUE_TYPE_RX    2    /* Receive queue */

/* Device private data */
struct dp83815_priv {
    struct net_device *        next;        /* Next dp83815device */
    struct dp83815_queue       tx_queue;    /* Transmit Descriptor Queue */
    struct dp83815_queue       rx_queue;    /* Receive Descriptor Queue */
    struct net_device_stats    stats;       /* MIB data */
    unsigned int               fullduplex;  /* half or full duplex */
    unsigned int               speed100;    /* 10/100 MBps */
    unsigned int               tx_desc;     /* number of transmit descriptor */
    unsigned int               rx_desc;     /* number of receive descriptor */
    unsigned int               autoneg;
    unsigned int 		PrevLinkSts;
#ifdef  LINK_AGGR
    struct NsmInfo             NsmCtxt;
#endif
};

static struct net_device *    dp83815_dev_list;        /* List of dp83815devices */

/* Linux Network Driver interface routines */
extern int dp83815_probe (struct net_device *dev);
static int dp83815_open (struct net_device *dev);
static int dp83815_close (struct net_device *dev);
static int dp83815_start_xmit (struct sk_buff *skb, struct net_device *dev);
static int dp83815_start_receive (struct net_device *dev);
static void dp83815_set_multicast_list (struct net_device *dev);
static int dp83815_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static void dp83815_interrupt (int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *dp83815_get_stats (struct net_device *dev);

/* Support Functions */
/*static u16 swap_16 (u16 us);*/
/*static u32 swap_32 (u32 ui);*/
static u32 io_read_32 (u16 io_port);
static void io_write_32 (u16 io_port, u32 data);
static u16 io_read_16 (u16 io_port);
static void io_write_16 (u16 io_port, u16 data);

/* Driver Private Routines */
#ifdef LINK_AGGR
static void dp83815_mac_address_set (AdapterContext *pAdp, char *mac_addr);
static status dp83815_dev_reset (AdapterContext *pAdp);
static UCHAR  dp83815_send_packet (AdapterContext *pAdp, PktInfo *pPkt, int priority);
#else
static void dp83815_mac_address_set (u32 iobase, char *mac_addr);
static status dp83815_dev_reset (u32 iobase);
static int dp83815_send_packet (struct sk_buff *skb, struct net_device *dev);
#endif
static void dp83815_mac_address_get (u32 iobase, char *mac_addr);
static status dp83815_queue_create (struct dp83815_queue *q, int count, int qtype);
static status dp83815_queue_delete (struct dp83815_queue *q);
static virt_addr dp83815_tx_desc_get (struct net_device *dev);
static virt_addr dp83815_rx_desc_get (struct net_device *dev);
static status dp83815_phy_setup (struct net_device *dev);
static int dp83815_crc (char * mc_addr);
static void dp83815_tx_skb_reclaim_irq (struct net_device *dev, virt_addr desc_addr);
static void dp83815_eeprom_delay (u32 iobase);
static u16  dp83815_eeprom_read (u32 iobase, int addr);

/* Short Cable Fixed function */
void	dp83815_PhyAdjust(struct net_device *);
void	dp83815_PhyCoefAdjust(struct net_device *);
void	dp83815_ResetPhy(struct net_device *);

/* LACP specific routines */
#ifdef LINK_AGGR
static void dp83815_rx_control (AdapterContext *pAdp, int flag);
static void dp83815_clear_mca_tbl (AdapterContext *pAdapter);
static unsigned char dp83815_multicast_delete (AdapterContext* pAdp, MultiList *pMulti);
static unsigned char dp83815_multicast_add (AdapterContext *pAdp, MultiList *pMulti, UCHAR  ReloadFlag);
static void dp83815_IndicateLinkStatus (AdapterContext *pAdapter);
static unsigned char dp83815_setphy (AdapterContext *pAdapter, UINT PhysFlags, UINT SetSpeed);
static unsigned char dp83815_rxfilter (AdapterContext *pAdapter, UINT rxFilterFlag);
#endif

/* Driver Debug Routines */
#ifdef DEBUG
#if 0 /* not used */
static void dp83815_regs_info (u16 iobase);
#endif /* not used */
#endif

/* default driver parameters */
#define MAX_DEV   10   /* number of devices could be more */
unsigned int fullduplex[MAX_DEV]  = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
unsigned int speed100[MAX_DEV]    = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
unsigned int txdesc[MAX_DEV]      = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
unsigned int rxdesc[MAX_DEV]      = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
unsigned int autoneg[MAX_DEV]     = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
unsigned int debug                = 0;
unsigned int atan		  = 1;	// NSC20030123 for Atan Fix

/* Module description and parameters */

#ifdef MODULE
MODULE_DESCRIPTION("National Semiconductor DP83815 10/100 Ethernet Driver");
MODULE_PARM(fullduplex, "1-" __MODULE_STRING(MAX_DEV) "i");
MODULE_PARM(speed100,   "1-" __MODULE_STRING(MAX_DEV) "i");
MODULE_PARM(autoneg,    "1-" __MODULE_STRING(MAX_DEV) "i");
MODULE_PARM(txdesc,     "1-" __MODULE_STRING(MAX_DEV) "i");
MODULE_PARM(rxdesc,     "1-" __MODULE_STRING(MAX_DEV) "i");
MODULE_PARM(debug, "i");
MODULE_PARM(atan,"i");			// NSC20030123 for Atan Fix
#endif

/*
 * dp83815_probe - enumerate the PCI bus for instances of DP83815
 *
 * This routine enumerates DP83815 ethernet devices on the PCI bus, and
 * registers each DP83815 device found.
 */
int
dp83815_probe (struct net_device *dev)
{
    int  dev_count;
    u8   bus;
    u8   func;
    u8   irq;
    u32  iobase;
    u32  version;
    struct dp83815_priv *dev_priv;
#ifdef LINK_AGGR
    NsmContext *pNsm = NULL;
    AdapterContext *pAdp = NULL;
#endif

    if (! pcibios_present())
        return -ENODEV;        /* No such device */

    dev_count=0;
    while (pcibios_find_device (PCI_VENDOR_ID_NS, PCI_VENDOR_ID_NS_83815,
                                dev_count, &bus, &func)
           == PCIBIOS_SUCCESSFUL) {

        /* Allocate, name the device and add to ethernet device list */
        dev = init_etherdev(dev, sizeof (struct dp83815_priv));

        if (dev == NULL) {
            printk (KERN_INFO "%s: Failed to create device struct\n",
                    DP_DRV_NAME);
            break;
        }

#ifdef LINK_AGGR
        pNsm = &((struct dp83815_priv *)(dev->priv))->NsmCtxt;
        pNsm->dev = dev;
        pAdp = &pNsm->AdpCtxt;
        pAdp->pNsmContext = (void *)pNsm;
        pAdp->MacStats.txOkCount = 0;
#endif
        
        /* Read PCI Configuration Registers */
        pcibios_read_config_byte (bus, func, PCI_INTERRUPT_LINE, &irq);
        pcibios_read_config_dword (bus, func, PCI_BASE_ADDRESS_0, &iobase);
        iobase &= PCI_BASE_ADDRESS_IO_MASK;

#ifdef LINK_AGGR
        pAdp->RegAddr = (UCHAR *)iobase;
#endif        

        /* set the parameters for the driver */
        dev_priv = (struct dp83815_priv *)dev->priv;
        if (dev_count < MAX_DEV) {
        
            if (autoneg[dev_count] != 0) {

	        dev_priv->autoneg = 1;
                
                /* set the speed and duplex mode*/
		if (speed100[dev_count] == 1) {

		    dev_priv->speed100 = 1;
                    dev_priv->fullduplex = 2;
		}
		else if (speed100[dev_count] == 0) {

		    dev_priv->speed100 = 0; 
                    dev_priv->fullduplex = 2;
		}
		else {

		    dev_priv->speed100 = 2;
                    if (fullduplex[dev_count] == 0)
                        dev_priv->fullduplex = 0;
                    else
                        dev_priv->fullduplex = 2;                                                 
		}
            } else {
	        dev_priv->autoneg = 0;
                
                /* set the speed */
                if (speed100[dev_count] == 0)
		    dev_priv->speed100 = 0;
                else
                    dev_priv->speed100 = 1;
            
                /* set the duplex mode */
                if (fullduplex[dev_count] == 1)
		    dev_priv->fullduplex = 1;
                else
		    dev_priv->fullduplex = 0;
	    }

            dev_priv->tx_desc = ((txdesc[dev_count] == -1) ?
                                 DP_DEFAULT_TXQ_SIZE : txdesc[dev_count]);  
            dev_priv->rx_desc = ((rxdesc[dev_count] == -1) ?
                                 DP_DEFAULT_RXQ_SIZE : rxdesc[dev_count]);
	}
        else {

	    dev_priv->autoneg = 1;
	    dev_priv->fullduplex = 2;
	    dev_priv->speed100 = 2;
            dev_priv->tx_desc = DP_DEFAULT_TXQ_SIZE;
            dev_priv->rx_desc = DP_DEFAULT_RXQ_SIZE;
	}
        
#ifdef DEBUG
	dp_debug_level = debug;         
#endif        

        /* Put the device in a quiescent state */
#ifdef LINK_AGGR
        if (dp83815_dev_reset (pAdp) != OK)
#else            
        if (dp83815_dev_reset (iobase) != OK)
#endif            
        {

            printk (KERN_INFO "%s: Device Reset failed.\n",
                    DP_DRV_NAME);
            kfree (dev); 
            continue;             /* Try the next device */
        }

        /* Get the ethernet address */
        dp83815_mac_address_get (iobase, dev->dev_addr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -