atapi: Implement read support

parent 78ab3862
......@@ -62,18 +62,14 @@ impl Disk for DiskATA {
let mut sector: usize = 0;
while sectors - sector >= 255 {
if let Err(err) = self.port.ata_dma(block + sector as u64, 255, false, &mut self.clb, &mut self.ctbas, &mut self.buf) {
return Err(err);
}
self.port.ata_dma(block + sector as u64, 255, false, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().offset(sector as isize * 512), 255 * 512); }
sector += 255;
}
if sector < sectors {
if let Err(err) = self.port.ata_dma(block + sector as u64, sectors - sector, false, &mut self.clb, &mut self.ctbas, &mut self.buf) {
return Err(err);
}
self.port.ata_dma(block + sector as u64, sectors - sector, false, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().offset(sector as isize * 512), (sectors - sector) * 512); }
......@@ -108,4 +104,8 @@ impl Disk for DiskATA {
Ok(sector * 512)
}
fn block_length(&mut self) -> Result<u32> {
Ok(512)
}
}
#![allow(dead_code)]
use std::ptr;
use byteorder::{ByteOrder, BigEndian};
use syscall::io::Dma;
......@@ -9,6 +11,7 @@ use super::hba::{HbaPort, HbaCmdTable, HbaCmdHeader};
use super::Disk;
const SCSI_READ_CAPACITY: u8 = 0x25;
const SCSI_READ10: u8 = 0x28;
pub struct DiskATAPI {
id: usize,
......@@ -17,6 +20,8 @@ pub struct DiskATAPI {
clb: Dma<[HbaCmdHeader; 32]>,
ctbas: [Dma<HbaCmdTable>; 32],
_fb: Dma<[u8; 256]>,
// Just using the same buffer size as DiskATA
// Although the sector size is different (and varies)
buf: Dma<[u8; 256 * 512]>
}
......@@ -77,12 +82,48 @@ impl Disk for DiskATAPI {
}
}
fn read(&mut self, _block: u64, _buffer: &mut [u8]) -> Result<usize> {
Err(Error::new(ENOSYS))
fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
// TODO: Handle audio CDs, which use special READ CD command
let blk_len = self.block_length()?;
let sectors = buffer.len() as u32 / blk_len;
fn read10_cmd(block: u32, count: u16) -> [u8; 16] {
let mut cmd = [0; 16];
cmd[0] = SCSI_READ10;
BigEndian::write_u32(&mut cmd[2..6], block as u32);
BigEndian::write_u16(&mut cmd[7..9], count as u16);
cmd
}
let mut sector = 0;
let buf_len = (256 * 512) / blk_len;
let buf_size = buf_len * blk_len;
while sectors - sector >= buf_len {
let cmd = read10_cmd(block as u32 + sector, buf_len as u16);
self.port.packet(&cmd, buf_size, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().offset(sector as isize * blk_len as isize), buf_size as usize); }
sector += blk_len;
}
if sector < sectors {
let cmd = read10_cmd(block as u32 + sector, (sectors - sector) as u16);
self.port.packet(&cmd, buf_size, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().offset(sector as isize * blk_len as isize), ((sectors - sector) * blk_len) as usize); }
sector += sectors - sector;
}
Ok((sector * blk_len) as usize)
}
fn write(&mut self, _block: u64, _buffer: &[u8]) -> Result<usize> {
Err(Error::new(ENOSYS)) // TODO: Implement writting
}
fn block_length(&mut self) -> Result<u32> {
Ok(self.read_capacity()?.1)
}
}
......@@ -15,6 +15,7 @@ pub trait Disk {
fn size(&mut self) -> u64;
fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize>;
fn write(&mut self, block: u64, buffer: &[u8]) -> Result<usize>;
fn block_length(&mut self) -> Result<u32>;
}
pub fn disks(base: usize, name: &str) -> Vec<Box<Disk>> {
......
......@@ -150,7 +150,8 @@ impl Scheme for DiskScheme {
},
Handle::Disk(ref mut handle, ref mut size, _) => {
let mut disk = handle.lock();
let count = disk.read((*size as u64)/512, buf)?;
let blk_len = disk.block_length()?;
let count = disk.read((*size as u64)/(blk_len as u64), buf)?;
*size += count;
Ok(count)
}
......@@ -165,7 +166,8 @@ impl Scheme for DiskScheme {
},
Handle::Disk(ref mut handle, ref mut size, _) => {
let mut disk = handle.lock();
let count = disk.write((*size as u64)/512, buf)?;
let blk_len = disk.block_length()?;
let count = disk.write((*size as u64)/(blk_len as u64), buf)?;
*size += count;
Ok(count)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment