我想自己编写一个小型的OS,仅仅为了学习的目的
在访问IDE时碰到一些问题想请教大家
我的开发环境是virtualPC 2007
部分32位引导代码如下
; ebx= start sector
; ecx= sector number to read 0
; edi= buffer address
mov dx, 3f6h ;reset hd disk
mov al, 04h
out dx, al ;SRST=1
xor al, al
out dx, al ;SRST=0
wait_ready:
mov dx, 1f7h
in al, dx
and al, 01000000b
jz wait_ready ;Wait DRDY=1
sub dl, 6
xor al, al
out dx, al ;out 1f1h, 0
inc dl
mov al, cl
out dx, al ;out 1f2h, sectorsToRead
inc dl
mov al, 40h
shl eax, 24
add eax, ebx
out dx, eax ;out 1f3h, ebx | 0x40000000
add dl, 4
mov al, 20h
out dx, al ;out 1f7h, 20h
shl ecx, 8 ;ecx=ecx*256
waitHDD:
in al, dx
and al, 00001000b
jz waitHDD ;wait next data ready
sub dl, 7
;rep insw
mov ax, dx
stosw
add dl, 7
loop waitHDD
这段代码是在刚开机bootsector中的,
问题是很奇怪,如果用rep insw就有一定的可能读不全数据
而用mov ax, dx
stosw
add dl, 7
loop waitHDD
则每次都能读对
不知道大家有么有碰到过这个问题
全部的代码在http://minios2.googlecode.com/svn/trunk/codes/可以用svn check out出来
可以跟大家一起学习
更奇怪的是boot起来之后
用ide.c中的ide_readpio4读取ide则每次都可以成功
ide_readpio4地实现基本和上面的代码相同
难道是virtualPC的问题?
另外一个问题是采用DMA方式读,数据是读出来了,但是中断迟迟不触发
以下是代码的片断,详细的代码都可以check out 出来
struct _DMABUFDES
{
uint32 base;
uint16 eot;
uint16 len;
} idedmabuf = {0x10000, 0x8000, 0};
uint32 ide_readdma(uint32 start, uint32 number)
{
start |= 0x40000000;
_out(PCIIDE_CTRL, 0);
_out(PCIIDE_CTRL + 2, 0x06);
_out32(PCIIDE_CTRL + 4, (uint32)&idedmabuf); // Setup dma buffer
_out(PRIMARY_CTRL, 0); // enable interrupt
_out32(PRIMARY_ATA + 6, 0x40);
while((_in(PRIMARY_ATA + 7) & 0x40) == 0)
;
_out(PRIMARY_ATA + 2, number);
_out32(PRIMARY_ATA + 3, start);
_out(PRIMARY_ATA + 7, 0xC8);
while((_in(PRIMARY_ATA + 7) & 0x0f) == 0)
;
_out(PCIIDE_CTRL, 9);
return 0;
}
好象不能用insw,记不清了,改成insb或insd试试。