RSS

PciFuncs

22 11月

PciFuncs.h

/**********************************************************************

PciFuncs.h : PCIバス制御関数ヘッダファイル Version 3.0

**********************************************************************/
#ifndef __PCIFUNCS_H

//
//  _USERが定義されていればDllImportとExternが有効
//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifdef _USER
#define DllImport __declspec(dllimport)
//#define Extern    extern"C"
#define Extern
#else
#define DllImport
#define Extern
#endif

Extern BOOL DllImport WINAPI Pcibus_Open();
Extern void DllImport WINAPI Pcibus_Close();
Extern BOOL DllImport WINAPI Pcibus_Scan(WORD vid, WORD did, BOOL* exists);
Extern DWORD DllImport WINAPI Pcibus_Input(short type, WORD off);
Extern void DllImport WINAPI Pcibus_Output(short type, WORD off, DWORD data);
Extern WORD DllImport WINAPI Pcibus_Version();
Extern void DllImport WINAPI Pcibus_BaseSel(short n);
Extern DWORD DllImport WINAPI Pcibus_ReadConfig(short reg);
Extern void DllImport WINAPI Pcibus_WriteConfig(short reg, DWORD value);

// Version 2.0
Extern DWORD DllImport WINAPI BaseAddr(short n);
Extern DWORD DllImport WINAPI AbsInput(short type, WORD addr);
Extern void DllImport WINAPI  AbsOutput(short type, WORD addr, DWORD data);

// Version 3.0 (Pcibus.vxd V1.1)
Extern void DllImport WINAPI Pcibus_BlockRead(WORD off, long Count, WORD* buff);
Extern void DllImport WINAPI Pcibus_BlockWrite(WORD off, long Count, WORD* buff);

#endif

PciFuncs.c

/***********************************************************************

PCI Bus 制御関数DLL for Windows 98 Version 3.0
Copyright(c)1999 by @@@. All rights reserved.

***********************************************************************/
#include <windows.h>
#include <stdlib.h>
#include <memory.h>
#include <stdio.h>
#include "pcifuncs.h"

#define USE_VXD            0  // 非0ならPcibus.vxdを使用する
#define BUFSIZE  256

#define GET_VERSION        0xff    // バージョン番号を得る
#define WRITE_CONFIG    1        // PCI CONFIG_ADDRESSレジスタに書く
#define READ_CONFIG        2        // PCI CONFIG_DATAレジスタを読む
#define READ_CONFIG_REG    3        // 指定されたコンフィギュレーションレジスタを読む
#define GET_BASE_ADDR0    4        // Base Address Register0を読む
#define GET_BASE_ADDR1    5        // Base Address Register1を読む
#define INP_BYTE        6        // 8ビット入力
#define INP_WORD        7        // 16ビット入力
#define INP_DWORD        8        // 32ビット入力
#define OUT_BYTE        9        // 8ビット出力
#define OUT_WORD        10        // 16ビット出力
#define OUT_DWORD        11        // 32ビット出力
#define WRITE_CONFIG_DATA    12    // Config Dataレジスタに書く

static PDWORD pInBuff, pOutBuff;
static HANDLE hVxd = NULL;
static WORD m_vid, m_did;
static short m_deviceNumber = 0;
static BOOL m_detect = FALSE;
static WORD m_bar[5];    // ベースアドレスレジスタ
short  m_barnum = 0;    // 使うベースアドレスレジスタ
static BOOL m_winnt = FALSE;
static short useVxd = USE_VXD;

//
//  DLL EntryPoint
//  ==============
BOOL WINAPI DllEntryPoint(HINSTANCE hInst, DWORD dwReason, LPVOID Reserved)
{
OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&info);
if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
m_winnt = TRUE;
return TRUE;
}

/////////////////////////////////////////////////////////////////////

//
//  初期化
//  ======
BOOL WINAPI Pcibus_Open()
{
// Windows NTのとき
if (m_winnt)
return FALSE;

// VxDを使わないとき
if (! useVxd)
{
hVxd = NULL;
return TRUE;
}

// VxDを開く
hVxd = CreateFile(
"\\\\.\\Pcibus.vxd",
0,
0,
NULL,
CREATE_ALWAYS,
0,
NULL);
if(hVxd == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
hVxd = NULL;
return FALSE;
}

// パラメータ領域を確保
pInBuff = (PDWORD)malloc(BUFSIZE);
pOutBuff = (PDWORD)malloc(BUFSIZE);

return TRUE;
}

