72 lines
1.7 KiB
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;
|
|
}
|