Linux设备驱动工程师之路——DM9000网卡驱动程序分析(3)

5.接收数据

  1. /*
     *  Received a packet and pass to upper layer
     */
  2. static void  
  3. dm9000_rx(struct net_device *dev)  
  4. {  
  5.     board_info_t *db = netdev_priv(dev);  
  6.     struct dm9000_rxhdr rxhdr;  
  7.     struct sk_buff *skb;  
  8.     u8 rxbyte, *rdptr;  
  9.     bool GoodPacket;  
  10.     int RxLen;  
  11.   
  12.     /* Check packet ready or not */  
  13.     do {  
  14.         ior(db, DM9000_MRCMDX); /* Dummy read */  
  15.   
  16.         //获取接收数据的长度  
  17.         /* Get most updated data */  
  18.         rxbyte = readb(db->io_data);  
  19.   
  20.         //检查设备接收状态  
  21.         /* Status check: this byte must be 0 or 1 */  
  22.         if (rxbyte > DM9000_PKT_RDY) {  
  23.             dev_warn(db->dev, "status check fail: %d\n", rxbyte);  
  24.             iow(db, DM9000_RCR, 0x00);  /* Stop Device */  
  25.             iow(db, DM9000_ISR, IMR_PAR);   /* Stop INT request */  
  26.             return;  
  27.         }  
  28.   
  29.         if (rxbyte != DM9000_PKT_RDY)  
  30.             return;  
  31.   
  32.           
  33.         /* A packet ready now  & Get status/length */  
  34.         GoodPacket = true;  
  35.         writeb(DM9000_MRCMD, db->io_addr);  
  36.   
  37.         (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));  
  38.   
  39.         RxLen = le16_to_cpu(rxhdr.RxLen);  
  40.   
  41.         if (netif_msg_rx_status(db))  
  42.             dev_dbg(db->dev, "RX: status %02x, length %04x\n",  
  43.                 rxhdr.RxStatus, RxLen);  
  44.   
  45.         /* Packet Status check */  
  46.         if (RxLen < 0x40) {  
  47.             GoodPacket = false;  
  48.             if (netif_msg_rx_err(db))  
  49.                 dev_dbg(db->dev, "RX: Bad Packet (runt)\n");  
  50.         }  
  51.   
  52.         if (RxLen > DM9000_PKT_MAX) {  
  53.             dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);  
  54.         }  
  55.   
  56.         /* rxhdr.RxStatus is identical to RSR register. */  
  57.         if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |  
  58.                       RSR_PLE | RSR_RWTO |  
  59.                       RSR_LCS | RSR_RF)) {  
  60.             GoodPacket = false;  
  61.             if (rxhdr.RxStatus & RSR_FOE) {  
  62.                 if (netif_msg_rx_err(db))  
  63.                     dev_dbg(db->dev, "fifo error\n");  
  64.                 dev->stats.rx_fifo_errors++;  
  65.             }  
  66.             if (rxhdr.RxStatus & RSR_CE) {  
  67.                 if (netif_msg_rx_err(db))  
  68.                     dev_dbg(db->dev, "crc error\n");  
  69.                 dev->stats.rx_crc_errors++;  
  70.             }  
  71.             if (rxhdr.RxStatus & RSR_RF) {  
  72.                 if (netif_msg_rx_err(db))  
  73.                     dev_dbg(db->dev, "length error\n");  
  74.                 dev->stats.rx_length_errors++;  
  75.             }  
  76.         }  
  77.   
  78.         /* Move data from DM9000 */  
  79.         //如果接收正确,开始接收  
  80.         if (GoodPacket  
  81.             && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {  
  82.             skb_reserve(skb, 2);  
  83.             rdptr = (u8 *) skb_put(skb, RxLen - 4);//获取skb的数据指针  
  84.   
  85.             /* Read received packet from RX SRAM */  
  86.   
  87.             (db->inblk)(db->io_data, rdptr, RxLen);//读取数据  
  88.             dev->stats.rx_bytes += RxLen;  
  89.   
  90.             /* Pass to upper layer */  
  91.             skb->protocol = eth_type_trans(skb, dev);  
  92.             netif_rx(skb);//将接收到的skb交给协议层  
  93.             dev->stats.rx_packets++;  
  94.   
  95.         } else {  
  96.             /* need to dump the packet's data */  
  97.   
  98.             (db->dumpblk)(db->io_data, RxLen);  
  99.         }  
  100.     } while (rxbyte == DM9000_PKT_RDY);  
  101. }  

