显存读写
? ? ? ? 要在顯示屏顯示圖像,方法有兩種,mmio pio。現在的顯卡都應當支持vbe。
? ? ? ? ?vbe 提供了保護模式的接口,bios方式太舊了,且保護模式操作太復雜,故想找個簡單的方式,但這方面的資料太少,花了不少時間,終于成功。
? ? ? ? ?利用bios 10號中斷取得保護接口信息,除5、7、9號程序,還有幾個端口信息,好不容易找到保護模式切換顯示模式的使用方法。不過還不確定bios返回端口的具體用途,但顯示設置的函數實驗成功。
? ? ? ? 顯存的訪問,在低分辨率及字符模式,地址在0xa0000---0xbffff之間,但到了高分辨率就一般在高端內存。網上查的說可以直接訪問,我怎么實驗都沒成功。搞了一個星期,終于可以正確顯示。
? ? ? 要想訪問顯存,有3步:
? ? ?1. 顯存的物理地址,英文叫LFB,可以bios 1號中段獲取,資料上說可以自主設置,不過我在bochs上沒成功,不知哪里出錯了,后來沒搞了。
? ? ? 2. MTRR,說起來有點復雜,意思就是把顯存地址注冊到地址空間。獨顯、核顯、仿真對地址分配有沒區別,還待實驗。
? ? ? 3. 顯卡設置,開啟lfb。好象只能顯示真彩色,低色彩的還沒成功。
? ? 開啟之后,就顯存地址就是物理地址了,統一在4G之內,讀寫也正常,屏幕顯示正常,不過bochs顯示內存指令不能顯示,不知道是bochs的問題,還是本來就這樣。關鍵代碼在下面
void BgaSetVideoMode(unsigned int Width, unsigned int Height, unsigned int BitDepth, int UseLinearFrameBuffer, int ClearVideoMemory)
{
?? ?// VBE disabling
? ? BgaWriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
?? ?//
? ? BgaWriteRegister(VBE_DISPI_INDEX_XRES, Width);
? ? BgaWriteRegister(VBE_DISPI_INDEX_YRES, Height);
? ? BgaWriteRegister(VBE_DISPI_INDEX_BPP, BitDepth);
? ? BgaWriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED |
? ? ? ? (UseLinearFrameBuffer ? VBE_DISPI_LFB_ENABLED : 0) |
? ? ? ? (ClearVideoMemory ? 0 : VBE_DISPI_NOCLEARMEM));
}
?
DWORD find_empty_mtrr()
{
?? ?
?? ??? ?//RDMSR將64位由ECX寄存器指定的MSR(model specific register,
?? ??? ?//模式指定寄存器)的內容讀出至寄存器EDX:EAX中
?? ??? ?//(在支持intel64架構的處理器中RCX的高32位忽略)。
?? ??? ?//MSR的高32位內容存放在EDX寄存器中,
?? ??? ?//MSR的低32位內容存放在EAX寄存器中
?? ??? ?//(在支持intel64架構的處理器中RDX和RAX的高32位忽略)。
?? ??? ?//如果MSR中沒有64位(有些位沒有實現),
?? ??? ?//則EDX:EAX中沒有實現的位置則未定義。
?? ??? ?//寄存器2個一組
?? ??? ?DWORD empmtrr,port,val1,val2;
?? ??? ?empmtrr=0;
?? ??? ?for (port=0x201;port<0x200+16;port=port+2)
?? ??? ?{
?? ??? ??? ?rdmsr(port,val1,val2);
?? ??? ??? ?if (!(val1&0x0800))
?? ??? ??? ?{
?? ??? ??? ??? ?port--;
?? ??? ??? ??? ?empmtrr=port;
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return empmtrr;
}
void enableMtrr(DWORD addr)
{
?? ?DWORD mttr,val1,val2;
?? ?mttr = find_empty_mtrr();
?? ?// ; LFB , +8 M , write combine
?? ?//|64 保留 ? ?| 物理地址 12|11 ?8|7 type |0
?? ?//|64 保留 ? ?| 掩碼|Valid 11|10 保留 |0?? ?
?? ?wrmsr(mttr,addr | 1,0);
?? ?
? ? wrmsr(mttr+1,0xff800800,0xf);?
//?? ? enable mtrr's
? ? rdmsr(0x2ff,val1,val2); ?
?? ?wrmsr(0x2ff,val1 | 0x800 ,val2);
? ? ?
?? ??? ?
}
?
總結
- 上一篇: 解决make: *** [install
- 下一篇: jQuery-表单校验