aloe/uio.rs
1/*
2 ____ __ __ __
3 / __ \__ _____ ____ / /___ ____ _ / / / /__ ___ ____
4/ /_/ / // / _ `/ _ \/ __/ // / ' \ / /_/ (_-</ -_) __/
5\___\_\_,_/\_,_/_//_/\__/\_,_/_/_/_/ \____/___/\__/_/
6 Part of the Quantum OS Kernel
7
8Copyright 2025 Gavin Kellam
9
10Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
11associated documentation files (the "Software"), to deal in the Software without restriction,
12including without limitation the rights to use, copy, modify, merge, publish, distribute,
13sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in all copies or substantial
17portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
20NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
23OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24*/
25
26use core::marker::PhantomData;
27
28use private::IoInterface;
29use vera_portal::sys_client::{
30 fixme_cpuio_read_u8, fixme_cpuio_read_u16, fixme_cpuio_write_u8, fixme_cpuio_write_u16,
31};
32
33mod private {
34 pub trait IoInterface {
35 /// Ask QuantumOS for ownership over this IO device.
36 ///
37 /// IO devices should never have multiple ownership, and should be held for the lifetime
38 /// of the device's use. Other processes should also respect all device ownership to ensure
39 /// two userspace programs cannot cause undefined driver behavior.
40 ///
41 /// If `complete_ownership` is set, this device must also respect ownership within the owner
42 /// process. This means that no two references to the same device can exist on the system at
43 /// all. Sometimes, however, interally in a process it might request to have shared ownership
44 /// over the device.
45 fn own(&self, complete_ownership: bool);
46
47 /// Inform QuantumOS to release ownership over this IO device.
48 ///
49 /// IO devices should never have multiple ownership, and should be held for the lifetime
50 /// of the device's use. Other processes should also respect all device ownership to ensure
51 /// two userspace programs cannot cause undefined driver behavior.
52 fn unown(&self);
53 }
54
55 impl IoInterface for super::CpuIO {
56 fn own(&self, _: bool) {
57 // FIXME: Add support for device ownership in the kernel
58 }
59
60 fn unown(&self) {
61 // FIXME: Add support for device ownership in the kernel
62 }
63 }
64}
65pub unsafe trait IoAccessKind {}
66unsafe impl IoAccessKind for opt::ReadOnly {}
67unsafe impl IoAccessKind for opt::WriteOnly {}
68unsafe impl IoAccessKind for opt::ReadWrite {}
69
70pub unsafe trait OwnStrictness {
71 const COMPLETE_OWNERSHIP: bool;
72}
73unsafe impl OwnStrictness for opt::Owned {
74 const COMPLETE_OWNERSHIP: bool = true;
75}
76unsafe impl OwnStrictness for opt::Shared {
77 const COMPLETE_OWNERSHIP: bool = false;
78}
79
80pub mod opt {
81 pub struct Owned(());
82 pub struct Shared(());
83
84 pub struct ReadOnly(());
85 pub struct WriteOnly(());
86 pub struct ReadWrite(());
87}
88
89pub unsafe trait IoSupportsReading {}
90pub unsafe trait IoSupportsWritting {}
91pub unsafe trait IoSupportsReadWrite {}
92
93unsafe impl<Interface: private::IoInterface, Owner: OwnStrictness> IoSupportsReading
94 for UserIO<Interface, opt::ReadOnly, Owner>
95{
96}
97unsafe impl<Interface: private::IoInterface, Owner: OwnStrictness> IoSupportsReading
98 for UserIO<Interface, opt::ReadWrite, Owner>
99{
100}
101unsafe impl<Interface: private::IoInterface, Owner: OwnStrictness> IoSupportsWritting
102 for UserIO<Interface, opt::WriteOnly, Owner>
103{
104}
105unsafe impl<Interface: private::IoInterface, Owner: OwnStrictness> IoSupportsWritting
106 for UserIO<Interface, opt::ReadWrite, Owner>
107{
108}
109unsafe impl<Interface: private::IoInterface, Owner: OwnStrictness> IoSupportsReadWrite
110 for UserIO<Interface, opt::ReadWrite, Owner>
111{
112}
113
114#[derive(Debug)]
115#[repr(transparent)]
116pub struct CpuIO(u16);
117
118/// Userspace access to IO devices
119///
120/// # Currently Supported Interfaces
121/// - [`CpuIO`] *CPU IO Port bus access*
122///
123/// # Why use this type?
124/// `UserIO` represents an 'owned' access over some IO device on the system. This is important because future
125/// processes will not be able to access this IO device until it is dropped.
126///
127/// This type also attempts to implment the interface to access such hardware device in the safest possible
128/// way.
129pub struct UserIO<
130 Interface: private::IoInterface,
131 Access: IoAccessKind = opt::ReadWrite,
132 OwnKind: OwnStrictness = opt::Owned,
133> {
134 interface: Interface,
135 access: PhantomData<Access>,
136 own_kind: PhantomData<OwnKind>,
137}
138
139impl<Access: IoAccessKind, OwnKind: OwnStrictness> UserIO<CpuIO, Access, OwnKind> {
140 /// Create a new CpuIO port for access in userspace.
141 pub unsafe fn new(address: u16) -> Self {
142 let cpu_io = CpuIO(address);
143 cpu_io.own(OwnKind::COMPLETE_OWNERSHIP);
144
145 Self {
146 interface: cpu_io,
147 access: PhantomData,
148 own_kind: PhantomData,
149 }
150 }
151}
152
153impl<Access: IoAccessKind, OwnKind: OwnStrictness> UserIO<CpuIO, Access, OwnKind>
154where
155 UserIO<CpuIO, Access, OwnKind>: IoSupportsReading,
156{
157 #[inline]
158 pub unsafe fn read_u8(&self) -> u8 {
159 fixme_cpuio_read_u8(self.interface.0)
160 }
161
162 #[inline]
163 pub unsafe fn read_u16(&self) -> u16 {
164 fixme_cpuio_read_u16(self.interface.0)
165 }
166}
167
168impl<Access: IoAccessKind, OwnKind: OwnStrictness> UserIO<CpuIO, Access, OwnKind>
169where
170 UserIO<CpuIO, Access, OwnKind>: IoSupportsWritting,
171{
172 #[inline]
173 pub unsafe fn write_u8(&mut self, value: u8) {
174 fixme_cpuio_write_u8(self.interface.0, value);
175 }
176
177 #[inline]
178 pub unsafe fn write_u16(&mut self, value: u16) {
179 fixme_cpuio_write_u16(self.interface.0, value);
180 }
181}