24
24
25
25
bool qtest_allowed ;
26
26
27
- static DeviceState * irq_intercept_dev ;
27
+ static DeviceState * irq_intercept_dev = NULL ;
28
28
static FILE * qtest_log_fp ;
29
29
static CharDriverState * qtest_chr ;
30
30
static GString * inbuf ;
31
- static int irq_levels [MAX_IRQ ];
32
31
static qemu_timeval start_time ;
33
32
static bool qtest_opened ;
34
33
@@ -123,22 +122,31 @@ static bool qtest_opened;
123
122
*
124
123
* IRQ management:
125
124
*
126
- * > irq_intercept_in QOM-PATH
125
+ * > irq_intercept_in QOM-PATH ID-NUM
127
126
* < OK
128
127
*
129
- * > irq_intercept_out QOM-PATH
128
+ * > irq_intercept_out QOM-PATH ID-NUM
130
129
* < OK
131
130
*
132
131
* Attach to the gpio-in (resp. gpio-out) pins exported by the device at
133
132
* QOM-PATH. When the pin is triggered, one of the following async messages
134
133
* will be printed to the qtest stream:
135
134
*
136
- * IRQ raise NUM
137
- * IRQ lower NUM
135
+ * IRQ raise GPIO-ID NUM
136
+ * IRQ lower GPIO-ID NUM
138
137
*
139
138
* where NUM is an IRQ number. For the PC, interrupts can be intercepted
140
139
* simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with
141
140
* NUM=0 even though it is remapped to GSI 2).
141
+ *
142
+ * A gpio-in IRQ mon an arbitrary device may be changed as follows:
143
+ *
144
+ * > set_irq_in QOM-PATH raise
145
+ * < OK
146
+ *
147
+ * > set_irq_in QOM-PATH lower
148
+ * < OK
149
+ *
142
150
*/
143
151
144
152
static int hex2nib (char ch )
@@ -197,16 +205,13 @@ static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
197
205
198
206
static void qtest_irq_handler (void * opaque , int n , int level )
199
207
{
200
- qemu_irq * old_irqs = opaque ;
208
+ IRQInterceptData * intercept_data = opaque ;
209
+ qemu_irq * old_irqs = intercept_data -> old_irqs ;
201
210
qemu_set_irq (old_irqs [n ], level );
202
-
203
- if (irq_levels [n ] != level ) {
204
- CharDriverState * chr = qtest_chr ;
205
- irq_levels [n ] = level ;
206
- qtest_send_prefix (chr );
207
- qtest_send (chr , "IRQ %s %d\n" ,
208
- level ? "raise" : "lower" , n );
209
- }
211
+ CharDriverState * chr = qtest_chr ;
212
+ qtest_send_prefix (chr );
213
+ qtest_send (chr , "IRQ %s %d %d\n" ,
214
+ level ? "raise" : "lower" , intercept_data -> id , n );
210
215
}
211
216
212
217
static void qtest_process_command (CharDriverState * chr , gchar * * words )
@@ -235,6 +240,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
235
240
|| strcmp (words [0 ], "irq_intercept_in" ) == 0 ) {
236
241
DeviceState * dev ;
237
242
NamedGPIOList * ngl ;
243
+ int id ;
238
244
239
245
g_assert (words [1 ]);
240
246
dev = DEVICE (object_resolve_path (words [1 ], NULL ));
@@ -244,14 +250,13 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
244
250
return ;
245
251
}
246
252
247
- if (irq_intercept_dev ) {
253
+ g_assert (words [2 ]);
254
+ id = strtoul (words [2 ], NULL , 0 );
255
+
256
+ if (irq_intercept_dev == dev ) {
248
257
qtest_send_prefix (chr );
249
- if (irq_intercept_dev != dev ) {
250
- qtest_send (chr , "FAIL IRQ intercept already enabled\n" );
251
- } else {
252
- qtest_send (chr , "OK\n" );
253
- }
254
- return ;
258
+ qtest_send (chr , "OK\n" );
259
+ return ;
255
260
}
256
261
257
262
QLIST_FOREACH (ngl , & dev -> gpios , node ) {
@@ -261,16 +266,42 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
261
266
}
262
267
if (words [0 ][14 ] == 'o' ) {
263
268
qemu_irq_intercept_out (& ngl -> out , qtest_irq_handler ,
264
- ngl -> num_out );
269
+ id , ngl -> num_out );
265
270
} else {
266
271
qemu_irq_intercept_in (ngl -> in , qtest_irq_handler ,
267
- ngl -> num_in );
272
+ id , ngl -> num_in );
268
273
}
269
274
}
270
275
irq_intercept_dev = dev ;
271
276
qtest_send_prefix (chr );
272
277
qtest_send (chr , "OK\n" );
273
278
279
+ } else if (strcmp (words [0 ], "set_irq_in" ) == 0 ) {
280
+ DeviceState * dev ;
281
+ qemu_irq irq ;
282
+ unsigned n , level ;
283
+
284
+ g_assert (words [1 ]);
285
+ dev = DEVICE (object_resolve_path (words [1 ], NULL ));
286
+ if (!dev ) {
287
+ qtest_send_prefix (chr );
288
+ qtest_send (chr , "FAIL Unknown device\n" );
289
+ return ;
290
+ }
291
+
292
+ g_assert (words [2 ]);
293
+ n = strtoul (words [2 ], NULL , 0 );
294
+ irq = qdev_get_gpio_in (dev , n );
295
+
296
+ g_assert (words [3 ]);
297
+ if (strcmp (words [3 ], "raise" ) == 0 ) {
298
+ level = 1 ;
299
+ } else {
300
+ level = 0 ;
301
+ }
302
+ qemu_set_irq (irq , level );
303
+
304
+ qtest_send (chr , "OK\n" );
274
305
} else if (strcmp (words [0 ], "outb" ) == 0 ||
275
306
strcmp (words [0 ], "outw" ) == 0 ||
276
307
strcmp (words [0 ], "outl" ) == 0 ) {
@@ -475,8 +506,6 @@ static int qtest_can_read(void *opaque)
475
506
476
507
static void qtest_event (void * opaque , int event )
477
508
{
478
- int i ;
479
-
480
509
switch (event ) {
481
510
case CHR_EVENT_OPENED :
482
511
/*
@@ -485,9 +514,6 @@ static void qtest_event(void *opaque, int event)
485
514
* used. Injects an extra reset even when it's not used, and
486
515
* that can mess up tests, e.g. -boot once.
487
516
*/
488
- for (i = 0 ; i < ARRAY_SIZE (irq_levels ); i ++ ) {
489
- irq_levels [i ] = 0 ;
490
- }
491
517
qemu_gettimeofday (& start_time );
492
518
qtest_opened = true;
493
519
if (qtest_log_fp ) {
0 commit comments