mini2440网卡驱动DM9000之dm9000_start_xmit

/* 调用时机:当网卡有数据需要发送的时候,该函数被调用 */

static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
 unsigned long flags;
 board_info_t *db = netdev_priv(dev);

 dm9000_dbg(db, 3, "%s:\n", __func__);

 if (db->tx_pkt_cnt > 1)//只能存放两个数据包,如果已经有两个就退出,原因见注释
  return 1;

 spin_lock_irqsave(&db->lock, flags);/*详见注视*/

 /* Move data to DM9000 TX RAM ,详见注释*/
 writeb(DM9000_MWCMD, db->io_addr);/*MWCMD:/*将io_addr写入寄存器MWCMD (Memory data write

                                                                                    command with addressincrement Register)中;进行

                                                                                    这个command操作后,向io_data写入的数据会传输到

                                                                                    dm9000内部TX SRAM中;
                                                                                                                      */

 (db->outblk)(db->io_data, skb->data, skb->len);      /*将内核网络套接字结构体sk_buff的数据skb->data写入

                                                                                    db->io_data中*/
 dev->stats.tx_bytes += skb->len;                              /*写完后将结构体net_device成员stats.tx_bytes加上刚刚

                                                                                   发送的字节数*/

 db->tx_pkt_cnt++;
 /* TX control: First packet immediately send, second packet queue */
 if (db->tx_pkt_cnt == 1) {
  /* Set TX length to DM9000 */
  iow(db, DM9000_TXPLL, skb->len);
  iow(db, DM9000_TXPLH, skb->len >> 8);

  /* Issue TX polling command */
  iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete *//*这个命令之后TX Buffer中的数据被发送出去*/

  dev->trans_start = jiffies; /* save the time stamp */
 } else {
/*如果发送的是第二个数据包(表明队列中此时有包发送),则将其加入队列中:将skb->len和

skb->ip_summed(控制校验操作)赋值给board_info_t中有关队列的相关成员。调用函数netif_stop_queue(dev),通

知内核现在queue已满,不能再将发送数据传到队列中,注:第二个包的发送将在tx_done中实现,这是因为当第一个数据发送完之后会产生一个中断,在中断中如果判断出事发送完成产生的中断,则会调用tx_done对应的函数,对这个函数的分析在中断函数分析中有详细讲解*/ 

  db->queue_pkt_len = skb->len;
  netif_stop_queue(dev);
 }

 spin_unlock_irqrestore(&db->lock, flags);/*释放自旋锁*/

 /* free this SKB */
 dev_kfree_skb(skb);

 return 0;
}

(1)锁机制:spin_lock(spinlock_t *my_spinlock)--->试图获取锁my_spinlock,如果锁已被别的进程持有,必须等待并不断测试锁的状态直到锁被释放。锁释放后可立即获取。

                       spin_lock_irqsave(spinlock_t *my_spinlock,unsigned long flags)--->与spin_lock()功能类似。额外的它自动屏蔽本地中断,并将CPU的当前状态寄存器值保存到变量flags中。

        二者的区别所在: spin_lock_irqsave屏蔽了本地中断,更加安全,如果用 spin_lock的话可能会照成死锁。比如:进程A与中断运行在同一块CPU上,并且进程A与中断处理程序都spin_lock(&lock)试图获取锁。那么好让我们看看会发生什么事情,进程A正在运行,并且获取了锁,此时产生中断的话,进程A会被置位TASK_INTERRUPT状态(即进程A会被中断),但是它还持有锁啊,它还没有释放锁呢,可是中断处理程序中也要试图获取锁啊,获取不了怎么办?那就忙等待。这样进程A无法运行,中断处理函数也无法运行,就产生了死锁。而使用spin_lock_irqsave的话,由于屏蔽了本地中断,所以就不发生死锁。

(2)Tx Buffer与Rx Buffer:在DM9000内部SRAM中,地址0x0000~0x0BFF是TX Buffer, 地址0x0C00~0x3FFF是RX Buffer。在发送一个包之前,包中的有效数据必须先被存储到TX Buffer中,接下来通过设置发送控制寄存器TCR的bit[0]位来将Tx Buffer中的数据发送出去。那么如何将数据存储到Tx Buffer中呢?首先让WMCMD指向映射过来的db->io_addr,接着将要发送到TX Buffer中的数据写到db->io_addr所指向的db->io_data区域。

(2)Tx Buffer只能存放两个数据包的原因:Tx Buffer中有两个发送索引,依次为indexI和indexII。首先,如果有数据需要发送,则先通过indexI将数据写入Tx Buffer,然后设置发送控制寄存器相应的位将indexI发送。在indexI发送时,还有数据需要发送的话,就将数据通过indexII写入Tx Buffer,当indexI发送结束后,就会依次将indexII发送出去。但我们同时要明白,虽然Tx Buffer中可以存放两个数据包,但是同一时间只能有一个数据包处于发送状态。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DM9000是一个常用的网络接口控制器芯片,用于将嵌入式系统连接到以太网。要调试DM9000网卡,可以按照以下步骤进行: 1. 硬件连接:首先,确保DM9000芯片正确连接到嵌入式系统板上,并与以太网接口相连接。检查芯片的供电和时钟信号。 2. 驱动程序:编写适当的驱动程序,以便嵌入式系统能够与DM9000通信。这通常涉及到与DM9000芯片的寄存器进行交互,读取和写入必要的控制和配置参数。确保驱动程序正确加载到系统中。 3. 硬件配置:检查DM9000的配置寄存器,确保MAC地址设置正确,并且与局域网中的其他设备不冲突。还可以配置其他参数,例如速度和双工模式。 4. 命令行工具:一些嵌入式操作系统提供了用于调试以太网接口的命令行工具。使用这些工具,您可以查看和配置DM9000的状态和参数。例如,您可以使用ifconfig命令查看和配置网络接口的IP地址和子网掩码。 5. debug信息:通过在驱动程序中添加适当的调试信息,可以轻松地跟踪和定位问题。打印DM9000的状态、接收和发送的数据包以及其他有用的信息,有助于确定问题所在。 6. 监视网络流量:使用网络分析工具,例如Wireshark,来监视DM9000的数据流量。这将帮助您识别任何异常数据包或通信问题。 7. FQA和论坛:查阅DM9000相关的文档、常见问题解答(FAQ),以及在线社区和论坛寻求帮助。在这些平台上,您可以找到其他用户的经验和解决方案。 总的来说,要调试DM9000网卡,需要确保正确连接硬件,编写驱动程序并配置相关参数。使用命令行工具、添加debug信息、监视网络流量和寻求帮助,可以更容易地发现和解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值