6.发送完成

  1. /*
     * DM9000 interrupt handler
     * receive the packet to upper layer, free the transmitted packet
     */
  2. static void dm9000_tx_done(struct net_device *dev, board_info_t *db)  
  3. {  
  4.     int tx_status = ior(db, DM9000_NSR);    /* Got TX status */  
  5.   
  6.     if (tx_status & (NSR_TX2END | NSR_TX1END)) {  
  7.         /* One packet sent complete */  
  8.   
  9.         //将数据包计数减1  
  10.         db->tx_pkt_cnt--;  
  11.         dev->stats.tx_packets++;  
  12.   
  13.         if (netif_msg_tx_done(db))  
  14.             dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status);  
  15.   
  16.         /* Queue packet check & send */  
  17.         //如果数据包数量依然大于0,说明是TX RAM中的第二个包,再次启动发送,将TX RAM中第二个包发送出去  
  18.         if (db->tx_pkt_cnt > 0) {  
  19.           /*把数据的长度填到TXPLL(发送包长度低字节)和TXPLH(发送包长度高字节)中*/    
  20.         iow(db, DM9000_TXPLL, skb->len);    
  21.         iow(db, DM9000_TXPLH, skb->len >> 8);    
  22.         /*置发送控制寄存器(TX Control Register)的发送请求位TXREQ(Auto clears after sending completely),这样就可以发送出去了*/   
  23.             dev->trans_start = jiffies;  
  24.         }  
  25.         netif_wake_queue(dev);//唤醒发送队列  
  26.     }  
  27. }  

7.超时处理

  1. static void dm9000_timeout(struct net_device *dev)  
  2. {  
  3.     board_info_t *db = netdev_priv(dev);  
  4.     u8 reg_save;  
  5.     unsigned long flags;  
  6.   
  7.     /* Save previous register address */  
  8.     reg_save = readb(db->io_addr);  
  9.     spin_lock_irqsave(&db->lock, flags);  
  10.   
  11.     //停止发送队列并复位DM9000网卡  
  12.     netif_stop_queue(dev);  
  13.     dm9000_reset(db);  
  14.     dm9000_init_dm9000(dev);  
  15.     /* We can accept TX packets again */  
  16.   
  17.     //重新发送  
  18.     dev->trans_start = jiffies;  
  19.     netif_wake_queue(dev);  
  20.   
  21.     /* Restore previous register address */  
  22.     writeb(reg_save, db->io_addr);  
  23.     spin_unlock_irqrestore(&db->lock, flags);  
  24. }  
