can somebody help me with an issue? I’m working on an operating system project of a 32 bit protected mode.
I’m currently writing a file system so I first need to initialize communication with the disk -basically I need function to read and write sectors. I chose the ATA PIO interface and wrote some simple functions but when I try to execute them I appear to get stuck inside the function ata_read_sector. Any ideas? To run my code I first compile it, then make an ISO file that is loaded into a QEMU virtual machine. To create the virtual hard drive I use the following command:
/usr/bin/qemu-img create -f qcow2 os-disk.qcow2 512M
# This starts a GParted virtual machine that is used to define the ext2 partition to the hard drive used by the os
/usr/bin/qemu-system-i386 -cdrom gparted-live-1.6.0-3-i686.iso -hda os-disk.qcow2 -boot d -m 512
(I use GParted to format the disk)
(I then format this virtual hard drive to have one partition and work with a specific file system design such as ext2)
#define ATA_PRIMARY_IO 0x1F0
#define ATA_PRIMARY_DATA 0x1F0
#define ATA_PRIMARY_ERROR 0x1F1
#define ATA_PRIMARY_SECCOUNT 0x1F2
#define ATA_PRIMARY_LBA0 0x1F3
#define ATA_PRIMARY_LBA1 0x1F4
#define ATA_PRIMARY_LBA2 0x1F5
#define ATA_PRIMARY_DRIVE 0x1F6
#define ATA_PRIMARY_COMMAND 0x1F7
#define ATA_PRIMARY_STATUS 0x1F7
#define ATA_PRIMARY_ALTSTATUS 0x3F6
#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_WRITE_PIO 0x30
#define ATA_CMD_IDENTIFY 0xEC
#define ATA_SR_BSY 0x80
#define ATA_SR_DRQ 0x08
uint8_t port_inb(uint8_t portnumber)
{
uint8_t result;
__asm__ volatile("inb %1, %0" : "=a" (result) : "Nd" ((uint16_t)portnumber));
return result;
}
void port_outb(uint16_t port, uint8_t data)
{
__asm__ volatile("outb %0, %1" : : "a" (data), "Nd" (port));
}
void port_insw(uint16_t port, void* addr, int count)
{
__asm__ volatile("rep insw" : "+D"(addr), "+c"(count) : "d"(port) : "memory");
}
void port_outsw(uint16_t port, void* addr, int count)
{
__asm__ volatile("rep outsw" : "+S"(addr), "+c"(count) : "d"(port));
}
void ata_initialize()
{
// Initialize both primary and secondary ATA buses, master and slave
port_outb(0x1F6, 0xA0); // Select master drive on primary bus
// You can add additional initialization for slave or secondary if needed
printf((uint8_t*)" exiting initlize",0);
}
void ata_wait_bsy()
{
while (port_inb(ATA_PRIMARY_STATUS) & ATA_SR_BSY);
}
void ata_wait_drq()
{
while (!(port_inb(ATA_PRIMARY_STATUS) & ATA_SR_DRQ));
}
void ata_read_sector(uint32_t lba, uint8_t* buffer)
{
printf((uint8_t*)"in ata read sector n",0);
// Read from a specified location
ata_wait_bsy();
port_outb(ATA_PRIMARY_DRIVE, 0xE0 | ((lba >> 24) & 0x0F));
port_outb(ATA_PRIMARY_SECCOUNT, 1);
port_outb(ATA_PRIMARY_LBA0, (uint8_t)lba);
port_outb(ATA_PRIMARY_LBA1, (uint8_t)(lba >> 8));
port_outb(ATA_PRIMARY_LBA2, (uint8_t)(lba >> 16));
port_outb(ATA_PRIMARY_COMMAND, ATA_CMD_READ_PIO);
ata_wait_bsy();
ata_wait_drq();
printf((uint8_t*)"exited stage n",0);
port_insw(ATA_PRIMARY_DATA, buffer, 256); // Read 256 words (512 bytes)
}
void ata_write_sector(uint32_t lba, uint8_t* buffer)
{
ata_wait_bsy();
port_outb(ATA_PRIMARY_DRIVE, 0xE0 | ((lba >> 24) & 0x0F));
port_outb(ATA_PRIMARY_SECCOUNT, 1);
port_outb(ATA_PRIMARY_LBA0, (uint8_t)lba);
port_outb(ATA_PRIMARY_LBA1, (uint8_t)(lba >> 8));
port_outb(ATA_PRIMARY_LBA2, (uint8_t)(lba >> 16));
port_outb(ATA_PRIMARY_COMMAND, ATA_CMD_WRITE_PIO);
ata_wait_bsy();
ata_wait_drq();
port_outsw(ATA_PRIMARY_DATA, buffer, 256); // Write 256 words (512 bytes)
}
## and then in the main kernel file
ata_initialize();
uint8_t buffer[512];
uint32_t sector = 0;
ata_read_sector(sector, buffer);
printf((uint8_t*)buffer,0);
The last print message I’m getting is “in ata read sector”.
Any ideas?