New working ATA PIO driver
This commit is contained in:
parent
837d69a44b
commit
920aca5bbf
@ -44,7 +44,7 @@ var
|
|||||||
function load(ptr: void) : boolean;
|
function load(ptr: void) : boolean;
|
||||||
procedure init();
|
procedure init();
|
||||||
function get_status(var device : TIDE_Device) : TIDE_Status;
|
function get_status(var device : TIDE_Device) : TIDE_Status;
|
||||||
function wait_for_device(device : TIDE_Device) : boolean;
|
function wait_for_device(device : TIDE_Device; ioop : boolean) : boolean;
|
||||||
procedure no_interrupt(isPrimary : boolean);
|
procedure no_interrupt(isPrimary : boolean);
|
||||||
procedure select_device(device : TIDE_Device);
|
procedure select_device(device : TIDE_Device);
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ end;
|
|||||||
@param(device The device to wait for)
|
@param(device The device to wait for)
|
||||||
@returns(@True if the device is ready, @False otherwise)
|
@returns(@True if the device is ready, @False otherwise)
|
||||||
}
|
}
|
||||||
function wait_for_device(device : TIDE_Device) : boolean;
|
function wait_for_device(device : TIDE_Device; ioop : boolean) : boolean;
|
||||||
var
|
var
|
||||||
status : TIDE_Status;
|
status : TIDE_Status;
|
||||||
i : uint32;
|
i : uint32;
|
||||||
@ -78,10 +78,10 @@ begin
|
|||||||
|
|
||||||
i := 0;
|
i := 0;
|
||||||
|
|
||||||
while (i < 10000) do begin
|
while (i < 50000) do begin
|
||||||
status := get_status(device);
|
status := get_status(device);
|
||||||
|
|
||||||
if (status.BUSY = false) then begin //todo test
|
if (status.BUSY = false) and (status.DRQ or (not ioop)) then begin //todo test
|
||||||
wait_for_device := true;
|
wait_for_device := true;
|
||||||
pop_trace();
|
pop_trace();
|
||||||
exit;
|
exit;
|
||||||
@ -127,17 +127,31 @@ end;
|
|||||||
function get_status(var device : TIDE_Device) : TIDE_Status;
|
function get_status(var device : TIDE_Device) : TIDE_Status;
|
||||||
var
|
var
|
||||||
status : TIDE_Status;
|
status : TIDE_Status;
|
||||||
|
errorReg : uint8;
|
||||||
begin
|
begin
|
||||||
push_trace('ide.get_status()');
|
push_trace('ide.get_status()');
|
||||||
|
|
||||||
select_device(device);
|
// select_device(device);
|
||||||
|
|
||||||
status := TIDE_Status(inb(device.base + ATA_REG_STATUS));
|
status := TIDE_Status(inb(device.base + ATA_REG_STATUS));
|
||||||
|
|
||||||
device.status := status;
|
device.status := status;
|
||||||
|
|
||||||
pop_trace();
|
if status.ERROR then begin
|
||||||
get_status := status;
|
errorReg := inb(device.base + ATA_REG_ERROR);
|
||||||
|
|
||||||
|
console.writestringln('[IDE] ERROR detected!');
|
||||||
|
console.writestring('[IDE] ERROR REGISTER: ');
|
||||||
|
console.writebin8ln(errorReg);
|
||||||
|
|
||||||
|
if (errorReg and $04) <> 0 then console.writestringln('[IDE] ERROR: Aborted Command');
|
||||||
|
if (errorReg and $10) <> 0 then console.writestringln('[IDE] ERROR: ID Not Found');
|
||||||
|
if (errorReg and $40) <> 0 then console.writestringln('[IDE] ERROR: Uncorrectable Data');
|
||||||
|
if (errorReg and $80) <> 0 then console.writestringln('[IDE] ERROR: Bad Block');
|
||||||
|
|
||||||
|
console.redrawWindows();
|
||||||
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -175,6 +189,19 @@ begin
|
|||||||
select_device(device);
|
select_device(device);
|
||||||
|
|
||||||
//TODO make sure dvice signture is set at this time, else reset it
|
//TODO make sure dvice signture is set at this time, else reset it
|
||||||
|
//reset any device signature
|
||||||
|
{
|
||||||
|
Write 0x04 to the Control Register (0x3F6 for primary bus, 0x376 for secondary).
|
||||||
|
Wait ~5 microseconds.
|
||||||
|
Write 0x00 back to Control Register to complete reset.
|
||||||
|
// }
|
||||||
|
outb(ATA_PRIMARY_BASE1, $04);
|
||||||
|
outb(ATA_SECONDARY_BASE1, $04);
|
||||||
|
sleep(1);
|
||||||
|
// outb(ATA_PRIMARY_BASE1, $00);
|
||||||
|
// outb(ATA_SECONDARY_BASE1, $00);
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
//read all bytes of LBA address
|
//read all bytes of LBA address
|
||||||
sec := inb(device.base + ATA_REG_SECCOUNT);
|
sec := inb(device.base + ATA_REG_SECCOUNT);
|
||||||
@ -182,14 +209,26 @@ begin
|
|||||||
lba1 := inb(device.base + ATA_REG_LBA1);
|
lba1 := inb(device.base + ATA_REG_LBA1);
|
||||||
lba2 := inb(device.base + ATA_REG_LBA2);
|
lba2 := inb(device.base + ATA_REG_LBA2);
|
||||||
|
|
||||||
//check if the device is an ATAPI device (01, 01, 14, EB)
|
console.writestring('[IDE] (check_device_type) SEC: ');
|
||||||
if (lba1 = $14) and (lba2 = $EB) then begin
|
console.writehexln(sec);
|
||||||
|
console.writestring('[IDE] (check_device_type) LBA0: ');
|
||||||
|
console.writehexln(lba0);
|
||||||
|
console.writestring('[IDE] (check_device_type) LBA1: ');
|
||||||
|
console.writehexln(lba1);
|
||||||
|
console.writestring('[IDE] (check_device_type) LBA2: ');
|
||||||
|
console.writehexln(lba2);
|
||||||
|
|
||||||
|
|
||||||
|
//check if the device is an ATAPI device
|
||||||
|
if ((sec = 3) or (lba2 = $EB)) then begin
|
||||||
check_device_type := true;
|
check_device_type := true;
|
||||||
|
device.isATAPI := true;
|
||||||
|
end else if sec = 1 then begin
|
||||||
|
check_device_type := true;
|
||||||
|
device.isATAPI := false;
|
||||||
end else begin
|
end else begin
|
||||||
check_device_type := false;
|
check_device_type := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
device.isATAPI := check_device_type;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -207,11 +246,12 @@ var
|
|||||||
begin
|
begin
|
||||||
|
|
||||||
push_trace('ide.load_device()');
|
push_trace('ide.load_device()');
|
||||||
|
success := check_device_type(device);
|
||||||
|
|
||||||
if (is_device_present(device)) then begin
|
if (is_device_present(device) and success) then begin
|
||||||
console.writestringln('[IDE] (load_device) Device is present');
|
console.writestringln('[IDE] (load_device) Device is present');
|
||||||
|
|
||||||
if (check_device_type(device)) then begin
|
if (device.isATAPI) then begin
|
||||||
console.writestringln('[IDE] (load_device) Device is ATAPI');
|
console.writestringln('[IDE] (load_device) Device is ATAPI');
|
||||||
//todo load device info
|
//todo load device info
|
||||||
end else begin
|
end else begin
|
||||||
@ -253,25 +293,27 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
//wrtie test, 1F2F1F2F repeated
|
//wrtie test, 1F2F1F2F repeated
|
||||||
buffer := puint8(kalloc(512));
|
buffer := puint8(kalloc(1024));
|
||||||
memset(uint32(buffer), 0, 512);
|
memset(uint32(buffer), $02, 1024);
|
||||||
for i:=0 to 200 do begin
|
|
||||||
if (i mod 4 = 0) then begin
|
uint8(buffer[0]) := $1F;
|
||||||
buffer[i] := $1F;
|
uint8(buffer[1]) := $2F;
|
||||||
end else begin
|
uint8(buffer[2]) := $3F;
|
||||||
buffer[i] := $2F;
|
uint8(buffer[3]) := $4F;
|
||||||
end;
|
uint8(buffer[4]) := $5F;
|
||||||
end;
|
uint8(buffer[5]) := $6F;
|
||||||
|
uint8(buffer[6]) := $7F;
|
||||||
|
uint8(buffer[7]) := $8F;
|
||||||
|
|
||||||
//write to the first sector
|
//write to the first sector
|
||||||
ata.write_pio28(device, 0, 1, puint16(buffer));
|
ata.write_pio28(device, 10, 2, puint16(buffer));
|
||||||
|
|
||||||
//read the first sector
|
//read the first sector
|
||||||
memset(uint32(buffer), 0, 512);
|
memset(uint32(buffer), 0, 512);
|
||||||
ata.read_pio28(device, 0, 1, puint16(buffer));
|
ata.read_pio28(device, 10, 1, puint16(buffer));
|
||||||
|
|
||||||
//check if the data is the same
|
//check if the data is the same
|
||||||
for i:=0 to 200 do begin
|
for i:=0 to 10 do begin
|
||||||
console.writehexln(buffer[i]);
|
console.writehexln(buffer[i]);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -30,6 +30,14 @@ implementation
|
|||||||
uses
|
uses
|
||||||
ide;
|
ide;
|
||||||
|
|
||||||
|
|
||||||
|
procedure outb(port : uint16; value : uint8);
|
||||||
|
begin
|
||||||
|
util.outb(port, value);
|
||||||
|
psleep(1);
|
||||||
|
// get_status(primaryDevices[0]);
|
||||||
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
ensure the address is a valid 28 bit address
|
ensure the address is a valid 28 bit address
|
||||||
|
|
||||||
@ -72,7 +80,7 @@ begin
|
|||||||
console.writestringln('Error identifying device, maybe'); //todo
|
console.writestringln('Error identifying device, maybe'); //todo
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ready := wait_for_device(device);
|
ready := wait_for_device(device, false);
|
||||||
|
|
||||||
if not ready then begin
|
if not ready then begin
|
||||||
console.writestringln('Device not ready in time!');
|
console.writestringln('Device not ready in time!');
|
||||||
@ -123,18 +131,26 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
select_device(device);
|
select_device(device);
|
||||||
|
psleep(50);
|
||||||
no_interrupt(device.isPrimary);
|
no_interrupt(device.isPrimary);
|
||||||
|
psleep(50);
|
||||||
set_lba_mode(device, lba);
|
set_lba_mode(device, lba);
|
||||||
|
psleep(50);
|
||||||
|
|
||||||
outb(device.base + ATA_REG_SECCOUNT, count);
|
outb(device.base + ATA_REG_SECCOUNT, count);
|
||||||
|
psleep(50);
|
||||||
|
|
||||||
outb(device.base + ATA_REG_LBA0, (lba and $000000FF));
|
outb(device.base + ATA_REG_LBA0, (lba and $000000FF));
|
||||||
|
psleep(50);
|
||||||
outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8);
|
outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8);
|
||||||
|
psleep(50);
|
||||||
outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16);
|
outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16);
|
||||||
|
psleep(50);
|
||||||
|
|
||||||
outb(device.base + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
outb(device.base + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
||||||
|
psleep(50);
|
||||||
|
|
||||||
ready := wait_for_device(device);
|
ready := wait_for_device(device, false);
|
||||||
|
|
||||||
if not ready then begin
|
if not ready then begin
|
||||||
console.writestringln('Device not ready in time!');
|
console.writestringln('Device not ready in time!');
|
||||||
@ -142,15 +158,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
for i:=0 to count-1 do begin
|
for i:=0 to count-1 do begin
|
||||||
for ii:=0 to 511 do begin //TODO needs to read sector size
|
ii:=0;
|
||||||
buffer[i] := inw(device.base + ATA_REG_DATA);
|
while ii < 256 do begin
|
||||||
|
buffer[ii+(i*256)] := inw(device.base + ATA_REG_DATA);
|
||||||
ready := wait_for_device(device);
|
ii := ii + 1;
|
||||||
|
psleep(50);
|
||||||
if not ready then begin
|
|
||||||
console.writestringln('Device not ready in time!');
|
|
||||||
BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR READ');
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -175,17 +187,16 @@ begin
|
|||||||
|
|
||||||
select_device(device);
|
select_device(device);
|
||||||
no_interrupt(device.isPrimary); //maybe not?
|
no_interrupt(device.isPrimary); //maybe not?
|
||||||
|
|
||||||
set_lba_mode(device, lba);
|
set_lba_mode(device, lba);
|
||||||
|
|
||||||
|
|
||||||
outb(device.base + ATA_REG_SECCOUNT, count);
|
outb(device.base + ATA_REG_SECCOUNT, count);
|
||||||
outb(device.base + ATA_REG_LBA0, (lba and $000000FF));
|
outb(device.base + ATA_REG_LBA0, (lba and $000000FF));
|
||||||
outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8);
|
outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8);
|
||||||
outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16);
|
outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16);
|
||||||
|
|
||||||
outb(device.base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
outb(device.base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
||||||
|
|
||||||
ready := wait_for_device(device);
|
ready := wait_for_device(device, false);
|
||||||
|
|
||||||
if not ready then begin
|
if not ready then begin
|
||||||
console.writestringln('Device not ready in time!');
|
console.writestringln('Device not ready in time!');
|
||||||
@ -193,21 +204,23 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
for i:=0 to count-1 do begin
|
for i:=0 to count-1 do begin
|
||||||
for ii:=0 to 511 do begin //TODO needs to read sector size
|
ii:=0;
|
||||||
outw(device.base + ATA_REG_DATA, uint16(buffer[i]));
|
while ii < 256 do begin
|
||||||
|
outw(ATA_PRIMARY_BASE + ATA_REG_DATA, buffer[ii+(i*256)]);
|
||||||
|
ii := ii + 1;
|
||||||
|
psleep(50);
|
||||||
|
end;
|
||||||
|
|
||||||
ready := wait_for_device(device);
|
psleep(50); //todo check
|
||||||
|
outb(device.base + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
|
||||||
|
ready := wait_for_device(device, false);
|
||||||
|
|
||||||
if not ready then begin
|
if not ready then begin
|
||||||
console.writestringln('Device not ready in time!');
|
console.writestringln('Device not ready in time!');
|
||||||
BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR WRITE');
|
BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR WRITE');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
psleep(50); //todo check
|
|
||||||
outb(device.base + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
|
|
||||||
ready := wait_for_device(device);
|
|
||||||
|
|
||||||
// if not ready then begin
|
// if not ready then begin
|
||||||
// console.writestringln('Device not ready in time!');
|
// console.writestringln('Device not ready in time!');
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
unit atapi;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
util,
|
||||||
|
drivertypes,
|
||||||
|
console,
|
||||||
|
terminal,
|
||||||
|
drivermanagement,
|
||||||
|
vmemorymanager,
|
||||||
|
lmemorymanager,
|
||||||
|
storagemanagement,
|
||||||
|
strings,
|
||||||
|
tracer,
|
||||||
|
drivemanager,
|
||||||
|
storagetypes,
|
||||||
|
idetypes;
|
||||||
|
|
||||||
|
var
|
||||||
|
|
||||||
|
test : uint32;
|
||||||
|
|
||||||
|
function identify_device(var device : TIDE_Device) : Boolean;
|
||||||
|
function read_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||||
|
function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||||
|
|
||||||
|
|
||||||
|
implementation
|
||||||
|
uses
|
||||||
|
ide;
|
||||||
|
|
||||||
|
{
|
||||||
|
Identify the device on the IDE bus
|
||||||
|
|
||||||
|
@param(device The device to identify)
|
||||||
|
@returns(@True if the device is identified, @False otherwise)
|
||||||
|
}
|
||||||
|
function identify_device(var device : TIDE_Device) : Boolean;
|
||||||
|
var
|
||||||
|
i : uint8;
|
||||||
|
status : TIDE_Status;
|
||||||
|
buffer : TIdentResponse;
|
||||||
|
ready : boolean;
|
||||||
|
begin
|
||||||
|
select_device(device);
|
||||||
|
no_interrupt(device.isPrimary);
|
||||||
|
|
||||||
|
status := get_status(device);
|
||||||
|
|
||||||
|
outb(device.base + ATA_REG_SECCOUNT, 0);
|
||||||
|
outb(device.base + ATA_REG_LBA0, 0);
|
||||||
|
outb(device.base + ATA_REG_LBA1, 0);
|
||||||
|
outb(device.base + ATA_REG_LBA2, 0);
|
||||||
|
|
||||||
|
psleep(1);
|
||||||
|
|
||||||
|
outb(device.base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
|
||||||
|
|
||||||
|
status := get_status(device);
|
||||||
|
|
||||||
|
if status.ERROR then begin
|
||||||
|
console.writestringln('Error identifying device, maybe'); //todo
|
||||||
|
end;
|
||||||
|
|
||||||
|
ready := wait_for_device(device, false);
|
||||||
|
|
||||||
|
if not ready then begin
|
||||||
|
console.writestringln('Device not ready in time!');
|
||||||
|
//teapot time
|
||||||
|
// BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR IDENT');
|
||||||
|
exit(false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i:=0 to 255 do begin
|
||||||
|
buffer[i] := inw(device.base + ATA_REG_DATA);
|
||||||
|
end;
|
||||||
|
|
||||||
|
device.info := @buffer;
|
||||||
|
|
||||||
|
identify_device := true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function read_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||||
|
var
|
||||||
|
i : uint16;
|
||||||
|
ii : uint16;
|
||||||
|
status : TIDE_Status;
|
||||||
|
ready : boolean;
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||||
|
var
|
||||||
|
i : uint16;
|
||||||
|
ii : uint16;
|
||||||
|
status : TIDE_Status;
|
||||||
|
ready : boolean;
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
@ -84,7 +84,7 @@ const
|
|||||||
ATA_REG_LBA3 = $09;
|
ATA_REG_LBA3 = $09;
|
||||||
ATA_REG_LBA4 = $0A;
|
ATA_REG_LBA4 = $0A;
|
||||||
ATA_REG_LBA5 = $0B;
|
ATA_REG_LBA5 = $0B;
|
||||||
ATA_REG_CONTROL = $0C;
|
ATA_REG_CONTROL = $0C; //1FC on some systems, 3F6 on all
|
||||||
ATA_REG_ALTSTATUS = $0C;
|
ATA_REG_ALTSTATUS = $0C;
|
||||||
ATA_REG_DEVADDRESS = $0D;
|
ATA_REG_DEVADDRESS = $0D;
|
||||||
|
|
||||||
@ -134,6 +134,13 @@ type
|
|||||||
info : PIdentResponse;
|
info : PIdentResponse;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TIDE_PACKET = record
|
||||||
|
command : uint8;
|
||||||
|
lba : uint32;
|
||||||
|
count : uint8;
|
||||||
|
buffer : puint16;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
@ -335,6 +335,7 @@ begin
|
|||||||
//serial.sendString('[outb]');
|
//serial.sendString('[outb]');
|
||||||
//serial.sendHex(port);
|
//serial.sendHex(port);
|
||||||
//serial.sendHex(val);
|
//serial.sendHex(val);
|
||||||
|
psleep(1);
|
||||||
asm
|
asm
|
||||||
PUSH EAX
|
PUSH EAX
|
||||||
PUSH EDX
|
PUSH EDX
|
||||||
|
Loading…
x
Reference in New Issue
Block a user