22//! in a wide range of address spaces.
33
44use crate :: { AcpiError , Handler , PhysicalMapping } ;
5+ use core:: ptr;
56use log:: warn;
67
78/// This is the raw form of a Generic Address Structure, and follows the layout found in the ACPI tables.
@@ -143,7 +144,7 @@ where
143144 }
144145 AddressSpace :: SystemIo => Ok ( MappedGas { gas, handler : handler. clone ( ) , mapping : None } ) ,
145146 other => {
146- warn ! ( "Tried to map GAS of unsupported type {:?}" , other) ;
147+ warn ! ( "Mapping a GAS in address space {:?} is not supported! " , other) ;
147148 Err ( AcpiError :: LibUnimplemented )
148149 }
149150 }
@@ -158,25 +159,24 @@ where
158159 match self . gas . address_space {
159160 AddressSpace :: SystemMemory => {
160161 let mapping = self . mapping . as_ref ( ) . unwrap ( ) ;
161- let value = match access_size_bits {
162- 8 => unsafe { core:: ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u8 ) as u64 } ,
163- 16 => unsafe { core:: ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u16 ) as u64 } ,
164- 32 => unsafe { core:: ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u32 ) as u64 } ,
165- 64 => unsafe { core:: ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u64 ) } ,
166- _ => panic ! ( ) ,
167- } ;
168- Ok ( value)
162+ match access_size_bits {
163+ 8 => Ok ( unsafe { ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u8 ) as u64 } ) ,
164+ 16 => Ok ( unsafe { ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u16 ) as u64 } ) ,
165+ 32 => Ok ( unsafe { ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u32 ) as u64 } ) ,
166+ 64 => Ok ( unsafe { ptr:: read_volatile ( mapping. virtual_start . as_ptr ( ) as * const u64 ) } ) ,
167+ _ => Err ( AcpiError :: InvalidGenericAddress ) ,
168+ }
169169 }
170- AddressSpace :: SystemIo => {
171- let value = match access_size_bits {
172- 8 => self . handler . read_io_u8 ( self . gas . address as u16 ) as u64 ,
173- 16 => self . handler . read_io_u16 ( self . gas . address as u16 ) as u64 ,
174- 32 => self . handler . read_io_u32 ( self . gas . address as u16 ) as u64 ,
175- _ => panic ! ( ) ,
176- } ;
177- Ok ( value)
170+ AddressSpace :: SystemIo => match access_size_bits {
171+ 8 => Ok ( self . handler . read_io_u8 ( self . gas . address as u16 ) as u64 ) ,
172+ 16 => Ok ( self . handler . read_io_u16 ( self . gas . address as u16 ) as u64 ) ,
173+ 32 => Ok ( self . handler . read_io_u32 ( self . gas . address as u16 ) as u64 ) ,
174+ _ => Err ( AcpiError :: InvalidGenericAddress ) ,
175+ } ,
176+ _ => {
177+ warn ! ( "Read from GAS with address space {:?} is not supported. Ignored." , self . gas. address_space) ;
178+ Err ( AcpiError :: LibUnimplemented )
178179 }
179- _ => unimplemented ! ( ) ,
180180 }
181181 }
182182
@@ -188,16 +188,16 @@ where
188188 let mapping = self . mapping . as_ref ( ) . unwrap ( ) ;
189189 match access_size_bits {
190190 8 => unsafe {
191- core :: ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) , value as u8 ) ;
191+ ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) , value as u8 ) ;
192192 } ,
193193 16 => unsafe {
194- core :: ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) as * mut u16 , value as u16 ) ;
194+ ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) as * mut u16 , value as u16 ) ;
195195 } ,
196196 32 => unsafe {
197- core :: ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) as * mut u32 , value as u32 ) ;
197+ ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) as * mut u32 , value as u32 ) ;
198198 } ,
199- 64 => unsafe { core :: ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) as * mut u64 , value) } ,
200- _ => panic ! ( ) ,
199+ 64 => unsafe { ptr:: write_volatile ( mapping. virtual_start . as_ptr ( ) as * mut u64 , value) } ,
200+ _ => return Err ( AcpiError :: InvalidGenericAddress ) ,
201201 }
202202 Ok ( ( ) )
203203 }
@@ -206,11 +206,14 @@ where
206206 8 => self . handler . write_io_u8 ( self . gas . address as u16 , value as u8 ) ,
207207 16 => self . handler . write_io_u16 ( self . gas . address as u16 , value as u16 ) ,
208208 32 => self . handler . write_io_u32 ( self . gas . address as u16 , value as u32 ) ,
209- _ => panic ! ( ) ,
209+ _ => return Err ( AcpiError :: InvalidGenericAddress ) ,
210210 }
211211 Ok ( ( ) )
212212 }
213- _ => unimplemented ! ( ) ,
213+ _ => {
214+ warn ! ( "Write to GAS with address space {:?} is not supported. Ignored." , self . gas. address_space) ;
215+ Err ( AcpiError :: LibUnimplemented )
216+ }
214217 }
215218 }
216219}
@@ -228,7 +231,7 @@ fn gas_decode_access_bit_width(gas: GenericAddress) -> Result<u8, AcpiError> {
228231 *
229232 * We use a third method, based on the alignment of the address, for registers that have
230233 * non-zero bit offsets. These are not typically encountered in normal registers - they very
231- * often mean the GAS has come from APEI (ACPI Platform Error Interface), and so needs speical
234+ * often mean the GAS has come from APEI (ACPI Platform Error Interface), and so needs special
232235 * handling.
233236 */
234237 if gas. bit_offset == 0 && [ 8 , 16 , 32 , 64 ] . contains ( & gas. bit_width ) {
@@ -242,7 +245,19 @@ fn gas_decode_access_bit_width(gas: GenericAddress) -> Result<u8, AcpiError> {
242245 _ => Err ( AcpiError :: InvalidGenericAddress ) ,
243246 }
244247 } else {
245- // TODO: work out access size based on alignment of the address
246- todo ! ( )
248+ /*
249+ * Work out the access size based on the alignment of the address. We round up the total
250+ * width (`bit_offset + bit_width`) to the next power-of-two, up to 64.
251+ */
252+ let total_width = gas. bit_offset + gas. bit_width ;
253+ Ok ( if total_width <= 8 {
254+ 8
255+ } else if total_width <= 16 {
256+ 16
257+ } else if total_width <= 32 {
258+ 32
259+ } else {
260+ 64
261+ } )
247262 }
248263}
0 commit comments