Skip to content

Commit c386b96

Browse files
committed
Add index/bank field tests
1 parent e0ea86d commit c386b96

2 files changed

Lines changed: 354 additions & 0 deletions

File tree

tests/bank_fields.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Test operations on "Bank" fields
2+
3+
use aml_test_tools::handlers::std_test_handler::{
4+
Command,
5+
construct_std_handler,
6+
create_mutex,
7+
read_u16,
8+
write_u8,
9+
write_u16,
10+
};
11+
12+
mod test_infra;
13+
14+
#[test]
15+
fn test_basic_bank_store_and_load() {
16+
// This is a straightforward test of banked fields.
17+
// Internally: Apart from setting the bank index beforehand, the field read/write is identical
18+
// to normal fields. So this test is probably sufficient testing of banked fields.
19+
const AML: &str = r#"DefinitionBlock("%FN%", "DSDT", 1, "RSACPI", "BNKFLD", 1) {
20+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
21+
Field(MEM, ByteAcc, NoLock, Preserve) {
22+
INDX, 8
23+
}
24+
25+
BankField (MEM, INDX, 0, WordAcc, NoLock, Preserve) {
26+
OFFSET (0x02), // Prevent aliasing INDX
27+
A, 16,
28+
B, 16,
29+
C, 16
30+
}
31+
32+
BankField (MEM, INDX, 1, WordAcc, NoLock, Preserve) {
33+
OFFSET (0x02),
34+
D, 16,
35+
E, 16,
36+
F, 16
37+
}
38+
39+
Method(MAIN, 0, NotSerialized) {
40+
C = 0xA55A
41+
D = C
42+
E = 0x5AA5
43+
A = E
44+
Return (0)
45+
}
46+
}
47+
"#;
48+
49+
const EXPECTED_COMMANDS: &[Command] = &[
50+
create_mutex(),
51+
// C = 0xA55A
52+
write_u8(0x40000, 0), // Select bank 0.
53+
write_u16(0x40006, 0xA55A), // Write the value to C.
54+
// D = C
55+
write_u8(0x40000, 0), // Select bank 0.
56+
read_u16(0x40006, 0xA55A), // Read the value from C.
57+
write_u8(0x40000, 1), // Select bank 1.
58+
write_u16(0x40002, 0xA55A), // Write the value to D.
59+
// E = 0x5AA5
60+
write_u8(0x40000, 1), // Select bank 1.
61+
write_u16(0x40004, 0x5AA5), // Write the value to E.
62+
// A = E
63+
write_u8(0x40000, 1), // Select bank 1.
64+
read_u16(0x40004, 0x5AA5), // Read from E
65+
write_u8(0x40000, 0), // Select bank 0.
66+
write_u16(0x40002, 0x5AA5), // Write the value to A.
67+
];
68+
69+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
70+
test_infra::run_aml_test(AML, handler);
71+
}

