mod.rs 2.82 KB
Newer Older
1 2 3 4
use io::Io;

use syscall::error::Result;

5 6
use self::dma::Dma;
use self::hba::{HbaMem, HbaCmdTable, HbaCmdHeader, HbaPort, HbaPortType};
7

8
pub mod dma;
9 10 11 12 13 14 15
pub mod fis;
pub mod hba;

pub struct Ahci;

impl Ahci {
    pub fn disks(base: usize, irq: u8) -> Vec<AhciDisk> {
Jeremy Soller's avatar
Jeremy Soller committed
16
        println!(" + AHCI on: {:X} IRQ: {}", base as usize, irq);
17 18 19 20 21

        let pi = unsafe { &mut *(base as *mut HbaMem) }.pi.read();
        let ret: Vec<AhciDisk> = (0..32)
              .filter(|&i| pi & 1 << i as i32 == 1 << i as i32)
              .filter_map(|i| {
22 23
                  let port = &mut unsafe { &mut *(base as *mut HbaMem) }.ports[i];
                  let port_type = port.probe();
24 25 26
                  println!("{}: {:?}", i, port_type);
                  match port_type {
                      HbaPortType::SATA => {
27 28 29 30 31 32
                          match AhciDisk::new(port) {
                              Ok(disk) => Some(disk),
                              Err(err) => {
                                  println!("{}: {}", i, err);
                                  None
                              }
33 34 35 36 37 38 39 40 41 42 43 44 45 46
                          }
                      }
                      _ => None,
                  }
              })
              .collect();

        ret
    }
}

pub struct AhciDisk {
    port: &'static mut HbaPort,
    size: u64,
47 48 49
    clb: Dma<[HbaCmdHeader; 32]>,
    ctbas: [Dma<HbaCmdTable>; 32],
    fb: Dma<[u8; 256]>
50 51 52
}

impl AhciDisk {
53 54 55 56 57 58 59 60 61 62 63 64 65
    fn new(port: &'static mut HbaPort) -> Result<Self> {
        let mut clb = Dma::zeroed()?;
        let mut ctbas = [
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
            Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?,
        ];
        let mut fb = Dma::zeroed()?;
66

67 68 69
        port.init(&mut clb, &mut ctbas, &mut fb);

        let size = unsafe { port.identify(&mut clb, &mut ctbas).unwrap_or(0) };
70

71 72 73 74 75 76 77
        Ok(AhciDisk {
            port: port,
            size: size,
            clb: clb,
            ctbas: ctbas,
            fb: fb
        })
78 79 80 81 82 83 84 85 86 87 88 89 90 91
    }

    fn size(&self) -> u64 {
        self.size
    }

    fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
        self.port.ata_dma(block, buffer.len() / 512, buffer.as_ptr() as usize, false)
    }

    fn write(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
        self.port.ata_dma(block, buffer.len() / 512, buffer.as_ptr() as usize, true)
    }
}