小華的部落格: Windows 下的I/O存取

搜尋此網誌

網頁

星期二, 5月 08, 2007

Windows 下的I/O存取

昨天我們Leader 請我幫忙寫一個Tools給對岸同胞的生產線使用,他們需要在Vista 底下去存取Panel ID.
所以自己留下個撰寫紀錄,讓自己下次修改自己的Source Code的時候有個依據。

目前Panel ID我們是使用跳線的方式去改變GPIO值來做辨別,所以只要去存取GPIO就可以了。

1.南橋ICH8會把GPIO 值 mapped 到某個IO Range...所以只要利用組合語言的IN/OUT 去存取他映對過去的IO 位址就可以知道GPIO的值。
2.查看主機板電路圖,看實際上被當成選擇Panel ID的GPIO是哪幾支接腳。
3.開發一個DOS版的Tools直接使用IN/OUT指令去存取,例如下面範例:
byte ReadGpioStatus(word OEM_GPIO_ADDR)
{
byte mbid;
...
_asm {
mov dx, OEM_GPIO_ADDR
in ax, dx
mov mbid, al
}
...
return mbid;
}
4.開發一個Windows 版的Tools也是使用IN/OUT指令,不過是由自己撰寫的I/O Driver所提供
byte ReadGpioStatus(word OEM_GPIO_ADDR)
{
byte mbid;
mbid=IN_B(OEM_GPIO_ADDR); //IN_B 會去呼叫Windows API然後送IRP給我自己寫的Driver
return mbid;
}
5.在Source code內做一個介面IN_B() 然後呼叫API去使用自己寫的I/O Driver所提供的服務
byte IN_B (WORD port)
{
ireg.x.DX = port;
...
bRc = DeviceIoControl (...); //送IRP給我自己寫的I/O Driver...
...
return (ireg.h.AL);
}
6.整個Windows版本的Source code架構與DOS版本差異不大,只是Windows版本需要去動態載入驅動程式,而這部分寫在if (!InitializeWinIo()) return 1 ;

上述這幾個部份是比較重要的地方,而整個DOS版與Windows版的程式架構如下:
int main(int argc,char *argv[])
{
modelString[]={
"000"," Reserved. ",
"001"," Vendor1. ",
"002"," Vendor2. ",
....
}
...
if (!InitializeWinIo()) return 1 ; // For Windows version only.
...
pStatus1=ReadGpioStatus(OEM_GPIO_DEFAULT_IO1); // Read Gpio
pStatus2=ReadGpioStatus(OEM_GPIO_DEFAULT_IO2);
...
panelid=(GetBit(pStatus1,2)<<2)+(GetBit(pStatus1,6)<<1)+GetBit(pStatus2,6);
...
if (strcmp(argv[2], modelString[panelid*2]))
{
...// if match...return passed!
}
return 0;
}

從上面範例可以知道其實DOS版與Windows版的Source code 寫法幾乎一樣,只是Windows版因為無法直接存取I/O,所以我自己多加了一個I/O Driver,然後做了兩個Function (IN_B()跟InitializeWinIo())來載入與使用這個Driver 。

沒有留言: