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
#![allow(missing_docs)]
use super::super::*;
use kernel_hal::{inpd, outpd};
use spin::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 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)
}
pub fn pio_config_read(bus: u8, dev: u8, func: u8, offset: u8, width: usize) -> ZxResult<u32> {
pio_config_read_addr(pci_bdf_raw_addr(bus, dev, func, offset), width)
}
pub fn pio_config_read_addr(addr: u32, width: usize) -> ZxResult<u32> {
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
outpd(PCI_CONFIG_ADDR, (addr & !0x3) | PCI_CONFIG_ENABLE);
let tmp_val = u32::from_le(inpd(PCI_CONFIG_DATA));
Ok((tmp_val >> shift) & (((1u64 << width) - 1) as u32))
}
pub fn pio_config_write(
bus: u8,
dev: u8,
func: u8,
offset: u8,
val: u32,
width: usize,
) -> ZxResult {
pio_config_write_addr(pci_bdf_raw_addr(bus, dev, func, offset), val, width)
}
pub fn pio_config_write_addr(addr: u32, val: u32, width: usize) -> ZxResult {
let _lock = PIO_LOCK.lock();
let shift = ((addr & 0x3) << 3) as usize;
if shift + width > 32 {
return Err(ZxError::INVALID_ARGS);
}
outpd(PCI_CONFIG_ADDR, (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(inpd(PCI_CONFIG_DATA)) & !(width_mask << shift)) | (val << shift)
} else {
val
};
outpd(PCI_CONFIG_DATA, u32::to_le(tmp_val));
Ok(())
}