atapi 0.2.0

Low-level ATAPI driver in no_std environments.
Documentation

atapi 13.09.2026

atapi #![no_std] ATAPI driver, used to bare-metal and OS dev or other drivers. It providing comfortable API for work with this protocol

NOTE

you can send your offers, ideas, meaning, chatting with other devs and so on in our Discord server: https://discord.gg/cwXhbFXm

check "is_has_device" method. For better usage implement delay function with 1us timeout

example

Example of work ATAPI with this crate example/sectors.

fn read_pio_lba_28(&self, sectors: u8, lba: usize, mut buffer: *mut u16) -> Result<(), &'static str> {
    let count = if sectors == 0 { 256 } else { sectors as usize };

    for s in 0..count {
        let sector_lba = lba + s;

        self.set_flags(MasterOrSlave::Master, LBAOrCHS::LBA);
        self.wait_busy();
        self.set_dma_or_pio(DMAOrPIO::PIO);

        // set byte transfer limit in LBA mid and LBA high registers: 2048 bytes (0x0800)
        outb(self.io_registers.lba_mid_rw_w, 0x00);
        outb(self.io_registers.lba_high_rw_w, 0x08);

        self.prepare_scsi();
        if let Some(_) = self.wait_drq_and_busy(){
            return Err("timeout waiting for DRQ \\ \0");
        }

        // send 12-byte SCSI READ (12) packet (6 words to data port)
        let packet: [u8; 12] = [
            0xA8, // SCSI READ (12) opcode
            0x00, // flags
            ((sector_lba >> 24) & 0xFF) as u8,
            ((sector_lba >> 16) & 0xFF) as u8,
            ((sector_lba >> 8) & 0xFF) as u8,
            (sector_lba & 0xFF) as u8,
            0x00,
            0x00,
            0x00,
            1,    // 1 sector (2048 bytes)
            0x00, // reserved
            0x00, // control
        ];

        for chunk in 0..6 {
            let low = packet[chunk * 2] as u16;
            let high = (packet[chunk * 2 + 1] as u16) << 8;
            outw(self.io_registers.data_register_rw_w, low | high);
        }

        self.prepare_scsi();
        if let Some(_) = self.wait_drq_and_busy(){
            return Err("timeout waiting for DRQ \\ \0");
        }

        for _ in 0..(SECTOR_SIZE / 2) {
            unsafe {
                *buffer = inw(self.io_registers.data_register_rw_w);
                buffer = buffer.add(1);
            }
        }
    }
    Ok(())
}