add atapi helpers

Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
Julien CLEMENT 2022-12-11 16:36:40 +01:00
parent daca502ce0
commit 1ad893a219

@ -1,52 +1,117 @@
use x86_64::instructions::port::Port;
const CD_SECTOR_SIZE: usize = 2048;
// Data buses
const ATA_BUS_PRIMARY: u16= 0x1f0;
const ATA_BUS_SECONDARY: u16 = 0x170;
const ATA_DRIVE_MASTER: u16 = 0xa0;
const ATA_DRIVE_SLAVE: u16 = 0xb0;
// Drives
const ATA_DRIVE_MASTER: u8 = 0xa0;
const ATA_DRIVE_SLAVE: u8 = 0xb0;
macro_rules! ATA_DATA {
($reg:expr) => (reg);
// Status bits
const ATA_ERR: u8 = 1 << 0;
const ATA_DRQ: u8 = 1 << 3;
const ATA_SRV: u8 = 1 << 4;
const ATA_DF: u8 = 1 << 5;
const ATA_RDY: u8 = 1 << 6;
const ATA_BSY: u8 = 1 << 7;
// ATAPI signature
const ATAPI_SIG_SC: u8 = 0x01;
const ATAPI_SIG_LBA_LO: u8 = 0x01;
const ATAPI_SIG_LBA_MI: u8 = 0x14;
const ATAPI_SIG_LBA_HI: u8 = 0xeb;
static ATAPI_SIG: [u8; 4] = [
ATAPI_SIG_SC,
ATAPI_SIG_LBA_LO,
ATAPI_SIG_LBA_MI,
ATAPI_SIG_LBA_HI
];
struct ATABus {
// IO ports
data: Port<u8>,
features: Port<u8>, // write
error: Port<u8>, // read
sector_count: Port<u8>,
address1: Port<u8>,
address2: Port<u8>,
address3: Port<u8>,
drive_select: Port<u8>,
command: Port<u8>, // write
status: Port<u8>, // read
dcr: Port<u8>,
current_drive: u8,
}
macro_rules! ATA_ERROR {
($reg:expr) => (reg + 1); // read
}
impl ATABus {
pub fn new(port: u16) -> Self {
ATABus {
data: Port::new(port),
features: Port::new(port + 1), // write
error: Port::new(port + 1), // read
sector_count: Port::new(port + 2),
address1: Port::new(port + 3),
address2: Port::new(port + 4),
address3: Port::new(port + 5),
drive_select: Port::new(port + 6),
command: Port::new(port + 7), // write
status: Port::new(port + 7), // read
dcr: Port::new(port + 0x206),
macro_rules! ATA_FEATURES {
($reg:expr) => (reg + 1); // write
}
current_drive: 0,
}
}
macro_rules! ATA_SECTOR_COUNT {
($reg:expr) => (reg + 2);
}
fn select_drive(&mut self, drive: u8) {
unsafe {
self.drive_select.write(drive);
}
self.select_delay();
self.current_drive = drive;
}
macro_rules! ATA_ADDRESS1 {
($reg:expr) => (reg + 3);
}
fn is_atapi(&mut self) -> bool {
macro_rules! ATA_ADDRESS2 {
($reg:expr) => (reg + 4);
}
let mut sig: [u8; 4] = [0, 0, 0, 0];
unsafe {
sig[0] = self.sector_count.read();
sig[1] = self.address1.read();
sig[2] = self.address2.read();
sig[3] = self.address3.read();
}
macro_rules! ATA_ADDRESS3 {
($reg:expr) => (reg + 5);
}
ATAPI_SIG == sig
}
macro_rules! ATA_DRIVE_SELECT {
($reg:expr) => (reg + 6);
}
fn wait_busy(&mut self) {
let mut status = ATA_BSY;
while (status & ATA_BSY) != 0 {
unsafe {
status = self.status.read();
}
}
}
macro_rules! ATA_STATUS {
($reg:expr) => (reg + 7); // read
}
fn select_delay(&mut self) {
unsafe {
self.dcr.read();
self.dcr.read();
self.dcr.read();
self.dcr.read();
}
}
macro_rules! ATA_COMMAND {
($reg:expr) => (reg + 7); // write
}
macro_rules! ATA_DCR {
($reg:expr) => (reg + 0x206);
fn wait_packet_request(&mut self) {
let mut status = ATA_BSY;
while (status & ATA_BSY) != 0 && (status & ATA_DRQ) == 0 {
unsafe {
status = self.status.read();
}
}
}
}