INtimeドキュメンタリトップへ

PCIボードを検出しろ!!

10月14日・・・ベースアドレスがずれるって!?

PCIデバイスの検出ロジック部で、GetPciInterruptLevel()をコピー、修正し、割り込みレベルの他にベースアドレスを取得するようにプログラムした関数です(FindAnalogBoard())


/***********************************************************************/
/*	関数名	:	FindAnalogBord                     */
/*	説明	:	アナログボード検索                */
/*	引数	:	なし                                */
/*	戻り値	:	正常:TRUE  エラー時:FALSE        */
/************************************************************************/
BOOL			FindAnalogBord(void)
{
	PCIDEV		PciDevInfo;		/* PCI Device Infomation*/
	BYTE		ret;			/* PCIデバイス検索用変数*/
	static const BYTE	irq2level[] =		/* 割り込みレベル*/
	{
		IRQ0_LEVEL,  IRQ1_LEVEL,  IRQ2_LEVEL,  IRQ3_LEVEL,
		IRQ4_LEVEL,  IRQ5_LEVEL,  IRQ6_LEVEL,  IRQ7_LEVEL,
		IRQ8_LEVEL,  IRQ9_LEVEL,  IRQ10_LEVEL, IRQ11_LEVEL,
		IRQ12_LEVEL, IRQ13_LEVEL, IRQ14_LEVEL, IRQ15_LEVEL
	};
	strInfo.analogAdd = 0;
	/* ベンダーIDとデバイスIDを代入*/
	PciDevInfo.wVendorId	=	ANALOG_VENDORI...............(1)
	PciDevInfo.wDeviceId	=	ANALOG_DEVICEI...............(2)
	PciDevInfo.wDeviceIndex= 0;
	/* +++ デバイス検索  +++*/
	//	ベンダーID、デバイスIDよりPCIボードの検索を行う
	ret	=	PciFindDevice(&PciDevInfo...............(3)
	/* +++ デバイス検索に該当しなかったか || IRQ判定 +++*/
	if( (ret == FALSE) || (PciDevInfo.byIntLine > 15)...............(4)
	{
		/* デバイスは見つからないのでエラーコードを返す*/
		return FALSE;
	}
	/*	PCIコンフィギュレーションレジスタ書き込み	*/
	PciSetConfigRegister(&PciDevInfo,0x04,T_BYTE,0x01);
	/* アドレス取得	*/
	strInfo.analogAdd = (WORD)PciDevInfo.dwBaseAddr[0...............(5)
	printf("Analog Board Base Address=%4x\n",PciDevInfo.dwBaseAddr[0]);
          //	割込みレベルを設定する
	strInfo.wIntLevel = irq2level[PciDevInfo.byIntLine..............(6)
	printf("Interrupt Level=%4x\n",PciDevInfo.wIntLevel);

         return TRUE;
}
strInfoはグローバルデータ構造体
(1)ベンダーIDをPCIDEV構造体に格納
(2)デバイスIDをPCIDEV構造体に格納
(3)PciFindDevice()コール
(4)PCIデバイスの検出を判別
(5)ベースアドレスを取得
(6)割り込みレベルを取得

途中経過

新たに検出ロジック部をこのロジックに変更し実行してみたところ

Analog Board Base Address=C001
Interrupt Level=0020


とアドレスが返却されました。

≪これでベースアドレスが取れたし、割り込みレベルも取得できた≫


とりあえず、ここまできたので一度マネージャーに報告することにしました。マネージャーに現在の状況を説明し、現コードを実行してみせると・・・

「あれっ?ベースアドレスってこれでいいのかなぁ?」

≪おいおい、これ以上はきちんとできないくらいにきちんとかいたつもりだよ~・・・!!≫

おもむろにPCIバス詳細本を取り出し、

「これについて言うのを忘れていた・・・!」 「・・・・・・・・・・・・・・・・・・・・・・・。」


≪え~ぅっ・・・何について・・・?≫



「ベースレジスタにはI/O空間なのか、メモリ空間なのかを識別するフラグ(I/O空間インジケータ)があるんですよ・・・。」


「なんですと・・・・」


【I/O空間用ベース・アドレスレジスタの場合】

結果
「ADボードの場合、ここはI/O空間ですから、ベースアドレスの末尾ビットに1がたっているはずです。」

「・・・なるほど・・・それでC001と1が末尾ビットに1がたっているわけですね・・・でそれではどうしたらよろしいのでしょう?」

「単純に取得したベースアドレスの末尾2桁(この場合予約部分も不透明なため)をマスク処理する方向でよいのではないですか?」

「なるほど・・・ということは、このビットを0にするようにするには・・・」

≪・・・・・・・マスク:1111111111111100これは・・・・・0xFFFC・・・・・?≫


strInfo.analogAdd = (WORD)PciDevInfo.dwBaseAddr[0] & 0xFFFC;


「ビンゴです!!」


「この値を取得したベースアドレスとの"アンド"を取ればよいのですな・・・・なっとく!!」

メモリ空間用ベースアドレスレジスタの場合

ベースアドレスレジスタの場合、メモリ空間、I/O空間かを識別する必要があります。末尾ビットが0の場合、メモリ空間として使用されています。末尾ビットが1の場合、I/O空間として使用されています。

メモリ空間用ベースアドレスの場合は末尾ビットがメモリ空間用インジケータであり、この値が0となります。


※TenAsys®, INtime®, eVM® and iRMX® are registered trademarks in USA of the TenAsys Corporation.