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
use hwio::{Io, Pio};
use crate::{
Access,
Error,
SuperIo,
Timeout,
timeout,
};
use super::*;
pub struct AccessLpcDirect<T: Timeout + Send + 'static> {
cmd: u16,
dbg: u16,
timeout: T,
}
impl<T: Timeout + Send> AccessLpcDirect<T> {
pub unsafe fn new(timeout: T) -> Result<Self, Error> {
let mut sio = SuperIo::new(0x2E);
let id =
(sio.read(0x20) as u16) << 8 |
(sio.read(0x21) as u16);
match id {
0x5570 | 0x8587 => (),
_ => return Err(Error::SuperIoId(id)),
}
Ok(Self {
cmd: SMFI_CMD_BASE,
dbg: SMFI_DBG_BASE,
timeout,
})
}
unsafe fn read_cmd(&mut self, addr: u8) -> u8 {
Pio::<u8>::new(
self.cmd + (addr as u16)
).read()
}
unsafe fn write_cmd(&mut self, addr: u8, data: u8) {
Pio::<u8>::new(
self.cmd + (addr as u16)
).write(data)
}
pub unsafe fn read_debug(&mut self, addr: u8) -> u8 {
Pio::<u8>::new(
self.dbg + (addr as u16)
).read()
}
unsafe fn command_check(&mut self) -> Result<(), Error> {
if self.read_cmd(SMFI_CMD_CMD) == 0 {
Ok(())
} else {
Err(Error::WouldBlock)
}
}
}
impl<T: Timeout + Send> Access for AccessLpcDirect<T> {
unsafe fn command(&mut self, cmd: u8, data: &mut [u8]) -> Result<u8, Error> {
if data.len() > self.data_size() {
return Err(Error::DataLength(data.len()));
}
self.command_check()?;
for i in 0..data.len() {
self.write_cmd(i as u8 + SMFI_CMD_DATA, data[i]);
}
self.write_cmd(SMFI_CMD_CMD, cmd as u8);
self.timeout.reset();
timeout!(self.timeout, self.command_check())?;
for i in 0..data.len() {
data[i] = self.read_cmd(i as u8 + SMFI_CMD_DATA);
}
Ok(self.read_cmd(SMFI_CMD_RES))
}
fn data_size(&self) -> usize {
SMFI_CMD_SIZE - SMFI_CMD_DATA as usize
}
}