tests/index_fields.rs

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
// Test operations on "Index" fields
2+
3+
use aml_test_tools::handlers::std_test_handler::{
4+
Command,
5+
construct_std_handler,
6+
create_mutex,
7+
read_u8,
8+
read_u16,
9+
write_u8,
10+
write_u16,
11+
};
12+
13+
mod test_infra;
14+
15+
#[test]
16+
fn test_basic_index_store_and_load_8_bit() {
17+
// In this test, the data register has the same width as the fields and all fields are correctly
18+
// aligned. We should see single reads and writes for each store operation.
19+
const AML: &str = r#"DefinitionBlock("%FN%", "DSDT", 1, "RSACPI", "IDXFLD", 1) {
20+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
21+
Field(MEM, ByteAcc, NoLock, Preserve) {
22+
OFFSET(0x10),
23+
INDX, 8,
24+
DATA, 8
25+
}
26+
27+
IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
28+
A, 8,
29+
B, 8,
30+
C, 8
31+
}
32+
33+
Method(MAIN, 0, NotSerialized) {
34+
C = 0xA5
35+
A = 0x5A
36+
B = A
37+
C = A
38+
Return (0)
39+
}
40+
}
41+
"#;
42+
43+
const EXPECTED_COMMANDS: &[Command] = &[
44+
create_mutex(),
45+
// C = 0xA5
46+
write_u8(0x40010, 0x02), // Set index to point at C
47+
write_u8(0x40011, 0xA5), // Set C = 0xA5
48+
// A = 0x5A
49+
write_u8(0x40010, 0x00), // Set index to point at A
50+
write_u8(0x40011, 0x5A), // Set A = 0x5A
51+
// Read A
52+
write_u8(0x40010, 0x00), // etc.
53+
read_u8(0x40011, 0x5A),
54+
// B = A
55+
write_u8(0x40010, 0x01),
56+
write_u8(0x40011, 0x5A),
57+
// Read A
58+
write_u8(0x40010, 0x00),
59+
read_u8(0x40011, 0x5A),
60+
// C = A
61+
write_u8(0x40010, 0x02),
62+
write_u8(0x40011, 0x5A),
63+
];
64+
65+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
66+
test_infra::run_aml_test(AML, handler);
67+
}
68+
69+
#[test]
70+
fn test_basic_index_store_and_load_16_bit() {
71+
// In this test, the data register has the same width as the fields and all fields are correctly
72+
// aligned. We should see single reads and writes for each store operation.
73+
const AML: &str = r#"DefinitionBlock("%FN%", "DSDT", 1, "RSACPI", "IDXFLD", 1) {
74+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
75+
Field(MEM, WordAcc, NoLock, Preserve) {
76+
OFFSET(0x20),
77+
INDX, 16,
78+
DATA, 16
79+
}
80+
81+
IndexField (INDX, DATA, WordAcc, NoLock, Preserve) {
82+
A, 16,
83+
B, 16,
84+
C, 16
85+
}
86+
87+
Method(MAIN, 0, NotSerialized) {
88+
C = 0xA5B6
89+
A = 0x5A6B
90+
B = A
91+
C = A
92+
Return (0)
93+
}
94+
}
95+
"#;
96+
97+
const EXPECTED_COMMANDS: &[Command] = &[
98+
create_mutex(),
99+
// C = 0xA5B6
100+
write_u16(0x40020, 0x04), // Set index to point at C
101+
write_u16(0x40022, 0xA5B6), // Set C = 0xA5B6
102+
// A = 0x5A6B
103+
write_u16(0x40020, 0x00), // Set index to point at A
104+
write_u16(0x40022, 0x5A6B), // Set A = 0x5A6B
105+
// Read A
106+
write_u16(0x40020, 0x00), // etc.
107+
read_u16(0x40022, 0x5A6B),
108+
// B = A
109+
write_u16(0x40020, 0x02),
110+
write_u16(0x40022, 0x5A6B),
111+
// Read A
112+
write_u16(0x40020, 0x00),
113+
read_u16(0x40022, 0x5A6B),
114+
// C = A
115+
write_u16(0x40020, 0x04),
116+
write_u16(0x40022, 0x5A6B),
117+
];
118+
119+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
120+
test_infra::run_aml_test(AML, handler);
121+
}
122+
123+
#[test]
124+
fn test_index_multiple_aligned_reads() {
125+
// In this test, the data register is narrower than the fields, so multiple data register
126+
// reads are needed to access each field.
127+
const AML: &str = r#"DefinitionBlock("%FN%", "DSDT", 1, "RSACPI", "IDXFLD", 1) {
128+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
129+
Field(MEM, ByteAcc, NoLock, Preserve) {
130+
OFFSET(0x04),
131+
INDX, 8,
132+
DATA, 8
133+
}
134+
135+
IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
136+
A, 16,
137+
B, 16,
138+
C, 16
139+
}
140+
141+
Method(MAIN, 0, NotSerialized) {
142+
C = 0xA5B6
143+
B = C
144+
Return (0)
145+
}
146+
}
147+
"#;
148+
149+
const EXPECTED_COMMANDS: &[Command] = &[
150+
create_mutex(),
151+
// C = 0xA5B6
152+
write_u8(0x40004, 0x04), // Set index to point at C (low byte)
153+
write_u8(0x40005, 0xB6), // Set low C = 0xB6
154+
write_u8(0x40004, 0x05), // Set index to point at C (high byte)
155+
write_u8(0x40005, 0xA5), // Set low C = 0xA5
156+
// B = C. Read C
157+
write_u8(0x40004, 0x04),
158+
read_u8(0x40005, 0xB6),
159+
write_u8(0x40004, 0x05),
160+
read_u8(0x40005, 0xA5),
161+
// Write B
162+
write_u8(0x40004, 0x02),
163+
write_u8(0x40005, 0xB6),
164+
write_u8(0x40004, 0x03),
165+
write_u8(0x40005, 0xA5),
166+
];
167+
168+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
169+
test_infra::run_aml_test(AML, handler);
170+
}
171+
172+
#[test]
173+
fn test_index_narrower_than_data() {
174+
// In this test, the access width of the index field is smaller than the data register. Even
175+
// though it looks as though individual 16-bit reads/writes would be OK, actually multiple
176+
// 8-bit reads/writes are needed to access each field. (Not intuitive, but matches ACPICA)
177+
const AML: &str = r#"DefinitionBlock("%FN%", "DSDT", 1, "RSACPI", "IDXFLD", 1) {
178+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
179+
Field(MEM, WordAcc, NoLock, Preserve) {
180+
OFFSET(0x06),
181+
INDX, 16,
182+
DATA, 16
183+
}
184+
185+
IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
186+
A, 16,
187+
B, 16,
188+
C, 16
189+
}
190+
191+
Method(MAIN, 0, NotSerialized) {
192+
C = 0xA5B6
193+
B = C
194+
Return (0)
195+
}
196+
}
197+
"#;
198+
199+
const EXPECTED_COMMANDS: &[Command] = &[
200+
create_mutex(),
201+
// C = 0xA5B6
202+
write_u16(0x40006, 0x04), // Set index to point at C, low byte
203+
write_u8(0x40008, 0xB6), // Set C (low) = 0xB6
204+
write_u16(0x40006, 0x05), // Set index to point at C, high byte
205+
write_u8(0x40008, 0xA5), // Set C (high) = 0xA5
206+
// Read C
207+
write_u16(0x40006, 0x04), // etc.
208+
read_u8(0x40008, 0xB6),
209+
write_u16(0x40006, 0x05),
210+
read_u8(0x40008, 0xA5),
211+
// B = C
212+
write_u16(0x40006, 0x02),
213+
write_u8(0x40008, 0xB6),
214+
write_u16(0x40006, 0x03),
215+
write_u8(0x40008, 0xA5),
216+
];
217+
218+
//let handler = NullHandler;
219+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
220+
test_infra::run_aml_test(AML, handler);
221+
}
222+
223+
#[test]
224+
fn test_index_misaligned_field() {
225+
// Check that we can successfully update non-aligned index fields.
226+
const AML: &str = r#"DefinitionBlock("%FN%", "DSDT", 1, "RSACPI", "IDXFLD", 1) {
227+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
228+
Field(MEM, ByteAcc, NoLock, Preserve) {
229+
OFFSET(0x08),
230+
INDX, 8,
231+
DATA, 8
232+
}
233+
234+
IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
235+
SKIP, 4, // Nybbles make it easier to model mentally!
236+
A, 8,
237+
B, 8
238+
}
239+
240+
Method(MAIN, 0, NotSerialized) {
241+
B = 0xB6
242+
A = B
243+
Return (0)
244+
}
245+
}
246+
"#;
247+
248+
const EXPECTED_COMMANDS: &[Command] = &[
249+
create_mutex(),
250+
// B = 0xB6
251+
// Set index to point at B, low nybble. Which is actually the byte containing A's high
252+
// nybble as well.
253+
write_u8(0x40008, 0x01),
254+
// Read that byte so as to be able to preserve A's high nybble. Pretend that A's high nybble
255+
// is 0xA.
256+
read_u8(0x40009, 0x0A),
257+
// Write back A's high nybble and B's low nybble. This is as much as we test Preserve
258+
// behaviour in the index field tests - it's assumed that if it works for normal fields, it
259+
// works for index fields as well.
260+
write_u8(0x40009, 0x6A),
261+
// Set the index to point at B, high nybble.
262+
write_u8(0x40008, 0x02),
263+
// Read that byte, which also contains an unused nybble. (Which we've just set to zero)
264+
read_u8(0x40009, 0x00),
265+
// Write B's high nybble, preserving the unused zero nybble.
266+
write_u8(0x40009, 0x0B),
267+
// A = B. Start by reading B
268+
write_u8(0x40008, 0x01),
269+
read_u8(0x40009, 0x60),
270+
write_u8(0x40008, 0x02),
271+
read_u8(0x40009, 0x0B),
272+
// Set A, remembering that there are some reads needed to preserve the other nybbles.
273+
write_u8(0x40008, 0x00),
274+
read_u8(0x40009, 0x00),
275+
write_u8(0x40009, 0x60),
276+
write_u8(0x40008, 0x01),
277+
read_u8(0x40009, 0x60),
278+
write_u8(0x40009, 0x6B),
279+
];
280+
281+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
282+
test_infra::run_aml_test(AML, handler);
283+
}

0 commit comments

Comments
 (0)