11//! Host Controller Runtime Registers.
22
33use 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 ;
58use accessor:: single;
69use accessor:: Mapper ;
710use core:: convert:: TryFrom ;
811use core:: convert:: TryInto ;
12+ use core:: marker:: PhantomData ;
913
1014/// Runtime Registers
1115///
@@ -57,21 +61,19 @@ impl_debug_from_methods! {
5761
5862/// Interrupter Register Set
5963#[ 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 ,
7371}
74- impl InterrupterRegisterSet {
72+
73+ impl < M > InterrupterRegisterSet < M >
74+ where
75+ M : Mapper + Clone ,
76+ {
7577 /// Creates an accessor to the Interrupter Register Set.
7678 ///
7779 /// # Safety
@@ -83,19 +85,79 @@ impl InterrupterRegisterSet {
8385 ///
8486 /// This method panics if the base address of the Interrupter Register Sets is not aligned
8587 /// 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 {
9689 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+ }
97135
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+ }
99161 }
100162}
101163
@@ -220,7 +282,3 @@ impl_debug_from_methods! {
220282 event_ring_dequeue_pointer
221283 }
222284}
223-
224- /// Alias for [`InterrupterRegisterSet`].
225- #[ deprecated( note = "use InterrupterRegisterSet instead (note 'er')" ) ]
226- pub type InterruptRegisterSet = InterrupterRegisterSet ;
0 commit comments