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);
--}