diff --git a/src/driver/ATA.pas b/src/driver/ATA.pas index 3196b5b9..1bed8fa9 100644 --- a/src/driver/ATA.pas +++ b/src/driver/ATA.pas @@ -19,10 +19,14 @@ uses type - charptr = ^char; + 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; @@ -37,18 +41,32 @@ type empty2 : 64..65; end; - ATA_Command_Buffer bitpacked record + 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; - PRG_Table : array[0..10] of Physical_Region_Descriptor; // up 64K r/w each, upto 8000 supported per table. + 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); +procedure read(address : uint32; data_lba : uint32; data_bytes : uint32); procedure write(address : uint32); procedure callback(data : void); @@ -65,10 +83,112 @@ begin 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; + end; -procedure callback(data : void); +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); begin + end; + +procedure callback(data : void); //need r/w, is last +var + cb : ATA_Command_Buffer; +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 + outb(ports.sector_count, PRD_Table[devices[0].currentIndex].data_bytes / 512); // 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; + + cb.start_stop_bit := 1; + cb.read_write_bit := 0; + + ptr := intptr(devices[0].Command_Register); + ptr^ := uint8(cb); + + devices[0].currentIndex := devices[0].currentIndex + 1; + end; end; diff --git a/src/driver/PCI.pas b/src/driver/PCI.pas index 7be819a7..a2da26f8 100644 --- a/src/driver/PCI.pas +++ b/src/driver/PCI.pas @@ -251,7 +251,7 @@ begin device_count := device_count + 1; if devices[device_count - 1].header_type and $80 <> 0 then begin for i:=0 to 8 do begin - // console.writechar(char(21)); + //console.writechar(char(21)); vendor_id := get_vendor_ID(bus, device, i, 0); //if vendor_id = $FFFF then exit(false); devices[device_count] := read_device_config(bus, device, i, 0); @@ -401,7 +401,7 @@ begin if tmp.class_code = 1 then begin console.writestringln('-Device is MASS_STORAGE_CONTROLLER '); - //if tmp.subclass_class = 1 then ATA.init(tmp); + if tmp.subclass_class = 1 then ATA.init(tmp); end; if tmp.class_code = 2 then begin console.writestringln('-Device is NETWORK_CONTROLLER '); diff --git a/src/isr/isr76.pas b/src/isr/isr76.pas index f5187613..3de1f4bf 100644 --- a/src/isr/isr76.pas +++ b/src/isr/isr76.pas @@ -7,7 +7,7 @@ * Contributors: ************************************************ } -unit isr46; +unit isr76; interface