1use super::Io;
2
3pub struct MmioPtr<T> {
5 ptr: *mut T,
6}
7
8impl<T> MmioPtr<T> {
9 pub unsafe fn new(ptr: *mut T) -> Self {
12 Self { ptr }
13 }
14
15 pub const fn as_ptr(&self) -> *const T {
17 self.ptr
18 }
19
20 pub const fn as_mut_ptr(&mut self) -> *mut T {
22 self.ptr
23 }
24}
25
26#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
28impl<T> Io for MmioPtr<T>
29where
30 T: Copy
31 + PartialEq
32 + core::ops::BitAnd<Output = T>
33 + core::ops::BitOr<Output = T>
34 + core::ops::Not<Output = T>,
35{
36 type Value = T;
37
38 fn read(&self) -> T {
39 unsafe { core::ptr::read_volatile(self.ptr) }
40 }
41
42 fn write(&mut self, value: T) {
43 unsafe { core::ptr::write_volatile(self.ptr, value) };
44 }
45}
46
47#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
49impl Io for MmioPtr<u8> {
50 type Value = u8;
51
52 fn read(&self) -> Self::Value {
53 unsafe {
54 let value: Self::Value;
55 core::arch::asm!(
56 "mov {}, [{}]",
57 out(reg_byte) value,
58 in(reg) self.ptr
59 );
60 value
61 }
62 }
63
64 fn write(&mut self, value: Self::Value) {
65 unsafe {
66 core::arch::asm!(
67 "mov [{}], {}",
68 in(reg) self.ptr,
69 in(reg_byte) value,
70 );
71 }
72 }
73}
74
75#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
77impl Io for MmioPtr<u16> {
78 type Value = u16;
79
80 fn read(&self) -> Self::Value {
81 unsafe {
82 let value: Self::Value;
83 core::arch::asm!(
84 "mov {:x}, [{}]",
85 out(reg) value,
86 in(reg) self.ptr
87 );
88 value
89 }
90 }
91
92 fn write(&mut self, value: Self::Value) {
93 unsafe {
94 core::arch::asm!(
95 "mov [{}], {:x}",
96 in(reg) self.ptr,
97 in(reg) value,
98 );
99 }
100 }
101}
102
103#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
105impl Io for MmioPtr<u32> {
106 type Value = u32;
107
108 fn read(&self) -> Self::Value {
109 unsafe {
110 let value: Self::Value;
111 core::arch::asm!(
112 "mov {:e}, [{}]",
113 out(reg) value,
114 in(reg) self.ptr
115 );
116 value
117 }
118 }
119
120 fn write(&mut self, value: Self::Value) {
121 unsafe {
122 core::arch::asm!(
123 "mov [{}], {:e}",
124 in(reg) self.ptr,
125 in(reg) value,
126 );
127 }
128 }
129}
130
131#[cfg(target_arch = "x86_64")]
133impl Io for MmioPtr<u64> {
134 type Value = u64;
135
136 fn read(&self) -> Self::Value {
137 unsafe {
138 let value: Self::Value;
139 core::arch::asm!(
140 "mov {:r}, [{}]",
141 out(reg) value,
142 in(reg) self.ptr
143 );
144 value
145 }
146 }
147
148 fn write(&mut self, value: Self::Value) {
149 unsafe {
150 core::arch::asm!(
151 "mov [{}], {:r}",
152 in(reg) self.ptr,
153 in(reg) value,
154 );
155 }
156 }
157}