dm9000驱动分析



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




猜你喜欢

转载自blog.csdn.net/jun_8018/article/details/77531111
今日推荐