Wholesale cargo fmt to get CI back to green

This commit is contained in:
Andrey Turkin
2024-10-17 20:07:05 +03:00
parent 17b2f5eab1
commit 09b5033fbd
67 changed files with 4804 additions and 3613 deletions
+24 -16
View File
@@ -26,7 +26,6 @@ pub struct DmarStruct {
pub host_addr_width: u8,
pub flags: u8,
pub _rsvd: [u8; 10],
// This header is followed by N remapping structures.
}
unsafe impl plain::Plain for DmarStruct {}
@@ -84,16 +83,23 @@ impl Dmar {
log::debug!("GCMD: {:X}", drhd.gl_cmd.read());
log::debug!("GSTS: {:X}", drhd.gl_sts.read());
log::debug!("RT: {:X}", drhd.root_table.read());
},
_ => ()
}
_ => (),
}
}
}
fn new(sdt: Sdt) -> Option<Dmar> {
assert_eq!(sdt.signature, *b"DMAR", "signature already checked against `DMAR`");
assert_eq!(
sdt.signature, *b"DMAR",
"signature already checked against `DMAR`"
);
if sdt.length() < mem::size_of::<DmarStruct>() {
log::error!("The DMAR table was too small ({} B < {} B).", sdt.length(), mem::size_of::<Dmar>());
log::error!(
"The DMAR table was too small ({} B < {} B).",
sdt.length(),
mem::size_of::<Dmar>()
);
return None;
}
// No need to check alignment for #[repr(packed)] structs.
@@ -102,7 +108,9 @@ impl Dmar {
}
pub fn iter(&self) -> DmarIter<'_> {
DmarIter(DmarRawIter { bytes: self.remmapping_structs_area() })
DmarIter(DmarRawIter {
bytes: self.remmapping_structs_area(),
})
}
}
@@ -128,7 +136,6 @@ pub struct DeviceScopeHeader {
pub _rsvd: u16,
pub enumeration_id: u8,
pub start_bus_num: u8,
// The variable-sized path comes after.
}
unsafe impl plain::Plain for DeviceScopeHeader {}
@@ -196,8 +203,7 @@ impl DmarDrhd {
pub fn map(&self) -> DrhdPage {
let base = usize::try_from(self.base).expect("expected u64 to fit within usize");
DrhdPage::map(base)
.expect("failed to map DRHD registers")
DrhdPage::map(base).expect("failed to map DRHD registers")
}
}
impl Deref for DmarDrhd {
@@ -227,7 +233,6 @@ pub struct DmarRmrrHeader {
pub segment: u16,
pub base: u64,
pub limit: u64,
// The device scopes come after.
}
unsafe impl plain::Plain for DmarRmrrHeader {}
@@ -269,7 +274,6 @@ pub struct DmarAtsrHeader {
flags: u8,
_rsv: u8,
segment: u16,
// The device scopes come after.
}
unsafe impl plain::Plain for DmarAtsrHeader {}
@@ -334,7 +338,6 @@ pub struct DmarAnddHeader {
pub _rsv: [u8; 3],
pub acpi_dev: u8,
// The device scopes come after.
}
unsafe impl plain::Plain for DmarAnddHeader {}
@@ -377,7 +380,6 @@ pub struct DmarSatcHeader {
pub flags: u8,
pub _rsvd: u8,
pub seg_num: u16,
// The device scopes come after.
}
unsafe impl plain::Plain for DmarSatcHeader {}
@@ -467,8 +469,10 @@ impl<'sdt> Iterator for DmarRawIter<'sdt> {
};
let remainder = &self.bytes[4..];
let type_bytes = <[u8; 2]>::try_from(type_bytes).expect("expected a 2-byte slice to be convertible to [u8; 2]");
let len_bytes = <[u8; 2]>::try_from(type_bytes).expect("expected a 2-byte slice to be convertible to [u8; 2]");
let type_bytes = <[u8; 2]>::try_from(type_bytes)
.expect("expected a 2-byte slice to be convertible to [u8; 2]");
let len_bytes = <[u8; 2]>::try_from(type_bytes)
.expect("expected a 2-byte slice to be convertible to [u8; 2]");
let ty = u16::from_ne_bytes(type_bytes);
let len = u16::from_ne_bytes(len_bytes);
@@ -500,7 +504,11 @@ impl Iterator for DmarIter<'_> {
let entry_type = match EntryType::from_u16(raw_type) {
Some(ty) => ty,
None => {
log::warn!("Encountered invalid entry type {} (length {})", raw_type, raw.len());
log::warn!(
"Encountered invalid entry type {} (length {})",
raw_type,
raw.len()
);
return Some(DmarEntry::Unknown(raw_type));
}
};
+8 -3
View File
@@ -1,10 +1,10 @@
use common::io::{Io, Pio};
use num_traits::PrimInt;
use rustc_hash::FxHashMap;
use std::fmt::LowerHex;
use std::mem::size_of;
use std::sync::{Arc, Mutex};
use syscall::PAGE_SIZE;
use common::io::{Io, Pio};
const PAGE_MASK: usize = !(PAGE_SIZE - 1);
const OFFSET_MASK: usize = PAGE_SIZE - 1;
@@ -17,8 +17,13 @@ struct MappedPage {
impl MappedPage {
fn new(phys_page: usize) -> std::io::Result<Self> {
let virt_page = unsafe {
common::physmap(phys_page, PAGE_SIZE, common::Prot::RO, common::MemoryType::default())
.map_err(|error| std::io::Error::from_raw_os_error(error.errno()))?
common::physmap(
phys_page,
PAGE_SIZE,
common::Prot::RO,
common::MemoryType::default(),
)
.map_err(|error| std::io::Error::from_raw_os_error(error.errno()))?
} as usize;
Ok(Self {
phys_page,
+231 -204
View File
@@ -1,276 +1,300 @@
#![allow(dead_code)]
use std::mem;
use std::collections::BTreeMap;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering};
use syscall::error::{Error, EACCES, EBADF, Result, EINVAL, ENOENT};
use common::io::Pio;
use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, ENOENT};
use syscall::scheme::SchemeBlockMut;
use common::{dma::Dma, io::{Io, Mmio}};
use common::{
dma::Dma,
io::{Io, Mmio},
};
use spin::Mutex;
const NUM_SUB_BUFFS: usize = 32;
const SUB_BUFF_SIZE: usize = 2048;
enum Handle {
Todo,
Todo,
}
#[allow(dead_code)]
struct MixerRegs {
/* 0x00 */ reset: Pio<u16>,
/* 0x02 */ master_volume: Pio<u16>,
/* 0x04 */ aux_out_volume: Pio<u16>,
/* 0x06 */ mono_volume: Pio<u16>,
/* 0x08 */ master_tone: Pio<u16>,
/* 0x0A */ pc_beep_volume: Pio<u16>,
/* 0x0C */ phone_volume: Pio<u16>,
/* 0x0E */ mic_volume: Pio<u16>,
/* 0x10 */ line_in_volume: Pio<u16>,
/* 0x12 */ cd_volume: Pio<u16>,
/* 0x14 */ video_volume: Pio<u16>,
/* 0x16 */ aux_in_volume: Pio<u16>,
/* 0x18 */ pcm_out_volume: Pio<u16>,
/* 0x1A */ record_select: Pio<u16>,
/* 0x1C */ record_gain: Pio<u16>,
/* 0x1E */ record_gain_mic: Pio<u16>,
/* 0x20 */ general_purpose: Pio<u16>,
/* 0x22 */ control_3d: Pio<u16>,
/* 0x24 */ audio_int_paging: Pio<u16>,
/* 0x26 */ powerdown: Pio<u16>,
/* 0x28 */ extended_id: Pio<u16>,
/* 0x2A */ extended_ctrl: Pio<u16>,
/* 0x2C */ vra_pcm_front: Pio<u16>,
/* 0x00 */ reset: Pio<u16>,
/* 0x02 */ master_volume: Pio<u16>,
/* 0x04 */ aux_out_volume: Pio<u16>,
/* 0x06 */ mono_volume: Pio<u16>,
/* 0x08 */ master_tone: Pio<u16>,
/* 0x0A */ pc_beep_volume: Pio<u16>,
/* 0x0C */ phone_volume: Pio<u16>,
/* 0x0E */ mic_volume: Pio<u16>,
/* 0x10 */ line_in_volume: Pio<u16>,
/* 0x12 */ cd_volume: Pio<u16>,
/* 0x14 */ video_volume: Pio<u16>,
/* 0x16 */ aux_in_volume: Pio<u16>,
/* 0x18 */ pcm_out_volume: Pio<u16>,
/* 0x1A */ record_select: Pio<u16>,
/* 0x1C */ record_gain: Pio<u16>,
/* 0x1E */ record_gain_mic: Pio<u16>,
/* 0x20 */ general_purpose: Pio<u16>,
/* 0x22 */ control_3d: Pio<u16>,
/* 0x24 */ audio_int_paging: Pio<u16>,
/* 0x26 */ powerdown: Pio<u16>,
/* 0x28 */ extended_id: Pio<u16>,
/* 0x2A */ extended_ctrl: Pio<u16>,
/* 0x2C */ vra_pcm_front: Pio<u16>,
}
impl MixerRegs {
fn new(bar0: u16) -> Self {
Self {
reset: Pio::new(bar0 + 0x00),
master_volume: Pio::new(bar0 + 0x02),
aux_out_volume: Pio::new(bar0 + 0x04),
mono_volume: Pio::new(bar0 + 0x06),
master_tone: Pio::new(bar0 + 0x08),
pc_beep_volume: Pio::new(bar0 + 0x0A),
phone_volume: Pio::new(bar0 + 0x0C),
mic_volume: Pio::new(bar0 + 0x0E),
line_in_volume: Pio::new(bar0 + 0x10),
cd_volume: Pio::new(bar0 + 0x12),
video_volume: Pio::new(bar0 + 0x14),
aux_in_volume: Pio::new(bar0 + 0x16),
pcm_out_volume: Pio::new(bar0 + 0x18),
record_select: Pio::new(bar0 + 0x1A),
record_gain: Pio::new(bar0 + 0x1C),
record_gain_mic: Pio::new(bar0 + 0x1E),
general_purpose: Pio::new(bar0 + 0x20),
control_3d: Pio::new(bar0 + 0x22),
audio_int_paging: Pio::new(bar0 + 0x24),
powerdown: Pio::new(bar0 + 0x26),
extended_id: Pio::new(bar0 + 0x28),
extended_ctrl: Pio::new(bar0 + 0x2A),
vra_pcm_front: Pio::new(bar0 + 0x2C),
}
}
fn new(bar0: u16) -> Self {
Self {
reset: Pio::new(bar0 + 0x00),
master_volume: Pio::new(bar0 + 0x02),
aux_out_volume: Pio::new(bar0 + 0x04),
mono_volume: Pio::new(bar0 + 0x06),
master_tone: Pio::new(bar0 + 0x08),
pc_beep_volume: Pio::new(bar0 + 0x0A),
phone_volume: Pio::new(bar0 + 0x0C),
mic_volume: Pio::new(bar0 + 0x0E),
line_in_volume: Pio::new(bar0 + 0x10),
cd_volume: Pio::new(bar0 + 0x12),
video_volume: Pio::new(bar0 + 0x14),
aux_in_volume: Pio::new(bar0 + 0x16),
pcm_out_volume: Pio::new(bar0 + 0x18),
record_select: Pio::new(bar0 + 0x1A),
record_gain: Pio::new(bar0 + 0x1C),
record_gain_mic: Pio::new(bar0 + 0x1E),
general_purpose: Pio::new(bar0 + 0x20),
control_3d: Pio::new(bar0 + 0x22),
audio_int_paging: Pio::new(bar0 + 0x24),
powerdown: Pio::new(bar0 + 0x26),
extended_id: Pio::new(bar0 + 0x28),
extended_ctrl: Pio::new(bar0 + 0x2A),
vra_pcm_front: Pio::new(bar0 + 0x2C),
}
}
}
#[allow(dead_code)]
struct BusBoxRegs {
/// Buffer descriptor list base address
/* 0x00 */ bdbar: Pio<u32>,
/// Current index value
/* 0x04 */ civ: Pio<u8>,
/// Last valid index
/* 0x05 */ lvi: Pio<u8>,
/// Status
/* 0x06 */ sr: Pio<u16>,
/// Position in current buffer
/* 0x08 */ picb: Pio<u16>,
/// Prefetched index value
/* 0x0A */ piv: Pio<u8>,
/// Control
/* 0x0B */ cr: Pio<u8>,
/// Buffer descriptor list base address
/* 0x00 */
bdbar: Pio<u32>,
/// Current index value
/* 0x04 */
civ: Pio<u8>,
/// Last valid index
/* 0x05 */
lvi: Pio<u8>,
/// Status
/* 0x06 */
sr: Pio<u16>,
/// Position in current buffer
/* 0x08 */
picb: Pio<u16>,
/// Prefetched index value
/* 0x0A */
piv: Pio<u8>,
/// Control
/* 0x0B */
cr: Pio<u8>,
}
impl BusBoxRegs {
fn new(base: u16) -> Self {
Self {
bdbar: Pio::new(base + 0x00),
civ: Pio::new(base + 0x04),
lvi: Pio::new(base + 0x05),
sr: Pio::new(base + 0x06),
picb: Pio::new(base + 0x08),
piv: Pio::new(base + 0x0A),
cr: Pio::new(base + 0x0B),
}
}
fn new(base: u16) -> Self {
Self {
bdbar: Pio::new(base + 0x00),
civ: Pio::new(base + 0x04),
lvi: Pio::new(base + 0x05),
sr: Pio::new(base + 0x06),
picb: Pio::new(base + 0x08),
piv: Pio::new(base + 0x0A),
cr: Pio::new(base + 0x0B),
}
}
}
#[allow(dead_code)]
struct BusRegs {
/// PCM in register box
/* 0x00 */ pi: BusBoxRegs,
/// PCM out register box
/* 0x10 */ po: BusBoxRegs,
/// Microphone register box
/* 0x20 */ mc: BusBoxRegs,
/// PCM in register box
/* 0x00 */
pi: BusBoxRegs,
/// PCM out register box
/* 0x10 */
po: BusBoxRegs,
/// Microphone register box
/* 0x20 */
mc: BusBoxRegs,
}
impl BusRegs {
fn new(bar1: u16) -> Self {
Self {
pi: BusBoxRegs::new(bar1 + 0x00),
po: BusBoxRegs::new(bar1 + 0x10),
mc: BusBoxRegs::new(bar1 + 0x20),
}
}
fn new(bar1: u16) -> Self {
Self {
pi: BusBoxRegs::new(bar1 + 0x00),
po: BusBoxRegs::new(bar1 + 0x10),
mc: BusBoxRegs::new(bar1 + 0x20),
}
}
}
#[repr(packed)]
pub struct BufferDescriptor {
/* 0x00 */ addr: Mmio<u32>,
/* 0x04 */ samples: Mmio<u16>,
/* 0x06 */ flags: Mmio<u16>,
/* 0x00 */ addr: Mmio<u32>,
/* 0x04 */ samples: Mmio<u16>,
/* 0x06 */ flags: Mmio<u16>,
}
pub struct Ac97 {
mixer: MixerRegs,
bus: BusRegs,
bdl: Dma<[BufferDescriptor; NUM_SUB_BUFFS]>,
mixer: MixerRegs,
bus: BusRegs,
bdl: Dma<[BufferDescriptor; NUM_SUB_BUFFS]>,
buf: Dma<[u8; NUM_SUB_BUFFS * SUB_BUFF_SIZE]>,
handles: Mutex<BTreeMap<usize, Handle>>,
next_id: AtomicUsize,
handles: Mutex<BTreeMap<usize, Handle>>,
next_id: AtomicUsize,
}
impl Ac97 {
pub unsafe fn new(bar0: u16, bar1: u16) -> Result<Self> {
let mut module = Ac97 {
mixer: MixerRegs::new(bar0),
bus: BusRegs::new(bar1),
pub unsafe fn new(bar0: u16, bar1: u16) -> Result<Self> {
let mut module = Ac97 {
mixer: MixerRegs::new(bar0),
bus: BusRegs::new(bar1),
bdl: Dma::zeroed(
//TODO: PhysBox::new_in_32bit_space(bdl_size)?
)?.assume_init(),
)?
.assume_init(),
buf: Dma::zeroed(
//TODO: PhysBox::new_in_32bit_space(buf_size)?
)?.assume_init(),
handles: Mutex::new(BTreeMap::new()),
next_id: AtomicUsize::new(0),
};
)?
.assume_init(),
handles: Mutex::new(BTreeMap::new()),
next_id: AtomicUsize::new(0),
};
module.init()?;
module.init()?;
Ok(module)
}
Ok(module)
}
fn init(&mut self) -> Result<()> {
//TODO: support other sample rates, or just the default of 48000 Hz
{
// Check if VRA is supported
if ! self.mixer.extended_id.readf(1 << 0) {
println!("ac97d: VRA not supported and is currently required");
return Err(Error::new(ENOENT));
}
fn init(&mut self) -> Result<()> {
//TODO: support other sample rates, or just the default of 48000 Hz
{
// Check if VRA is supported
if !self.mixer.extended_id.readf(1 << 0) {
println!("ac97d: VRA not supported and is currently required");
return Err(Error::new(ENOENT));
}
// Enable VRA
self.mixer.extended_ctrl.writef(1 << 0, true);
// Enable VRA
self.mixer.extended_ctrl.writef(1 << 0, true);
// Attempt to set sample rate for PCM front to 44100 Hz
let desired_sample_rate = 44100;
self.mixer.vra_pcm_front.write(desired_sample_rate);
// Attempt to set sample rate for PCM front to 44100 Hz
let desired_sample_rate = 44100;
self.mixer.vra_pcm_front.write(desired_sample_rate);
// Read back real sample rate
let real_sample_rate = self.mixer.vra_pcm_front.read();
println!("ac97d: set sample rate to {}", real_sample_rate);
// Read back real sample rate
let real_sample_rate = self.mixer.vra_pcm_front.read();
println!("ac97d: set sample rate to {}", real_sample_rate);
// Error if we cannot set the sample rate as desired
if real_sample_rate != desired_sample_rate {
println!("ac97d: sample rate is {} but only {} is supported", real_sample_rate, desired_sample_rate);
return Err(Error::new(ENOENT));
}
}
// Error if we cannot set the sample rate as desired
if real_sample_rate != desired_sample_rate {
println!(
"ac97d: sample rate is {} but only {} is supported",
real_sample_rate, desired_sample_rate
);
return Err(Error::new(ENOENT));
}
}
// Ensure PCM out is stopped
self.bus.po.cr.writef(1, false);
// Ensure PCM out is stopped
self.bus.po.cr.writef(1, false);
// Reset PCM out
self.bus.po.cr.writef(1 << 1, true);
while self.bus.po.cr.readf(1 << 1) {
// Spinning on resetting PCM out
//TODO: relax
}
// Reset PCM out
self.bus.po.cr.writef(1 << 1, true);
while self.bus.po.cr.readf(1 << 1) {
// Spinning on resetting PCM out
//TODO: relax
}
// Initialize BDL for PCM out
for i in 0..NUM_SUB_BUFFS {
self.bdl[i].addr.write((self.buf.physical() + i * SUB_BUFF_SIZE) as u32);
self.bdl[i].samples.write((SUB_BUFF_SIZE / 2 /* Each sample is i16 or 2 bytes */) as u16);
self.bdl[i].flags.write(1 << 15 /* Interrupt on completion */);
}
self.bus.po.bdbar.write(self.bdl.physical() as u32);
// Initialize BDL for PCM out
for i in 0..NUM_SUB_BUFFS {
self.bdl[i]
.addr
.write((self.buf.physical() + i * SUB_BUFF_SIZE) as u32);
self.bdl[i]
.samples
.write((SUB_BUFF_SIZE / 2/* Each sample is i16 or 2 bytes */) as u16);
self.bdl[i]
.flags
.write(1 << 15 /* Interrupt on completion */);
}
self.bus.po.bdbar.write(self.bdl.physical() as u32);
// Enable interrupt on completion
self.bus.po.cr.writef(1 << 4, true);
// Enable interrupt on completion
self.bus.po.cr.writef(1 << 4, true);
// Start bus master
self.bus.po.cr.writef(1 << 0, true);
// Start bus master
self.bus.po.cr.writef(1 << 0, true);
// Set master volume to 0 db (loudest output, DANGER!)
self.mixer.master_volume.write(0);
// Set master volume to 0 db (loudest output, DANGER!)
self.mixer.master_volume.write(0);
// Set PCM output volume to 0 db (medium)
self.mixer.pcm_out_volume.write(0x808);
// Set PCM output volume to 0 db (medium)
self.mixer.pcm_out_volume.write(0x808);
Ok(())
}
Ok(())
}
pub fn irq(&mut self) -> bool {
let ints = self.bus.po.sr.read() & 0b11100;
if ints != 0 {
self.bus.po.sr.write(ints);
true
} else {
false
}
}
pub fn irq(&mut self) -> bool {
let ints = self.bus.po.sr.read() & 0b11100;
if ints != 0 {
self.bus.po.sr.write(ints);
true
} else {
false
}
}
}
impl SchemeBlockMut for Ac97 {
fn open(&mut self, _path: &str, _flags: usize, uid: u32, _gid: u32) -> Result<Option<usize>> {
if uid == 0 {
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.handles.lock().insert(id, Handle::Todo);
Ok(Some(id))
} else {
Err(Error::new(EACCES))
}
}
fn open(&mut self, _path: &str, _flags: usize, uid: u32, _gid: u32) -> Result<Option<usize>> {
if uid == 0 {
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.handles.lock().insert(id, Handle::Todo);
Ok(Some(id))
} else {
Err(Error::new(EACCES))
}
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
{
let mut handles = self.handles.lock();
let _handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
{
let mut handles = self.handles.lock();
let _handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
}
if buf.len() != SUB_BUFF_SIZE {
return Err(Error::new(EINVAL));
}
if buf.len() != SUB_BUFF_SIZE {
return Err(Error::new(EINVAL));
}
let civ = self.bus.po.civ.read() as usize;
let mut lvi = self.bus.po.lvi.read() as usize;
if lvi == (civ + 3) % NUM_SUB_BUFFS {
// Block if we already are 3 buffers ahead
Ok(None)
} else {
// Fill next buffer
lvi = (lvi + 1) % NUM_SUB_BUFFS;
for i in 0..SUB_BUFF_SIZE {
self.buf[lvi * SUB_BUFF_SIZE + i] = buf[i];
}
self.bus.po.lvi.write(lvi as u8);
let civ = self.bus.po.civ.read() as usize;
let mut lvi = self.bus.po.lvi.read() as usize;
if lvi == (civ + 3) % NUM_SUB_BUFFS {
// Block if we already are 3 buffers ahead
Ok(None)
} else {
// Fill next buffer
lvi = (lvi + 1) % NUM_SUB_BUFFS;
for i in 0..SUB_BUFF_SIZE {
self.buf[lvi * SUB_BUFF_SIZE + i] = buf[i];
}
self.bus.po.lvi.write(lvi as u8);
Ok(Some(SUB_BUFF_SIZE))
}
}
Ok(Some(SUB_BUFF_SIZE))
}
}
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
let mut handles = self.handles.lock();
@@ -285,8 +309,11 @@ impl SchemeBlockMut for Ac97 {
Ok(Some(i))
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
let mut handles = self.handles.lock();
handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(Some(0)))
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
let mut handles = self.handles.lock();
handles
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(Some(0)))
}
}
+52 -27
View File
@@ -1,14 +1,14 @@
//#![deny(warnings)]
extern crate bitflags;
extern crate event;
extern crate spin;
extern crate syscall;
extern crate event;
use std::fs::File;
use std::io::{ErrorKind, Read, Write, Result};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::cell::RefCell;
use std::fs::File;
use std::io::{ErrorKind, Read, Result, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::Arc;
use std::usize;
@@ -30,7 +30,10 @@ fn main() {
let bar0 = pci_config.func.bars[0].expect_port();
let bar1 = pci_config.func.bars[1].expect_port();
let irq = pci_config.func.legacy_interrupt_line.expect("ac97d: no legacy interrupts supported");
let irq = pci_config
.func
.legacy_interrupt_line
.expect("ac97d: no legacy interrupts supported");
println!(" + ac97 {}", pci_config.func.display());
@@ -44,12 +47,19 @@ fn main() {
log::LevelFilter::Info,
);
common::acquire_port_io_rights().expect("ac97d: failed to set I/O privilege level to Ring 3");
common::acquire_port_io_rights()
.expect("ac97d: failed to set I/O privilege level to Ring 3");
let mut irq_file = irq.irq_handle("ac97d");
let mut device = unsafe { device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device") };
let socket_fd = libredox::call::open(":audiohw", flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK, 0).expect("ac97d: failed to create hda scheme");
let mut device =
unsafe { device::Ac97::new(bar0, bar1).expect("ac97d: failed to allocate device") };
let socket_fd = libredox::call::open(
":audiohw",
flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK,
0,
)
.expect("ac97d: failed to create hda scheme");
let mut socket = unsafe { File::from_raw_fd(socket_fd as RawFd) };
user_data! {
@@ -59,9 +69,18 @@ fn main() {
}
}
let mut event_queue = EventQueue::<Source>::new().expect("ac97d: Could not create event queue.");
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ).unwrap();
event_queue.subscribe(socket_fd, Source::Scheme, event::EventFlags::READ).unwrap();
let mut event_queue =
EventQueue::<Source>::new().expect("ac97d: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(socket_fd, Source::Scheme, event::EventFlags::READ)
.unwrap();
daemon.ready().expect("ac97d: failed to signal readiness");
@@ -70,7 +89,10 @@ fn main() {
let mut todo = Vec::<Packet>::new();
let all = [Source::Irq, Source::Scheme];
'events: for event in all.into_iter().chain(event_queue.map(|e| e.expect("ac97d: failed to get next event").user_data)) {
'events: for event in all
.into_iter()
.chain(event_queue.map(|e| e.expect("ac97d: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
@@ -91,11 +113,11 @@ fn main() {
}
/*
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
}
Source::Scheme => {
@@ -104,10 +126,12 @@ fn main() {
match socket.read(&mut packet) {
Ok(0) => break 'events,
Ok(_) => (),
Err(err) => if err.kind() == ErrorKind::WouldBlock {
break;
} else {
panic!("ac97d: failed to read socket: {err}");
Err(err) => {
if err.kind() == ErrorKind::WouldBlock {
break;
} else {
panic!("ac97d: failed to read socket: {err}");
}
}
}
@@ -120,15 +144,16 @@ fn main() {
}
/*
let next_read = device.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
let next_read = device.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
}
}
std::process::exit(0);
}).expect("ac97d: failed to daemonize");
})
.expect("ac97d: failed to daemonize");
}
+12 -8
View File
@@ -177,8 +177,7 @@ impl Corb {
fn send_command(&mut self, cmd: u32) {
// wait for the commands to finish
while (self.regs.corbwp.read() & 0xff) != (self.regs.corbrp.read() & 0xff) {}
let write_pos: usize =
((self.regs.corbwp.read() as usize & 0xFF) + 1) % self.corb_count;
let write_pos: usize = ((self.regs.corbwp.read() as usize & 0xFF) + 1) % self.corb_count;
unsafe {
*self.corb_base.offset(write_pos as isize) = cmd;
}
@@ -348,15 +347,20 @@ pub struct CommandBuffer {
}
impl CommandBuffer {
pub fn new(
regs_addr: usize,
mut cmd_buff: Dma<[u8; 0x1000]>,
) -> CommandBuffer {
let corb = Corb::new(regs_addr + CORB_OFFSET, cmd_buff.physical(), cmd_buff.as_mut_ptr().cast());
pub fn new(regs_addr: usize, mut cmd_buff: Dma<[u8; 0x1000]>) -> CommandBuffer {
let corb = Corb::new(
regs_addr + CORB_OFFSET,
cmd_buff.physical(),
cmd_buff.as_mut_ptr().cast(),
);
let rirb = Rirb::new(
regs_addr + RIRB_OFFSET,
cmd_buff.physical() + CORB_BUFF_MAX_SIZE,
cmd_buff.as_mut_ptr().cast::<u8>().wrapping_add(CORB_BUFF_MAX_SIZE).cast(),
cmd_buff
.as_mut_ptr()
.cast::<u8>()
.wrapping_add(CORB_BUFF_MAX_SIZE)
.cast(),
);
let icmd = ImmediateCommand::new(regs_addr + ICMD_OFFSET);
File diff suppressed because it is too large Load Diff
+9 -10
View File
@@ -1,17 +1,16 @@
#![allow(dead_code)]
pub mod device;
pub mod stream;
pub mod common;
pub mod node;
pub mod cmdbuff;
pub mod common;
pub mod device;
pub mod node;
pub mod stream;
pub use self::stream::*;
pub use self::node::*;
pub use self::stream::*;
pub use self::cmdbuff::*;
pub use self::stream::StreamDescriptorRegs;
pub use self::stream::BufferDescriptorListEntry;
pub use self::stream::BitsPerSample;
pub use self::stream::StreamBuffer;
pub use self::device::IntelHDA;
pub use self::stream::BitsPerSample;
pub use self::stream::BufferDescriptorListEntry;
pub use self::stream::StreamBuffer;
pub use self::stream::StreamDescriptorRegs;
+82 -82
View File
@@ -1,108 +1,108 @@
use std::{mem, fmt};
use super::common::*;
use std::{fmt, mem};
#[derive(Clone)]
pub struct HDANode {
pub addr: WidgetAddr,
pub addr: WidgetAddr,
// 0x4
pub subnode_count: u16,
pub subnode_start: u16,
// 0x4
pub subnode_count: u16,
pub subnode_start: u16,
// 0x5
pub function_group_type: u8,
// 0x5
pub function_group_type: u8,
// 0x9
pub capabilities: u32,
// 0x9
pub capabilities: u32,
// 0xE
pub conn_list_len: u8,
// 0xE
pub conn_list_len: u8,
pub connections: Vec<WidgetAddr>,
pub connections: Vec<WidgetAddr>,
pub connection_default: u8,
pub connection_default: u8,
pub is_widget: bool,
pub is_widget: bool,
pub config_default: u32,
pub config_default: u32,
}
impl HDANode {
pub fn new() -> HDANode {
HDANode {
addr: (0,0),
subnode_count: 0,
subnode_start: 0,
function_group_type: 0,
capabilities: 0,
conn_list_len: 0,
pub fn new() -> HDANode {
HDANode {
addr: (0, 0),
subnode_count: 0,
subnode_start: 0,
function_group_type: 0,
capabilities: 0,
conn_list_len: 0,
config_default: 0,
is_widget: false,
connections: Vec::<WidgetAddr>::new(),
connection_default: 0,
}
}
config_default: 0,
is_widget: false,
connections: Vec::<WidgetAddr>::new(),
connection_default: 0,
}
}
pub fn widget_type(&self) -> HDAWidgetType {
unsafe { mem::transmute( ((self.capabilities >> 20) & 0xF) as u8 )}
pub fn widget_type(&self) -> HDAWidgetType {
unsafe { mem::transmute(((self.capabilities >> 20) & 0xF) as u8) }
}
}
pub fn device_default(&self) -> Option<DefaultDevice> {
if self.widget_type() != HDAWidgetType::PinComplex {
None
} else {
Some(unsafe { mem::transmute(((self.config_default >> 20) & 0xF) as u8) })
}
}
pub fn device_default(&self) -> Option<DefaultDevice> {
if self.widget_type() != HDAWidgetType::PinComplex {
None
} else {
Some(unsafe { mem::transmute( ((self.config_default >> 20) & 0xF) as u8 )} )
}
}
pub fn configuration_default(&self) -> ConfigurationDefault {
ConfigurationDefault::from_u32(self.config_default)
}
pub fn configuration_default(&self) -> ConfigurationDefault {
ConfigurationDefault::from_u32(self.config_default)
}
pub fn addr(&self) -> WidgetAddr {
self.addr
}
pub fn addr(&self) -> WidgetAddr {
self.addr
}
}
impl fmt::Display for HDANode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.addr == (0,0) {
write!(f, "Addr: {:02X}:{:02X}, Root Node.", self.addr.0, self.addr.1)
} else if self.is_widget {
match self.widget_type() {
HDAWidgetType::PinComplex => write!(
f,
"Addr: {:02X}:{:02X}, Type: {:?}: {:?}, Inputs: {}/{}: {:X?}.",
self.addr.0,
self.addr.1,
self.widget_type(),
self.device_default().unwrap(),
self.connection_default,
self.conn_list_len,
self.connections
),
_ => write!(
f,
"Addr: {:02X}:{:02X}, Type: {:?}, Inputs: {}/{}: {:X?}.",
self.addr.0,
self.addr.1,
self.widget_type(),
self.connection_default,
self.conn_list_len,
self.connections
),
}
} else {
write!(
f,
"Addr: {:02X}:{:02X}, AFG: {}, Widget count {}.",
self.addr.0,
self.addr.1,
self.function_group_type,
self.subnode_count
)
}
if self.addr == (0, 0) {
write!(
f,
"Addr: {:02X}:{:02X}, Root Node.",
self.addr.0, self.addr.1
)
} else if self.is_widget {
match self.widget_type() {
HDAWidgetType::PinComplex => write!(
f,
"Addr: {:02X}:{:02X}, Type: {:?}: {:?}, Inputs: {}/{}: {:X?}.",
self.addr.0,
self.addr.1,
self.widget_type(),
self.device_default().unwrap(),
self.connection_default,
self.conn_list_len,
self.connections
),
_ => write!(
f,
"Addr: {:02X}:{:02X}, Type: {:?}, Inputs: {}/{}: {:X?}.",
self.addr.0,
self.addr.1,
self.widget_type(),
self.connection_default,
self.conn_list_len,
self.connections
),
}
} else {
write!(
f,
"Addr: {:02X}:{:02X}, AFG: {}, Widget count {}.",
self.addr.0, self.addr.1, self.function_group_type, self.subnode_count
)
}
}
}
+287 -252
View File
@@ -1,353 +1,388 @@
use common::dma::Dma;
use common::io::{Mmio, Io};
use syscall::PAGE_SIZE;
use syscall::error::{Error, EIO, Result};
use std::result;
use common::io::{Io, Mmio};
use std::cmp::min;
use std::ptr::copy_nonoverlapping;
use std::ptr;
use std::ptr::copy_nonoverlapping;
use std::result;
use syscall::error::{Error, Result, EIO};
use syscall::PAGE_SIZE;
extern crate syscall;
pub enum BaseRate {
BR44_1,
BR48,
BR44_1,
BR48,
}
pub struct SampleRate {
base: BaseRate,
mult: u16,
div: u16,
base: BaseRate,
mult: u16,
div: u16,
}
use self::BaseRate::{BR44_1, BR48};
pub const SR_8: SampleRate = SampleRate {base: BR48 , mult: 1, div: 6};
pub const SR_11_025: SampleRate = SampleRate {base: BR44_1, mult: 1, div: 4};
pub const SR_16: SampleRate = SampleRate {base: BR48 , mult: 1, div: 3};
pub const SR_22_05: SampleRate = SampleRate {base: BR44_1, mult: 1, div: 2};
pub const SR_32: SampleRate = SampleRate {base: BR48 , mult: 2, div: 3};
pub const SR_44_1: SampleRate = SampleRate {base: BR44_1, mult: 1, div: 1};
pub const SR_48: SampleRate = SampleRate {base: BR48 , mult: 1, div: 1};
pub const SR_88_1: SampleRate = SampleRate {base: BR44_1, mult: 2, div: 1};
pub const SR_96: SampleRate = SampleRate {base: BR48 , mult: 2, div: 1};
pub const SR_176_4: SampleRate = SampleRate {base: BR44_1, mult: 4, div: 1};
pub const SR_192: SampleRate = SampleRate {base: BR48 , mult: 4, div: 1};
pub const SR_8: SampleRate = SampleRate {
base: BR48,
mult: 1,
div: 6,
};
pub const SR_11_025: SampleRate = SampleRate {
base: BR44_1,
mult: 1,
div: 4,
};
pub const SR_16: SampleRate = SampleRate {
base: BR48,
mult: 1,
div: 3,
};
pub const SR_22_05: SampleRate = SampleRate {
base: BR44_1,
mult: 1,
div: 2,
};
pub const SR_32: SampleRate = SampleRate {
base: BR48,
mult: 2,
div: 3,
};
pub const SR_44_1: SampleRate = SampleRate {
base: BR44_1,
mult: 1,
div: 1,
};
pub const SR_48: SampleRate = SampleRate {
base: BR48,
mult: 1,
div: 1,
};
pub const SR_88_1: SampleRate = SampleRate {
base: BR44_1,
mult: 2,
div: 1,
};
pub const SR_96: SampleRate = SampleRate {
base: BR48,
mult: 2,
div: 1,
};
pub const SR_176_4: SampleRate = SampleRate {
base: BR44_1,
mult: 4,
div: 1,
};
pub const SR_192: SampleRate = SampleRate {
base: BR48,
mult: 4,
div: 1,
};
#[repr(u8)]
pub enum BitsPerSample {
Bits8 = 0,
Bits16 = 1,
Bits20 = 2,
Bits24 = 3,
Bits32 = 4,
Bits8 = 0,
Bits16 = 1,
Bits20 = 2,
Bits24 = 3,
Bits32 = 4,
}
pub fn format_to_u16(sr: &SampleRate, bps: BitsPerSample, channels: u8) -> u16 {
// 3.3.41
let base: u16 = match sr.base {
BaseRate::BR44_1 => 1 << 14,
BaseRate::BR48 => 0,
};
pub fn format_to_u16(sr: &SampleRate, bps: BitsPerSample, channels:u8) -> u16{
let mult = ((sr.mult - 1) & 0x7) << 11;
let div = ((sr.div - 1) & 0x7) << 8;
// 3.3.41
let bits = (bps as u16) << 4;
let base:u16 = match sr.base {
BaseRate::BR44_1 => { 1 << 14},
BaseRate::BR48 => { 0 },
};
let chan = ((channels - 1) & 0xF) as u16;
let mult = ((sr.mult - 1) & 0x7) << 11;
let div = ((sr.div - 1) & 0x7) << 8;
let bits = (bps as u16) << 4;
let chan = ((channels - 1) & 0xF) as u16;
let val:u16 = base | mult | div | bits | chan;
val
let val: u16 = base | mult | div | bits | chan;
val
}
#[repr(packed)]
pub struct StreamDescriptorRegs {
ctrl_lo: Mmio<u16>,
ctrl_hi: Mmio<u8>,
status: Mmio<u8>,
link_pos: Mmio<u32>,
buff_length: Mmio<u32>,
last_valid_index: Mmio<u16>,
resv1: Mmio<u16>,
fifo_size_: Mmio<u16>,
format: Mmio<u16>,
resv2: Mmio<u32>,
buff_desc_list_lo: Mmio<u32>,
buff_desc_list_hi: Mmio<u32>,
ctrl_lo: Mmio<u16>,
ctrl_hi: Mmio<u8>,
status: Mmio<u8>,
link_pos: Mmio<u32>,
buff_length: Mmio<u32>,
last_valid_index: Mmio<u16>,
resv1: Mmio<u16>,
fifo_size_: Mmio<u16>,
format: Mmio<u16>,
resv2: Mmio<u32>,
buff_desc_list_lo: Mmio<u32>,
buff_desc_list_hi: Mmio<u32>,
}
impl StreamDescriptorRegs {
pub fn status(&self) -> u8 {
self.status.read()
}
pub fn status(&self) -> u8 {
self.status.read()
}
pub fn set_status(&mut self, status: u8){
self.status.write(status);
}
pub fn set_status(&mut self, status: u8) {
self.status.write(status);
}
pub fn control(&self) -> u32 {
let mut ctrl = self.ctrl_lo.read() as u32;
ctrl |= (self.ctrl_hi.read() as u32) << 16;
ctrl
}
pub fn control(&self) -> u32 {
let mut ctrl = self.ctrl_lo.read() as u32;
ctrl |= (self.ctrl_hi.read() as u32) << 16;
ctrl
}
pub fn set_control(&mut self, control:u32) {
self.ctrl_lo.write((control & 0xFFFF) as u16);
self.ctrl_hi.write(((control >> 16) & 0xFF) as u8);
}
pub fn set_control(&mut self, control: u32) {
self.ctrl_lo.write((control & 0xFFFF) as u16);
self.ctrl_hi.write(((control >> 16) & 0xFF) as u8);
}
pub fn set_pcm_format(&mut self, sr: &SampleRate, bps: BitsPerSample, channels:u8) {
pub fn set_pcm_format(&mut self, sr: &SampleRate, bps: BitsPerSample, channels: u8) {
// 3.3.41
let val = format_to_u16(sr, bps, channels);
self.format.write(val);
}
// 3.3.41
pub fn fifo_size(&self) -> u16 {
self.fifo_size_.read()
}
let val = format_to_u16(sr,bps,channels);
self.format.write(val);
pub fn set_cyclic_buffer_length(&mut self, length: u32) {
self.buff_length.write(length);
}
}
pub fn cyclic_buffer_length(&self) -> u32 {
self.buff_length.read()
}
pub fn fifo_size(&self) -> u16 {
self.fifo_size_.read()
}
pub fn run(&mut self) {
let val = self.control() | (1 << 1);
self.set_control(val);
}
pub fn set_cyclic_buffer_length(&mut self, length: u32) {
self.buff_length.write(length);
}
pub fn stop(&mut self) {
let val = self.control() & !(1 << 1);
self.set_control(val);
}
pub fn cyclic_buffer_length(&self) -> u32 {
self.buff_length.read()
}
pub fn stream_number(&self) -> u8 {
((self.control() >> 20) & 0xF) as u8
}
pub fn run(&mut self) {
let val = self.control() | (1 << 1);
self.set_control(val);
}
pub fn set_stream_number(&mut self, stream_number: u8) {
let val = (self.control() & 0x00FFFF) | (((stream_number & 0xF) as u32) << 20);
self.set_control(val);
}
pub fn stop(&mut self) {
let val = self.control() & !(1 << 1);
self.set_control(val);
}
pub fn set_address(&mut self, addr: usize) {
self.buff_desc_list_lo.write((addr & 0xFFFFFFFF) as u32);
self.buff_desc_list_hi
.write((((addr as u64) >> 32) & 0xFFFFFFFF) as u32);
}
pub fn stream_number(&self) -> u8 {
((self.control() >> 20) & 0xF) as u8
}
pub fn set_last_valid_index(&mut self, index: u16) {
self.last_valid_index.write(index);
}
pub fn set_stream_number(&mut self, stream_number: u8) {
let val = (self.control() & 0x00FFFF ) | (((stream_number & 0xF ) as u32) << 20);
self.set_control(val);
}
pub fn link_position(&self) -> u32 {
self.link_pos.read()
}
pub fn set_address(&mut self, addr: usize) {
self.buff_desc_list_lo.write( (addr & 0xFFFFFFFF) as u32);
self.buff_desc_list_hi.write( ( ((addr as u64) >> 32) & 0xFFFFFFFF) as u32);
}
pub fn set_interrupt_on_completion(&mut self, enable: bool) {
let mut ctrl = self.control();
if enable {
ctrl |= 1 << 2;
} else {
ctrl &= !(1 << 2);
}
self.set_control(ctrl);
}
pub fn set_last_valid_index(&mut self, index:u16) {
self.last_valid_index.write(index);
}
pub fn link_position(&self) -> u32 {
self.link_pos.read()
}
pub fn set_interrupt_on_completion(&mut self, enable:bool) {
let mut ctrl = self.control();
if enable {
ctrl |= 1 << 2;
} else {
ctrl &= !(1 << 2);
}
self.set_control(ctrl);
}
pub fn buffer_complete(&self) -> bool {
self.status.readf(1 << 2)
}
pub fn clear_interrupts(&mut self) {
self.status.write(0x7 << 2);
}
// get sample size in bytes
pub fn sample_size(&self) -> usize {
let format = self.format.read();
let chan = (format & 0xF) as usize;
let bits = ((format >> 4) & 0xF) as usize;
match bits {
0 => 1 * (chan + 1),
1 => 2 * (chan + 1),
_ => 4 * (chan + 1),
}
}
pub fn buffer_complete(&self) -> bool {
self.status.readf(1 << 2)
}
pub fn clear_interrupts(&mut self) {
self.status.write(0x7 << 2);
}
// get sample size in bytes
pub fn sample_size(&self) -> usize {
let format = self.format.read();
let chan = (format & 0xF) as usize;
let bits = ((format >> 4) & 0xF) as usize;
match bits {
0 => 1 * (chan + 1),
1 => 2 * (chan + 1),
_ => 4 * (chan + 1),
}
}
}
pub struct OutputStream {
buff: StreamBuffer,
buff: StreamBuffer,
desc_regs: &'static mut StreamDescriptorRegs,
desc_regs: &'static mut StreamDescriptorRegs,
}
impl OutputStream {
pub fn new(block_count: usize, block_length: usize, regs: &'static mut StreamDescriptorRegs) -> OutputStream {
OutputStream {
buff: StreamBuffer::new(block_length, block_count).unwrap(),
pub fn new(
block_count: usize,
block_length: usize,
regs: &'static mut StreamDescriptorRegs,
) -> OutputStream {
OutputStream {
buff: StreamBuffer::new(block_length, block_count).unwrap(),
desc_regs: regs,
}
}
desc_regs: regs,
}
}
pub fn write_block(&mut self, buf: &[u8]) -> Result<usize> {
self.buff.write_block(buf)
}
pub fn write_block(&mut self, buf: &[u8]) -> Result<usize> {
self.buff.write_block(buf)
}
pub fn block_size(&self) -> usize {
self.buff.block_size()
}
pub fn block_size(&self) -> usize {
self.buff.block_size()
}
pub fn block_count(&self) -> usize {
self.buff.block_count()
}
pub fn block_count(&self) -> usize {
self.buff.block_count()
}
pub fn current_block(&self) -> usize {
self.buff.current_block()
}
pub fn current_block(&self) -> usize {
self.buff.current_block()
}
pub fn addr(&self) -> usize {
self.buff.addr()
}
pub fn addr(&self) -> usize {
self.buff.addr()
}
pub fn phys(&self) -> usize {
self.buff.phys()
}
pub fn phys(&self) -> usize {
self.buff.phys()
}
}
#[repr(packed)]
pub struct BufferDescriptorListEntry {
addr_low: Mmio<u32>,
addr_high: Mmio<u32>,
len: Mmio<u32>,
ioc_resv: Mmio<u32>,
addr_low: Mmio<u32>,
addr_high: Mmio<u32>,
len: Mmio<u32>,
ioc_resv: Mmio<u32>,
}
impl BufferDescriptorListEntry {
pub fn address(&self) -> u64 {
(self.addr_low.read() as u64) |
((self.addr_high.read() as u64) << 32)
}
pub fn address(&self) -> u64 {
(self.addr_low.read() as u64) | ((self.addr_high.read() as u64) << 32)
}
pub fn set_address(&mut self, addr: u64) {
self.addr_low.write(addr as u32);
self.addr_high.write((addr >> 32) as u32);
}
pub fn set_address(&mut self, addr: u64) {
self.addr_low.write(addr as u32);
self.addr_high.write((addr >> 32) as u32);
}
pub fn length(&self) -> u32 {
self.len.read()
}
pub fn length(&self) -> u32 {
self.len.read()
}
pub fn set_length(&mut self, length: u32) {
self.len.write(length)
}
pub fn set_length(&mut self, length: u32) {
self.len.write(length)
}
pub fn interrupt_on_completion(&self) -> bool {
(self.ioc_resv.read() & 0x1) == 0x1
}
pub fn interrupt_on_completion(&self) -> bool {
(self.ioc_resv.read() & 0x1) == 0x1
}
pub fn set_interrupt_on_complete(&mut self, ioc: bool) {
self.ioc_resv.writef(1, ioc);
}
pub fn set_interrupt_on_complete(&mut self, ioc: bool) {
self.ioc_resv.writef(1, ioc);
}
}
pub struct StreamBuffer {
mem: Dma<[u8]>,
mem: Dma<[u8]>,
block_cnt: usize,
block_len: usize,
block_cnt: usize,
block_len: usize,
cur_pos: usize,
cur_pos: usize,
}
impl StreamBuffer {
pub fn new(block_length: usize, block_count: usize) -> result::Result<StreamBuffer, &'static str> {
let page_aligned_size = (block_length * block_count).next_multiple_of(PAGE_SIZE);
let mem = unsafe { Dma::zeroed_slice(page_aligned_size).map_err(|_| "Could not allocate physical memory for buffer.")?.assume_init() };
pub fn new(
block_length: usize,
block_count: usize,
) -> result::Result<StreamBuffer, &'static str> {
let page_aligned_size = (block_length * block_count).next_multiple_of(PAGE_SIZE);
let mem = unsafe {
Dma::zeroed_slice(page_aligned_size)
.map_err(|_| "Could not allocate physical memory for buffer.")?
.assume_init()
};
Ok(StreamBuffer {
mem,
block_len: block_length,
block_cnt: block_count,
cur_pos: 0,
})
}
Ok(StreamBuffer {
mem,
block_len: block_length,
block_cnt: block_count,
cur_pos: 0,
})
}
pub fn length(&self) -> usize {
self.block_len * self.block_cnt
}
pub fn length(&self) -> usize {
self.block_len * self.block_cnt
}
pub fn addr(&self) -> usize {
self.mem.as_ptr() as usize
}
pub fn addr(&self) -> usize {
self.mem.as_ptr() as usize
}
pub fn phys(&self) -> usize {
self.mem.physical()
}
pub fn phys(&self) -> usize {
self.mem.physical()
}
pub fn block_size(&self) -> usize {
self.block_len
}
pub fn block_size(&self) -> usize {
self.block_len
}
pub fn block_count(&self) -> usize {
self.block_cnt
}
pub fn block_count(&self) -> usize {
self.block_cnt
}
pub fn current_block(&self) -> usize {
self.cur_pos
}
pub fn current_block(&self) -> usize {
self.cur_pos
}
pub fn write_block(&mut self, buf: &[u8]) -> Result<usize> {
if buf.len() != self.block_size() {
return Err(Error::new(EIO))
}
let len = min(self.block_size(), buf.len());
pub fn write_block(&mut self, buf: &[u8]) -> Result<usize> {
if buf.len() != self.block_size() {
return Err(Error::new(EIO));
}
let len = min(self.block_size(), buf.len());
//log::trace!("Phys: {:X} Virt: {:X} Offset: {:X} Len: {:X}", self.phys(), self.addr(), self.current_block() * self.block_size(), len);
unsafe {
copy_nonoverlapping(
buf.as_ptr(),
(self.addr() + self.current_block() * self.block_size()) as *mut u8,
len,
);
}
//log::trace!("Phys: {:X} Virt: {:X} Offset: {:X} Len: {:X}", self.phys(), self.addr(), self.current_block() * self.block_size(), len);
unsafe {
copy_nonoverlapping(buf.as_ptr(), (self.addr() + self.current_block() * self.block_size()) as * mut u8, len);
}
self.cur_pos += 1;
self.cur_pos %= self.block_count();
self.cur_pos += 1;
self.cur_pos %= self.block_count();
Ok(len)
}
Ok(len)
}
}
impl Drop for StreamBuffer {
fn drop(&mut self) {
log::debug!("IHDA: Deallocating buffer.");
}
fn drop(&mut self) {
log::debug!("IHDA: Deallocating buffer.");
}
}
+75 -39
View File
@@ -2,46 +2,53 @@
#![feature(int_roundings)]
extern crate bitflags;
extern crate event;
extern crate spin;
extern crate syscall;
extern crate event;
use std::usize;
use std::fs::File;
use std::io::{ErrorKind, Read, Write, Result};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use libredox::flag;
use syscall::{Packet, SchemeBlockMut, EventFlags};
use std::cell::RefCell;
use std::fs::File;
use std::io::{ErrorKind, Read, Result, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::Arc;
use std::usize;
use syscall::{EventFlags, Packet, SchemeBlockMut};
use event::{user_data, EventQueue};
use pcid_interface::{MsiSetFeatureInfo, PciFunctionHandle, PciFeature, PciFeatureInfo, SetFeatureInfo};
#[cfg(target_arch = "x86_64")]
use pcid_interface::irq_helpers::allocate_single_interrupt_vector_for_msi;
use pcid_interface::irq_helpers::read_bsp_apic_id;
use pcid_interface::{
MsiSetFeatureInfo, PciFeature, PciFeatureInfo, PciFunctionHandle, SetFeatureInfo,
};
pub mod hda;
/*
VEND:PROD
Virtualbox 8086:2668
QEMU ICH9 8086:293E
82801H ICH8 8086:284B
*/
VEND:PROD
Virtualbox 8086:2668
QEMU ICH9 8086:293E
82801H ICH8 8086:284B
*/
#[cfg(target_arch = "x86_64")]
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
let pci_config = pcid_handle.config();
let all_pci_features = pcid_handle.fetch_all_features().expect("ihdad: failed to fetch pci features");
let all_pci_features = pcid_handle
.fetch_all_features()
.expect("ihdad: failed to fetch pci features");
log::debug!("PCI FEATURES: {:?}", all_pci_features);
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
if has_msi && !has_msix {
let capability = match pcid_handle.feature_info(PciFeature::Msi).expect("ihdad: failed to retrieve the MSI capability structure from pcid") {
let capability = match pcid_handle
.feature_info(PciFeature::Msi)
.expect("ihdad: failed to retrieve the MSI capability structure from pcid")
{
PciFeatureInfo::Msi(s) => s,
PciFeatureInfo::MsiX(_) => panic!(),
};
@@ -51,16 +58,21 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
// pcid_interface, so that this can be shared between nvmed, xhcid, ixgebd, etc..
let destination_id = read_bsp_apic_id().expect("ihdad: failed to read BSP apic id");
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
let (msg_addr_and_data, interrupt_handle) =
allocate_single_interrupt_vector_for_msi(destination_id);
let set_feature_info = MsiSetFeatureInfo {
multi_message_enable: Some(0),
message_address_and_data: Some(msg_addr_and_data),
mask_bits: None,
};
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info)).expect("ihdad: failed to set feature info");
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(set_feature_info))
.expect("ihdad: failed to set feature info");
pcid_handle.enable_feature(PciFeature::Msi).expect("ihdad: failed to enable MSI");
pcid_handle
.enable_feature(PciFeature::Msi)
.expect("ihdad: failed to enable MSI");
log::debug!("Enabled MSI");
interrupt_handle
@@ -96,7 +108,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::LevelFilter::Info,
);
let mut pcid_handle = PciFunctionHandle::connect_default().expect("ihdad: failed to setup channel to pcid");
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("ihdad: failed to setup channel to pcid");
let pci_config = pcid_handle.config();
@@ -105,7 +118,9 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::info!(" + IHDA {}", pci_config.func.display());
let address = unsafe { pcid_handle.map_bar(0).expect("ihdad") }.ptr.as_ptr() as usize;
let address = unsafe { pcid_handle.map_bar(0).expect("ihdad") }
.ptr
.as_ptr() as usize;
//TODO: MSI-X
let mut irq_file = get_int_method(&mut pcid_handle);
@@ -121,13 +136,29 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
}
let mut event_queue = EventQueue::<Source>::new().expect("ihdad: Could not create event queue.");
let mut device = unsafe { hda::IntelHDA::new(address, vend_prod).expect("ihdad: failed to allocate device") };
let socket_fd = libredox::call::open(":audiohw", flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK, 0).expect("ihdad: failed to create hda scheme");
let mut event_queue =
EventQueue::<Source>::new().expect("ihdad: Could not create event queue.");
let mut device = unsafe {
hda::IntelHDA::new(address, vend_prod).expect("ihdad: failed to allocate device")
};
let socket_fd = libredox::call::open(
":audiohw",
flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK,
0,
)
.expect("ihdad: failed to create hda scheme");
let mut socket = unsafe { File::from_raw_fd(socket_fd as RawFd) };
event_queue.subscribe(socket_fd, Source::Scheme, event::EventFlags::READ).unwrap();
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ).unwrap();
event_queue
.subscribe(socket_fd, Source::Scheme, event::EventFlags::READ)
.unwrap();
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
daemon.ready().expect("ihdad: failed to signal readiness");
@@ -137,7 +168,10 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let all = [Source::Irq, Source::Scheme];
'events: for event in all.into_iter().chain(event_queue.map(|e| e.expect("failed to get next event").user_data)) {
'events: for event in all
.into_iter()
.chain(event_queue.map(|e| e.expect("failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
@@ -158,11 +192,11 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
/*
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
let next_read = device_irq.next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
}
Source::Scheme => {
@@ -171,10 +205,12 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
match socket.read(&mut packet) {
Ok(0) => break 'events,
Ok(_) => (),
Err(err) => if err.kind() == ErrorKind::WouldBlock {
break;
} else {
panic!("ihdad: failed to read from socket: {err}");
Err(err) => {
if err.kind() == ErrorKind::WouldBlock {
break;
} else {
panic!("ihdad: failed to read from socket: {err}");
}
}
}
@@ -187,11 +223,11 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
/*
let next_read = device.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
let next_read = device.borrow().next_read();
if next_read > 0 {
return Ok(Some(next_read));
}
*/
}
}
}
+2 -1
View File
@@ -41,5 +41,6 @@ fn main() {
.write(&packet)
.expect("pcspkrd: failed to write responses to pcspkr scheme");
}
}).expect("pcspkrd: failed to daemonize");
})
.expect("pcspkrd: failed to daemonize");
}
+8 -5
View File
@@ -1,12 +1,12 @@
#![allow(dead_code)]
use std::{thread, time};
use std::collections::BTreeMap;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::{thread, time};
use common::io::{Pio, Io, ReadOnly, WriteOnly};
use common::io::{Io, Pio, ReadOnly, WriteOnly};
use syscall::error::{Error, EACCES, EBADF, Result, ENODEV};
use syscall::error::{Error, Result, EACCES, EBADF, ENODEV};
use syscall::scheme::SchemeBlockMut;
use spin::Mutex;
@@ -68,7 +68,7 @@ impl Sb16 {
fn dsp_read(&mut self) -> Result<u8> {
// Bit 7 must be 1 before data can be sent
while ! self.dsp_read_status.readf(1 << 7) {
while !self.dsp_read_status.readf(1 << 7) {
//TODO: timeout!
std::thread::yield_now();
}
@@ -212,6 +212,9 @@ impl SchemeBlockMut for Sb16 {
fn close(&mut self, id: usize) -> Result<Option<usize>> {
let mut handles = self.handles.lock();
handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(Some(0)))
handles
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(Some(0)))
}
}
+45 -25
View File
@@ -1,8 +1,8 @@
//#![deny(warnings)]
use std::{env, usize};
use libredox::errno::{EAGAIN, EWOULDBLOCK};
use libredox::{flag, Fd};
use std::{env, usize};
use syscall::{Packet, SchemeBlockMut};
use event::{user_data, EventQueue};
@@ -29,12 +29,19 @@ fn main() {
common::acquire_port_io_rights().expect("sb16d: failed to acquire port IO rights");
let mut device = unsafe { device::Sb16::new(addr).expect("sb16d: failed to allocate device") };
let socket = Fd::open(":audiohw", flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK, 0).expect("sb16d: failed to create hda scheme");
let mut device =
unsafe { device::Sb16::new(addr).expect("sb16d: failed to allocate device") };
let socket = Fd::open(
":audiohw",
flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK,
0,
)
.expect("sb16d: failed to create hda scheme");
//TODO: error on multiple IRQs?
let irq_file = match device.irqs.first() {
Some(irq) => Fd::open(&format!("/scheme/irq/{}", irq), flag::O_RDWR, 0).expect("sb16d: failed to open IRQ file"),
Some(irq) => Fd::open(&format!("/scheme/irq/{}", irq), flag::O_RDWR, 0)
.expect("sb16d: failed to open IRQ file"),
None => panic!("sb16d: no IRQs found"),
};
user_data! {
@@ -44,9 +51,14 @@ fn main() {
}
}
let event_queue = EventQueue::<Source>::new().expect("sb16d: Could not create event queue.");
event_queue.subscribe(irq_file.raw(), Source::Irq, event::EventFlags::READ).unwrap();
event_queue.subscribe(socket.raw(), Source::Scheme, event::EventFlags::READ).unwrap();
let event_queue =
EventQueue::<Source>::new().expect("sb16d: Could not create event queue.");
event_queue
.subscribe(irq_file.raw(), Source::Irq, event::EventFlags::READ)
.unwrap();
event_queue
.subscribe(socket.raw(), Source::Scheme, event::EventFlags::READ)
.unwrap();
daemon.ready().expect("sb16d: failed to signal readiness");
@@ -56,7 +68,10 @@ fn main() {
let all = [Source::Irq, Source::Scheme];
'events: for event in all.into_iter().chain(event_queue.map(|e| e.expect("sb16d: failed to get next event").user_data)) {
'events: for event in all
.into_iter()
.chain(event_queue.map(|e| e.expect("sb16d: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
@@ -70,7 +85,9 @@ fn main() {
if let Some(a) = device.handle(&mut todo[i]) {
let mut packet = todo.remove(i);
packet.a = a;
socket.write(&packet).expect("sb16d: failed to write to socket");
socket
.write(&packet)
.expect("sb16d: failed to write to socket");
} else {
i += 1;
}
@@ -84,30 +101,33 @@ fn main() {
*/
}
}
Source::Scheme => {
loop {
let mut packet = Packet::default();
match socket.read(&mut packet) {
Ok(0) => break 'events,
Ok(_) => (),
Err(err) => if err.errno() == EWOULDBLOCK || err.errno() == EAGAIN {
Source::Scheme => loop {
let mut packet = Packet::default();
match socket.read(&mut packet) {
Ok(0) => break 'events,
Ok(_) => (),
Err(err) => {
if err.errno() == EWOULDBLOCK || err.errno() == EAGAIN {
break;
} else {
panic!("sb16d: failed to read from scheme socket");
}
}
if let Some(a) = device.handle(&mut packet) {
packet.a = a;
socket.write(&packet).expect("sb16d: failed to write to scheme socket");
} else {
todo.push(packet);
}
}
}
if let Some(a) = device.handle(&mut packet) {
packet.a = a;
socket
.write(&packet)
.expect("sb16d: failed to write to scheme socket");
} else {
todo.push(packet);
}
},
}
}
std::process::exit(0);
}).expect("sb16d: failed to daemonize");
})
.expect("sb16d: failed to daemonize");
}
+5 -1
View File
@@ -35,7 +35,11 @@ impl<T> Mmio<T> {
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
impl<T> Io for Mmio<T>
where
T: Copy + PartialEq + core::ops::BitAnd<Output = T> + core::ops::BitOr<Output = T> + core::ops::Not<Output = T>,
T: Copy
+ PartialEq
+ core::ops::BitAnd<Output = T>
+ core::ops::BitOr<Output = T>
+ core::ops::Not<Output = T>,
{
type Value = T;
+884 -881
View File
File diff suppressed because it is too large Load Diff
+10 -30
View File
@@ -421,10 +421,7 @@ pub const PHY_CTRL_RTL_MODE: u32 = 1 << 1;
/* bit0: out of dsp RST state */
pub const PHY_CTRL_DSPRST_OUT: u32 = 1 << 0;
pub const PHY_CTRL_DSPRST_TO: u32 = 80;
pub const PHY_CTRL_CLS: u32 =
PHY_CTRL_LED_MODE |
PHY_CTRL_100AB_EN |
PHY_CTRL_PLL_ON;
pub const PHY_CTRL_CLS: u32 = PHY_CTRL_LED_MODE | PHY_CTRL_100AB_EN | PHY_CTRL_PLL_ON;
pub const MAC_STS: u32 = 0x1410;
pub const MAC_STS_SFORCE_MASK: u32 = 0xF;
@@ -439,10 +436,7 @@ pub const MAC_STS_RXQ_BUSY: u32 = 1 << 2;
pub const MAC_STS_TXMAC_BUSY: u32 = 1 << 1;
pub const MAC_STS_RXMAC_BUSY: u32 = 1 << 0;
pub const MAC_STS_IDLE: u32 =
MAC_STS_TXQ_BUSY |
MAC_STS_RXQ_BUSY |
MAC_STS_TXMAC_BUSY |
MAC_STS_RXMAC_BUSY;
MAC_STS_TXQ_BUSY | MAC_STS_RXQ_BUSY | MAC_STS_TXMAC_BUSY | MAC_STS_RXMAC_BUSY;
pub const MDIO: u32 = 0x1414;
pub const MDIO_MODE_EXT: u32 = 1 << 30;
@@ -876,7 +870,7 @@ pub const SRAM_RXF_HEAD_ADDR_SHIFT: u32 = 0;
pub const SRAM5: u32 = 0x1524;
pub const SRAM_RXF_LEN_MASK: u32 = 0xFFF;
pub const SRAM_RXF_LEN_SHIFT: u32 = 0;
pub const SRAM_RXF_LEN_8K: u32 = (8*1024);
pub const SRAM_RXF_LEN_8K: u32 = (8 * 1024);
pub const SRAM6: u32 = 0x1528;
pub const SRAM_TXF_TAIL_ADDR_MASK: u32 = 0xFFF;
@@ -955,7 +949,7 @@ pub const TXQ1_ERRLGPKT_DROP_EN: u32 = 1 << 11;
/* bit[9:0]:: u32 = 8bytes unit */
pub const TXQ1_JUMBO_TSOTHR_MASK: u32 = 0x7FF;
pub const TXQ1_JUMBO_TSOTHR_SHIFT: u32 = 0;
pub const TXQ1_JUMBO_TSO_TH: u32 = (7*1024);
pub const TXQ1_JUMBO_TSO_TH: u32 = (7 * 1024);
/* L1 entrance control */
pub const TXQ2: u32 = 0x1598;
@@ -990,11 +984,10 @@ pub const RXQ0_RSS_HSTYP_IPV6_TCP_EN: u32 = 1 << 5;
pub const RXQ0_RSS_HSTYP_IPV6_EN: u32 = 1 << 4;
pub const RXQ0_RSS_HSTYP_IPV4_TCP_EN: u32 = 1 << 3;
pub const RXQ0_RSS_HSTYP_IPV4_EN: u32 = 1 << 2;
pub const RXQ0_RSS_HSTYP_ALL: u32 =
RXQ0_RSS_HSTYP_IPV6_TCP_EN |
RXQ0_RSS_HSTYP_IPV4_TCP_EN |
RXQ0_RSS_HSTYP_IPV6_EN |
RXQ0_RSS_HSTYP_IPV4_EN;
pub const RXQ0_RSS_HSTYP_ALL: u32 = RXQ0_RSS_HSTYP_IPV6_TCP_EN
| RXQ0_RSS_HSTYP_IPV4_TCP_EN
| RXQ0_RSS_HSTYP_IPV6_EN
| RXQ0_RSS_HSTYP_IPV4_EN;
pub const RXQ0_ASPM_THRESH_MASK: u32 = 0x3;
pub const RXQ0_ASPM_THRESH_SHIFT: u32 = 0;
pub const RXQ0_ASPM_THRESH_NO: u32 = 0;
@@ -1223,7 +1216,6 @@ pub const INT_DEASST_TIMER: u32 = 0x1614;
pub const PATTERN_MASK: u32 = 0x1620;
pub const PATTERN_MASK_LEN: u32 = 128;
pub const FLT1_SRC_IP0: u32 = 0x1A00;
pub const FLT1_SRC_IP1: u32 = 0x1A04;
pub const FLT1_SRC_IP2: u32 = 0x1A08;
@@ -1392,12 +1384,7 @@ pub const CLK_GATE_TXQ: u32 = 1 << 2;
pub const CLK_GATE_DMAR: u32 = 1 << 1;
pub const CLK_GATE_DMAW: u32 = 1 << 0;
pub const CLK_GATE_ALL_A0: u32 =
CLK_GATE_RXMAC |
CLK_GATE_TXMAC |
CLK_GATE_RXQ |
CLK_GATE_TXQ |
CLK_GATE_DMAR |
CLK_GATE_DMAW;
CLK_GATE_RXMAC | CLK_GATE_TXMAC | CLK_GATE_RXQ | CLK_GATE_TXQ | CLK_GATE_DMAR | CLK_GATE_DMAW;
pub const CLK_GATE_ALL_B0: u32 = CLK_GATE_ALL_A0;
/* PORST affect */
@@ -1834,7 +1821,6 @@ pub const CR_DMA_CTRL_WEARLY_EN: u32 = 1 << 8;
pub const CR_DMA_CTRL_RXTH_MASK: u32 = 0xF;
pub const CR_DMA_CTRL_WTH_MASK: u32 = 0xF;
pub const EFUSE_BIST: u32 = 0x1934;
pub const EFUSE_BIST_COL_MASK: u32 = 0x3F;
pub const EFUSE_BIST_COL_SHIFT: u32 = 24;
@@ -1988,7 +1974,6 @@ pub const IO_MDIO: u32 = 0x38;
/* same as reg140C */
pub const IO_PHY_CTRL: u32 = 0x3C;
/********************* PHY regs definition ***************************/
/* Autoneg Advertisement Register */
@@ -2043,7 +2028,6 @@ pub const CDTC_EN: u16 = 1;
pub const CDTC_PAIR_MASK: u16 = 0x3;
pub const CDTC_PAIR_SHIFT: u16 = 8;
/* Cable-Detect-Test Status Register */
pub const MII_CDTS: u16 = 0x1C;
pub const CDTS_STATUS_MASK: u16 = 0x3;
@@ -2080,7 +2064,6 @@ pub const ANACTRL_MANUSWON_BW3_4M: u16 = 0x0002;
pub const ANACTRL_RESTART_CAL: u16 = 0x0001;
pub const ANACTRL_DEF: u16 = 0x02EF;
pub const MIIDBG_SYSMODCTRL: u16 = 0x04;
pub const SYSMODCTRL_IECHOADJ_PFMH_PHY: u16 = 0x8000;
pub const SYSMODCTRL_IECHOADJ_BIASGEN: u16 = 0x4000;
@@ -2100,7 +2083,6 @@ pub const SYSMODCTRL_IECHOADJ_VDLANSW: u16 = 0x0001;
/* en half bias */
pub const SYSMODCTRL_IECHOADJ_DEF: u16 = 0xBB8B;
pub const MIIDBG_SRDSYSMOD: u16 = 0x05;
pub const SRDSYSMOD_LCKDET_EN: u16 = 0x2000;
pub const SRDSYSMOD_PLL_EN: u16 = 0x0800;
@@ -2114,7 +2096,6 @@ pub const SRDSYSMOD_CDR_ADC_VLTG: u16 = 0x0002;
pub const SRDSYSMOD_CDR_DAC_1MA: u16 = 0x0001;
pub const SRDSYSMOD_DEF: u16 = 0x2C46;
pub const MIIDBG_HIBNEG: u16 = 0x0B;
pub const HIBNEG_PSHIB_EN: u16 = 0x8000;
pub const HIBNEG_WAKE_BOTH: u16 = 0x4000;
@@ -2204,7 +2185,6 @@ pub const MIIDBG_GREENCFG2: u16 = 0x3D;
pub const GREENCFG2_BP_GREEN: u16 = 0x8000;
pub const GREENCFG2_GATE_DFSE_EN: u16 = 0x0080;
/***************************** extension **************************************/
/******* dev 3 *********/
@@ -2292,4 +2272,4 @@ pub const MIIEXT_NLP56_DEF: u16 = 0x1010;
pub const MIIEXT_NLP78: u16 = 0x8027;
/* for: u16 = 160m */
pub const MIIEXT_NLP78_160M_DEF: u16 = 0x8D05;
pub const MIIEXT_NLP78_120M_DEF : u16 = 0x8A05;
pub const MIIEXT_NLP78_120M_DEF: u16 = 0x8A05;
+49 -14
View File
@@ -6,16 +6,16 @@
extern crate event;
extern crate syscall;
use std::{env, iter};
use std::fs::File;
use std::io::{Read, Write};
use std::os::fd::AsRawFd;
use std::os::unix::io::{FromRawFd, RawFd};
use std::{env, iter};
use event::{user_data, EventQueue};
use libredox::flag;
use syscall::{Packet, SchemeMut};
use syscall::error::EWOULDBLOCK;
use syscall::{Packet, SchemeMut};
pub mod device;
@@ -35,16 +35,31 @@ fn main() {
// Daemonize
redox_daemon::Daemon::new(move |daemon| {
let socket_fd = libredox::call::open(":network", flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK, 0).expect("alxd: failed to create network scheme");
let socket_fd = libredox::call::open(
":network",
flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK,
0,
)
.expect("alxd: failed to create network scheme");
let mut socket = unsafe { File::from_raw_fd(socket_fd as RawFd) };
daemon.ready().expect("alxd: failed to signal readiness");
let mut irq_file = File::open(format!("/scheme/irq/{}", irq)).expect("alxd: failed to open IRQ file");
let mut irq_file =
File::open(format!("/scheme/irq/{}", irq)).expect("alxd: failed to open IRQ file");
let address = unsafe { common::physmap(bar, 128*1024, common::Prot::RW, common::MemoryType::Uncacheable).expect("alxd: failed to map address") as usize };
let address = unsafe {
common::physmap(
bar,
128 * 1024,
common::Prot::RW,
common::MemoryType::Uncacheable,
)
.expect("alxd: failed to map address") as usize
};
{
let mut device = unsafe { device::Alx::new(address).expect("alxd: failed to allocate device") };
let mut device =
unsafe { device::Alx::new(address).expect("alxd: failed to allocate device") };
user_data! {
enum Source {
@@ -53,15 +68,26 @@ fn main() {
}
}
let event_queue = EventQueue::<Source>::new().expect("alxd: failed to create event queue");
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ).unwrap();
event_queue.subscribe(socket_fd, Source::Scheme, event::EventFlags::READ).unwrap();
let event_queue =
EventQueue::<Source>::new().expect("alxd: failed to create event queue");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(socket_fd, Source::Scheme, event::EventFlags::READ)
.unwrap();
libredox::call::setrens(0, 0).expect("alxd: failed to enter null namespace");
let mut todo = Vec::<Packet>::new();
for event in iter::once(Source::Scheme).chain(event_queue.map(|e| e.expect("alxd: failed to get next event").user_data)) {
for event in iter::once(Source::Scheme)
.chain(event_queue.map(|e| e.expect("alxd: failed to get next event").user_data))
{
match event {
Source::Irq => {
let mut irq = [0; 8];
@@ -77,7 +103,9 @@ fn main() {
todo[i].a = a;
i += 1;
} else {
socket.write(&mut todo[i]).expect("alxd: failed to write to socket");
socket
.write(&mut todo[i])
.expect("alxd: failed to write to socket");
todo.remove(i);
}
}
@@ -93,7 +121,11 @@ fn main() {
Source::Scheme => {
loop {
let mut packet = Packet::default();
if socket.read(&mut packet).expect("alxd: failed read from socket") == 0 {
if socket
.read(&mut packet)
.expect("alxd: failed read from socket")
== 0
{
break;
}
@@ -103,7 +135,9 @@ fn main() {
packet.a = a;
todo.push(packet);
} else {
socket.write(&mut packet).expect("alxd: failed to write to socket");
socket
.write(&mut packet)
.expect("alxd: failed to write to socket");
}
}
@@ -119,5 +153,6 @@ fn main() {
}
}
std::process::exit(0);
}).expect("alxd: failed to daemonize");
})
.expect("alxd: failed to daemonize");
}
+12 -2
View File
@@ -49,9 +49,19 @@ fn main() {
let mut event_queue =
EventQueue::<Source>::new().expect("e1000d: failed to create event queue");
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ)
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.expect("e1000d: failed to subscribe to IRQ fd");
event_queue.subscribe(scheme.event_handle() as usize, Source::Scheme, event::EventFlags::READ)
event_queue
.subscribe(
scheme.event_handle() as usize,
Source::Scheme,
event::EventFlags::READ,
)
.expect("e1000d: failed to subscribe to scheme fd");
libredox::call::setrens(0, 0).expect("e1000d: failed to enter null namespace");
+21 -12
View File
@@ -55,8 +55,8 @@ impl NetworkAdapter for Intel8259x {
let i = cmp::min(buf.len(), data.len());
buf[..i].copy_from_slice(&data[..i]);
desc.read.pkt_addr = self.receive_buffer[self.receive_index].physical() as u64;
desc.read.hdr_addr = 0;
desc.read.pkt_addr = self.receive_buffer[self.receive_index].physical() as u64;
desc.read.hdr_addr = 0;
self.write_reg(IXGBE_RDT(0), self.receive_index as u32);
self.receive_index = wrap_ring(self.receive_index, self.receive_ring.len());
@@ -103,14 +103,14 @@ impl NetworkAdapter for Intel8259x {
let i = cmp::min(buf.len(), data.len());
data[..i].copy_from_slice(&buf[..i]);
desc.read.cmd_type_len = IXGBE_ADVTXD_DCMD_EOP
| IXGBE_ADVTXD_DCMD_RS
| IXGBE_ADVTXD_DCMD_IFCS
| IXGBE_ADVTXD_DCMD_DEXT
| IXGBE_ADVTXD_DTYP_DATA
| buf.len() as u32;
desc.read.cmd_type_len = IXGBE_ADVTXD_DCMD_EOP
| IXGBE_ADVTXD_DCMD_RS
| IXGBE_ADVTXD_DCMD_IFCS
| IXGBE_ADVTXD_DCMD_DEXT
| IXGBE_ADVTXD_DTYP_DATA
| buf.len() as u32;
desc.read.olinfo_status = (buf.len() as u32) << IXGBE_ADVTXD_PAYLEN_SHIFT;
desc.read.olinfo_status = (buf.len() as u32) << IXGBE_ADVTXD_PAYLEN_SHIFT;
self.transmit_index = wrap_ring(self.transmit_index, self.transmit_ring.len());
self.transmit_ring_free -= 1;
@@ -290,7 +290,10 @@ impl Intel8259x {
self.wait_write_reg(IXGBE_EEC, IXGBE_EEC_ARD);
// section 4.6.3 - wait for dma initialization done
self.wait_write_reg(IXGBE_RDRXCTL, IXGBE_RDRXCTL_DMAIDONE | IXGBE_RDRXCTL_RESERVED_BITS);
self.wait_write_reg(
IXGBE_RDRXCTL,
IXGBE_RDRXCTL_DMAIDONE | IXGBE_RDRXCTL_RESERVED_BITS,
);
// section 4.6.4 - initialize link (auto negotiation)
self.init_link();
@@ -361,7 +364,10 @@ impl Intel8259x {
self.write_reg(IXGBE_RDBAL(i), self.receive_ring.physical() as u32);
self.write_reg(IXGBE_RDBAH(i), ((self.receive_ring.physical() as u64) >> 32) as u32);
self.write_reg(
IXGBE_RDBAH(i),
((self.receive_ring.physical() as u64) >> 32) as u32,
);
self.write_reg(
IXGBE_RDLEN(i),
(self.receive_ring.len() * mem::size_of::<ixgbe_adv_rx_desc>()) as u32,
@@ -407,7 +413,10 @@ impl Intel8259x {
// section 7.1.9 - setup descriptor ring
self.write_reg(IXGBE_TDBAL(i), self.transmit_ring.physical() as u32);
self.write_reg(IXGBE_TDBAH(i), ((self.transmit_ring.physical() as u64) >> 32) as u32);
self.write_reg(
IXGBE_TDBAH(i),
((self.transmit_ring.physical() as u64) >> 32) as u32,
);
self.write_reg(
IXGBE_TDLEN(i),
(self.transmit_ring.len() * mem::size_of::<ixgbe_adv_tx_desc>()) as u32,
+16 -3
View File
@@ -47,9 +47,22 @@ fn main() {
}
}
let mut event_queue = EventQueue::<Source>::new().expect("ixgbed: Could not create event queue.");
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ).unwrap();
event_queue.subscribe(scheme.event_handle() as usize, Source::Scheme, event::EventFlags::READ).unwrap();
let mut event_queue =
EventQueue::<Source>::new().expect("ixgbed: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
scheme.event_handle() as usize,
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
libredox::call::setrens(0, 0).expect("ixgbed: failed to enter null namespace");
+27 -26
View File
@@ -1,11 +1,11 @@
use std::mem;
use std::convert::TryInto;
use std::mem;
use driver_network::NetworkAdapter;
use syscall::error::{Error, EIO, EMSGSIZE, Result};
use syscall::error::{Error, Result, EIO, EMSGSIZE};
use common::io::{Mmio, Io, ReadOnly};
use common::dma::Dma;
use common::io::{Io, Mmio, ReadOnly};
const RX_BUFFER_SIZE: usize = 64 * 1024;
@@ -135,16 +135,11 @@ impl NetworkAdapter for Rtl8139 {
self.next_read()
}
fn read_packet(&mut self, buf: &mut [u8]) -> Result<Option<usize>> {
if !self.regs.cr.readf(CR_BUFE) {
let rxsts =
(self.rx(0) as u16) |
(self.rx(1) as u16) << 8;
let rxsts = (self.rx(0) as u16) | (self.rx(1) as u16) << 8;
let size_with_crc =
(self.rx(2) as usize) |
(self.rx(3) as usize) << 8;
let size_with_crc = (self.rx(2) as usize) | (self.rx(3) as usize) << 8;
let res = if (rxsts & RXSTS_ROK) == RXSTS_ROK {
let mut i = 0;
@@ -159,7 +154,8 @@ impl NetworkAdapter for Rtl8139 {
Err(Error::new(EIO))
};
self.receive_i = (self.receive_i + 4 + size_with_crc).next_multiple_of(4) % RX_BUFFER_SIZE;
self.receive_i =
(self.receive_i + 4 + size_with_crc).next_multiple_of(4) % RX_BUFFER_SIZE;
let capr = self.receive_i.wrapping_sub(16) as u16;
self.regs.capr.write(capr);
@@ -243,13 +239,9 @@ impl Rtl8139 {
pub fn next_read(&self) -> usize {
if !self.regs.cr.readf(CR_BUFE) {
let rxsts =
(self.rx(0) as u16) |
(self.rx(1) as u16) << 8;
let rxsts = (self.rx(0) as u16) | (self.rx(1) as u16) << 8;
let size_with_crc =
(self.rx(2) as usize) |
(self.rx(3) as usize) << 8;
let size_with_crc = (self.rx(2) as usize) | (self.rx(3) as usize) << 8;
if (rxsts & RXSTS_ROK) == RXSTS_ROK {
size_with_crc.saturating_sub(4)
@@ -264,13 +256,18 @@ impl Rtl8139 {
pub unsafe fn init(&mut self) {
let mac_low = self.regs.mac[0].read();
let mac_high = self.regs.mac[1].read();
let mac = [mac_low as u8,
(mac_low >> 8) as u8,
(mac_low >> 16) as u8,
(mac_low >> 24) as u8,
mac_high as u8,
(mac_high >> 8) as u8];
println!(" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
let mac = [
mac_low as u8,
(mac_low >> 8) as u8,
(mac_low >> 16) as u8,
(mac_low >> 24) as u8,
mac_high as u8,
(mac_high >> 8) as u8,
];
println!(
" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
);
self.mac_address = mac;
// Reset - this will disable tx and rx, reinitialize FIFOs, and set the system buffer pointer to the initial value
@@ -282,13 +279,17 @@ impl Rtl8139 {
// Set up rx buffer
println!(" - Receive buffer");
self.regs.rbstart.write(self.receive_buffer.physical() as u32);
self.regs
.rbstart
.write(self.receive_buffer.physical() as u32);
println!(" - Interrupt mask");
self.regs.imr.write(IMR_TOK | IMR_ROK);
println!(" - Receive configuration");
self.regs.rcr.write(RCR_RBLEN_64K | RCR_AB | RCR_AM | RCR_APM | RCR_AAP);
self.regs
.rcr
.write(RCR_RBLEN_64K | RCR_AB | RCR_AM | RCR_APM | RCR_AAP);
println!(" - Enable RX and TX");
self.regs.cr.writef(CR_RE | CR_TE, true);
+55 -22
View File
@@ -53,14 +53,19 @@ impl MappedMsixRegs {
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
let pci_config = pcid_handle.config();
let all_pci_features = pcid_handle.fetch_all_features().expect("rtl8139d: failed to fetch pci features");
let all_pci_features = pcid_handle
.fetch_all_features()
.expect("rtl8139d: failed to fetch pci features");
log::info!("PCI FEATURES: {:?}", all_pci_features);
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
if has_msi && !has_msix {
let capability = match pcid_handle.feature_info(PciFeature::Msi).expect("rtl8139d: failed to retrieve the MSI capability structure from pcid") {
let capability = match pcid_handle
.feature_info(PciFeature::Msi)
.expect("rtl8139d: failed to retrieve the MSI capability structure from pcid")
{
PciFeatureInfo::Msi(s) => s,
PciFeatureInfo::MsiX(_) => panic!(),
};
@@ -70,21 +75,29 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
// pcid_interface, so that this can be shared between nvmed, xhcid, ixgebd, etc..
let destination_id = read_bsp_apic_id().expect("rtl8139d: failed to read BSP apic id");
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
let (msg_addr_and_data, interrupt_handle) =
allocate_single_interrupt_vector_for_msi(destination_id);
let set_feature_info = MsiSetFeatureInfo {
multi_message_enable: Some(0),
message_address_and_data: Some(msg_addr_and_data),
mask_bits: None,
};
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info)).expect("rtl8139d: failed to set feature info");
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(set_feature_info))
.expect("rtl8139d: failed to set feature info");
pcid_handle.enable_feature(PciFeature::Msi).expect("rtl8139d: failed to enable MSI");
pcid_handle
.enable_feature(PciFeature::Msi)
.expect("rtl8139d: failed to enable MSI");
log::info!("Enabled MSI");
interrupt_handle
} else if has_msix {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8139d: failed to retrieve the MSI-X capability structure from pcid") {
let msix_info = match pcid_handle
.feature_info(PciFeature::MsiX)
.expect("rtl8139d: failed to retrieve the MSI-X capability structure from pcid")
{
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
@@ -94,7 +107,8 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
.ptr
.as_ptr() as usize;
let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let virt_table_base =
(bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let mut info = MappedMsixRegs {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
@@ -119,7 +133,9 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
interrupt_handle
};
pcid_handle.enable_feature(PciFeature::MsiX).expect("rtl8139d: failed to enable MSI-X");
pcid_handle
.enable_feature(PciFeature::MsiX)
.expect("rtl8139d: failed to enable MSI-X");
log::info!("Enabled MSI-X");
method
@@ -148,14 +164,12 @@ fn find_bar(pci_config: &SubdriverArguments) -> Option<(usize, usize)> {
// RTL8139 uses BAR2, RTL8169 uses BAR1, search in that order
for &barnum in &[2, 1] {
match pci_config.func.bars[barnum] {
pcid_interface::PciBar::Memory32 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
pcid_interface::PciBar::Memory64 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
pcid_interface::PciBar::Memory32 { addr, size } => {
return Some((addr.try_into().unwrap(), size.try_into().unwrap()))
}
pcid_interface::PciBar::Memory64 { addr, size } => {
return Some((addr.try_into().unwrap(), size.try_into().unwrap()))
}
other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other),
}
}
@@ -171,7 +185,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::LevelFilter::Info,
);
let mut pcid_handle = PciFunctionHandle::connect_default().expect("rtl8139d: failed to setup channel to pcid");
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("rtl8139d: failed to setup channel to pcid");
let pci_config = pcid_handle.config();
@@ -182,8 +197,13 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::info!(" + RTL8139 {}", pci_config.func.display());
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("rtl8139d: failed to map address") as usize
common::physmap(
bar_ptr,
bar_size,
common::Prot::RW,
common::MemoryType::Uncacheable,
)
.expect("rtl8139d: failed to map address") as usize
};
//TODO: MSI-X
@@ -201,9 +221,22 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
}
let mut event_queue = EventQueue::<Source>::new().expect("rtl8139d: Could not create event queue.");
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ).unwrap();
event_queue.subscribe(scheme.event_handle() as usize, Source::Scheme, event::EventFlags::READ).unwrap();
let mut event_queue =
EventQueue::<Source>::new().expect("rtl8139d: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
scheme.event_handle() as usize,
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
libredox::call::setrens(0, 0).expect("rtl8139d: failed to enter null namespace");
+32 -18
View File
@@ -1,9 +1,9 @@
use std::mem;
use std::convert::TryInto;
use std::mem;
use common::io::{Io, Mmio, ReadOnly};
use driver_network::NetworkAdapter;
use syscall::error::{Error, Result, EMSGSIZE};
use common::io::{Mmio, Io, ReadOnly};
use common::dma::Dma;
@@ -89,14 +89,13 @@ impl NetworkAdapter for Rtl8168 {
self.next_read()
}
fn read_packet(&mut self, buf: &mut [u8]) -> Result<Option<usize>> {
if self.receive_i >= self.receive_ring.len() {
self.receive_i = 0;
}
let rd = &mut self.receive_ring[self.receive_i];
if ! rd.ctrl.readf(OWN) {
if !rd.ctrl.readf(OWN) {
let rd_len = rd.ctrl.read() & 0x3FFF;
let data = &self.receive_buffer[self.receive_i];
@@ -125,7 +124,7 @@ impl NetworkAdapter for Rtl8168 {
}
let td = &mut self.transmit_ring[self.transmit_i];
if ! td.ctrl.readf(OWN) {
if !td.ctrl.readf(OWN) {
let data = &mut self.transmit_buffer[self.transmit_i];
if buf.len() > data.len() {
@@ -214,7 +213,7 @@ impl Rtl8168 {
}
let rd = &self.receive_ring[receive_i];
if ! rd.ctrl.readf(OWN) {
if !rd.ctrl.readf(OWN) {
(rd.ctrl.read() & 0x3FFF) as usize
} else {
0
@@ -224,13 +223,18 @@ impl Rtl8168 {
pub unsafe fn init(&mut self) {
let mac_low = self.regs.mac[0].read();
let mac_high = self.regs.mac[1].read();
let mac = [mac_low as u8,
(mac_low >> 8) as u8,
(mac_low >> 16) as u8,
(mac_low >> 24) as u8,
mac_high as u8,
(mac_high >> 8) as u8];
println!(" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
let mac = [
mac_low as u8,
(mac_low >> 8) as u8,
(mac_low >> 16) as u8,
(mac_low >> 24) as u8,
mac_high as u8,
(mac_high >> 8) as u8,
];
println!(
" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
);
self.mac_address = mac;
// Reset - this will disable tx and rx, reinitialize FIFOs, and set the system buffer pointer to the initial value
@@ -256,8 +260,12 @@ impl Rtl8168 {
// Set up normal priority tx buffers
println!(" - Transmit buffers (normal priority)");
for i in 0..self.transmit_ring.len() {
self.transmit_ring[i].buffer_low.write(self.transmit_buffer[i].physical() as u32);
self.transmit_ring[i].buffer_high.write((self.transmit_buffer[i].physical() as u64 >> 32) as u32);
self.transmit_ring[i]
.buffer_low
.write(self.transmit_buffer[i].physical() as u32);
self.transmit_ring[i]
.buffer_high
.write((self.transmit_buffer[i].physical() as u64 >> 32) as u32);
}
if let Some(td) = self.transmit_ring.last_mut() {
td.ctrl.writef(EOR, true);
@@ -266,8 +274,12 @@ impl Rtl8168 {
// Set up high priority tx buffers
println!(" - Transmit buffers (high priority)");
for i in 0..self.transmit_ring_h.len() {
self.transmit_ring_h[i].buffer_low.write(self.transmit_buffer_h[i].physical() as u32);
self.transmit_ring_h[i].buffer_high.write((self.transmit_buffer_h[i].physical() as u64 >> 32) as u32);
self.transmit_ring_h[i]
.buffer_low
.write(self.transmit_buffer_h[i].physical() as u32);
self.transmit_ring_h[i]
.buffer_high
.write((self.transmit_buffer_h[i].physical() as u64 >> 32) as u32);
}
if let Some(td) = self.transmit_ring_h.last_mut() {
td.ctrl.writef(EOR, true);
@@ -306,7 +318,9 @@ impl Rtl8168 {
self.regs.isr.write(isr);
// Interrupt on tx error (bit 3), tx ok (bit 2), rx error(bit 1), and rx ok (bit 0)
self.regs.imr.write(1 << 15 | 1 << 14 | 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1);
self.regs.imr.write(
1 << 15 | 1 << 14 | 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1,
);
// Set TX config
self.regs.tcr.write(0b11 << 24 | 0b111 << 8);
+59 -23
View File
@@ -8,11 +8,14 @@ use std::rc::Rc;
use driver_network::NetworkScheme;
use event::{user_data, EventQueue};
use pcid_interface::{MsiSetFeatureInfo, PciFunctionHandle, PciFeature, PciFeatureInfo, SetFeatureInfo, SubdriverArguments};
#[cfg(target_arch = "x86_64")]
use pcid_interface::irq_helpers::allocate_single_interrupt_vector_for_msi;
use pcid_interface::irq_helpers::read_bsp_apic_id;
use pcid_interface::msi::{MsixInfo, MsixTableEntry};
use pcid_interface::{
MsiSetFeatureInfo, PciFeature, PciFeatureInfo, PciFunctionHandle, SetFeatureInfo,
SubdriverArguments,
};
use syscall::EventFlags;
pub mod device;
@@ -48,14 +51,19 @@ impl MappedMsixRegs {
fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
let pci_config = pcid_handle.config();
let all_pci_features = pcid_handle.fetch_all_features().expect("rtl8168d: failed to fetch pci features");
let all_pci_features = pcid_handle
.fetch_all_features()
.expect("rtl8168d: failed to fetch pci features");
log::info!("PCI FEATURES: {:?}", all_pci_features);
let has_msi = all_pci_features.iter().any(|feature| feature.is_msi());
let has_msix = all_pci_features.iter().any(|feature| feature.is_msix());
if has_msi && !has_msix {
let capability = match pcid_handle.feature_info(PciFeature::Msi).expect("rtl8168d: failed to retrieve the MSI capability structure from pcid") {
let capability = match pcid_handle
.feature_info(PciFeature::Msi)
.expect("rtl8168d: failed to retrieve the MSI capability structure from pcid")
{
PciFeatureInfo::Msi(s) => s,
PciFeatureInfo::MsiX(_) => panic!(),
};
@@ -65,21 +73,29 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
// pcid_interface, so that this can be shared between nvmed, xhcid, ixgebd, etc..
let destination_id = read_bsp_apic_id().expect("rtl8168d: failed to read BSP apic id");
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
let (msg_addr_and_data, interrupt_handle) =
allocate_single_interrupt_vector_for_msi(destination_id);
let set_feature_info = MsiSetFeatureInfo {
multi_message_enable: Some(0),
message_address_and_data: Some(msg_addr_and_data),
mask_bits: None,
};
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info)).expect("rtl8168d: failed to set feature info");
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(set_feature_info))
.expect("rtl8168d: failed to set feature info");
pcid_handle.enable_feature(PciFeature::Msi).expect("rtl8168d: failed to enable MSI");
pcid_handle
.enable_feature(PciFeature::Msi)
.expect("rtl8168d: failed to enable MSI");
log::info!("Enabled MSI");
interrupt_handle
} else if has_msix {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8168d: failed to retrieve the MSI-X capability structure from pcid") {
let msix_info = match pcid_handle
.feature_info(PciFeature::MsiX)
.expect("rtl8168d: failed to retrieve the MSI-X capability structure from pcid")
{
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
@@ -89,7 +105,8 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
.ptr
.as_ptr() as usize;
let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let virt_table_base =
(bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let mut info = MappedMsixRegs {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
@@ -114,7 +131,9 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> File {
interrupt_handle
};
pcid_handle.enable_feature(PciFeature::MsiX).expect("rtl8168d: failed to enable MSI-X");
pcid_handle
.enable_feature(PciFeature::MsiX)
.expect("rtl8168d: failed to enable MSI-X");
log::info!("Enabled MSI-X");
method
@@ -143,14 +162,12 @@ fn find_bar(pci_config: &SubdriverArguments) -> Option<(usize, usize)> {
// RTL8168 uses BAR2, RTL8169 uses BAR1, search in that order
for &barnum in &[2, 1] {
match pci_config.func.bars[barnum] {
pcid_interface::PciBar::Memory32 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
pcid_interface::PciBar::Memory64 { addr, size } => return Some((
addr.try_into().unwrap(),
size.try_into().unwrap()
)),
pcid_interface::PciBar::Memory32 { addr, size } => {
return Some((addr.try_into().unwrap(), size.try_into().unwrap()))
}
pcid_interface::PciBar::Memory64 { addr, size } => {
return Some((addr.try_into().unwrap(), size.try_into().unwrap()))
}
other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other),
}
}
@@ -166,7 +183,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::LevelFilter::Info,
);
let mut pcid_handle = PciFunctionHandle::connect_default().expect("rtl8168d: failed to setup channel to pcid");
let mut pcid_handle =
PciFunctionHandle::connect_default().expect("rtl8168d: failed to setup channel to pcid");
let pci_config = pcid_handle.config();
@@ -177,8 +195,13 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::info!(" + RTL8168 {}", pci_config.func.display());
let address = unsafe {
common::physmap(bar_ptr, bar_size, common::Prot::RW, common::MemoryType::Uncacheable)
.expect("rtl8168d: failed to map address") as usize
common::physmap(
bar_ptr,
bar_size,
common::Prot::RW,
common::MemoryType::Uncacheable,
)
.expect("rtl8168d: failed to map address") as usize
};
//TODO: MSI-X
@@ -196,9 +219,22 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
}
let mut event_queue = EventQueue::<Source>::new().expect("rtl8168d: Could not create event queue.");
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ).unwrap();
event_queue.subscribe(scheme.event_handle() as usize, Source::Scheme, event::EventFlags::READ).unwrap();
let mut event_queue =
EventQueue::<Source>::new().expect("rtl8168d: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
event_queue
.subscribe(
scheme.event_handle() as usize,
Source::Scheme,
event::EventFlags::READ,
)
.unwrap();
libredox::call::setrens(0, 0).expect("rtl8168d: failed to enter null namespace");
+115 -100
View File
@@ -1,19 +1,25 @@
use log::{debug, error, info, trace};
use common::io::{Io, Pio, ReadOnly, WriteOnly};
use log::{debug, error, info, trace};
use std::fmt;
#[cfg(target_arch = "aarch64")]
#[inline(always)]
pub(crate) unsafe fn pause() { std::arch::aarch64::__yield(); }
pub(crate) unsafe fn pause() {
std::arch::aarch64::__yield();
}
#[cfg(target_arch = "x86")]
#[inline(always)]
pub(crate) unsafe fn pause() { std::arch::x86::_mm_pause(); }
pub(crate) unsafe fn pause() {
std::arch::x86::_mm_pause();
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub(crate) unsafe fn pause() { std::arch::x86_64::_mm_pause(); }
pub(crate) unsafe fn pause() {
std::arch::x86_64::_mm_pause();
}
#[derive(Debug)]
pub enum Error {
@@ -67,7 +73,7 @@ enum Command {
Diagnostic = 0xAC,
DisableFirst = 0xAD,
EnableFirst = 0xAE,
WriteSecond = 0xD4
WriteSecond = 0xD4,
}
#[derive(Clone, Copy, Debug)]
@@ -77,13 +83,13 @@ enum KeyboardCommand {
EnableReporting = 0xF4,
SetDefaultsDisable = 0xF5,
SetDefaults = 0xF6,
Reset = 0xFF
Reset = 0xFF,
}
#[derive(Clone, Copy, Debug)]
#[repr(u8)]
enum KeyboardCommandData {
ScancodeSet = 0xF0
ScancodeSet = 0xF0,
}
#[derive(Clone, Copy, Debug)]
@@ -97,7 +103,7 @@ enum MouseCommand {
EnableReporting = 0xF4,
SetDefaultsDisable = 0xF5,
SetDefaults = 0xF6,
Reset = 0xFF
Reset = 0xFF,
}
#[derive(Clone, Copy, Debug)]
@@ -132,7 +138,9 @@ impl Ps2 {
if self.status().contains(StatusFlags::OUTPUT_FULL) {
return Ok(());
}
unsafe { pause(); }
unsafe {
pause();
}
timeout -= 1;
}
Err(Error::ReadTimeout)
@@ -141,10 +149,12 @@ impl Ps2 {
fn wait_write(&mut self) -> Result<(), Error> {
let mut timeout = 100_000;
while timeout > 0 {
if ! self.status().contains(StatusFlags::INPUT_FULL) {
if !self.status().contains(StatusFlags::INPUT_FULL) {
return Ok(());
}
unsafe { pause(); }
unsafe {
pause();
}
timeout -= 1;
}
Err(Error::WriteTimeout)
@@ -157,7 +167,9 @@ impl Ps2 {
let val = self.data.read();
trace!("ps2d: flush {}: {:X}", message, val);
}
unsafe { pause(); }
unsafe {
pause();
}
timeout -= 1;
}
}
@@ -179,7 +191,12 @@ impl Ps2 {
Ok(())
}
fn retry<F: Fn(&mut Self) -> Result<u8, Error>>(&mut self, name: fmt::Arguments, retries: usize, f: F) -> Result<u8, Error> {
fn retry<F: Fn(&mut Self) -> Result<u8, Error>>(
&mut self,
name: fmt::Arguments,
retries: usize,
f: F,
) -> Result<u8, Error> {
trace!("ps2d: {}", name);
let mut res = Err(Error::NoMoreTries);
for retry in 0..retries {
@@ -187,7 +204,7 @@ impl Ps2 {
match res {
Ok(ok) => {
return Ok(ok);
},
}
Err(ref err) => {
info!("ps2d: {}: retry {}/{}: {:?}", name, retry + 1, retries, err);
}
@@ -197,26 +214,19 @@ impl Ps2 {
}
fn config(&mut self) -> Result<ConfigFlags, Error> {
self.retry(
format_args!("read config"),
4,
|x| {
x.command(Command::ReadConfig)?;
x.read()
}
).map(ConfigFlags::from_bits_truncate)
self.retry(format_args!("read config"), 4, |x| {
x.command(Command::ReadConfig)?;
x.read()
})
.map(ConfigFlags::from_bits_truncate)
}
fn set_config(&mut self, config: ConfigFlags) -> Result<(), Error> {
self.retry(
format_args!("write config"),
4,
|x| {
x.command(Command::WriteConfig)?;
x.write(config.bits())?;
Ok(0)
}
)?;
self.retry(format_args!("write config"), 4, |x| {
x.command(Command::WriteConfig)?;
x.write(config.bits())?;
Ok(0)
})?;
Ok(())
}
@@ -229,14 +239,16 @@ impl Ps2 {
}
fn keyboard_command(&mut self, command: KeyboardCommand) -> Result<u8, Error> {
self.retry(
format_args!("keyboard command {:?}", command),
4,
|x| x.keyboard_command_inner(command as u8)
)
self.retry(format_args!("keyboard command {:?}", command), 4, |x| {
x.keyboard_command_inner(command as u8)
})
}
fn keyboard_command_data(&mut self, command: KeyboardCommandData, data: u8) -> Result<u8, Error> {
fn keyboard_command_data(
&mut self,
command: KeyboardCommandData,
data: u8,
) -> Result<u8, Error> {
self.retry(
format_args!("keyboard command {:?} {:#x}", command, data),
4,
@@ -248,7 +260,7 @@ impl Ps2 {
}
x.write(data);
x.read()
}
},
)
}
@@ -262,11 +274,9 @@ impl Ps2 {
}
fn mouse_command(&mut self, command: MouseCommand) -> Result<u8, Error> {
self.retry(
format_args!("mouse command {:?}", command),
4,
|x| x.mouse_command_inner(command as u8)
)
self.retry(format_args!("mouse command {:?}", command), 4, |x| {
x.mouse_command_inner(command as u8)
})
}
fn mouse_command_data(&mut self, command: MouseCommandData, data: u8) -> Result<u8, Error> {
@@ -282,7 +292,7 @@ impl Ps2 {
x.command(Command::WriteSecond)?;
x.write(data as u8)?;
x.read()
}
},
)
}
@@ -290,7 +300,7 @@ impl Ps2 {
let status = self.status();
if status.contains(StatusFlags::OUTPUT_FULL) {
let data = self.data.read();
Some((! status.contains(StatusFlags::SECOND_OUTPUT_FULL), data))
Some((!status.contains(StatusFlags::SECOND_OUTPUT_FULL), data))
} else {
None
}
@@ -323,32 +333,31 @@ impl Ps2 {
self.flush_read("keyboard reset");
}
self.retry(
format_args!("keyboard defaults"),
4,
|x| {
x.flush_read("keyboard before defaults");
self.retry(format_args!("keyboard defaults"), 4, |x| {
x.flush_read("keyboard before defaults");
// Set defaults and disable scanning
let b = x.keyboard_command(KeyboardCommand::SetDefaultsDisable)?;
if b != 0xFA {
error!("ps2d: keyboard failed to set defaults: {:02X}", b);
return Err(Error::CommandRetry);
}
// Clear remaining data
x.flush_read("keyboard after defaults");
Ok(b)
// Set defaults and disable scanning
let b = x.keyboard_command(KeyboardCommand::SetDefaultsDisable)?;
if b != 0xFA {
error!("ps2d: keyboard failed to set defaults: {:02X}", b);
return Err(Error::CommandRetry);
}
)?;
// Clear remaining data
x.flush_read("keyboard after defaults");
Ok(b)
})?;
{
// Set scancode set to 2
let scancode_set = 2;
b = self.keyboard_command_data(KeyboardCommandData::ScancodeSet, scancode_set)?;
if b != 0xFA {
error!("ps2d: keyboard failed to set scancode set {}: {:02X}", scancode_set, b);
error!(
"ps2d: keyboard failed to set scancode set {}: {:02X}",
scancode_set, b
);
}
// Clear remaining data
@@ -369,38 +378,34 @@ impl Ps2 {
self.flush_read("enable second");
}
self.retry(
format_args!("mouse reset"),
4,
|x| {
// Clear remaining data
x.flush_read("mouse before reset");
self.retry(format_args!("mouse reset"), 4, |x| {
// Clear remaining data
x.flush_read("mouse before reset");
// Reset mouse
let mut b = x.mouse_command(MouseCommand::Reset)?;
if b == 0xFA {
b = x.read()?;
if b != 0xAA {
error!("ps2d: mouse failed self test 1: {:02X}", b);
return Err(Error::CommandRetry);
}
b = x.read()?;
if b != 0x00 {
error!("ps2d: mouse failed self test 2: {:02X}", b);
return Err(Error::CommandRetry);
}
} else {
error!("ps2d: mouse failed to reset: {:02X}", b);
// Reset mouse
let mut b = x.mouse_command(MouseCommand::Reset)?;
if b == 0xFA {
b = x.read()?;
if b != 0xAA {
error!("ps2d: mouse failed self test 1: {:02X}", b);
return Err(Error::CommandRetry);
}
// Clear remaining data
x.flush_read("mouse after reset");
Ok(b)
b = x.read()?;
if b != 0x00 {
error!("ps2d: mouse failed self test 2: {:02X}", b);
return Err(Error::CommandRetry);
}
} else {
error!("ps2d: mouse failed to reset: {:02X}", b);
return Err(Error::CommandRetry);
}
)?;
// Clear remaining data
x.flush_read("mouse after reset");
Ok(b)
})?;
{
// Set defaults
@@ -417,8 +422,9 @@ impl Ps2 {
// Enable extra packet on mouse
//TODO: show error return values
if self.mouse_command_data(MouseCommandData::SetSampleRate, 200)? != 0xFA
|| self.mouse_command_data(MouseCommandData::SetSampleRate, 100)? != 0xFA
|| self.mouse_command_data(MouseCommandData::SetSampleRate, 80)? != 0xFA {
|| self.mouse_command_data(MouseCommandData::SetSampleRate, 100)? != 0xFA
|| self.mouse_command_data(MouseCommandData::SetSampleRate, 80)? != 0xFA
{
error!("ps2d: mouse failed to enable extra packet");
}
@@ -442,7 +448,10 @@ impl Ps2 {
let resolution = 3;
b = self.mouse_command_data(MouseCommandData::SetResolution, resolution)?;
if b != 0xFA {
error!("ps2d: mouse failed to set resolution to {}: {:02X}", resolution, b);
error!(
"ps2d: mouse failed to set resolution to {}: {:02X}",
resolution, b
);
}
// Clear remaining data
@@ -453,7 +462,7 @@ impl Ps2 {
// Set scaling to 1:1
b = self.mouse_command(MouseCommand::SetScaling1To1)?;
if b != 0xFA {
error!("ps2d: mouse failed to set scaling: {:02X}", b);
error!("ps2d: mouse failed to set scaling: {:02X}", b);
}
// Clear remaining data
@@ -465,7 +474,10 @@ impl Ps2 {
let sample_rate = 200;
b = self.mouse_command_data(MouseCommandData::SetSampleRate, sample_rate)?;
if b != 0xFA {
error!("ps2d: mouse failed to set sample rate to {}: {:02X}", sample_rate, b);
error!(
"ps2d: mouse failed to set sample rate to {}: {:02X}",
sample_rate, b
);
}
// Clear remaining data
@@ -475,13 +487,16 @@ impl Ps2 {
{
b = self.mouse_command(MouseCommand::StatusRequest)?;
if b != 0xFA {
error!("ps2d: mouse failed to request status: {:02X}", b);
error!("ps2d: mouse failed to request status: {:02X}", b);
} else {
let a = self.read()?;
let b = self.read()?;
let c = self.read()?;
debug!("ps2d: mouse status {:#x} resolution {:#x} sample rate {:#x}", a, b, c);
debug!(
"ps2d: mouse status {:#x} resolution {:#x} sample rate {:#x}",
a, b, c
);
}
}
@@ -506,9 +521,9 @@ impl Ps2 {
{
// Since the default config may have interrupts enabled, and the kernel may eat up
// our data in that case, we will write a config without reading the current one
config = ConfigFlags::POST_PASSED |
ConfigFlags::FIRST_DISABLED |
ConfigFlags::SECOND_DISABLED;
config = ConfigFlags::POST_PASSED
| ConfigFlags::FIRST_DISABLED
| ConfigFlags::SECOND_DISABLED;
trace!("ps2d: config set {:?}", config);
self.set_config(config)?;
+5 -5
View File
@@ -57,7 +57,7 @@ pub mod us {
['\0', '\0'],
['\0', '\0'],
['\0', '\0'],
[' ', ' ']
[' ', ' '],
];
pub fn get_char(scancode: u8, shift: bool) -> char {
@@ -236,7 +236,7 @@ pub mod dvorak {
['\0', '\0'],
['\0', '\0'],
['\0', '\0'],
[' ', ' ']
[' ', ' '],
];
pub fn get_char(scancode: u8, shift: bool) -> char {
@@ -311,7 +311,7 @@ pub mod azerty {
['\0', '\0'],
['\0', '\0'],
['\0', '\0'],
[' ', ' ']
[' ', ' '],
];
pub fn get_char(scancode: u8, shift: bool) -> char {
@@ -386,7 +386,7 @@ pub mod bepo {
['\0', '\0'],
['\0', '\0'],
['\0', '\0'],
[' ', ' ']
[' ', ' '],
];
pub fn get_char(scancode: u8, shift: bool) -> char {
@@ -461,7 +461,7 @@ pub mod it {
['\0', '\0'],
['\0', '\0'],
['\0', '\0'],
[' ', ' ']
[' ', ' '],
];
pub fn get_char(scancode: u8, shift: bool) -> char {
+24 -18
View File
@@ -5,11 +5,11 @@ extern crate bitflags;
extern crate orbclient;
extern crate syscall;
use std::{env, process};
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::{env, process};
use log::info;
use syscall::call::iopl;
@@ -21,7 +21,6 @@ mod keymap;
mod state;
mod vm;
fn daemon(daemon: redox_daemon::Daemon) -> ! {
common::setup_logging(
"misc",
@@ -35,10 +34,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
iopl(3).expect("ps2d: failed to get I/O permission");
}
let (keymap, keymap_name): (
fn(u8, bool) -> char,
&str
) = match env::args().skip(1).next() {
let (keymap, keymap_name): (fn(u8, bool) -> char, &str) = match env::args().skip(1).next() {
Some(k) => match k.to_lowercase().as_ref() {
"dvorak" => (keymap::dvorak::get_char, "dvorak"),
"us" => (keymap::us::get_char, "us"),
@@ -71,11 +67,13 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
.open("/scheme/serio/0")
.expect("ps2d: failed to open /scheme/serio/0");
event_file.write(&syscall::Event {
id: key_file.as_raw_fd() as usize,
flags: syscall::EVENT_READ,
data: 0
}).expect("ps2d: failed to event /scheme/serio/0");
event_file
.write(&syscall::Event {
id: key_file.as_raw_fd() as usize,
flags: syscall::EVENT_READ,
data: 0,
})
.expect("ps2d: failed to event /scheme/serio/0");
let mut mouse_file = OpenOptions::new()
.read(true)
@@ -84,15 +82,19 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
.open("/scheme/serio/1")
.expect("ps2d: failed to open /scheme/serio/1");
event_file.write(&syscall::Event {
id: mouse_file.as_raw_fd() as usize,
flags: syscall::EVENT_READ,
data: 1
}).expect("ps2d: failed to event /scheme/serio/1");
event_file
.write(&syscall::Event {
id: mouse_file.as_raw_fd() as usize,
flags: syscall::EVENT_READ,
data: 1,
})
.expect("ps2d: failed to event /scheme/serio/1");
libredox::call::setrens(0, 0).expect("ps2d: failed to enter null namespace");
daemon.ready().expect("ps2d: failed to mark daemon as ready");
daemon
.ready()
.expect("ps2d: failed to mark daemon as ready");
let mut ps2d = Ps2d::new(input, keymap);
@@ -108,7 +110,11 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
// to grab bytes and sort them based on the source
let mut event = syscall::Event::default();
if event_file.read(&mut event).expect("ps2d: failed to read event file") == 0 {
if event_file
.read(&mut event)
.expect("ps2d: failed to read event file")
== 0
{
break;
}
+81 -42
View File
@@ -4,7 +4,7 @@ use std::os::unix::io::AsRawFd;
use std::str;
use log::{error, warn};
use orbclient::{KeyEvent, MouseEvent, MouseRelativeEvent, ButtonEvent, ScrollEvent};
use orbclient::{ButtonEvent, KeyEvent, MouseEvent, MouseRelativeEvent, ScrollEvent};
use crate::controller::Ps2;
use crate::vm;
@@ -22,7 +22,7 @@ bitflags! {
}
}
pub struct Ps2d<F: Fn(u8,bool) -> char> {
pub struct Ps2d<F: Fn(u8, bool) -> char> {
ps2: Ps2,
vmmouse: bool,
vmmouse_relative: bool,
@@ -39,10 +39,10 @@ pub struct Ps2d<F: Fn(u8,bool) -> char> {
packet_i: usize,
extra_packet: bool,
//Keymap function
get_char: F
get_char: F,
}
impl<F: Fn(u8,bool) -> char> Ps2d<F> {
impl<F: Fn(u8, bool) -> char> Ps2d<F> {
pub fn new(input: File, keymap: F) -> Self {
let mut ps2 = Ps2::new();
let extra_packet = ps2.init().expect("ps2d: failed to initialize");
@@ -67,7 +67,7 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
packets: [0; 4],
packet_i: 0,
extra_packet,
get_char: keymap
get_char: keymap,
}
}
@@ -228,11 +228,19 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
}
if scancode != 0 {
self.input.write(&KeyEvent {
character: (self.get_char)(ps2_scancode, self.lshift || self.rshift),
scancode,
pressed
}.to_event()).expect("ps2d: failed to write key event");
self.input
.write(
&KeyEvent {
character: (self.get_char)(
ps2_scancode,
self.lshift || self.rshift,
),
scancode,
pressed,
}
.to_event(),
)
.expect("ps2d: failed to write key event");
}
}
} else if self.vmmouse {
@@ -254,10 +262,15 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
if self.vmmouse_relative {
if dx != 0 || dy != 0 {
self.input.write(&MouseRelativeEvent {
dx: dx as i32,
dy: dy as i32,
}.to_event()).expect("ps2d: failed to write mouse event");
self.input
.write(
&MouseRelativeEvent {
dx: dx as i32,
dy: dy as i32,
}
.to_event(),
)
.expect("ps2d: failed to write mouse event");
}
} else {
let x = dx as i32;
@@ -272,24 +285,37 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
};
if dz != 0 {
self.input.write(&ScrollEvent {
x: 0,
y: -(dz as i32),
}.to_event()).expect("ps2d: failed to write scroll event");
self.input
.write(
&ScrollEvent {
x: 0,
y: -(dz as i32),
}
.to_event(),
)
.expect("ps2d: failed to write scroll event");
}
let left = status & vm::LEFT_BUTTON == vm::LEFT_BUTTON;
let middle = status & vm::MIDDLE_BUTTON == vm::MIDDLE_BUTTON;
let right = status & vm::RIGHT_BUTTON == vm::RIGHT_BUTTON;
if left != self.mouse_left || middle != self.mouse_middle || right != self.mouse_right {
if left != self.mouse_left
|| middle != self.mouse_middle
|| right != self.mouse_right
{
self.mouse_left = left;
self.mouse_middle = middle;
self.mouse_right = right;
self.input.write(&ButtonEvent {
left: left,
middle: middle,
right: right,
}.to_event()).expect("ps2d: failed to write button event");
self.input
.write(
&ButtonEvent {
left: left,
middle: middle,
right: right,
}
.to_event(),
)
.expect("ps2d: failed to write button event");
}
}
} else {
@@ -297,13 +323,17 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
self.packet_i += 1;
let flags = MousePacketFlags::from_bits_truncate(self.packets[0]);
if ! flags.contains(MousePacketFlags::ALWAYS_ON) {
if !flags.contains(MousePacketFlags::ALWAYS_ON) {
error!("ps2d: mouse misalign {:X}", self.packets[0]);
self.packets = [0; 4];
self.packet_i = 0;
} else if self.packet_i >= self.packets.len() || (!self.extra_packet && self.packet_i >= 3) {
if ! flags.contains(MousePacketFlags::X_OVERFLOW) && ! flags.contains(MousePacketFlags::Y_OVERFLOW) {
} else if self.packet_i >= self.packets.len()
|| (!self.extra_packet && self.packet_i >= 3)
{
if !flags.contains(MousePacketFlags::X_OVERFLOW)
&& !flags.contains(MousePacketFlags::Y_OVERFLOW)
{
let mut dx = self.packets[1] as i32;
if flags.contains(MousePacketFlags::X_SIGN) {
dx -= 0x100;
@@ -324,34 +354,43 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
}
if dx != 0 || dy != 0 {
self.input.write(&MouseRelativeEvent {
dx: dx,
dy: dy,
}.to_event()).expect("ps2d: failed to write mouse event");
self.input
.write(&MouseRelativeEvent { dx: dx, dy: dy }.to_event())
.expect("ps2d: failed to write mouse event");
}
if dz != 0 {
self.input.write(&ScrollEvent {
x: 0,
y: dz,
}.to_event()).expect("ps2d: failed to write scroll event");
self.input
.write(&ScrollEvent { x: 0, y: dz }.to_event())
.expect("ps2d: failed to write scroll event");
}
let left = flags.contains(MousePacketFlags::LEFT_BUTTON);
let middle = flags.contains(MousePacketFlags::MIDDLE_BUTTON);
let right = flags.contains(MousePacketFlags::RIGHT_BUTTON);
if left != self.mouse_left || middle != self.mouse_middle || right != self.mouse_right {
if left != self.mouse_left
|| middle != self.mouse_middle
|| right != self.mouse_right
{
self.mouse_left = left;
self.mouse_middle = middle;
self.mouse_right = right;
self.input.write(&ButtonEvent {
left: left,
middle: middle,
right: right,
}.to_event()).expect("ps2d: failed to write button event");
self.input
.write(
&ButtonEvent {
left: left,
middle: middle,
right: right,
}
.to_event(),
)
.expect("ps2d: failed to write button event");
}
} else {
warn!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]);
warn!(
"ps2d: overflow {:X} {:X} {:X} {:X}",
self.packets[0], self.packets[1], self.packets[2], self.packets[3]
);
}
self.packets = [0; 4];
+39 -18
View File
@@ -5,7 +5,7 @@ use syscall::error::Result;
use common::dma::Dma;
use super::hba::{HbaPort, HbaCmdTable, HbaCmdHeader};
use super::hba::{HbaCmdHeader, HbaCmdTable, HbaPort};
use super::Disk;
enum BufferKind<'a> {
@@ -28,7 +28,7 @@ pub struct DiskATA {
clb: Dma<[HbaCmdHeader; 32]>,
ctbas: [Dma<HbaCmdTable>; 32],
_fb: Dma<[u8; 256]>,
buf: Dma<[u8; 256 * 512]>
buf: Dma<[u8; 256 * 512]>,
}
impl DiskATA {
@@ -56,26 +56,28 @@ impl DiskATA {
clb: clb,
ctbas,
_fb: fb,
buf: buf
buf: buf,
})
}
fn request(&mut self, block: u64, mut buffer_kind: BufferKind) -> Result<Option<usize>> {
let (write, address, total_sectors) = match buffer_kind {
BufferKind::Read(ref buffer) => (false, buffer.as_ptr() as usize, buffer.len()/512),
BufferKind::Write(ref buffer) => (true, buffer.as_ptr() as usize, buffer.len()/512),
BufferKind::Read(ref buffer) => (false, buffer.as_ptr() as usize, buffer.len() / 512),
BufferKind::Write(ref buffer) => (true, buffer.as_ptr() as usize, buffer.len() / 512),
};
loop {
let mut request = match self.request_opt.take() {
Some(request) => if address == request.address && total_sectors == request.total_sectors {
// Keep servicing current request
request
} else {
// Have to wait for another request to finish
self.request_opt = Some(request);
return Ok(None);
},
Some(request) => {
if address == request.address && total_sectors == request.total_sectors {
// Keep servicing current request
request
} else {
// Have to wait for another request to finish
self.request_opt = Some(request);
return Ok(None);
}
}
None => {
// Create new request
Request {
@@ -99,7 +101,13 @@ impl DiskATA {
self.port.ata_stop(running.0)?;
if let BufferKind::Read(ref mut buffer) = buffer_kind {
unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().add(request.sector * 512), running.1 * 512); }
unsafe {
ptr::copy(
self.buf.as_ptr(),
buffer.as_mut_ptr().add(request.sector * 512),
running.1 * 512,
);
}
}
request.sector += running.1;
@@ -114,10 +122,23 @@ impl DiskATA {
};
if let BufferKind::Write(ref buffer) = buffer_kind {
unsafe { ptr::copy(buffer.as_ptr().add(request.sector * 512), self.buf.as_mut_ptr(), sectors * 512); }
unsafe {
ptr::copy(
buffer.as_ptr().add(request.sector * 512),
self.buf.as_mut_ptr(),
sectors * 512,
);
}
}
if let Some(slot) = self.port.ata_dma(block + request.sector as u64, sectors, write, &mut self.clb, &mut self.ctbas, &mut self.buf) {
if let Some(slot) = self.port.ata_dma(
block + request.sector as u64,
sectors,
write,
&mut self.clb,
&mut self.ctbas,
&mut self.buf,
) {
request.running_opt = Some((slot, sectors));
}
@@ -146,7 +167,7 @@ impl Disk for DiskATA {
loop {
match self.request(block, BufferKind::Read(buffer))? {
Some(count) => return Ok(Some(count)),
None => std::thread::yield_now()
None => std::thread::yield_now(),
}
}
}
@@ -156,7 +177,7 @@ impl Disk for DiskATA {
loop {
match self.request(block, BufferKind::Write(buffer))? {
Some(count) => return Ok(Some(count)),
None => std::thread::yield_now()
None => std::thread::yield_now(),
}
}
}
+39 -10
View File
@@ -3,13 +3,13 @@
use std::convert::TryInto;
use std::ptr;
use byteorder::{ByteOrder, BigEndian};
use byteorder::{BigEndian, ByteOrder};
use syscall::error::{Result, EBADF, Error};
use syscall::error::{Error, Result, EBADF};
use common::dma::Dma;
use super::hba::{HbaPort, HbaCmdTable, HbaCmdHeader};
use super::hba::{HbaCmdHeader, HbaCmdTable, HbaPort};
use super::Disk;
const SCSI_READ_CAPACITY: u8 = 0x25;
@@ -24,7 +24,7 @@ pub struct DiskATAPI {
_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]>
buf: Dma<[u8; 256 * 512]>,
}
impl DiskATAPI {
@@ -60,7 +60,8 @@ impl DiskATAPI {
let mut cmd = [0; 16];
cmd[0] = SCSI_READ_CAPACITY;
self.port.atapi_dma(&cmd, 8, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
self.port
.atapi_dma(&cmd, 8, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
// Instead of a count, contains number of last LBA, so add 1
let blk_count = BigEndian::read_u32(&self.buf[0..4]) + 1;
@@ -78,7 +79,7 @@ impl Disk for DiskATAPI {
fn size(&mut self) -> u64 {
match self.read_capacity() {
Ok((blk_count, blk_size)) => (blk_count as u64) * (blk_size as u64),
Err(_) => 0 // XXX
Err(_) => 0, // XXX
}
}
@@ -101,17 +102,45 @@ impl Disk for DiskATAPI {
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.atapi_dma(&cmd, buf_size, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
self.port.atapi_dma(
&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); }
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.atapi_dma(&cmd, buf_size, &mut self.clb, &mut self.ctbas, &mut self.buf)?;
self.port.atapi_dma(
&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); }
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;
}
+25 -25
View File
@@ -17,7 +17,7 @@ pub enum FisType {
/// PIO setup FIS - device to host
PioSetup = 0x5F,
/// Set device bits FIS - device to host
DevBits = 0xA1
DevBits = 0xA1,
}
#[repr(packed)]
@@ -27,25 +27,25 @@ pub struct FisRegH2D {
pub pm: Mmio<u8>, // Port multiplier, 1: Command, 0: Control
pub command: Mmio<u8>, // Command register
pub command: Mmio<u8>, // Command register
pub featurel: Mmio<u8>, // Feature register, 7:0
// DWORD 1
pub lba0: Mmio<u8>, // LBA low register, 7:0
pub lba1: Mmio<u8>, // LBA mid register, 15:8
pub lba2: Mmio<u8>, // LBA high register, 23:16
pub lba0: Mmio<u8>, // LBA low register, 7:0
pub lba1: Mmio<u8>, // LBA mid register, 15:8
pub lba2: Mmio<u8>, // LBA high register, 23:16
pub device: Mmio<u8>, // Device register
// DWORD 2
pub lba3: Mmio<u8>, // LBA register, 31:24
pub lba4: Mmio<u8>, // LBA register, 39:32
pub lba5: Mmio<u8>, // LBA register, 47:40
pub lba3: Mmio<u8>, // LBA register, 31:24
pub lba4: Mmio<u8>, // LBA register, 39:32
pub lba5: Mmio<u8>, // LBA register, 47:40
pub featureh: Mmio<u8>, // Feature register, 15:8
// DWORD 3
pub countl: Mmio<u8>, // Count register, 7:0
pub counth: Mmio<u8>, // Count register, 15:8
pub icc: Mmio<u8>, // Isochronous command completion
pub countl: Mmio<u8>, // Count register, 7:0
pub counth: Mmio<u8>, // Count register, 15:8
pub icc: Mmio<u8>, // Isochronous command completion
pub control: Mmio<u8>, // Control register
// DWORD 4
@@ -60,12 +60,12 @@ pub struct FisRegD2H {
pub pm: Mmio<u8>, // Port multiplier, Interrupt bit: 2
pub status: Mmio<u8>, // Status register
pub error: Mmio<u8>, // Error register
pub error: Mmio<u8>, // Error register
// DWORD 1
pub lba0: Mmio<u8>, // LBA low register, 7:0
pub lba1: Mmio<u8>, // LBA mid register, 15:8
pub lba2: Mmio<u8>, // LBA high register, 23:16
pub lba0: Mmio<u8>, // LBA low register, 7:0
pub lba1: Mmio<u8>, // LBA mid register, 15:8
pub lba2: Mmio<u8>, // LBA high register, 23:16
pub device: Mmio<u8>, // Device register
// DWORD 2
@@ -75,8 +75,8 @@ pub struct FisRegD2H {
pub rsv2: Mmio<u8>, // Reserved
// DWORD 3
pub countl: Mmio<u8>, // Count register, 7:0
pub counth: Mmio<u8>, // Count register, 15:8
pub countl: Mmio<u8>, // Count register, 7:0
pub counth: Mmio<u8>, // Count register, 15:8
pub rsv3: [Mmio<u8>; 2], // Reserved
// DWORD 4
@@ -104,12 +104,12 @@ pub struct FisPioSetup {
pub pm: Mmio<u8>, // Port multiplier, direction: 4 - device to host, interrupt: 2
pub status: Mmio<u8>, // Status register
pub error: Mmio<u8>, // Error register
pub error: Mmio<u8>, // Error register
// DWORD 1
pub lba0: Mmio<u8>, // LBA low register, 7:0
pub lba1: Mmio<u8>, // LBA mid register, 15:8
pub lba2: Mmio<u8>, // LBA high register, 23:16
pub lba0: Mmio<u8>, // LBA low register, 7:0
pub lba1: Mmio<u8>, // LBA mid register, 15:8
pub lba2: Mmio<u8>, // LBA high register, 23:16
pub device: Mmio<u8>, // Device register
// DWORD 2
@@ -119,13 +119,13 @@ pub struct FisPioSetup {
pub rsv2: Mmio<u8>, // Reserved
// DWORD 3
pub countl: Mmio<u8>, // Count register, 7:0
pub counth: Mmio<u8>, // Count register, 15:8
pub rsv3: Mmio<u8>, // Reserved
pub countl: Mmio<u8>, // Count register, 7:0
pub counth: Mmio<u8>, // Count register, 15:8
pub rsv3: Mmio<u8>, // Reserved
pub e_status: Mmio<u8>, // New value of status register
// DWORD 4
pub tc: Mmio<u16>, // Transfer count
pub tc: Mmio<u16>, // Transfer count
pub rsv4: [Mmio<u8>; 2], // Reserved
}
+171 -83
View File
@@ -6,7 +6,7 @@ use std::{ptr, u32};
use common::io::{Io, Mmio};
use syscall::error::{Error, Result, EIO};
use super::fis::{FisType, FisRegH2D};
use super::fis::{FisRegH2D, FisType};
use common::dma::Dma;
@@ -42,20 +42,20 @@ pub enum HbaPortType {
#[repr(packed)]
pub struct HbaPort {
pub clb: [Mmio<u32>; 2], // 0x00, command list base address, 1K-byte aligned
pub fb: [Mmio<u32>; 2], // 0x08, FIS base address, 256-byte aligned
pub is: Mmio<u32>, // 0x10, interrupt status
pub ie: Mmio<u32>, // 0x14, interrupt enable
pub cmd: Mmio<u32>, // 0x18, command and status
pub _rsv0: Mmio<u32>, // 0x1C, Reserved
pub tfd: Mmio<u32>, // 0x20, task file data
pub sig: Mmio<u32>, // 0x24, signature
pub ssts: Mmio<u32>, // 0x28, SATA status (SCR0:SStatus)
pub sctl: Mmio<u32>, // 0x2C, SATA control (SCR2:SControl)
pub serr: Mmio<u32>, // 0x30, SATA error (SCR1:SError)
pub sact: Mmio<u32>, // 0x34, SATA active (SCR3:SActive)
pub ci: Mmio<u32>, // 0x38, command issue
pub sntf: Mmio<u32>, // 0x3C, SATA notification (SCR4:SNotification)
pub fbs: Mmio<u32>, // 0x40, FIS-based switch control
pub fb: [Mmio<u32>; 2], // 0x08, FIS base address, 256-byte aligned
pub is: Mmio<u32>, // 0x10, interrupt status
pub ie: Mmio<u32>, // 0x14, interrupt enable
pub cmd: Mmio<u32>, // 0x18, command and status
pub _rsv0: Mmio<u32>, // 0x1C, Reserved
pub tfd: Mmio<u32>, // 0x20, task file data
pub sig: Mmio<u32>, // 0x24, signature
pub ssts: Mmio<u32>, // 0x28, SATA status (SCR0:SStatus)
pub sctl: Mmio<u32>, // 0x2C, SATA control (SCR2:SControl)
pub serr: Mmio<u32>, // 0x30, SATA error (SCR1:SError)
pub sact: Mmio<u32>, // 0x34, SATA active (SCR3:SActive)
pub ci: Mmio<u32>, // 0x38, command issue
pub sntf: Mmio<u32>, // 0x3C, SATA notification (SCR4:SNotification)
pub fbs: Mmio<u32>, // 0x40, FIS-based switch control
pub _rsv1: [Mmio<u32>; 11], // 0x44 ~ 0x6F, Reserved
pub vendor: [Mmio<u32>; 4], // 0x70 ~ 0x7F, vendor specific
}
@@ -104,13 +104,20 @@ impl HbaPort {
None
}
pub fn init(&mut self, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma<HbaCmdTable>; 32], fb: &mut Dma<[u8; 256]>) {
pub fn init(
&mut self,
clb: &mut Dma<[HbaCmdHeader; 32]>,
ctbas: &mut [Dma<HbaCmdTable>; 32],
fb: &mut Dma<[u8; 256]>,
) {
self.stop();
for i in 0..32 {
let cmdheader = &mut clb[i];
cmdheader.ctba_low.write(ctbas[i].physical() as u32);
cmdheader.ctba_high.write((ctbas[i].physical() as u64 >> 32) as u32);
cmdheader
.ctba_high
.write((ctbas[i].physical() as u64 >> 32) as u32);
cmdheader.prdtl.write(0);
}
@@ -125,7 +132,7 @@ impl HbaPort {
self.serr.write(serr);
// Disable power management
let sctl = self.sctl.read() ;
let sctl = self.sctl.read();
self.sctl.write(sctl | 7 << 8);
// Power on and spin up device
@@ -134,16 +141,29 @@ impl HbaPort {
debug!(" - AHCI init {:X}", self.cmd.read());
}
pub unsafe fn identify(&mut self, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma<HbaCmdTable>; 32]) -> Option<u64> {
pub unsafe fn identify(
&mut self,
clb: &mut Dma<[HbaCmdHeader; 32]>,
ctbas: &mut [Dma<HbaCmdTable>; 32],
) -> Option<u64> {
self.identify_inner(ATA_CMD_IDENTIFY, clb, ctbas)
}
pub unsafe fn identify_packet(&mut self, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma<HbaCmdTable>; 32]) -> Option<u64> {
pub unsafe fn identify_packet(
&mut self,
clb: &mut Dma<[HbaCmdHeader; 32]>,
ctbas: &mut [Dma<HbaCmdTable>; 32],
) -> Option<u64> {
self.identify_inner(ATA_CMD_IDENTIFY_PACKET, clb, ctbas)
}
// Shared between identify() and identify_packet()
unsafe fn identify_inner(&mut self, cmd: u8, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma<HbaCmdTable>; 32]) -> Option<u64> {
unsafe fn identify_inner(
&mut self,
cmd: u8,
clb: &mut Dma<[HbaCmdHeader; 32]>,
ctbas: &mut [Dma<HbaCmdTable>; 32],
) -> Option<u64> {
let dest: Dma<[u16; 256]> = Dma::new([0; 256]).unwrap();
let slot = self.ata_start(clb, ctbas, |cmdheader, cmdfis, prdt_entries, _acmd| {
@@ -151,7 +171,9 @@ impl HbaPort {
let prdt_entry = &mut prdt_entries[0];
prdt_entry.dba_low.write(dest.physical() as u32);
prdt_entry.dba_high.write((dest.physical() as u64 >> 32) as u32);
prdt_entry
.dba_high
.write((dest.physical() as u64 >> 32) as u32);
prdt_entry.dbc.write(512 | 1);
cmdfis.pm.write(1 << 7);
@@ -201,10 +223,10 @@ impl HbaPort {
}
}
let mut sectors = (dest[100] as u64) |
((dest[101] as u64) << 16) |
((dest[102] as u64) << 32) |
((dest[103] as u64) << 48);
let mut sectors = (dest[100] as u64)
| ((dest[101] as u64) << 16)
| ((dest[102] as u64) << 32)
| ((dest[103] as u64) << 48);
let lba_bits = if sectors == 0 {
sectors = (dest[60] as u64) | ((dest[61] as u64) << 16);
@@ -213,8 +235,14 @@ impl HbaPort {
48
};
info!(" + Serial: {} Firmware: {} Model: {} {}-bit LBA Size: {} MB",
serial.trim(), firmware.trim(), model.trim(), lba_bits, sectors / 2048);
info!(
" + Serial: {} Firmware: {} Model: {} {}-bit LBA Size: {} MB",
serial.trim(),
firmware.trim(),
model.trim(),
lba_bits,
sectors / 2048
);
Some(sectors * 512)
} else {
@@ -222,8 +250,22 @@ impl HbaPort {
}
}
pub fn ata_dma(&mut self, block: u64, sectors: usize, write: bool, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma<HbaCmdTable>; 32], buf: &mut Dma<[u8; 256 * 512]>) -> Option<u32> {
trace!("AHCI {:X} DMA BLOCK: {:X} SECTORS: {} WRITE: {}", (self as *mut HbaPort) as usize, block, sectors, write);
pub fn ata_dma(
&mut self,
block: u64,
sectors: usize,
write: bool,
clb: &mut Dma<[HbaCmdHeader; 32]>,
ctbas: &mut [Dma<HbaCmdTable>; 32],
buf: &mut Dma<[u8; 256 * 512]>,
) -> Option<u32> {
trace!(
"AHCI {:X} DMA BLOCK: {:X} SECTORS: {} WRITE: {}",
(self as *mut HbaPort) as usize,
block,
sectors,
write
);
assert!(sectors > 0 && sectors < 256);
@@ -237,7 +279,9 @@ impl HbaPort {
let prdt_entry = &mut prdt_entries[0];
prdt_entry.dba_low.write(buf.physical() as u32);
prdt_entry.dba_high.write((buf.physical() as u64 >> 32) as u32);
prdt_entry
.dba_high
.write((buf.physical() as u64 >> 32) as u32);
prdt_entry.dbc.write(((sectors * 512) as u32) | 1);
cmdfis.pm.write(1 << 7);
@@ -263,44 +307,74 @@ impl HbaPort {
}
/// Send ATAPI packet
pub fn atapi_dma(&mut self, cmd: &[u8; 16], size: u32, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma<HbaCmdTable>; 32], buf: &mut Dma<[u8; 256 * 512]>) -> Result<()> {
let slot = self.ata_start(clb, ctbas, |cmdheader, cmdfis, prdt_entries, acmd| {
let cfl = cmdheader.cfl.read();
cmdheader.cfl.write(cfl | 1 << 5);
pub fn atapi_dma(
&mut self,
cmd: &[u8; 16],
size: u32,
clb: &mut Dma<[HbaCmdHeader; 32]>,
ctbas: &mut [Dma<HbaCmdTable>; 32],
buf: &mut Dma<[u8; 256 * 512]>,
) -> Result<()> {
let slot = self
.ata_start(clb, ctbas, |cmdheader, cmdfis, prdt_entries, acmd| {
let cfl = cmdheader.cfl.read();
cmdheader.cfl.write(cfl | 1 << 5);
cmdheader.prdtl.write(1);
cmdheader.prdtl.write(1);
let prdt_entry = &mut prdt_entries[0];
prdt_entry.dba_low.write(buf.physical() as u32);
prdt_entry.dba_high.write((buf.physical() as u64 >> 32) as u32);
prdt_entry.dbc.write(size - 1);
let prdt_entry = &mut prdt_entries[0];
prdt_entry.dba_low.write(buf.physical() as u32);
prdt_entry
.dba_high
.write((buf.physical() as u64 >> 32) as u32);
prdt_entry.dbc.write(size - 1);
cmdfis.pm.write(1 << 7);
cmdfis.command.write(ATA_CMD_PACKET);
cmdfis.device.write(0);
cmdfis.lba1.write(0);
cmdfis.lba2.write(0);
cmdfis.featurel.write(1);
cmdfis.featureh.write(0);
cmdfis.pm.write(1 << 7);
cmdfis.command.write(ATA_CMD_PACKET);
cmdfis.device.write(0);
cmdfis.lba1.write(0);
cmdfis.lba2.write(0);
cmdfis.featurel.write(1);
cmdfis.featureh.write(0);
unsafe { ptr::write_volatile(acmd.as_mut_ptr() as *mut [u8; 16], *cmd) };
}).ok_or(Error::new(EIO))?;
unsafe { ptr::write_volatile(acmd.as_mut_ptr() as *mut [u8; 16], *cmd) };
})
.ok_or(Error::new(EIO))?;
self.ata_stop(slot)
}
pub fn ata_start<F>(&mut self, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma<HbaCmdTable>; 32], callback: F) -> Option<u32>
where F: FnOnce(&mut HbaCmdHeader, &mut FisRegH2D, &mut [HbaPrdtEntry; PRDT_ENTRIES], &mut [Mmio<u8>; 16]) {
pub fn ata_start<F>(
&mut self,
clb: &mut Dma<[HbaCmdHeader; 32]>,
ctbas: &mut [Dma<HbaCmdTable>; 32],
callback: F,
) -> Option<u32>
where
F: FnOnce(
&mut HbaCmdHeader,
&mut FisRegH2D,
&mut [HbaPrdtEntry; PRDT_ENTRIES],
&mut [Mmio<u8>; 16],
),
{
//TODO: Should probably remove
self.is.write(u32::MAX);
if let Some(slot) = self.slot() {
{
let cmdheader = &mut clb[slot as usize];
cmdheader.cfl.write((size_of::<FisRegH2D>() / size_of::<u32>()) as u8);
cmdheader
.cfl
.write((size_of::<FisRegH2D>() / size_of::<u32>()) as u8);
let cmdtbl = &mut ctbas[slot as usize];
unsafe { ptr::write_bytes(cmdtbl.deref_mut() as *mut HbaCmdTable as *mut u8, 0, size_of::<HbaCmdTable>()); }
unsafe {
ptr::write_bytes(
cmdtbl.deref_mut() as *mut HbaCmdTable as *mut u8,
0,
size_of::<HbaCmdTable>(),
);
}
let cmdfis = unsafe { &mut *(cmdtbl.cfis.as_mut_ptr() as *mut FisRegH2D) };
cmdfis.fis_type.write(FisType::RegH2D as u8);
@@ -338,18 +412,25 @@ impl HbaPort {
self.stop();
if self.is.read() & HBA_PORT_IS_ERR != 0 {
let (
is, ie, cmd, tfd,
ssts, sctl, serr, sact,
ci, sntf, fbs
) = (
self.is.read(), self.ie.read(), self.cmd.read(), self.tfd.read(),
self.ssts.read(), self.sctl.read(), self.serr.read(), self.sact.read(),
self.ci.read(), self.sntf.read(), self.fbs.read()
let (is, ie, cmd, tfd, ssts, sctl, serr, sact, ci, sntf, fbs) = (
self.is.read(),
self.ie.read(),
self.cmd.read(),
self.tfd.read(),
self.ssts.read(),
self.sctl.read(),
self.serr.read(),
self.sact.read(),
self.ci.read(),
self.sntf.read(),
self.fbs.read(),
);
error!("IS {:X} IE {:X} CMD {:X} TFD {:X}", is, ie, cmd, tfd);
error!("SSTS {:X} SCTL {:X} SERR {:X} SACT {:X}", ssts, sctl, serr, sact);
error!(
"SSTS {:X} SCTL {:X} SERR {:X} SACT {:X}",
ssts, sctl, serr, sact
);
error!("CI {:X} SNTF {:X} FBS {:X}", ci, sntf, fbs);
self.is.write(u32::MAX);
@@ -362,20 +443,20 @@ impl HbaPort {
#[repr(packed)]
pub struct HbaMem {
pub cap: Mmio<u32>, // 0x00, Host capability
pub ghc: Mmio<u32>, // 0x04, Global host control
pub is: Mmio<u32>, // 0x08, Interrupt status
pub pi: Mmio<u32>, // 0x0C, Port implemented
pub vs: Mmio<u32>, // 0x10, Version
pub ccc_ctl: Mmio<u32>, // 0x14, Command completion coalescing control
pub ccc_pts: Mmio<u32>, // 0x18, Command completion coalescing ports
pub em_loc: Mmio<u32>, // 0x1C, Enclosure management location
pub em_ctl: Mmio<u32>, // 0x20, Enclosure management control
pub cap2: Mmio<u32>, // 0x24, Host capabilities extended
pub bohc: Mmio<u32>, // 0x28, BIOS/OS handoff control and status
pub _rsv: [Mmio<u8>; 116], // 0x2C - 0x9F, Reserved
pub cap: Mmio<u32>, // 0x00, Host capability
pub ghc: Mmio<u32>, // 0x04, Global host control
pub is: Mmio<u32>, // 0x08, Interrupt status
pub pi: Mmio<u32>, // 0x0C, Port implemented
pub vs: Mmio<u32>, // 0x10, Version
pub ccc_ctl: Mmio<u32>, // 0x14, Command completion coalescing control
pub ccc_pts: Mmio<u32>, // 0x18, Command completion coalescing ports
pub em_loc: Mmio<u32>, // 0x1C, Enclosure management location
pub em_ctl: Mmio<u32>, // 0x20, Enclosure management control
pub cap2: Mmio<u32>, // 0x24, Host capabilities extended
pub bohc: Mmio<u32>, // 0x28, BIOS/OS handoff control and status
pub _rsv: [Mmio<u8>; 116], // 0x2C - 0x9F, Reserved
pub vendor: [Mmio<u8>; 96], // 0xA0 - 0xFF, Vendor specific registers
pub ports: [HbaPort; 32], // 0x100 - 0x10FF, Port control registers
pub ports: [HbaPort; 32], // 0x100 - 0x10FF, Port control registers
}
impl HbaMem {
@@ -388,18 +469,25 @@ impl HbaMem {
*/
self.ghc.write(1 << 31 | 1 << 1);
debug!(" - AHCI CAP {:X} GHC {:X} IS {:X} PI {:X} VS {:X} CAP2 {:X} BOHC {:X}",
self.cap.read(), self.ghc.read(), self.is.read(), self.pi.read(),
self.vs.read(), self.cap2.read(), self.bohc.read());
debug!(
" - AHCI CAP {:X} GHC {:X} IS {:X} PI {:X} VS {:X} CAP2 {:X} BOHC {:X}",
self.cap.read(),
self.ghc.read(),
self.is.read(),
self.pi.read(),
self.vs.read(),
self.cap2.read(),
self.bohc.read()
);
}
}
#[repr(packed)]
pub struct HbaPrdtEntry {
dba_low: Mmio<u32>, // Data base address (low
dba_low: Mmio<u32>, // Data base address (low
dba_high: Mmio<u32>, // Data base address (high)
_rsv0: Mmio<u32>, // Reserved
dbc: Mmio<u32>, // Byte count, 4M max, interrupt = 1
_rsv0: Mmio<u32>, // Reserved
dbc: Mmio<u32>, // Byte count, 4M max, interrupt = 1
}
#[repr(packed)]
@@ -431,7 +519,7 @@ pub struct HbaCmdHeader {
_prdbc: Mmio<u32>, // Physical region descriptor byte count transferred
// DW2, 3
ctba_low: Mmio<u32>, // Command table descriptor base address (low)
ctba_low: Mmio<u32>, // Command table descriptor base address (low)
ctba_high: Mmio<u32>, // Command table descriptor base address (high)
// DW4 - 7
+26 -30
View File
@@ -1,6 +1,6 @@
use common::io::Io;
use driver_block::Disk;
use log::{error, info};
use common::io::Io;
use self::disk_ata::DiskATA;
use self::disk_atapi::DiskATAPI;
@@ -16,37 +16,33 @@ pub fn disks(base: usize, name: &str) -> (&'static mut HbaMem, Vec<Box<dyn Disk>
hba_mem.init();
let pi = hba_mem.pi.read();
let disks: Vec<Box<dyn Disk>> = (0..hba_mem.ports.len())
.filter(|&i| pi & 1 << i as i32 == 1 << i as i32)
.filter_map(|i| {
let port = unsafe { &mut *hba_mem.ports.as_mut_ptr().add(i) };
let port_type = port.probe();
info!("{}-{}: {:?}", name, i, port_type);
.filter(|&i| pi & 1 << i as i32 == 1 << i as i32)
.filter_map(|i| {
let port = unsafe { &mut *hba_mem.ports.as_mut_ptr().add(i) };
let port_type = port.probe();
info!("{}-{}: {:?}", name, i, port_type);
let disk: Option<Box<dyn Disk>> = match port_type {
HbaPortType::SATA => {
match DiskATA::new(i, port) {
Ok(disk) => Some(Box::new(disk)),
Err(err) => {
error!("{}: {}", i, err);
None
}
}
}
HbaPortType::SATAPI => {
match DiskATAPI::new(i, port) {
Ok(disk) => Some(Box::new(disk)),
Err(err) => {
error!("{}: {}", i, err);
None
}
}
}
_ => None,
};
let disk: Option<Box<dyn Disk>> = match port_type {
HbaPortType::SATA => match DiskATA::new(i, port) {
Ok(disk) => Some(Box::new(disk)),
Err(err) => {
error!("{}: {}", i, err);
None
}
},
HbaPortType::SATAPI => match DiskATAPI::new(i, port) {
Ok(disk) => Some(Box::new(disk)),
Err(err) => {
error!("{}: {}", i, err);
None
}
},
_ => None,
};
disk
})
.collect();
disk
})
.collect();
(hba_mem, disks)
}
+60 -25
View File
@@ -1,8 +1,8 @@
#![cfg_attr(target_arch = "aarch64", feature(stdsimd))] // Required for yield instruction
#![feature(int_roundings)]
extern crate syscall;
extern crate byteorder;
extern crate syscall;
use std::io::{Read, Write};
use std::os::fd::AsRawFd;
@@ -33,7 +33,10 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut name = pci_config.func.name();
name.push_str("_ahci");
let irq = pci_config.func.legacy_interrupt_line.expect("ahcid: no legacy interrupts supported");
let irq = pci_config
.func
.legacy_interrupt_line
.expect("ahcid: no legacy interrupts supported");
common::setup_logging(
"disk",
@@ -45,10 +48,13 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
info!(" + AHCI {}", pci_config.func.display());
let address = unsafe { pcid_handle.map_bar(5).expect("ahcid") }.ptr.as_ptr() as usize;
let address = unsafe { pcid_handle.map_bar(5).expect("ahcid") }
.ptr
.as_ptr() as usize;
{
let scheme_name = format!("disk.{}", name);
let socket = Socket::<V2>::nonblock(&scheme_name).expect("ahcid: failed to create disk scheme");
let socket =
Socket::<V2>::nonblock(&scheme_name).expect("ahcid: failed to create disk scheme");
let mut irq_file = irq.irq_handle("ahcid");
let irq_fd = irq_file.as_raw_fd() as usize;
@@ -57,8 +63,12 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
libredox::call::setrens(0, 0).expect("ahcid: failed to enter null namespace");
event_queue.subscribe(socket.inner().raw(), 1, EventFlags::READ).expect("ahcid: failed to event scheme socket");
event_queue.subscribe(irq_fd, 1, EventFlags::READ).expect("ahcid: failed to event irq scheme");
event_queue
.subscribe(socket.inner().raw(), 1, EventFlags::READ)
.expect("ahcid: failed to event scheme socket");
event_queue
.subscribe(irq_fd, 1, EventFlags::READ)
.expect("ahcid: failed to event irq scheme");
daemon.ready().expect("ahcid: failed to notify parent");
@@ -68,7 +78,11 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut mounted = true;
let mut todo = Vec::new();
while mounted {
let Some(event) = event_queue.next().transpose().expect("ahcid: failed to read event file") else {
let Some(event) = event_queue
.next()
.transpose()
.expect("ahcid: failed to read event file")
else {
break;
};
if event.fd == socket.inner().raw() {
@@ -77,39 +91,53 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
Ok(None) => {
mounted = false;
break;
},
Ok(Some(s)) => if let RequestKind::Call(call) = s.kind() {
call
} else {
// TODO: Support e.g. cancellation
continue;
},
Err(err) => if err.errno == EWOULDBLOCK || err.errno == EAGAIN {
break;
} else {
panic!("ahcid: failed to read disk scheme: {}", err);
}
Ok(Some(s)) => {
if let RequestKind::Call(call) = s.kind() {
call
} else {
// TODO: Support e.g. cancellation
continue;
}
}
Err(err) => {
if err.errno == EWOULDBLOCK || err.errno == EAGAIN {
break;
} else {
panic!("ahcid: failed to read disk scheme: {}", err);
}
}
};
if let Some(response) = sqe.handle_scheme_block_mut(&mut scheme) {
// TODO: handle full CQE?
socket.write_response(response, SignalBehavior::Restart).expect("ahcid: failed to write disk scheme");
socket
.write_response(response, SignalBehavior::Restart)
.expect("ahcid: failed to write disk scheme");
} else {
todo.push(sqe);
}
}
} else if event.fd == irq_fd {
let mut irq = [0; 8];
if irq_file.read(&mut irq).expect("ahcid: failed to read irq file") >= irq.len() {
if irq_file
.read(&mut irq)
.expect("ahcid: failed to read irq file")
>= irq.len()
{
if scheme.irq() {
irq_file.write(&irq).expect("ahcid: failed to write irq file");
irq_file
.write(&irq)
.expect("ahcid: failed to write irq file");
// Handle todos in order to finish previous packets if possible
let mut i = 0;
while i < todo.len() {
if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) {
let _sqe = todo.remove(i);
socket.write_response(resp, SignalBehavior::Restart).expect("ahcid: failed to write disk scheme");
socket
.write_response(resp, SignalBehavior::Restart)
.expect("ahcid: failed to write disk scheme");
} else {
i += 1;
}
@@ -125,15 +153,22 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
while i < todo.len() {
if let Some(response) = todo[i].handle_scheme_block_mut(&mut scheme) {
let _sqe = todo.remove(i);
socket.write_response(response, SignalBehavior::Restart).expect("ahcid: failed to write disk scheme");
socket
.write_response(response, SignalBehavior::Restart)
.expect("ahcid: failed to write disk scheme");
} else {
i += 1;
}
}
if ! mounted {
if !mounted {
for sqe in todo.drain(..) {
socket.write_response(Response::new(&sqe, Err(Error::new(ENODEV))), SignalBehavior::Restart).expect("ahcid: failed to write disk scheme");
socket
.write_response(
Response::new(&sqe, Err(Error::new(ENODEV))),
SignalBehavior::Restart,
)
.expect("ahcid: failed to write disk scheme");
}
}
}
+112 -50
View File
@@ -1,22 +1,22 @@
use std::collections::BTreeMap;
use std::str;
use std::fmt::Write;
use std::str;
use common::io::Io as _;
use driver_block::{Disk, DiskWrapper};
use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
use syscall::schemev2::NewFdFlags;
use syscall::{
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Stat, MODE_DIR,
Error, Result, Stat, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, MODE_DIR,
MODE_FILE, O_DIRECTORY, O_STAT,
};
use common::io::Io as _;
use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
use crate::ahci::hba::HbaMem;
#[derive(Clone)]
enum Handle {
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
Partition(usize, u32), // Disk index, partition index
}
@@ -25,17 +25,25 @@ pub struct DiskScheme {
hba_mem: &'static mut HbaMem,
disks: Box<[DiskWrapper]>,
handles: BTreeMap<usize, Handle>,
next_id: usize
next_id: usize,
}
impl DiskScheme {
pub fn new(scheme_name: String, hba_mem: &'static mut HbaMem, disks: Vec<Box<dyn Disk>>) -> DiskScheme {
pub fn new(
scheme_name: String,
hba_mem: &'static mut HbaMem,
disks: Vec<Box<dyn Disk>>,
) -> DiskScheme {
DiskScheme {
scheme_name,
hba_mem,
disks: disks.into_iter().map(DiskWrapper::new).collect::<Vec<_>>().into_boxed_slice(),
disks: disks
.into_iter()
.map(DiskWrapper::new)
.collect::<Vec<_>>()
.into_boxed_slice(),
handles: BTreeMap::new(),
next_id: 0
next_id: 0,
}
}
@@ -62,19 +70,25 @@ impl DiskScheme {
fn check_locks(&self, disk_i: usize, part_i_opt: Option<u32>) -> Result<()> {
for (_, handle) in self.handles.iter() {
match handle {
Handle::Disk(i) => if disk_i == *i {
return Err(Error::new(ENOLCK));
},
Handle::Partition(i, p) => if disk_i == *i {
match part_i_opt {
Some(part_i) => if part_i == *p {
return Err(Error::new(ENOLCK));
},
None => {
return Err(Error::new(ENOLCK));
Handle::Disk(i) => {
if disk_i == *i {
return Err(Error::new(ENOLCK));
}
}
Handle::Partition(i, p) => {
if disk_i == *i {
match part_i_opt {
Some(part_i) => {
if part_i == *p {
return Err(Error::new(ENOLCK));
}
}
None => {
return Err(Error::new(ENOLCK));
}
}
}
},
}
_ => (),
}
}
@@ -99,7 +113,7 @@ impl SchemeBlockMut for DiskScheme {
write!(list, "{}\n", disk_index).unwrap();
if disk.pt.is_none() {
continue
continue;
}
for part_index in 0..disk.pt.as_ref().unwrap().partitions.len() {
write!(list, "{}p{}\n", disk_index, part_index).unwrap();
@@ -117,7 +131,15 @@ impl SchemeBlockMut for DiskScheme {
let p = part_id_str.parse::<u32>().or(Err(Error::new(ENOENT)))?;
let disk = self.disks.get(i).ok_or(Error::new(ENOENT))?;
if disk.pt.is_none() || disk.pt.as_ref().unwrap().partitions.get(p as usize).is_none() {
if disk.pt.is_none()
|| disk
.pt
.as_ref()
.unwrap()
.partitions
.get(p as usize)
.is_none()
{
return Err(Error::new(ENOENT));
}
@@ -137,11 +159,14 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, handle);
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
}
fn xdup(&mut self, id: usize, buf: &[u8], _: &CallerCtx) -> Result<Option<OpenResult>> {
if ! buf.is_empty() {
if !buf.is_empty() {
return Err(Error::new(EINVAL));
}
@@ -153,7 +178,10 @@ impl SchemeBlockMut for DiskScheme {
let new_id = self.next_id;
self.next_id += 1;
self.handles.insert(new_id, new_handle);
Ok(Some(OpenResult::ThisScheme { number: new_id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: new_id,
flags: NewFdFlags::POSITIONED,
}))
}
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<Option<usize>> {
@@ -162,7 +190,7 @@ impl SchemeBlockMut for DiskScheme {
stat.st_mode = MODE_DIR;
stat.st_size = data.len() as u64;
Ok(Some(0))
},
}
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
stat.st_mode = MODE_FILE;
@@ -174,7 +202,10 @@ impl SchemeBlockMut for DiskScheme {
let disk = self.disks.get_mut(disk_id).ok_or(Error::new(EBADF))?;
let size = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
partition.size
};
@@ -232,15 +263,24 @@ impl SchemeBlockMut for DiskScheme {
Ok(Some(i))
}
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
fn read(
&mut self,
id: usize,
buf: &mut [u8],
offset: u64,
_fcntl_flags: u32,
) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle) => {
let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]);
let src = usize::try_from(offset)
.ok()
.and_then(|o| handle.get(o..))
.unwrap_or(&[]);
let byte_count = core::cmp::min(src.len(), buf.len());
buf[..byte_count].copy_from_slice(&src[..byte_count]);
Ok(Some(byte_count))
},
}
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
@@ -255,7 +295,10 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
let abs_block = partition.start_lba + rel_block;
// TODO: This shouldn't return EOVERFLOW?
@@ -270,11 +313,15 @@ impl SchemeBlockMut for DiskScheme {
}
}
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
fn write(
&mut self,
id: usize,
buf: &[u8],
offset: u64,
_fcntl_flags: u32,
) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(_) => {
Err(Error::new(EBADF))
},
Handle::List(_) => Err(Error::new(EBADF)),
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
@@ -289,7 +336,10 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
let abs_block = partition.start_lba + rel_block;
if rel_block >= partition.size {
@@ -304,21 +354,33 @@ impl SchemeBlockMut for DiskScheme {
}
fn fsize(&mut self, id: usize) -> Result<Option<u64>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle) => handle.len() as u64,
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
disk.size()
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let block_count = disk.pt.as_ref().ok_or(Error::new(EBADF))?.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?.size;
u64::from(disk.block_length()?) * block_count
}
}))
Ok(Some(
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle) => handle.len() as u64,
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
disk.size()
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let block_count = disk
.pt
.as_ref()
.ok_or(Error::new(EBADF))?
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?
.size;
u64::from(disk.block_length()?) * block_count
}
},
))
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
self.handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(Some(0)))
self.handles
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(Some(0)))
}
}
+60 -23
View File
@@ -1,17 +1,26 @@
use std::{fs::File, io::{Read, Write}, process};
use std::{
fs::File,
io::{Read, Write},
process,
};
use driver_block::Disk;
use event::{EventFlags, RawEventQueue};
use fdt::{Fdt, node::FdtNode};
use fdt::{node::FdtNode, Fdt};
use redox_scheme::{RequestKind, Response, SignalBehavior, Socket, V2};
use syscall::{
data::{Event, Packet}, error::{Error, ENODEV}, flag::EVENT_READ, io::Io, scheme::SchemeBlockMut, EAGAIN, EINTR, EWOULDBLOCK
data::{Event, Packet},
error::{Error, ENODEV},
flag::EVENT_READ,
io::Io,
scheme::SchemeBlockMut,
EAGAIN, EINTR, EWOULDBLOCK,
};
use crate::scheme::DiskScheme;
mod sd;
mod scheme;
mod sd;
#[cfg(target_os = "redox")]
fn get_dtb() -> Vec<u8> {
@@ -45,12 +54,23 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let compat_node = fdt.find_compatible(&with).unwrap();
let reg = compat_node.reg().unwrap().next().unwrap();
let reg_size = reg.size.unwrap();
println!("DeviceMemory start = 0x{:08x}, size = 0x{:08x}", reg.starting_address as usize, reg_size);
println!(
"DeviceMemory start = 0x{:08x}, size = 0x{:08x}",
reg.starting_address as usize, reg_size
);
let addr = unsafe {
common::physmap(reg.starting_address as usize, reg_size, common::Prot::RW, common::MemoryType::DeviceMemory)
.expect("bcm2835-sdhcid: failed to map address") as usize
common::physmap(
reg.starting_address as usize,
reg_size,
common::Prot::RW,
common::MemoryType::DeviceMemory,
)
.expect("bcm2835-sdhcid: failed to map address") as usize
};
println!("ioremap 0x{:08x} to 0x{:08x} 2222", reg.starting_address as usize, addr);
println!(
"ioremap 0x{:08x} to 0x{:08x} 2222",
reg.starting_address as usize, addr
);
let mut sdhci = sd::SdHostCtrl::new(addr);
unsafe {
sdhci.init();
@@ -80,12 +100,13 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
*/
}
let scheme_name = "disk.mmc";
let socket_fd = Socket::<V2>::create(&scheme_name).expect("mmcd: failed to create disk scheme");
let mut event_queue = RawEventQueue::new().expect("mmcd: failed to open event file");
event_queue.subscribe(socket_fd.inner().raw(), 0, EventFlags::READ).expect("mmcd: failed to event disk scheme");
event_queue
.subscribe(socket_fd.inner().raw(), 0, EventFlags::READ)
.expect("mmcd: failed to event disk scheme");
libredox::call::setrens(0, 0).expect("mmcd: failed to enter null namespace");
daemon.ready().expect("mmcd: failed to notify parent");
@@ -97,26 +118,36 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut scheme = DiskScheme::new(scheme_name.to_string(), disks);
'outer: loop {
let Some(event) = event_queue.next().transpose().expect("mmcd: failed to read event file") else {
let Some(event) = event_queue
.next()
.transpose()
.expect("mmcd: failed to read event file")
else {
break;
};
if event.fd == socket_fd.inner().raw() {
loop {
let req = match socket_fd.next_request(SignalBehavior::Interrupt) {
Ok(None) => break 'outer,
Ok(Some(r)) => if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
},
Err(err) => if matches!(err.errno, EAGAIN | EWOULDBLOCK | EINTR) {
break;
} else {
panic!("mmcd: failed to read disk scheme: {}", err);
Ok(Some(r)) => {
if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
}
}
Err(err) => {
if matches!(err.errno, EAGAIN | EWOULDBLOCK | EINTR) {
break;
} else {
panic!("mmcd: failed to read disk scheme: {}", err);
}
}
};
if let Some(resp) = req.handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("mmcd: failed to write disk scheme");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("mmcd: failed to write disk scheme");
} else {
todo.push(req);
}
@@ -129,14 +160,20 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut i = 0;
while i < todo.len() {
if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("mmcd: failed to write disk scheme");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("mmcd: failed to write disk scheme");
} else {
i += 1;
}
}
for req in todo.drain(..) {
socket_fd.write_response(Response::new(&req, Err(Error::new(ENODEV))), SignalBehavior::Restart)
socket_fd
.write_response(
Response::new(&req, Err(Error::new(ENODEV))),
SignalBehavior::Restart,
)
.expect("mmcd: failed to write disk scheme");
}
}
+90 -39
View File
@@ -1,12 +1,12 @@
use std::collections::BTreeMap;
use std::str;
use std::fmt::Write;
use std::str;
use std::sync::{Arc, Mutex};
use driver_block::{Disk, DiskWrapper};
use syscall::schemev2::NewFdFlags;
use syscall::{
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Stat, MODE_DIR,
Error, Result, Stat, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, MODE_DIR,
MODE_FILE, O_DIRECTORY, O_STAT,
};
@@ -14,8 +14,8 @@ use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
#[derive(Clone)]
enum Handle {
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
Partition(usize, u32), // Disk index, partition index
}
@@ -23,16 +23,20 @@ pub struct DiskScheme {
scheme_name: String,
disks: Box<[DiskWrapper]>,
handles: BTreeMap<usize, Handle>,
next_id: usize
next_id: usize,
}
impl DiskScheme {
pub fn new(scheme_name: String, disks: Vec<Box<dyn Disk>>) -> DiskScheme {
DiskScheme {
scheme_name,
disks: disks.into_iter().map(DiskWrapper::new).collect::<Vec<_>>().into_boxed_slice(),
disks: disks
.into_iter()
.map(DiskWrapper::new)
.collect::<Vec<_>>()
.into_boxed_slice(),
handles: BTreeMap::new(),
next_id: 0
next_id: 0,
}
}
@@ -40,19 +44,25 @@ impl DiskScheme {
fn check_locks(&self, disk_i: usize, part_i_opt: Option<u32>) -> Result<()> {
for (_, handle) in self.handles.iter() {
match handle {
Handle::Disk(i) => if disk_i == *i {
return Err(Error::new(ENOLCK));
},
Handle::Partition(i, p) => if disk_i == *i {
match part_i_opt {
Some(part_i) => if part_i == *p {
return Err(Error::new(ENOLCK));
},
None => {
return Err(Error::new(ENOLCK));
Handle::Disk(i) => {
if disk_i == *i {
return Err(Error::new(ENOLCK));
}
}
Handle::Partition(i, p) => {
if disk_i == *i {
match part_i_opt {
Some(part_i) => {
if part_i == *p {
return Err(Error::new(ENOLCK));
}
}
None => {
return Err(Error::new(ENOLCK));
}
}
}
},
}
_ => (),
}
}
@@ -72,7 +82,7 @@ impl SchemeBlockMut for DiskScheme {
write!(list, "{}\n", disk_index).unwrap();
if disk.pt.is_none() {
continue
continue;
}
for part_index in 0..disk.pt.as_ref().unwrap().partitions.len() {
write!(list, "{}p{}\n", disk_index, part_index).unwrap();
@@ -82,7 +92,10 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::List(list.into_bytes()));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
Err(Error::new(EISDIR))
}
@@ -96,7 +109,15 @@ impl SchemeBlockMut for DiskScheme {
let p = part_id_str.parse::<u32>().or(Err(Error::new(ENOENT)))?;
if let Some(disk) = self.disks.get(i) {
if disk.pt.is_none() || disk.pt.as_ref().unwrap().partitions.get(p as usize).is_none() {
if disk.pt.is_none()
|| disk
.pt
.as_ref()
.unwrap()
.partitions
.get(p as usize)
.is_none()
{
return Err(Error::new(ENOENT));
}
@@ -105,7 +126,10 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Partition(i, p));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
Err(Error::new(ENOENT))
}
@@ -118,7 +142,10 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Disk(i));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
Err(Error::new(ENOENT))
}
@@ -129,7 +156,7 @@ impl SchemeBlockMut for DiskScheme {
}
fn dup(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
if ! buf.is_empty() {
if !buf.is_empty() {
return Err(Error::new(EINVAL));
}
@@ -150,7 +177,7 @@ impl SchemeBlockMut for DiskScheme {
stat.st_mode = MODE_DIR;
stat.st_size = data.len() as u64;
Ok(Some(0))
},
}
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
stat.st_mode = MODE_FILE;
@@ -162,7 +189,10 @@ impl SchemeBlockMut for DiskScheme {
let disk = self.disks.get_mut(disk_id).ok_or(Error::new(EBADF))?;
let size = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
partition.size
};
@@ -220,14 +250,23 @@ impl SchemeBlockMut for DiskScheme {
Ok(Some(i))
}
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _flags: u32) -> Result<Option<usize>> {
fn read(
&mut self,
id: usize,
buf: &mut [u8],
offset: u64,
_flags: u32,
) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle) => {
let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]);
let src = usize::try_from(offset)
.ok()
.and_then(|o| handle.get(o..))
.unwrap_or(&[]);
let bytes = src.len().min(buf.len());
buf[..bytes].copy_from_slice(&src[..bytes]);
Ok(Some(bytes))
},
}
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
@@ -242,7 +281,10 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
let abs_block = partition.start_lba + rel_block;
if rel_block >= partition.size {
@@ -258,9 +300,7 @@ impl SchemeBlockMut for DiskScheme {
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(_) => {
Err(Error::new(EBADF))
},
Handle::List(_) => Err(Error::new(EBADF)),
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
@@ -275,7 +315,10 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
let abs_block = partition.start_lba + rel_block;
if rel_block >= partition.size {
@@ -291,22 +334,30 @@ impl SchemeBlockMut for DiskScheme {
fn fsize(&mut self, id: usize) -> Result<Option<u64>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle) => {
Ok(Some(handle.len() as u64))
},
Handle::List(ref mut handle) => Ok(Some(handle.len() as u64)),
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
Ok(Some(disk.size()))
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let block_count = disk.pt.as_ref().ok_or(Error::new(EBADF))?.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?.size;
let block_count = disk
.pt
.as_ref()
.ok_or(Error::new(EBADF))?
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?
.size;
Ok(Some(u64::from(disk.block_length()?) * block_count))
}
}
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
self.handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(Some(0)))
self.handles
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(Some(0)))
}
}
+67 -52
View File
@@ -26,7 +26,6 @@ pub(crate) unsafe fn wait_msec(mut n: usize) {
asm!("mrs {0}, cntfrq_el0", out(reg) f);
asm!("mrs {0}, cntpct_el0", out(reg) t);
t += ((f / 1000) * n) / 1000;
loop {
@@ -34,7 +33,7 @@ pub(crate) unsafe fn wait_msec(mut n: usize) {
if r >= t {
break;
}
};
}
}
#[cfg(target_arch = "x86_64")]
@@ -60,15 +59,13 @@ const CMD_STOP_TRANS: u32 = 0x0c03_0000;
const CMD_READ_SINGLE: u32 = 0x1122_0010;
const CMD_READ_MULTI: u32 = 0x1222_0032;
const CMD_SET_BLOCKCNT: u32 = 0x1702_0000;
const CMD_WRITE_SINGLE:u32 = 0x1822_0000;
const CMD_WRITE_MULTI:u32 = 0x1922_0022;
const CMD_WRITE_SINGLE: u32 = 0x1822_0000;
const CMD_WRITE_MULTI: u32 = 0x1922_0022;
const CMD_APP_CMD: u32 = 0x3700_0000;
const CMD_SET_BUS_WIDTH: u32 = 0x0602_0000|CMD_NEED_APP;
const CMD_SEND_OP_COND: u32 = 0x2902_0000|CMD_NEED_APP;
const CMD_SEND_SCR: u32 = 0x3322_0010|CMD_NEED_APP;
const CMD_SET_BUS_WIDTH: u32 = 0x0602_0000 | CMD_NEED_APP;
const CMD_SEND_OP_COND: u32 = 0x2902_0000 | CMD_NEED_APP;
const CMD_SEND_SCR: u32 = 0x3322_0010 | CMD_NEED_APP;
//STATUS register settings
const SR_READ_AVAILABLE: u32 = 0x0000_0800;
@@ -93,7 +90,6 @@ const C1_CLK_EN: u32 = 0x0000_0004;
const C1_CLK_STABLE: u32 = 0x0000_0002;
const C1_CLK_INTLEN: u32 = 0x0000_0001;
//INTERRUPT register settings
const INT_DATA_TIMEOUT: u32 = 0x0010_0000;
const INT_CMD_TIMEOUT: u32 = 0x0001_0000;
@@ -168,7 +164,7 @@ pub struct SdHostCtrlRegs {
_rsvd: [Mmio<u32>; 47],
//Slot Interrupt Status and Version
slotisr_ver: Mmio<u32>
slotisr_ver: Mmio<u32>,
}
//TODO: refactor, sd/sdhci/bcmh2835-sdhci three different modules.
@@ -180,13 +176,13 @@ pub struct SdHostCtrl {
rca: u32, //relative card address
scr: [u32; 2],
ocr: u32,
size: u64
size: u64,
}
impl SdHostCtrl {
pub fn new(address: usize) -> Self {
SdHostCtrl {
regs: RwLock::new(unsafe { &mut *(address as *mut SdHostCtrlRegs)}),
regs: RwLock::new(unsafe { &mut *(address as *mut SdHostCtrlRegs) }),
host_spec_ver: 0,
cid: [0; 4],
csd: [0; 4],
@@ -207,15 +203,14 @@ impl SdHostCtrl {
reg_val = regs.control1.read();
regs.control1.write(reg_val | C1_SRST_HC);
let mut cnt = 1000;
while (cnt >= 0) &&
((regs.control1.read() & C1_SRST_HC) == C1_SRST_HC) {
while (cnt >= 0) && ((regs.control1.read() & C1_SRST_HC) == C1_SRST_HC) {
cnt -= 1;
wait_msec(10);
}
if cnt < 0 {
println!("ERROR: failed to reset EMMC");
return ;
return;
}
println!("EMMC: reset OK");
reg_val = regs.control1.read();
@@ -226,7 +221,7 @@ impl SdHostCtrl {
{
if let Err(_) = self.set_clock(40_0000) {
println!("ERROR: failed to set clock {}", 40_0000);
return ;
return;
}
}
@@ -236,12 +231,12 @@ impl SdHostCtrl {
if let Err(_) = self.sd_cmd(CMD_GO_IDLE, 0) {
println!("failed to go idle");
return ;
return;
}
if let Err(_) = self.sd_cmd(CMD_SEND_IF_COND, 0x0000_01aa) {
println!("failed to send if cond");
return ;
return;
}
cnt = 6;
@@ -268,21 +263,25 @@ impl SdHostCtrl {
print!("\n");
} else {
println!("ERROR: EMMC ACMD41 returned error");
return ;
return;
}
}
if (reg_val & ACMD41_CMD_COMPLETE) == 0 || cnt <= 0 {
println!("ACMD41 TIMEOUT");
return ;
return;
}
if (reg_val & ACMD41_VOLTAGE) == 0 {
println!("ACMD41 VOLTAGE NOT FOUND!");
return ;
return;
}
let ccs = if (reg_val & ACMD41_CMD_CCS) != 0 { SCR_SUPP_CCS } else { 0 };
let ccs = if (reg_val & ACMD41_CMD_CCS) != 0 {
SCR_SUPP_CCS
} else {
0
};
if let Err(_) = self.sd_cmd(CMD_ALL_SEND_CID, 0) {
println!("CMD_ALL_SEND_CID ERROR, IGNORE!");
@@ -294,7 +293,7 @@ impl SdHostCtrl {
if let Err(_) = self.sd_cmd(CMD_SEND_CSD, sd_rca) {
println!("failed to get csd");
return ;
return;
}
let (csize, cmult) = if (self.ocr & ACMD41_CMD_CCS) != 0 {
@@ -309,20 +308,19 @@ impl SdHostCtrl {
self.size = ((csize + 1) << (cmult + 2)) * 512;
println!("mmc size = 0x{:08x}", self.size);
if let Err(_) = self.set_clock(2500_0000) {
println!("failed to set clock 2500_0000 Hz");
return ;
return;
}
if let Err(_) = self.sd_cmd(CMD_CARD_SELECT, sd_rca) {
println!("failed to CMD_CARD_SELECT 0x{:08x}", sd_rca);
return ;
return;
}
if let Err(_) = self.sd_status(SR_DAT_INHIBIT) {
println!("SR_DAT_INHIBIT return");
return ;
return;
}
let regs = self.regs.get_mut().unwrap();
@@ -330,12 +328,12 @@ impl SdHostCtrl {
if let Err(_) = self.sd_cmd(CMD_SEND_SCR, 0) {
println!("failed to CMD_SEND_SCR");
return ;
return;
}
if let Err(_) = self.sd_int(INT_READ_RDY) {
println!("failed to INT_READ_RDY");
return ;
return;
}
cnt = 10000;
@@ -354,13 +352,13 @@ impl SdHostCtrl {
}
if i != 2 {
println!("SD TIMEOUT FOR SCR[; 2]");
return ;
return;
}
if (self.scr[0] & SCR_SD_BUS_WIDTH_4) != 0 {
if let Err(_) = self.sd_cmd(CMD_SET_BUS_WIDTH, sd_rca | 2) {
println!("failed to set bus width, {}", sd_rca | 2);
return ;
return;
}
let regs = self.regs.get_mut().unwrap();
regs.control0.write(C0_HCTL_DWITDH);
@@ -411,13 +409,32 @@ impl SdHostCtrl {
if x == 0 {
s = 0;
} else {
if (x & 0xffff_0000) == 0 { x <<= 16; s -= 16; }
if (x & 0xff00_0000) == 0 { x <<= 8; s -= 8; }
if (x & 0xf000_0000) == 0 { x <<= 4; s -= 4; }
if (x & 0xc000_0000) == 0 { x <<= 2; s -= 2; }
if (x & 0x8000_0000) == 0 { x <<= 1; s -= 1; }
if s > 0 { s -= 1; }
if s > 7 { s = 7; }
if (x & 0xffff_0000) == 0 {
x <<= 16;
s -= 16;
}
if (x & 0xff00_0000) == 0 {
x <<= 8;
s -= 8;
}
if (x & 0xf000_0000) == 0 {
x <<= 4;
s -= 4;
}
if (x & 0xc000_0000) == 0 {
x <<= 2;
s -= 2;
}
if (x & 0x8000_0000) == 0 {
x <<= 1;
s -= 1;
}
if s > 0 {
s -= 1;
}
if s > 7 {
s = 7;
}
}
let mut d = 0;
if self.host_spec_ver > HOST_SPEC_V2 {
@@ -437,7 +454,7 @@ impl SdHostCtrl {
h = (d & 0x300) >> 2;
}
d = ( ((d & 0xff) << 8)| h);
d = (((d & 0xff) << 8) | h);
reg_val = regs.control1.read() & 0xffff_003f;
regs.control1.write(reg_val | d);
wait_msec(10);
@@ -550,7 +567,6 @@ impl SdHostCtrl {
} else {
return Ok(reg_val & CMD_ERRORS_MASK);
}
}
pub unsafe fn sd_status(&mut self, mask: u32) -> Result<()> {
@@ -647,7 +663,8 @@ impl SdHostCtrl {
cnt += 1;
}
if num > 1 && (self.scr[0] & SCR_SUPP_SET_BLKCNT) == 0 && (self.scr[0] & SCR_SUPP_CCS) != 0 {
if num > 1 && (self.scr[0] & SCR_SUPP_SET_BLKCNT) == 0 && (self.scr[0] & SCR_SUPP_CCS) != 0
{
self.sd_cmd(CMD_STOP_TRANS, 0).unwrap();
}
Ok((num * 512) as usize)
@@ -707,7 +724,8 @@ impl SdHostCtrl {
return Err(Error::new(EINVAL));
}
if num > 1 && (self.scr[0] & SCR_SUPP_SET_BLKCNT) == 0 && (self.scr[0] & SCR_SUPP_CCS) != 0 {
if num > 1 && (self.scr[0] & SCR_SUPP_SET_BLKCNT) == 0 && (self.scr[0] & SCR_SUPP_CCS) != 0
{
self.sd_cmd(CMD_STOP_TRANS, 0).unwrap();
}
Ok((num * 512) as usize)
@@ -724,10 +742,9 @@ impl Disk for SdHostCtrl {
self.size
}
fn read(&mut self, block:u64, buffer: &mut [u8]) -> Result<Option<usize>> {
fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result<Option<usize>> {
if (buffer.len() % 512) != 0 {
println!("buffer.len {} should be aligned to {}",
buffer.len(), 512);
println!("buffer.len {} should be aligned to {}", buffer.len(), 512);
return Err(Error::new(EINVAL));
}
let u32_len = buffer.len() / core::mem::size_of::<u32>();
@@ -739,14 +756,13 @@ impl Disk for SdHostCtrl {
};
match ret {
Ok(cnt) => Ok(Some(cnt)),
Err(err) => Err(err)
Err(err) => Err(err),
}
}
fn write(&mut self, block:u64, buffer: &[u8]) -> Result<Option<usize>> {
fn write(&mut self, block: u64, buffer: &[u8]) -> Result<Option<usize>> {
if (buffer.len() % 512) != 0 {
println!("buffer.len {} should be aligned to {}",
buffer.len(), 512);
println!("buffer.len {} should be aligned to {}", buffer.len(), 512);
return Err(Error::new(EINVAL));
}
let u32_len = buffer.len() / core::mem::size_of::<u32>();
@@ -758,12 +774,11 @@ impl Disk for SdHostCtrl {
};
match ret {
Ok(cnt) => Ok(Some(cnt)),
Err(err) => Err(err)
Err(err) => Err(err),
}
}
fn block_length(&mut self) -> Result<u32> {
Ok(512)
}
}
+28 -9
View File
@@ -80,12 +80,14 @@ impl Channel {
prdt: unsafe {
Dma::zeroed(
//TODO: PhysBox::new_in_32bit_space(4096)?
)?.assume_init()
)?
.assume_init()
},
buf: unsafe {
Dma::zeroed(
//TODO: PhysBox::new_in_32bit_space(16 * 4096)?
)?.assume_init()
)?
.assume_init()
},
})
}
@@ -142,7 +144,12 @@ impl Channel {
break;
}
if start.elapsed() >= TIMEOUT {
log::error!("line {} polling {} timeout with status 0x{:02X}", line, if read { "read" } else { "write" }, status);
log::error!(
"line {} polling {} timeout with status 0x{:02X}",
line,
if read { "read" } else { "write" },
status
);
return Err(Error::new(EIO));
}
thread::yield_now();
@@ -181,7 +188,13 @@ impl Disk for AtaDisk {
let sectors = (chunk.len() + 511) / 512;
assert!(sectors <= 128);
log::trace!("IDE read chan {} dev {} block {:#x} count {:#x}", self.chan_i, self.dev, block, sectors);
log::trace!(
"IDE read chan {} dev {} block {:#x} count {:#x}",
self.chan_i,
self.dev,
block,
sectors
);
let mut chan = self.chan.lock().unwrap();
@@ -315,7 +328,13 @@ impl Disk for AtaDisk {
let sectors = (chunk.len() + 511) / 512;
assert!(sectors <= 128);
log::trace!("IDE write chan {} dev {} block {:#x} count {:#x}", self.chan_i, self.dev, block, sectors);
log::trace!(
"IDE write chan {} dev {} block {:#x} count {:#x}",
self.chan_i,
self.dev,
block,
sectors
);
let mut chan = self.chan.lock().unwrap();
@@ -424,10 +443,10 @@ impl Disk for AtaDisk {
for i in 0..128 {
chan.data32.write(
((chunk[sector * 512 + i * 4 + 0] as u32) << 0) |
((chunk[sector * 512 + i * 4 + 1] as u32) << 8) |
((chunk[sector * 512 + i * 4 + 2] as u32) << 16) |
((chunk[sector * 512 + i * 4 + 3] as u32) << 24)
((chunk[sector * 512 + i * 4 + 0] as u32) << 0)
| ((chunk[sector * 512 + i * 4 + 1] as u32) << 8)
| ((chunk[sector * 512 + i * 4 + 2] as u32) << 16)
| ((chunk[sector * 512 + i * 4 + 3] as u32) << 24),
);
}
}
+76 -44
View File
@@ -1,3 +1,4 @@
use common::io::Io as _;
use driver_block::Disk;
use event::{EventFlags, RawEventQueue};
use libredox::flag;
@@ -12,9 +13,12 @@ use std::{
thread::{self, sleep},
time::Duration,
};
use common::io::Io as _;
use syscall::{
data::{Event, Packet}, error::{Error, ENODEV}, flag::EVENT_READ, scheme::SchemeBlockMut, EAGAIN, EINTR, EWOULDBLOCK
data::{Event, Packet},
error::{Error, ENODEV},
flag::EVENT_READ,
scheme::SchemeBlockMut,
EAGAIN, EINTR, EWOULDBLOCK,
};
use crate::{
@@ -164,10 +168,10 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
}
let mut sectors = (dest[100] as u64) |
((dest[101] as u64) << 16) |
((dest[102] as u64) << 32) |
((dest[103] as u64) << 48);
let mut sectors = (dest[100] as u64)
| ((dest[101] as u64) << 16)
| ((dest[102] as u64) << 32)
| ((dest[103] as u64) << 48);
let lba_bits = if sectors == 0 {
sectors = (dest[60] as u64) | ((dest[61] as u64) << 16);
@@ -196,21 +200,23 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
let scheme_name = format!("disk.{}", name);
let socket_fd = Socket::<V2>::nonblock(&scheme_name)
.expect("ided: failed to create disk scheme");
let socket_fd =
Socket::<V2>::nonblock(&scheme_name).expect("ided: failed to create disk scheme");
let primary_irq_fd = libredox::call::open(
&format!("/scheme/irq/{}", primary_irq),
flag::O_RDWR | flag::O_NONBLOCK,
0,
).expect("ided: failed to open irq file");
)
.expect("ided: failed to open irq file");
let mut primary_irq_file = unsafe { File::from_raw_fd(primary_irq_fd as RawFd) };
let secondary_irq_fd = libredox::call::open(
&format!("/scheme/irq/{}", secondary_irq),
flag::O_RDWR | flag::O_NONBLOCK,
0,
).expect("ided: failed to open irq file");
)
.expect("ided: failed to open irq file");
let mut secondary_irq_file = unsafe { File::from_raw_fd(secondary_irq_fd as RawFd) };
let mut event_queue = RawEventQueue::new().expect("ided: failed to open event file");
@@ -219,63 +225,75 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
daemon.ready().expect("ided: failed to notify parent");
event_queue.subscribe(
socket_fd.inner().raw(),
0,
EventFlags::READ,
).expect("ided: failed to event disk scheme");
event_queue
.subscribe(socket_fd.inner().raw(), 0, EventFlags::READ)
.expect("ided: failed to event disk scheme");
event_queue.subscribe(
primary_irq_fd,
0,
EventFlags::READ,
).expect("ided: failed to event irq scheme");
event_queue
.subscribe(primary_irq_fd, 0, EventFlags::READ)
.expect("ided: failed to event irq scheme");
event_queue.subscribe(
secondary_irq_fd,
0,
EventFlags::READ,
).expect("ided: failed to event irq scheme");
event_queue
.subscribe(secondary_irq_fd, 0, EventFlags::READ)
.expect("ided: failed to event irq scheme");
let mut scheme = DiskScheme::new(scheme_name, chans, disks);
let mut todo = Vec::new();
'outer: loop {
let Some(event) = event_queue.next().transpose().expect("ided: failed to read event file") else {
let Some(event) = event_queue
.next()
.transpose()
.expect("ided: failed to read event file")
else {
break;
};
if event.fd == socket_fd.inner().raw() {
loop {
let req = match socket_fd.next_request(SignalBehavior::Interrupt) {
Ok(None) => break 'outer,
Ok(Some(r)) => if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
},
Err(err) => if matches!(err.errno, EAGAIN | EWOULDBLOCK | EINTR) {
break;
} else {
panic!("ided: failed to read disk scheme: {}", err);
Ok(Some(r)) => {
if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
}
}
Err(err) => {
if matches!(err.errno, EAGAIN | EWOULDBLOCK | EINTR) {
break;
} else {
panic!("ided: failed to read disk scheme: {}", err);
}
}
};
if let Some(resp) = req.handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("ided: failed to write disk scheme");
} else {
todo.push(req);
}
}
} else if event.fd == primary_irq_fd {
let mut irq = [0; 8];
if primary_irq_file.read(&mut irq).expect("ided: failed to read irq file") >= irq.len() {
if primary_irq_file
.read(&mut irq)
.expect("ided: failed to read irq file")
>= irq.len()
{
if scheme.irq(0) {
primary_irq_file.write(&irq).expect("ided: failed to write irq file");
primary_irq_file
.write(&irq)
.expect("ided: failed to write irq file");
// Handle todos in order to finish previous packets if possible
let mut i = 0;
while i < todo.len() {
if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("ided: failed to write disk scheme");
} else {
i += 1;
}
@@ -284,15 +302,23 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
} else if event.fd == secondary_irq_fd {
let mut irq = [0; 8];
if secondary_irq_file.read(&mut irq).expect("ided: failed to read irq file") >= irq.len() {
if secondary_irq_file
.read(&mut irq)
.expect("ided: failed to read irq file")
>= irq.len()
{
if scheme.irq(1) {
secondary_irq_file.write(&irq).expect("ided: failed to write irq file");
secondary_irq_file
.write(&irq)
.expect("ided: failed to write irq file");
// Handle todos in order to finish previous packets if possible
let mut i = 0;
while i < todo.len() {
if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("ided: failed to write disk scheme");
} else {
i += 1;
}
@@ -307,14 +333,20 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut i = 0;
while i < todo.len() {
if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("ided: failed to write disk scheme");
} else {
i += 1;
}
}
for req in todo.drain(..) {
socket_fd.write_response(Response::new(&req, Err(Error::new(ENODEV))), SignalBehavior::Restart)
socket_fd
.write_response(
Response::new(&req, Err(Error::new(ENODEV))),
SignalBehavior::Restart,
)
.expect("ided: failed to write disk scheme");
}
}
+96 -41
View File
@@ -1,22 +1,22 @@
use std::collections::BTreeMap;
use std::str;
use std::fmt::Write;
use std::str;
use std::sync::{Arc, Mutex};
use driver_block::{Disk, DiskWrapper};
use syscall::schemev2::NewFdFlags;
use syscall::{
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Stat, MODE_DIR,
Error, Result, Stat, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, MODE_DIR,
MODE_FILE, O_DIRECTORY, O_STAT,
};
use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
use crate::ide::Channel;
use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
#[derive(Clone)]
enum Handle {
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
Partition(usize, u32), // Disk index, partition index
}
@@ -25,17 +25,25 @@ pub struct DiskScheme {
chans: Box<[Arc<Mutex<Channel>>]>,
disks: Box<[DiskWrapper]>,
handles: BTreeMap<usize, Handle>,
next_id: usize
next_id: usize,
}
impl DiskScheme {
pub fn new(scheme_name: String, chans: Vec<Arc<Mutex<Channel>>>, disks: Vec<Box<dyn Disk>>) -> DiskScheme {
pub fn new(
scheme_name: String,
chans: Vec<Arc<Mutex<Channel>>>,
disks: Vec<Box<dyn Disk>>,
) -> DiskScheme {
DiskScheme {
scheme_name,
chans: chans.into_boxed_slice(),
disks: disks.into_iter().map(DiskWrapper::new).collect::<Vec<_>>().into_boxed_slice(),
disks: disks
.into_iter()
.map(DiskWrapper::new)
.collect::<Vec<_>>()
.into_boxed_slice(),
handles: BTreeMap::new(),
next_id: 0
next_id: 0,
}
}
@@ -49,19 +57,25 @@ impl DiskScheme {
fn check_locks(&self, disk_i: usize, part_i_opt: Option<u32>) -> Result<()> {
for (_, handle) in self.handles.iter() {
match handle {
Handle::Disk(i) => if disk_i == *i {
return Err(Error::new(ENOLCK));
},
Handle::Partition(i, p) => if disk_i == *i {
match part_i_opt {
Some(part_i) => if part_i == *p {
return Err(Error::new(ENOLCK));
},
None => {
return Err(Error::new(ENOLCK));
Handle::Disk(i) => {
if disk_i == *i {
return Err(Error::new(ENOLCK));
}
}
Handle::Partition(i, p) => {
if disk_i == *i {
match part_i_opt {
Some(part_i) => {
if part_i == *p {
return Err(Error::new(ENOLCK));
}
}
None => {
return Err(Error::new(ENOLCK));
}
}
}
},
}
_ => (),
}
}
@@ -81,7 +95,7 @@ impl SchemeBlockMut for DiskScheme {
write!(list, "{}\n", disk_index).unwrap();
if disk.pt.is_none() {
continue
continue;
}
for part_index in 0..disk.pt.as_ref().unwrap().partitions.len() {
write!(list, "{}p{}\n", disk_index, part_index).unwrap();
@@ -91,7 +105,10 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::List(list.into_bytes()));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
Err(Error::new(EISDIR))
}
@@ -105,7 +122,15 @@ impl SchemeBlockMut for DiskScheme {
let p = part_id_str.parse::<u32>().or(Err(Error::new(ENOENT)))?;
if let Some(disk) = self.disks.get(i) {
if disk.pt.is_none() || disk.pt.as_ref().unwrap().partitions.get(p as usize).is_none() {
if disk.pt.is_none()
|| disk
.pt
.as_ref()
.unwrap()
.partitions
.get(p as usize)
.is_none()
{
return Err(Error::new(ENOENT));
}
@@ -114,7 +139,10 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Partition(i, p));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
Err(Error::new(ENOENT))
}
@@ -127,7 +155,10 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Disk(i));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
Err(Error::new(ENOENT))
}
@@ -138,7 +169,7 @@ impl SchemeBlockMut for DiskScheme {
}
fn dup(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
if ! buf.is_empty() {
if !buf.is_empty() {
return Err(Error::new(EINVAL));
}
@@ -159,7 +190,7 @@ impl SchemeBlockMut for DiskScheme {
stat.st_mode = MODE_DIR;
stat.st_size = data.len() as u64;
Ok(Some(0))
},
}
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
stat.st_mode = MODE_FILE;
@@ -171,7 +202,10 @@ impl SchemeBlockMut for DiskScheme {
let disk = self.disks.get_mut(disk_id).ok_or(Error::new(EBADF))?;
let size = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
partition.size
};
@@ -229,14 +263,23 @@ impl SchemeBlockMut for DiskScheme {
Ok(Some(i))
}
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _flags: u32) -> Result<Option<usize>> {
fn read(
&mut self,
id: usize,
buf: &mut [u8],
offset: u64,
_flags: u32,
) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle) => {
let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]);
let src = usize::try_from(offset)
.ok()
.and_then(|o| handle.get(o..))
.unwrap_or(&[]);
let bytes = src.len().min(buf.len());
buf[..bytes].copy_from_slice(&src[..bytes]);
Ok(Some(bytes))
},
}
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
@@ -251,7 +294,10 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
let abs_block = partition.start_lba + rel_block;
if rel_block >= partition.size {
@@ -267,9 +313,7 @@ impl SchemeBlockMut for DiskScheme {
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(_) => {
Err(Error::new(EBADF))
},
Handle::List(_) => Err(Error::new(EBADF)),
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
@@ -284,7 +328,10 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
let partition = pt.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?;
let partition = pt
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
let abs_block = partition.start_lba + rel_block;
if rel_block >= partition.size {
@@ -300,22 +347,30 @@ impl SchemeBlockMut for DiskScheme {
fn fsize(&mut self, id: usize) -> Result<Option<u64>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle) => {
Ok(Some(handle.len() as u64))
},
Handle::List(ref mut handle) => Ok(Some(handle.len() as u64)),
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
Ok(Some(disk.size()))
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let block_count = disk.pt.as_ref().ok_or(Error::new(EBADF))?.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?.size;
let block_count = disk
.pt
.as_ref()
.ok_or(Error::new(EBADF))?
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?
.size;
Ok(Some(u64::from(disk.block_length()?) * block_count))
}
}
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
self.handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(Some(0)))
self.handles
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(Some(0)))
}
}
+50 -29
View File
@@ -12,12 +12,12 @@ use libredox::flag;
use redox_scheme::{CallerCtx, OpenResult, RequestKind, SchemeMut, SignalBehavior, Socket, V2};
use syscall::data::Stat;
use syscall::schemev2::NewFdFlags;
use syscall::error::*;
use syscall::flag::{MODE_DIR, MODE_FILE};
use syscall::schemev2::NewFdFlags;
use syscall::PAGE_SIZE;
use anyhow::{anyhow, Context, bail};
use anyhow::{anyhow, bail, Context};
const LIST: [u8; 2] = *b"0\n";
@@ -46,7 +46,10 @@ impl DiskScheme {
let mut size = 0;
// TODO: handle error
for line in std::fs::read_to_string("/scheme/sys/env").context("failed to read env")?.lines() {
for line in std::fs::read_to_string("/scheme/sys/env")
.context("failed to read env")?
.lines()
{
let mut parts = line.splitn(2, '=');
let name = parts.next().unwrap_or("");
let value = parts.next().unwrap_or("");
@@ -61,11 +64,18 @@ impl DiskScheme {
}
if phys == 0 || size == 0 {
bail!("either livedisk phys ({}) or size ({}) was zero", phys, size);
bail!(
"either livedisk phys ({}) or size ({}) was zero",
phys,
size
);
}
let start = phys.div_floor(PAGE_SIZE) * PAGE_SIZE;
let end = phys.checked_add(size).context("phys + size overflow")?.next_multiple_of(PAGE_SIZE);
let end = phys
.checked_add(size)
.context("phys + size overflow")?
.next_multiple_of(PAGE_SIZE);
let size = end - start;
let the_data = unsafe {
@@ -77,23 +87,24 @@ impl DiskScheme {
length: size,
prot: flag::PROT_READ | flag::PROT_WRITE,
flags: flag::MAP_SHARED,
}).map_err(|err| anyhow!("failed to mmap livedisk: {}", err))?;
})
.map_err(|err| anyhow!("failed to mmap livedisk: {}", err))?;
std::slice::from_raw_parts_mut(base as *mut u8, size)
};
Ok(DiskScheme {
the_data,
})
Ok(DiskScheme { the_data })
}
}
impl SchemeMut for DiskScheme {
fn fsize(&mut self, id: usize) -> Result<u64> {
Ok(match HandleType::try_from_raw(id).ok_or(Error::new(EBADF))? {
HandleType::TopLevel => LIST.len() as u64,
HandleType::TheData => self.the_data.len() as u64,
})
Ok(
match HandleType::try_from_raw(id).ok_or(Error::new(EBADF))? {
HandleType::TopLevel => LIST.len() as u64,
HandleType::TheData => self.the_data.len() as u64,
},
)
}
fn fcntl(&mut self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
@@ -116,12 +127,8 @@ impl SchemeMut for DiskScheme {
Ok(OpenResult::ThisScheme {
number: match path_trimmed {
"" => {
HandleType::TopLevel as usize
},
"0" => {
HandleType::TheData as usize
}
"" => HandleType::TopLevel as usize,
"0" => HandleType::TheData as usize,
_ => return Err(Error::new(ENOENT)),
},
flags: NewFdFlags::POSITIONED,
@@ -133,7 +140,10 @@ impl SchemeMut for DiskScheme {
HandleType::TopLevel => &LIST,
};
let src = usize::try_from(offset).ok().and_then(|o| data.get(o..)).unwrap_or(&[]);
let src = usize::try_from(offset)
.ok()
.and_then(|o| data.get(o..))
.unwrap_or(&[]);
let byte_count = std::cmp::min(src.len(), buf.len());
buf[..byte_count].copy_from_slice(&src[..byte_count]);
Ok(byte_count)
@@ -144,7 +154,10 @@ impl SchemeMut for DiskScheme {
HandleType::TopLevel => return Err(Error::new(EBADF)),
};
let dst = usize::try_from(offset).ok().and_then(|o| data.get_mut(o..)).unwrap_or(&mut []);
let dst = usize::try_from(offset)
.ok()
.and_then(|o| data.get_mut(o..))
.unwrap_or(&mut []);
let byte_count = std::cmp::min(dst.len(), buf.len());
dst[..byte_count].copy_from_slice(&buf[..byte_count]);
Ok(byte_count)
@@ -190,18 +203,26 @@ fn main() -> anyhow::Result<()> {
daemon.ready().expect("failed to signal readiness");
loop {
let req = match socket_fd.next_request(SignalBehavior::Restart).expect("failed to get next request") {
Some(r) => if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
},
let req = match socket_fd
.next_request(SignalBehavior::Restart)
.expect("failed to get next request")
{
Some(r) => {
if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
}
}
None => break,
};
let resp = req.handle_scheme_mut(&mut scheme);
socket_fd.write_response(resp, SignalBehavior::Restart).expect("failed to write packet");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("failed to write packet");
}
std::process::exit(0);
}).map_err(|err| anyhow!("failed to start daemon: {}", err))?;
})
.map_err(|err| anyhow!("failed to start daemon: {}", err))?;
}
+34 -26
View File
@@ -12,10 +12,7 @@ use std::{slice, usize};
use libredox::flag;
use pcid_interface::{PciFeature, PciFeatureInfo, PciFunction, PciFunctionHandle};
use redox_scheme::{CallRequest, RequestKind, SignalBehavior, Socket, V2};
use syscall::{
Event, Packet, Result, SchemeBlockMut,
PAGE_SIZE,
};
use syscall::{Event, Packet, Result, SchemeBlockMut, PAGE_SIZE};
use self::nvme::{InterruptMethod, InterruptSources, Nvme};
use self::scheme::DiskScheme;
@@ -53,10 +50,8 @@ fn get_int_method(
fn bar_base(pcid_handle: &mut PciFunctionHandle, bir: u8) -> Result<NonNull<u8>> {
Ok(unsafe { pcid_handle.map_bar(bir) }.expect("nvmed").ptr)
}
let table_bar_base: *mut u8 =
bar_base(pcid_handle, msix_info.table_bar)?.as_ptr();
let table_base =
unsafe { table_bar_base.offset(msix_info.table_offset as isize) };
let table_bar_base: *mut u8 = bar_base(pcid_handle, msix_info.table_bar)?.as_ptr();
let table_base = unsafe { table_bar_base.offset(msix_info.table_offset as isize) };
let vector_count = msix_info.table_size;
let table_entries: &'static mut [MsixTableEntry] = unsafe {
@@ -107,11 +102,13 @@ fn get_int_method(
let (msg_addr_and_data, irq_handle) =
irq_helpers::allocate_single_interrupt_vector_for_msi(bsp_cpu_id);
pcid_handle.set_feature_info(SetFeatureInfo::Msi(MsiSetFeatureInfo {
message_address_and_data: Some(msg_addr_and_data),
multi_message_enable: Some(0), // enable 2^0=1 vectors
mask_bits: None,
})).unwrap();
pcid_handle
.set_feature_info(SetFeatureInfo::Msi(MsiSetFeatureInfo {
message_address_and_data: Some(msg_addr_and_data),
multi_message_enable: Some(0), // enable 2^0=1 vectors
mask_bits: None,
}))
.unwrap();
(0, irq_handle)
};
@@ -177,9 +174,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
daemon.ready().expect("nvmed: failed to signal readiness");
let (reactor_sender, reactor_receiver) = crossbeam_channel::unbounded();
let (interrupt_method, interrupt_sources) =
get_int_method(&mut pcid_handle, &pci_config.func)
.expect("nvmed: failed to find a suitable interrupt method");
let (interrupt_method, interrupt_sources) = get_int_method(&mut pcid_handle, &pci_config.func)
.expect("nvmed: failed to find a suitable interrupt method");
let mut nvme = Nvme::new(
address.as_ptr() as usize,
interrupt_method,
@@ -191,7 +187,11 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
log::debug!("Finished base initialization");
let nvme = Arc::new(nvme);
#[cfg(feature = "async")]
let reactor_thread = nvme::cq_reactor::start_cq_reactor_thread(Arc::clone(&nvme), interrupt_sources, reactor_receiver);
let reactor_thread = nvme::cq_reactor::start_cq_reactor_thread(
Arc::clone(&nvme),
interrupt_sources,
reactor_receiver,
);
let namespaces = nvme.init_with_queues();
libredox::call::setrens(0, 0).expect("nvmed: failed to enter null namespace");
@@ -200,15 +200,20 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
let mut todo = Vec::new();
loop {
// TODO: Use a proper event queue once interrupt support is back.
match socket.next_request(SignalBehavior::Restart).expect("nvmed: failed to read disk scheme") {
match socket
.next_request(SignalBehavior::Restart)
.expect("nvmed: failed to read disk scheme")
{
None => {
break;
},
Some(req) => if let RequestKind::Call(c) = req.kind() {
todo.push(c);
} else {
// TODO: cancellation
continue;
}
Some(req) => {
if let RequestKind::Call(c) = req.kind() {
todo.push(c);
} else {
// TODO: cancellation
continue;
}
}
}
@@ -216,7 +221,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
while i < todo.len() {
if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) {
let _req = todo.remove(i);
socket.write_response(resp, SignalBehavior::Restart)
socket
.write_response(resp, SignalBehavior::Restart)
.expect("nvmed: failed to write disk scheme");
} else {
i += 1;
@@ -226,7 +232,9 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
//TODO: destroy NVMe stuff
#[cfg(feature = "async")]
reactor_thread.join().expect("nvmed: failed to join reactor thread");
reactor_thread
.join()
.expect("nvmed: failed to join reactor thread");
std::process::exit(0);
}
+115 -36
View File
@@ -19,7 +19,7 @@ use syscall::Result;
use crossbeam_channel::Receiver;
use super::{CmdId, CqId, InterruptSources, Nvme, NvmeComp, NvmeCmd, SqId};
use super::{CmdId, CqId, InterruptSources, Nvme, NvmeCmd, NvmeComp, SqId};
/// A notification request, sent by the future in order to tell the completion thread that the
/// current task wants a notification when a matching completion queue entry has been seen.
@@ -39,7 +39,7 @@ pub enum NotifReq {
RequestAvailSubmission {
sq_id: SqId,
waker: task::Waker,
}
},
}
enum PendingReq {
@@ -97,7 +97,11 @@ impl CqReactor {
receiver,
})
}
fn handle_notif_reqs_raw(pending_reqs: &mut Vec<PendingReq>, receiver: &Receiver<NotifReq>, block_until_first: bool) {
fn handle_notif_reqs_raw(
pending_reqs: &mut Vec<PendingReq>,
receiver: &Receiver<NotifReq>,
block_until_first: bool,
) {
let mut blocking_iter;
let mut nonblocking_iter;
@@ -125,7 +129,9 @@ impl CqReactor {
message,
waker,
}),
NotifReq::RequestAvailSubmission { sq_id, waker } => pending_reqs.push(PendingReq::PendingAvailSubmission { sq_id, waker, }),
NotifReq::RequestAvailSubmission { sq_id, waker } => {
pending_reqs.push(PendingReq::PendingAvailSubmission { sq_id, waker })
}
}
}
}
@@ -144,14 +150,22 @@ impl CqReactor {
while let Some((head, entry)) = completion_queue.complete(None) {
unsafe { self.nvme.completion_queue_head(cq_id, head) };
log::trace!("Got completion queue entry (CQID {}): {:?} at {}", cq_id, entry, head);
log::trace!(
"Got completion queue entry (CQID {}): {:?} at {}",
cq_id,
entry,
head
);
{
let submission_queues_read_lock = self.nvme.submission_queues.read().unwrap();
// this lock is actually important, since it will block during submission from other
// threads. the lock won't be held for long by the submitters, but it still prevents
// the entry being lost before this reactor is actually able to respond:
let &(ref sq_lock, corresponding_cq_id) = submission_queues_read_lock.get(&{entry.sq_id}).expect("nvmed: internal error: queue returned from controller doesn't exist");
let &(ref sq_lock, corresponding_cq_id) =
submission_queues_read_lock.get(&{ entry.sq_id }).expect(
"nvmed: internal error: queue returned from controller doesn't exist",
);
assert_eq!(cq_id, corresponding_cq_id);
let mut sq_guard = sq_lock.lock().unwrap();
sq_guard.head = entry.sq_head;
@@ -159,7 +173,6 @@ impl CqReactor {
Self::handle_notif_reqs_raw(&mut self.pending_reqs, &self.receiver, false);
}
Self::try_notify_futures(&mut self.pending_reqs, cq_id, &entry);
entry_count += 1;
@@ -169,11 +182,16 @@ impl CqReactor {
Some(())
}
fn finish_pending_completion(pending_reqs: &mut Vec<PendingReq>, req_cq_id: CqId, cq_id: CqId, sq_id: SqId, cmd_id: CmdId, entry: &NvmeComp, i: usize) -> bool {
if req_cq_id == cq_id
&& sq_id == entry.sq_id
&& cmd_id == entry.cid
{
fn finish_pending_completion(
pending_reqs: &mut Vec<PendingReq>,
req_cq_id: CqId,
cq_id: CqId,
sq_id: SqId,
cmd_id: CmdId,
entry: &NvmeComp,
i: usize,
) -> bool {
if req_cq_id == cq_id && sq_id == entry.sq_id && cmd_id == entry.cid {
let (waker, message) = match pending_reqs.remove(i) {
PendingReq::PendingCompletion { waker, message, .. } => (waker, message),
_ => unreachable!(),
@@ -187,7 +205,12 @@ impl CqReactor {
false
}
}
fn finish_pending_avail_submission(pending_reqs: &mut Vec<PendingReq>, sq_id: SqId, entry: &NvmeComp, i: usize) -> bool {
fn finish_pending_avail_submission(
pending_reqs: &mut Vec<PendingReq>,
sq_id: SqId,
entry: &NvmeComp,
i: usize,
) -> bool {
if sq_id == entry.sq_id {
let waker = match pending_reqs.remove(i) {
PendingReq::PendingAvailSubmission { waker, .. } => waker,
@@ -200,22 +223,43 @@ impl CqReactor {
false
}
}
fn try_notify_futures(pending_reqs: &mut Vec<PendingReq>, cq_id: CqId, entry: &NvmeComp) -> Option<()> {
fn try_notify_futures(
pending_reqs: &mut Vec<PendingReq>,
cq_id: CqId,
entry: &NvmeComp,
) -> Option<()> {
let mut i = 0usize;
let mut futures_notified = 0;
while i < pending_reqs.len() {
match &pending_reqs[i] {
&PendingReq::PendingCompletion { cq_id: req_cq_id, sq_id, cmd_id, .. } => if Self::finish_pending_completion(pending_reqs, req_cq_id, cq_id, sq_id, cmd_id, entry, i) {
futures_notified += 1;
} else {
i += 1;
&PendingReq::PendingCompletion {
cq_id: req_cq_id,
sq_id,
cmd_id,
..
} => {
if Self::finish_pending_completion(
pending_reqs,
req_cq_id,
cq_id,
sq_id,
cmd_id,
entry,
i,
) {
futures_notified += 1;
} else {
i += 1;
}
}
&PendingReq::PendingAvailSubmission { sq_id, .. } => if Self::finish_pending_avail_submission(pending_reqs, sq_id, entry, i) {
futures_notified += 1;
} else {
i += 1;
&PendingReq::PendingAvailSubmission { sq_id, .. } => {
if Self::finish_pending_avail_submission(pending_reqs, sq_id, entry, i) {
futures_notified += 1;
} else {
i += 1;
}
}
}
}
@@ -272,7 +316,7 @@ pub fn start_cq_reactor_thread(
// multiple vectors to point to different CPUs, so that the load can be balanced across the
// logical processors.
let reactor = CqReactor::new(nvme, interrupt_sources, receiver)
.expect("nvmed: failed to setup CQ reactor");
.expect("nvmed: failed to setup CQ reactor");
thread::spawn(move || reactor.run())
}
@@ -317,7 +361,11 @@ where
let this = &mut self.get_mut().state;
match mem::replace(this, CompletionFutureState::Placeholder) {
CompletionFutureState::PendingSubmission { cmd_init, nvme, sq_id } => {
CompletionFutureState::PendingSubmission {
cmd_init,
nvme,
sq_id,
} => {
let sqs_read_guard = nvme.submission_queues.read().unwrap();
let &(ref sq_lock, cq_id) = sqs_read_guard
.get(&sq_id)
@@ -329,20 +377,43 @@ where
// when the CQ reactor gets a new completion queue entry, it'll lock the
// submisson queue it came from. since we're holding the same lock, this
// message will always be sent before the reactor is done with the entry.
nvme.reactor_sender.send(NotifReq::RequestAvailSubmission { sq_id, waker: context.waker().clone() }).unwrap();
*this = CompletionFutureState::PendingSubmission { cmd_init, nvme, sq_id };
nvme.reactor_sender
.send(NotifReq::RequestAvailSubmission {
sq_id,
waker: context.waker().clone(),
})
.unwrap();
*this = CompletionFutureState::PendingSubmission {
cmd_init,
nvme,
sq_id,
};
return task::Poll::Pending;
}
let cmd_id =
u16::try_from(sq.tail).expect("nvmed: internal error: CQ has more than 2^16 entries");
let cmd_id = u16::try_from(sq.tail)
.expect("nvmed: internal error: CQ has more than 2^16 entries");
let tail = sq.submit_unchecked(cmd_init(cmd_id));
let tail = u16::try_from(tail).unwrap();
// make sure that we register interest before the reactor can get notified
let message = Arc::new(Mutex::new(None));
*this = CompletionFutureState::PendingCompletion { nvme, cq_id, cmd_id, sq_id, message: Arc::clone(&message), };
nvme.reactor_sender.send(NotifReq::RequestCompletion { cq_id, sq_id, cmd_id, message, waker: context.waker().clone() }).expect("reactor dead");
*this = CompletionFutureState::PendingCompletion {
nvme,
cq_id,
cmd_id,
sq_id,
message: Arc::clone(&message),
};
nvme.reactor_sender
.send(NotifReq::RequestCompletion {
cq_id,
sq_id,
cmd_id,
message,
waker: context.waker().clone(),
})
.expect("reactor dead");
unsafe { nvme.submission_queue_tail(sq_id, tail) };
task::Poll::Pending
}
@@ -357,14 +428,22 @@ where
*this = CompletionFutureState::Finished;
return task::Poll::Ready(value.cq_entry);
}
nvme.reactor_sender.send(NotifReq::RequestCompletion {
nvme.reactor_sender
.send(NotifReq::RequestCompletion {
cq_id,
sq_id,
cmd_id,
waker: context.waker().clone(),
message: Arc::clone(&message),
})
.expect("reactor dead");
*this = CompletionFutureState::PendingCompletion {
message,
cq_id,
sq_id,
cmd_id,
waker: context.waker().clone(),
message: Arc::clone(&message),
}).expect("reactor dead");
*this = CompletionFutureState::PendingCompletion { message, cq_id, cmd_id, sq_id, nvme };
sq_id,
nvme,
};
task::Poll::Pending
}
CompletionFutureState::Finished => {
+22 -13
View File
@@ -61,7 +61,6 @@ pub struct IdentifyNamespaceData {
pub nows: u16,
pub _rsvd1: [u8; 18],
// 92
pub anagrpid: u32,
pub _rsvd2: [u8; 3],
pub nsattr: u8,
@@ -137,8 +136,12 @@ impl LbaFormat {
((self.0 >> 16) & 0xFF) as u8
}
pub fn lba_data_size(&self) -> Option<u64> {
if self.log_lba_data_size() < 9 { return None }
if self.log_lba_data_size() >= 32 { return None }
if self.log_lba_data_size() < 9 {
return None;
}
if self.log_lba_data_size() >= 32 {
return None;
}
Some(1u64 << self.log_lba_data_size())
}
pub fn metadata_size(&self) -> u16 {
@@ -153,8 +156,9 @@ impl Nvme {
let data: Dma<IdentifyControllerData> = unsafe { Dma::zeroed().unwrap().assume_init() };
// println!(" - Attempting to identify controller");
let comp = self
.submit_and_complete_admin_command(|cid| NvmeCmd::identify_controller(cid, data.physical()));
let comp = self.submit_and_complete_admin_command(|cid| {
NvmeCmd::identify_controller(cid, data.physical())
});
log::trace!("Completion: {:?}", comp);
// println!(" - Dumping identify controller");
@@ -169,7 +173,9 @@ impl Nvme {
log::info!(
" - Model: {} Serial: {} Firmware: {}",
model, serial, firmware,
model,
serial,
firmware,
);
}
pub fn identify_namespace_list(&self, base: u32) -> Vec<u32> {
@@ -177,10 +183,9 @@ impl Nvme {
let data: Dma<[u32; 1024]> = unsafe { Dma::zeroed().unwrap().assume_init() };
// println!(" - Attempting to retrieve namespace ID list");
let comp = self
.submit_and_complete_admin_command(|cid| {
NvmeCmd::identify_namespace_list(cid, data.physical(), base)
});
let comp = self.submit_and_complete_admin_command(|cid| {
NvmeCmd::identify_namespace_list(cid, data.physical(), base)
});
log::trace!("Completion2: {:?}", comp);
@@ -192,8 +197,9 @@ impl Nvme {
let data: Dma<IdentifyNamespaceData> = unsafe { Dma::zeroed().unwrap().assume_init() };
// println!(" - Attempting to identify namespace {}", nsid);
let comp = self
.submit_and_complete_admin_command(|cid| NvmeCmd::identify_namespace(cid, data.physical(), nsid));
let comp = self.submit_and_complete_admin_command(|cid| {
NvmeCmd::identify_namespace(cid, data.physical(), nsid)
});
// println!(" - Dumping identify namespace");
@@ -201,7 +207,10 @@ impl Nvme {
let capacity = data.capacity_in_blocks();
log::info!("NSID: {} Size: {} Capacity: {}", nsid, size, capacity);
let block_size = data.formatted_lba_size().lba_data_size().expect("nvmed: error: size outside 512-2^64 range");
let block_size = data
.formatted_lba_size()
.lba_data_size()
.expect("nvmed: error: size outside 512-2^64 range");
log::debug!("NVME block size: {}", block_size);
NvmeNamespace {
+90 -38
View File
@@ -9,8 +9,8 @@ use std::thread;
use crossbeam_channel::Sender;
use smallvec::{smallvec, SmallVec};
use syscall::error::{Error, Result, EINVAL, EIO};
use common::io::{Io, Mmio};
use syscall::error::{Error, Result, EINVAL, EIO};
use common::dma::Dma;
@@ -27,15 +27,21 @@ use pcid_interface::PciFunctionHandle;
#[cfg(target_arch = "aarch64")]
#[inline(always)]
pub(crate) unsafe fn pause() { std::arch::aarch64::__yield(); }
pub(crate) unsafe fn pause() {
std::arch::aarch64::__yield();
}
#[cfg(target_arch = "x86")]
#[inline(always)]
pub(crate) unsafe fn pause() { std::arch::x86::_mm_pause(); }
pub(crate) unsafe fn pause() {
std::arch::x86::_mm_pause();
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub(crate) unsafe fn pause() { std::arch::x86_64::_mm_pause(); }
pub(crate) unsafe fn pause() {
std::arch::x86_64::_mm_pause();
}
/// Used in conjunction with `InterruptMethod`, primarily by the CQ reactor.
#[derive(Debug)]
@@ -91,7 +97,10 @@ pub enum InterruptMethod {
/// Traditional level-triggered, INTx# interrupt pins.
Intx,
/// Message signaled interrupts
Msi { msi_info: MsiInfo, log2_multiple_message_enabled: u8 },
Msi {
msi_info: MsiInfo,
log2_multiple_message_enabled: u8,
},
/// Extended message signaled interrupts
MsiX(MappedMsixRegs),
}
@@ -218,7 +227,8 @@ impl Nvme {
std::iter::once((0u16, (Mutex::new(NvmeCmdQueue::new()?), 0u16))).collect(),
),
completion_queues: RwLock::new(
std::iter::once((0u16, Mutex::new((NvmeCompQueue::new()?, smallvec!(0))))).collect(),
std::iter::once((0u16, Mutex::new((NvmeCompQueue::new()?, smallvec!(0)))))
.collect(),
),
// map the zero interrupt vector (which according to the spec shall always point to the
// admin completion queue) to CQID 0 (admin completion queue)
@@ -301,12 +311,24 @@ impl Nvme {
for (qid, queue) in self.completion_queues.get_mut().unwrap().iter_mut() {
let &(ref cq, ref sq_ids) = &*queue.get_mut().unwrap();
let data = &cq.data;
log::debug!("completion queue {}: {:X}, {}, (submission queue ids: {:?}", qid, data.physical(), data.len(), sq_ids);
log::debug!(
"completion queue {}: {:X}, {}, (submission queue ids: {:?}",
qid,
data.physical(),
data.len(),
sq_ids
);
}
for (qid, (queue, cq_id)) in self.submission_queues.get_mut().unwrap().iter_mut() {
let data = &queue.get_mut().unwrap().data;
log::debug!("submission queue {}: {:X}, {}, attached to CQID: {}", qid, data.physical(), data.len(), cq_id);
log::debug!(
"submission queue {}: {:X}, {}, attached to CQID: {}",
qid,
data.physical(),
data.len(),
cq_id
);
}
{
@@ -319,9 +341,11 @@ impl Nvme {
regs.aqa
.write(((acq.data.len() as u32 - 1) << 16) | (asq.data.len() as u32 - 1));
regs.asq_low.write(asq.data.physical() as u32);
regs.asq_high.write((asq.data.physical() as u64 >> 32) as u32);
regs.asq_high
.write((asq.data.physical() as u64 >> 32) as u32);
regs.acq_low.write(acq.data.physical() as u32);
regs.acq_high.write((acq.data.physical() as u64 >> 32) as u32);
regs.acq_high
.write((acq.data.physical() as u64 >> 32) as u32);
// Set IOCQES, IOSQES, AMS, MPS, and CSS
let mut cc = regs.cc.read();
@@ -371,7 +395,10 @@ impl Nvme {
self.regs.write().unwrap().intmc.write(0x0000_0001);
}
}
&mut InterruptMethod::Msi { msi_info: _, log2_multiple_message_enabled: log2_enabled_messages } => {
&mut InterruptMethod::Msi {
msi_info: _,
log2_multiple_message_enabled: log2_enabled_messages,
} => {
let mut to_mask = 0x0000_0000;
let mut to_clear = 0x0000_0000;
@@ -421,7 +448,11 @@ impl Nvme {
}
#[cfg(not(feature = "async"))]
pub fn submit_and_complete_command<F: FnOnce(CmdId) -> NvmeCmd>(&self, sq_id: SqId, cmd_init: F) -> NvmeComp {
pub fn submit_and_complete_command<F: FnOnce(CmdId) -> NvmeCmd>(
&self,
sq_id: SqId,
cmd_init: F,
) -> NvmeComp {
// Submit command
let cmd = {
let sqs_read_guard = self.submission_queues.read().unwrap();
@@ -433,10 +464,15 @@ impl Nvme {
assert!(!sq.is_full());
let cmd_id =
u16::try_from(sq.tail).expect("nvmed: internal error: CQ has more than 2^16 entries");
let cmd_id = u16::try_from(sq.tail)
.expect("nvmed: internal error: CQ has more than 2^16 entries");
let cmd = cmd_init(cmd_id);
log::trace!("Sent submission queue entry (SQID {}): {:?} at {}", sq_id, cmd, cmd_id);
log::trace!(
"Sent submission queue entry (SQID {}): {:?} at {}",
sq_id,
cmd,
cmd_id
);
let tail = sq.submit_unchecked(cmd);
let tail = u16::try_from(tail).unwrap();
@@ -460,7 +496,12 @@ impl Nvme {
while let Some((head, entry)) = completion_queue.complete(Some((sq_id, cmd))) {
unsafe { self.completion_queue_head(*cq_id, head) };
log::trace!("Got completion queue entry (CQID {}): {:?} at {}", cq_id, entry, head);
log::trace!(
"Got completion queue entry (CQID {}): {:?} at {}",
cq_id,
entry,
head
);
assert_eq!(sq_id, { entry.sq_id });
assert_eq!({ cmd.cid }, { entry.cid });
@@ -484,16 +525,25 @@ impl Nvme {
}
#[cfg(feature = "async")]
pub fn submit_and_complete_command<F: FnOnce(CmdId) -> NvmeCmd>(&self, sq_id: SqId, cmd_init: F) -> NvmeComp {
pub fn submit_and_complete_command<F: FnOnce(CmdId) -> NvmeCmd>(
&self,
sq_id: SqId,
cmd_init: F,
) -> NvmeComp {
use crate::nvme::cq_reactor::{CompletionFuture, CompletionFutureState};
futures::executor::block_on(
CompletionFuture {
state: CompletionFutureState::PendingSubmission { cmd_init, nvme: &self, sq_id },
}
)
futures::executor::block_on(CompletionFuture {
state: CompletionFutureState::PendingSubmission {
cmd_init,
nvme: &self,
sq_id,
},
})
}
pub fn submit_and_complete_admin_command<F: FnOnce(CmdId) -> NvmeCmd>(&self, cmd_init: F) -> NvmeComp {
pub fn submit_and_complete_admin_command<F: FnOnce(CmdId) -> NvmeCmd>(
&self,
cmd_init: F,
) -> NvmeComp {
self.submit_and_complete_command(0, cmd_init)
}
@@ -522,10 +572,9 @@ impl Nvme {
.checked_sub(1)
.expect("nvmed: internal error: CQID 0 for I/O CQ");
let comp = self
.submit_and_complete_admin_command(|cid| {
NvmeCmd::create_io_completion_queue(cid, io_cq_id, ptr, raw_len, vector)
});
let comp = self.submit_and_complete_admin_command(|cid| {
NvmeCmd::create_io_completion_queue(cid, io_cq_id, ptr, raw_len, vector)
});
if let Some(vector) = vector {
self.cqs_for_ivs
@@ -540,14 +589,15 @@ impl Nvme {
let (ptr, len) = {
let mut submission_queues_guard = self.submission_queues.write().unwrap();
let (queue_lock, _) = submission_queues_guard
.entry(io_sq_id)
.or_insert_with(|| {
(Mutex::new(
let (queue_lock, _) = submission_queues_guard.entry(io_sq_id).or_insert_with(|| {
(
Mutex::new(
NvmeCmdQueue::new()
.expect("nvmed: failed to allocate I/O completion queue"),
), io_cq_id)
});
),
io_cq_id,
)
});
let queue = queue_lock.get_mut().unwrap();
(queue.data.physical(), queue.data.len())
@@ -559,10 +609,9 @@ impl Nvme {
.checked_sub(1)
.expect("nvmed: internal error: SQID 0 for I/O SQ");
let comp = self
.submit_and_complete_admin_command(|cid| {
NvmeCmd::create_io_submission_queue(cid, io_sq_id, ptr, raw_len, io_cq_id)
});
let comp = self.submit_and_complete_admin_command(|cid| {
NvmeCmd::create_io_submission_queue(cid, io_sq_id, ptr, raw_len, io_cq_id)
});
}
pub fn init_with_queues(&self) -> BTreeMap<u32, NvmeNamespace> {
@@ -604,7 +653,10 @@ impl Nvme {
} else if bytes <= 8192 {
(buffer_prp_guard[0], buffer_prp_guard[1])
} else {
(buffer_prp_guard[0], (buffer_prp_guard.physical() + 8) as u64)
(
buffer_prp_guard[0],
(buffer_prp_guard.physical() + 8) as u64,
)
};
let mut cmd = NvmeCmd::default();
+4 -4
View File
@@ -69,9 +69,7 @@ impl NvmeCompQueue {
//HACK FOR SOMETIMES RETURNING INVALID DATA ON QEMU!
if let Some((sq_id, cmd)) = cmd_opt {
if entry.sq_id != sq_id
|| entry.cid != cmd.cid
{
if entry.sq_id != sq_id || entry.cid != cmd.cid {
return None;
}
}
@@ -94,7 +92,9 @@ impl NvmeCompQueue {
if let Some(some) = self.complete(cmd_opt) {
return some;
} else {
unsafe { super::pause(); }
unsafe {
super::pause();
}
}
}
}
+79 -43
View File
@@ -6,12 +6,12 @@ use std::io::prelude::*;
use std::sync::Arc;
use std::{cmp, str};
use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
use syscall::schemev2::NewFdFlags;
use syscall::{
Error, Result, Stat, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, MODE_DIR,
MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET,
};
use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
use crate::nvme::{Nvme, NvmeNamespace};
@@ -84,8 +84,10 @@ impl DiskWrapper {
return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW));
}
loop {
match nvme.namespace_read(disk, disk.id, block, block_bytes)
.map_err(|err| io::Error::from_raw_os_error(err.errno))? {
match nvme
.namespace_read(disk, disk.id, block, block_bytes)
.map_err(|err| io::Error::from_raw_os_error(err.errno))?
{
Some(bytes) => {
assert_eq!(bytes, block_bytes.len());
assert_eq!(bytes, blksize as usize);
@@ -164,19 +166,25 @@ impl DiskScheme {
fn check_locks(&self, disk_i: u32, part_i_opt: Option<u32>) -> Result<()> {
for (_, handle) in self.handles.iter() {
match handle {
Handle::Disk(i) => if disk_i == *i {
return Err(Error::new(ENOLCK));
},
Handle::Partition(i, p) => if disk_i == *i {
match part_i_opt {
Some(part_i) => if part_i == *p {
return Err(Error::new(ENOLCK));
},
None => {
return Err(Error::new(ENOLCK));
Handle::Disk(i) => {
if disk_i == *i {
return Err(Error::new(ENOLCK));
}
}
Handle::Partition(i, p) => {
if disk_i == *i {
match part_i_opt {
Some(part_i) => {
if part_i == *p {
return Err(Error::new(ENOLCK));
}
}
None => {
return Err(Error::new(ENOLCK));
}
}
}
},
}
_ => (),
}
}
@@ -185,12 +193,16 @@ impl DiskScheme {
}
impl SchemeBlockMut for DiskScheme {
fn xopen(&mut self, path_str: &str, flags: usize, ctx: &CallerCtx) -> Result<Option<OpenResult>> {
fn xopen(
&mut self,
path_str: &str,
flags: usize,
ctx: &CallerCtx,
) -> Result<Option<OpenResult>> {
if ctx.uid != 0 {
return Err(Error::new(EACCES));
}
let path_str = path_str
.trim_matches('/');
let path_str = path_str.trim_matches('/');
let handle = if path_str.is_empty() {
if flags & O_DIRECTORY == O_DIRECTORY || flags & O_STAT == O_STAT {
@@ -253,7 +265,10 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, handle);
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
}
fn dup(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
@@ -358,10 +373,19 @@ impl SchemeBlockMut for DiskScheme {
Ok(Some(i))
}
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
fn read(
&mut self,
id: usize,
buf: &mut [u8],
offset: u64,
_fcntl_flags: u32,
) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle) => {
let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]);
let src = usize::try_from(offset)
.ok()
.and_then(|o| handle.get(o..))
.unwrap_or(&[]);
let count = core::cmp::min(src.len(), buf.len());
buf[..count].copy_from_slice(&src[..count]);
Ok(Some(count))
@@ -369,7 +393,8 @@ impl SchemeBlockMut for DiskScheme {
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
let block_size = disk.as_ref().block_size;
self.nvme.namespace_read(disk.as_ref(), disk.as_ref().id, offset / block_size, buf)
self.nvme
.namespace_read(disk.as_ref(), disk.as_ref().id, offset / block_size, buf)
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
@@ -389,18 +414,26 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = part.start_lba + rel_block;
self.nvme.namespace_read(disk.as_ref(), disk.as_ref().id, abs_block, buf)
self.nvme
.namespace_read(disk.as_ref(), disk.as_ref().id, abs_block, buf)
}
}
}
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> Result<Option<usize>> {
fn write(
&mut self,
id: usize,
buf: &[u8],
offset: u64,
_fcntl_flags: u32,
) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(_) => Err(Error::new(EBADF)),
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
let block_size = disk.as_ref().block_size;
self.nvme.namespace_write(disk.as_ref(), disk.as_ref().id, offset / block_size, buf)
self.nvme
.namespace_write(disk.as_ref(), disk.as_ref().id, offset / block_size, buf)
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
@@ -420,31 +453,34 @@ impl SchemeBlockMut for DiskScheme {
let abs_block = part.start_lba + rel_block;
self.nvme.namespace_write(disk.as_ref(), disk.as_ref().id, abs_block, buf)
self.nvme
.namespace_write(disk.as_ref(), disk.as_ref().id, abs_block, buf)
}
}
}
fn fsize(&mut self, id: usize) -> Result<Option<u64>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle) => handle.len() as u64,
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
disk.as_ref().blocks * disk.as_ref().block_size
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
let part = disk
.pt
.as_ref()
.ok_or(Error::new(EBADF))?
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
Ok(Some(
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle) => handle.len() as u64,
Handle::Disk(number) => {
let disk = self.disks.get_mut(&number).ok_or(Error::new(EBADF))?;
disk.as_ref().blocks * disk.as_ref().block_size
}
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(&disk_num).ok_or(Error::new(EBADF))?;
let part = disk
.pt
.as_ref()
.ok_or(Error::new(EBADF))?
.partitions
.get(part_num as usize)
.ok_or(Error::new(EBADF))?;
part.size * disk.as_ref().block_size
}
}))
part.size * disk.as_ref().block_size
}
},
))
}
fn close(&mut self, id: usize) -> Result<Option<usize>> {
+14 -8
View File
@@ -33,7 +33,8 @@ fn main() {
scheme, port, protocol
);
redox_daemon::Daemon::new(move |d| daemon(d, scheme, port, protocol)).expect("usbscsid: failed to daemonize");
redox_daemon::Daemon::new(move |d| daemon(d, scheme, port, protocol))
.expect("usbscsid: failed to daemonize");
}
fn daemon(daemon: redox_daemon::Daemon, scheme: String, port: usize, protocol: u8) -> ! {
let disk_scheme_name = format!(":disk.usb-{scheme}+{port}-scsi");
@@ -81,8 +82,8 @@ fn daemon(daemon: redox_daemon::Daemon, scheme: String, port: usize, protocol: u
// TODO: Let all of the USB drivers fork or be managed externally, and xhcid won't have to keep
// track of all the drivers.
let socket_fd = Socket::<V2>::create(&disk_scheme_name)
.expect("usbscsid: failed to create disk scheme");
let socket_fd =
Socket::<V2>::create(&disk_scheme_name).expect("usbscsid: failed to create disk scheme");
//libredox::call::setrens(0, 0).expect("scsid: failed to enter null namespace");
let mut scsi = Scsi::new(&mut *protocol).expect("usbscsid: failed to setup SCSI");
@@ -95,11 +96,16 @@ fn daemon(daemon: redox_daemon::Daemon, scheme: String, port: usize, protocol: u
// TODO: Use nonblocking and put all pending calls in a todo VecDeque. Use an eventfd as well.
loop {
let req = match socket_fd.next_request(SignalBehavior::Restart).expect("scsid: failed to read disk scheme") {
Some(r) => if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
let req = match socket_fd
.next_request(SignalBehavior::Restart)
.expect("scsid: failed to read disk scheme")
{
Some(r) => {
if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
}
}
None => break,
};
+61 -20
View File
@@ -3,8 +3,8 @@ use std::slice;
use xhcid_interface::{
ConfDesc, DeviceReqData, EndpBinaryDirection, EndpDirection, EndpointStatus, IfDesc, Invalid,
PortReqRecipient, PortReqTy, PortTransferStatus, PortTransferStatusKind, XhciClientHandle, XhciClientHandleError,
XhciEndpHandle,
PortReqRecipient, PortReqTy, PortTransferStatus, PortTransferStatusKind, XhciClientHandle,
XhciClientHandleError, XhciEndpHandle,
};
use super::{Protocol, ProtocolError, SendCommandStatus, SendCommandStatusKind};
@@ -162,9 +162,16 @@ impl<'a> BulkOnlyTransport<'a> {
}
Ok(())
}
fn read_csw_raw(&mut self, csw_buffer: &mut [u8; 13], already: bool) -> Result<(), ProtocolError> {
fn read_csw_raw(
&mut self,
csw_buffer: &mut [u8; 13],
already: bool,
) -> Result<(), ProtocolError> {
match self.bulk_in.transfer_read(&mut csw_buffer[..])? {
PortTransferStatus { kind: PortTransferStatusKind::Stalled, .. } => {
PortTransferStatus {
kind: PortTransferStatusKind::Stalled,
..
} => {
if already {
self.reset_recovery()?;
}
@@ -172,8 +179,14 @@ impl<'a> BulkOnlyTransport<'a> {
self.clear_stall_in()?;
self.read_csw_raw(csw_buffer, true)?;
}
PortTransferStatus { kind: PortTransferStatusKind::ShortPacket, bytes_transferred } if bytes_transferred != 13 => {
panic!("received a short packet when reading CSW ({} != 13)", bytes_transferred)
PortTransferStatus {
kind: PortTransferStatusKind::ShortPacket,
bytes_transferred,
} if bytes_transferred != 13 => {
panic!(
"received a short packet when reading CSW ({} != 13)",
bytes_transferred
)
}
_ => (),
}
@@ -199,24 +212,38 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
let cbw = *cbw;
match self.bulk_out.transfer_write(&cbw_bytes)? {
PortTransferStatus { kind: PortTransferStatusKind::Stalled, .. } => {
PortTransferStatus {
kind: PortTransferStatusKind::Stalled,
..
} => {
// TODO: Error handling
panic!("bulk out endpoint stalled when sending CBW {:?}", cbw);
//self.clear_stall_out()?;
//dbg!(self.bulk_in.status()?, self.bulk_out.status()?);
}
PortTransferStatus { bytes_transferred, .. } if bytes_transferred != 31 => {
panic!("received short packet when sending CBW ({} != 31)", bytes_transferred);
PortTransferStatus {
bytes_transferred, ..
} if bytes_transferred != 31 => {
panic!(
"received short packet when sending CBW ({} != 31)",
bytes_transferred
);
}
_ => (),
}
let early_residue: Option<NonZeroU32> = match data {
DeviceReqData::In(buffer) => match self.bulk_in.transfer_read(buffer)? {
PortTransferStatus { kind, bytes_transferred } => match kind {
PortTransferStatus {
kind,
bytes_transferred,
} => match kind {
PortTransferStatusKind::Success => None,
PortTransferStatusKind::ShortPacket => {
println!("received short packet (len {}) when transferring data", bytes_transferred);
println!(
"received short packet (len {}) when transferring data",
bytes_transferred
);
NonZeroU32::new(bytes_transferred)
}
PortTransferStatusKind::Stalled => {
@@ -230,13 +257,19 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
)),
));
}
}
}
},
},
DeviceReqData::Out(buffer) => match self.bulk_out.transfer_write(buffer)? {
PortTransferStatus { kind, bytes_transferred } => match kind {
PortTransferStatus {
kind,
bytes_transferred,
} => match kind {
PortTransferStatusKind::Success => None,
PortTransferStatusKind::ShortPacket => {
println!("received short packet (len {}) when transferring data", bytes_transferred);
println!(
"received short packet (len {}) when transferring data",
bytes_transferred
);
NonZeroU32::new(bytes_transferred)
}
PortTransferStatusKind::Stalled => {
@@ -245,10 +278,12 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
}
PortTransferStatusKind::Unknown => {
return Err(ProtocolError::XhciError(
XhciClientHandleError::InvalidResponse(Invalid("unknown transfer status")),
XhciClientHandleError::InvalidResponse(Invalid(
"unknown transfer status",
)),
));
}
}
},
},
DeviceReqData::NoData => None,
};
@@ -266,10 +301,16 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
if !csw.is_valid() || csw.tag != cbw.tag {
println!("Invald CSW {:?} (for CBW {:?})", csw, cbw);
self.reset_recovery()?;
if self.bulk_in.status()? == EndpointStatus::Halted || self.bulk_out.status()? == EndpointStatus::Halted {
return Err(ProtocolError::ProtocolError("Reset Recovery didn't reset endpoints"));
if self.bulk_in.status()? == EndpointStatus::Halted
|| self.bulk_out.status()? == EndpointStatus::Halted
{
return Err(ProtocolError::ProtocolError(
"Reset Recovery didn't reset endpoints",
));
}
return Err(ProtocolError::ProtocolError("CSW invalid, but a recover was successful"));
return Err(ProtocolError::ProtocolError(
"CSW invalid, but a recover was successful",
));
}
/*if self.bulk_in.status()? == EndpointStatus::Halted
+9 -4
View File
@@ -47,8 +47,7 @@ impl SchemeMut for ScsiScheme<'_> {
if flags & O_DIRECTORY != 0 && flags & O_STAT == 0 {
return Err(Error::new(EACCES));
}
let path_str = path_str
.trim_start_matches('/');
let path_str = path_str.trim_start_matches('/');
let handle = if path_str.is_empty() {
// List
Handle::List
@@ -60,7 +59,10 @@ impl SchemeMut for ScsiScheme<'_> {
};
self.next_fd += 1;
self.handles.insert(self.next_fd, handle);
Ok(OpenResult::ThisScheme { number: self.next_fd, flags: NewFdFlags::POSITIONED })
Ok(OpenResult::ThisScheme {
number: self.next_fd,
flags: NewFdFlags::POSITIONED,
})
}
fn fstat(&mut self, fd: usize, stat: &mut syscall::Stat) -> Result<usize> {
match self.handles.get(&fd).ok_or(Error::new(EBADF))? {
@@ -111,7 +113,10 @@ impl SchemeMut for ScsiScheme<'_> {
}
}
Handle::List => {
let src = usize::try_from(offset).ok().and_then(|o| LIST_CONTENTS.get(o..)).unwrap_or(&[]);
let src = usize::try_from(offset)
.ok()
.and_then(|o| LIST_CONTENTS.get(o..))
.unwrap_or(&[]);
let min = core::cmp::min(src.len(), buf.len());
buf[..min].copy_from_slice(&src[..min]);
+3 -5
View File
@@ -1,6 +1,6 @@
use super::opcodes::Opcode;
use std::{fmt, mem, slice};
use std::convert::TryInto;
use std::{fmt, mem, slice};
#[repr(packed)]
pub struct Inquiry {
@@ -517,7 +517,7 @@ impl<'a> Iterator for ModePageIterRaw<'a> {
#[derive(Clone, Copy, Debug)]
pub enum AnyModePage<'a> {
RwErrorRecovery(&'a RwErrorRecoveryPage),
Caching(&'a CachingModePage)
Caching(&'a CachingModePage),
}
struct ModePageIter<'a> {
@@ -540,9 +540,7 @@ impl<'a> Iterator for ModePageIter<'a> {
plain::from_bytes(next_buf).ok()?,
))
} else if page_code == 0x08 {
Some(AnyModePage::Caching(
plain::from_bytes(next_buf).ok()?,
))
Some(AnyModePage::Caching(plain::from_bytes(next_buf).ok()?))
} else {
println!("Unimplemented sub_page {}", base64::encode(next_buf));
None
+29 -34
View File
@@ -56,7 +56,7 @@ impl Scsi {
let max_inquiry_len = this.get_inquiry_alloc_len(protocol)?;
// Get the Standard Inquiry Data.
this.get_standard_inquiry_data(protocol, max_inquiry_len)?;
let version = this.res_standard_inquiry_data().version();
println!("Inquiry version: {}", version);
@@ -89,50 +89,52 @@ impl Scsi {
let standard_inquiry_data = self.res_standard_inquiry_data();
Ok(4 + u16::from(standard_inquiry_data.additional_len))
}
pub fn get_standard_inquiry_data(&mut self, protocol: &mut dyn Protocol, max_inquiry_len: u16) -> Result<()> {
pub fn get_standard_inquiry_data(
&mut self,
protocol: &mut dyn Protocol,
max_inquiry_len: u16,
) -> Result<()> {
let inquiry = self.cmd_inquiry();
*inquiry = cmds::Inquiry::new(false, 0, max_inquiry_len, 0);
protocol
.send_command(
&self.command_buffer[..INQUIRY_CMD_LEN as usize],
DeviceReqData::In(&mut self.inquiry_buffer[..max_inquiry_len as usize]),
)?;
protocol.send_command(
&self.command_buffer[..INQUIRY_CMD_LEN as usize],
DeviceReqData::In(&mut self.inquiry_buffer[..max_inquiry_len as usize]),
)?;
Ok(())
}
pub fn get_ff_sense(&mut self, protocol: &mut dyn Protocol, alloc_len: u8) -> Result<()> {
let request_sense = self.cmd_request_sense();
*request_sense = cmds::RequestSense::new(false, alloc_len, 0);
self.data_buffer.resize(alloc_len.into(), 0);
protocol
.send_command(
&self.command_buffer[..REQUEST_SENSE_CMD_LEN as usize],
DeviceReqData::In(&mut self.data_buffer[..alloc_len as usize]),
)?;
protocol.send_command(
&self.command_buffer[..REQUEST_SENSE_CMD_LEN as usize],
DeviceReqData::In(&mut self.data_buffer[..alloc_len as usize]),
)?;
Ok(())
}
pub fn read_capacity(&mut self, protocol: &mut dyn Protocol) -> Result<&cmds::ReadCapacity10ParamData> {
pub fn read_capacity(
&mut self,
protocol: &mut dyn Protocol,
) -> Result<&cmds::ReadCapacity10ParamData> {
// The spec explicitly states that the allocation length is 8 bytes.
let read_capacity10 = self.cmd_read_capacity10();
*read_capacity10 = cmds::ReadCapacity10::new(0);
self.data_buffer.resize(10usize, 0u8);
protocol
.send_command(
&self.command_buffer[..10],
DeviceReqData::In(&mut self.data_buffer[..8]),
)?;
protocol.send_command(
&self.command_buffer[..10],
DeviceReqData::In(&mut self.data_buffer[..8]),
)?;
Ok(self.res_read_capacity10())
}
pub fn get_mode_sense10(
&mut self,
protocol: &mut dyn Protocol,
) -> Result<
(
&cmds::ModeParamHeader10,
BlkDescSlice,
impl Iterator<Item = cmds::AnyModePage>,
)
> {
) -> Result<(
&cmds::ModeParamHeader10,
BlkDescSlice,
impl Iterator<Item = cmds::AnyModePage>,
)> {
let initial_alloc_len = mem::size_of::<cmds::ModeParamHeader10>() as u16; // covers both mode_data_len and blk_desc_len.
let mode_sense10 = self.cmd_mode_sense10();
*mode_sense10 = cmds::ModeSense10::get_block_desc(initial_alloc_len, 0);
@@ -149,9 +151,7 @@ impl Scsi {
panic!("{:?}", self.res_ff_sense_data());
}
let optimal_alloc_len =
self.res_mode_param_header10().mode_data_len()
+ 2; // the length of the mode data field itself
let optimal_alloc_len = self.res_mode_param_header10().mode_data_len() + 2; // the length of the mode data field itself
let mode_sense10 = self.cmd_mode_sense10();
*mode_sense10 = cmds::ModeSense10::get_block_desc(optimal_alloc_len, 0);
@@ -278,12 +278,7 @@ impl Scsi {
buffer[..bytes_to_read].copy_from_slice(&self.data_buffer[..bytes_to_read]);
Ok(status.bytes_transferred(bytes_to_read as u32))
}
pub fn write(
&mut self,
protocol: &mut dyn Protocol,
lba: u64,
buffer: &[u8],
) -> Result<u32> {
pub fn write(&mut self, protocol: &mut dyn Protocol, lba: u64, buffer: &[u8]) -> Result<u32> {
let blocks_to_write = buffer.len() as u64 / u64::from(self.block_size);
let bytes_to_write = blocks_to_write as usize * self.block_size as usize;
let transfer_len = u32::try_from(blocks_to_write).or(Err(ScsiError::Overflow(
+15 -5
View File
@@ -154,12 +154,22 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> {
deamon.ready().expect("virtio-blkd: failed to deamonize");
loop {
let req = match socket_fd.next_request(SignalBehavior::Restart)
.expect("virtio-blkd: failed to read disk scheme") {
Some(r) => if let RequestKind::Call(c) = r.kind() { c } else { continue },
None => break,
let req = match socket_fd
.next_request(SignalBehavior::Restart)
.expect("virtio-blkd: failed to read disk scheme")
{
Some(r) => {
if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
}
}
None => break,
};
let resp = req.handle_scheme_block_mut(&mut scheme).expect("TODO: block?");
let resp = req
.handle_scheme_block_mut(&mut scheme)
.expect("TODO: block?");
socket_fd
.write_response(resp, SignalBehavior::Restart)
.expect("virtio-blkd: failed to write to disk scheme");
+125 -98
View File
@@ -14,8 +14,8 @@ use partitionlib::PartitionTable;
use redox_scheme::CallerCtx;
use redox_scheme::OpenResult;
use redox_scheme::SchemeBlockMut;
use syscall::flag::*;
use syscall::error::*;
use syscall::flag::*;
use syscall::schemev2::NewFdFlags;
use virtio_core::spec::{Buffer, ChainBuilder, DescriptorFlags};
use virtio_core::transport::Queue;
@@ -40,7 +40,11 @@ impl BlkExtension for Queue<'_> {
})
.unwrap();
let result = unsafe { Dma::<[u8]>::zeroed_slice(target.len()).unwrap().assume_init() };
let result = unsafe {
Dma::<[u8]>::zeroed_slice(target.len())
.unwrap()
.assume_init()
};
let status = Dma::new(u8::MAX).unwrap();
let chain = ChainBuilder::new()
@@ -65,7 +69,11 @@ impl BlkExtension for Queue<'_> {
})
.unwrap();
let mut result = unsafe { Dma::<[u8]>::zeroed_slice(target.len()).unwrap().assume_init() };
let mut result = unsafe {
Dma::<[u8]>::zeroed_slice(target.len())
.unwrap()
.assume_init()
};
result.copy_from_slice(target.as_ref());
let status = Dma::new(u8::MAX).unwrap();
@@ -122,30 +130,31 @@ impl<'a> DiskScheme<'a> {
impl<'a, 'b> Read for VirtioShim<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
let read_block = |block: u64, block_bytes: &mut [u8]| -> Result<(), std::io::Error> {
let req = Dma::new(BlockVirtRequest {
ty: BlockRequestTy::In,
reserved: 0,
sector: block,
})
.unwrap();
let read_block =
|block: u64, block_bytes: &mut [u8]| -> Result<(), std::io::Error> {
let req = Dma::new(BlockVirtRequest {
ty: BlockRequestTy::In,
reserved: 0,
sector: block,
})
.unwrap();
let result = Dma::new([0u8; 512]).unwrap();
let status = Dma::new(u8::MAX).unwrap();
let result = Dma::new([0u8; 512]).unwrap();
let status = Dma::new(u8::MAX).unwrap();
let chain = ChainBuilder::new()
.chain(Buffer::new(&req))
.chain(Buffer::new(&result).flags(DescriptorFlags::WRITE_ONLY))
.chain(Buffer::new(&status).flags(DescriptorFlags::WRITE_ONLY))
.build();
let chain = ChainBuilder::new()
.chain(Buffer::new(&req))
.chain(Buffer::new(&result).flags(DescriptorFlags::WRITE_ONLY))
.chain(Buffer::new(&status).flags(DescriptorFlags::WRITE_ONLY))
.build();
futures::executor::block_on(self.scheme.queue.send(chain));
assert_eq!(*status, 0);
futures::executor::block_on(self.scheme.queue.send(chain));
assert_eq!(*status, 0);
let size = core::cmp::min(block_bytes.len(), result.len());
block_bytes[..size].copy_from_slice(&result.as_slice()[..size]);
Ok(())
};
let size = core::cmp::min(block_bytes.len(), result.len());
block_bytes[..size].copy_from_slice(&result.as_slice()[..size]);
Ok(())
};
let bytes_read =
driver_block::block_read(self.offset, 512, buf, self.block_bytes, read_block)
@@ -224,7 +233,10 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
},
);
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
return Err(syscall::Error::new(EISDIR));
}
@@ -242,14 +254,13 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(
id,
Handle::Partition {
number: part_num,
},
);
self.handles
.insert(id, Handle::Partition { number: part_num });
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
} else {
let nsid = path_str.parse::<u32>().unwrap();
assert_eq!(nsid, 0);
@@ -257,94 +268,110 @@ impl<'a> SchemeBlockMut for DiskScheme<'a> {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Disk);
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
Ok(Some(OpenResult::ThisScheme {
number: id,
flags: NewFdFlags::POSITIONED,
}))
}
}
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _fcntl_flags: u32) -> syscall::Result<Option<usize>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List {
ref mut entries,
} => {
let src = usize::try_from(offset).ok().and_then(|o| entries.get(o..)).unwrap_or(&[]);
let count = core::cmp::min(src.len(), buf.len());
buf[..count].copy_from_slice(&src[..count]);
count
}
fn read(
&mut self,
id: usize,
buf: &mut [u8],
offset: u64,
_fcntl_flags: u32,
) -> syscall::Result<Option<usize>> {
Ok(Some(
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List { ref mut entries } => {
let src = usize::try_from(offset)
.ok()
.and_then(|o| entries.get(o..))
.unwrap_or(&[]);
let count = core::cmp::min(src.len(), buf.len());
buf[..count].copy_from_slice(&src[..count]);
count
}
Handle::Partition {
number,
} => {
let part_table = self.part_table.as_ref().unwrap();
let part = part_table
.partitions
.get(number as usize)
.ok_or(Error::new(EBADF))?;
Handle::Partition { number } => {
let part_table = self.part_table.as_ref().unwrap();
let part = part_table
.partitions
.get(number as usize)
.ok_or(Error::new(EBADF))?;
// Get the offset in sectors.
let rel_block = offset / BLK_SIZE;
// if rel_block >= part.size {
// return Err(Error::new(EOVERFLOW));
// }
// Get the offset in sectors.
let rel_block = offset / BLK_SIZE;
// if rel_block >= part.size {
// return Err(Error::new(EOVERFLOW));
// }
let abs_block = part.start_lba + rel_block;
let abs_block = part.start_lba + rel_block;
futures::executor::block_on(self.queue.read(abs_block, buf))
}
futures::executor::block_on(self.queue.read(abs_block, buf))
}
Handle::Disk => {
let block_size = self.cfg.block_size();
Handle::Disk => {
let block_size = self.cfg.block_size();
futures::executor::block_on(
self.queue.read(offset / u64::from(block_size), buf),
)
}
}))
futures::executor::block_on(
self.queue.read(offset / u64::from(block_size), buf),
)
}
},
))
}
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _fcntl_flags: u32) -> syscall::Result<Option<usize>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Disk => {
let block_size = self.cfg.block_size();
futures::executor::block_on(
self.queue.write(offset / u64::from(block_size), buf),
)
}
fn write(
&mut self,
id: usize,
buf: &[u8],
offset: u64,
_fcntl_flags: u32,
) -> syscall::Result<Option<usize>> {
Ok(Some(
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::Disk => {
let block_size = self.cfg.block_size();
futures::executor::block_on(
self.queue.write(offset / u64::from(block_size), buf),
)
}
_ => todo!(),
}))
_ => todo!(),
},
))
}
fn fsize(&mut self, id: usize) -> syscall::Result<Option<u64>> {
Ok(Some(match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List {
ref entries,
} => {
let len = entries.len() as u64;
log::debug!("list: part_len={len:?}");
Ok(Some(
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List { ref entries } => {
let len = entries.len() as u64;
log::debug!("list: part_len={len:?}");
len
}
len
}
Handle::Partition {
number,
} => {
let part_table = self.part_table.as_ref().unwrap();
let part = part_table
.partitions
.get(number as usize)
.ok_or(Error::new(EBADF))?;
Handle::Partition { number } => {
let part_table = self.part_table.as_ref().unwrap();
let part = part_table
.partitions
.get(number as usize)
.ok_or(Error::new(EBADF))?;
// Partition size in bytes.
let len = part.size * BLK_SIZE;
// Partition size in bytes.
let len = part.size * BLK_SIZE;
log::debug!("part: part_len={len:?}");
log::debug!("part: part_len={len:?}");
len
}
len
}
Handle::Disk => self.cfg.capacity() * u64::from(self.cfg.block_size()),
}))
Handle::Disk => self.cfg.capacity() * u64::from(self.cfg.block_size()),
},
))
}
fn fpath(&mut self, _id: usize, _buf: &mut [u8]) -> syscall::Result<Option<usize>> {
+37 -36
View File
@@ -9,7 +9,9 @@ use rehid::{
report_handler::ReportHandler,
usage_tables::{GenericDesktopUsage, UsagePage},
};
use xhcid_interface::{ConfigureEndpointsReq, DevDesc, EndpDirection, EndpointTy, PortReqRecipient, XhciClientHandle};
use xhcid_interface::{
ConfigureEndpointsReq, DevDesc, EndpDirection, EndpointTy, PortReqRecipient, XhciClientHandle,
};
mod keymap;
mod reqs;
@@ -203,36 +205,36 @@ fn main() {
.expect("Failed to get standard descriptors");
log::info!("{:X?}", desc);
let (conf_desc, conf_num, (if_desc, endpoint_num_opt, hid_desc)) = desc
.config_descs
.iter()
.enumerate()
.find_map(|(conf_num, conf_desc)| {
let if_desc = conf_desc.interface_descs.iter().find_map(|if_desc| {
if if_desc.number == interface_num {
let endpoint_num_opt = if_desc.endpoints.iter().enumerate().find_map(|(endpoint_i, endpoint)| {
if endpoint.ty() == EndpointTy::Interrupt && endpoint.direction() == EndpDirection::In {
Some(endpoint_i + 1)
} else {
None
}
});
let hid_desc = if_desc.hid_descs.iter().find_map(|hid_desc| {
//TODO: should we do any filtering?
Some(hid_desc)
})?;
Some((if_desc.clone(), endpoint_num_opt, hid_desc))
} else {
None
}
})?;
Some((
conf_desc.clone(),
conf_num,
if_desc,
))
})
.expect("Failed to find suitable configuration");
let (conf_desc, conf_num, (if_desc, endpoint_num_opt, hid_desc)) =
desc.config_descs
.iter()
.enumerate()
.find_map(|(conf_num, conf_desc)| {
let if_desc = conf_desc.interface_descs.iter().find_map(|if_desc| {
if if_desc.number == interface_num {
let endpoint_num_opt = if_desc.endpoints.iter().enumerate().find_map(
|(endpoint_i, endpoint)| {
if endpoint.ty() == EndpointTy::Interrupt
&& endpoint.direction() == EndpDirection::In
{
Some(endpoint_i + 1)
} else {
None
}
},
);
let hid_desc = if_desc.hid_descs.iter().find_map(|hid_desc| {
//TODO: should we do any filtering?
Some(hid_desc)
})?;
Some((if_desc.clone(), endpoint_num_opt, hid_desc))
} else {
None
}
})?;
Some((conf_desc.clone(), conf_num, if_desc))
})
.expect("Failed to find suitable configuration");
handle
.configure_endpoints(&ConfigureEndpointsReq {
@@ -292,7 +294,9 @@ fn main() {
if let Some(endpoint) = &mut endpoint_opt {
// interrupt transfer
endpoint.transfer_read(&mut report_buffer).expect("failed to get report");
endpoint
.transfer_read(&mut report_buffer)
.expect("failed to get report");
} else {
// control transfer
reqs::get_report(
@@ -419,10 +423,7 @@ fn main() {
}
if scroll_y != 0 {
let scroll_event = orbclient::event::ScrollEvent {
x: 0,
y: scroll_y,
};
let scroll_event = orbclient::event::ScrollEvent { x: 0, y: scroll_y };
match display.write(&scroll_event.to_event()) {
Ok(_) => (),
+5 -6
View File
@@ -3,7 +3,10 @@ use std::env;
use std::fs::File;
use std::io::{Read, Write};
use xhcid_interface::{plain, usb, ConfigureEndpointsReq, DevDesc, DeviceReqData, EndpDirection, EndpointTy, PortReqRecipient, PortReqTy, XhciClientHandle};
use xhcid_interface::{
plain, usb, ConfigureEndpointsReq, DevDesc, DeviceReqData, EndpDirection, EndpointTy,
PortReqRecipient, PortReqTy, XhciClientHandle,
};
fn main() {
common::setup_logging(
@@ -55,11 +58,7 @@ fn main() {
None
}
})?;
Some((
conf_desc.clone(),
conf_num,
if_desc,
))
Some((conf_desc.clone(), conf_num, if_desc))
})
.expect("Failed to find suitable configuration");
+1 -1
View File
@@ -43,4 +43,4 @@ impl Bga {
self.write(BGA_INDEX_BPP, 32);
self.write(BGA_INDEX_ENABLE, 0x41);
}
}
}
+71 -28
View File
@@ -1,14 +1,14 @@
//#![deny(warnings)]
use event::{user_data, EventQueue};
use std::{iter, mem};
use std::os::unix::io::AsRawFd;
use std::fs::File;
use std::io::{Result, Read, Write};
use std::io::{Read, Result, Write};
use std::os::unix::io::AsRawFd;
use std::{iter, mem};
use common::io::{Io, Mmio, Pio};
use pcid_interface::{PciBar, PciFunctionHandle};
use syscall::flag::EventFlags;
use common::io::{Io, Mmio, Pio};
use common::dma::Dma;
@@ -56,7 +56,9 @@ struct VboxGetMouse {
}
impl VboxGetMouse {
fn request() -> u32 { 1 }
fn request() -> u32 {
1
}
fn new() -> syscall::Result<Dma<Self>> {
let mut packet = unsafe { Dma::<Self>::zeroed()?.assume_init() };
@@ -79,7 +81,9 @@ struct VboxSetMouse {
}
impl VboxSetMouse {
fn request() -> u32 { 2 }
fn request() -> u32 {
2
}
fn new() -> syscall::Result<Dma<Self>> {
let mut packet = unsafe { Dma::<Self>::zeroed()?.assume_init() };
@@ -100,7 +104,9 @@ struct VboxAckEvents {
}
impl VboxAckEvents {
fn request() -> u32 { 41 }
fn request() -> u32 {
41
}
fn new() -> syscall::Result<Dma<Self>> {
let mut packet = unsafe { Dma::<Self>::zeroed()?.assume_init() };
@@ -121,7 +127,9 @@ struct VboxGuestCaps {
}
impl VboxGuestCaps {
fn request() -> u32 { 55 }
fn request() -> u32 {
55
}
fn new() -> syscall::Result<Dma<Self>> {
let mut packet = unsafe { Dma::<Self>::zeroed()?.assume_init() };
@@ -144,7 +152,9 @@ struct VboxDisplayChange {
}
impl VboxDisplayChange {
fn request() -> u32 { 51 }
fn request() -> u32 {
51
}
fn new() -> syscall::Result<Dma<Self>> {
let mut packet = unsafe { Dma::<Self>::zeroed()?.assume_init() };
@@ -166,7 +176,9 @@ struct VboxGuestInfo {
}
impl VboxGuestInfo {
fn request() -> u32 { 50 }
fn request() -> u32 {
50
}
fn new() -> syscall::Result<Dma<Self>> {
let mut packet = unsafe { Dma::<Self>::zeroed()?.assume_init() };
@@ -189,7 +201,10 @@ fn main() {
let bar0 = pci_config.func.bars[0].expect_port();
let irq = pci_config.func.legacy_interrupt_line.expect("vboxd: no legacy interrupts supported");
let irq = pci_config
.func
.legacy_interrupt_line
.expect("vboxd: no legacy interrupts supported");
println!(" + VirtualBox {}", pci_config.func.display());
@@ -205,15 +220,28 @@ fn main() {
if let Ok(count) = libredox::call::fpath(display.as_raw_fd() as usize, &mut buf) {
let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
let res = path.split(":").nth(1).unwrap_or("");
width = res.split("/").nth(1).unwrap_or("").parse::<u32>().unwrap_or(0);
height = res.split("/").nth(2).unwrap_or("").parse::<u32>().unwrap_or(0);
width = res
.split("/")
.nth(1)
.unwrap_or("")
.parse::<u32>()
.unwrap_or(0);
height = res
.split("/")
.nth(2)
.unwrap_or("")
.parse::<u32>()
.unwrap_or(0);
}
}
let mut irq_file = irq.irq_handle("vboxd");
let mut port = Pio::<u32>::new(bar0 as u16);
let address = unsafe { pcid_handle.map_bar(1) }.expect("vboxd").ptr.as_ptr();
let address = unsafe { pcid_handle.map_bar(1) }
.expect("vboxd")
.ptr
.as_ptr();
{
let vmmdev = unsafe { &mut *(address as *mut VboxVmmDev) };
@@ -230,7 +258,9 @@ fn main() {
set_mouse.features.write(1 << 4 | 1);
port.write(set_mouse.physical() as u32);
vmmdev.guest_events.write(VBOX_EVENT_DISPLAY | VBOX_EVENT_MOUSE);
vmmdev
.guest_events
.write(VBOX_EVENT_DISPLAY | VBOX_EVENT_MOUSE);
user_data! {
enum Source {
@@ -238,8 +268,15 @@ fn main() {
}
}
let event_queue = EventQueue::<Source>::new().expect("vboxd: Could not create event queue.");
event_queue.subscribe(irq_file.as_raw_fd() as usize, Source::Irq, event::EventFlags::READ).unwrap();
let event_queue =
EventQueue::<Source>::new().expect("vboxd: Could not create event queue.");
event_queue
.subscribe(
irq_file.as_raw_fd() as usize,
Source::Irq,
event::EventFlags::READ,
)
.unwrap();
daemon.ready().expect("failed to signal readiness");
@@ -247,10 +284,13 @@ fn main() {
let mut bga = Bga::new();
let get_mouse = VboxGetMouse::new().expect("vboxd: failed to map GetMouse");
let display_change = VboxDisplayChange::new().expect("vboxd: failed to map DisplayChange");
let display_change =
VboxDisplayChange::new().expect("vboxd: failed to map DisplayChange");
let ack_events = VboxAckEvents::new().expect("vboxd: failed to map AckEvents");
for Source::Irq in iter::once(Source::Irq).chain(event_queue.map(|e| e.expect("vboxd: failed to get next event").user_data)) {
for Source::Irq in iter::once(Source::Irq)
.chain(event_queue.map(|e| e.expect("vboxd: failed to get next event").user_data))
{
let mut irq = [0; 8];
if irq_file.read(&mut irq).unwrap() >= irq.len() {
let host_events = vmmdev.host_events.read();
@@ -268,10 +308,9 @@ fn main() {
height = new_height;
println!("Display {}, {}", width, height);
bga.set_size(width as u16, height as u16);
let _ = display.write(&orbclient::ResizeEvent {
width,
height,
}.to_event());
let _ = display.write(
&orbclient::ResizeEvent { width, height }.to_event(),
);
}
}
}
@@ -281,10 +320,13 @@ fn main() {
if let Some(ref mut display) = display_opt {
let x = get_mouse.x.read() * width / 0x10000;
let y = get_mouse.y.read() * height / 0x10000;
let _ = display.write(&orbclient::MouseEvent {
x: x as i32,
y: y as i32,
}.to_event());
let _ = display.write(
&orbclient::MouseEvent {
x: x as i32,
y: y as i32,
}
.to_event(),
);
}
}
}
@@ -293,5 +335,6 @@ fn main() {
}
std::process::exit(0);
}).expect("vboxd: failed to daemonize");
})
.expect("vboxd: failed to daemonize");
}
+1 -1
View File
@@ -45,11 +45,11 @@ use pcid_interface::{
MsiSetFeatureInfo, PciFeature, PciFeatureInfo, PciFunctionHandle, SetFeatureInfo,
};
use common::io::Io;
use event::{Event, RawEventQueue};
use syscall::data::Packet;
use syscall::error::EWOULDBLOCK;
use syscall::flag::EventFlags;
use common::io::Io;
use syscall::scheme::Scheme;
use crate::xhci::{InterruptMethod, Xhci};
+1 -1
View File
@@ -1,8 +1,8 @@
use std::collections::BTreeMap;
use common::io::{Io, Mmio};
use log::debug;
use syscall::error::Result;
use common::io::{Io, Mmio};
use syscall::PAGE_SIZE;
use common::dma::Dma;
+1 -1
View File
@@ -1,5 +1,5 @@
use syscall::error::Result;
use common::io::{Io, Mmio};
use syscall::error::Result;
use common::dma::Dma;
+1 -1
View File
@@ -1,7 +1,7 @@
use common::io::{Io, Mmio};
use std::ops::Range;
use std::ptr::NonNull;
use std::{fmt, mem, ptr, slice};
use common::io::{Io, Mmio};
pub struct ExtendedCapabilitiesIter {
base: *const u8,
+1 -1
View File
@@ -20,8 +20,8 @@ use std::sync::{Arc, Mutex, MutexGuard, Weak};
use std::{mem, process, slice, sync::atomic, task, thread};
use syscall::error::{Error, Result, EBADF, EBADMSG, EIO, ENOENT};
use common::io::Io;
use syscall::error::{Error, Result, EBADF, EBADMSG, EIO, ENOENT};
use syscall::PAGE_SIZE;
use chashmap::CHashMap;
+1 -1
View File
@@ -1,6 +1,6 @@
use common::io::{Io, Mmio};
use std::num::NonZeroU8;
use std::slice;
use common::io::{Io, Mmio};
use super::CapabilityRegs;
+3 -8
View File
@@ -67,8 +67,9 @@ lazy_static! {
.expect("Failed to create the regex for the port<n>/request scheme");
static ref REGEX_PORT_ENDPOINTS: Regex = Regex::new(r"^port(\d{1,3})/endpoints$")
.expect("Failed to create the regex for the port<n>/endpoints scheme");
static ref REGEX_PORT_SPECIFIC_ENDPOINT: Regex = Regex::new(r"^port(\d{1,3})/endpoints/(\d{1,3})$")
.expect("Failed to create the regex for the port<n>/endpoints/<n> scheme");
static ref REGEX_PORT_SPECIFIC_ENDPOINT: Regex =
Regex::new(r"^port(\d{1,3})/endpoints/(\d{1,3})$")
.expect("Failed to create the regex for the port<n>/endpoints/<n> scheme");
static ref REGEX_PORT_SUB_ENDPOINT: Regex = Regex::new(
r"port(\d{1,3})/endpoints/(\d{1,3})/(ctl|data)$"
)
@@ -352,33 +353,27 @@ impl SchemeParameters {
Ok(Self::ConfigureEndpoints(port_num))
} else if REGEX_PORT_DESCRIPTORS.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_DESCRIPTORS, scheme, 0)?;
Ok(Self::PortDesc(port_num))
} else if REGEX_PORT_STATE.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_STATE, scheme, 0)?;
Ok(Self::PortState(port_num))
} else if REGEX_PORT_REQUEST.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_REQUEST, scheme, 0)?;
Ok(Self::PortReq(port_num))
} else if REGEX_PORT_ENDPOINTS.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_ENDPOINTS, scheme, 0)?;
Ok(Self::Endpoints(port_num))
} else if REGEX_PORT_SPECIFIC_ENDPOINT.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_SPECIFIC_ENDPOINT, scheme, 0)?;
let endpoint_num = get_u8_from_regex(&REGEX_PORT_SPECIFIC_ENDPOINT, scheme, 1)?;
Ok(Self::Endpoint(port_num, endpoint_num, String::from("root")))
} else if REGEX_PORT_SUB_ENDPOINT.is_match(scheme) {
let port_num = get_usize_from_regex(&REGEX_PORT_SUB_ENDPOINT, scheme, 0)?;
let endpoint_num = get_u8_from_regex(&REGEX_PORT_SUB_ENDPOINT, scheme, 1)?;
let handle_type = get_string_from_regex(&REGEX_PORT_SUB_ENDPOINT, scheme, 2)?;
+1 -1
View File
@@ -1,6 +1,6 @@
use crate::usb;
use std::{fmt, mem};
use common::io::{Io, Mmio};
use std::{fmt, mem};
use super::context::StreamContextType;