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
use crate::{ZxError, ZxResult};
pub fn pci_bdf_raw_addr(bus: u8, dev: u8, func: u8, offset: u8) -> u32 {
((bus as u32 & 0xff) << 16)
| ((dev as u32 & 0x1f) << 11)
| ((func as u32 & 0x7) << 8)
| (offset as u32 & 0xff)
}
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "x86_64", target_os = "none"))] {
use kernel_hal::x86_64::{Io, Pmio};
use lock::Mutex;
static PIO_LOCK: Mutex<()> = Mutex::new(());
const PCI_CONFIG_ADDR: u16 = 0xcf8;
const PCI_CONFIG_DATA: u16 = 0xcfc;
const PCI_CONFIG_ENABLE: u32 = 1 << 31;
pub fn pmio_config_read_addr(addr: u32, width: usize) -> ZxResult<u32> {
let mut port_cfg = Pmio::<u32>::new(PCI_CONFIG_ADDR);
let port_data = Pmio::<u32>::new(PCI_CONFIG_DATA);
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
port_cfg.write((addr & !0x3) | PCI_CONFIG_ENABLE);
let tmp_val = u32::from_le(port_data.read());
Ok((tmp_val >> shift) & (((1u64 << width) - 1) as u32))
}
pub fn pmio_config_write_addr(addr: u32, val: u32, width: usize) -> ZxResult {
let mut port_cfg = Pmio::<u32>::new(PCI_CONFIG_ADDR);
let mut port_data = Pmio::<u32>::new(PCI_CONFIG_DATA);
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
port_cfg.write((addr & !0x3) | PCI_CONFIG_ENABLE);
let width_mask = ((1u64 << width) - 1) as u32;
let val = val & width_mask;
let tmp_val = if width < 32 {
(u32::from_le(port_data.read()) & !(width_mask << shift)) | (val << shift)
} else {
val
};
port_data.write(u32::to_le(tmp_val));
Ok(())
}
} else {
pub fn pmio_config_read_addr(_addr: u32, _width: usize) -> ZxResult<u32> {
Err(ZxError::NOT_SUPPORTED)
}
pub fn pmio_config_write_addr(_addr: u32, _val: u32, _width: usize) -> ZxResult {
Err(ZxError::NOT_SUPPORTED)
}
}
}
pub fn pio_config_read(bus: u8, dev: u8, func: u8, offset: u8, width: usize) -> ZxResult<u32> {
pmio_config_read_addr(pci_bdf_raw_addr(bus, dev, func, offset), width)
}
pub fn pio_config_write(
bus: u8,
dev: u8,
func: u8,
offset: u8,
val: u32,
width: usize,
) -> ZxResult {
pmio_config_write_addr(pci_bdf_raw_addr(bus, dev, func, offset), val, width)
}