Steal ata driver.

This commit is contained in:
Alexander Myltsev 2022-11-17 22:57:04 +03:00
parent 0be6fbed9d
commit e31e56f8f9
2 changed files with 82 additions and 0 deletions

80
drivers/ata.c Normal file
View File

@ -0,0 +1,80 @@
// stolen from https://github.com/dhavalhirdhav/LearnOS/blob/master/drivers/ata/ata.c
#include <stdint.h>
#include "ata.h"
#include "../ports.h"
/*
BSY: a 1 means that the controller is busy executing a command. No register should be accessed (except the digital output register) while this bit is set.
RDY: a 1 means that the controller is ready to accept a command, and the drive is spinning at correct speed..
WFT: a 1 means that the controller detected a write fault.
SKC: a 1 means that the read/write head is in position (seek completed).
DRQ: a 1 means that the controller is expecting data (for a write) or is sending data (for a read). Don't access the data register while this bit is 0.
COR: a 1 indicates that the controller had to correct data, by using the ECC bytes (error correction code: extra bytes at the end of the sector that allows to verify its integrity and, sometimes, to correct errors).
IDX: a 1 indicates the the controller retected the index mark (which is not a hole on hard-drives).
ERR: a 1 indicates that an error occured. An error code has been placed in the error register.
*/
#define STATUS_BSY 0x80
#define STATUS_RDY 0x40
#define STATUS_DRQ 0x08
#define STATUS_DF 0x20
#define STATUS_ERR 0x01
//This is really specific to out OS now, assuming ATA bus 0 master
//Source - OsDev wiki
static void ATA_wait_BSY();
static void ATA_wait_DRQ();
void read_sectors_ATA_PIO(uint32_t target_address, uint32_t LBA, uint8_t sector_count)
{
ATA_wait_BSY();
port_byte_out(0x1F6,0xE0 | ((LBA >>24) & 0xF));
port_byte_out(0x1F2,sector_count);
port_byte_out(0x1F3, (uint8_t) LBA);
port_byte_out(0x1F4, (uint8_t)(LBA >> 8));
port_byte_out(0x1F5, (uint8_t)(LBA >> 16));
port_byte_out(0x1F7,0x20); //Send the read command
uint16_t *target = (uint16_t*) target_address;
for (int j =0;j<sector_count;j++)
{
ATA_wait_BSY();
ATA_wait_DRQ();
for(int i=0;i<256;i++)
target[i] = port_word_in(0x1F0);
target+=256;
}
}
void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t* bytes)
{
ATA_wait_BSY();
port_byte_out(0x1F6,0xE0 | ((LBA >>24) & 0xF));
port_byte_out(0x1F2,sector_count);
port_byte_out(0x1F3, (uint8_t) LBA);
port_byte_out(0x1F4, (uint8_t)(LBA >> 8));
port_byte_out(0x1F5, (uint8_t)(LBA >> 16));
port_byte_out(0x1F7,0x30); //Send the write command
for (int j =0;j<sector_count;j++)
{
ATA_wait_BSY();
ATA_wait_DRQ();
for(int i=0;i<256;i++)
{
port_long_out(0x1F0, bytes[i]);
}
}
}
static void ATA_wait_BSY() //Wait for bsy to be 0
{
while(port_byte_in(0x1F7)&STATUS_BSY);
}
static void ATA_wait_DRQ() //Wait fot drq to be 1
{
while(!(port_byte_in(0x1F7)&STATUS_RDY));
}

2
drivers/ata.h Normal file
View File

@ -0,0 +1,2 @@
void read_sectors_ATA_PIO(uint32_t target_address, uint32_t LBA, uint8_t sector_count);
void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t* bytes);