//
//  終了処理
//  ========
void WINAPI Pcibus_Close()
{
// Windows NTのとき
if (m_winnt)
return;

if (hVxd)
{
CloseHandle(hVxd);
free(pInBuff);
free(pOutBuff);
}
}

/******************************************************

PCIをスキャンして指定されたベンダIDとデバイスIDを持つデバイスを検出する

******************************************************/
BOOL WINAPI Pcibus_Scan(WORD vid, WORD did, BOOL *exists)
{
short i;
DWORD result, refval, BytesReturned;

// Windows NTのとき
if (m_winnt)
{
*exists = FALSE;
return FALSE;
}

*exists = FALSE;    // ターゲット存在の有無
refval = MAKELONG((WORD)vid, (WORD)did);    // コンフィグレジスタ0の期待値

// スロットをスキャン
for (i = 0; i < 32; i++)
{
if (useVxd)
{
*pInBuff = 0x80000000L | (DWORD)(i << 11);
result = DeviceIoControl(hVxd, 3, pInBuff, BUFSIZE, pOutBuff, BUFSIZE, &BytesReturned, NULL);
if (! result)
return FALSE;
else
{
if (*pOutBuff == refval)
{
// 検出した
m_vid = vid;
m_did = did;
m_detect = TRUE;
*exists = TRUE;
m_deviceNumber = i;
// ベースレジスタ0を得る
*pInBuff = 0x80000010L | (DWORD)(i << 11);
result = DeviceIoControl(hVxd, 3, pInBuff, BUFSIZE, pOutBuff, BUFSIZE, &BytesReturned, NULL);
//printf("BAR0=%08x\n", *pOutBuff);  // debug
if (! result)
return FALSE;
if (*pOutBuff & 1) // I/Oアドレスかチェック
m_bar[0] = (WORD)(*pOutBuff & 0xfffc);
else
return FALSE;    // メモリアドレス
// ベースレジスタ1を得る
*pInBuff = 0x80000010L | (DWORD)(i << 11);
result = DeviceIoControl(hVxd, 3, pInBuff, BUFSIZE, pOutBuff, BUFSIZE, &BytesReturned, NULL);
if (! result)
return FALSE;
m_bar[1] = (WORD)(*pOutBuff & 0xfffc);
break;
}
}
}
else
{
DWORD dw;
dw = 0x80000000L | (i << 11);
_asm
{
mov dx, 0cf8h
mov eax, dw
out dx, eax
mov dx, 0cfch
in eax, dx
mov dw, eax
}
// 検出したか
if (dw == refval)
{
m_vid = vid;
m_did = did;
m_detect = TRUE;
*exists = TRUE;
m_deviceNumber = i;
// ベースレジスタ0を得る
m_bar[0] = (WORD)(Pcibus_ReadConfig(4) & 0xfffc);
//printf("BAR0=%08x\n", *pOutBuff);  // debug
// ベースレジスタ1を得る
m_bar[1] = (WORD)(Pcibus_ReadConfig(5) & 0xfffc);
break;
}
}
}
return TRUE;
}

/******************************************************

ポートから入力

******************************************************/
DWORD WINAPI Pcibus_Input(short type, WORD off)
{
static short VxdCmd[] = {INP_BYTE, INP_WORD, INP_DWORD};
DWORD BytesReturned;
BOOL result;
DWORD value;
WORD addr;

// Windows NTのとき
if (m_winnt)
return 0;

if (m_detect)
{
addr = m_bar[m_barnum] + (WORD)off;
if (useVxd)
{
*pInBuff = (DWORD)addr;
result = DeviceIoControl(
hVxd,
VxdCmd[type],
pInBuff,
BUFSIZE,
pOutBuff,
BUFSIZE,
&BytesReturned,
NULL);
if (! result)
return 0xffffffffL;
else
value = (long)*pOutBuff;
}
else
{
_asm
{
mov dx, addr
mov eax, 0
in ax, dx
mov value, eax
}
}
}
else
return 0xffffffffL;

return value;
}

