122 lines
2.3 KiB
C
122 lines
2.3 KiB
C
#include "ata_pio.h"
|
|
#include "io.h"
|
|
#include "pic.h"
|
|
#include "idt.h"
|
|
#include "pci.h"
|
|
#include "exceptions.h"
|
|
#include "stdlib.h"
|
|
|
|
typedef struct {
|
|
u8 buf[512];
|
|
u16 io_base;
|
|
u16 ctrl_base;
|
|
u32 slavebit;
|
|
u32 wait;
|
|
} ata_pio_t;
|
|
|
|
static ata_pio_t s_ata;
|
|
|
|
void ata_interrupt_master(int idx)
|
|
{
|
|
s_ata.wait = 0;
|
|
kprintf("interrupt happend\n");
|
|
}
|
|
|
|
void ata_wait()
|
|
{
|
|
__asm("cli");
|
|
s_ata.wait = 1;
|
|
__asm("sti");
|
|
do {
|
|
__asm("hlt");
|
|
} while(s_ata.wait);
|
|
}
|
|
|
|
void ata_init_drive(u8 drv,u8 slavebit)
|
|
{
|
|
u8 poll;
|
|
|
|
if(!slavebit)
|
|
{
|
|
s_ata.io_base = slavebit ? 0x170 : 0xC080;
|
|
s_ata.ctrl_base = 0x3E6;
|
|
}
|
|
else
|
|
{
|
|
s_ata.io_base = slavebit ? 0x168 : 0x1E8;
|
|
s_ata.ctrl_base = 0x366;
|
|
}
|
|
|
|
kprintf("s_ata.io_base %x\ns_ata.ctrl_base %x\n",
|
|
s_ata.io_base,s_ata.ctrl_base);
|
|
|
|
outb(s_ata.io_base + ATA_DRV,slavebit ? 0xB0 : 0xA0);
|
|
|
|
outb(s_ata.io_base + ATA_LBALO,0);
|
|
outb(s_ata.io_base + ATA_LBAMID,0);
|
|
outb(s_ata.io_base + ATA_LBAHI,0);
|
|
|
|
outb(s_ata.io_base + ATA_COMMAND,ATA_CMD_IDENTIFY);
|
|
|
|
if(inb(s_ata.io_base + ATA_STATUS) == 0) return;
|
|
// Poll status
|
|
while((poll=inb(s_ata.io_base + ATA_STATUS)) & ATA_STS_BSY)
|
|
{
|
|
if(poll == 0xFF)
|
|
{
|
|
kprintf("ATA Drive not found!\n");
|
|
return;
|
|
}
|
|
kprintf("polling 1 (%x)\n",inb(s_ata.io_base + ATA_STATUS));
|
|
}
|
|
if(inb(s_ata.io_base + ATA_LBAMID) | s_ata.io_base + ATA_LBAHI)
|
|
{
|
|
kprintf("Non-ATA\n");
|
|
return; // Non-ATA
|
|
}
|
|
// Wait DRQ
|
|
while((inb(s_ata.io_base + ATA_STATUS) & ATA_STS_DRQ) == 0)
|
|
{
|
|
kprintf("polling 2\n");
|
|
if(inb(s_ata.io_base + ATA_STATUS) & ATA_STS_ERR)
|
|
{
|
|
kprintf("ATA_STS_ERR\n");
|
|
return;
|
|
}
|
|
}
|
|
// Read data
|
|
_insw256(s_ata.io_base + ATA_DATA,s_ata.buf);
|
|
|
|
kprintf("LBA size %u\n",*(u32*)(&s_ata.buf[0xC0]));
|
|
}
|
|
|
|
void ata_init()
|
|
{
|
|
pci_device_t sata;
|
|
u32 irq;
|
|
u32 bar[6];
|
|
|
|
|
|
//Use PCI
|
|
sata = pci_find_device(0x01,0x06);
|
|
if(sata == 0)
|
|
{
|
|
kprintf("Serial ATA not found!\n");
|
|
return;
|
|
}
|
|
|
|
kprintf("SATA %x\n",sata);
|
|
for(u32 i = 0; i < 6; i++)
|
|
{
|
|
bar[i] = pci_read_config_word_dev(sata,0x10+(i<<2));
|
|
kprintf("bar%u %x\n",i,bar[i]);
|
|
}
|
|
irq = pci_read_config_word_dev(sata,0x3C)&0xFF;
|
|
kprintf("SATA irq %u\n",irq);
|
|
kprintf("SATA prog_if %x\n",(pci_read_config_word_dev(sata,0x08)&0x0000FF00)>>8);
|
|
|
|
pic_set_mask(14,1);
|
|
idt_setup(_int14_handler,ata_interrupt_master,
|
|
46,IDT_TYPE_INTERRUPT);
|
|
|
|
}
|