dosemu2/test/func_pit_mode_2.py
geos_one 91736529d5
Some checks failed
Master / Scheduled (FULL) (push) Has been cancelled
Master / Triggered (push) Has been cancelled
Master / Triggered (ASAN) (push) Has been cancelled
Master / Triggered (FULL) (push) Has been cancelled
New upstream version 2.0pre9.2
2025-08-10 12:35:43 +02:00

139 lines
3.8 KiB
Python

def pit_mode_2(self):
self.mkfile("testit.bat", """\
pitmode2
rem end
""", newline="\r\n")
# compile sources
self.mkcom_with_ia16("pitmode2", r"""
/*
Sample program #15
Demonstrates absolute timestamping in mode two
Part of the PC Timing FAQ / Application notes
By K. Heidenstrom (kheidens@actrix.gen.nz)
Rewritten to be non-interactive and compile with ia16-elf-gcc
*/
#define _BORLANDC_SOURCE
#include <conio.h>
#include <dos.h>
#include <stdio.h>
typedef struct {
unsigned int part;
unsigned long ticks;
} __attribute__((packed)) timestamp;
// #define BIOS_TICK_COUNT_P ((volatile unsigned long far *)0x0040006CL)
volatile unsigned long __far *BIOS_TICK_COUNT_P = MK_FP(0x0040, 0x006C);
void set_mode2(void)
{
unsigned int tick_loword;
tick_loword = *BIOS_TICK_COUNT_P;
while ((unsigned int)*BIOS_TICK_COUNT_P == tick_loword)
/* do nothing */;
#if 0
asm pushf;
asm cli;
outportb(0x43, 0x34); /* Channel 0, mode 2 */
outportb(0x40, 0x00); /* Loword of divisor */
outportb(0x40, 0x00); /* Hiword of divisor */
asm popf;
#endif
asm volatile("pushf\n"
"push %%ax\n"
"cli\n"
"mov $0x34, %%al\n"
"outb %%al, $0x43\n" /* Channel 0, mode 2 */
"mov $0x00, %%al\n"
"outb %%al, $0x40\n" /* Loword of divisor */
"outb %%al, $0x40\n" /* Hiword of divisor */
"pop %%ax\n"
"popf\n"
:
:
:
);
return;
}
void get_timestamp(timestamp *tsp)
{
unsigned long tickcount1, tickcount2;
unsigned int ctcvalue;
unsigned char ctclow, ctchigh;
again:
tickcount1 = *BIOS_TICK_COUNT_P;
outportb(0x43, 0); /* Latch value */
ctclow = inportb(0x40);
ctchigh = inportb(0x40); /* Read count in progress */
ctcvalue = -((ctchigh << 8) + ctclow);
tickcount2 = *BIOS_TICK_COUNT_P;
if (tickcount2 != tickcount1)
goto again;
tsp->ticks = tickcount1;
tsp->part = ctcvalue;
return;
}
int main(void)
{
timestamp ts, ts1, ts2;
uint64_t start;
printf("Sample program #15 - Demonstrates absolute timestamping\n");
printf("Part of the PC Timing FAQ / Application notes\n");
printf("By K. Heidenstrom (kheidens@actrix.gen.nz)\n\n");
set_mode2();
// Info
get_timestamp(&ts); /* Get timestamp */
printf("Absolute timestamp: 0x%04X%04X%04X units of 0.8381 us\n", (unsigned int)(ts.ticks >> 16),
(unsigned int)(ts.ticks & 0xFFFF), ts.part);
// Continuous test for 2 minutes
printf("\nContinuous timestamp test - start\n\n");
for (start = (ts.ticks << 16) + ts.part; /* */; /* */) {
ts2.ticks = ts1.ticks;
ts2.part = ts1.part;
ts1.ticks = ts.ticks;
ts1.part = ts.part;
get_timestamp(&ts);
// printf("0x%04X%04X%04X\r", (unsigned int)(ts.ticks >> 16), (unsigned int)(ts.ticks & 0xFFFF), ts.part);
if ((ts.ticks < ts1.ticks) || ((ts.ticks == ts1.ticks) && (ts.part < ts1.part))) { /* Went backwards? */
printf("Timestamp went backwards: 0x%04X%04X%04X, 0x%04X%04X%04X, then 0x%04X%04X%04X\n",
(unsigned int)(ts2.ticks >> 16), (unsigned int)(ts2.ticks & 0xFFFF), ts2.part,
(unsigned int)(ts1.ticks >> 16), (unsigned int)(ts1.ticks & 0xFFFF), ts1.part,
(unsigned int)(ts.ticks >> 16), (unsigned int)(ts.ticks & 0xFFFF), ts.part);
}
if (((uint64_t)((ts.ticks << 16) + ts.part) - start) > 143181004) // 120 secs: 120/(0.8381/1000000)
break;
}
printf("\nContinuous timestamp test - complete\n\n");
return 0;
}
""")
starttime = self.utcnow()
results = self.runDosemu("testit.bat", config="""\
$_hdimage = "dXXXXs/c:hdtype1 +1"
$_floppy_a = ""
""", timeout=150)
endtime = self.utcnow()
self.assertIn("Continuous timestamp test - complete", results)
self.assertNotIn("Timestamp went backwards", results)
self.assertLess((endtime - starttime).seconds, 125)