Skip to content

Commit 69b429d

Browse files
Improved ahci, not sure if it is working tho!
1 parent 28f883c commit 69b429d

File tree

2 files changed

+72
-24
lines changed

2 files changed

+72
-24
lines changed

disk.txt

512 Bytes
Binary file not shown.

source/kernel/C/ahci.c

+72-24
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@ void detect_ahci_devices(ahci_controller* ahci_ctrl) {
3535
printf("SATA Disk detected at port %d", i);
3636
uint8_t sector_buffer[SECTOR_SIZE * 1]; // Buffer to store 5 sectors
3737

38-
if (read_sectors(0, 1, sector_buffer) != 0) {
38+
if (read_sectors(1, 1, sector_buffer) != 0) {
3939
error("sector reading failed!", __FILE__);
4040
}
4141

4242
// for(int x = 0; x < SECTOR_SIZE * 1; x++){
43-
// debug_printf("%u ", sector_buffer[x]);
43+
// debug_printf("%u ", (int)sector_buffer[x]);
4444
// }
45+
// debug_print("\n");
46+
4547
} else if (sig == satapi_disk) {
4648
printf("SATAPI Disk detected at port %d", i);
4749
} else if (sig == semb_disk) {
@@ -75,35 +77,81 @@ prdt_entry_t* allocate_prdt(size_t num_entries) {
7577
return (prdt_entry_t*)malloc(num_entries * sizeof(prdt_entry_t));
7678
}
7779

80+
prdt_entry_t* free_prdt(prdt_entry_t* a) {
81+
return (prdt_entry_t*)free(a);
82+
}
83+
7884
int read_sectors(uint32_t lba, uint32_t sector_count, void* buffer) {
79-
// 1. Get AHCI command header and PRDT
85+
if (sector_count == 0) return -1; // Handle invalid input
86+
8087
ahci_command_header_t* cmd_header = get_free_command_header();
88+
if (!cmd_header) return -1; // Handle allocation failure
89+
8190
prdt_entry_t* prdt = allocate_prdt(1);
91+
if (!prdt) {
92+
// free_command_header(cmd_header);
93+
return -1;
94+
}
8295

83-
// 2. Fill command FIS
84-
cmd_header->cfis[0] = 0x27; // ATA command: Read
85-
cmd_header->cfis[2] = lba & 0xFF;
86-
cmd_header->cfis[3] = (lba >> 8) & 0xFF;
87-
cmd_header->cfis[4] = (lba >> 16) & 0xFF;
88-
cmd_header->cfis[5] = (lba >> 24) & 0xFF;
89-
cmd_header->cfis[7] = sector_count & 0xFF;
90-
cmd_header->cfis[8] = (sector_count >> 8) & 0xFF;
91-
92-
// 3. Fill PRDT
93-
prdt[0].dba = (uint32_t)buffer; // Address of the buffer to store data
94-
prdt[0].dbc = sector_count * SECTOR_SIZE - 1; // Number of bytes to transfer
95-
96-
// 4. Set up command header
97-
cmd_header->prdtl = sizeof(prdt_entry_t); // Size of PRDT
96+
// 1. Fill command FIS (Corrected for 48-bit LBA if needed)
97+
cmd_header->cfis[0] = 0x20; // ATA command: Read (0x20 for 28-bit, 0x24 for 48-bit)
98+
99+
if (lba > 0xFFFFFFF || (lba + sector_count) > 0xFFFFFFF) { // Check for 28-bit overflow
100+
cmd_header->cfis[0] = 0x24; // Use 48-bit command if needed
101+
cmd_header->cfis[1] = 0;
102+
cmd_header->cfis[2] = lba & 0xFF;
103+
cmd_header->cfis[3] = (lba >> 8) & 0xFF;
104+
cmd_header->cfis[4] = (lba >> 16) & 0xFF;
105+
cmd_header->cfis[5] = (lba >> 24) & 0xFF;
106+
cmd_header->cfis[6] = (lba >> 32) & 0xFF; // LBA 48 bit
107+
cmd_header->cfis[7] = (lba >> 40) & 0xFF; // LBA 48 bit
108+
cmd_header->cfis[8] = sector_count & 0xFF;
109+
cmd_header->cfis[9] = (sector_count >> 8) & 0xFF; // Sector count 16 bit
110+
} else {
111+
cmd_header->cfis[2] = lba & 0xFF;
112+
cmd_header->cfis[3] = (lba >> 8) & 0xFF;
113+
cmd_header->cfis[4] = (lba >> 16) & 0xFF;
114+
cmd_header->cfis[5] = (lba >> 24) & 0xFF;
115+
cmd_header->cfis[7] = sector_count & 0xFF;
116+
cmd_header->cfis[8] = (sector_count >> 8) & 0xFF;
117+
}
118+
119+
120+
// 2. Fill PRDT (Corrected DBC)
121+
prdt[0].dba = (uint32_t)buffer;
122+
prdt[0].dbc = sector_count * SECTOR_SIZE - 1; // Byte count, not sector count
123+
124+
// 3. Set up command header
125+
cmd_header->prdtl = 1; // Number of PRDT entries, not size in bytes.
98126
cmd_header->prdt = (uint32_t)prdt;
99127

100-
// 5. Issue the command
101-
cmd_header->ci = 1; // Issue command
128+
// 4. Issue the command
129+
cmd_header->ci = 1;
102130

131+
// 5. **CRITICAL:** Wait for command completion. This is the most likely source of your original problem.
132+
wait_for_command_completion(cmd_header);
103133

104-
sleep(2);
134+
// 6. Check for errors (add this!)
135+
if (cmd_header->ciss & 0x1) { // Error bit set
136+
// free_command_header(cmd_header);
137+
free_prdt(prdt);
138+
return -1; // Or a more specific error code.
139+
}
140+
141+
// free_command_header(cmd_header);
142+
free_prdt(prdt);
105143

106-
// 7. Read data from the buffer
144+
return 0;
145+
}
107146

108-
return 0; // Command successful
109-
}
147+
void wait_for_command_completion(ahci_command_header_t* cmd_header) {
148+
volatile uint32_t* status_reg = (volatile uint32_t*)(cmd_header + 0x08); // Example, adjust as needed.
149+
while (1) {
150+
if (! (status_reg[0] & (1 << 7))) { // Check BSY (Busy) bit in PxSATASTATUS register
151+
break;
152+
}
153+
}
154+
155+
// Check the command complete (CC) bit in the command header.
156+
// while (cmd_header->ci) ; // Wait for CI to clear (command complete)
157+
}

0 commit comments

Comments
 (0)