新闻  |   论坛  |   博客  |   在线研讨会
DM9003 驱动学习(六)Linux driver 04
0750long | 2009-05-26 18:49:22    阅读:2874   发布文章

DM9003 驱动学习(六)Linux driver 04

 

DM9003 发送及接收packet程序
MWCMDX 写SRAM,地址指针不变
MWCMD 写SRAM,地址指针自动增加
MRCMDX 预处理读SRAM,地址指针不变
MRCMDX1/MRCMD 读SRAM,地址指针增加

/*
  Hardware start transmission.
  Send a packet to media from the upper layer.
*/
static int dm9013_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
 board_info_t *db = (board_info_t *)dev->priv;
 char * data_ptr;

 DM9013_DBUG(0, "dm9013_start_xmit()", 0);
 if (db->tx_pkt_cnt >= 2)
 {
  netif_stop_queue(dev);
  db->stop_transmit =1;
  return 1;
 }

        //发送数据统计
 /* packet counting */
 db->tx_pkt_cnt++;

 db->stats.tx_packets++;
 db->stats.tx_bytes+=skb->len;

 // FIFO has fulled already
 if (db->tx_pkt_cnt == 2)
 {
  netif_stop_queue(dev);
  db->stop_transmit =1;
 }

        //所有中断禁止
 /* Disable all interrupt */
 dm9013_disable_interrupt(db);

       //发送数据包长度
 /* Set TX length to reg. 0xfc & 0xfd */
 iow(db, DM9013_TXPLL, (skb->len & 0xff));
 iow(db, DM9013_TXPLH, (skb->len >> 8) & 0xff);
    
        //copy发送数据到SRAM
 /* Move data to TX SRAM */
 data_ptr = (char *)skb->data;
 
 outb(DM9013_MWCMD, db->io_addr); /* Write data into SRAM trigger */
 db->MoveData(db, data_ptr, skb->len, 1);
 //发送请求
 /* Issue TX polling command */
 iow(db, DM9013_TCR, TCR_TX_Request);
        //发送时间
 /* Saved the time stamp */
 dev->trans_start = jiffies;
 db->cont_rx_pkt_cnt =0;
      
        //释放系统发送数据块
 /* Free this SKB */
 dev_kfree_skb(skb);

        //使能DM9003所有中断
 /* Re-enable interrupt */
 dm9013_enable_interrupt(db);

 return 0;
}

/*
 * Received a packet and pass to upper layer
 */
static void dm9013_packet_receive(struct net_device *dev)
{
 board_info_t *db = (board_info_t *)dev->priv;
 struct sk_buff *skb;
 u8 rxbyte, val;
 u16 MDRAH, MDRAL;

 rx_t rx;

 u8 * ptr = (u8*)℞
 u8* rdptr;

 DM9013_DBUG(0, "dm9013_packet_receive()", 0);
 
 db->cont_rx_pkt_cnt=0; 
 do {
               //保留读数据地址到MDR(读数据地址寄存器)
  /*store the value of Memory Data Read address register*/
  MDRAH=ior(db, DM9013_MDRAH);
  MDRAL=ior(db, DM9013_MDRAL);
 
                //预读数据 
            rxbyte =ior(db, DM9013_MRCMDX);/* Dummy read */ 
     rxbyte =inb(db->io_data);  /* read the byte of packet ready */
         //检查数据包是否OK,第一个byte为0x01
  /* packet ready to receive check */
  if(!(val = check_rx_ready(rxbyte))) break;

                //开始从SRAM读数据
  /* A packet ready now  & Get status/length */
  outb(DM9013_MRCMD, db->io_addr);

  /* Read packet status & length */
  db->MoveData(db,ptr,4,0);
               //检查数据包状态
  /* Packet status check */
  if (rx.desc.status & 0x03) //0xbf)
      {
   //printk("DM9013:RX ERROR\n");
         db->stats.rx_errors++;
          if (rx.desc.status & RX_FIFO_over)
           db->stats.rx_fifo_errors++;
          if (rx.desc.status & RX_CRCErr)
              db->stats.rx_crc_errors++;
                       
          /* drop this packet */
          db->MoveData(db, NULL, rx.desc.length, 0);
          db->stats.rx_dropped++;
          continue;
                }

                //Move SRAM数据至系统  
  skb = dev_alloc_skb(rx.desc.length+4);
  if (skb == NULL ) //系统申请数据块失败
  { 
   printk(KERN_INFO "%s: Memory squeeze.\n", dev->name);
   /*re-load the value into Memory data read address register*/
   iow(db,DM9013_MDRAH,MDRAH);
   iow(db,DM9013_MDRAL,MDRAL);
   return;
  }
  else //申请到数据块
  {
   /* Move data from DM9000 */
   skb->dev = dev;
   skb_reserve(skb, 2);
   rdptr = (u8*)skb_put(skb, rx.desc.length - 4);
   
   db->MoveData(db, rdptr, rx.desc.length, 0);
   /* Pass to upper layer */
   skb->protocol = eth_type_trans(skb,dev);
#ifdef CHECKSUM  
   skb->ip_summed = CHECKSUM_UNNECESSARY; // V1.03 (3)
   if ((rxbyte&0xE0)||(rxbyte==0x01))
    skb->ip_summed = CHECKSUM_NECESSARY; /* receive packet no checksum fail */
#endif
   netif_rx(skb);  //系统处理数据至网络memory
   dev->last_rx=jiffies;
   db->stats.rx_packets++;
   db->stats.rx_bytes += rx.desc.length;
   db->cont_rx_pkt_cnt++;
   if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
   {
    printk("RX out \n");
    dm9013_tx_done(0);
    break;
   }
  }
 }while((rxbyte & 0x01) == DM9013_PKT_RDY);
 DM9013_DBUG(0, "[END]dm9013_packet_receive()", 0);
 }

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客