fn pio48_read_sectors(&self, lba: u64, buf: &mut [u8], sec_num: u64) -> Result<(), ATAError> {
        // now data is ready, we now read data from the data port
        // the remainder must be empty since we had checked the alignment before
        let sectors = slice_as_sectors(buf)
            .ok_or(ATAError::BufferNotAligned)?;

        if sec_num > sectors.len() as u64 {
            return Err(ATAError::BufferOverflow)
        }

        let drive = match self {
            ATADriver::PRIMARY => 0x40,
            ATADriver::SECONDARY => 0x50
        };

        
        // select drive
        outb(self.drive_reg(), drive);
        // set pio mode 
        outb(self.feature_reg(), ATAFeature::PIO as u8);

        // send parameters
        outb(self.sector_num_reg(), ((sec_num >> 8) & 0xff) as u8);
        outb(self.lba_lo_reg(), (lba >> 24 & 0xff) as u8);
        outb(self.lba_mid_reg(), (lba >> 32 & 0xff) as u8);
        outb(self.lba_hi_reg(), (lba >> 48 & 0xff) as u8);
        outb(self.sector_num_reg(), ((sec_num >> 0) & 0xff) as u8);
        outb(self.lba_lo_reg(), (lba >> 0 & 0xff) as u8);
        outb(self.lba_mid_reg(), (lba >> 8 & 0xff) as u8);
        outb(self.lba_hi_reg(), (lba >> 16 & 0xff) as u8);

        // send read sector command
        outb(self.command_reg(), ATACommand::ReadExt as u8);

        for sector in &mut sectors[..sec_num as usize] {
            // delay 400ns to wait ATA controller to set status registers
            self.ata_delay_400ns();

            let mut status = inb(self.status_reg());
            // spin wait until the BUSY flag is unset
            while status & ATAStatus::BSY as u8 != 0 {
                spin_loop();
                status = inb(self.status_reg());
            }
        
            // make a error checking
            if status & (ATAStatus::DF as u8 | ATAStatus::ERR as u8) != 0 {
                return Err(ATAError::DiskError(inb(self.error_reg())))
            }
            self.pio_read_port(self.data_reg(), sector);
        }
        
        Ok(())
    }
/// read sectors in PIO mode, this has huge performance issue. So it should only be used
/// in bootloader for loading kernel into memory.
read sectors in PIO mode, this has huge performance issue. So it should only be used
in bootloader for loading kernel into memory.
read sectors in PIO mode this has huge performance issue . So it should only be used in bootloader for loading kernel into memory .
fn pio48_read_sectors(&self, lba: u64, buf: &mut [u8], sec_num: u64) -> Result<(), ATAError> {
        // now data is ready, we now read data from the data port
        // the remainder must be empty since we had checked the alignment before
        let sectors = slice_as_sectors(buf)
            .ok_or(ATAError::BufferNotAligned)?;
        if sec_num > sectors.len() as u64 {
            return Err(ATAError::BufferOverflow)
        }
        let drive = match self {
            ATADriver::PRIMARY => 0x40,
            ATADriver::SECONDARY => 0x50
        };
        // select drive
        outb(self.drive_reg(), drive);
        // set pio mode 
        outb(self.feature_reg(), ATAFeature::PIO as u8);
        // send parameters
        outb(self.sector_num_reg(), ((sec_num >> 8) & 0xff) as u8);
        outb(self.lba_lo_reg(), (lba >> 24 & 0xff) as u8);
        outb(self.lba_mid_reg(), (lba >> 32 & 0xff) as u8);
        outb(self.lba_hi_reg(), (lba >> 48 & 0xff) as u8);
        outb(self.sector_num_reg(), ((sec_num >> 0) & 0xff) as u8);
        outb(self.lba_lo_reg(), (lba >> 0 & 0xff) as u8);
        outb(self.lba_mid_reg(), (lba >> 8 & 0xff) as u8);
        outb(self.lba_hi_reg(), (lba >> 16 & 0xff) as u8);
        // send read sector command
        outb(self.command_reg(), ATACommand::ReadExt as u8);
        for sector in &mut sectors[..sec_num as usize] {
            // delay 400ns to wait ATA controller to set status registers
            self.ata_delay_400ns();
            let mut status = inb(self.status_reg());
            // spin wait until the BUSY flag is unset
            while status & ATAStatus::BSY as u8 != 0 {
                spin_loop();
                status = inb(self.status_reg());
            }
            // make a error checking
            if status & (ATAStatus::DF as u8 | ATAStatus::ERR as u8) != 0 {
                return Err(ATAError::DiskError(inb(self.error_reg())))
            }
            self.pio_read_port(self.data_reg(), sector);
        }
        Ok(())
    }
fn pio48_read_sectors ( & self , lba : u64 , buf : & mut [ u8 ] , sec_num : u64 ) -> Result < ( ) , ATAError > { // now data is ready, we now read data from the data port // the remainder must be empty since we had checked the alignment before let sectors = slice_as_sectors ( buf ) . ok_or ( ATAError :: BufferNotAligned ) ? ; if sec_num > sectors . len ( ) as u64 { return Err ( ATAError :: BufferOverflow ) } let drive = match self { ATADriver :: PRIMARY => 0x40 , ATADriver :: SECONDARY => 0x50 } ; // select drive outb ( self . drive_reg ( ) , drive ) ; // set pio mode  outb ( self . feature_reg ( ) , ATAFeature :: PIO as u8 ) ; // send parameters outb ( self . sector_num_reg ( ) , ( ( sec_num >> 8 ) & 0xff ) as u8 ) ; outb ( self . lba_lo_reg ( ) , ( lba >> 24 & 0xff ) as u8 ) ; outb ( self . lba_mid_reg ( ) , ( lba >> 32 & 0xff ) as u8 ) ; outb ( self . lba_hi_reg ( ) , ( lba >> 48 & 0xff ) as u8 ) ; outb ( self . sector_num_reg ( ) , ( ( sec_num >> 0 ) & 0xff ) as u8 ) ; outb ( self . lba_lo_reg ( ) , ( lba >> 0 & 0xff ) as u8 ) ; outb ( self . lba_mid_reg ( ) , ( lba >> 8 & 0xff ) as u8 ) ; outb ( self . lba_hi_reg ( ) , ( lba >> 16 & 0xff ) as u8 ) ; // send read sector command outb ( self . command_reg ( ) , ATACommand :: ReadExt as u8 ) ; for sector in & mut sectors [ .. sec_num as usize ] { // delay 400ns to wait ATA controller to set status registers self . ata_delay_400ns ( ) ; let mut status = inb ( self . status_reg ( ) ) ; // spin wait until the BUSY flag is unset while status & ATAStatus :: BSY as u8 != 0 { spin_loop ( ) ; status = inb ( self . status_reg ( ) ) ; } // make a error checking if status & ( ATAStatus :: DF as u8 | ATAStatus :: ERR as u8 ) != 0 { return Err ( ATAError :: DiskError ( inb ( self . error_reg ( ) ) ) ) } self . pio_read_port ( self . data_reg ( ) , sector ) ; } Ok ( ( ) ) }
read sectors in PIO mode, this has huge performance issue.
read sectors in PIO mode this has huge performance issue .
&self
lba
u64
buf
&mut [u8]
sec_num
u64