1
1
//! Host Controller Runtime Registers.
2
2
3
3
use super :: capability:: RuntimeRegisterSpaceOffset ;
4
- use accessor:: array;
4
+ use accessor:: marker:: AccessorTypeSpecifier ;
5
+ use accessor:: marker:: ReadOnly ;
6
+ use accessor:: marker:: ReadWrite ;
7
+ use accessor:: marker:: Readable ;
5
8
use accessor:: single;
6
9
use accessor:: Mapper ;
7
10
use core:: convert:: TryFrom ;
8
11
use core:: convert:: TryInto ;
12
+ use core:: marker:: PhantomData ;
9
13
10
14
/// Runtime Registers
11
15
///
@@ -57,21 +61,19 @@ impl_debug_from_methods! {
57
61
58
62
/// Interrupter Register Set
59
63
#[ repr( C ) ]
60
- #[ derive( Copy , Clone , Debug ) ]
61
- pub struct InterrupterRegisterSet {
62
- /// Interrupter Management Register
63
- pub iman : InterrupterManagementRegister ,
64
- /// Interrupter Moderation Register
65
- pub imod : InterrupterModerationRegister ,
66
- /// Event Ring Segment Table Size Register
67
- pub erstsz : EventRingSegmentTableSizeRegister ,
68
- _rsvd : u32 ,
69
- /// Event Ring Segment Table Base Address Register
70
- pub erstba : EventRingSegmentTableBaseAddressRegister ,
71
- /// Event Ring Dequeue Pointer Register
72
- pub erdp : EventRingDequeuePointerRegister ,
64
+ #[ derive( Debug ) ]
65
+ pub struct InterrupterRegisterSet < M >
66
+ where
67
+ M : Mapper + Clone ,
68
+ {
69
+ base : usize ,
70
+ mapper : M ,
73
71
}
74
- impl InterrupterRegisterSet {
72
+
73
+ impl < M > InterrupterRegisterSet < M >
74
+ where
75
+ M : Mapper + Clone ,
76
+ {
75
77
/// Creates an accessor to the Interrupter Register Set.
76
78
///
77
79
/// # Safety
@@ -83,19 +85,79 @@ impl InterrupterRegisterSet {
83
85
///
84
86
/// This method panics if the base address of the Interrupter Register Sets is not aligned
85
87
/// correctly.
86
- pub unsafe fn new < M > (
87
- mmio_base : usize ,
88
- rtoff : RuntimeRegisterSpaceOffset ,
89
- mapper : M ,
90
- ) -> array:: ReadWrite < Self , M >
91
- where
92
- M : Mapper ,
93
- {
94
- const NUM_INTERRUPT_REGISTER_SET : usize = 1024 ;
95
-
88
+ pub unsafe fn new ( mmio_base : usize , rtoff : RuntimeRegisterSpaceOffset , mapper : M ) -> Self {
96
89
let base = mmio_base + usize:: try_from ( rtoff. get ( ) ) . unwrap ( ) + 0x20 ;
90
+ assert ! ( base % 0x20 == 0 , "base is not aligned" ) ;
91
+
92
+ Self { base, mapper }
93
+ }
94
+
95
+ /// Returns a handler for an interrupter.
96
+ ///
97
+ /// # Panics
98
+ ///
99
+ /// This method panics if `index > 1023`.
100
+ pub fn interrupter ( & self , index : usize ) -> Interrupter < ' _ , M , ReadOnly > {
101
+ unsafe { Interrupter :: new ( self . base , index, self . mapper . clone ( ) ) }
102
+ }
103
+
104
+ /// Returns a mutable handler for an interrupter.
105
+ ///
106
+ /// # Panics
107
+ ///
108
+ /// This method panics if `index > 1023`.
109
+ pub fn interrupter_mut ( & mut self , index : usize ) -> Interrupter < ' _ , M , ReadWrite > {
110
+ unsafe { Interrupter :: new ( self . base , index, self . mapper . clone ( ) ) }
111
+ }
112
+ }
113
+
114
+ /// Interrupter
115
+ #[ derive( Debug ) ]
116
+ pub struct Interrupter < ' a , M , A >
117
+ where
118
+ M : Mapper + Clone ,
119
+ A : AccessorTypeSpecifier + Readable ,
120
+ {
121
+ /// Interrupter Management Register
122
+ pub iman : single:: Generic < InterrupterManagementRegister , M , A > ,
123
+ /// Interrupter Moderation Register
124
+ pub imod : single:: Generic < InterrupterModerationRegister , M , A > ,
125
+ /// Event Ring Segment Table Size Register
126
+ pub erstsz : single:: Generic < EventRingSegmentTableSizeRegister , M , A > ,
127
+ /// Event Ring Segment Table Base Address Register
128
+ pub erstba : single:: Generic < EventRingSegmentTableBaseAddressRegister , M , A > ,
129
+ /// Event Ring Dequeue Pointer Register
130
+ pub erdp : single:: Generic < EventRingDequeuePointerRegister , M , A > ,
131
+ // Tie the lifetime of this Interrupter to the parent InterrupterRegisterSet.
132
+ // This prevents multiple mutable handlers from being created.
133
+ _marker : PhantomData < & ' a InterrupterRegisterSet < M > > ,
134
+ }
97
135
98
- array:: ReadWrite :: new ( base, NUM_INTERRUPT_REGISTER_SET , mapper)
136
+ impl < M , A > Interrupter < ' _ , M , A >
137
+ where
138
+ M : Mapper + Clone ,
139
+ A : AccessorTypeSpecifier + Readable ,
140
+ {
141
+ /// Creates an accessor to an interrupter.
142
+ ///
143
+ /// # Safety
144
+ ///
145
+ /// Any mutable handlers to this Interrupter must be unique.
146
+ ///
147
+ /// # Panics
148
+ ///
149
+ /// This method panics if `index > 1023`.
150
+ unsafe fn new ( interrupter_register_set_base : usize , index : usize , mapper : M ) -> Self {
151
+ assert ! ( index < 1024 , "index out of range" ) ;
152
+ let base = interrupter_register_set_base + index * 0x20 ;
153
+ Self {
154
+ iman : single:: Generic :: new ( base, mapper. clone ( ) ) ,
155
+ imod : single:: Generic :: new ( base + 0x4 , mapper. clone ( ) ) ,
156
+ erstsz : single:: Generic :: new ( base + 0x8 , mapper. clone ( ) ) ,
157
+ erstba : single:: Generic :: new ( base + 0x10 , mapper. clone ( ) ) ,
158
+ erdp : single:: Generic :: new ( base + 0x18 , mapper) ,
159
+ _marker : PhantomData ,
160
+ }
99
161
}
100
162
}
101
163
@@ -220,7 +282,3 @@ impl_debug_from_methods! {
220
282
event_ring_dequeue_pointer
221
283
}
222
284
}
223
-
224
- /// Alias for [`InterrupterRegisterSet`].
225
- #[ deprecated( note = "use InterrupterRegisterSet instead (note 'er')" ) ]
226
- pub type InterruptRegisterSet = InterrupterRegisterSet ;
0 commit comments