/******************************************************

ポートに出力

******************************************************/
void WINAPI Pcibus_Output(short type, WORD off, DWORD data)
{
DWORD BytesReturned;
HRESULT hr = S_OK;
WORD addr, d;
BOOL result;
PDWORD p;
static short VxdCmd[] = {OUT_BYTE, OUT_WORD, OUT_DWORD};

// Windows NTのとき
if (m_winnt)
return;

if (m_detect)
{
addr = m_bar[m_barnum] + (WORD)off;
if (useVxd)
{
p = pInBuff;
*p = (DWORD)addr;
p++;
*p = data;
result = DeviceIoControl(
hVxd,
VxdCmd[type],
pInBuff,
BUFSIZE,
pOutBuff,
BUFSIZE,
&BytesReturned,
NULL
);
}
else
{
d = (WORD)data;
_asm
{
mov    dx, addr
mov ax, d
out dx, ax
}
}
}
}

/******************************************************

ドライバのバージョンを得る

******************************************************/
WORD WINAPI Pcibus_Version()
{
BOOL result;
DWORD BytesReturned;

// Windows NTのとき
if (m_winnt)
return 0;

if (! useVxd)
return 0x8210;

if (! hVxd)
return 0xffff;

result = DeviceIoControl(hVxd, GET_VERSION, pInBuff, BUFSIZE, pOutBuff, BUFSIZE, &BytesReturned, NULL);
if (result)
return (WORD)*pOutBuff;
else
return 0xffff;
}

/******************************************************

ベースアドレスレジスタを変更する(0 or 1)

******************************************************/
void WINAPI Pcibus_BaseSel(short n)
{
m_barnum = n;
}

/******************************************************

PCIコンフィギュレーションレジスタを読む

******************************************************/
DWORD WINAPI Pcibus_ReadConfig(short reg)
{
BOOL result;
DWORD BytesReturned, dw;

if (!m_detect)
return 0xffffffffL;

dw = 0x80000000L | (m_deviceNumber << 11) | (reg << 2);
if (useVxd)
{
*pInBuff = dw;
result = DeviceIoControl(
hVxd,
READ_CONFIG_REG,
pInBuff,
BUFSIZE,
pOutBuff,
BUFSIZE,
&BytesReturned,
NULL);
if (! result)
return 0xffffffffL;
else
return *pOutBuff;
}
else
{
_asm
{
mov dx, 0cf8h
mov eax, dw
out dx, eax
mov dx, 0cfch
in eax, dx
mov dw, eax
}
return dw;
}
}

/******************************************************

PCIコンフィギュレーションレジスタに書く

******************************************************/
void WINAPI Pcibus_WriteConfig(short reg, DWORD value)
{
//    BOOL result;
DWORD BytesReturned;
DWORD dw;

if (!m_detect)
return;

dw = *pInBuff = 0x80000000L | (m_deviceNumber << 11) | (reg << 2);
if (useVxd)
{
// Config Addressレジスタに書く
DeviceIoControl(
hVxd,
WRITE_CONFIG,
pInBuff,
BUFSIZE,
pOutBuff,
BUFSIZE,
&BytesReturned,
NULL);
// Config Dataレジスタに書く
*pInBuff = value;
DeviceIoControl(
hVxd,
WRITE_CONFIG_DATA,
pInBuff,
BUFSIZE,
pOutBuff,
BUFSIZE,
&BytesReturned,
NULL);
}
else
{
_asm
{
mov dx, 0cf8h
mov eax, dw
out dx, eax
mov dx, 0cfch
mov eax, value
out dx, eax
}
}
}

/*************************** Version 2.0 *********************************/

//
//  ベースアドレスを得る
//  ====================
DWORD WINAPI BaseAddr(short n)
{
DWORD dw = 0xffffffffL;

if (n < 2)
dw = m_bar[n];

return dw;
}

