Cleanup
This commit is contained in:
parent
babe4290e4
commit
a2f6d7e76d
@ -50,6 +50,7 @@ function send_read_dma(device : PAHCI_Device; lba : uint64; count : uint32; buff
|
|||||||
function send_write_dma(device : PAHCI_Device; lba : uint64; count : uint32; buffer : puint32) : boolean;
|
function send_write_dma(device : PAHCI_Device; lba : uint64; count : uint32; buffer : puint32) : boolean;
|
||||||
function read_atapi(device : PAHCI_Device; lba : uint64; count : uint32; buffer : puint32) : boolean;
|
function read_atapi(device : PAHCI_Device; lba : uint64; count : uint32; buffer : puint32) : boolean;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
procedure init();
|
procedure init();
|
||||||
@ -113,8 +114,44 @@ begin
|
|||||||
|
|
||||||
// Clear the SERR register by writing 1s to it.
|
// Clear the SERR register by writing 1s to it.
|
||||||
port^.sata_error := $FFFFFFFF;
|
port^.sata_error := $FFFFFFFF;
|
||||||
|
|
||||||
|
start_port(port);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// procedure reset_port(port : PHBA_Port);
|
||||||
|
// var
|
||||||
|
// ssts, serr, timeout : uint32;
|
||||||
|
// begin
|
||||||
|
// console.writestringln('AHCI: Performing a full port reset.');
|
||||||
|
|
||||||
|
// port^.cmd := port^.cmd and not $1;
|
||||||
|
|
||||||
|
// // Wait until CR (bit 15) is cleared.
|
||||||
|
// timeout := 0;
|
||||||
|
// while (port^.cmd and $8000) <> 0 do begin
|
||||||
|
// timeout := timeout + 1;
|
||||||
|
// if timeout > 1000000 then begin
|
||||||
|
// console.writestringln('AHCI: Port reset timeout.');
|
||||||
|
// break;
|
||||||
|
// end;
|
||||||
|
// end;
|
||||||
|
|
||||||
|
// port^.sata_ctrl := port^.sata_ctrl and $FFFF0000;
|
||||||
|
// port^.sata_ctrl := port^.sata_ctrl or $1;
|
||||||
|
// psleep(10);
|
||||||
|
// port^.sata_ctrl := port^.sata_ctrl and $FFFF0000;
|
||||||
|
|
||||||
|
// while (port^.sata_status and $F) <> $3 do begin
|
||||||
|
// //wait for the port to be ready
|
||||||
|
// end;
|
||||||
|
|
||||||
|
// // Clear the SERR register by writing 1s to it.
|
||||||
|
// port^.sata_error := $FFFFFFFF;
|
||||||
|
|
||||||
|
// // start_port(port);
|
||||||
|
// end;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Check the ports on the controller and setup the command list, FIS, and command table
|
Check the ports on the controller and setup the command list, FIS, and command table
|
||||||
}
|
}
|
||||||
@ -229,7 +266,6 @@ begin
|
|||||||
|
|
||||||
//reset the port
|
//reset the port
|
||||||
reset_port(port);
|
reset_port(port);
|
||||||
start_port(port);
|
|
||||||
|
|
||||||
//print sata status
|
//print sata status
|
||||||
console.writestring('AHCI: sata status: ');
|
console.writestring('AHCI: sata status: ');
|
||||||
@ -383,19 +419,23 @@ begin
|
|||||||
|
|
||||||
console.writestringln('');
|
console.writestringln('');
|
||||||
|
|
||||||
buffer := puint32(kalloc(512));
|
buffer := puint32(kalloc(2048));
|
||||||
memset(uint32(buffer), 0, 512);
|
memset(uint32(buffer), 0, 2048);
|
||||||
|
|
||||||
//send a read DMA command to the device
|
//send a read DMA command to the device
|
||||||
if isATAPI then begin
|
if isATAPI then begin
|
||||||
read_atapi(device, 16, 512, buffer);
|
read_atapi(device, 0, 2048, buffer);
|
||||||
end else begin
|
end else begin
|
||||||
send_read_dma(device, 10, 512, buffer);
|
memset(uint32(buffer), $77, 2048);
|
||||||
|
send_write_dma(device, 22, 512, buffer);
|
||||||
|
memset(uint32(buffer), 0, 2048);
|
||||||
|
|
||||||
|
send_read_dma(device, 22, 512, buffer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//print the buffer
|
//print the buffer
|
||||||
for i:=0 to 63 do begin
|
for i:=0 to 63 do begin
|
||||||
console.writehex(uint32(buffer[i]));
|
console.writehex(puInt8(buffer)[i]);
|
||||||
console.writestring(' ');
|
console.writestring(' ');
|
||||||
end;
|
end;
|
||||||
console.writestringln('');
|
console.writestringln('');
|
||||||
@ -536,7 +576,6 @@ begin
|
|||||||
console.writestringln('AHCI: Sending read DMA command');
|
console.writestringln('AHCI: Sending read DMA command');
|
||||||
|
|
||||||
reset_port(device^.port);
|
reset_port(device^.port);
|
||||||
start_port(device^.port);
|
|
||||||
|
|
||||||
//prdt count is 22 bits
|
//prdt count is 22 bits
|
||||||
prdt_count := (count div 4194304) + 1;
|
prdt_count := (count div 4194304) + 1;
|
||||||
@ -647,7 +686,6 @@ begin
|
|||||||
console.writestringln('AHCI: Sending write DMA command');
|
console.writestringln('AHCI: Sending write DMA command');
|
||||||
|
|
||||||
reset_port(device^.port);
|
reset_port(device^.port);
|
||||||
start_port(device^.port);
|
|
||||||
|
|
||||||
//prdt count is 22 bits
|
//prdt count is 22 bits
|
||||||
prdt_count := (count div 4194304) + 1;
|
prdt_count := (count div 4194304) + 1;
|
||||||
@ -688,6 +726,8 @@ begin
|
|||||||
fis^.command := ATA_CMD_WRITE_DMA_EXT;
|
fis^.command := ATA_CMD_WRITE_DMA_EXT;
|
||||||
fis^.device := $40; // LBA mode 48?
|
fis^.device := $40; // LBA mode 48?
|
||||||
|
|
||||||
|
count:= count div 512;
|
||||||
|
|
||||||
fis^.lba0 := lba and $FF;
|
fis^.lba0 := lba and $FF;
|
||||||
fis^.lba1 := (
|
fis^.lba1 := (
|
||||||
lba shr 8) and $FF;
|
lba shr 8) and $FF;
|
||||||
@ -764,7 +804,6 @@ begin
|
|||||||
console.writestringln('AHCI: Sending read ATAPI command');
|
console.writestringln('AHCI: Sending read ATAPI command');
|
||||||
|
|
||||||
reset_port(device^.port);
|
reset_port(device^.port);
|
||||||
start_port(device^.port);
|
|
||||||
|
|
||||||
//prdt count is 22 bits
|
//prdt count is 22 bits
|
||||||
prdt_count := (count div 4194304) + 1;
|
prdt_count := (count div 4194304) + 1;
|
||||||
@ -781,12 +820,13 @@ begin
|
|||||||
cmd_header^.wrt := 0;
|
cmd_header^.wrt := 0;
|
||||||
cmd_header^.prdtl := 1;
|
cmd_header^.prdtl := 1;
|
||||||
cmd_header^.atapi := 1;
|
cmd_header^.atapi := 1;
|
||||||
|
cmd_header^.clear_busy := 1;
|
||||||
|
|
||||||
// Setup the command table (using slot 0)
|
// Setup the command table (using slot 0)
|
||||||
cmd_table := PHBA_CMD_TABLE(uint32(device^.command_table) + (slot * sizeof(THBA_CMD_TABLE)));
|
cmd_table := PHBA_CMD_TABLE(uint32(device^.command_table) + (slot * sizeof(THBA_CMD_TABLE)));
|
||||||
|
|
||||||
cmd_table^.prdt[0].dba := vtop(uint32(buffer));
|
cmd_table^.prdt[0].dba := vtop(uint32(buffer));
|
||||||
cmd_table^.prdt[0].dbc := 512 - 1; // 512 bytes (0-based count
|
cmd_table^.prdt[0].dbc := 2048 - 1; // 512 bytes (0-based count
|
||||||
cmd_table^.prdt[0].int := 1; // Interrupt on completion
|
cmd_table^.prdt[0].int := 1; // Interrupt on completion
|
||||||
|
|
||||||
// Construct the Command FIS in the command table's CFIS area
|
// Construct the Command FIS in the command table's CFIS area
|
||||||
@ -795,7 +835,7 @@ begin
|
|||||||
fis^.fis_type := uint8(FIS_TYPE_REG_H2D);
|
fis^.fis_type := uint8(FIS_TYPE_REG_H2D);
|
||||||
fis^.c := $1;
|
fis^.c := $1;
|
||||||
fis^.command := ATA_CMD_PACKET;
|
fis^.command := ATA_CMD_PACKET;
|
||||||
fis^.device := $A0; // LBA mode 48?
|
fis^.device := $A0;
|
||||||
|
|
||||||
fis^.featurel := fis^.featurel or 1; //setting both of these might not work on real hardware
|
fis^.featurel := fis^.featurel or 1; //setting both of these might not work on real hardware
|
||||||
fis^.featurel := fis^.featurel or (1 shl 2);
|
fis^.featurel := fis^.featurel or (1 shl 2);
|
||||||
|
@ -1,296 +0,0 @@
|
|||||||
// // Copyright 2021 Aaron Hance
|
|
||||||
// //
|
|
||||||
// // Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// // you may not use this file except in compliance with the License.
|
|
||||||
// // You may obtain a copy of the License at
|
|
||||||
// //
|
|
||||||
// // http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
// //
|
|
||||||
// // Unless required by applicable law or agreed to in writing, software
|
|
||||||
// // distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// // See the License for the specific language governing permissions and
|
|
||||||
// // limitations under the License.
|
|
||||||
|
|
||||||
// {
|
|
||||||
// Drivers->Storage->AHCI - AHCI SATA Driver.
|
|
||||||
|
|
||||||
// @author(Aaron Hance <ah@aaronhance.me>)
|
|
||||||
// }
|
|
||||||
// unit AHCI;
|
|
||||||
|
|
||||||
// interface
|
|
||||||
|
|
||||||
// uses
|
|
||||||
// util,
|
|
||||||
// PCI,
|
|
||||||
// drivertypes,
|
|
||||||
// drivermanagement,
|
|
||||||
// lmemorymanager,
|
|
||||||
// console,
|
|
||||||
// vmemorymanager;
|
|
||||||
|
|
||||||
// type
|
|
||||||
|
|
||||||
// //Struct hell
|
|
||||||
|
|
||||||
// TFIS_Type = (
|
|
||||||
// REG_H2D = $27,
|
|
||||||
// REG_D2H = $34,
|
|
||||||
// DMA_ACT = $39,
|
|
||||||
// DMA_SETUP = $41,
|
|
||||||
// DATA = $46,
|
|
||||||
// BIST = $58,
|
|
||||||
// PIO_SETUP = $5F,
|
|
||||||
// DEV_BITS = $A0
|
|
||||||
// );
|
|
||||||
|
|
||||||
// PFIS_REG_H2D = ^TFIS_REG_H2D;
|
|
||||||
// TFIS_REG_H2D = bitpacked record
|
|
||||||
// fis_type : uint8;
|
|
||||||
// port_mult : UBit4;
|
|
||||||
// rsv0 : UBit3;
|
|
||||||
// coc : boolean;
|
|
||||||
// command : uint8;
|
|
||||||
// feature_low : uint8;
|
|
||||||
// lba0 : uint8;
|
|
||||||
// lba1 : uint8;
|
|
||||||
// lba2 : uint8;
|
|
||||||
// device : uint8;
|
|
||||||
// lba3 : uint8;
|
|
||||||
// lba4 : uint8;
|
|
||||||
// lba5 : uint8;
|
|
||||||
// feature_high : uint8;
|
|
||||||
// count_low : uint8;
|
|
||||||
// count_high : uint8;
|
|
||||||
// icc : uint8;
|
|
||||||
// control : uint8;
|
|
||||||
// rsvl : uint32;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// TFIS_REG_D2H = bitpacked record
|
|
||||||
// fis_type : uint8;
|
|
||||||
// port_mult : UBit4;
|
|
||||||
// rsv0 : UBit2;
|
|
||||||
// i : boolean;
|
|
||||||
// rsvl : boolean;
|
|
||||||
// status : uint8;
|
|
||||||
// error : uint8;
|
|
||||||
// lba0 : uint8;
|
|
||||||
// lba1 : uint8;
|
|
||||||
// lba2 : uint8;
|
|
||||||
// device : uint8;
|
|
||||||
// lba3 : uint8;
|
|
||||||
// lba4 : uint8;
|
|
||||||
// lba5 : uint8;
|
|
||||||
// rsv2 : uint8;
|
|
||||||
// count_low : uint8;
|
|
||||||
// count_high : uint8;
|
|
||||||
// rsv3 : uint16;
|
|
||||||
// rsv4 : uint32;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// TFIS_Data = bitpacked record
|
|
||||||
// fis_type : uint8;
|
|
||||||
// port_mult : UBit4;
|
|
||||||
// rsv0 : UBit4;
|
|
||||||
// rsv1 : uint16;
|
|
||||||
// data : ^uint32;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// TFIS_PIO_Setup = bitpacked record
|
|
||||||
// fis_type : uint8;
|
|
||||||
// pmport : UBit4;
|
|
||||||
// rsv0 : boolean;
|
|
||||||
// d : boolean;
|
|
||||||
// i : boolean;
|
|
||||||
// rsv1 : boolean;
|
|
||||||
// status : uint8;
|
|
||||||
// error : uint8;
|
|
||||||
// lba0 : uint8;
|
|
||||||
// lba1 : uint8;
|
|
||||||
// lba2 : uint8;
|
|
||||||
// device : uint8;
|
|
||||||
// lba3 : uint8;
|
|
||||||
// lba4 : uint8;
|
|
||||||
// lba5 : uint8;
|
|
||||||
// rsv2 : uint8;
|
|
||||||
// countl : uint8;
|
|
||||||
// counth : uint8;
|
|
||||||
// rsv3 : uint8;
|
|
||||||
// e_status : uint8;
|
|
||||||
// tc : uint16;
|
|
||||||
// rsv4 : uint16;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// // TFIS_DMA_Setup = bitpacked record
|
|
||||||
// // end;
|
|
||||||
|
|
||||||
// // THBA_Memory = bitpacked record
|
|
||||||
// // end;
|
|
||||||
|
|
||||||
// // THBA_Port = bitpacked record
|
|
||||||
// // end;
|
|
||||||
|
|
||||||
// // THBA_FIS = bitpacked record
|
|
||||||
// // end;
|
|
||||||
|
|
||||||
// PHBA_PORT = ^THBA_PORT;
|
|
||||||
// THBA_PORT = bitpacked record
|
|
||||||
// clb : uint32;
|
|
||||||
// clbu : uint32;
|
|
||||||
// fb : uint32;
|
|
||||||
// fbu : uint32;
|
|
||||||
// istat : uint32;
|
|
||||||
// ie : uint32;
|
|
||||||
// cmd : uint32;
|
|
||||||
// rsv0 : uint32;
|
|
||||||
// tfd : uint32;
|
|
||||||
// sig : uint32;
|
|
||||||
// ssts : uint32;
|
|
||||||
// sctl : uint32;
|
|
||||||
// serr : uint32;
|
|
||||||
// sact : uint32;
|
|
||||||
// ci : uint32;
|
|
||||||
// sntf : uint32;
|
|
||||||
// fbs : uint32;
|
|
||||||
// rsv1 : array[0..11] of uint32;
|
|
||||||
// vendor : array[0..4] of uint32;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// THBA_MEM = bitpacked record
|
|
||||||
// cap : uint32; //0
|
|
||||||
// global_host_control : uint32; //4
|
|
||||||
// interrupt_status : uint32; //8
|
|
||||||
// port_implemented : uint32; //c
|
|
||||||
// version : uint32; //10
|
|
||||||
// ccc_control : uint32; //14
|
|
||||||
// ccc_ports : uint32; //18
|
|
||||||
// em_location : uint32; //1c
|
|
||||||
// em_Control : uint32; //20
|
|
||||||
// hcap2 : uint32; //24
|
|
||||||
// bohc : uint32; //28
|
|
||||||
// rsv0 : array[0..210] of boolean;
|
|
||||||
// ports : array[0..31] of THBA_Port;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// PHBA = ^THBA_MEM;
|
|
||||||
|
|
||||||
// PCMDHeader = ^ TCommand_Header;
|
|
||||||
// TCommand_Header = bitpacked record
|
|
||||||
// cfl : ubit5;
|
|
||||||
// a : boolean;
|
|
||||||
// w : boolean;
|
|
||||||
// p : boolean;
|
|
||||||
// r : boolean;
|
|
||||||
// b : boolean;
|
|
||||||
// c : boolean;
|
|
||||||
// rsv0 : boolean;
|
|
||||||
// pmp : ubit4;
|
|
||||||
// PRDTL : uint16;
|
|
||||||
// PRDTBC : uint32;
|
|
||||||
// CTBA : uint32;
|
|
||||||
// CTBAU : uint32;
|
|
||||||
// rsv1 : array[0..3] of uint32;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// TPRD_Entry = bitpacked record
|
|
||||||
// data_base_address : uint32;
|
|
||||||
// data_bade_address_U : uint32;
|
|
||||||
// rsv0 : uint32;
|
|
||||||
// data_byte_count : ubit22;
|
|
||||||
// rsv1 : ubit9;
|
|
||||||
// interrupt_oc : boolean;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// PCommand_Table = ^TCommand_Table;
|
|
||||||
// TCommand_Table = bitpacked record
|
|
||||||
// cfis : array[0..64] of uint8;
|
|
||||||
// acmd : array[0..16] of uint8;
|
|
||||||
// rsv : array[0..48] of uint8;
|
|
||||||
// prdt : array[0..7] of TPRD_Entry;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// TSataDevice = record
|
|
||||||
// controller : uint8;
|
|
||||||
// port : uint8;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// var
|
|
||||||
// //constants
|
|
||||||
// //SATA_SIG_ATA := $101;
|
|
||||||
// //SATA_SIG_ATAPI := $EB140101;
|
|
||||||
// //STA_SIG_SEMB := $C33C0101;
|
|
||||||
// //STAT_SIG_PM := $96690101;
|
|
||||||
// AHCI_BASE: uint32 = $400000; //irrelivent
|
|
||||||
|
|
||||||
// //other
|
|
||||||
// ahciControllers : array[0.16] of PuInt32;
|
|
||||||
// ahciControllerCount : uint8 = 0;
|
|
||||||
// hba : array[0..16] of PHBA;
|
|
||||||
|
|
||||||
// sataDevices : array[0..127] of TSataDevice;
|
|
||||||
// sataDeviceCount : uint8;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// procedure init();
|
|
||||||
// procedure check_ports(controller : uint8);
|
|
||||||
// procedure enable_cmd(port : uint8);
|
|
||||||
// procedure disable_cmd(port : uint8);
|
|
||||||
// procedure port_rebase(port : uint8);
|
|
||||||
// function load(ptr:void): boolean;
|
|
||||||
// function read(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
|
|
||||||
// function write(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
|
|
||||||
// function find_cmd_slot(port : uint8) : uint32;
|
|
||||||
|
|
||||||
// implementation
|
|
||||||
|
|
||||||
// procedure init();
|
|
||||||
// var
|
|
||||||
// devID : TDeviceIdentifier;
|
|
||||||
// begin
|
|
||||||
// console.writestringln('AHCI: Registering driver');
|
|
||||||
// devID.bus:= biPCI;
|
|
||||||
// devID.id0:= idANY;
|
|
||||||
// devID.id1:= $00000001;
|
|
||||||
// devID.id2:= $00000006;
|
|
||||||
// devID.id3:= $00000001;
|
|
||||||
// devID.id4:= idANY;
|
|
||||||
// devID.ex:= nil;
|
|
||||||
// drivermanagement.register_driver('AHCI Driver', @devID, @load);
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// procedure load(ptr : void);
|
|
||||||
// begin
|
|
||||||
// console.writestringln('AHCI: initilizing a new controller');
|
|
||||||
// ahciControllers[ahciControllerCount] := ptr;
|
|
||||||
// hba[ahciControllerCount] := PPCI_Device(ptr)^.address5;
|
|
||||||
// new_page_at_address(hba[ahciControllerCount]);
|
|
||||||
|
|
||||||
// //here would be any controller setup needed
|
|
||||||
|
|
||||||
// check_ports(ahciControllerCount);
|
|
||||||
// ahciControllerCount += 1;
|
|
||||||
// exit(true);
|
|
||||||
// end;
|
|
||||||
|
|
||||||
// procedure check_ports(controller : uint8);
|
|
||||||
// var
|
|
||||||
// d : uint32 = 1;
|
|
||||||
// i : uint32;
|
|
||||||
// begin
|
|
||||||
// for i:=0 to 31 do begin
|
|
||||||
// if (d > 0) and (hba[controller]^.port_implemented shr i) = 1 then begin
|
|
||||||
// if (hba[controller]^.ports[i].ssts shr 8) <> 1 and (hba[controller]^.ports[i].ssts and $0F) <> 3 then begin
|
|
||||||
// if hba[controller]^.ports[i].sig = 1 then begin
|
|
||||||
// //device is sata
|
|
||||||
// sataDevices[sataDeviceCount].controller := controller;
|
|
||||||
// sataDevices[sataDeviceCount].port := i;
|
|
||||||
// sataDeviceCount += 1;
|
|
||||||
// end;
|
|
||||||
// //TODO implement ATAPI
|
|
||||||
// end;
|
|
||||||
// end;
|
|
||||||
// end;
|
|
||||||
// end;
|
|
@ -1,85 +0,0 @@
|
|||||||
// Copyright 2021 Aaron Hance
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
{
|
|
||||||
Drivers->Storage->ATA_ISR - Primary ATA IRQ.
|
|
||||||
|
|
||||||
@author(Aaron Hance <ah@aaronhance.me>)
|
|
||||||
}
|
|
||||||
unit ATA_ISR;
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
uses
|
|
||||||
util,
|
|
||||||
console,
|
|
||||||
isr_types,
|
|
||||||
isrmanager,
|
|
||||||
IDT;
|
|
||||||
|
|
||||||
procedure register();
|
|
||||||
procedure hook(hook_method : uint32);
|
|
||||||
procedure unhook(hook_method : uint32);
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
||||||
var
|
|
||||||
Hooks : Array[1..MAX_HOOKS] of pp_hook_method;
|
|
||||||
|
|
||||||
procedure Main(); interrupt;
|
|
||||||
var
|
|
||||||
i : integer;
|
|
||||||
|
|
||||||
begin
|
|
||||||
CLI;
|
|
||||||
for i:=0 to MAX_HOOKS-1 do begin
|
|
||||||
if uint32(Hooks[i]) <> 0 then Hooks[i](void($00000000));
|
|
||||||
end;
|
|
||||||
console.writestringln('Disk Operation Complete');
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure register();
|
|
||||||
begin
|
|
||||||
memset(uint32(@Hooks[0]), 0, sizeof(pp_hook_method)*MAX_HOOKS);
|
|
||||||
//isrmanager.registerISR(76, @Main);
|
|
||||||
//IDT.set_gate(76, uint32(@Main), $08, ISR_RING_0);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure hook(hook_method : uint32);
|
|
||||||
var
|
|
||||||
i : uint32;
|
|
||||||
|
|
||||||
begin
|
|
||||||
for i:=0 to MAX_HOOKS-1 do begin
|
|
||||||
if uint32(Hooks[i]) = hook_method then exit;
|
|
||||||
end;
|
|
||||||
for i:=0 to MAX_HOOKS-1 do begin
|
|
||||||
if uint32(Hooks[i]) = 0 then begin
|
|
||||||
Hooks[i]:= pp_hook_method(hook_method);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure unhook(hook_method : uint32);
|
|
||||||
var
|
|
||||||
i : uint32;
|
|
||||||
begin
|
|
||||||
for i:=0 to MAX_HOOKS-1 do begin
|
|
||||||
If uint32(Hooks[i]) = hook_method then Hooks[i]:= nil;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
@ -15,6 +15,8 @@
|
|||||||
{
|
{
|
||||||
Drivers->Storage->ide - IDE Driver.
|
Drivers->Storage->ide - IDE Driver.
|
||||||
|
|
||||||
|
NOT FINSIHED NEEDS WORK
|
||||||
|
|
||||||
@author(Aaron Hance <ah@aaronhance.me>)
|
@author(Aaron Hance <ah@aaronhance.me>)
|
||||||
}
|
}
|
||||||
unit ide;
|
unit ide;
|
||||||
|
@ -1,3 +1,27 @@
|
|||||||
|
// Copyright 2021 Aaron Hance
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
{
|
||||||
|
Drivers->Storage->ATAPI - ATAPI Driver.
|
||||||
|
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!! CURRENTLY NOT FUNCTIONAL !!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
@author(Aaron Hance <ah@aaronhance.me>)
|
||||||
|
}
|
||||||
|
|
||||||
unit atapi;
|
unit atapi;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
@ -1,504 +0,0 @@
|
|||||||
{ ************************************************
|
|
||||||
* Asuro
|
|
||||||
* Unit: Drivers/storage/IDE
|
|
||||||
* Description: IDE ATA Driver
|
|
||||||
*
|
|
||||||
************************************************
|
|
||||||
* Author: Aaron Hance
|
|
||||||
* Contributors:
|
|
||||||
************************************************ }
|
|
||||||
unit IDE;
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
uses
|
|
||||||
util,
|
|
||||||
drivertypes,
|
|
||||||
console,
|
|
||||||
terminal,
|
|
||||||
drivermanagement,
|
|
||||||
vmemorymanager,
|
|
||||||
lmemorymanager,
|
|
||||||
storagemanagement,
|
|
||||||
strings,
|
|
||||||
tracer,
|
|
||||||
drivemanager,
|
|
||||||
storagetypes;
|
|
||||||
|
|
||||||
type
|
|
||||||
TPortMode = (P_READ, P_WRITE);
|
|
||||||
|
|
||||||
TIdentResponse = array[0..255] of uint16;
|
|
||||||
|
|
||||||
TIDE_Channel_Registers = record
|
|
||||||
base : uint16;
|
|
||||||
ctrl : uint16;
|
|
||||||
bmide : uint16;
|
|
||||||
noInter : uint8
|
|
||||||
end;
|
|
||||||
|
|
||||||
TIDE_Device = record
|
|
||||||
exists : boolean;
|
|
||||||
isPrimary : boolean;
|
|
||||||
isMaster : boolean;
|
|
||||||
isATAPI : boolean;
|
|
||||||
info : TIdentResponse;
|
|
||||||
end;
|
|
||||||
|
|
||||||
TIDE_Status = bitpacked record
|
|
||||||
Busy : Boolean;
|
|
||||||
Ready : Boolean;
|
|
||||||
Fault : Boolean;
|
|
||||||
Seek : Boolean;
|
|
||||||
DRQ : Boolean;
|
|
||||||
CORR : Boolean;
|
|
||||||
IDDEX : Boolean;
|
|
||||||
ERROR : Boolean;
|
|
||||||
end;
|
|
||||||
PIDE_Status = ^TIDE_Status;
|
|
||||||
|
|
||||||
|
|
||||||
const
|
|
||||||
ATA_SR_BUSY = $80; //BUSY
|
|
||||||
ATA_SR_DRDY = $40; //DRIVE READY
|
|
||||||
ATA_SR_DF = $20; //DRIVE WRITE FAULT
|
|
||||||
ATA_SR_DSC = $10; //DRIVE SEEK COMPLETE
|
|
||||||
ATA_SR_DRQ = $08; //DATA REQUEST READY
|
|
||||||
ATA_SR_CORR = $04; //CORRECTED DATA
|
|
||||||
ATA_SR_IDX = $02; //INLEX
|
|
||||||
ATA_SR_ERR = $01; //ERROR
|
|
||||||
|
|
||||||
ATA_ER_BBK = $80; //BAD SECTOR
|
|
||||||
ATA_ER_UNC = $40; //UNCORRECTABLE DATA
|
|
||||||
ATA_ER_MC = $20; //NO MEDIA
|
|
||||||
ATA_ER_IDNF = $10; //ID MARK NOT FOUND
|
|
||||||
ATA_ER_MCR = $08; //NO MEDIA
|
|
||||||
ATA_ER_ABRT = $04; //COMMAND ABORTED
|
|
||||||
ATA_ER_TK0NF = $02; //TRACK 0 NOT FOUND
|
|
||||||
ATA_ER_AMNF = $01; //NO ADDRESS MARK
|
|
||||||
|
|
||||||
ATA_CMD_READ_PIO = $20;
|
|
||||||
ATA_CMD_READ_PIO_EXT = $24;
|
|
||||||
ATA_CMD_READ_DMA = $C8;
|
|
||||||
ATA_CMD_READ_DMA_EXT = $25;
|
|
||||||
ATA_CMD_WRITE_PIO = $30;
|
|
||||||
ATA_CMD_WRITE_PIO_EXT = $34;
|
|
||||||
ATA_CMD_WRITE_DMA = $CA;
|
|
||||||
ATA_CMD_WRITE_DMA_EXT = $35;
|
|
||||||
ATA_CMD_CACHE_FLUSH = $E7;
|
|
||||||
ATA_CMD_CACHE_FLUSH_EXT = $EA;
|
|
||||||
ATA_CMD_PACKET = $A0;
|
|
||||||
ATA_CMD_IDENTIFY_PACKET = $A1;
|
|
||||||
ATA_CMD_IDENTIFY = $EC;
|
|
||||||
|
|
||||||
ATAPI_CMD_READ = $A8;
|
|
||||||
ATAPI_CMD_EJECT = $1B;
|
|
||||||
|
|
||||||
ATA_IDENT_DEVICETYPE = $0;
|
|
||||||
ATA_IDENT_CYLINDERS = $2;
|
|
||||||
ATA_IDENT_HEADS = $6;
|
|
||||||
ATA_IDENT_SECOTRS = $12;
|
|
||||||
ATA_IDENT_SERIAL = $20;
|
|
||||||
ATA_IDENT_MODEL = $54;
|
|
||||||
ATA_IDENT_CAPABILITIES = $98;
|
|
||||||
ATA_IDENT_FIELDVALID = $106;
|
|
||||||
ATA_IDENT_MAX_LBA = $120;
|
|
||||||
ATA_IDENT_COMMANDSETS = $164;
|
|
||||||
ATA_IDENT_MAX_LBA_EXT = $200;
|
|
||||||
|
|
||||||
ATA_REG_DATA = $00;
|
|
||||||
ATA_REG_ERROR = $01;
|
|
||||||
ATA_REG_FEATURES = $01;
|
|
||||||
ATA_REG_SECCOUNT = $02;
|
|
||||||
ATA_REG_LBA0 = $03;
|
|
||||||
ATA_REG_LBA1 = $04;
|
|
||||||
ATA_REG_LBA2 = $05;
|
|
||||||
ATA_REG_HDDEVSEL = $06;
|
|
||||||
ATA_REG_COMMAND = $07;
|
|
||||||
ATA_REG_STATUS = $07;
|
|
||||||
ATA_REG_SECCOUNT1 = $08;
|
|
||||||
ATA_REG_LBA3 = $09;
|
|
||||||
ATA_REG_LBA4 = $0A;
|
|
||||||
ATA_REG_LBA5 = $0B;
|
|
||||||
ATA_REG_CONTROL = $0C;
|
|
||||||
ATA_REG_ALTSTATUS = $0C;
|
|
||||||
ATA_REG_DEVADDRESS = $0D;
|
|
||||||
|
|
||||||
ATA_DEVICE_MASTER = $A0;
|
|
||||||
ATA_DEVICE_SLAVE = $B0;
|
|
||||||
|
|
||||||
ATA_PRIMARY_BASE = $1F0;
|
|
||||||
|
|
||||||
var
|
|
||||||
controller : PPCI_Device;
|
|
||||||
|
|
||||||
bar0 : uint32;
|
|
||||||
bar1 : uint32;
|
|
||||||
bar4 : uint32;
|
|
||||||
|
|
||||||
IDEDevices : array[0..3] of TIDE_Device;
|
|
||||||
|
|
||||||
buffer : Puint32;
|
|
||||||
|
|
||||||
procedure init();
|
|
||||||
function load(ptr : void) : boolean;
|
|
||||||
function identify_device(bus : uint8; device : uint8) : TIdentResponse;
|
|
||||||
|
|
||||||
// procedure flush();
|
|
||||||
procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
|
||||||
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
|
||||||
//read/write must be capable of reading/writting any amknt of data upto disk size
|
|
||||||
|
|
||||||
procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
|
|
||||||
procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
||||||
function port_read(register : uint8) : uint8;
|
|
||||||
begin
|
|
||||||
port_read:= inb(ATA_PRIMARY_BASE + register);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure port_write(register : uint8; data : uint8);
|
|
||||||
var
|
|
||||||
i : uint8;
|
|
||||||
begin
|
|
||||||
outb(ATA_PRIMARY_BASE + register, data);
|
|
||||||
util.psleep(1);
|
|
||||||
if register = ATA_REG_COMMAND then begin
|
|
||||||
for i:= 0 to 5 do begin
|
|
||||||
port_read(ATA_REG_STATUS);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure no_interrupt(device : uint8);
|
|
||||||
begin
|
|
||||||
outb($3F6, inb($3f6) or (1 shl 1));
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure device_select(device : uint8);
|
|
||||||
begin
|
|
||||||
outb($1F6, device); //TODO clean
|
|
||||||
end;
|
|
||||||
|
|
||||||
function is_ready() : boolean;
|
|
||||||
var
|
|
||||||
status : uint8;
|
|
||||||
i : uint32;
|
|
||||||
begin
|
|
||||||
//wait for drive to be ready
|
|
||||||
while true do begin
|
|
||||||
status := port_read(ATA_REG_COMMAND);
|
|
||||||
|
|
||||||
if(status and ATA_SR_ERR) = ATA_SR_ERR then begin
|
|
||||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) DRIVE ERROR!');
|
|
||||||
console.redrawWindows();
|
|
||||||
is_ready := false;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (status and ATA_SR_BUSY) <> ATA_SR_BUSY then begin
|
|
||||||
is_ready := true;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function validate_28bit_address(addr : uint32) : boolean;
|
|
||||||
begin
|
|
||||||
validate_28bit_address := (addr and $F0000000) = 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function identify_device(bus : uint8; device : uint8) : TIdentResponse;
|
|
||||||
var
|
|
||||||
status : uint8;
|
|
||||||
identResponse : TIdentResponse;
|
|
||||||
i : uint8;
|
|
||||||
begin
|
|
||||||
push_trace('IDE.Identify_Device');
|
|
||||||
device_select(device);
|
|
||||||
no_interrupt(device);
|
|
||||||
port_write(ATA_REG_CONTROL, 0);
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) CHECK FLOATING BUS');
|
|
||||||
|
|
||||||
//check if bus is floating
|
|
||||||
status := port_read(ATA_REG_COMMAND);
|
|
||||||
if status = $FF then exit;
|
|
||||||
|
|
||||||
port_write(ATA_REG_SECCOUNT, 0);
|
|
||||||
port_write(ATA_REG_LBA0, 0);
|
|
||||||
port_write(ATA_REG_LBA1, 0);
|
|
||||||
port_write(ATA_REG_LBA2, 0);
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) SEND IDENTIFY COMMAND');
|
|
||||||
|
|
||||||
port_write(ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) WAIT FOR DRIVE TO BE READY');
|
|
||||||
|
|
||||||
//check if drive is present
|
|
||||||
status := port_read(ATA_REG_COMMAND);
|
|
||||||
if status = $00 then exit;
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) WAIT FOR DRIVE TO BE READY');
|
|
||||||
|
|
||||||
if not is_ready() then exit;
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) READ IDENTIFY RESPONSE');
|
|
||||||
|
|
||||||
for i:=0 to 255 do begin
|
|
||||||
console.writeint(i);
|
|
||||||
identResponse[i] := inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) IDENTIFY RESPONSE RECEIVED');
|
|
||||||
|
|
||||||
identify_device := identResponse;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure init();
|
|
||||||
var
|
|
||||||
devID : TDeviceIdentifier;
|
|
||||||
begin
|
|
||||||
push_trace('ide.init');
|
|
||||||
console.writestringln('[IDE] (INIT) BEGIN');
|
|
||||||
devID.bus:= biPCI;
|
|
||||||
devID.id0:= idANY;
|
|
||||||
devID.id1:= $00000001;
|
|
||||||
devID.id2:= $00000001;
|
|
||||||
devID.id3:= idANY;
|
|
||||||
devID.id4:= idANY;
|
|
||||||
devID.ex:= nil;
|
|
||||||
drivermanagement.register_driver('IDE ATA Driver', @devID, @load);
|
|
||||||
console.writestringln('[IDE] (INIT) END');
|
|
||||||
end;
|
|
||||||
|
|
||||||
function load(ptr : void) : boolean;
|
|
||||||
var
|
|
||||||
controller : PPCI_Device;
|
|
||||||
masterDevice : TStorage_Device;
|
|
||||||
slaveDevice : TStorage_Device;
|
|
||||||
buffer : puint8;
|
|
||||||
i : uint8;
|
|
||||||
test : PStorage_device;
|
|
||||||
tbuf : puint8;
|
|
||||||
begin
|
|
||||||
push_trace('ide.load');
|
|
||||||
console.writestringln('[IDE] (LOAD) BEGIN');
|
|
||||||
controller := PPCI_Device(ptr);
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (INIT) CHECK FLOATING BUS');
|
|
||||||
//check if bus is floating and identify device
|
|
||||||
if inb($1F7) <> $FF then begin
|
|
||||||
//outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts
|
|
||||||
IDEDevices[0].isMaster:= true;
|
|
||||||
IDEDevices[0].info := identify_device(0, ATA_DEVICE_MASTER);
|
|
||||||
e
|
|
||||||
mastrDevice.controller := ControllerIDE;
|
|
||||||
masterDevice.controllerId0:= 0;
|
|
||||||
masterDevice.maxSectorCount:= (IDEDevices[0].info[60] or (IDEDevices[0].info[61] shl 16) ); //LBA28 SATA
|
|
||||||
|
|
||||||
if IDEDevices[0].info[1] = 0 then begin
|
|
||||||
console.writestringln('[IDE] (INIT) ERROR: DEVICE IDENT FAILED!');
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]); //TODO wtf is hpc
|
|
||||||
|
|
||||||
masterDevice.sectorSize:= 512;
|
|
||||||
if masterDevice.maxSectorCount <> 0 then begin
|
|
||||||
IDEDevices[0].exists:= true;
|
|
||||||
masterDevice.readCallback:= @dread;
|
|
||||||
masterDevice.writeCallback:= @dwrite;
|
|
||||||
// storagemanagement.register_device(@masterDevice);
|
|
||||||
drivemanager.register_device(@masterDevice);
|
|
||||||
end;
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
// buffer:= puint8(kalloc(512));
|
|
||||||
// buffer[0] := 1;
|
|
||||||
// buffer[1] := 2;
|
|
||||||
// buffer[2] := 3;
|
|
||||||
// buffer[3] := 4;
|
|
||||||
// buffer[4] := 5;
|
|
||||||
// buffer[5] := 6;
|
|
||||||
// writePIO28(0, 3, buffer);
|
|
||||||
// writePIO28(0, 3, buffer);
|
|
||||||
// writePIO28(0, 3, buffer);
|
|
||||||
// writePIO28(0, 4, buffer);
|
|
||||||
// writePIO28(0, 5, buffer);
|
|
||||||
// writePIO28(0, 5, buffer);
|
|
||||||
// writePIO28(0, 5, buffer);
|
|
||||||
// psleep(1000);
|
|
||||||
// writePIO28(0, 5, buffer);
|
|
||||||
// writePIO28(0, 5, buffer);
|
|
||||||
// writePIO28(0, 5, buffer);
|
|
||||||
// kfree(puint32(buffer));
|
|
||||||
|
|
||||||
console.writestringln('[IDE] (LOAD) END');
|
|
||||||
|
|
||||||
//read first 16 bytes of disk
|
|
||||||
tbuf:= puint8(kalloc(512));
|
|
||||||
|
|
||||||
//set buffer to 1F1F repeating
|
|
||||||
for i:=0 to 200 do begin
|
|
||||||
tbuf[i] := 31;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//write buffer to disk
|
|
||||||
writePIO28(0, 0, tbuf);
|
|
||||||
|
|
||||||
memset(uint32(tbuf), 0, 512);
|
|
||||||
readPIO28(0, 0, puint8(tbuf));
|
|
||||||
console.writestringln('[IDE] (INIT) READ FIRST 4 BYTES OF DISK');
|
|
||||||
console.writehexln(tbuf[0]);
|
|
||||||
console.writehexln(tbuf[1]);
|
|
||||||
console.writehexln(tbuf[2]);
|
|
||||||
console.writehexln(tbuf[3]);
|
|
||||||
kfree(puint32(tbuf));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
|
||||||
var
|
|
||||||
status : uint8;
|
|
||||||
i: uint16;
|
|
||||||
device: uint8;
|
|
||||||
data: uint16;
|
|
||||||
begin
|
|
||||||
push_trace('IDE.readPIO28');
|
|
||||||
|
|
||||||
if not validate_28bit_address(LBA) then begin
|
|
||||||
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
|
||||||
end;
|
|
||||||
|
|
||||||
// push_trace('IDE.readPIO28.2');
|
|
||||||
|
|
||||||
//Add last 4 bits of LBA to device port
|
|
||||||
if IDEDevices[drive].isMaster then begin
|
|
||||||
device:= ATA_DEVICE_MASTER;
|
|
||||||
device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
device:= ATA_DEVICE_SLAVE;
|
|
||||||
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
|
||||||
end;
|
|
||||||
|
|
||||||
// push_trace('IDE.readPIO28.3');
|
|
||||||
|
|
||||||
no_interrupt(device);
|
|
||||||
port_write(ATA_REG_ERROR, 0);
|
|
||||||
|
|
||||||
//Write sector count and LBA
|
|
||||||
port_write(ATA_REG_SECCOUNT, 1);
|
|
||||||
port_write(ATA_REG_LBA0, (LBA and $000000FF));
|
|
||||||
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
|
||||||
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
|
||||||
|
|
||||||
// push_trace('IDE.readPIO28.4');
|
|
||||||
|
|
||||||
//send read command
|
|
||||||
port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
|
||||||
if not is_ready() then exit;
|
|
||||||
|
|
||||||
i:=0;
|
|
||||||
while i < 512 do begin
|
|
||||||
// if not is_ready() then exit;
|
|
||||||
|
|
||||||
data:= inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
|
|
||||||
|
|
||||||
buffer[i+1] := uint8($00ff and (data shr 8));
|
|
||||||
buffer[i] := uint8($00ff and data);
|
|
||||||
|
|
||||||
i:= i + 2;
|
|
||||||
|
|
||||||
if not is_ready() then exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// push_trace('IDE.readPIO28.5');
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
|
||||||
var
|
|
||||||
status : uint8;
|
|
||||||
i: uint16;
|
|
||||||
device: uint8;
|
|
||||||
begin
|
|
||||||
push_trace('IDE.WritePIO28');
|
|
||||||
if not validate_28bit_address(LBA) then begin
|
|
||||||
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writeintln(uint32(drive));
|
|
||||||
console.writeintln(LBA);
|
|
||||||
|
|
||||||
//Add last 4 bits of LBA to device port
|
|
||||||
if IDEDevices[drive].isMaster then begin
|
|
||||||
device:= ATA_DEVICE_MASTER;
|
|
||||||
device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
device:= ATA_DEVICE_SLAVE;
|
|
||||||
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
|
||||||
end;
|
|
||||||
|
|
||||||
// no_interrupt(device);
|
|
||||||
|
|
||||||
port_write(ATA_REG_ERROR, 0);
|
|
||||||
port_write(ATA_REG_CONTROL, 0);
|
|
||||||
|
|
||||||
// check if bus is floating
|
|
||||||
status := port_read(ATA_REG_COMMAND);
|
|
||||||
if status = $FF then exit;
|
|
||||||
|
|
||||||
//Write sector count and LBA
|
|
||||||
port_write(ATA_REG_SECCOUNT, 1);
|
|
||||||
port_write(ATA_REG_LBA0, (LBA and $000000FF));
|
|
||||||
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
|
||||||
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
|
||||||
|
|
||||||
//send write command
|
|
||||||
port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
|
||||||
|
|
||||||
//write data
|
|
||||||
i:=0;
|
|
||||||
while i < 512 do begin
|
|
||||||
outw(ATA_PRIMARY_BASE + ATA_REG_DATA, uint16(buffer[i] or (buffer[i+1] shl 8)));
|
|
||||||
i:= i + 2;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//flush drive cache
|
|
||||||
psleep(1);
|
|
||||||
port_write(ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
|
|
||||||
psleep(1);
|
|
||||||
if not is_ready() then exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
|
|
||||||
var
|
|
||||||
i : uint16;
|
|
||||||
begin
|
|
||||||
push_trace('IDE.dread');
|
|
||||||
for i:=0 to sectorCount-1 do begin
|
|
||||||
readPIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i]));
|
|
||||||
psleep(100)
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
|
|
||||||
var
|
|
||||||
i : uint16;
|
|
||||||
begin
|
|
||||||
for i:=0 to sectorCount-1 do begin
|
|
||||||
writePIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i]));
|
|
||||||
psleep(100)
|
|
||||||
end;
|
|
||||||
// writePIO28(device^.controllerId0, LBA, puint8(buffer));
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
Loading…
x
Reference in New Issue
Block a user