Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
This commit is contained in:
257
src/timer.h
257
src/timer.h
@@ -1,57 +1,228 @@
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
|
||||
#include "cpu/cpu.h"
|
||||
|
||||
extern int64_t timer_start;
|
||||
/* Maximum period, currently 1 second. */
|
||||
#define MAX_USEC64 1000000ULL
|
||||
#define MAX_USEC 1000000.0
|
||||
|
||||
#define timer_start_period(cycles) \
|
||||
timer_start = cycles;
|
||||
#define TIMER_SPLIT 2
|
||||
#define TIMER_ENABLED 1
|
||||
|
||||
#define timer_end_period(cycles) \
|
||||
do \
|
||||
{ \
|
||||
int64_t diff = timer_start - (cycles); \
|
||||
timer_count -= diff; \
|
||||
timer_start = cycles; \
|
||||
if (timer_count <= 0) \
|
||||
{ \
|
||||
timer_process(); \
|
||||
timer_update_outstanding(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define timer_clock() \
|
||||
do \
|
||||
{ \
|
||||
int64_t diff; \
|
||||
if (AT) \
|
||||
{ \
|
||||
diff = timer_start - (cycles << TIMER_SHIFT); \
|
||||
timer_start = cycles << TIMER_SHIFT; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
diff = timer_start - (cycles * xt_cpu_multi); \
|
||||
timer_start = cycles * xt_cpu_multi; \
|
||||
} \
|
||||
timer_count -= diff; \
|
||||
timer_process(); \
|
||||
timer_update_outstanding(); \
|
||||
} while (0)
|
||||
#pragma pack(push,1)
|
||||
typedef struct
|
||||
{
|
||||
uint32_t frac;
|
||||
uint32_t integer;
|
||||
} ts_struct_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
extern void timer_process(void);
|
||||
extern void timer_update_outstanding(void);
|
||||
extern void timer_reset(void);
|
||||
extern int64_t timer_add(void (*callback)(void *priv), int64_t *count, int64_t *enable, void *priv);
|
||||
extern void timer_set_callback(int64_t timer, void (*callback)(void *priv));
|
||||
typedef union
|
||||
{
|
||||
uint64_t ts64;
|
||||
ts_struct_t ts32;
|
||||
} ts_t;
|
||||
|
||||
#define TIMER_ALWAYS_ENABLED &timer_one
|
||||
|
||||
extern int64_t timer_count;
|
||||
extern int64_t timer_one;
|
||||
/*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a
|
||||
32:32 fixed point format, with the integer part compared against the TSC. The
|
||||
fractional part is used when advancing the timestamp to ensure a more accurate
|
||||
period.
|
||||
|
||||
As the timer only stores 32 bits of integer timestamp, and the TSC is 64 bits,
|
||||
the timer period can only be at most 0x7fffffff CPU cycles. To allow room for
|
||||
(optimistic) CPU frequency growth, timer period must be at most 1 second.
|
||||
|
||||
#define TIMER_SHIFT 6
|
||||
When a timer callback is called, the timer has been disabled. If the timer is
|
||||
to repeat, the callback must call timer_advance_u64(). This is a change from
|
||||
the old timer API.*/
|
||||
typedef struct pc_timer_t
|
||||
{
|
||||
#ifdef USE_PCEM_TIMER
|
||||
uint32_t ts_integer;
|
||||
uint32_t ts_frac;
|
||||
#else
|
||||
ts_t ts;
|
||||
#endif
|
||||
int flags, pad; /* The flags are defined above. */
|
||||
double period; /* This is used for large period timers to count
|
||||
the microseconds and split the period. */
|
||||
|
||||
extern int64_t TIMER_USEC;
|
||||
void (*callback)(void *p);
|
||||
void *p;
|
||||
|
||||
struct pc_timer_t *prev, *next;
|
||||
} pc_timer_t;
|
||||
|
||||
/*Timestamp of nearest enabled timer. CPU emulation must call timer_process()
|
||||
when TSC matches or exceeds this.*/
|
||||
extern uint32_t timer_target;
|
||||
|
||||
/*Enable timer, without updating timestamp*/
|
||||
extern void timer_enable(pc_timer_t *timer);
|
||||
/*Disable timer*/
|
||||
extern void timer_disable(pc_timer_t *timer);
|
||||
|
||||
/*Process any pending timers*/
|
||||
extern void timer_process(void);
|
||||
|
||||
/*Reset timer system*/
|
||||
extern void timer_close(void);
|
||||
extern void timer_init(void);
|
||||
|
||||
/*Add new timer. If start_timer is set, timer will be enabled with a zero
|
||||
timestamp - this is useful for permanently enabled timers*/
|
||||
extern void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer);
|
||||
|
||||
/*1us in 32:32 format*/
|
||||
extern uint64_t TIMER_USEC;
|
||||
|
||||
/*True if timer a expires before timer b*/
|
||||
#if 0
|
||||
#define TIMER_LESS_THAN(a, b) ((int32_t)((a)->ts_integer - (b)->ts_integer) <= 0)
|
||||
#else
|
||||
#define TIMER_LESS_THAN(a, b) ((int64_t)((a)->ts.ts64 - (b)->ts.ts64) <= 0)
|
||||
#endif
|
||||
/*True if timer a expires before 32 bit integer timestamp b*/
|
||||
#if 0
|
||||
#define TIMER_LESS_THAN_VAL(a, b) ((int32_t)((a)->ts_integer - (b)) <= 0)
|
||||
#else
|
||||
#define TIMER_LESS_THAN_VAL(a, b) ((int32_t)((a)->ts.ts32.integer - (b)) <= 0)
|
||||
#endif
|
||||
/*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/
|
||||
#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t)((a) - (b)) <= 0)
|
||||
|
||||
|
||||
/*Advance timer by delay, specified in 32:32 format. This should be used to
|
||||
resume a recurring timer in a callback routine*/
|
||||
static __inline void
|
||||
timer_advance_u64(pc_timer_t *timer, uint64_t delay)
|
||||
{
|
||||
#if 0
|
||||
uint32_t int_delay = delay >> 32;
|
||||
uint32_t frac_delay = delay & 0xffffffff;
|
||||
|
||||
if ((frac_delay + timer->ts_frac) < frac_delay)
|
||||
timer->ts_integer++;
|
||||
timer->ts_frac += frac_delay;
|
||||
timer->ts_integer += int_delay;
|
||||
#else
|
||||
timer->ts.ts64 += delay;
|
||||
#endif
|
||||
|
||||
timer_enable(timer);
|
||||
}
|
||||
|
||||
|
||||
/*Set a timer to the given delay, specified in 32:32 format. This should be used
|
||||
when starting a timer*/
|
||||
static __inline void
|
||||
timer_set_delay_u64(pc_timer_t *timer, uint64_t delay)
|
||||
{
|
||||
#if 0
|
||||
uint32_t int_delay = delay >> 32;
|
||||
uint32_t frac_delay = delay & 0xffffffff;
|
||||
|
||||
timer->ts_frac = frac_delay;
|
||||
timer->ts_integer = int_delay + (uint32_t)tsc;
|
||||
#else
|
||||
timer->ts.ts64 = 0ULL;
|
||||
timer->ts.ts32.integer = tsc;
|
||||
timer->ts.ts64 += delay;
|
||||
#endif
|
||||
|
||||
timer_enable(timer);
|
||||
}
|
||||
|
||||
|
||||
/*True if timer currently enabled*/
|
||||
static __inline int
|
||||
timer_is_enabled(pc_timer_t *timer)
|
||||
{
|
||||
return !!(timer->flags & TIMER_ENABLED);
|
||||
}
|
||||
|
||||
|
||||
/*Return integer timestamp of timer*/
|
||||
static __inline uint32_t
|
||||
timer_get_ts_int(pc_timer_t *timer)
|
||||
{
|
||||
#if 0
|
||||
return timer->ts_integer;
|
||||
#else
|
||||
return timer->ts.ts32.integer;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*Return remaining time before timer expires, in us. If the timer has already
|
||||
expired then return 0*/
|
||||
static __inline uint32_t
|
||||
timer_get_remaining_us(pc_timer_t *timer)
|
||||
{
|
||||
int64_t remaining;
|
||||
|
||||
if (timer->flags & TIMER_ENABLED) {
|
||||
#if 0
|
||||
remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32);
|
||||
#else
|
||||
remaining = (int64_t) (timer->ts.ts64 - (uint64_t)(tsc << 32));
|
||||
#endif
|
||||
|
||||
if (remaining < 0)
|
||||
return 0;
|
||||
return remaining / TIMER_USEC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*Return remaining time before timer expires, in 32:32 timestamp format. If the
|
||||
timer has already expired then return 0*/
|
||||
static __inline uint64_t
|
||||
timer_get_remaining_u64(pc_timer_t *timer)
|
||||
{
|
||||
int64_t remaining;
|
||||
|
||||
if (timer->flags & TIMER_ENABLED) {
|
||||
#if 0
|
||||
remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32);
|
||||
#else
|
||||
remaining = (int64_t) (timer->ts.ts64 - (uint64_t)(tsc << 32));
|
||||
#endif
|
||||
|
||||
if (remaining < 0)
|
||||
return 0;
|
||||
return remaining;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*Set timer callback function*/
|
||||
static __inline void
|
||||
timer_set_callback(pc_timer_t *timer, void (*callback)(void *p))
|
||||
{
|
||||
timer->callback = callback;
|
||||
}
|
||||
|
||||
|
||||
/*Set timer private data*/
|
||||
static __inline void
|
||||
timer_set_p(pc_timer_t *timer, void *p)
|
||||
{
|
||||
timer->p = p;
|
||||
}
|
||||
|
||||
|
||||
/* The API for big timer periods starts here. */
|
||||
extern void timer_stop(pc_timer_t *timer);
|
||||
extern void timer_advance_ex(pc_timer_t *timer, int start);
|
||||
extern void timer_on(pc_timer_t *timer, double period, int start);
|
||||
extern void timer_on_auto(pc_timer_t *timer, double period);
|
||||
|
||||
#endif /*_TIMER_H_*/
|
||||
|
||||
Reference in New Issue
Block a user