dm9000最详细的中文数据手册 最全的中文 DM9000A数据手册 目 录 1. 概述 5 2. 模块图 5 3. 特性 5 4. 引脚配置 6 4.1(16位模式) 6 4.2(8位模式) 7 5. 引脚描述 7 5.1处理器接口 7 5.1.1 8位模式引脚 8 5.2 EEPROM接口 8 5.3时钟引脚 9 5.4 LED接口 9 5.5 10/100 PHY/Fiber 9 5.6其他 10 5.7电源引脚 10 5.8捆绑引脚列表(Strap pins table) 10 6. 控制和状态寄存器列表 10 6.1网络控制寄存器(NCR) 12 6.2网络状态寄存器(NSR) 13 6.3发送控制寄存器(TCR) 13 6.4数据包1发送状态寄存器1(TSR I) 13 6.5数据包2发送状态寄存器2(TSR II) 14 6.6接收控制寄存器(RCR) 14 6.7接收状态寄存器(RSR) 15 6.8接收溢出计数寄存器(ROCR) 15 6.9背压阈值寄存器(BPTR) 15 6.10流控制阈值寄存器(FCTR) 16 6.11接收/发送流控制寄存器(RTFCR) 16 6.12 EEPROM与PHY控制寄存器(EPCR) 17 6.13 EEPROM与PHY地址寄存器(EPAR) 17 6.14 EEPROM与PHY数据寄存器(EPDRL/EPDRH) 18 6.15唤醒控制寄存器(WCR) 18 6.16物理地址(MAC)寄存器(PAR) 18 6.17多播地址寄存器(MAR) 19 6.18通用目的控制寄存器(GPCR) 19 6.19通用目的寄存器(GPR) 19 6.20 TX SRAM读指针地址寄存器(TRPAL/TRPAH) 20 6.21 RX SRAM写指针地址寄存器(RWPAL/RWPAH) 20 6.22厂家ID寄存器(VID) 20 6.23产品ID寄存器(PID) 20 6.24芯片版本寄存器(CHIPR) 20 6.25发送控制寄存器2(TCR2) 20 6.26操作测试控制寄存器(OCR) 21 6.27特殊模式控制寄存器(SMCR) 21 6.28即将发送控制/状态寄存器(ETXCSR) 22 6.29校验和控制寄存器(TCSCR) 22 6.30接收校验和控制状态寄存器(RCSCSR) 22 6.31内存数据预取读命令寄存器(地址不加1)(MRCMDX) 23 6.32内存数据读命令寄存器(地址不加1)(MRCMDX1) 23 6.33内存数据读命令寄存器(地址加1)(MRCMD) 23 6.34内存数据读地址寄存器(MRRL/ MRRH) 23 6.35内存数据写命令寄存器(地址不加1)(MWCMDX) 23 6.36内存数据写命令寄存器(地址加1)(MWCMD) 24 6.37内存数据写地址寄存器(MWRL/ MWRH) 24 6.38发送数据包长度寄存器(TXPLL/TXPLH) 24 6.39中断状态寄存器 (ISR) 24 6.40中断屏蔽寄存器(IMR) 24 7.EEPROM格式 25 8.PHY寄存器描述 26 8.1基本模式控制寄存器(BMCR) 27 8.2基本模式状态寄存器(BMSR) 28 8.3 PHY ID标识符寄存器#1(PHYID1) 29 8.4 PHY ID标识符寄存器#2(PHYID1) 29 8.5自动协商通知寄存器(ANAR) 30 8.6自动协商连接对象寄存器(ANLPAR) 31 8.7自动协商扩展寄存器(ANER) 32 8.8 DAVICOM指定配置寄存器(DSCR) 33 8.9 DAVICOM指定配置和状态寄存器(DSCSR) 34 8.10 10BASE-T配置/状态(10BTCSR) 36 8.11掉电控制寄存器(PWDOR) 36 8.12指定配置寄存器(SCR) 37 9. 功能描述 38 9.1 主机接口(HI) 38 9.2 直接内存访问控制(DMAC) 38 9.3 数据包发送(PT) 38 9.4 数据包接收(PR) 39 9.5 100Base-TX操作 39 9.5.1 4B5B编码器 39 9.5.2扰频器(Scrambler) 39 9.5.3 并--串转换 39 9.5.4 NRZ码到NRZI码转换 39 9.5.5 NRZI码到MLT-3码转换 39 9.5.6 MLT-3驱动 40 9.5.7 4B5B编码 40 9.6 100Base-TX接收器 40 9.6.1 信号检测 41 9.6.2 自适应补偿 41 9.6.3 MLT-3到NRZI解码 41 9.6.4 时钟复原模块 41 9.6.5 NRZI 到NRZ 41 9.6.6 串-并转换 41 9.6.7 扰频器 41 9.6.8 编码组对齐模块 42 9.6.9 4B5B解码 42 9.7 10Base-T操作 42 9.8 冲突检测 42 9.9 载波检测 42 9.10 自动协商 42 9.11 省电模式 42 9.11.1 掉电模式 43 9.11.2 降低发送损耗模式 43 10 DC与AC电器特性 43 10.1 最大绝对额定值 43 10.1.1 工作条件 43 10.2 DC电器特性(VDD=3.3V) 44 10.3 AC电器特性与时序 44 10.3.1 TP接口 44 10.3.2 晶振/振荡时钟 44 10.3.3 I/O读时序 45 10.3.4 I/O写时序 45 10.3.5 EEPROM接口时序 46 11应用说明 46 11.1网络接口信号接线 46 11.2 10Base-T/100Base-TX自动MDIX应用 47 11.3 10Base-T/100Base-TX无自动MDIX变压器应用 47 11.4电源退偶电容 47 11.5地平面布局 48 11.6电源平面分割 49 11.7铁氧体磁珠选择指导 50 11.8晶振选择指导 50 12封装信息 50 13订购信息 52
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值