More Related Content Similar to Linux Ethernet device driver (20) Linux Ethernet device driver4. 4
開發流程
宣告struct
net_device 結構變數
或
用alloc_etherdev()
設定必要的callback
fuction在上述的結構
中
呼叫
register_netdev()註
冊該driver
系統呼叫init callback
function初始化該元件
啓動該介面時系統會
呼叫open callback
function
送資料時系統呼叫
hard_start_xmit
callback function
當收到資料時
可呼叫
netif_rx()往
上層送資料
5. struct net_device
struct net_device
{
char name[IFNAMSIZ];
…………………………………..
unsigned long base_addr; /* device I/O address */
unsigned int irq; /* device IRQ number */
struct net_device_stats* (*get_stats)(struct net_device *dev);
const struct ethtool_ops *ethtool_ops;
int (*open)(struct net_device *dev);
int (*stop)(struct net_device *dev);
void (*set_multicast_list)(struct net_device *dev);
int (*do_ioctl)(struct net_device *dev,
struct ifreq *ifr, int cmd);
void (*tx_timeout) (struct net_device *dev);
unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address,
(before bcast
because most packets are unicast) */
…………………………………….
}
6. Module init example (dm9000.c)
static struct platform_driver dm9000_driver = {
.driver = {
.name = "dm9000",
.owner = THIS_MODULE,
},
.probe = dm9000_probe,
.remove = __devexit_p(dm9000_drv_remove),
.suspend = dm9000_drv_suspend,
.resume = dm9000_drv_resume,
};
static int __init dm9000_init(void)
{
printk(KERN_INFO "%s Ethernet Driver, V%sn", CARDNAME, DRV_VERSION);
return platform_driver_register(&dm9000_driver);
}
static void __exitdm9000_cleanup(void)
{
platform_driver_unregister(&dm9000_driver);
}
module_init(dm9000_init);
module_exit(dm9000_cleanup);
7. Probe example (dm9000.c)
static int __devinit dm9000_probe(struct platform_device *pdev)
{
……………………….
ndev = alloc_etherdev(sizeof(struct board_info));
………………………
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
…………………….
db->addr_req = request_mem_region(db->addr_res->start, iosize,
pdev->name);
db->io_addr = ioremap(db->addr_res->start, iosize);
/* fill in parameters for net-dev structure */
ndev->base_addr = (unsigned long)db->io_addr;
ndev->irq = db->irq_res->start;
/* driver system function */
ether_setup(ndev);
ndev->open = &dm9000_open;
ndev->hard_start_xmit = &dm9000_start_xmit;
ndev->tx_timeout = &dm9000_timeout;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
ndev->stop = &dm9000_stop;
ndev->set_multicast_list = &dm9000_hash_table;
ndev->ethtool_ops = &dm9000_ethtool_ops;
ndev->do_ioctl = &dm9000_ioctl;
……………….
ret = register_netdev(ndev);
return 0;
}
8. 上傳資料
1) 可用interrupt service routine or polling將底層的資
料收進來
2) 呼叫netif_rx()上傳資料
下傳資料
1) 上層將會呼叫所註冊的hard_start_xmit() callback
function
Allocate buffer kernel API
1) struct sk_buff *alloc_skb(unsigned int size,gfp_t
priority)
8
如何上下傳資料
9. Start xmit example
/* Move data to DM9000 TX RAM */
writeb(DM9000_MWCMD, db->io_addr);
(db->outblk)(db->io_data, skb->data, skb->len);
dev->stats.tx_bytes += skb->len;
db->tx_pkt_cnt++;
/* TX control: First packet immediately send, second packet queue */
if (db->tx_pkt_cnt == 1) {
/* Set TX length to DM9000 */
iow(db, DM9000_TXPLL, skb->len);
iow(db, DM9000_TXPLH, skb->len >> 8);
/* Issue TX polling command */
iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
dev->trans_start = jiffies; /* save the time stamp */
} else {
/* Second packet */
db->queue_pkt_len = skb->len;
netif_stop_queue(dev);
}
/* free this SKB */
dev_kfree_skb(skb);
return 0;
10. Receive packet interrupt example
if (GoodPacket
&& ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
skb_reserve(skb, 2);
rdptr = (u8 *) skb_put(skb, RxLen - 4);
/* Read received packet from RX SRAM */
(db->inblk)(db->io_data, rdptr, RxLen);
dev->stats.rx_bytes += RxLen;
/* Pass to upper layer */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
} else {
/* need to dump the packet's data */
(db->dumpblk)(db->io_data, RxLen);
}
11. struct sk_buff {
struct sk_buff *next;
struct sk_buff *prev;
…………………………..
unsigned char *data;
unsigned int len;
………….
}
11
skb buffer stream
struct sk_buff {
struct sk_buff *next;
struct sk_buff *prev;
…………………………..
unsigned char *data;
unsigned int len;
………….
}
Data
buffer
Data
buffer
12. Tx/Rx Buffer Management
12
Buffer Descriptor
Start Address
Register
+
BRXBDCNT+0
… …
BDMATXDPTR
buffer pointer #1
status length
buffer pointer #2
status length
buffer pointer #N
status length
Buffer Descriptor Rx Buffer
… … …
buffer #1
not used
buffer #2
not used
buffer #N
not used
Memory for frame
BRXBDCNT+1
BRXBDCNT+(N-1)
BRxBS of
BDMARXLEN
BRxBS of
BDMARXLEN
BRxBS of
BDMARXLEN
BDMA buffer
descriptor
counter of
current pointer
…
Memory for Rx buffer descriptor
13. skb buffer由下而上時是由ethernet device
driver allocate,而由上層的TCP free
skb buffer由上而下時是由TCP allocate,而
由底層的ethernet free
其中在open的call back function需要
netif_start_queue()
在close時需要netif_stop_queue()
在timeout時需要netif_wake_queue()
13
注意事項