2011-12-15 10 views
1

私はカーネル(linux-3.1)ネットワークドライバを学習しています、カードドライバはsmc91cxです。私はSMSC lan91c111のデータシートを手に持っています。もしそうなら、私はドライバのコードについていくつか質問がある:linux smc91cxドライバコードと関連するデータシートに困惑?

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を追加するのですか?

次の行がある:このマクロは、最終的にはバンク2セット SMC_ACK_INT(lp, IM_ALLOC_INT); - 割り込みステータス・レジスタを、データシートは、ALLOC INTが任意のヒントので、書き込み可能にすることができます表示されませんか?

+0

データシートがドライバコードと一致することを願っています。 – liunx

+1

データシート*決して実際のコードと一致しません。実際のハードウェアには常にいくつかのバグ/複雑さがあり、デザイナーが望んでいたものがあります。 – Flexo

+0

ありがとうございますが、これらのバグ/合併症をどのように知ることができますか?データシートのコードや詳細でこれを説明するコメントが見つからない場合、私は何を参照することができますか?あるタイプのカード用のドライバコードを書いて、データシートに明確な定義が与えられていない場合、どうすればそれを実現できますか? smc91cxドライバの作者もそうですか? – liunx

答えて

1

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に使用されるビットは '予約済み'とマークされますが、 'ignored'は近い用語です。

SMC_ACK_INT(lp, IM_ALLOC_INT); 

ドキュメントは、割り込みステータスレジスタ(ISR)を示している方法については

は少しあなたは、データシートのこのスタイルで働いてきた最初の時間を混乱かもしれません。データシートの「オフセット」列を見ると、アドレスが共有されていても読み込みまたは書き込みに基づいて異なる動作をすることを意味する0xCに割り込み認識レジスタ(IAR)もあります。具体的には、IARのビットはISRのビットを反映しているため、これはWrite-One-To-Clear-Register(Googleの「W1Cレジスタ」を使用)とも呼ばれます。

ISR/IARが単一の読み書き可能なレジスタであった場合、カーネルがISRを読み込み、ビットをクリアし、ISRに戻す直前にハードウェアが別のISRの現在の古いコピーでISRを上書きします。

関連する問題