11

単純なテスト デバイス用の PCI ドライバーを作成しています。

ハードウェアは lspci で正しく認識されます (ドライバーvabsが登録されていることがわかります):

04:02.0 Non-VGA unclassified device: Device bace:55aa
    Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
    Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
    Latency: 0
    Region 0: Memory at f0000000 (32-bit, prefetchable) [size=16M]
    Kernel driver in use: vabs

ドライバーと PCI サブシステムの初期化と初期化解除は正常に機能します。デバイス番号を取得し、udev がデバイス ファイルを作成します。

デバイス ファイルから読み取ると、次のエラー メッセージが表示されます。

BUG: unable to handle kernel paging request at 00000000f0000000

初期化で PCI リソースを正常に要求しました。これは、PCI のベースアドレス 0 である memstart0 に対して 00000000f0000000 を返します。

memstart0 = pci_resource_start( pdev, 0 );
memlen = pci_resource_len( pdev, 0 );
if( request_mem_region(memstart0,memlen,pdev->dev.kobj.name)==NULL ) {
    dev_err(&pdev->dev,"Memory address conflict for device\n");
    goto cleanup_mem;
}

次のコードでこの memio アドレスから読み取ろうとすると、前述のエラーが発生します。

ssize_t driver_read(struct file *instance, char __user *buffer, size_t max_bytes_to_read, loff_t *offset) {
    u32 test;

    dev_dbg(vabs_dev,"copying from %p\n", (void *) memstart0);
    test = readl((void *) memstart0);

    return max_bytes_to_read;
}

memcpy_fromio、ioread32、ダイレクト ポインター アクセスなどの他のアクセス関数も試しましたが、結果は同じでした。

ハードウェアは Windows マシンで動作します。唯一の注目すべき違いは、Windows ではベース アドレス 0 が 00000000f d 000000 として予約されているのに対し、Linux ではベース アドレス 0 が 00000000f 0 000000 として予約されていることです。

これは、公立学校での非営利の教育目的のためのものです。ご協力いただきありがとうございます!

4

1 に答える 1

19

Documentation/IO-mapping.txt (「 iomap 」を検索) および/またはLDD3 の第 15 章をお読みください

request_mem_region他のドライバーがそのメモリ領域を既に取得していないことを確認するだけです。iomap読み取り/書き込みを行う前に、カーネルの VM スペースにマップする必要があります。

ダンス全体pci_resource_startなどはやや非推奨であることに注意してください。最近推奨されるアプローチは次のとおりだと思います。

pci_request_regions(pdev, "myname");  /* to request regions for all BARs */

それで:

void __iomem *base = pci_iomap(pdev, 0, pci_resources_len(pdev,0)); /* to map BAR 0 */

それで:

ioread32(base + offset);  /* Or readl(base + offset), but this is more generic */

そして最後に、最後に:

pci_iounmap(pdev, base);  /* Release kernel VM mapping (undoes pci_iomap) */
pci_release_regions(pdev); /* Release all regions (undoes pci_request_regions) */

pci_resource_start最初の 2 つは、 、pci_resource_lenrequest_mem_region、およびを組み合わせて手動で行うことができますiomap。ただし、上記は (a) 短く、(b) メモリ マップド デバイスと古い x86 I/O 空間を使用するデバイスの間で一般的です。(もうたくさんの人がいるというわけではありません。)

于 2012-12-10T17:08:03.320 に答える