x86_64/instructions/
port.rs1use core::arch::asm;
4use core::fmt;
5use core::marker::PhantomData;
6
7use crate::sealed::Sealed;
8pub use crate::structures::port::{PortRead, PortWrite};
9
10impl PortRead for u8 {
11 #[inline]
12 unsafe fn read_from_port(port: u16) -> u8 {
13 let value: u8;
14 unsafe {
15 asm!("in al, dx", out("al") value, in("dx") port, options(nomem, nostack, preserves_flags));
16 }
17 value
18 }
19}
20
21impl PortRead for u16 {
22 #[inline]
23 unsafe fn read_from_port(port: u16) -> u16 {
24 let value: u16;
25 unsafe {
26 asm!("in ax, dx", out("ax") value, in("dx") port, options(nomem, nostack, preserves_flags));
27 }
28 value
29 }
30}
31
32impl PortRead for u32 {
33 #[inline]
34 unsafe fn read_from_port(port: u16) -> u32 {
35 let value: u32;
36 unsafe {
37 asm!("in eax, dx", out("eax") value, in("dx") port, options(nomem, nostack, preserves_flags));
38 }
39 value
40 }
41}
42
43impl PortWrite for u8 {
44 #[inline]
45 unsafe fn write_to_port(port: u16, value: u8) {
46 unsafe {
47 asm!("out dx, al", in("dx") port, in("al") value, options(nomem, nostack, preserves_flags));
48 }
49 }
50}
51
52impl PortWrite for u16 {
53 #[inline]
54 unsafe fn write_to_port(port: u16, value: u16) {
55 unsafe {
56 asm!("out dx, ax", in("dx") port, in("ax") value, options(nomem, nostack, preserves_flags));
57 }
58 }
59}
60
61impl PortWrite for u32 {
62 #[inline]
63 unsafe fn write_to_port(port: u16, value: u32) {
64 unsafe {
65 asm!("out dx, eax", in("dx") port, in("eax") value, options(nomem, nostack, preserves_flags));
66 }
67 }
68}
69
70pub trait PortAccess: Sealed {
72 const DEBUG_STR: &'static str;
74}
75
76pub trait PortReadAccess: PortAccess {}
78
79pub trait PortWriteAccess: PortAccess {}
81
82#[derive(Debug)]
84pub struct ReadOnlyAccess(());
85
86impl Sealed for ReadOnlyAccess {}
87impl PortAccess for ReadOnlyAccess {
88 const DEBUG_STR: &'static str = "ReadOnly";
89}
90impl PortReadAccess for ReadOnlyAccess {}
91
92#[derive(Debug)]
94pub struct WriteOnlyAccess(());
95
96impl Sealed for WriteOnlyAccess {}
97impl PortAccess for WriteOnlyAccess {
98 const DEBUG_STR: &'static str = "WriteOnly";
99}
100impl PortWriteAccess for WriteOnlyAccess {}
101
102#[derive(Debug)]
104pub struct ReadWriteAccess(());
105
106impl Sealed for ReadWriteAccess {}
107impl PortAccess for ReadWriteAccess {
108 const DEBUG_STR: &'static str = "ReadWrite";
109}
110impl PortReadAccess for ReadWriteAccess {}
111impl PortWriteAccess for ReadWriteAccess {}
112
113pub struct PortGeneric<T, A> {
122 port: u16,
123 phantom: PhantomData<(T, A)>,
124}
125
126pub type Port<T> = PortGeneric<T, ReadWriteAccess>;
128
129pub type PortReadOnly<T> = PortGeneric<T, ReadOnlyAccess>;
131
132pub type PortWriteOnly<T> = PortGeneric<T, WriteOnlyAccess>;
134
135impl<T, A> PortGeneric<T, A> {
136 #[inline]
138 pub const fn new(port: u16) -> PortGeneric<T, A> {
139 PortGeneric {
140 port,
141 phantom: PhantomData,
142 }
143 }
144}
145
146impl<T: PortRead, A: PortReadAccess> PortGeneric<T, A> {
147 #[doc(alias = "in")]
154 #[doc(alias = "inb")]
155 #[doc(alias = "inw")]
156 #[doc(alias = "inl")]
157 #[inline]
158 pub unsafe fn read(&mut self) -> T {
159 unsafe { T::read_from_port(self.port) }
160 }
161}
162
163impl<T: PortWrite, A: PortWriteAccess> PortGeneric<T, A> {
164 #[doc(alias = "out")]
171 #[doc(alias = "outb")]
172 #[doc(alias = "outw")]
173 #[doc(alias = "outl")]
174 #[inline]
175 pub unsafe fn write(&mut self, value: T) {
176 unsafe { T::write_to_port(self.port, value) }
177 }
178}
179
180impl<T, A: PortAccess> fmt::Debug for PortGeneric<T, A> {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 f.debug_struct("PortGeneric")
183 .field("port", &self.port)
184 .field("size", &core::mem::size_of::<T>())
185 .field("access", &format_args!("{}", A::DEBUG_STR))
186 .finish()
187 }
188}
189
190impl<T, A> Clone for PortGeneric<T, A> {
191 fn clone(&self) -> Self {
192 Self {
193 port: self.port,
194 phantom: PhantomData,
195 }
196 }
197}
198
199impl<T, A> PartialEq for PortGeneric<T, A> {
200 fn eq(&self, other: &Self) -> bool {
201 self.port == other.port
202 }
203}
204
205impl<T, A> Eq for PortGeneric<T, A> {}