diff --git a/src/drivers/atapi/mod.rs b/src/drivers/atapi/mod.rs index 17f6b91..efbc50d 100644 --- a/src/drivers/atapi/mod.rs +++ b/src/drivers/atapi/mod.rs @@ -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, + features: Port, // write + error: Port, // read + sector_count: Port, + address1: Port, + address2: Port, + address3: Port, + drive_select: Port, + command: Port, // write + status: Port, // read + dcr: Port, + + 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(); + } + } + } } \ No newline at end of file