matos/drivers/ata.c

72 lines
1.7 KiB
C

#include "ata.h"
#include "io.h"
#include "kernel.h"
#include "klibc.h"
static struct ata_drive drives[4];
int ATADectectType(struct ata_drive *drive)
{
outb(drive->base + ATA_PIO_DRIVE, 0xA0 | drive->isSlave << 4);
outb(drive->base + ATA_PIO_SEC_COUNT, 0x0);
outb(drive->base + ATA_PIO_LBALO, 0x0);
outb(drive->base + ATA_PIO_LBAMID, 0x0);
outb(drive->base + ATA_PIO_LBAHI, 0x0);
outb(drive->base + ATA_PIO_CMD, ATA_PIO_CMD_IDENTIFY);
unsigned st = inb(drive->base + ATA_PIO_STATUS);
if(st & ATA_PIO_STATUS_DRIVE_BUSY)
goto no_disk;
inb(drive->dev_ctl); /* Drop the next 4 read to wait */
inb(drive->dev_ctl);
inb(drive->dev_ctl);
inb(drive->dev_ctl);
unsigned cl = inb(drive->base + ATA_PIO_LBAMID); /* get the "signature bytes" */
unsigned ch = inb(drive->base + ATA_PIO_LBAHI);
/* differentiate ATA, ATAPI, SATA and SATAPI */
if (cl == 0x14 && ch == 0xEB) {
drive->status = ATA_DEV_PATAPI;
return 0;
}
if (cl == 0x69 && ch == 0x96) {
drive->status = ATA_DEV_SATAPI;
return 0;
}
if (cl == 0 && ch == 0) {
drive->status = ATA_DEV_PATA;
return 0;
}
if (cl == 0x3c && ch == 0xc3) {
drive->status = ATA_DEV_SATA;
return 0;
}
no_disk:
drive->status = ATA_DEV_UNKNOWN;
return -1;
}
int ATAInit()
{
memset(drives, 0, sizeof(drives));
drives[0].base = 0x1F0;
drives[0].dev_ctl = 0x3F6;
drives[0].isSlave = 0;
drives[1].base = 0x1F0;
drives[1].dev_ctl = 0x3F6;
drives[1].isSlave = 1;
drives[1].base = 0x170;
drives[1].dev_ctl = 0x376;
drives[1].isSlave = 0;
drives[2].base = 0x170;
drives[2].dev_ctl = 0x376;
drives[2].isSlave = 1;
for(uint i = 0; i < ARRAY_SIZE(drives); i++){
if(!ATADectectType(&drives[i])){
printf("Driver %d detected %d\n", i, drives[i].status);
}
}
return 0;
}