Linux网卡设备驱动,Linux 网卡设备驱动1

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#if defined(CONFIG_SH_DREAMCAST)

#define RX_BUF_IDX 1 #else

#define RX_BUF_IDX 2 #endif

#define RX_BUF_LEN (8192

<< RX_BUF_IDX)

#define RX_BUF_PAD 16

#define RX_BUF_WRAP_PAD 2048

#if RX_BUF_LEN == 65536

#define RX_BUF_TOT_LEN RX_BUF_LEN

#else

#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD +

RX_BUF_WRAP_PAD)

#endif

typedef enum

{

RTL8139 =

0,

RTL8129,

} board_t;

static struct pci_device_id xc_id[] =

{

{0x10ec,

0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x10ec,

0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1113,

0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1500,

0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x4033,

0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1186,

0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1186,

0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x13d1,

0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1259,

0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1259,

0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x14ea,

0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x14ea,

0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x11db,

0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1432,

0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x02ac,

0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x018a,

0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x126c,

0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x1743,

0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

{0x021b,

0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

#ifdef

CONFIG_SH_SECUREEDGE5410 {0x10ec,

0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },

#endif

#ifdef CONFIG_8139TOO_8129

{0x10ec,

0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 },

#endif

{PCI_ANY_ID,

0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 },

{PCI_ANY_ID,

0x8139, 0x1186, 0x1300, 0, 0, RTL8139 },

{PCI_ANY_ID,

0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 },

{0,}

};

MODULE_DEVICE_TABLE (pci,xc_id);

enum RTL8139_registers

{

MAC0 =

0, MAR0 =

8, TxStatus0 =

0x10, TxAddr0 =

0x20, RxBuf =

0x30, ChipCmd =

0x37,

RxBufPtr =

0x38,

IntrMask =

0x3C,

IntrStatus =

0x3E,

TxConfig =

0x40,

RxConfig =

0x44,

RxMissed =

0x4C,

Cfg9346 =

0x50,

Config1 =

0x52,

Config3 =

0x59,

Config4 =

0x5A,

HltClk =

0x5B,

MultiIntr =

0x5C, BasicModeCtrl = 0x62,

BasicModeStatus = 0x64,

NWayAdvert =

0x66,

NWayLPAR =

0x68,

NWayExpansion = 0x6A, CSCR =

0x74,

};

enum ChipCmdBits {

CmdReset =

0x10,

CmdRxEnb =

0x08,

CmdTxEnb =

0x04,

RxBufEmpty =

0x01,

};

enum IntrStatusBits

{

PCIErr =

0x8000,

PCSTimeout =

0x4000,

RxFIFOOver =

0x40,

RxUnderrun =

0x20,

RxOverflow =

0x10,

TxErr =

0x08,

TxOK =

0x04,

RxErr =

0x02,

RxOK =

0x01,

RxAckBits =

RxFIFOOver | RxOverflow | RxOK,

};

static const u16 xc_intr_mask =

PCIErr |

PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |

TxErr | TxOK

| RxErr | RxOK;

static const u16 xc_norx_intr_mask =

PCIErr |

PCSTimeout | RxUnderrun | TxErr | TxOK | RxErr ;

enum Config1Bits {

Cfg1_PM_Enable = 0x01,

LWAKE =

0x10,

};

enum Config3Bits {

Cfg3_Magic = (1 << 5),

};

enum Config4Bits {

LWPTN = (1

<< 2),

};

enum Cfg9346Bits

{

Cfg9346_lock

= 0x00,

Cfg9346_Unlock = 0xC0,

};

enum TxStatusBits {

TxHostOwns =

0x2000,

TxUnderrun =

0x4000,

TxStatOK =

0x8000,

TxOutOfWindow = 0x20000000,

TxAborted =

0x40000000,

TxCarrierLost = 0x80000000,

};

enum rx_mode_bits

{

AcceptErr =

0x20,

AcceptRunt =

0x10,

AcceptBroadcast = 0x08,

AcceptMulticast = 0x04,

AcceptMyPhys

= 0x02,

AcceptAllPhys = 0x01,

};

typedef enum

{

CH_8139 =

0,

CH_8139_K,

CH_8139A,

CH_8139A_G,

CH_8139B,

CH_8130,

CH_8139C,

CH_8100,

CH_8100B_8139D,

CH_8101,

} chip_t;

enum chip_flags

{

HasHltClk =

(1 << 0),

HasLWake =

(1 << 1),

};

#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) /

(b30<<30 |

b29<<29 |

b28<<28 |

b27<<27 |

b26<<26 |

b23<<23 |

b22<<22)

#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1)

static const struct

{

const char

*name;

u32

version;

u32

flags;

} rtl_chip_info[] =

{

{

"RTL-8139",HW_REVID(1, 0, 0, 0, 0, 0, 0),HasHltClk,},

{ "RTL-8139

rev K",HW_REVID(1, 1, 0, 0, 0, 0, 0),HasHltClk,},

{

"RTL-8139A",HW_REVID(1, 1, 1, 0, 0, 0, 0),HasHltClk,},

{ "RTL-8139A

rev G",HW_REVID(1, 1, 1, 0, 0, 1, 0),HasHltClk,},

{

"RTL-8139B",HW_REVID(1, 1, 1, 1, 0, 0, 0),HasLWake,},

{

"RTL-8130",HW_REVID(1, 1, 1, 1, 1, 0, 0),HasLWake,},

{

"RTL-8139C",HW_REVID(1, 1, 1, 0, 1, 0, 0),HasLWake,},

{

"RTL-8100",HW_REVID(1, 1, 1, 1, 0, 1, 0),HasLWake,},

{

"RTL-8100B/8139D",HW_REVID(1, 1, 1, 0, 1, 0, 1),HasHltClk |

HasLWake,},

{

"RTL-8101", HW_REVID(1, 1, 1, 0, 1, 1, 1),HasLWake,},

};

struct xc_priv

{

void __iomem

*ioaddr;

spinlock_t

lock;

spinlock_t

rx_lock;

chip_t

chipset;

struct

napi_struct napi;

struct

pci_dev *pdev;

struct

net_device *dev;

struct

net_device_stats stats;

u32

rx_config;

unsigned

char *rx_bufs;

unsigned int

cur_rx;

dma_addr_t

rx_bufs_dma;

unsigned int

tx_flag;

unsigned

long cur_tx;

unsigned

long dirty_tx;

unsigned

char *tx_bufs;

unsigned

char *tx_buf[4];

dma_addr_t

tx_bufs_dma; u32

msg_enable;

unsigned int

default_port : 4; signed char

phys[4]; struct

mii_if_info mii; };

#if RX_BUF_IDX == 1

static const unsigned int xc_rx_config =

(1

<< 11) | (1

<< 7) | (7

<< 13) | (7

<< 8);

#elif RX_BUF_IDX == 2

static const unsigned int xc_rx_config =

(1

<< 12) | (1

<< 7) | (7

<< 13) | (7

<< 8);

#else

#error "Invalid configuration for 8139_RXBUF_IDX"

#endif

static char mii_2_8139_map[8] =

{

BasicModeCtrl,BasicModeStatus,0,0,

NWayAdvert,NWayLPAR,NWayExpansion,0

};

static void xc_check_media(struct net_device *dev, unsigned int

init_media)

{

struct

xc_priv *tp = netdev_priv(dev);

if

(tp->phys[0] >= 0)

mii_check_media(&tp->mii,

netif_msg_link(tp), init_media);

}

static int mdio_read (struct net_device *dev, int phy_id, int

location)

{

struct

xc_priv *tp = netdev_priv(dev);

void __iomem

*ioaddr = tp->ioaddr;

return

location < 8 &&

mii_2_8139_map[location] ?

ioread16(ioaddr+mii_2_8139_map[location]) : 0;

}

static void mdio_write(struct net_device *dev, int phy_id, int

location,int value)

{

struct

xc_priv *tp = netdev_priv(dev);

void __iomem

*ioaddr = tp->ioaddr;

if (location

< 8 &&

mii_2_8139_map[location])

{

if (location == 0)

{

iowrite8(Cfg9346_Unlock,ioaddr+Cfg9346);

iowrite16(value,ioaddr+BasicModeCtrl);

iowrite8(Cfg9346_lock,ioaddr+Cfg9346);

}

else

iowrite32(value,ioaddr+mii_2_8139_map[location]);

}

}

static u32 xc_get_link(struct net_device *dev)

{

struct

xc_priv *tp = netdev_priv(dev);

return

mii_link_ok(&tp->mii);

}

static int xc_get_settings(struct net_device *dev, struct

ethtool_cmd *cmd)

{

struct

xc_priv *tp = netdev_priv(dev);

spin_lock_irq(&tp->lock);

mii_ethtool_gset(&tp->mii,

cmd);

spin_unlock_irq(&tp->lock);

return

0;

}

static struct ethtool_ops xc_ethtool_ops =

{

.get_settings = xc_get_settings,

.get_link = xc_get_link,

};

static void __set_rx_mode (struct net_device *dev)

{(leave)

struct

xc_priv *tp = netdev_priv(dev);

void __iomem

*ioaddr = tp->ioaddr;

u32

mc_filter[2]; int i,

rx_mode;

u32

tmp;

struct

dev_mc_list *mclist;

rx_mode =

AcceptBroadcast | AcceptMyPhys;

mc_filter[1]

= mc_filter[0] = 0;

for (i = 0,

mclist = dev->mc_list; mclist

&& i <

dev->mc_count;

i++, mclist = mclist->next)

{

int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr)

>> 26;

mc_filter[bit_nr >> 5] |= 1

<< (bit_nr &

31);

rx_mode |= AcceptMulticast;

} tmp =

xc_rx_config | rx_mode;

if

(tp->rx_config != tmp)

{

iowrite32(tmp,ioaddr+RxConfig);

ioread32(ioaddr+RxConfig);

tp->rx_config = tmp;

}

iowrite32(mc_filter[0],ioaddr+MAR0 + 0);

iowrite32(mc_filter[1],ioaddr+MAR0 + 4);

}

static void xc_set_multicast_list(struct net_device *dev)

{

unsigned

long flags;

struct

xc_priv *tp = netdev_priv(dev);

spin_lock_irqsave (&tp->lock,

flags);

__set_rx_mode(dev);

spin_unlock_irqrestore (&tp->lock,

flags);

}

static void xc_reset(void __iomem *ioaddr)

{

int

i; iowrite8(CmdReset,ioaddr+ChipCmd); for (i =

1000; i > 0; i--)

{

barrier();

if ((ioread8(ioaddr+ChipCmd) & CmdReset) ==

0)

break;

udelay (10);

}

}

static void xc_cleanup_dev(struct net_device *dev)

{

struct

xc_priv *tp = netdev_priv(dev);

if

(tp->pdev == NULL || dev == NULL)

return;

if

(tp->ioaddr)

pci_iounmap(tp->pdev,tp->ioaddr);

pci_release_regions(tp->pdev);

free_netdev(dev);

pci_set_drvdata(tp->pdev,NULL);

}

static int xc_rx(struct net_device *dev, struct xc_priv *tp, int

budget)

{

u16

status;

struct

sk_buff *skb;

int

packet_size,data_size;

int

work_done = 0;

void __iomem

*ioaddr = tp->ioaddr;

unsigned

long cur_rx = tp->cur_rx;

while

(netif_running(dev) && work_done

< budget &&

((ioread8(ioaddr+ChipCmd) & RxBufEmpty) ==

0))

{

u32 tmp_size;

u32 offset = cur_rx % RX_BUF_LEN;

rmb();

tmp_size = le32_to_cpu(*(u32

*)(tp->rx_bufs+offset));

packet_size = tmp_size >> 16;

data_size = packet_size - 4;

skb = dev_alloc_skb(data_size + 2);

if (likely(skb))

{

skb->dev = dev;

skb_reserve(skb,2);

skb_copy_to_linear_data (skb,

&tp->rx_bufs[offset + 4],

data_size);

skb_put(skb,data_size);

skb->protocol = eth_type_trans (skb, dev);

dev->last_rx = jiffies;

tp->stats.rx_bytes += data_size;

tp->stats.rx_packets++;

netif_receive_skb (skb);

}

else

tp->stats.rx_dropped++;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值