From 5bce9da97cac689fae749ee1ff78bc1fe3b238a2 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 6 Nov 2013 17:00:36 -0800 Subject: [PATCH] QVSS: Fix to get the VSYNC interrupts to be more reasonable. Addresses Issue #88. From Mike Burke The vertical sync interrupt generated in vc_svc() was too slow for Ultrix. The driver enables interrupts and then calls DELAY(20000), which I guess is 20ms. This translates to about 10000 simulated instructions, but tmxr_poll works out at ~75000 instructions. I've added a new unit to simulate just the vsync interrupts activating every 8000 instructions. This approach will completely disable the ability to idle while the QVSS device is enabled. --- VAX/vax_vc.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/VAX/vax_vc.c b/VAX/vax_vc.c index 2ef42b6c..b3cf318f 100644 --- a/VAX/vax_vc.c +++ b/VAX/vax_vc.c @@ -25,6 +25,8 @@ vc Qbus video subsystem + 06-Nov-2013 MB Increased the speed of v-sync interrupts, which + was too slow for some O/S drivers. 11-Jun-2013 MB First version */ @@ -170,6 +172,8 @@ BITFIELD vc_ic_mode_bits[] = { #define VC_XSIZE 1024 #define VC_YSIZE 864 +#define VC_MEMSIZE (1u << 16) /* video memory size */ + #define VCMAP_VLD 0x80000000 /* valid */ #define VCMAP_LN 0x00000FFF /* buffer line */ @@ -181,6 +185,8 @@ BITFIELD vc_ic_mode_bits[] = { #define CUR_V ((vc_crtc[CRTC_CSCS] & 0x20) == 0) /* cursor visible */ #define CUR_F (vc_csr & CSR_FNC) /* cursor function */ +#define VSYNC_TIME 8000 /* vertical sync interval */ + #define IOLN_QVSS 0100 extern int32 int_req[IPL_HLVL]; @@ -215,16 +221,16 @@ uint32 vc_crtc_p = 0; /* CRTC pointer */ uint32 vc_icdr = 0; /* Interrupt controller data */ uint32 vc_icsr = 0; /* Interrupt controller status */ uint32 vc_map[1024]; /* Scanline map */ -uint32 vc_buf[(1u << 16)]; /* Video memory */ +uint32 *vc_buf = NULL; /* Video memory */ uint8 vc_cur[256]; /* Cursor image */ DEVICE vc_dev; t_stat vc_rd (int32 *data, int32 PA, int32 access); t_stat vc_wr (int32 data, int32 PA, int32 access); t_stat vc_svc (UNIT *uptr); +t_stat vc_vsync (UNIT *uptr); t_stat vc_reset (DEVICE *dptr); t_stat vc_set_enable (UNIT *uptr, int32 val, char *cptr, void *desc); -void vc_powerdown (void); void vc_setint (int32 src); int32 vc_inta (void); void vc_clrint (int32 src); @@ -276,7 +282,10 @@ DEBTAB vc_debug[] = { {0} }; -UNIT vc_unit = { UDATA (&vc_svc, UNIT_IDLE, 0) }; +UNIT vc_unit[] = { + { UDATA (&vc_svc, UNIT_IDLE, 0) }, + { UDATA (&vc_vsync, UNIT_DIS+UNIT_IDLE, 0) } + }; REG vc_reg[] = { { HRDATADF (CSR, vc_csr, 16, "Control and status register", vc_csr_bits) }, @@ -312,8 +321,8 @@ MTAB vc_mod[] = { }; DEVICE vc_dev = { - "QVSS", &vc_unit, vc_reg, vc_mod, - 1, DEV_RDX, 20, 1, DEV_RDX, 8, + "QVSS", vc_unit, vc_reg, vc_mod, + 2, DEV_RDX, 20, 1, DEV_RDX, 8, NULL, NULL, &vc_reset, NULL, NULL, NULL, &vc_dib, DEV_DIS | DEV_QBUS | DEV_DEBUG, 0, @@ -368,7 +377,7 @@ uint32 rg = (PA >> 1) & 0x1F; uint32 crtc_rg, i; *data = 0; -switch ((PA >> 1) & 0x1F) { /* decode PA<1> */ +switch (rg) { case 0: /* CSR */ *data = vc_csr; @@ -454,7 +463,7 @@ uint32 rg = (PA >> 1) & 0x1F; uint32 crtc_rg; sim_debug (DBG_REG, &vc_dev, "vc_wr(%s) data=0x%04X\n", vc_regnames[(PA >> 1) & 0x1F], data); -switch ((PA >> 1) & 0x1F) { /* decode PA<1> */ +switch (rg) { case 0: /* CSR */ vc_csr = (vc_csr & ~CSR_RW) | (data & CSR_RW); @@ -774,13 +783,21 @@ sim_activate (uptr, tmxr_poll); /* reactivate */ return SCPE_OK; } +t_stat vc_vsync (UNIT *uptr) +{ +vc_setint (IRQ_VSYNC); /* VSYNC int */ +sim_activate (uptr, VSYNC_TIME); /* reactivate */ +return SCPE_OK; +} + t_stat vc_reset (DEVICE *dptr) { uint32 i; t_stat r; CLR_INT (QVSS); /* clear int req */ -sim_cancel (&vc_unit); /* stop poll */ +sim_cancel (&vc_unit[0]); /* stop poll */ +sim_cancel (&vc_unit[1]); /* stop VSYNC */ ua2681_reset (&vc_uart); /* reset DUART */ vc_intc.ptr = 0; /* interrupt controller */ @@ -800,13 +817,21 @@ for (i = 0; i < CRTC_SIZE; i++) vc_crtc[CRTC_CSCS] = 0x20; /* hide cursor */ vc_crtc_p = (CRTCP_LPF | CRTCP_VB); -if (dptr->flags & DEV_DIS) +if (dptr->flags & DEV_DIS) { + free (vc_buf); + vc_buf = NULL; return vid_close (); + } if (!vid_active) { r = vid_open (dptr, VC_XSIZE, VC_YSIZE); /* display size */ if (r != SCPE_OK) return r; + vc_buf = (uint32 *) calloc (VC_MEMSIZE, sizeof (uint32)); + if (vc_buf == NULL) { + vid_close (); + return SCPE_MEM; + } printf ("QVSS Display Created. "); vid_show_release_key (stdout, NULL, 0, NULL); printf ("\n"); @@ -816,7 +841,8 @@ if (!vid_active) { fprintf (sim_log, "\n"); } } -sim_activate_abs (&vc_unit, tmxr_poll); +sim_activate_abs (&vc_unit[0], tmxr_poll); +sim_activate_abs (&vc_unit[1], VSYNC_TIME); return auto_config (NULL, 0); /* run autoconfig */ }