//
//  指定されたI/Oアドレス(絶対値)から入力する
//  =========================================
DWORD WINAPI AbsInput(short type, WORD addr)
{
static short VxdCmd[] = {INP_BYTE, INP_WORD, INP_DWORD};
DWORD BytesReturned;
BOOL result;
DWORD value;

// Windows NTのとき
if (m_winnt)
return 0;

if (m_detect)
{
*pInBuff = (DWORD)addr;
if (useVxd)
{
result = DeviceIoControl(
hVxd,
VxdCmd[type],
pInBuff,
BUFSIZE,
pOutBuff,
BUFSIZE,
&BytesReturned,
NULL);
if (! result)
return 0xffffffffL;
else
value = (long)*pOutBuff;
}
else
{
_asm
{
mov dx, addr
mov eax, 0
in ax, dx
mov value, eax
}
}
}
else
return 0xffffffffL;

return value;
}

//
//  指定されたI/Oアドレス(絶対値)へ出力する
//  ========================================
void WINAPI  AbsOutput(short type, WORD addr, DWORD data)
{
DWORD BytesReturned;
HRESULT hr = S_OK;
WORD d;
BOOL result;
PDWORD p;
static short VxdCmd[] = {OUT_BYTE, OUT_WORD, OUT_DWORD};

// Windows NTのとき
if (m_winnt)
return;

if (m_detect)
{
p = pInBuff;
*p = (DWORD)addr;
p++;
*p = data;
if (useVxd)
{
result = DeviceIoControl(
hVxd,
VxdCmd[type],
pInBuff,
BUFSIZE,
pOutBuff,
BUFSIZE,
&BytesReturned,
NULL
);
}
else
{
d = (WORD)data;
_asm
{
mov    dx, addr
mov ax, d
out dx, ax
}
}
}
}

/*************************** Version 3.0 *********************************/

//
//  指定されたI/Oアドレス(OFFSET)からワード列を入力する
//  ====================================================
void WINAPI Pcibus_BlockRead(WORD off, long Count, WORD* buff)
{
long i;
BOOL result;
DWORD BytesReturned;
WORD wData;
WORD addr = m_bar[m_barnum] + off;
PWORD pw = (PWORD)pInBuff;
PDWORD pd;

*pw = addr;
pw++;
*pw = 0;
pw++;
pd = (PDWORD)pw;
*pd = Count;

if (useVxd)
{
result = DeviceIoControl(
hVxd, 13, pInBuff, BUFSIZE, pOutBuff, BUFSIZE, &BytesReturned, NULL);
if (result)
{
memcpy((PBYTE)buff, (PBYTE)pOutBuff, (Count * 2));
}
}
else
{
pw = buff;
for (i = 0; i < Count; i++)
{
_asm
{
mov dx, addr;
in  ax, dx
mov wData, ax
}
*pw = wData;
pw++;
}
}
}

//
//  指定されたI/Oアドレス(OFFSET)へワード列を出力する
//  =================================================
void WINAPI Pcibus_BlockWrite(WORD off, long Count, WORD* buff)
{
long i;
BOOL result;
DWORD BytesReturned;
WORD wData;
WORD addr = m_bar[m_barnum] + (WORD)off;
PWORD pw = (PWORD)pInBuff;
PWORD qw;
*pw = addr; pw++;
*pw = 0; pw++;
*pw = LOWORD(Count);
pw++;
*pw = HIWORD(Count);
pw++;
qw = buff;

for (i = 0; i < Count; i++)
{
*pw = *qw;
pw++;
qw++;
}

if (useVxd)
{
result = DeviceIoControl(
hVxd, 14, pInBuff, BUFSIZE, pOutBuff, BUFSIZE, &BytesReturned, NULL);
}
else
{
pw = buff;
for (i = 0; i < Count; i++)
{
wData = *pw; pw++;
_asm
{
mov dx, addr;
mov ax, wData
out  dx, ax
}
}
}
}

PciFunc.def

LIBRARY PciFuncs
EXPORTS
Pcibus_Open            @1
Pcibus_Close        @2
Pcibus_Scan            @3
Pcibus_Input        @4
Pcibus_Output        @5
Pcibus_Version        @6
Pcibus_BaseSel        @7
Pcibus_ReadConfig    @8
Pcibus_WriteConfig    @9
BaseAddr            @10
AbsInput            @11
AbsOutput            @12
Pcibus_BlockRead    @13
Pcibus_BlockWrite    @14

 

 
コメントする

投稿者: : 2010/11/22 投稿先 C

 

タグ: , , , , , ,

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中