add atapi helpers
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
		
							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();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user