I'm encountering a paging fault in my custom OS when attempting to perform ATA read and write operations in my
Code: Select all
updateDir
Code: Select all
// Read the current directory entries from the disk
uint8_t dir_buffer[MAX_DIR * 16] = {0};
ata_identify(ATA_PRIMARY_IO, ATA_MASTER);
ata_read(ATA_PRIMARY_IO, ATA_MASTER, START_DIR, 1, dir_buffer);
// Copy the DirEntry struct into the directory buffer at the correct position
memcpy(&dir_buffer[pos * 16], &entry, sizeof(DirEntry));
// Write the updated directory entries back to the disk
ata_identify(ATA_PRIMARY_IO, ATA_MASTER);
ata_write(ATA_PRIMARY_IO, ATA_MASTER, START_DIR, MAX_DIR * 16 / 512, dir_buffer);
Code: Select all
CR2=00000000
EIP=c01015d0
Here's the full function where the problematic code resides:
Code: Select all
bool_t updateDir(char* filename) {
DirEntry entry = {0};
strncpy((char *)entry.name, filename, sizeof(entry.name) - 1);
entry.size = 0;
int pos = -1;
// Find the first available directory slot
for (int i = 0; i < MAX_DIR; i++) {
if (dir[i] == 0) {
dir[i] = 1;
entry.fat_entry = i;
pos = i;
break;
}
}
if (pos == -1) {
printf("Error: No free directory entry found\n");
return false;
}
uint8_t dir_buffer[MAX_DIR * 16] = {0};
ata_identify(ATA_PRIMARY_IO, ATA_MASTER);
ata_read(ATA_PRIMARY_IO, ATA_MASTER, START_DIR, 1, dir_buffer);
memcpy(&dir_buffer[pos * 16], &entry, sizeof(DirEntry));
ata_identify(ATA_PRIMARY_IO, ATA_MASTER);
ata_write(ATA_PRIMARY_IO, ATA_MASTER, START_DIR, MAX_DIR * 16 / 512, dir_buffer);
return true;
}
Code: Select all
#include "../Includes/ata.h"
void ata_initialize(uint16_t io_base, uint8_t drive) {
outPort(io_base + 6, drive);
outPort(io_base + 2, 0);
outPort(io_base + 3, 0);
outPort(io_base + 4, 0);
outPort(io_base + 5, 0);
outPort(io_base + 7, 0xEC);
uint8_t status = inPort(io_base + 7);
// Wait for BSY to clear
while ((status & 0x80) != 0) {
status = inPort(io_base + 7);
}
}
static void ata_wait_bsy(uint16_t io_base) {
while (inPort(io_base + 7) & 0x80); // Wait for BSY to clear
}
static void ata_wait_drq(uint16_t io_base) {
while (!(inPort(io_base + 7) & 0x08)); // Wait for DRQ to set
}
void ata_read(uint16_t io_base, uint8_t drive, uint32_t lba, uint8_t sectors, uint8_t* buffer) {
if (!buffer || sectors == 0) {
return;
}
if (sectors > 256) {
return;
}
// Select drive and LBA
outPort(io_base + 6, 0xE0 | (drive << 4) | ((lba >> 24) & 0x0F));
outPort(io_base + 2, sectors);
outPort(io_base + 3, (uint8_t)(lba));
outPort(io_base + 4, (uint8_t)(lba >> 8));
outPort(io_base + 5, (uint8_t)(lba >> 16));
outPort(io_base + 7, 0x20); // Read command
for (uint8_t i = 0; i < sectors; i++) {
ata_wait_bsy(io_base);
if (inPort(io_base + 7) & 0x01) { // Check for error
printf("ATA read error on sector %u.\n",RED_ON_BLACK_WARNING, lba + i);
return;
}
ata_wait_drq(io_base);
for (uint16_t j = 0; j < ATA_SECTOR_SIZE / 2; j++) {
((uint16_t*)buffer)[j] = inPort16(io_base);
}
buffer += ATA_SECTOR_SIZE;
}
}
void ata_write(uint16_t io_base, uint8_t drive, uint32_t lba, uint8_t sectors, const uint8_t* buffer) {
outPort(io_base + 6, 0xE0 | (drive << 4) | ((lba >> 24) & 0x0F));
outPort(io_base + 2, sectors);
outPort(io_base + 3, (uint8_t)(lba));
outPort(io_base + 4, (uint8_t)(lba >> 8));
outPort(io_base + 5, (uint8_t)(lba >> 16));
outPort(io_base + 7, 0x30);
for (uint8_t i = 0; i < sectors; i++) {
ata_wait_bsy(io_base);
ata_wait_drq(io_base);
for (uint16_t j = 0; j < ATA_SECTOR_SIZE / 2; j++) {
outPort16(io_base, ((uint16_t*)buffer)[j]);
}
buffer += ATA_SECTOR_SIZE;
}
ata_wait_bsy(io_base);
outPort(io_base + 7, 0xE7);
ata_wait_bsy(io_base);
}
void ata_identify(uint16_t io_base, uint8_t drive) {
outPort(io_base + 6, drive);
outPort(io_base + 2, 0);
outPort(io_base + 3, 0);
outPort(io_base + 4, 0);
outPort(io_base + 5, 0);
outPort(io_base + 7, 0xEC);
ata_wait_bsy(io_base);
uint8_t status = inPort(io_base + 7);
if (status == 0) {
printf("No ATA device detected.\n", COLOR_BLACK_ON_WHITE);
return;
}
uint16_t buffer[256];
for (uint16_t i = 0; i < 256; i++) {
buffer[i] = inPort16(io_base);
}
}
1. Verified that the dir_buffer array is allocated correctly.
2. Checked the ata_identify and ata_read/ata_write functions, and they seem to work in other contexts.
3. Confirmed that the START_DIR address is within the expected range.
Any help or suggestions would be greatly appreciated!
Thank you in advance.
https://github.com/IlanVinograd/OS_32Bi ... keyboard.c