Linux kernel 对linux smc91cx驱动程序代码和相关数据表感到困惑?

Linux kernel 对linux smc91cx驱动程序代码和相关数据表感到困惑?,linux-kernel,linux-device-driver,Linux Kernel,Linux Device Driver,我正在学习内核(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->ba

我正在学习内核(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可写,因此任何提示?

smc91x.c驱动程序涵盖91c111和旧芯片。“91C111忽略了尺寸位,但早期型号没有。”因此

两者都适用于91c111。但是,91c90/c92/c94/c95/c100可能需要传入numPages。在91c111上,用于NUMPAGE的位被标记为“保留”,但“忽略”可能是一个更接近的术语

至于

SMC_ACK_INT(lp, IM_ALLOC_INT);
文档显示中断状态寄存器(ISR)的方式在您第一次使用这种类型的数据表时可能有点混乱。如果查看数据表中的“偏移量”列,您会注意到中断确认寄存器(IAR)也位于0xC,这意味着地址是共享的,但根据读取或写入的情况,其行为不同。具体来说,由于IAR中的位反映了ISR中的位,因此这也被称为清除寄存器的写入位(在google中使用“W1C寄存器”)


如果ISR/IAR是一个单一的读写寄存器,它会打开一个竞争条件,内核可能会读取ISR,清除其中的一个位,在将其存储回ISR之前,硬件会在ISR中设置另一个位,然后内核会用它现在过时的副本覆盖ISR。

我希望数据表与驱动程序代码匹配,有什么提示吗?数据表永远不会匹配真实代码。与设计师想要的相比,真正的硬件总是有一些缺陷/复杂度。谢谢,但是我怎么知道这些缺陷/复杂度呢?当我在代码或数据表的细节中找不到解释这一点的注释时,我可以参考什么?如果我想为某些类型的卡编写驱动程序代码,而数据表没有给我一个明确的定义,我该如何实现它?smc91cx驱动程序的作者也是如此?通常情况下,这些知识是由编写代码的人掌握的——他们要么是偏离原始计划的人,要么是发现困难的人,并询问那些知道的人。哦,天哪!再次感谢,但是这对普通读者来说有点不公平,虽然它打开了数据表,打开了代码,但是“关闭”了一些详细但关键的部分,无论如何,这是不幸运的。
SMC_SET_MMU_CMD(lp, MC_ALLOC); // also work well
SMC_ACK_INT(lp, IM_ALLOC_INT);