我正在学习内核(linux-3.1)网络驱动程序,卡驱动程序是smc91cx,我手边有SMSC lan91c111的数据表,那么数据表是否与代码匹配?如果是这样,我对驱动程序代码有一些疑问:
static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) {
struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
unsigned int numPages, poll_count, status;
unsigned long flags;
DBG(3, "%s: %s\n", dev->name, __func__);
BUG_ON(lp->pending_tx_skb != NULL);
/*
* The MMU wants the number of pages to be the number of 256 bytes
* 'pages', minus 1 (since a packet can't ever have 0 pages :))
*
* The 91C111 ignores the size bits, but earlier models don't.
*
* Pkt size for allocating is data length +6 (for additional status
* words, length and ctl)
*
* If odd size then last byte is included in ctl word.
*/
numPages = ((skb->len & ~1) + (6 - 1)) >> 8;
if (unlikely(numPages > 7)) {
printk("%s: Far too big packet error.\n", dev->name);
dev->stats.tx_errors++;
dev->stats.tx_dropped++;
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
smc_special_lock(&lp->lock, flags);
/* now, try to allocate the memory */
SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); // why?
// SMC_SET_MMU_CMD(lp, MC_ALLOC); // also work well
/*
* Poll the chip for a short amount of time in case the
* allocation succeeds quickly.
*/
poll_count = MEMORY_WAIT_TIME;
do {
status = SMC_GET_INT(lp);
if (status & IM_ALLOC_INT) {
printk(KERN_INFO "SMC91X: status & IM_ALLOC_INT\n");
SMC_ACK_INT(lp, IM_ALLOC_INT);
status = SMC_GET_INT(lp);
if (status & IM_ALLOC_INT)
printk(KERN_INFO "SMC91X: SMC_ACK_INT done.\n");
break;
}
} while (--poll_count);
smc_special_unlock(&lp->lock, flags);
lp->pending_tx_skb = skb;
if (!poll_count) {
/* oh well, wait until the chip finds memory later */
netif_stop_queue(dev);
DBG(2, "%s: TX memory allocation deferred.\n", dev->name);
SMC_ENABLE_INT(lp, IM_ALLOC_INT);
} else {
/*
* Allocation succeeded: push packet to the chip's own memory
* immediately.
*/
smc_hardware_send_pkt((unsigned long)dev);
}
return NETDEV_TX_OK;
}
看到代码片段,我添加了一些测试代码,我对SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
感到困惑
这个宏最后设置了smc91c111卡的mmu命令寄存器,它只允许3位操作码,但为什么要添加numPages?
下一行是:
SMC_ACK_INT(lp, IM_ALLOC_INT);
这个宏终于设置了Bank2 - 中断状态寄存器,数据表没有显示ALLOC INT可写,所以任何提示?
答案 0 :(得分:2)
smc91x.c驱动程序涵盖91c111和旧芯片。 " 91C111忽略了尺寸位,但早期的型号没有。"因此,
SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); // why?
和
SMC_SET_MMU_CMD(lp, MC_ALLOC); // also work well
都适用于91c111。但是,91c90 / c92 / c94 / c95 / c100可能需要传入numPages。在91c111上,用于numPages的位标记为'保留',但它可能是' ;忽略'是一个更接近的术语。
至于
SMC_ACK_INT(lp, IM_ALLOC_INT);
当您第一次使用这种数据表时,文档显示中断状态寄存器(ISR)的方式可能有点令人困惑。如果你看看'偏移'在数据表中的列中,您会注意到中断确认寄存器(IAR)也处于0xC,这意味着该地址是共享的,但基于读取或写入的行为有所不同。具体来说,因为IAR中的位与ISR中的位相同,所以这也称为Write-One-To-Clear-Register(使用" W1C寄存器"在谷歌中)。
如果ISR / IAR是一个读写寄存器,它会打开一个竞争条件,内核可能会读取ISR,清除一点,然后在将其存储回ISR之前,硬件会设置另一个位在ISR中,然后内核用现在陈旧的副本覆盖ISR。