lenochka/kernel_old/ahci.c
2019-03-29 00:27:42 +02:00

169 lines
3.4 KiB
C

#include "ahci.h"
#include "pci.h"
#include "pit.h"
#include "io.h"
#include "paging.h"
#include "stdlib.h"
typedef struct {
u32 hba_phys;
hba_port_t* sata;
hba_port_t* atapi;
} ahci_t;
static ahci_t s_ahci;
static hba_mem_t* HBA;
static __align(4096) u16 buf[256];
void sata_identify()
{
hba_cmd_header_t* cmdhdr = (hba_cmd_header_t*)s_ahci.sata->clb;
hba_cmd_tbl_t* cmdtbl = (hba_cmd_tbl_t*)cmdhdr->ctba;
fis_reg_h2d_t* fis = (fis_reg_h2d_t*)&cmdtbl->cfis;
kprintf("cmdhdr %x cmdtbl %x fis %x\n",cmdhdr,cmdtbl,fis);
s_ahci.sata->is = 0xFFFFFFFF;
cmdhdr->cfl = sizeof(fis_reg_h2d_t)/sizeof(u32);
cmdhdr->w = 0;
cmdhdr->prdtl = 1;
kmemzero(cmdtbl, sizeof(hba_cmd_tbl_t) +
(cmdhdr->prdtl-1)*sizeof(hba_prdt_entry_t));
kmemzero(fis,sizeof(fis_reg_h2d_t));
/*fis->fis_type = FIS_TYPE_REG_H2D;
fis->c = 1;
fis->command = ATA_CMD_IDENTIFY;
fis->device = ATA_LBA_MODE; // Master*/
fis->fis_type = FIS_TYPE_REG_H2D;
fis->c = 1;
fis->command = 0xEC;
fis->lba0 = 0;
fis->lba1 = 0;
fis->lba2 = 0;
fis->device = ATA_LBA_MODE;
fis->lba3 = 0;
fis->lba4 = 0;
fis->lba5 = 0;
fis->countl = 1;
fis->counth = 0;
kmemzero(&cmdtbl->prdt_entry[0],sizeof(hba_prdt_entry_t));
cmdtbl->prdt_entry[0].dba = page_v2p((u32)buf);
cmdtbl->prdt_entry[0].dbc = 511; // 512 bytes
cmdtbl->prdt_entry[0].i = 0;
kprintf("s_ahci.sata->tfd %x\n",s_ahci.sata->tfd);
kprintf("s_ahci.sata->ci %x\n",s_ahci.sata->ci);
kprintf("s_ahci.sata->sact %x\n",s_ahci.sata->sact);
_debug();
//Wait before executing new commands
while(s_ahci.sata->tfd & (ATA_DEV_BUSY|ATA_DEV_DRQ))
{
kprintf("wait to issue cmd\n");
}
s_ahci.sata->ci = (1<<0);
while((s_ahci.sata->ci & (1<<0)) != 0)
{
if(s_ahci.sata->is & (1<<5))
{
kprintf("disk error\n");
return;
}
kprintf("wait\n");
}
kprintf("IDENTIFY command executed!\n");
kprintf("%x %x %u",buf,buf[83],*(u32*)&buf[60]);
}
void ahci_init()
{
pci_device_t ahci;
u32 bar;
//Use PCI
ahci = pci_find_device(0x01,0x06);
if(ahci == 0)
{
kprintf("AHCI not found!\n");
return;
}
bar = pci_read_config_word_dev(ahci,0x24);
s_ahci.hba_phys = bar & 0xFFFFFFF0;
kprintf("HBA %x\n",s_ahci.hba_phys);
//Identity map
page_map(s_ahci.hba_phys,s_ahci.hba_phys,
16384,PAGE_TABLE_READWRITE);
HBA = (hba_mem_t*)s_ahci.hba_phys;
HBA->ghc |= (1<<31); //Enable GHC.AE
if(HBA->cap & (1<<27))
{
kprintf("AHCI supports stagered spin-up\n");
}
//kprintf("pi %x\n",HBA->pi);
for(u32 i = 0; i < 32; i++)
{
hba_port_t* port = &HBA->ports[i];
if(!((HBA->pi>>i)&1)) continue;
switch(port->sig)
{
case SATA_SIG_ATA: s_ahci.sata = port; break;
case SATA_SIG_ATAPI: s_ahci.atapi = port; break;
}
//Initialize port
if(port->cmd & (SCMD_ST|SCMD_FR|SCMD_CR|SCMD_FRE)) //Isn't IDLE
{
port->cmd &= ~SCMD_ST;
while(port->cmd & SCMD_CR)
{
sleep(1000);
}
port->cmd &= ~SCMD_FRE;
while(port->cmd & SCMD_FR)
{
sleep(1000);
}
}
//Start it again
port->cmd |= SCMD_ST|SCMD_FRE;
//Clear SERR
port->serr = 0xFFFFFFFF;
port->ie = 0;
u32 data = port->is;
port->is = data;
}
HBA->is = 0;
page_map(s_ahci.sata->clb,s_ahci.sata->clb,
AHCI_CLB_SIZE,PAGE_DIR_READWRITE);
page_map(s_ahci.sata->fb,s_ahci.sata->fb,
AHCI_FB_SIZE,PAGE_DIR_READWRITE);
page_map(s_ahci.atapi->clb,s_ahci.sata->clb,
AHCI_CLB_SIZE,PAGE_DIR_READWRITE);
page_map(s_ahci.atapi->fb,s_ahci.sata->fb,
AHCI_FB_SIZE,PAGE_DIR_READWRITE);
//Initialize SATA and ATAPI
//sata_identify();
}