1.關於write函數條用過程
write
--->sock_aio_write
------>do_sock_write
--------->__sock_sendmsg /*--->協議無關層*/
sock->ops->sendmsg /*--->協議棧(以udp爲例)*/
--->udp_sendmsg
---->ip_route_output_flow(選擇路由)
----->ip_push_pending_frames
------->ip_local_out
--------->dst_output
---------->skb_dst(skb)->output(skb)
------------>ip_finish_output
--------------->ip_finish_output2
------------------>neigh->ops->queue_xmit(skb)
--------------------->dev_queue_xmit-->dev_hard_start_xmit
------------------------>ops->ndo_start_xmit(skb, dev); /*調用設備驅動中的發送函數(dm9000.c)*/
2.dm9000.c函數分析
--2.1 關於dm9000_probe ()
--{
/* Init network device */
ndev = alloc_etherdev(sizeof(struct board_info));
* setup board info structure */
db = netdev_priv(ndev);
/*映射dm9000 地址端口 和 數據端口 (s3c6410-->io_phyaddr = 1800 0000 ;-->data_phyaddr = 1800 0004*/
osize = resource_size(db->addr_res);
db->addr_req = request_mem_region(db->addr_res->start, iosize,
pdev->name);
if (db->addr_req == NULL) {
dev_err(db->dev, "cannot claim address reg area\n");
ret = -EIO;
goto out;
}
db->io_addr = ioremap(db->addr_res->start, iosize); /*映射io端口*/
if (db->io_addr == NULL) {
dev_err(db->dev, "failed to ioremap address reg\n");
ret = -EINVAL;
goto out;
}
iosize = resource_size(db->data_res);
db->data_req = request_mem_region(db->data_res->start, iosize, /*映射data端口*/
pdev->name);
/*其他設置板級包db(省略...)*/
dm9000_set_io(db, iosize);
dm9000_reset(db);//復位dm9000
/* 設置ndev*/
ether_setup(ndev);
ndev->netdev_ops = &dm9000_netdev_ops;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
ndev->ethtool_ops = &dm9000_ethtool_ops;
/*註冊net_device*/
ret = register_netdev(ndev);
--}
--2.2 關於dm9000_open( )
--{
board_info_t *db = netdev_priv(dev);/*取得板級包*/
if(request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)) /*註冊中斷*/
return -EAGAIN;
/* Initialize DM9000 board */
dm9000_reset(db);
dm9000_init_dm9000(dev);
/*檢查連接狀態,開啓發送隊列*/
mii_check_media(&db->mii, netif_msg_link(db), 1);
netif_start_queue(dev);
--}
--2.3 關於發送數據包函數--dm9000_start_xmit( )
--{
/* 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_pkt_cnt在ether_setup(ndev)函數中值設爲0*/
/* TX control: First packet immediately send, second packet queue */
if (db->tx_pkt_cnt == 1) {
dm9000_send_packet(dev, skb->ip_summed, skb->len);
{
/* Set TX length to DM9000 */
iow(dm, DM9000_TXPLL, pkt_len);
iow(dm, DM9000_TXPLH, pkt_len >> 8);
/* set the bit1 of DM9000_TCR before tx data */
iow(dm, DM9000_TCR, TCR_TXREQ); /*automatic Cleare the bit-TCR_TXREQ after TX complete */
}
} else {
/* Second packet */
db->queue_pkt_len = skb->len;
db->queue_ip_summed = skb->ip_summed;
netif_stop_queue(dev);
}
/* free this SKB */
dev_kfree_skb(skb);
--}
--當發送數據完了以後,產生髮送中斷(在dm9000_open中註冊)--->dm9000_interrupt
-->dm9000_tx_done
--{
int tx_status = ior(db, DM9000_NSR); /* Got TX status */
if (tx_status & (NSR_TX2END | NSR_TX1END)) {
/* One packet sent complete */
db->tx_pkt_cnt--;
dev->stats.tx_packets++;
if (netif_msg_tx_done(db))
dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);
/* Queue packet check & send */
if (db->tx_pkt_cnt > 0) /*表明還有數據包要發送, 就接着發送*/
dm9000_send_packet(dev, db->queue_ip_summed, db->queue_pkt_len);
netif_wake_queue(dev); /*dm9000只能有兩個數據包在發送, 超過兩個。就讓其在隊列裏面等待 netif_stop_queue(dev);*/
--}
2.4.關於數據包接受函數--dm9000_rx( )
當有數據包產生時,就產生中斷,進入中斷處理函數dm9000_interrupt(),
-->接着調用dm9000_rx(struct net_device *dev)
--{
board_info_t *db = netdev_priv(dev);
struct dm9000_rxhdr rxhdr;
struct sk_buff *skb;
u8 rxbyte, *rdptr;
bool GoodPacket;
int RxLen;
/* Check packet ready or not */
do {
ior(db, DM9000_MRCMDX); /* Dummy read */
/* Get most updated data */
rxbyte = readb(db->io_data);
/* Status check: this byte must be 0 or 1 */
if (rxbyte & DM9000_PKT_ERR) {
dev_warn(db->dev, "status check fail: %d\n", rxbyte);
iow(db, DM9000_RCR, 0x00); /* Stop Device */
iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */
return;
}
if (!(rxbyte & DM9000_PKT_RDY))
return;
/* A packet ready now & Get status/length (4個字節)*/
GoodPacket = true;
writeb(DM9000_MRCMD, db->io_addr);
(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
RxLen = le16_to_cpu(rxhdr.RxLen);
if (netif_msg_rx_status(db))
dev_dbg(db->dev, "RX: status %02x, length %04x\n",
rxhdr.RxStatus, RxLen);
/* Packet Status check */
if (RxLen < 0x40) {
GoodPacket = false;
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
}
if (RxLen > DM9000_PKT_MAX) {
dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
}
.....................
/*構造數據包,並將數據包送個上層協議棧*/
/* Move data from DM9000 */
if (GoodPacket &&
((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
skb_reserve(skb, 2); /*ip包4字節對齊 */
rdptr = (u8 *) skb_put(skb, RxLen - 4); /*除去cfs*/
/* 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);
if (db->rx_csum) {
if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb_checksum_none_assert(skb);
}
netif_rx(skb); /*將數據包交給上層協議棧*/
dev->stats.rx_packets++;
} else {
/* need to dump the packet's data */
(db->dumpblk)(db->io_data, RxLen);
}
} while (rxbyte & DM9000_PKT_RDY);
--}