atapi: Implement read support
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#![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>> {
|
||||
|
||||
+4
-2
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user