120 lines
4.8 KiB
C
120 lines
4.8 KiB
C
/* Le masque LCD et l'acquittement doivent survivre à plusieurs resprings. */
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/main-loop.h"
|
|
#include "sysemu/cpus.h"
|
|
#include "hw/arm/ipod_touch_lcd.c"
|
|
#define ipod_touch_machine_types test_mipi_register_types
|
|
#include "hw/arm/ipod_touch_mipi_dsi.c"
|
|
#undef ipod_touch_machine_types
|
|
#include "hw/arm/ipod_touch_tvout.c"
|
|
|
|
static void irq_changed(void *opaque, int n, int level)
|
|
{
|
|
*(int *)opaque = level;
|
|
}
|
|
|
|
static void test_interrupt_reenable(void)
|
|
{
|
|
IPodTouchLCDState *s = IPOD_TOUCH_LCD(object_new(TYPE_IPOD_TOUCH_LCD));
|
|
int level = 0;
|
|
qemu_irq irq = qemu_allocate_irq(irq_changed, &level, 0);
|
|
sysbus_connect_irq(SYS_BUS_DEVICE(s), 0, irq);
|
|
s->refresh_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, refresh_timer_tick, s);
|
|
|
|
for (int cycle = 0; cycle < 3; cycle++) {
|
|
/* Vblank masqué : état en attente, aucune interruption CPU. */
|
|
ipod_touch_lcd_write(s, 0x8, 0, 4);
|
|
refresh_timer_tick(s);
|
|
g_assert_cmpint(level, ==, 0);
|
|
g_assert_cmpuint(ipod_touch_lcd_read(s, 0xc, 4), ==, 1);
|
|
ipod_touch_lcd_write(s, 0xc, 0xff, 4);
|
|
g_assert_cmpuint(ipod_touch_lcd_read(s, 0xc, 4), ==, 0);
|
|
|
|
/* Nouveau client : le masque réactive les vblanks après cet ACK. */
|
|
ipod_touch_lcd_write(s, 0x8, 1, 4);
|
|
g_assert_cmpint(level, ==, 0);
|
|
refresh_timer_tick(s);
|
|
g_assert_cmpint(level, ==, 1);
|
|
ipod_touch_lcd_write(s, 0xc, 2, 4);
|
|
g_assert_cmpint(level, ==, 1);
|
|
ipod_touch_lcd_write(s, 0xc, 1, 4);
|
|
g_assert_cmpint(level, ==, 0);
|
|
g_assert_cmpuint(ipod_touch_lcd_read(s, 0x8, 4), ==, 1);
|
|
refresh_timer_tick(s);
|
|
g_assert_cmpint(level, ==, 1);
|
|
ipod_touch_lcd_write(s, 0x8, 0, 4);
|
|
g_assert_cmpint(level, ==, 0);
|
|
ipod_touch_lcd_write(s, 0x8, 1, 4);
|
|
g_assert_cmpint(level, ==, 1);
|
|
}
|
|
ipod_touch_lcd_write(s, 0x24, 0x12340000, 4);
|
|
device_cold_reset(DEVICE(s));
|
|
g_assert_cmpint(level, ==, 0);
|
|
g_assert_cmpuint(ipod_touch_lcd_read(s, 0x8, 4), ==, 0);
|
|
g_assert_cmpuint(ipod_touch_lcd_read(s, 0xc, 4), ==, 0);
|
|
g_assert_cmpuint(ipod_touch_lcd_read(s, 0x24, 4), ==, 0);
|
|
timer_del(s->refresh_timer);
|
|
timer_free(s->refresh_timer);
|
|
object_unref(OBJECT(s));
|
|
qemu_free_irq(irq);
|
|
}
|
|
|
|
static void test_tvout_submissions(void)
|
|
{
|
|
IPodTouchTVOutState *s = IPOD_TOUCH_TVOUT(object_new(TYPE_IPOD_TOUCH_TVOUT));
|
|
int level = 0;
|
|
qemu_irq irq = qemu_allocate_irq(irq_changed, &level, 0);
|
|
sysbus_connect_irq(SYS_BUS_DEVICE(s), 0, irq);
|
|
/* L'ancien quota global cessait de répondre dès la troisième soumission. */
|
|
for (int cycle = 0; cycle < 20; cycle++) {
|
|
ipod_touch_tvout_mixer1_write(s, MXR_STATUS, 0x85, 4);
|
|
g_assert_cmpint(level, ==, 1);
|
|
ipod_touch_tvout_sdo_write(s, SDO_IRQ, 2, 4);
|
|
g_assert_cmpint(level, ==, 1);
|
|
ipod_touch_tvout_sdo_write(s, SDO_IRQ, 1, 4);
|
|
g_assert_cmpint(level, ==, 0);
|
|
}
|
|
ipod_touch_tvout_sdo_write(s, SDO_IRQMASK, 1, 4);
|
|
ipod_touch_tvout_mixer1_write(s, MXR_STATUS, 0x85, 4);
|
|
g_assert_cmpint(level, ==, 0);
|
|
g_assert_cmpuint(ipod_touch_tvout_sdo_read(s, SDO_IRQ, 4), ==, 1);
|
|
ipod_touch_tvout_sdo_write(s, SDO_IRQMASK, 0, 4);
|
|
g_assert_cmpint(level, ==, 1);
|
|
device_cold_reset(DEVICE(s));
|
|
g_assert_cmpint(level, ==, 0);
|
|
g_assert_cmpuint(ipod_touch_tvout_sdo_read(s, SDO_IRQ, 4), ==, 0);
|
|
ipod_touch_tvout_mixer1_write(s, MXR_STATUS, 0x85, 4);
|
|
g_assert_cmpint(level, ==, 1);
|
|
object_unref(OBJECT(s));
|
|
qemu_free_irq(irq);
|
|
}
|
|
|
|
static void test_panel_reset(void)
|
|
{
|
|
IPodTouchMIPIDSIState *s = IPOD_TOUCH_MIPI_DSI(object_new(TYPE_IPOD_TOUCH_MIPI_DSI));
|
|
for (int cycle = 0; cycle < 3; cycle++) {
|
|
ipod_touch_mipi_dsi_write(s, REG_CLKCTRL, DSIM_CLKCTRL_TX_REQUEST_HSCLK, 4);
|
|
g_assert_cmpuint(ipod_touch_mipi_dsi_read(s, 0, 4) & rDSIM_STATUS_TxReadyHsClk, !=, 0);
|
|
g_assert_cmpuint(ipod_touch_mipi_dsi_read(s, REG_RXFIFO, 4), ==, 0x31a);
|
|
/* Un reset pendant une réponse doit recommencer par son en-tête. */
|
|
device_cold_reset(DEVICE(s));
|
|
g_assert_cmpuint(ipod_touch_mipi_dsi_read(s, 0, 4) & rDSIM_STATUS_TxReadyHsClk, ==, 0);
|
|
g_assert_cmpuint(ipod_touch_mipi_dsi_read(s, REG_RXFIFO, 4), ==, 0x31a);
|
|
g_assert_cmpuint(ipod_touch_mipi_dsi_read(s, REG_RXFIFO, 4), ==, 0x00a1d13c);
|
|
}
|
|
object_unref(OBJECT(s));
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
g_test_init(&argc, &argv, NULL);
|
|
module_call_init(MODULE_INIT_QOM);
|
|
qemu_init_main_loop(&error_abort);
|
|
qemu_init_cpu_loop();
|
|
qemu_mutex_lock_iothread();
|
|
g_test_add_func("/ipod-lcd/interrupt-reenable", test_interrupt_reenable);
|
|
g_test_add_func("/ipod-tvout/repeated-submissions", test_tvout_submissions);
|
|
g_test_add_func("/ipod-mipi/panel-reset", test_panel_reset);
|
|
return g_test_run();
|
|
}
|