git-svn-id: https://spexeah.com:8443/svn/Asuro@973 6dbc8c32-bb84-406f-8558-d1cf31a0ab0c
This commit is contained in:
parent
717a642370
commit
fd564f56b7
@ -1,578 +0,0 @@
|
|||||||
{ ************************************************
|
|
||||||
* Asuro
|
|
||||||
* Unit: Drivers/AHCI
|
|
||||||
* Description: AHCI SATA Driver
|
|
||||||
************************************************
|
|
||||||
* Author: Aaron Hance
|
|
||||||
* Contributors:
|
|
||||||
************************************************ }
|
|
||||||
|
|
||||||
unit AHCI_OLD;
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
uses
|
|
||||||
util,
|
|
||||||
PCI,
|
|
||||||
drivertypes,
|
|
||||||
drivermanagement,
|
|
||||||
lmemorymanager,
|
|
||||||
console,
|
|
||||||
vmemorymanager,
|
|
||||||
terminal;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
THBAptr = ^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 : TFIS_REG_H2D;
|
|
||||||
acmd : array[0..15] of uint8;
|
|
||||||
rsv : array[0..47] of uint8;
|
|
||||||
prdt : array[0..7] of TPRD_Entry;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
//constants
|
|
||||||
//SATA_SIG_ATA := $101;
|
|
||||||
//SATA_SIG_ATAPI := $EB140101;
|
|
||||||
//STA_SIG_SEMB := $C33C0101;
|
|
||||||
//STAT_SIG_PM := $96690101;
|
|
||||||
AHCI_BASE: uint32 = $400000;
|
|
||||||
|
|
||||||
//other
|
|
||||||
ahciController : PuInt32;
|
|
||||||
hba : THBAptr;
|
|
||||||
|
|
||||||
sataStorageDevices : array[0..31] of PuInt32;
|
|
||||||
sataStorageDeviceCount : uint8;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
procedure init();
|
|
||||||
procedure check_ports();
|
|
||||||
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;
|
|
||||||
procedure test(value : uint32);
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
||||||
procedure test_command(params : PParamList);
|
|
||||||
begin
|
|
||||||
test(65534);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure init();
|
|
||||||
var
|
|
||||||
devID : TDeviceIdentifier;
|
|
||||||
begin
|
|
||||||
console.writestringln('AHCI: STARTING INIT');
|
|
||||||
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 Controller', @devID, @load);
|
|
||||||
terminal.registerCommand('AHCI', @test_command, 'TEST ACHI');
|
|
||||||
end;
|
|
||||||
|
|
||||||
function load(ptr : void) : boolean;
|
|
||||||
begin
|
|
||||||
ahciController := ptr + KERNEL_VIRTUAL_BASE;
|
|
||||||
hba := THBAptr(PPCI_Device(ahciController)^.address5);
|
|
||||||
new_page_at_address(uint32(hba));
|
|
||||||
new_page_at_address(AHCI_BASE);
|
|
||||||
AHCI_BASE := PPCI_Device(ahciController)^.address5;
|
|
||||||
check_ports();
|
|
||||||
load:= true;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure check_ports();
|
|
||||||
var
|
|
||||||
d : uint32;
|
|
||||||
i : uint32;
|
|
||||||
activePorts : array[0..32] of uint32;
|
|
||||||
|
|
||||||
begin
|
|
||||||
d:= 1;
|
|
||||||
for i:= 0 to 31 do begin
|
|
||||||
if (d > 0) and (hba^.port_implemented <> 0) then begin // port connected
|
|
||||||
if hba^.ports[i].ssts = 259 then begin // port in use and active
|
|
||||||
if hba^.ports[i].sig = 1 then begin //device is sata
|
|
||||||
sataStorageDevices[sataStorageDeviceCount - 1] := @hba^.ports[i];
|
|
||||||
sataStorageDeviceCount += 1;
|
|
||||||
port_rebase(i);
|
|
||||||
end;
|
|
||||||
//TODO implement other types
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
d := d shl 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure enable_cmd(port : uint8);
|
|
||||||
begin
|
|
||||||
while (hba^.ports[port].cmd and $8000) <> 0 do begin end;
|
|
||||||
hba^.ports[port].cmd := hba^.ports[port].cmd or $0010;
|
|
||||||
hba^.ports[port].cmd := hba^.ports[port].cmd or $0001;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure disable_cmd(port : uint8);
|
|
||||||
begin
|
|
||||||
hba^.ports[port].cmd := hba^.ports[port].cmd and $0001;
|
|
||||||
while (hba^.ports[port].cmd and $4000) <> 0 do begin end;
|
|
||||||
hba^.ports[port].cmd := hba^.ports[port].cmd and $0010;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure port_rebase(port : uint8);
|
|
||||||
var
|
|
||||||
cmdHeader : PCMDHeader;
|
|
||||||
i : uint16;
|
|
||||||
begin
|
|
||||||
disable_cmd(port);
|
|
||||||
hba^.ports[port].clb := AHCI_BASE + (port shl 10);
|
|
||||||
hba^.ports[port].clbu := 0;
|
|
||||||
memset(hba^.ports[port].clb, 0, 1024);
|
|
||||||
|
|
||||||
hba^.ports[port].fb := AHCI_BASE + (32 shl 10) + (port shl 8);
|
|
||||||
hba^.ports[port].fbu := 0;
|
|
||||||
memset(hba^.ports[port].fb, 0, 256);
|
|
||||||
|
|
||||||
cmdheader := PCMDHeader(hba^.ports[port].clb + KERNEL_VIRTUAL_BASE);
|
|
||||||
for i:= 0 to 31 do begin
|
|
||||||
cmdHeader[i].PRDTL := 8; // no of prdt entries per cmd table
|
|
||||||
cmdheader[i].ctba := AHCI_BASE + (40 shl 10) + (port shl 13) + (i shl 8);
|
|
||||||
cmdheader[i].CTBAU := 0;
|
|
||||||
memset(cmdheader[i].ctba, 0, 256);
|
|
||||||
end;
|
|
||||||
enable_cmd(port);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function read(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
|
|
||||||
var
|
|
||||||
pport : PHBA_PORT;
|
|
||||||
slot : uint32;
|
|
||||||
cmdHeader : PCMDHeader;
|
|
||||||
cmdTable : PCommand_Table;
|
|
||||||
cmdFis : PFIS_REG_H2D;
|
|
||||||
i : uint32;
|
|
||||||
spin : uint32 = 0;
|
|
||||||
begin
|
|
||||||
console.writestringln('1');
|
|
||||||
pport := PHBA_PORT(@hba^.ports[port] + KERNEL_VIRTUAL_BASE);
|
|
||||||
//new_page_at_address(uint32(pport));
|
|
||||||
pport^.istat := $ffff;
|
|
||||||
slot := find_cmd_slot(port);
|
|
||||||
if slot = -1 then exit(false);
|
|
||||||
|
|
||||||
console.writestringln('2');
|
|
||||||
cmdHeader := PCMDHeader(@pport^.clb + KERNEL_VIRTUAL_BASE);
|
|
||||||
//new_page_at_address(uint32(cmdHeader));
|
|
||||||
cmdHeader += slot;
|
|
||||||
cmdHeader^.w := false;
|
|
||||||
cmdHeader^.PRDTL := uint16(((count - 1) shr 4) + 1);
|
|
||||||
|
|
||||||
console.writestringln('3');
|
|
||||||
cmdTable := PCommand_Table(@cmdheader^.ctba + KERNEL_VIRTUAL_BASE);
|
|
||||||
//new_page_at_address(uint32(cmdTable));
|
|
||||||
memset(uint32(cmdTable), 0, sizeof(TCommand_Table) + (cmdheader^.PRDTL-1) * sizeof(TPRD_Entry));
|
|
||||||
|
|
||||||
console.writestringln('4');
|
|
||||||
if cmdHeader^.PRDTL > 0 then begin
|
|
||||||
for i:= 0 to cmdHeader^.PRDTL -1 do begin
|
|
||||||
cmdTable^.prdt[i].data_base_address := uint32(buf);
|
|
||||||
cmdTable^.prdt[i].data_byte_count := 8*1024-1;
|
|
||||||
cmdTable^.prdt[i].interrupt_oc := false;
|
|
||||||
buf += 4*1024;
|
|
||||||
count -= 16;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('5');
|
|
||||||
cmdTable^.prdt[cmdHeader^.PRDTL].data_base_address := uint32(buf);
|
|
||||||
cmdTable^.prdt[cmdHeader^.PRDTL].data_byte_count := (count shl 9)-1;
|
|
||||||
cmdTable^.prdt[cmdHeader^.PRDTL].interrupt_oc := false;
|
|
||||||
|
|
||||||
console.writestringln('6');
|
|
||||||
//setup command
|
|
||||||
cmdfis := PFIS_REG_H2D(@cmdTable^.cfis + KERNEL_VIRTUAL_BASE);
|
|
||||||
new_page_at_address(uint32(cmdfis));
|
|
||||||
cmdfis^.coc := true;
|
|
||||||
cmdfis^.command := $25;
|
|
||||||
cmdfis^.lba0 := uint8(startl);
|
|
||||||
cmdfis^.lba1 := uint8(startl shr 8);
|
|
||||||
cmdfis^.lba2 := uint8(startl shr 16);
|
|
||||||
cmdfis^.device := 1 shl 6;
|
|
||||||
cmdfis^.lba3 := uint8(startl shr 24);
|
|
||||||
cmdfis^.lba4 := uint8(starth);
|
|
||||||
cmdfis^.lba3 := uint8(starth shr 8);
|
|
||||||
cmdfis^.count_low := count and $FF;
|
|
||||||
cmdfis^.count_high:= (count shr 8) and $FF;
|
|
||||||
|
|
||||||
console.writestringln('7');
|
|
||||||
// while (pport^.tfd and $88) and spin < 1000000 do begin
|
|
||||||
// spin += 1;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
console.writestringln('8');
|
|
||||||
if spin = 1000000 then begin
|
|
||||||
console.writestringln('AHCI controller: port is hung!');
|
|
||||||
read:= false;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('9');
|
|
||||||
pport^.ci := 1 shl slot;
|
|
||||||
//pport^.ci := 1;
|
|
||||||
|
|
||||||
console.writestringln('10');
|
|
||||||
while true do begin
|
|
||||||
if(pport^.ci and (1 shl slot)) = (1 shl slot) then break;
|
|
||||||
if(pport^.istat and (1 shl 30)) = (1 shl 30) then begin
|
|
||||||
console.writestringln('AHCI controller: Disk read error!');
|
|
||||||
read:= false;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('11');
|
|
||||||
if(pport^.istat and (1 shl 30)) = (1 shl 30) then begin
|
|
||||||
console.writestringln('AHCI controller: Disk read error!');
|
|
||||||
read:= false;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('12');
|
|
||||||
read:= true;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function write(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
|
|
||||||
var
|
|
||||||
pport : PHBA_PORT;
|
|
||||||
slot : uint32;
|
|
||||||
cmdHeader : PCMDHeader;
|
|
||||||
cmdTable : PCommand_Table;
|
|
||||||
cmdFis : PFIS_REG_H2D;
|
|
||||||
i : uint32;
|
|
||||||
spin : uint32 = 0;
|
|
||||||
begin
|
|
||||||
//console.writeintln(sizeof(TCommand_Table));
|
|
||||||
//console.writeintln(sizeof(TCommand_Table) + (cmdheader^.PRDTL-1) * sizeof(TPRD_Entry));
|
|
||||||
//psleep(1000);
|
|
||||||
console.writestringln('1');
|
|
||||||
//pport := PHBA_PORT(@hba^.ports[port] + KERNEL_VIRTUAL_BASE);
|
|
||||||
//new_page_at_address(uint32(pport));
|
|
||||||
console.writestringln('1.1');
|
|
||||||
console.writehexln(uint32(hba));
|
|
||||||
hba^.ports[port].istat := $ffff;
|
|
||||||
console.writestringln('1.2');
|
|
||||||
slot := find_cmd_slot(port);
|
|
||||||
console.writestringln('1.3');
|
|
||||||
if slot = -1 then exit(false);
|
|
||||||
|
|
||||||
console.writestringln('2');
|
|
||||||
cmdHeader := PCMDHeader(hba^.ports[port].clb + KERNEL_VIRTUAL_BASE);
|
|
||||||
|
|
||||||
cmdHeader += slot;
|
|
||||||
// new_page_at_address(uint32(cmdHeader));
|
|
||||||
cmdHeader^.w := false;
|
|
||||||
cmdHeader^.PRDTL := uint16(((count - 1) shr 4) + 1);
|
|
||||||
console.writestringln('3');
|
|
||||||
cmdTable := PCommand_Table(cmdheader^.ctba);
|
|
||||||
// new_page_at_address(uint32(cmdTable));
|
|
||||||
// new_page_at_address(uint32(@cmdTable^.prdt));
|
|
||||||
console.writehexln(uint32(cmdTable));
|
|
||||||
kpalloc(uint32(cmdTable));
|
|
||||||
memset(uint32(cmdTable), 0, sizeof(TCommand_Table));
|
|
||||||
|
|
||||||
console.writestringln('4');
|
|
||||||
console.writestring('PRDTL: ');
|
|
||||||
console.writeintln(cmdHeader^.PRDTL);
|
|
||||||
if cmdHeader^.PRDTL > 0 then begin
|
|
||||||
console.writestringln('4.1');
|
|
||||||
for i:= 0 to cmdHeader^.PRDTL -1 do begin
|
|
||||||
console.writestring('PRDTL: ');
|
|
||||||
console.writeintln(cmdHeader^.PRDTL - 1);
|
|
||||||
console.writestring('i: ');
|
|
||||||
console.writeintln(i);
|
|
||||||
console.writestringln('4.2');
|
|
||||||
console.writehexln(uint32(cmdTable));
|
|
||||||
cmdTable^.prdt[i].data_base_address := uint32(buf);
|
|
||||||
console.writestringln('4.3');
|
|
||||||
cmdTable^.prdt[i].data_byte_count := 8*1024-1;
|
|
||||||
console.writestringln('4.4');
|
|
||||||
cmdTable^.prdt[i].interrupt_oc := false;
|
|
||||||
buf += 4*1024;
|
|
||||||
count -= 16;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('5');
|
|
||||||
cmdTable^.prdt[cmdHeader^.PRDTL].data_base_address := uint32(buf);
|
|
||||||
console.writestringln('5.1');
|
|
||||||
cmdTable^.prdt[cmdHeader^.PRDTL].data_byte_count := (count shl 9)-1;
|
|
||||||
console.writestringln('5.2');
|
|
||||||
cmdTable^.prdt[cmdHeader^.PRDTL].interrupt_oc := false;
|
|
||||||
|
|
||||||
console.writestringln('6');
|
|
||||||
//cmdfis := PFIS_REG_H2D(@cmdTable^.cfis);
|
|
||||||
//new_page_at_address(uint32(cmdfis));
|
|
||||||
cmdTable^.cfis.coc := true;
|
|
||||||
cmdTable^.cfis.command := $35;
|
|
||||||
cmdTable^.cfis.lba0 := uint8(startl);
|
|
||||||
cmdTable^.cfis.lba1 := uint8(startl shr 8);
|
|
||||||
cmdTable^.cfis.lba2 := uint8(startl shr 16);
|
|
||||||
cmdTable^.cfis.device := 1 shl 6;
|
|
||||||
cmdTable^.cfis.lba3 := uint8(startl shr 24);
|
|
||||||
cmdTable^.cfis.lba4 := uint8(starth);
|
|
||||||
cmdTable^.cfis.lba3 := uint8(starth shr 8);
|
|
||||||
cmdTable^.cfis.count_low := count and $FF;
|
|
||||||
cmdTable^.cfis.count_high:= (count shr 8) and $FF;
|
|
||||||
|
|
||||||
console.writestringln('7');
|
|
||||||
while (hba^.ports[port].tfd and $88) and spin < 1000000 do begin
|
|
||||||
spin += 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('8');
|
|
||||||
if spin = 1000000 then begin
|
|
||||||
console.writestringln('AHCI controller: port is hung!');
|
|
||||||
write:= false;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('9');
|
|
||||||
hba^.ports[port].ci := 1 shl slot;
|
|
||||||
//hba^.ports[port].ci := 1;
|
|
||||||
|
|
||||||
console.writestringln('10');
|
|
||||||
while true do begin
|
|
||||||
if(hba^.ports[port].ci and (1 shl slot)) = (1 shl slot) then break;
|
|
||||||
if(hba^.ports[port].istat and (1 shl 30)) = (1 shl 30) then begin
|
|
||||||
console.writestringln('AHCI controller: Disk write error!');
|
|
||||||
write:= false;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('11');
|
|
||||||
if(hba^.ports[port].istat and (1 shl 30)) = (1 shl 30) then begin
|
|
||||||
console.writestringln('AHCI controller: Disk write error!');
|
|
||||||
write:= false;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('12');
|
|
||||||
write:= true;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function find_cmd_slot(port : uint8) : uint32;
|
|
||||||
var
|
|
||||||
slots : uint32;
|
|
||||||
i : uint32;
|
|
||||||
begin
|
|
||||||
slots := hba^.ports[port].sact or hba^.ports[port].ci;
|
|
||||||
for i:=0 to 31 do begin
|
|
||||||
if (slots and 1) = 0 then begin
|
|
||||||
exit(i);
|
|
||||||
end;
|
|
||||||
slots := slots shr 1;
|
|
||||||
end;
|
|
||||||
console.writestringln('AHCI Controller: Unable to find free command slots!');
|
|
||||||
exit(-1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure test(value : uint32);
|
|
||||||
var
|
|
||||||
thing : PuInt32;
|
|
||||||
begin
|
|
||||||
thing:= Puint32(kalloc(1024*16));
|
|
||||||
thing^:= value;
|
|
||||||
write(0, $1, $0, 6, puint32(thing - KERNEL_VIRTUAL_BASE) );
|
|
||||||
thing^:= 365;
|
|
||||||
read(0, $1, $0, 6, puint32(thing - KERNEL_VIRTUAL_BASE) );
|
|
||||||
console.writeintln(thing^);
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
||||||
|
|
@ -1,271 +0,0 @@
|
|||||||
{ ************************************************
|
|
||||||
* Asuro
|
|
||||||
* Unit: Drivers/ATA
|
|
||||||
* Description: ATA DMA Driver
|
|
||||||
* currently a hack needs to be re-written if works
|
|
||||||
************************************************
|
|
||||||
* Author: Aaron Hance
|
|
||||||
* Contributors:
|
|
||||||
************************************************ }
|
|
||||||
unit ATA;
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
uses
|
|
||||||
util,
|
|
||||||
drivertypes,
|
|
||||||
console,
|
|
||||||
terminal,
|
|
||||||
isr76,
|
|
||||||
vmemorymanager;
|
|
||||||
|
|
||||||
type
|
|
||||||
|
|
||||||
intptr = ^uint32;
|
|
||||||
|
|
||||||
ATA_Device = record
|
|
||||||
reading : boolean;
|
|
||||||
master : boolean;
|
|
||||||
primary : boolean;
|
|
||||||
currentIndex : uint16;
|
|
||||||
device_lba : uint32;
|
|
||||||
Command_Register : uint32;
|
|
||||||
Status_Register : uint32;
|
|
||||||
PRDT_Address_Reg : uint32;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Physical_Region_Descriptor = bitpacked record
|
|
||||||
empty0 : 0..1;
|
|
||||||
MRPB_Address : 1..32; // memory address
|
|
||||||
Byte_Count : 32..47; // size in bytes (0 is 64K)
|
|
||||||
empty1 : 47..63;
|
|
||||||
EOT : 63..64; // end of table
|
|
||||||
empty2 : 64..65;
|
|
||||||
end;
|
|
||||||
|
|
||||||
ATA_Command_Buffer = bitpacked record
|
|
||||||
start_stop_bit : 0..1; // 0 stopped
|
|
||||||
read_write_bit : 3..4; // 0 read
|
|
||||||
end;
|
|
||||||
|
|
||||||
ATA_Status_Buffer = bitpacked record end;
|
|
||||||
|
|
||||||
ATA_IO_PORT = record
|
|
||||||
data : uint16;
|
|
||||||
error : uint8;
|
|
||||||
sector_count : uint8;
|
|
||||||
lba_low : uint8;
|
|
||||||
lba_mid : uint8;
|
|
||||||
lba_hi : uint8;
|
|
||||||
drive : uint8;
|
|
||||||
command : uint8;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
ports : ATA_IO_PORT;
|
|
||||||
devices : array[0..4] of ATA_Device;
|
|
||||||
PRD_Table : array[0..100] of Physical_Region_Descriptor; // up 64K r/w each, upto 8000 supported per table.
|
|
||||||
controller : TPCI_device;
|
|
||||||
|
|
||||||
procedure init(_controller : TPCI_device);
|
|
||||||
procedure read(address : uint32; data_lba : uint32; data_bytes : uint32);
|
|
||||||
procedure write(address : uint32; data_lba : uint32; data_bytes : uint32);
|
|
||||||
procedure callback(data : void);
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
||||||
procedure init(_controller : TPCI_device); //alloc, pmem; map_page vmem;
|
|
||||||
begin
|
|
||||||
console.writestringln('ATA: INIT BEGIN.');
|
|
||||||
isr76.hook(uint32(@callback));
|
|
||||||
|
|
||||||
controller := _controller;
|
|
||||||
|
|
||||||
new_page_at_address(controller.address4);
|
|
||||||
|
|
||||||
devices[0].primary := true;
|
|
||||||
devices[0].Command_Register := controller.address4;
|
|
||||||
devices[0].Status_Register := controller.address4 + 2;
|
|
||||||
devices[0].PRDT_Address_Reg := controller.address4 + 4;
|
|
||||||
|
|
||||||
ports.command := $1F7;
|
|
||||||
ports.lba_low := $1F3;
|
|
||||||
ports.lba_mid := $1F4;
|
|
||||||
ports.lba_hi := $1F5;
|
|
||||||
ports.drive := $1F6;
|
|
||||||
ports.sector_count := $F2;
|
|
||||||
console.writestringln('ATA: INIT END.');
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure read(address : uint32; data_lba : uint32; data_bytes : uint32);
|
|
||||||
var
|
|
||||||
PRD : Physical_Region_Descriptor;
|
|
||||||
empty_table : array[0..100] of Physical_Region_Descriptor;
|
|
||||||
i : uint32;
|
|
||||||
ptr : intptr;
|
|
||||||
sector_count : uint8;
|
|
||||||
cb : ATA_Command_Buffer;
|
|
||||||
begin
|
|
||||||
devices[0].device_lba := data_lba;
|
|
||||||
devices[0].reading := true;
|
|
||||||
PRD_Table := empty_table;
|
|
||||||
PRD.MRPB_Address := address;
|
|
||||||
|
|
||||||
//limit
|
|
||||||
if data_bytes > 6400000 then exit;
|
|
||||||
|
|
||||||
if data_bytes < 64001 then begin
|
|
||||||
PRD.EOT := 1;
|
|
||||||
if data_bytes = 64000 then begin
|
|
||||||
PRD.Byte_Count := 0
|
|
||||||
end else begin
|
|
||||||
PRD.Byte_Count := data_bytes;
|
|
||||||
end;
|
|
||||||
end else begin
|
|
||||||
while data_bytes > 64000 do begin
|
|
||||||
PRD.EOT := 0;
|
|
||||||
PRD.MRPB_Address := address;
|
|
||||||
PRD.Byte_Count := 0;
|
|
||||||
|
|
||||||
data_bytes := data_bytes - 64000;
|
|
||||||
address := address + 64000;
|
|
||||||
end;
|
|
||||||
|
|
||||||
PRD.EOT := 1;
|
|
||||||
PRD.MRPB_Address := address;
|
|
||||||
PRD.Byte_Count := data_bytes;
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
ptr := intptr(devices[0].PRDT_Address_Reg);
|
|
||||||
ptr^ := uint32(@PRD_Table);
|
|
||||||
|
|
||||||
ptr := intptr(devices[0].Status_Register);
|
|
||||||
ptr^ := 0;
|
|
||||||
|
|
||||||
outb(ports.drive, $A0);
|
|
||||||
outb(ports.sector_count, 125);
|
|
||||||
outb(ports.lba_low, (data_lba and $000000FF));
|
|
||||||
outb(ports.lba_mid, (data_lba and $0000FF00) SHR 8);
|
|
||||||
outb(ports.lba_hi, (data_lba and $0000FF00) SHR 16);
|
|
||||||
outb(ports.command, $C8);
|
|
||||||
devices[0].currentIndex := 1;
|
|
||||||
|
|
||||||
cb.start_stop_bit := 1;
|
|
||||||
cb.read_write_bit := 0;
|
|
||||||
|
|
||||||
ptr := intptr(devices[0].Command_Register);
|
|
||||||
ptr^ := uint8(cb);
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure write(address : uint32; data_lba : uint32; data_bytes : uint32);
|
|
||||||
var
|
|
||||||
PRD : Physical_Region_Descriptor;
|
|
||||||
empty_table : array[0..100] of Physical_Region_Descriptor;
|
|
||||||
i : uint32;
|
|
||||||
ptr : intptr;
|
|
||||||
sector_count : uint8;
|
|
||||||
cb : ATA_Command_Buffer;
|
|
||||||
begin
|
|
||||||
devices[0].device_lba := data_lba;
|
|
||||||
devices[0].reading := true;
|
|
||||||
PRD_Table := empty_table;
|
|
||||||
PRD.MRPB_Address := address;
|
|
||||||
|
|
||||||
//limit
|
|
||||||
if data_bytes > 6400000 then exit;
|
|
||||||
|
|
||||||
if data_bytes < 64001 then begin
|
|
||||||
PRD.EOT := 1;
|
|
||||||
if data_bytes = 64000 then begin
|
|
||||||
PRD.Byte_Count := 0
|
|
||||||
end else begin
|
|
||||||
PRD.Byte_Count := data_bytes;
|
|
||||||
end;
|
|
||||||
end else begin
|
|
||||||
while data_bytes > 64000 do begin
|
|
||||||
PRD.EOT := 0;
|
|
||||||
PRD.MRPB_Address := address;
|
|
||||||
PRD.Byte_Count := 0;
|
|
||||||
|
|
||||||
data_bytes := data_bytes - 64000;
|
|
||||||
address := address + 64000;
|
|
||||||
end;
|
|
||||||
|
|
||||||
PRD.EOT := 1;
|
|
||||||
PRD.MRPB_Address := address;
|
|
||||||
PRD.Byte_Count := data_bytes;
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
ptr := intptr(devices[0].PRDT_Address_Reg);
|
|
||||||
ptr^ := uint32(@PRD_Table);
|
|
||||||
|
|
||||||
ptr := intptr(devices[0].Status_Register);
|
|
||||||
ptr^ := 0;
|
|
||||||
|
|
||||||
outb(ports.drive, $A0);
|
|
||||||
outb(ports.sector_count, 125);
|
|
||||||
outb(ports.lba_low, (data_lba and $000000FF));
|
|
||||||
outb(ports.lba_mid, (data_lba and $0000FF00) SHR 8);
|
|
||||||
outb(ports.lba_hi, (data_lba and $0000FF00) SHR 16);
|
|
||||||
outb(ports.command, $CA);
|
|
||||||
devices[0].currentIndex := 1;
|
|
||||||
|
|
||||||
cb.start_stop_bit := 1;
|
|
||||||
cb.read_write_bit := 1;
|
|
||||||
|
|
||||||
ptr := intptr(devices[0].Command_Register);
|
|
||||||
ptr^ := uint8(cb);
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure callback(data : void); //need r/w, is last
|
|
||||||
var
|
|
||||||
cb : ATA_Command_Buffer;
|
|
||||||
ptr : intptr;
|
|
||||||
tmp : uint16;
|
|
||||||
mode : uint8;
|
|
||||||
begin
|
|
||||||
if(PRD_Table[devices[0].currentIndex - 1].EOT = 1) then begin
|
|
||||||
//other stuff
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//if(devices[0].reading = true) then begin
|
|
||||||
if(PRD_Table[devices[0].currentIndex].EOT = 0) then begin
|
|
||||||
outb(ports.sector_count, 125);
|
|
||||||
outb(ports.lba_low, (devices[0].device_lba + (64000 * devices[0].currentIndex)) and $000000FF);
|
|
||||||
outb(ports.lba_mid, (((devices[0].device_lba + (64000 * devices[0].currentIndex))) and $0000FF00) SHR 8);
|
|
||||||
outb(ports.lba_hi, (((devices[0].device_lba + (64000 * devices[0].currentIndex))) and $0000FF00) SHR 16);
|
|
||||||
//outb(ports.command, $C8);
|
|
||||||
end else begin
|
|
||||||
tmp := uint16((PRD_Table[devices[0].currentIndex].Byte_Count and $FFFF) DIV 512);
|
|
||||||
outb(ports.sector_count, uint16(tmp)); // wont work if 64k
|
|
||||||
outb(ports.lba_low, (devices[0].device_lba + (64000 * devices[0].currentIndex)) and $000000FF);
|
|
||||||
outb(ports.lba_mid, (((devices[0].device_lba + (64000 * devices[0].currentIndex))) and $0000FF00) SHR 8);
|
|
||||||
outb(ports.lba_hi, (((devices[0].device_lba + (64000 * devices[0].currentIndex))) and $0000FF00) SHR 16);
|
|
||||||
//outb(ports.command, $C8);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if(devices[0].reading = true) then begin
|
|
||||||
outb(ports.command, $C8);
|
|
||||||
cb.start_stop_bit := 1;
|
|
||||||
cb.read_write_bit := 0;
|
|
||||||
end else begin
|
|
||||||
outb(ports.command, $CA);
|
|
||||||
cb.start_stop_bit := 1;
|
|
||||||
cb.read_write_bit := 1;
|
|
||||||
end;
|
|
||||||
ptr := intptr(devices[0].Command_Register);
|
|
||||||
ptr^ := uint8(cb);
|
|
||||||
|
|
||||||
|
|
||||||
devices[0].currentIndex := devices[0].currentIndex + 1;
|
|
||||||
//end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end.
|
|
@ -303,6 +303,16 @@ begin
|
|||||||
|
|
||||||
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);
|
||||||
|
// kfree(puint32(buffer));
|
||||||
|
|
||||||
console.writestringln('[IDE] (LOAD) END');
|
console.writestringln('[IDE] (LOAD) END');
|
||||||
pop_trace();
|
pop_trace();
|
||||||
end;
|
end;
|
||||||
@ -397,7 +407,7 @@ begin
|
|||||||
//send write command
|
//send write command
|
||||||
port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
||||||
|
|
||||||
console.writestringln('ide write sttart');
|
console.writestringlnWND('ide write start', getTerminalHWND());
|
||||||
console.redrawWindows();
|
console.redrawWindows();
|
||||||
|
|
||||||
//write data
|
//write data
|
||||||
@ -407,7 +417,7 @@ begin
|
|||||||
i:= i + 2;
|
i:= i + 2;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
console.writestringln('ise write stop');
|
console.writestringlnWND('ide write end', getTerminalHWND());
|
||||||
console.redrawWindows();
|
console.redrawWindows();
|
||||||
|
|
||||||
//flush drive cache
|
//flush drive cache
|
||||||
|
@ -110,7 +110,7 @@ end;
|
|||||||
|
|
||||||
function load(ptr : void) : boolean;
|
function load(ptr : void) : boolean;
|
||||||
begin
|
begin
|
||||||
console.outputln('DUMMY DRIVER', 'LOADED.')
|
console.outputln('FAT32', 'LOADED.')
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function cleanString(str : pchar; status : puint32) : byteArray8;
|
function cleanString(str : pchar; status : puint32) : byteArray8;
|
||||||
@ -754,6 +754,7 @@ end;
|
|||||||
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
||||||
var
|
var
|
||||||
buffer : puint32;
|
buffer : puint32;
|
||||||
|
bt: puint32;
|
||||||
zeroBuffer : puint32;
|
zeroBuffer : puint32;
|
||||||
bootRecord : PBootRecord;
|
bootRecord : PBootRecord;
|
||||||
dataStart : uint32;
|
dataStart : uint32;
|
||||||
@ -800,7 +801,7 @@ begin //maybe increase buffer size by one?
|
|||||||
// memset(uint32(buffer), 0, sizeof(TBootRecord));
|
// memset(uint32(buffer), 0, sizeof(TBootRecord));
|
||||||
// bootRecord:= PBootRecord(buffer);
|
// bootRecord:= PBootRecord(buffer);
|
||||||
|
|
||||||
buffer:= puint32(kalloc(disk^.sectorSize));
|
buffer:= puint32(kalloc(disk^.sectorSize+512));
|
||||||
memset(uint32(buffer), 0, disk^.sectorSize);
|
memset(uint32(buffer), 0, disk^.sectorSize);
|
||||||
|
|
||||||
bootRecord:= PBootRecord(buffer);
|
bootRecord:= PBootRecord(buffer);
|
||||||
@ -824,9 +825,41 @@ begin //maybe increase buffer size by one?
|
|||||||
bootRecord^.bsignature := $29;
|
bootRecord^.bsignature := $29;
|
||||||
bootRecord^.identString := fatArray;
|
bootRecord^.identString := fatArray;
|
||||||
|
|
||||||
puint32(buffer)[127]:= $55AA;
|
|
||||||
|
|
||||||
disk^.writecallback(disk, start + 1, 1, buffer);
|
console.writestringWND('spc', getTerminalHWND());
|
||||||
|
console.writeintlnWND(config^, getTerminalHWND());
|
||||||
|
console.writestringWND('sectors', getTerminalHWND());
|
||||||
|
console.writeintlnWND(sectors, getTerminalHWND());
|
||||||
|
console.writestringWND('sectorsize', getTerminalHWND());
|
||||||
|
console.writeintlnWND(disk^.sectorsize, getTerminalHWND());
|
||||||
|
|
||||||
|
console.redrawWindows();
|
||||||
|
|
||||||
|
bt:= puint32(kalloc(512));
|
||||||
|
|
||||||
|
bt[1] := 1;
|
||||||
|
bt[2] := 1;
|
||||||
|
bt[3] := 1;
|
||||||
|
bt[4] := 1;
|
||||||
|
bt[5] := 1;
|
||||||
|
bt[6] := 1;
|
||||||
|
bt[7] := 11;
|
||||||
|
bt[8] := 33;
|
||||||
|
bt[9] := 22;
|
||||||
|
disk^.writecallback(disk, 3, 1, puint32(bt));
|
||||||
|
|
||||||
|
|
||||||
|
// puint32(buffer)[127]:= $55AA;
|
||||||
|
|
||||||
|
console.writestringlnWND('writting to bootrecord', getTerminalHWND());
|
||||||
|
console.writeintlnWND(start + 1, getTerminalHWND());
|
||||||
|
console.redrawWindows;
|
||||||
|
|
||||||
|
disk^.writecallback(disk, start + 1, 1, puint32(buffer));
|
||||||
|
|
||||||
|
console.writestringlnWND('finished writting to bootrecord', getTerminalHWND());
|
||||||
|
|
||||||
|
console.redrawWindows;
|
||||||
|
|
||||||
fatStart:= start + 1 + bootRecord^.rsvSectors;
|
fatStart:= start + 1 + bootRecord^.rsvSectors;
|
||||||
dataStart:= fatStart + bootRecord^.FATSize;
|
dataStart:= fatStart + bootRecord^.FATSize;
|
||||||
@ -843,10 +876,14 @@ begin //maybe increase buffer size by one?
|
|||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
kfree(zeroBuffer);
|
kfree(zeroBuffer);
|
||||||
writestring('Frees');
|
writestring('Frees');
|
||||||
|
console.redrawWindows;
|
||||||
|
console.writestringlnWND('writting 1', getTerminalHWND());
|
||||||
console.redrawWindows;
|
console.redrawWindows;
|
||||||
|
|
||||||
buffer:= puint32(kalloc(disk^.sectorSize));
|
buffer:= puint32(kalloc(disk^.sectorSize));
|
||||||
memset(uint32(buffer), 0, disk^.sectorSize);
|
memset(uint32(buffer), 0, disk^.sectorSize);
|
||||||
|
console.writestringlnWND('writting 1', getTerminalHWND());
|
||||||
|
console.redrawWindows;
|
||||||
|
|
||||||
puint32(buffer)[0]:= $FFFFFFF8; //fsinfo
|
puint32(buffer)[0]:= $FFFFFFF8; //fsinfo
|
||||||
puint32(buffer)[1]:= $FFFFFFF8; //root cluster
|
puint32(buffer)[1]:= $FFFFFFF8; //root cluster
|
||||||
|
@ -1,604 +0,0 @@
|
|||||||
{ ************************************************
|
|
||||||
* Asuro
|
|
||||||
* Unit: Drivers/storage/fat32
|
|
||||||
* Description: fat32 file system driver
|
|
||||||
*
|
|
||||||
************************************************
|
|
||||||
* Author: Aaron Hance
|
|
||||||
* Contributors:
|
|
||||||
************************************************ }
|
|
||||||
|
|
||||||
{
|
|
||||||
Todo in the future, optimise by prvoiding batch read/write commands
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unit FAT32;
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
uses
|
|
||||||
console,
|
|
||||||
storagemanagement,
|
|
||||||
util, terminal,
|
|
||||||
lmemorymanager,
|
|
||||||
strings,
|
|
||||||
lists,
|
|
||||||
tracer,
|
|
||||||
serial;
|
|
||||||
|
|
||||||
type
|
|
||||||
|
|
||||||
TBootRecord = bitpacked record
|
|
||||||
jmp2boot : ubit24;
|
|
||||||
OEMName : array[0..7] of char;
|
|
||||||
sectorSize : uint16;
|
|
||||||
spc : uint8;
|
|
||||||
rsvSectors : uint16;
|
|
||||||
numFats : uint8;
|
|
||||||
numDirEnt : uint16;
|
|
||||||
numSectors : uint16;
|
|
||||||
mediaDescp : uint8;
|
|
||||||
sectorsPerFat : uint16;
|
|
||||||
sectorsPerTrack : uint16;
|
|
||||||
heads : uint16;
|
|
||||||
hiddenSectors : uint32;
|
|
||||||
manySectors : uint32;
|
|
||||||
FATSize : uint32;
|
|
||||||
flags : uint16;
|
|
||||||
signature : uint8;
|
|
||||||
FATVersion : uint16;
|
|
||||||
rootCluster : uint32;
|
|
||||||
FSInfoCluster : uint16;
|
|
||||||
backupCluster : uint16;
|
|
||||||
reserved0 : array[0..11] of uint8;
|
|
||||||
driveNumber : uint8;
|
|
||||||
reserved1 : uint8;
|
|
||||||
bsignature : uint8;// = $28;
|
|
||||||
volumeID : uint32;
|
|
||||||
volumeLabel : array[0..10] of uint8;
|
|
||||||
identString : array[0..7] of char;// = 'FAT32 ';
|
|
||||||
end;
|
|
||||||
PBootRecord = ^TBootRecord;
|
|
||||||
|
|
||||||
byteArray8 = array[0..7] of char;
|
|
||||||
|
|
||||||
TDirectory = packed record
|
|
||||||
fileName : array[0..7] of char;
|
|
||||||
fileExtension : array[0..2] of char;
|
|
||||||
attributes : uint8;
|
|
||||||
reserved0 : uint8;
|
|
||||||
timeFine : uint8;
|
|
||||||
time : uint16;
|
|
||||||
date : uint16;
|
|
||||||
accessTime : uint16;
|
|
||||||
clusterHigh : uint16;
|
|
||||||
modifiedTime : uint16;
|
|
||||||
modifiedDate : uint16;
|
|
||||||
clusterLow : uint16;
|
|
||||||
byteSize : uint32;
|
|
||||||
end;
|
|
||||||
PDirectory = ^TDirectory;
|
|
||||||
|
|
||||||
TFilesystemInfo = record
|
|
||||||
leadSignature : uint32;
|
|
||||||
reserved0 : array[0..479] of uint8;
|
|
||||||
structSignature : uint32;
|
|
||||||
freeSectors : uint32;
|
|
||||||
nextFreeSector : uint32;
|
|
||||||
reserved1 : array[0..11] of uint8;
|
|
||||||
trailSignature : uint32;
|
|
||||||
end;
|
|
||||||
|
|
||||||
TFatVolumeInfo = record
|
|
||||||
sectorsPerCluster : uint8; // must be power of 2 and mult by sectorsize to max 32k
|
|
||||||
end;
|
|
||||||
PFatVolumeInfo = ^TFatVolumeInfo;
|
|
||||||
|
|
||||||
var
|
|
||||||
filesystem : TFilesystem;
|
|
||||||
|
|
||||||
procedure init;
|
|
||||||
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
|
||||||
procedure detect_volumes(disk : PStorage_Device);
|
|
||||||
//function writeDirectory(volume : PStorage_volume; directory : pchar; attributes : uint32) : uint8; // need to handle parent table cluster overflow, need to take attributes
|
|
||||||
//function readDirectory(volume : PStorage_volume; directory : pchar; listPtr : PLinkedListBase) : uint8; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error
|
|
||||||
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
||||||
procedure STOS(str : PChar);
|
|
||||||
var
|
|
||||||
i : uint32;
|
|
||||||
|
|
||||||
begin
|
|
||||||
for i:=0 to StringSize(str)-1 do begin
|
|
||||||
serial.send(COM1, uint8(str[i]), 100);
|
|
||||||
end;
|
|
||||||
serial.send(COM1, 13, 100);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function load(ptr : void) : boolean;
|
|
||||||
begin
|
|
||||||
console.outputln('DUMMY DRIVER', 'LOADED.')
|
|
||||||
end;
|
|
||||||
|
|
||||||
function readBootRecord(volume : PStorage_volume) : TBootRecord; // need write functions for boot record!
|
|
||||||
var
|
|
||||||
buffer : puint32;
|
|
||||||
begin
|
|
||||||
buffer:= puint32(kalloc(512 + 512));
|
|
||||||
volume^.device^.readcallback(volume^.device, volume^.sectorStart + 1, 1, buffer);
|
|
||||||
readBootRecord:= PBootRecord(buffer)^;
|
|
||||||
kfree(buffer);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function readFat(volume : PStorage_volume; cluster : uint32): uint32; //TODO need KFREE after use
|
|
||||||
var
|
|
||||||
buffer : puint32;
|
|
||||||
bootRecord : TBootRecord;
|
|
||||||
BytesPerFatEntree: uint8 = 4;
|
|
||||||
sectorLocation: uint32;
|
|
||||||
fatEntriesPerSector : uint32;
|
|
||||||
begin
|
|
||||||
push_trace('fat32.readFat');
|
|
||||||
bootRecord := readBootRecord(volume);
|
|
||||||
fatEntriesPerSector:= bootRecord.sectorSize div BytesPerFatEntree;
|
|
||||||
sectorLocation:= cluster div fatEntriesPerSector;
|
|
||||||
|
|
||||||
buffer:= puint32(kalloc(bootRecord.sectorSize + 512));
|
|
||||||
//console.writeintlnWND(sectorLocation, );
|
|
||||||
volume^.device^.readcallback(volume^.device, volume^.sectorStart + 2 + sectorLocation, 1, buffer);
|
|
||||||
readFat:= buffer[cluster - (sectorLocation * fatEntriesPerSector)];
|
|
||||||
kfree(buffer);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure writeFat(volume : PStorage_volume; cluster : uint32; value : uint32); // untested, but should work
|
|
||||||
var
|
|
||||||
buffer : puint32;
|
|
||||||
bootRecord : TBootRecord;
|
|
||||||
BytesPerFatEntree: uint8 = 4;
|
|
||||||
sectorLocation: uint32;
|
|
||||||
fatEntriesPerSector : uint32;
|
|
||||||
begin
|
|
||||||
push_trace('fat32.writeFat');
|
|
||||||
bootRecord := readBootRecord(volume);
|
|
||||||
fatEntriesPerSector:= bootRecord.sectorSize div BytesPerFatEntree;
|
|
||||||
sectorLocation:= cluster div fatEntriesPerSector;
|
|
||||||
|
|
||||||
buffer:= puint32(kalloc(bootrecord.sectorSize + 512));
|
|
||||||
memset(uint32(buffer), 0, 512);
|
|
||||||
|
|
||||||
volume^.device^.readcallback(volume^.device, volume^.sectorStart + 2 + sectorLocation, 1, buffer);
|
|
||||||
buffer[cluster - (sectorLocation * fatEntriesPerSector)]:= value; // not gonna work boi
|
|
||||||
volume^.device^.writecallback(volume^.device, volume^.sectorStart + 2 + sectorLocation, 1, buffer);
|
|
||||||
kfree(buffer);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function readDirectory(volume : PStorage_volume; directory : pchar; listPtr : PLinkedListBase) : uint8; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error
|
|
||||||
var
|
|
||||||
directories : PLinkedListBase;
|
|
||||||
rootTable : PLinkedListBase;
|
|
||||||
clusters : PLinkedListBase;
|
|
||||||
dirElm : void;
|
|
||||||
buffer : puint32;
|
|
||||||
//buffer : puint32;
|
|
||||||
bootRecord : TBootRecord;
|
|
||||||
clusterInfo : uint32;
|
|
||||||
cc : uint32;
|
|
||||||
clusterByteSize : uint32;
|
|
||||||
fatSectorSize : uint32;
|
|
||||||
device : PStorage_Device;
|
|
||||||
i : uint32;
|
|
||||||
dirI : uint32 = 0;
|
|
||||||
str : pchar;
|
|
||||||
targetStr : pchar;
|
|
||||||
dir : PDirectory;
|
|
||||||
clusterAllocSize : uint32;
|
|
||||||
begin
|
|
||||||
push_trace('freadDirectory');
|
|
||||||
|
|
||||||
console.writestringln('r1');
|
|
||||||
console.redrawWindows();
|
|
||||||
|
|
||||||
rootTable := LL_New(sizeof(TDirectory));
|
|
||||||
clusters := LL_New(sizeof(uint32));
|
|
||||||
directories := stringToLL(directory, '/');
|
|
||||||
bootRecord := readBootRecord(volume);
|
|
||||||
device := volume^.device;
|
|
||||||
clusterByteSize := bootrecord.spc * bootrecord.sectorSize;
|
|
||||||
fatSectorSize := bootrecord.fatSize;
|
|
||||||
|
|
||||||
readDirectory:= 0;
|
|
||||||
// if readFat(volume, bootrecord.rootCluster) = $FFFFFFF8 then begin
|
|
||||||
// buffer:= puint32(kalloc((bootrecord.spc * 512) + 1));
|
|
||||||
// volume^.device^.readcallback(volume^.device, volume^.sectorStart + 1 + (bootrecord.fatSize div 512) + (bootRecord.spc * bootRecord.rootCluster), bootrecord.spc, buffer);
|
|
||||||
// end else if readFat(volume, bootrecord.rootCluster) <> $FFFFFFF7 then begin
|
|
||||||
// //need to read multiple clusters to get full directory table
|
|
||||||
// end;
|
|
||||||
|
|
||||||
|
|
||||||
cc:= bootrecord.rootCluster;
|
|
||||||
|
|
||||||
while true do begin
|
|
||||||
|
|
||||||
targetStr:= pchar(LL_Get(directories, dirI));
|
|
||||||
|
|
||||||
//build list of clusters for current directory table
|
|
||||||
while true do begin
|
|
||||||
clusterInfo:= readFat(volume, cc);
|
|
||||||
if clusterInfo = $FFFFFFF7 then begin
|
|
||||||
readDirectory:= 3; //ERROR
|
|
||||||
break;
|
|
||||||
end else if clusterInfo = $FFFFFFF8 then begin
|
|
||||||
//last dir table cluster
|
|
||||||
dirElm:= LL_Add(clusters);
|
|
||||||
uint32(dirElm^):= cc;
|
|
||||||
break;
|
|
||||||
end else if clusterInfo = 0 then begin
|
|
||||||
break;
|
|
||||||
end else begin
|
|
||||||
//dir is longer than one cluster
|
|
||||||
dirElm:= LL_Add(clusters);
|
|
||||||
uint32(dirElm^):= cc;
|
|
||||||
cc:= clusterInfo;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('r2');
|
|
||||||
console.redrawWindows();
|
|
||||||
|
|
||||||
//load clusters into buffer
|
|
||||||
clusterAllocSize:= (clusterByteSize * (LL_size(clusters))) + 1024; //TODO FIX
|
|
||||||
buffer:= puint32(kalloc(clusterAllocSize + 512));
|
|
||||||
memset(uint32(buffer), 0, clusterAllocSize);
|
|
||||||
//buffer := buffer;
|
|
||||||
for i:= 0 to LL_size(clusters) - 1 do begin
|
|
||||||
cc:= uint32(LL_Get(clusters, i)^);
|
|
||||||
device^.readcallback(device, volume^.sectorStart + 1 + fatSectorSize + (bootRecord.spc * cc), bootrecord.spc, @buffer[i * (clusterByteSize div 4)] );
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('r2.5');
|
|
||||||
console.redrawWindows();
|
|
||||||
|
|
||||||
if dirI = LL_size(directories) - 1 then break;
|
|
||||||
if LL_size(directories) = 0 then break;
|
|
||||||
|
|
||||||
console.writestringln('r3');
|
|
||||||
console.redrawWindows();
|
|
||||||
|
|
||||||
//get elements in the directory table
|
|
||||||
i:=0;
|
|
||||||
while true do begin
|
|
||||||
dir:= PDirectory(buffer);
|
|
||||||
console.writestringln(dir[i].fileName);
|
|
||||||
|
|
||||||
if dir[i].fileName[0] = char(0) then break; //need to check if I have found the right directoy and set cc if not last
|
|
||||||
if (dir[i].attributes and $10) = $10 then begin // is a directory;
|
|
||||||
str:= dir[i].fileName;
|
|
||||||
str[9]:= char(0);
|
|
||||||
if stringEquals(str, targetStr) then begin //need to get current folder searching for
|
|
||||||
cc:= dir[i].clusterLow;
|
|
||||||
cc:= cc or (dir[i].clusterHigh shl 16);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//dirElm:= LL_Add(rootTable);
|
|
||||||
//PDirectory(dirElm)^:= dir[i];
|
|
||||||
i+=1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//set CC
|
|
||||||
dirI += 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('r3.5');
|
|
||||||
console.redrawWindows();
|
|
||||||
|
|
||||||
i:=0;
|
|
||||||
while true do begin
|
|
||||||
dir:= PDirectory(buffer);
|
|
||||||
if dir[i].fileName[0] = char(0) then break;
|
|
||||||
|
|
||||||
dirElm:= LL_Add(listPtr);
|
|
||||||
PDirectory(dirElm)^:= dir[i];
|
|
||||||
i+=1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
console.writestringln('r4');
|
|
||||||
console.redrawWindows();
|
|
||||||
|
|
||||||
kfree(buffer);
|
|
||||||
//listPtr := rootTable;
|
|
||||||
//console.writeintln(uint32(listPtr));
|
|
||||||
|
|
||||||
// while true do begin // I need to be inside another loop
|
|
||||||
// if PDirectory(buffer)^.fileName[0] = char(0) then break;
|
|
||||||
// dirElm:= LL_Add(rootTable);
|
|
||||||
// PDirectory(dirElm)^:= PDirectory(buffer)^;
|
|
||||||
|
|
||||||
// console.writestring('FileName: ');
|
|
||||||
// console.writechar(PDirectory(buffer)^.fileName[0]);
|
|
||||||
// //console.writecharln(PDirectory(buffer)^.fileName[1]);
|
|
||||||
// buffer:= puint32(buffer + 8);
|
|
||||||
// end;
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
function findFreeCluster(volume : PStorage_volume) : uint32;
|
|
||||||
var
|
|
||||||
i : uint32 = 1;
|
|
||||||
currentCluster : uint32;
|
|
||||||
begin
|
|
||||||
push_trace('fat32.findFreeCluster');
|
|
||||||
while true do begin
|
|
||||||
currentCluster:= readFat(volume, i);
|
|
||||||
if currentCluster = 0 then begin
|
|
||||||
findFreeCluster:= i;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
i+=1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//expects dirName to be packed with spaces.
|
|
||||||
function writeDirectory(volume : PStorage_volume; directory : pchar; dirName : pchar; attributes : uint32) : uint8; // need to handle parent table cluster overflow, need to take attributes
|
|
||||||
var
|
|
||||||
dirList : PLinkedListBase;
|
|
||||||
i : uint32 = 0;
|
|
||||||
ii : uint32 = 0;
|
|
||||||
buffer : puint32;
|
|
||||||
bootRecord : TBootRecord;
|
|
||||||
device : PStorage_Device;
|
|
||||||
dataStart : uint32;
|
|
||||||
cluster : uint32;
|
|
||||||
parentDir : PDirectory;
|
|
||||||
parentCluster : uint32;
|
|
||||||
emptyEntree : uint32;
|
|
||||||
dirIndex : uint32;
|
|
||||||
entriesPerSector: uint32;
|
|
||||||
entrySector : uint32;
|
|
||||||
|
|
||||||
meArray : byteArray8 = ('.', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
|
|
||||||
parentArray : byteArray8 = ('.', '.', ' ', ' ', ' ', ' ', ' ', ' ');
|
|
||||||
begin
|
|
||||||
push_trace('fat32.writeDirectory'); //////////////////////////TODO need to make sure writing is to data area not fat area DERRRRRRRPPPP!!!
|
|
||||||
bootRecord := readBootRecord(volume);
|
|
||||||
device := volume^.device;
|
|
||||||
buffer := puint32(kalloc(sizeof(volume^.sectorSize) + 512));
|
|
||||||
memset(uint32(buffer), 0, 512);
|
|
||||||
|
|
||||||
dataStart:= (bootrecord.fatSize) + 1 + volume^.sectorStart;
|
|
||||||
|
|
||||||
dirList:= LL_New(sizeof(TDirectory));
|
|
||||||
readDirectory(volume, directory, dirList);
|
|
||||||
parentDir:= PDirectory(LL_Get(dirList, 0));
|
|
||||||
parentCluster:= parentDir^.clusterLow and (parentDir^.clusterHigh shl 16);
|
|
||||||
|
|
||||||
//write to the fat to allocate area
|
|
||||||
cluster:= findFreeCluster(volume);
|
|
||||||
writeFat(volume, cluster, $FFFFFFF8);
|
|
||||||
|
|
||||||
//write new dir table
|
|
||||||
|
|
||||||
//construct buffer
|
|
||||||
PDirectory(buffer)[0].fileName:= meArray;
|
|
||||||
PDirectory(buffer)[0].attributes:= $10;
|
|
||||||
PDirectory(buffer)[0].clusterLow:= uint16($0000FFFF and cluster);
|
|
||||||
PDirectory(buffer)[0].clusterHigh:= uint16($0000FFFF and (cluster shr 16));
|
|
||||||
|
|
||||||
PDirectory(buffer)[0].fileName:= parentArray;
|
|
||||||
PDirectory(buffer)[0].attributes:= $10;
|
|
||||||
PDirectory(buffer)[0].clusterLow:= parentDir^.clusterLow;
|
|
||||||
PDirectory(buffer)[0].clusterHigh:= parentDir^.clusterHigh;
|
|
||||||
|
|
||||||
//write buffer
|
|
||||||
volume^.device^.writecallback(volume^.device, dataStart + (cluster * bootrecord.spc), 1, buffer);
|
|
||||||
|
|
||||||
//write to parent dir table
|
|
||||||
|
|
||||||
kfree(buffer);
|
|
||||||
buffer:= puint32(kalloc(bootrecord.sectorSize * 4 + 512));
|
|
||||||
memset(uint32(buffer), 0, bootrecord.sectorsize * 4);
|
|
||||||
|
|
||||||
emptyEntree:= LL_size(dirList) * 4;
|
|
||||||
entriesPerSector:= bootrecord.sectorSize div sizeof(TDirectory);
|
|
||||||
entrySector:= emptyEntree div entriesPerSector + 7;
|
|
||||||
|
|
||||||
volume^.device^.readcallback(volume^.device, dataStart + (parentCluster * bootrecord.spc) + entrySector, 4, buffer);
|
|
||||||
dirIndex:= emptyEntree - (entrySector * entriesPerSector);
|
|
||||||
|
|
||||||
|
|
||||||
PDirectory(buffer)[dirIndex].fileName:= byteArray8(dirName);
|
|
||||||
PDirectory(buffer)[dirIndex].attributes:= $10;
|
|
||||||
PDirectory(buffer)[dirIndex].clusterLow:= uint16($0000FFFF and cluster);
|
|
||||||
PDirectory(buffer)[dirIndex].clusterHigh:= uint16($0000FFFF and (cluster shr 16));
|
|
||||||
|
|
||||||
volume^.device^.writecallback(volume^.device, dataStart + (parentCluster * bootrecord.spc) + entrySector, 4, buffer);
|
|
||||||
|
|
||||||
kfree(buffer);
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure readFile(volume : PStorage_volume; directory : pchar; byteCount : uint32; buffer : puint32);
|
|
||||||
begin
|
|
||||||
|
|
||||||
end;
|
|
||||||
//need to be able to increase no of clusted used by a directory
|
|
||||||
procedure writeFile(volume : PStorage_volume; directory : pchar; byteCount : uint32; buffer : puint32);
|
|
||||||
begin
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure init;
|
|
||||||
begin
|
|
||||||
filesystem.sName:= 'FAT32';
|
|
||||||
filesystem.writecallback:= @writeFile;
|
|
||||||
filesystem.readcallback:= @readFile;
|
|
||||||
filesystem.createcallback:= @create_volume;
|
|
||||||
filesystem.detectcallback:= @detect_volumes;
|
|
||||||
filesystem.createDirCallback:= @writeDirectory;
|
|
||||||
filesystem.readDirCallback:= @readDirectory;
|
|
||||||
storagemanagement.register_filesystem(@filesystem);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
|
||||||
var
|
|
||||||
i : uint32;
|
|
||||||
bootRecord : TBootRecord;
|
|
||||||
buffer : puint32;
|
|
||||||
asuroArray : byteArray8 = ('A','S','U','R','O',' ','V','1');
|
|
||||||
fatArray : byteArray8 = ('F','A','T','3','2',' ',' ',' ');
|
|
||||||
tmpArray : byteArray8;
|
|
||||||
|
|
||||||
fatStart : uint32;
|
|
||||||
dataStart: uint32;
|
|
||||||
|
|
||||||
begin
|
|
||||||
buffer:= puint32(kalloc(1024));
|
|
||||||
memset(uint32(buffer), 0, 512);
|
|
||||||
|
|
||||||
for i:=1 to 512 do begin
|
|
||||||
disk^.writeCallback(disk, i, 1, buffer);
|
|
||||||
end;
|
|
||||||
|
|
||||||
bootrecord.jmp2boot:= $00; // TODO what ahppens here???
|
|
||||||
bootRecord.OEMName:= asuroArray;
|
|
||||||
bootrecord.sectorsize:= disk^.sectorSize;
|
|
||||||
bootrecord.spc:= config^;
|
|
||||||
console.writeintln(uint32(config^));
|
|
||||||
bootrecord.rsvSectors:= 32; //Is this acceptable?
|
|
||||||
bootrecord.numFats:= 1;
|
|
||||||
bootrecord.numDirEnt:= 0;
|
|
||||||
bootRecord.numSectors:= 0;
|
|
||||||
bootrecord.mediaDescp:= $F8;
|
|
||||||
bootrecord.sectorsPerFat:= 0;
|
|
||||||
bootRecord.sectorsPerTrack:= 0;
|
|
||||||
bootRecord.heads:= 0;
|
|
||||||
bootRecord.hiddenSectors:= start;
|
|
||||||
bootRecord.manySectors:= sectors;
|
|
||||||
|
|
||||||
//BootRecord.FATSize:= ((sectors DIV PFatVolumeInfo(config)^.sectorsPerCluster) * 16 DIV disk^.sectorSize);
|
|
||||||
//BootRecord.FATSize:= ((sectors DIV 4) * 2 DIV disk^.sectorSize);
|
|
||||||
BootRecord.FATSize:= ((sectors DIV bootrecord.spc) * 4) DIV 512;
|
|
||||||
//sectors div spc, *
|
|
||||||
BootRecord.flags:= 0; //1 shl 7 for mirroring
|
|
||||||
BootRecord.FATVersion:= 0;
|
|
||||||
BootRecord.rootCluster:= start + 1; // can be changed if needed.
|
|
||||||
BootRecord.FSInfoCluster:= start + 1 + bootrecord.fatSize; //TODO need FSINFO
|
|
||||||
BootRecord.driveNumber:= $80;
|
|
||||||
//BootRecord.reserved0:=0;
|
|
||||||
//BootRecord.reserved1:=0;
|
|
||||||
BootRecord.volumeID := 53424; //need random number generator
|
|
||||||
//BootRecord.volumeLabel[0] := 0; //needs to be set later !!!
|
|
||||||
BootRecord.bsignature:= $29;
|
|
||||||
BootRecord.identString:= fatArray;
|
|
||||||
|
|
||||||
buffer:= @bootrecord;
|
|
||||||
puint32(buffer + (127))^:= $55AA; //end marker
|
|
||||||
|
|
||||||
disk^.writeCallback(disk, start + 1, 1, buffer);
|
|
||||||
|
|
||||||
dataStart:= (bootrecord.fatSize) + 1 + start;
|
|
||||||
|
|
||||||
//TODO FSINFO struct
|
|
||||||
|
|
||||||
//write fat
|
|
||||||
buffer := puint32(kalloc((sectors DIV bootrecord.spc) * 4 + 512));
|
|
||||||
memset(uint32(buffer), 0, (sectors DIV bootrecord.spc) * 4);
|
|
||||||
puint32(buffer + bootRecord.rootCluster - 1)^:= $FFFFFFF7; //make space for fsinfo, by setting this field to bad.
|
|
||||||
puint32(buffer + bootRecord.rootCluster)^:= $FFFFFFF8; //root directory table cluster, currently root is only 1 cluster long
|
|
||||||
disk^.writeCallback(disk, start + 2, (sectors DIV bootrecord.spc) * 4, buffer);
|
|
||||||
//disk^.writeCallback(disk, start + 2 + (sectors Div bootrecord.sectorsPerCluster DIV 512), sectors DIV bootrecord.sectorsPerCluster, buffer);
|
|
||||||
kfree(buffer);
|
|
||||||
|
|
||||||
//setup root directory
|
|
||||||
buffer:= puint32(kalloc(1024));
|
|
||||||
memset(uint32(buffer), 0, 512);
|
|
||||||
|
|
||||||
tmpArray[0]:= '.';
|
|
||||||
tmpArray[1]:= ' ';
|
|
||||||
tmpArray[2]:= ' ';
|
|
||||||
tmpArray[3]:= ' ';
|
|
||||||
tmpArray[4]:= ' ';
|
|
||||||
tmpArray[5]:= ' ';
|
|
||||||
tmpArray[6]:= ' ';
|
|
||||||
tmpArray[7]:= ' ';
|
|
||||||
|
|
||||||
PDirectory(buffer)^.fileName:= tmpArray;
|
|
||||||
PDirectory(buffer)^.attributes:= $10; // is directory
|
|
||||||
PDirectory(buffer)^.clusterLow:= 2; //my cluster location
|
|
||||||
|
|
||||||
tmpArray[1]:= '.';
|
|
||||||
PDirectory(buffer + (sizeof(TDirectory) DIV 4 ) )^.fileName:= tmpArray;
|
|
||||||
PDirectory(buffer + (sizeof(TDirectory) DIV 4) )^.attributes:= $08; // volume id
|
|
||||||
PDirectory(buffer + (sizeof(TDirectory) DIV 4) )^.clusterLow:= 2; //my cluster location
|
|
||||||
|
|
||||||
tmpArray[0]:= 'M';
|
|
||||||
tmpArray[1]:= 'U';
|
|
||||||
tmpArray[2]:= 'S';
|
|
||||||
tmpArray[3]:= 'I';
|
|
||||||
tmpArray[4]:= 'C';
|
|
||||||
PDirectory(buffer + (sizeof(TDirectory) * 2 DIV 4 ) )^.fileName:= tmpArray;
|
|
||||||
PDirectory(buffer + (sizeof(TDirectory) * 2 DIV 4) )^.attributes:= $10; // volume id
|
|
||||||
PDirectory(buffer + (sizeof(TDirectory) * 2 DIV 4) )^.clusterLow:= 2; //my cluster location
|
|
||||||
|
|
||||||
disk^.writeCallback(disk, dataStart + (bootRecord.spc * bootrecord.rootCluster), 1, buffer);
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure detect_volumes(disk : PStorage_Device);
|
|
||||||
var
|
|
||||||
buffer : puint32;
|
|
||||||
i : uint8;
|
|
||||||
volume : PStorage_volume;
|
|
||||||
|
|
||||||
dir : PDirectory;
|
|
||||||
dirs : PLinkedListBase;
|
|
||||||
begin
|
|
||||||
push_trace('detect volume');
|
|
||||||
redrawWindows();
|
|
||||||
//sleep(1);
|
|
||||||
|
|
||||||
volume:= PStorage_volume(kalloc(sizeof(TStorage_Volume)));
|
|
||||||
//check first address for MBR
|
|
||||||
//if found then add volume and use info to see if there is another volume
|
|
||||||
buffer := puint32(kalloc(512));
|
|
||||||
memset(uint32(buffer), 0, 512);
|
|
||||||
disk^.readcallback(disk, 2, 1, buffer);
|
|
||||||
|
|
||||||
if (puint32(buffer)[127] = $55AA) and (PBootRecord(buffer)^.bsignature = $29) then begin
|
|
||||||
console.writestringln('FAT32: volume found!');
|
|
||||||
volume^.device:= disk;
|
|
||||||
volume^.sectorStart:= 1;
|
|
||||||
volume^.sectorSize:= PBootRecord(buffer)^.sectorSize;
|
|
||||||
volume^.freeSectors:= 1000000; //TODO implement get free sectors need FSINFO implemented first
|
|
||||||
volume^.filesystem := @filesystem;
|
|
||||||
storagemanagement.register_volume(disk, volume);
|
|
||||||
end;
|
|
||||||
redrawWindows();
|
|
||||||
|
|
||||||
// dirs:= LL_New(sizeof(TDirectory));
|
|
||||||
// readDirectory(volume, '', dirs);
|
|
||||||
|
|
||||||
// for i:=0 to LL_size(dirs) - 1 do begin
|
|
||||||
// dir:= PDirectory(LL_Get(dirs, i));
|
|
||||||
// console.writestringln(pchar(dir^.fileName));
|
|
||||||
// end;
|
|
||||||
|
|
||||||
console.writeintln(findFreeCluster(volume));
|
|
||||||
redrawWindows();
|
|
||||||
while true do begin end;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//writeFat(volume, 3, $ADABABAD);
|
|
||||||
//writeDirectory(volume, '', 'hello', $10);
|
|
||||||
//writeDirectory(volume, '', 'poo', $10);
|
|
||||||
//readDirectory(volume, '.', dirs);
|
|
||||||
push_trace('end detect');
|
|
||||||
redrawWindows();
|
|
||||||
kfree(buffer);
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
@ -138,7 +138,7 @@ begin
|
|||||||
drive := stringToInt(getParam(1, params));
|
drive := stringToInt(getParam(1, params));
|
||||||
console.writeintln(drive); // works
|
console.writeintln(drive); // works
|
||||||
if stringEquals(getParam(2, params), 'fat32') then begin
|
if stringEquals(getParam(2, params), 'fat32') then begin
|
||||||
PFilesystem(LL_Get(filesystems, 0))^.createCallback((PStorage_Device(LL_Get(storageDevices, drive))), 10000, 1, spc); //todo check fs
|
PFilesystem(LL_Get(filesystems, 0))^.createCallback((PStorage_Device(LL_Get(storageDevices, drive))), 1000, 1, spc); //todo check fs
|
||||||
console.writestring('Drive ');
|
console.writestring('Drive ');
|
||||||
//console.writeint(drive); // page faults
|
//console.writeint(drive); // page faults
|
||||||
console.writestringln(' formatted.');
|
console.writestringln(' formatted.');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user