My O/S is now in protected mode so i can not access to disk using interrupts now.And I do not know how to switch to v86 mode.I need to use ports to disk access.
I decided to try the code which i found on the forum.osdev.org.In the emulator,It shows Disk Read or Write successfuly Done.But when i check the HDD it is empty or when i test reading,Buffer is all empty.
What is the problem with this code or my O/S? (Maybe Stack Problem Causes That?) CODE:
set_up_buffer:
xor ax,ax
mov es,ax
mov di,[buffer]
mov al,0xCD
stosb
mov al,0x19
stosb
WriteToMbr:
mov dx,1f6h ;Drive and head port
mov al,0a0h ;Drive 0, head 0
out dx,al
mov dx,1f2h ;Sector count port
mov al,1 ;Write one sector
out dx,al
mov dx,1f3h ;Sector number port
mov al,1 ;Wrote to sector one
out dx,al
mov dx,1f4h ;Cylinder low port
mov al,0 ;Cylinder 0
out dx,al
mov dx,1f5h ;Cylinder high port
mov al,0 ;The rest of the cylinder 0
out dx,al
mov dx,1f7h ;Command port
mov al,30h ;Write with retry.
out dx,al
oogle:
in al,dx
test al,8 ;Wait for sector buffer ready.
jz oogle
mov cx,512/2 ;One sector /2
mov si,[buffer]
mov dx,1f0h ;Data port - data comes in and out of here.
rep outsw ;Send it.
leave
ret
buffer:
times 512 db 0
I FOUND THE PROBLEM,The problem was at rep outsw
, so I wrote a loop code which sends words to the data register without that command.
OK Here is the code I wrote in pascal:
uses ...;
var
RawData:array[0..255] of Word;
ATA_INDEX:Integer;
implementation
//...
function DiskReadSector(Drive,Head,Cylinder,SecNum:integer):Integer;stdcall;
var
xstat:Word;
i:integer;
BaseAdress:Word;
begin
if ATA_INDEX=0 then
BaseAdress:=$1f0 else
BaseAdress:=$170;
outb(BaseAdress+6,$0a0 or (Drive shl 4) or head);
outb(BaseAdress+2,1);//Count
outb(BaseAdress+3,SecNum);// Sector Number
outb(BaseAdress+4,Cylinder and $00FF);//LOW Cylinder
outb(BaseAdress+5,Cylinder shr 8);//HIGH Cylinder
outb(BaseAdress+7,$20);//READ COMMAND $30 for WRITE
asm //CHECK FOR DATA READY
mov dx,1f7h
@still_going:
in al,dx
test al,8
jz @still_going
end;
for i:=0 to 255 do begin //COPY DATA TO WORD ARRAY
xstat:=inw(BaseAdress);
RawData[i]:=xstat;
end;
DiskReadSector:=inb(BaseAdress+7);//DEBUG
end
Usage:
procedure kmain;stdcall;[public,alias:'kmain'];
begin
//...
ATA_INDEX:=0;//Zero for Primary Others for Secondary
DiskReadSector(0,0,0,1);//Drive 0 for Master 1 for Slave Example:
//ATA_INDEX=0 and Drive=0 it means Primary Master
//This Code Will Read Master Boot Record of IDE Primary Master
//a simple check for boot signature of first sector at primary master:
if RawData[255]=$AA55 then
WriteLn('Boot Signature Detected!');
end;