Search code examples
assemblyx86operating-systemdiskprotected-mode

Disk Read/Write Fault Using Ports in Assembly


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

Solution

  • 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;