So I wrote a new ATA_init() function where I fixed some of the issues. Unfortuantely, I'm still getting some weird behavior. On the machine I'm running my OS there is nothing attached to secondary channel but the status register doesn't turn to 0 after sending Identify command. You can see what's happenning on the picture I attached. I don't think it's the problem with secondary channel on the machine because when I connect the devices to secondary channel I'm having the same problem. It recognizes attached devices correctly.
Here is the code:
Code:
void ATA_init(){
terminal_print(debugTerminal, "Initializing ATA...\n");
channels[0].base = 0x1F0;
channels[0].ctrl = 0x3F6;
channels[1].base = 0x170;
channels[1].ctrl = 0x376;
int id = 0;
for(int ch=0; ch<2; ch++){
for(int dr=0; dr<2; dr++){
ATADevices[id].exists = false;
ATADevices[id].channel = ch;
ATADevices[id].drive = dr;
id++;
}
}
for(int id=0; id<4; id++){
int ch = ATADevices[id].channel;
int dr = ATADevices[id].drive;
// https://wiki.osdev.org/ATA_PIO_Mode#IDENTIFY_command
terminal_print(debugTerminal, "Status reg before command: %x\n", inb(channels[ch].base + ATA_REG_STATUS));
outb(channels[ch].base + ATA_REG_HDDEVSEL, (uint8_t []){0xA0, 0xB0}[dr]);
io_wait();
outb(channels[ch].base + ATA_REG_LBAlo, 0);
io_wait();
outb(channels[ch].base + ATA_REG_LBAmid, 0);
io_wait();
outb(channels[ch].base + ATA_REG_LBAhi, 0);
io_wait();
outb(channels[ch].base + ATA_REG_COMMAND, (uint8_t)(ATA_CMD_IDENTIFY));
long_wait();
terminal_print(debugTerminal, "Status reg after command: %x\n", inb(channels[ch].base + ATA_REG_STATUS));
if(inb(channels[ch].base + ATA_REG_STATUS) == 0){
terminal_print(debugTerminal, "Drive %d doesn't exist\n", id);
continue;
}
terminal_print(debugTerminal, "Drive %d seems to exist\n", id);
uint8_t type = IDE_ATA;
// Polling
uint8_t error = 0, status = 0;
while((status & ATA_SR_BSY) || !(status & ATA_SR_DRQ)) {
status = inb(channels[ch].base + ATA_REG_STATUS);
if(status & ATA_SR_ERR){ // If Err, Device is not ATA.
error = inb(channels[ch].base + ATA_REG_ERROR);
break;
}
}
if(error){
print_error(error);
uint8_t LBAmid = inb(channels[ch].base + ATA_REG_LBAmid);
uint8_t LBAhi = inb(channels[ch].base + ATA_REG_LBAhi);
if (LBAmid == 0x14 && LBAhi == 0xEB)
type = IDE_ATAPI;
else if (LBAmid == 0x69 && LBAhi == 0x96)
type = IDE_ATAPI;
else{
terminal_print(debugTerminal, "\t-> unknown type of a device. Running soft reset on the channel and skipping device\n", id);
soft_reset(ch);
continue; // Unknown Type (may not be a device).
}
terminal_print(debugTerminal, "\t-> it's ATAPI device\n", id);
outb(channels[ch].base + ATA_REG_COMMAND, (uint8_t)(ATA_CMD_IDENTIFY_PACKET));
long_wait();
error = 0, status = 0;
while((status & ATA_SR_BSY) || !(status & ATA_SR_DRQ)){
status = inb(channels[ch].base + ATA_REG_STATUS);
// ATAPI devices seem to throw ATA_ER_ABRT error even when everything is right for some reason so I commented it out
/*if(status & ATA_SR_ERR){
error = inb(channels[ch].base + ATA_REG_ERROR);
if(error != ATA_ER_ABRT)
break;
}*/
}
if(error){
print_error(error);
terminal_print(debugTerminal, "\t-> unexpected error. Running soft reset on the channel and skipping device\n", id);
soft_reset(ch);
continue;
}
}
// Reading data
char data_buffer[512];
insw(channels[ch].base + ATA_REG_DATA, (uint16_t *)data_buffer, 256);
ATADevices[id].exists = true;
ATADevices[id].type = type;
ATADevices[id].signature = *((uint16_t *)(data_buffer + ATA_IDENT_DEVICETYPE));
ATADevices[id].capabilities = *((uint16_t *)(data_buffer + ATA_IDENT_CAPABILITIES));
ATADevices[id].commandSets = *((uint32_t *)(data_buffer + ATA_IDENT_COMMANDSETS));
if(ATADevices[id].commandSets & (1 << 26)) // Device uses 48-Bit Addressing
ATADevices[id].size = *((int *)(data_buffer + ATA_IDENT_MAX_LBA_EXT));
else // Device uses CHS or 28-bit Addressing
ATADevices[id].size = *((int *)(data_buffer + ATA_IDENT_MAX_LBA));
for(int k=0; k<40; k+=2){
ATADevices[id].model[k] = data_buffer[ATA_IDENT_MODEL + k + 1];
ATADevices[id].model[k + 1] = data_buffer[ATA_IDENT_MODEL + k];
ATADevices[id].model[40] = 0; // Terminate String.
}
terminal_print(debugTerminal, "\t-> size: %uGB, type: %s, model: %s\n",
ATADevices[id].size / 1024 / 1024 / 2,
(char *[]){"ATA", "ATAPI"}[ATADevices[id].type],
ATADevices[id].model);
}
terminal_print(debugTerminal, "[X] ATA ready!\n");
}