use Direction;
#[cfg(not(target_os = "linux"))]
use Device;
use ata::{ATADevice, RegistersRead, RegistersWrite, Command, SMARTFeature};
use scsi::{self, SCSIDevice};
use ata::data::{id, health, attr};
use drivedb;
use std::io;
quick_error! {
#[derive(Debug)]
pub enum Error {
IO(err: io::Error) {
from()
display("IO error: {}", err)
description(err.description())
cause(err)
}
SCSI(err: scsi::ATAError) {
from()
display("{}", err)
}
}
}
pub trait Misc {
fn ata_do(&self, dir: Direction, regs: &RegistersWrite) -> Result<(RegistersRead, Vec<u8>), Error>;
fn get_device_id(&self) -> Result<id::Id, Error> {
info!("reading device identification packet");
let (_, data) = self.ata_do(Direction::From, &RegistersWrite {
command: Command::Identify as u8,
sector: 1,
features: 0,
sector_count: 1,
cyl_high: 0,
cyl_low: 0,
device: 0,
})?;
Ok(id::parse_id(&data))
}
fn get_smart_health(&self) -> Result<Option<bool>, Error> {
info!("reading SMART status");
let (regs, _) = self.ata_do(Direction::None, &RegistersWrite {
command: Command::SMART as u8,
features: SMARTFeature::ReturnStatus as u8,
sector_count: 0,
sector: 0,
cyl_low: 0x4f,
cyl_high: 0xc2,
device: 0,
})?;
Ok(health::parse_smart_status(®s))
}
fn get_smart_attributes(&self, meta: &Option<drivedb::DriveMeta>) -> Result<Vec<attr::SmartAttribute>, Error> {
info!("reading SMART attributes and thresholds");
let (_, data) = self.ata_do(Direction::From, &RegistersWrite {
command: Command::SMART as u8,
sector: 0,
features: SMARTFeature::ReadValues as u8,
sector_count: 1,
cyl_low: 0x4f,
cyl_high: 0xc2,
device: 0,
})?;
let (_, thresh) = self.ata_do(Direction::From, &RegistersWrite {
command: Command::SMART as u8,
sector: 0,
features: SMARTFeature::ReadThresholds as u8,
sector_count: 1,
cyl_low: 0x4f,
cyl_high: 0xc2,
device: 0,
})?;
Ok(attr::parse_smart_values(&data, &thresh, &meta))
}
}
#[cfg(not(target_os = "linux"))]
impl Misc for ATADevice<Device> {
fn ata_do(&self, dir: Direction, regs: &RegistersWrite) -> Result<(RegistersRead, Vec<u8>), Error> {
Ok(Self::ata_do(self, dir, regs)?)
}
}
impl Misc for ATADevice<SCSIDevice> {
fn ata_do(&self, dir: Direction, regs: &RegistersWrite) -> Result<(RegistersRead, Vec<u8>), Error> {
Ok(Self::ata_do(self, dir, regs)?)
}
}