-
Notifications
You must be signed in to change notification settings - Fork 14
/
device.rs
144 lines (117 loc) · 3.33 KB
/
device.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use alloc::rc::Rc;
use alloc::vec::Vec;
use core::cell::RefCell;
use errno::Result;
use event::EventListener;
use intrusive_collections::{KeyAdapter, RBTree, RBTreeLink};
use vm::VMAddressSpace;
// Keep this up-to-date with include/uapi/manticore/config_abi.h.
pub const CONFIG_ETHERNET_MAC_ADDRESS: i32 = 0;
pub const CONFIG_IO_QUEUE: i32 = 1;
/// A device descriptor.
pub struct DeviceDesc(i32);
/// A device configuration option.
pub type ConfigOption = i32;
impl DeviceDesc {
pub fn from_user(desc: i32) -> DeviceDesc {
DeviceDesc(desc)
}
pub fn to_user(&self) -> i32 {
self.0
}
pub fn to_idx(&self) -> Option<usize> {
if self.0 >= 0 {
Some(self.0 as usize)
} else {
None
}
}
}
pub trait DeviceOps {
fn acquire(&self, vmspace: &mut VMAddressSpace, listener: Rc<dyn EventListener>) -> Result<()>;
fn subscribe(&self, events: &'static str);
fn get_config(&self, option: ConfigOption) -> Option<Vec<u8>>;
fn process_io(&self);
}
pub struct Device {
name: &'static str,
ops: RefCell<Rc<dyn DeviceOps>>,
link: RBTreeLink,
}
intrusive_adapter!(pub DeviceAdapter = Rc<Device>: Device { link: RBTreeLink });
impl Device {
pub fn new(name: &'static str, ops: RefCell<Rc<dyn DeviceOps>>) -> Self {
Device { name, ops, link: RBTreeLink::new(), }
}
pub fn acquire(&self, vmspace: &mut VMAddressSpace, listener: Rc<dyn EventListener>) -> Result<()> {
self.ops.borrow().acquire(vmspace, listener)
}
pub fn subscribe(&self, events: &'static str) {
self.ops.borrow().subscribe(events);
}
pub fn get_config(&self, option: ConfigOption) -> Option<Vec<u8>> {
self.ops.borrow().get_config(option)
}
pub fn process_io(&self) {
self.ops.borrow().process_io()
}
}
impl<'a> KeyAdapter<'a> for DeviceAdapter {
type Key = &'static str;
fn get_key(&self, x: &'a Device) -> Self::Key {
x.name
}
}
pub struct Namespace {
devices: RBTree<DeviceAdapter>,
}
impl Namespace {
pub const fn new() -> Self {
Namespace {
devices: RBTree::new(DeviceAdapter::NEW),
}
}
pub fn add(&mut self, device: Rc<Device>) {
self.devices.insert(device);
}
pub fn lookup(&self, name: &'static str) -> Option<Rc<Device>> {
let cursor = self.devices.find(name);
cursor.clone_pointer()
}
}
pub static mut NAMESPACE: Namespace = Namespace::new();
pub struct DeviceSpace {
desc_table: Vec<Rc<Device>>,
}
impl DeviceSpace {
pub fn new() -> Self {
DeviceSpace { desc_table: vec![] }
}
pub fn attach(&mut self, device: Rc<Device>) -> DeviceDesc {
let idx = self.desc_table.len();
self.desc_table.push(device);
DeviceDesc::from_user(idx as i32)
}
pub fn lookup(&self, desc: DeviceDesc) -> Option<Rc<Device>> {
if let Some(idx) = desc.to_idx() {
if idx > self.desc_table.len() {
return None;
}
return Some(self.desc_table[idx].clone());
}
None
}
}
/// Register a device to the kernel.
pub fn register_device(device: Rc<Device>) {
unsafe {
NAMESPACE.add(device);
}
}
pub fn process_io() {
unsafe {
for dev in NAMESPACE.devices.iter() {
dev.process_io();
}
}
}