We're having a few problems trying to get ATA to work.
My code is in O'Caml, so it might not be so clear to read, but I hope people can help me figure out what is wrong. I've followed the instructions in http://www.geocities.com/SiliconValley/2072/atapi.htm to implement an identify_drive command.
One thing I'm not clear on is what happens when there's no drive attached?
Anyways, it gets stuck in an infinite loop =/ Here's my code (a little big...):
Code: Select all
type controller = Primary | Secondary;;
type device = Master | Slave;;
let primary_base_address = 0x1F0
and secondary_base_address = 0x170;;
module Register = struct
let data = 0x0
let error = 0x1
let features = 0x1
let sector_count = 0x2
let lba_low = 0x3
let lba_mid = 0x4
let lba_high = 0x5
let device_head = 0x6
let status = 0x7
let command = 0x7
let alt_status = 0x206
let device_control = 0x206
end;;
module Status = struct
let busy v = v land 1 <> 0
let ready v = v land 2 <> 0
let fault v = v land 4 <> 0
let seek_complete v = v land 8 <> 0
let transfer_req v = v land 16 <> 0
let data_corrected v = v land 32 <> 0
let index_mark v = v land 64 <> 0
let error v = v land 128 <> 0
end;;
module Error = struct
let bad_block v = v land 1 <> 0
let uncorrectable_data v = v land 2 <> 0
let media_changed v = v land 4 <> 0
let id_mark_not_found v = v land 8 <> 0
let media_change_req v = v land 16 <> 0
let aborted v = v land 32 <> 0
let track_0_not_found v = v land 64 <> 0
let address_mark_not_found v = v land 128 <> 0
end;;
let rec poll f = if f () then () else poll f;;
let controller = function
| Primary -> primary_base_address
| Secondary -> secondary_base_address;;
let device = function
| Master -> 0x00
| Slave -> 0x10;;
let issue_command c command =
poll (fun () -> not (Status.busy (Asm.in8 (controller c + Register.status))));
Asm.cli ();
poll (fun () -> Status.ready (Asm.in8 (controller c + Register.status)));
let result = command () in
Asm.sti ();
result;;
let identify_drive c d =
let action = (fun () ->
Asm.out8 (controller c + Register.device_head) (device d);
Asm.out8 (controller c + Register.command) 0x0EC; (* identify drive *)
poll (fun () -> Status.ready (Asm.in8 (controller c + Register.status)));
Asm.insw (controller c + Register.data) 256
) in
issue_command c action;;
Code: Select all
Console.printf "IDE 0:0: %s\n" (IDE.identify_drive IDE.Primary IDE.Master);;
What is it that I'm doing wrong?
Jonathan