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}