header:
Code: Select all
#define S2_ATA_BIT_BSY 0x80 // Busy
#define S2_ATA_BIT_DRDY 0x40 // Drive ready
#define S2_ATA_BIT_DEVF 0x20 // Drive write fault
#define S2_ATA_BIT_DSC 0x10 // Drive seek complete
#define S2_ATA_BIT_DRQ 0x08 // Data request ready
#define S2_ATA_BIT_CORR 0x04 // Corrected data
#define S2_ATA_BIT_IDX 0x02 // Index
#define S2_ATA_BIT_ERR 0x01 // Error
#define S2_ATA_REG_DATA 0x00
#define S2_ATA_REG_ERROR 0x01
#define S2_ATA_REG_FEATURES 0x01
#define S2_ATA_REG_SECCOUNT0 0x02
#define S2_ATA_REG_LBA0 0x03
#define S2_ATA_REG_LBA1 0x04
#define S2_ATA_REG_LBA2 0x05
#define S2_ATA_REG_HDDEVSEL 0x06
#define S2_ATA_REG_COMMAND 0x07
#define S2_ATA_REG_STATUS 0x07
#define S2_ATA_REG_CONTROL 0x206
#define S2_ATA_REG_ALTSTATUS 0x206
#define S2_ATAERR_NOERR 0
#define S2_ATAERR_ERR 0
#define S2_ATAERR_DEVF 1
#define S2_ATAERR_DRQ 2
#define S2_ATA_IERR_BBK 0x80 // Bad block
#define S2_ATA_IERR_UNC 0x40 // Uncorrectable data
#define S2_ATA_IERR_MC 0x20 // Media changed
#define S2_ATA_IERR_IDNF 0x10 // ID mark not found
#define S2_ATA_IERR_MCR 0x08 // Media change request
#define S2_ATA_IERR_ABRT 0x04 // Command aborted
#define S2_ATA_IERR_TK0NF 0x02 // Track 0 not found
#define S2_ATA_IERR_AMNF 0x01 // No address mark
#define S2_ATA_TYPE_ATAPI 0
#define S2_ATA_TYPE_ATA 1
#define S2_ATAPI_SECTOR_SIZE 2048
typedef struct
{
bool isPrimary;
s2_UInt16 base;
s2_UInt16 busMaster;
s2_UInt8 nIEN;
} s2_IDEChannel;
typedef struct
{
s2_UInt8 type;
s2_IDEChannel *channel;
bool exists;
bool isMaster;
s2_UInt16 signature;
s2_UInt16 features;
s2_UInt32 commands;
s2_UInt32 capacity;
s2_Byte model[41];
} s2_IDEDevice;
Code: Select all
s2_Byte s2_atapiPacket[12];
s2_UInt8 s2_IDERead(s2_IDEDevice *dev, s2_UInt8 offset)
{
return s2_InB(dev->channel->base+offset);
}
void s2_IDEWrite(s2_IDEDevice *dev, s2_UInt16 offset, s2_UInt16 data)
{
// Data
if (offset == 0)
s2_OutW(dev->channel->base, data);
else
s2_OutB(dev->channel->base+offset, data);
}
s2_UInt8 s2_IDEPoll(s2_IDEDevice *dev)
{
for (int i = 0; i < 4; i++)
s2_IDERead(dev->channel->base, S2_ATA_REG_ALTSTATUS);
while (s2_IDERead(dev->channel->base, S2_ATA_REG_STATUS) & S2_ATA_BIT_BSY) {};
s2_UInt8 state = s2_IDERead(dev->channel->base, S2_ATA_REG_STATUS);
if (state & S2_ATA_BIT_ERR)
return S2_ATAERR_ERR;
if (state & S2_ATA_BIT_DRQ)
return S2_ATAERR_ERR;
if (state & S2_ATA_BIT_DEVF)
return S2_ATAERR_DEVF;
return S2_ATAERR_NOERR;
}
s2_UInt8 s2_IDEATAPIRead(s2_IDEDevice *dev, s2_UInt32 lba, s2_Byte *buffer)
{
s2_UInt8 error;
s2_IDEWrite(dev, S2_ATA_REG_CONTROL, dev->channel->nIEN = ataLock = 0);
s2_atapiPacket[ 0] = 0xA8; // Read packet command
s2_atapiPacket[ 1] = 0x0;
s2_atapiPacket[ 2] = (lba >> 24) & 0xFF;
s2_atapiPacket[ 3] = (lba >> 16) & 0xFF;
s2_atapiPacket[ 4] = (lba >> 8) & 0xFF;
s2_atapiPacket[ 5] = (lba >> 0) & 0xFF;
s2_atapiPacket[ 6] = 0x0;
s2_atapiPacket[ 7] = 0x0;
s2_atapiPacket[ 8] = 0x0;
s2_atapiPacket[ 9] = 1; // Number of sectors
s2_atapiPacket[10] = 0x0;
s2_atapiPacket[11] = 0x0;
s2_IDEWrite(dev, S2_ATA_REG_HDDEVSEL, dev->isMaster ? (0xA0) : (0xB0));
// Delay
for(int i = 0; i < 4; i++)
s2_IDERead(dev, S2_ATA_REG_ALTSTATUS);
// PIO mode
s2_IDEWrite(dev, S2_ATA_REG_FEATURES, 0);
// Size of buffer
s2_IDEWrite(dev, S2_ATA_REG_LBA1, S2_ATAPI_SECTOR_SIZE & 0xFF);
s2_IDEWrite(dev, S2_ATA_REG_LBA2, S2_ATAPI_SECTOR_SIZE >> 8);
// Send packet
s2_IDEWrite(dev, S2_ATA_REG_COMMAND, 0xA0); // Packet command
if (error = s2_IDEPoll(dev)) return error;
s2_TVMPrintA("Status register value:");
s2_TVMPrintA(s2_ToHex(s2_IDERead(dev, S2_ATA_REG_STATUS)));
asm volatile("rep outsw" : : "c"(6), "d"(dev->channel->base), "S"(s2_atapiPacket)); // Send Packet Data
// Wait for irq
while (!ataLock) {}
ataLock = false;
s2_TVMPrintA("got here");
if (error = s2_IDEPoll(dev)) return error;
}
Code: Select all
void irq14_handler(void)
{
ataLock = true;
s2_TVMPrint("sfdasd", 0x70, 0); // Debug
s2_OutB(0xA0, 0x20);
s2_OutB(0x20, 0x20); //EOI
}