Ejemplo n.º 1
0
int main() {
    unsigned int i;

#if defined(TARGET_WINDOWS) && TARGET_WINDOWS == 32 && !defined(WIN386)
    /* As a 32-bit Windows application, we *can* talk directly to the 8254 but only if running under Windows 3.1/95/98/ME.
     * Windows NT would never permit us to directly talk to IO.
     *
     * However if we're a Win16 program or Watcom 386 application, Windows NT will trap and emulate the 8254 through NTVDM.EXE */
    detect_windows();
    if (!(windows_mode == WINDOWS_REAL || windows_mode == WINDOWS_STANDARD || windows_mode == WINDOWS_ENHANCED)) {
        printf("This test program is only applicable to Windows 3.x/9x\n");
        return 1;
    }
#endif

	printf("8254 library test program\n");
	if (!probe_8254()) {
		printf("Chip not present. Your computer might be 2010-era hardware that dropped support for it.\n");
		return 1;
	}

    printf("This program tests the ability for emulation to handle\n");
    printf("rapid changes to PC speaker frequency.\n");
    printf("Apogee/Duke Nukem style sound effects.\n");

#if defined(NO_PORT_43)
# undef write_8254_pc_speaker
#endif

	write_8254_system_timer(0); /* restore normal function to prevent BIOS from going crazy */
    write_8254_pc_speaker(0); /* make sure the PIT timer is in mode 3 (square wave) */

    printf("Rapid ramping (entry)\n");
    play_sfx(duke_entry);

    printf("Rapid ramping (entry) alternate with extra delay\n");
    play_sfx(duke_entry_alt);

    printf("Rapid ramping (item)\n");
    for (i=0;i < 8;i++) play_sfx(duke_item);

    printf("Rapid ramping (item) alternate\n");
    for (i=0;i < 8;i++) play_sfx(duke_item_alt);

	write_8254_system_timer(0); /* restore normal function to prevent BIOS from going crazy */
	return 0;
}
Ejemplo n.º 2
0
int main(int argc,char **argv) {
    struct acpi_rsdt_header sdth;
    acpi_memaddr_t addr;
    unsigned long i,max;
    uint32_t tmp32,tmplen;
    char tmp[32];

    for (i=1;i < (unsigned long)argc;) {
        const char *a = argv[(unsigned int)(i++)];

        if (*a == '-' || *a == '/') {
            do { a++; } while (*a == '-' || *a == '/');

            if (!strcmp(a,"?") || !strcmp(a,"h") || !strcmp(a,"help")) {
                help();
                return 1;
            }
            else if (!strcmp(a,"32")) {
                acpi_use_rsdt_32 = 1;
            }
            else {
                fprintf(stderr,"Unknown switch '%s'\n",a);
                help();
                return 1;
            }
        }
        else {
            fprintf(stderr,"Unknown arg '%s'\n",a);
            help();
            return 1;
        }
    }

    if (!probe_8254()) {
        printf("Cannot init 8254 timer\n");
        return 1;
    }
    if (!probe_8259()) {
        printf("Cannot init 8259 PIC\n");
        return 1;
    }
    cpu_probe();
    probe_dos();
    detect_windows();
#if TARGET_MSDOS == 32
    probe_dpmi();
    dos_ltp_probe();
#endif

#if TARGET_MSDOS == 16
    if (!flatrealmode_setup(FLATREALMODE_4GB)) {
        printf("Unable to set up flat real mode (needed for 16-bit builds)\n");
        printf("Most ACPI functions require access to the full 4GB range.\n");
        return 1;
    }
#endif

    if (!acpi_probe()) {
        printf("ACPI BIOS not found\n");
        return 1;
    }
    assert(acpi_rsdp != NULL);
    printf("ACPI %u.0 structure at 0x%05lX\n",acpi_rsdp->revision+1,(unsigned long)acpi_rsdp_location);

    memcpy(tmp,(char*)(&(acpi_rsdp->OEM_id)),6); tmp[6]=0;
    printf("ACPI OEM ID '%s', RSDT address (32-bit) 0x%08lX Length %lu\n",tmp,
        (unsigned long)(acpi_rsdp->rsdt_address),
        (unsigned long)(acpi_rsdp->length));
    if (acpi_rsdp->revision != 0)
        printf("   XSDT address (64-bit) 0x%016llX\n",
            (unsigned long long)(acpi_rsdp->xsdt_address));

    printf("Chosen RSDT/XSDT at 0x%08llX\n",(unsigned long long)acpi_rsdt_location);

    if (acpi_rsdt != NULL) {
        memcpy(tmp,(void*)(acpi_rsdt->signature),4); tmp[4] = 0;
        printf("  '%s': len=%lu rev=%u\n",tmp,(unsigned long)acpi_rsdt->length,
            acpi_rsdt->revision);

        memcpy(tmp,(void*)(acpi_rsdt->OEM_id),6); tmp[6] = 0;
        printf("  OEM id: '%s'\n",tmp);

        memcpy(tmp,(void*)(acpi_rsdt->OEM_table_id),8); tmp[8] = 0;
        printf("  OEM table id: '%s' rev %lu\n",tmp,
            (unsigned long)acpi_rsdt->OEM_revision);

        memcpy(tmp,(void*)(&(acpi_rsdt->creator_id)),4); tmp[4] = 0;
        printf("  Creator: '%s' rev %lu\n",tmp,
            (unsigned long)acpi_rsdt->creator_revision);
    }

    max = acpi_rsdt_entries();
    if (acpi_rsdt_is_xsdt()) {
        printf("Showing XSDT, %lu entries\n",max);
    }
    else {
        printf("Showing RSDT, %lu entries\n",max);
    }

    for (i=0;i < max;i++) {
        addr = acpi_rsdt_entry(i);
        printf(" [%lu] 0x%08llX ",i,(unsigned long long)addr);
        if (addr != 0ULL) {
            tmp32 = acpi_mem_readd(addr);
            tmplen = 0;

            memcpy(tmp,&tmp32,4); tmp[4] = 0;
            if (acpi_probe_rsdt_check(addr,tmp32,&tmplen)) {
                acpi_memcpy_from_phys(&sdth,addr,sizeof(struct acpi_rsdt_header));

                printf("'%s' len=0x%lX rev=%u ",tmp,(unsigned long)tmplen,sdth.revision);

                memcpy(tmp,&sdth.OEM_id,6); tmp[6] = 0;
                printf("OEM id: '%s'\n",tmp);

                memcpy(tmp,&sdth.OEM_table_id,8); tmp[8] = 0;
                printf("OEM table id: '%s' rev %u ",tmp,sdth.OEM_revision);

                memcpy(tmp,&sdth.creator_id,4); tmp[4] = 0;
                printf("Creator id: '%s' rev %u",tmp,sdth.creator_revision);

                if (!memcmp(sdth.signature,"MCFG",4)) {
                    struct acpi_mcfg_entry entry;
                    uint64_t o = addr + 44;
                    unsigned int count;

                    printf("\nPCI Express map:");
                    assert(sizeof(struct acpi_mcfg_entry) == 16);
                    count = (unsigned int)(tmplen / sizeof(struct acpi_mcfg_entry));
                    while (count != 0) {
                        acpi_memcpy_from_phys(&entry,o,sizeof(struct acpi_mcfg_entry));
                        o += sizeof(struct acpi_mcfg_entry);

                        /* Some bioses I test against seem to return enough for 3 but fill in only 1? */
                        if (entry.base_address != 0ULL || entry.start_pci_bus_number != 0 || entry.end_pci_bus_number != 0) {
                            uint64_t sz;

                            if (entry.start_pci_bus_number > entry.end_pci_bus_number)
                                entry.start_pci_bus_number = entry.end_pci_bus_number;

                            sz = (((unsigned long long)(entry.end_pci_bus_number - entry.start_pci_bus_number)) + 1ULL) << 20ULL;
                            printf("\n  @0x%08llX-0x%08llX seg=%u bus=%u-%u",
                                (unsigned long long)entry.base_address,
                                (unsigned long long)(entry.base_address + sz - 1ULL),
                                (unsigned int)entry.pci_segment_group_number,
                                (unsigned int)entry.start_pci_bus_number,
                                (unsigned int)entry.end_pci_bus_number);
                        }

                        count--;
                    }
                }
            }
            else {
                printf("'%s' check failed",tmp);
            }
        }
        printf("\n");
    }

    acpi_free();
    return 0;
}
Ejemplo n.º 3
0
int main(int argc,char **argv) {
	unsigned int req_ver = 0;
	unsigned int dont_disconnect = 0;
	unsigned int req_mode = APM_CONNECT_NONE;
	const char *action = NULL;
	int i;

	for (i=1;i < argc;) {
		const char *a = argv[i++];

		if (*a == '/' || *a == '-') {
			do { a++; } while (*a == '/' || *a == '-');

			if (!strncmp(a,"v1.",3)) {
				a += 3;
				req_ver = 0x100 + (atoi(a) & 0xFF);
			}
			else if (!strcmp(a,"vn")) {
				req_ver = REQ_VER_NONE;
			}
			else if (!strcmp(a,"nd")) {
				dont_disconnect = 1;
			}
			else if (!strcmp(a,"h") || !strcmp(a,"help")) {
				help();
			}
			else if (!strncmp(a,"if:",3)) {
				a += 3;
				if (!strcmp(a,"real"))
					req_mode = APM_CONNECT_REALMODE;
				else if (!strcmp(a,"16pm"))
					req_mode = APM_CONNECT_16_PM;
				else if (!strcmp(a,"32pm"))
					req_mode = APM_CONNECT_32_PM;
				else {
					fprintf(stderr,"Unknown interface %s\n",a);
					return 1;
				}
			}
			else {
				fprintf(stderr,"Unknown param '%s'\n",a);
				help();
				return 1;
			}
		}
		else if (action == NULL) {
			action = a;
		}
		else {
			fprintf(stderr,"Unknown param\n");
			return 1;
		}
	}

	if (!probe_8254()) {
		printf("Cannot init 8254 timer\n");
		return 1;
	}
	if (!probe_8259()) {
		printf("Cannot init 8259 PIC\n");
		return 1;
	}
	probe_dos();
	detect_windows();
	if (!apm_bios_probe()) {
		printf("APM BIOS not found\n");
		return 1;
	}

	if (req_mode == APM_CONNECT_NONE)
		req_mode = APM_CONNECT_REALMODE;

	printf("APM BIOS v%u.%u: ",apm_bios->major,apm_bios->minor);
	if (apm_bios->flags & APM_FL_16BIT_PM) printf("[16-bit pm] ");
	if (apm_bios->flags & APM_FL_32BIT_PM) printf("[32-bit pm] ");
	if (apm_bios->flags & APM_FL_CPU_IDLE_SLOWS) printf("[cpu-idle-slow] ");
	if (apm_bios->flags & APM_FL_PM_DISABLED) printf("[disabled] ");
	if (apm_bios->flags & APM_FL_PM_DISENGAGED) printf("[disengaged] ");
	printf("\n");

	if (req_ver >= 0x100) apm_bios->version_want = req_ver;

	if (req_ver != REQ_VER_NONE) {
		if (!apm_bios_connect(req_mode)) {
			fprintf(stderr,"Failed to connect to APM BIOS (last=0x%02X)\n",apm_bios->last_error);
			return 1;
		}

		printf("Connected to APM BIOS v%u.%u interface\n",apm_bios->major_neg,apm_bios->minor_neg);
		printf("  batteries:    %u\n",apm_bios->batteries);
		printf("  capabilities:\n");
		if (apm_bios->capabilities & 1) printf("    Can enter global standby state\n");
		if (apm_bios->capabilities & 2) printf("    Can enter global suspend state\n");
		if (apm_bios->capabilities & 4) printf("    Resume timer will wake from standby\n");
		if (apm_bios->capabilities & 8) printf("    Resume timer will wake from suspend\n");
		if (apm_bios->capabilities & 16) printf("    Resume on ring will wake from standby\n");
		if (apm_bios->capabilities & 32) printf("    Resume on ring will wake from suspend\n");
		if (apm_bios->capabilities & 64) printf("    PCMCIA ring indicator will wake up from standby\n");
		if (apm_bios->capabilities & 128) printf("    PCMCIA ring indicator will wake up from suspend\n");
		printf("\n");
	}

	if (action == NULL) {
	}
	else if (!strcmp(action,"cpu-idle")) {
		printf("Issuing CPU idle command\n");
		if (!apm_bios_cpu_idle())
			fprintf(stderr,"CPU Idle failed\n");
	}
	else if (!strcmp(action,"cpu-busy")) {
		printf("Issuing CPU busy command\n");
		if (!apm_bios_cpu_busy())
			fprintf(stderr,"CPU Busy failed\n");
	}
	else if (!strcmp(action,"events")) {
		while (1) {
			signed long ev = apm_bios_pm_evnet();
			if (ev >= 0LL) {
				printf("Event 0x%04X\n",(unsigned int)ev);
			}

			if (kbhit()) {
				if (getch() == 27) break;
			}
		}
	}
	else if (!strcmp(action,"status")) {
		apm_bios_update_status();

		printf("AC=0x%X Batt=0x%X BattFlag=0x%X BattPercent=%u BattLife=%u%s\n",
			apm_bios->status_ac,
			apm_bios->status_battery,
			apm_bios->status_battery_flag,
			apm_bios->status_battery_life,
			apm_bios->status_battery_time&0x7FFF,
			(apm_bios->status_battery_time&0x8000)?"m":"s");
	}
	else if (!strcmp(action,"standby")) {
		if (!apm_bios_power_state(APM_POWER_STANDBY))
			fprintf(stderr,"Unable to set power state\n");
	}
	else if (!strcmp(action,"suspend")) {
		if (!apm_bios_power_state(APM_POWER_SUSPEND))
			fprintf(stderr,"Unable to set power state\n");
	}
	else if (!strcmp(action,"off")) {
		if (!apm_bios_power_state(APM_POWER_OFF))
			fprintf(stderr,"Unable to set power state\n");
	}

	if (req_ver != REQ_VER_NONE && !dont_disconnect) {
		if (!apm_bios_connect(APM_CONNECT_NONE)) {
			fprintf(stderr,"Failed to disconnect\n");
		}

		printf("Disconnected APM BIOS\n");
	}

	return 0;
}
Ejemplo n.º 4
0
int main() {
	struct t8254_readback_t readback;
	t8254_time_t tick[3];
	unsigned int i;

	printf("8254 library test program\n");
	if (!probe_8254()) {
		printf("Chip not present. Your computer might be 2010-era hardware that dropped support for it.\n");
		return 1;
	}
	if (!probe_8259()) {
		printf("8259 interrupt controller not present. Your computer might be 2010-era hardware that dropped support for it.\n");
		return 1;
	}

	printf("8254 base clock: %luHz\n",T8254_REF_CLOCK_HZ);

	speaker_rate = T8254_REF_CLOCK_HZ / 400UL;	/* 400Hz */

	prev_irq0 = _dos_getvect(T8254_IRQ+0x08);
	_dos_setvect(T8254_IRQ+0x8,irq0);

	_cli();
	write_8254_pc_speaker(speaker_rate);
	write_8254_system_timer(max);
	_sti();

#ifdef TARGET_PC98
	/* PC-98 does not have IRQ0 running by default */
	p8259_unmask(T8254_IRQ);
#endif

	while (1) {
		if (kbhit()) {
			int c = getch();
			if (c == 27)
				break;
			else if (c == '-') {
				max -= 80;
				if (max > (0xFFFF-80))
					max = 0xFFFF;

				_cli();
				write_8254_system_timer(max);
				_sti();
			}
			else if (c == '=') {
				max += 110;
				if (max < 110 || max > (0xFFFF-110))
					max = 0xFFFF;
	
				_cli();
				write_8254_system_timer(max);
				_sti();
			}
			/* play with timer 2 and the PC speaker gate */
			else if (c == 'p') {
				unsigned char on = (t8254_pc_speaker_read_gate() != 0) ? 1 : 0;
				if (on) t8254_pc_speaker_set_gate(0);
				else t8254_pc_speaker_set_gate(3);
			}
			else if (c == '1') {
#ifndef TARGET_PC98
				unsigned char v = t8254_pc_speaker_read_gate();
				t8254_pc_speaker_set_gate(v ^ PC_SPEAKER_OUTPUT_TTL_AND_GATE);
#endif
			}
			else if (c == '2') {
#ifndef TARGET_PC98
				unsigned char v = t8254_pc_speaker_read_gate();
				t8254_pc_speaker_set_gate(v ^ PC_SPEAKER_COUNTER_2_GATE);
#endif
			}
			else if (c == '[') {
				speaker_rate += 110;
				if (speaker_rate > (0xFFFF-110) || speaker_rate < 110)
					speaker_rate = 0xFFFF;

				write_8254_pc_speaker(speaker_rate);
			}
			else if (c == ']') {
				speaker_rate -= 110;
				if (speaker_rate > (0xFFFF-110))
					speaker_rate = 0;

				write_8254_pc_speaker(speaker_rate);
			}
			else if (c == 'w') {
				printf("\n");
				pulse_width_test();
				_cli();
				write_8254_system_timer(max);
				_sti();
				printf("\n");
			}
			else if (c == 'z') {
				/* sleep-wait loop test */
				unsigned long delay_ticks;
				unsigned long z;
				unsigned int c,cmax;

				printf("\nDelay interval in us? ");
				z = 1000000; scanf("%lu",&z);

				delay_ticks = t8254_us2ticks(z);
				printf("  %lu = %lu ticks\n",z,delay_ticks);

				if (delay_ticks == 0UL)	cmax = (unsigned int)(T8254_REF_CLOCK_HZ / 20UL);
				else			cmax = (unsigned int)(T8254_REF_CLOCK_HZ / 20UL / (unsigned long)delay_ticks);
				if (cmax == 0) cmax = 1;

				write_8254_pc_speaker(T8254_REF_CLOCK_HZ / 400UL); /* tick as fast as possible */
				while (1) {
					if (kbhit()) {
						if (getch() == 27) break;
					}

					for (c=0;c < cmax;c++) {
						t8254_pc_speaker_set_gate(3);
						t8254_wait(delay_ticks);
						t8254_pc_speaker_set_gate(0);
						t8254_wait(delay_ticks);
					}
				}
			}
			else if (c == 'd') {
				printf("\n                                    \nDetail mode, hit 'd' again to exit: [WARNING: 8254 only]\n");
				while (1) {
					if (kbhit()) {
						int c = getch();
						if (c == 'd') {
							break;
						}
					}

					_cli();
					readback_8254(T8254_READBACK_ALL,&readback);
					_sti();
					printf("\x0D");
					for (i=0;i <= 2;i++) {
						printf("[%u] stat=%02x count=%04x  ",i,
							readback.timer[i].status,
							readback.timer[i].count);
					}
					fflush(stdout);
				}
				printf("\n");
			}
		}

		for (i=0;i <= 2;i++) tick[i] = read_8254(i);

		/* BUG: DOSBox/DOSBox-X appear to have a bug where the PC speaker readback toggles
		 *      regardless of the GATE input to Counter 2. Bring GATE low (setting bit 1
		 *      of port 61h to 0) is supposed to cause Counter 2 to stop. The AND gate
		 *      after the output (bit 0 of port 61h) is not supposed to affect the readback. */
		printf("\x0D %04x %04x %04x max=%04x count=%04x SPKR=%u",tick[0],tick[1],tick[2],
			max,counter,read_8254_pc_speaker_output()!=0?1:0);
		fflush(stdout);
	}
	printf("\n");

#ifdef TARGET_PC98
	/* PC-98 does not have IRQ0 running by default */
	p8259_mask(T8254_IRQ);
#endif

	_cli();
	write_8254_pc_speaker(0);
	t8254_pc_speaker_set_gate(0);
	_dos_setvect(T8254_IRQ+0x8,prev_irq0);
	_sti();

	write_8254_system_timer(0xFFFF); /* restore normal function to prevent BIOS from going crazy */
	return 0;
}
Ejemplo n.º 5
0
int main() {
#if defined(TARGET_WINDOWS)
	HWND hwnd;
#endif
	unsigned char redraw;
	int c;

	probe_dos();
	detect_windows();

#if !defined(TARGET_WINDOWS)
	if (!probe_8254()) {
		printf("8254 not found (I need this for time-sensitive portions of the driver)\n");
		return 1;
	}
#endif

#if defined(TARGET_WINDOWS)
# ifdef WIN_STDOUT_CONSOLE
	hwnd = _win_hwnd();
# else
	hwnd = GetFocus();

	printf("WARNING: The Win32 console version is experimental. It generally works...\n");
	printf("         but can run into problems if focus is taken or if the console window\n");
	printf("         is started minimized or maximized. ENTER to continue, ESC to cancel.\n");
	printf("         If this console is full-screen, hit ALT+ENTER to switch to window.\n");
	do {
		c = getch();
		if (c == 27) return 1;
	} while (c != 13);
# endif

# if TARGET_WINDOWS == 32
	if (!InitWin16EB()) {
		MessageBox(hwnd,"Failed to init win16eb","Win16eb",MB_OK);
		return 1;
	}
# endif

	/* setup DISPDIB */
	if (DisplayDibLoadDLL()) {
		MessageBox(hwnd,dispDibLastError,"Failed to load DISPDIB.DLL",MB_OK);
		return 1;
	}

	if (DisplayDibCreateWindow(hwnd)) {
		MessageBox(hwnd,dispDibLastError,"Failed to create DispDib window",MB_OK);
		return 1;
	}

	if (DisplayDibGenerateTestImage()) {
		MessageBox(hwnd,dispDibLastError,"Failed to generate test card",MB_OK);
		return 1;
	}

	if (DisplayDibDoBegin()) {
		MessageBox(hwnd,dispDibLastError,"Failed to begin display",MB_OK);
		return 1;
	}
#endif

	if (!probe_vga()) {
#if defined(TARGET_WINDOWS)
		DisplayDibDoEnd();
		DisplayDibUnloadDLL();
		MessageBox(hwnd,"Probe failed","VGA lib",MB_OK);
#else
		printf("VGA probe failed\n");
#endif
		return 1;
	}

	int10_setmode(3);
	update_state_from_vga();

	redraw = 1;
	while (1) {
		if (redraw) {
			/* position the cursor to home */
			vga_moveto(0,0);
			vga_sync_bios_cursor();

			printf("ESC  Exit to DOS       A. 320x200x256 VGA\n");
		}

		c = getch();
		if (c == 27)
			break;
		else if (c == 'a' || c == 'A')
			v320x200x256_VGA_menu();
	}

#if defined(TARGET_WINDOWS)
	DisplayDibDoEnd();
	if (DisplayDibUnloadDLL())
		MessageBox(hwnd,dispDibLastError,"Failed to unload DISPDIB.DLL",MB_OK);

# if TARGET_MSDOS == 32
	FreeWin16EB();
# endif
#endif

	return 0;
}
Ejemplo n.º 6
0
int main(int argc,char *argv[],char *envp[]) {
	rdtsc_t start,measure,ticks_per_sec;
    unsigned char force = 0;
	double t;
	int c;

    {
        int i = 1;
        char *a;

        while (i < argc) {
            a = argv[i++];

            if (*a == '-') {
                do { a++; } while (*a == '-');

                if (!strcmp(a,"f") || !strcmp(a,"force"))
                    force = 1;
                else
                    return 1;
            }
            else {
                return 1;
            }
        }
    }

	cpu_probe();
	printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level));
	if (cpu_v86_active)
		printf(" - Your CPU is currently running me in virtual 8086 mode\n");

    if (force) {
        printf(" - You're forcing me to use RDTSC. I may crash if your CPU doesn't\n");
        printf("   support it or the environment doesn't enable it.\n");
        printf("   OK! Here we go....!\n");
    }
    else {
        if (!(cpu_flags & CPU_FLAG_CPUID)) {
            printf(" - Your CPU doesn't support CPUID, how can it support RDTSC?\n");
            return 1;
        }

        if (!(cpu_cpuid_features.a.raw[2] & 0x10)) {
            printf(" - Your CPU does not support RDTSC\n");
            return 1;
        }

        if (cpu_flags & CPU_FLAG_DONT_USE_RDTSC) {
            printf(" - Your CPU does support RDTSC but it's not recommended in this environment.\n");
            printf("   This is usually due to running a 16-bit build in pure DOS under EMM386.EXE.\n");
            return 1;
        }
    }

#if defined(TARGET_OS2)
# if TARGET_MSDOS == 32
	/* OS/2 32-bit: We can use DosQuerySysInfo() */
	printf("Measuring CPU speed, using DosQuerySysInfo(), over 3 seconds\n");
	{
		ULONG startTick,tmp;
		start = cpu_rdtsc();
		startTick = GetMsCount();
		do { tmp = GetMsCount();
		} while ((tmp - startTick) < 3000); /* NTS: <- I know this rolls over in 49 days,
		the math though should overflow the 32-bit integer and produce correct results anyway */
		measure = cpu_rdtsc();

		/* use the precise tick count to better compute ticks_per_sec */
		ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick));
		printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
		printf("             From 0x%llX to 0x%llX\n",start,measure);
	}
# else
	/* OS/2 16-bit: There is no API (that I know of) to get tick count. Use system clock. */
	printf("Measuring CPU speed, using system clock with 1-second resolution, across 3 seconds\n");
	{
		time_t startTick,tmp;

		/* wait for the immediate start of a one-second tick, then record RDTSC and count until 3 seconds */
		startTick = time(NULL);
		do { tmp = time(NULL); } while (tmp == startTick);
		start = cpu_rdtsc(); startTick = tmp;

		/* NOW! Count 3 seconds and measure CPU ticks */
		do { tmp = time(NULL);
		} while ((tmp - startTick) < 3);
		measure = cpu_rdtsc();

		/* use the precise tick count to better compute ticks_per_sec */
		ticks_per_sec = ((measure - start) * 1ULL) / ((rdtsc_t)(tmp - startTick));
		printf("Measurement: %lu seconds = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
		printf("             From 0x%llX to 0x%llX\n",start,measure);
	}
# endif
#elif defined(TARGET_WINDOWS)
# if TARGET_MSDOS == 16
	/* Windows 2.x/3.0/3.1: Use GetTickCount() or
	 * Windows 3.1: Use TOOLHELP.DLL TimerCount() which is more accurate (really?) */
	if (ToolHelpInit()) {
		TIMERINFO ti;

		ti.dwSize = sizeof(ti);
		printf("Measuring CPU speed, using TOOLHELP TimerCount() over 1 second\n");
		{
			DWORD startTick,tmp;
			start = cpu_rdtsc();
			if (!__TimerCount(&ti)) {
				printf("TimerCount() failed\n");
				return 1;
			}
			startTick = ti.dwmsSinceStart;
			do {
#  if defined(WIN_STDOUT_CONSOLE)
				_win_pump(); /* <- you MUST call this. The message pump must run, or else the timer won't advance and this loop will run forever.
			                           The fact that GetTickCount() depends on a working message pump under Windows 3.1 seems to be a rather serious
						   oversight on Microsoft's part. Note that the problem described here does not apply to Windows 9x/ME. Also note
						   the Toolhelp function TimerCount() relies on GetTickCount() as a basic for time (though Toolhelp uses VxD services
						   or direct I/O port hackery to refine the timer count) */
#  endif

				if (!__TimerCount(&ti)) {
					printf("TimerCount() failed\n");
					return 1;
				}

				tmp = ti.dwmsSinceStart;
			} while ((tmp - startTick) < 1000); /* NTS: <- I know this rolls over in 49 days,
			the math though should overflow the 32-bit integer and produce correct results anyway */
			measure = cpu_rdtsc();

			/* use the precise tick count to better compute ticks_per_sec */
			ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick));
			printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
			printf("             From 0x%llX to 0x%llX\n",start,measure);
		}
	}
	else {
# else
	{
# endif
		printf("Measuring CPU speed, using GetTickCount() over 3 second\n");
		{
			DWORD startTick,tmp;
			start = cpu_rdtsc();
			startTick = GetTickCount();
			/* NTS: Dunno yet about Windows 3.1, but Windows 95 seems to require we Yield(). If we don't, the GetTickCount() return
			 *      value never updates and we're forever stuck in a loop. */
			do {
#  if defined(WIN_STDOUT_CONSOLE)
				_win_pump(); /* <- you MUST call this. The message pump must run, or else the timer won't advance and this loop will run forever.
			                           The fact that GetTickCount() depends on a working message pump under Windows 3.1 seems to be a rather serious
						   oversight on Microsoft's part. Note that the problem described here does not apply to Windows 9x/ME */
#  endif
				tmp = GetTickCount();
			} while ((tmp - startTick) < 3000); /* NTS: <- I know this rolls over in 49 days,
			the math though should overflow the 32-bit integer and produce correct results anyway */
			measure = cpu_rdtsc();

			/* use the precise tick count to better compute ticks_per_sec */
			ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick));
			printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec);
			printf("             From 0x%llX to 0x%llX\n",start,measure);
		}
	}
#else
	/* MS-DOS: Init the 8254 timer library for precise measurement */
	if (!probe_8254()) {
		printf("Cannot init 8254 timer\n");
		return 1;
	}

    /* DOSBox-X and most motherboards leave the PIT in a mode that counts down by 2.
     * Our code sets the counter and puts it in a mode that counts down by 1.
     * We have to do this or our wait functions exit in half the time (which explains
     * why testing this code in DOSBox-X often comes up with RDTSC running at 2x
     * normal speed. */
    write_8254_system_timer(0); /* 18.2 tick/sec on our terms (proper PIT mode) */

	printf("Measuring CPU speed (relative to 8254 timer)\n");

	_cli();
	start = cpu_rdtsc();
	t8254_wait(t8254_us2ticks(1000000));
	measure = cpu_rdtsc();
	_sti();

	printf("Measurement: 1 sec = %lld ticks\n",(int64_t)(measure - start));
	printf("             From 0x%llX to 0x%llX\n",start,measure);
	ticks_per_sec = (measure - start);
#endif

	if ((int64_t)ticks_per_sec < 0) {
		printf("Cannot determine CPU cycle count\n");
		ticks_per_sec = 100000ULL;
	}

	while (1) {
		measure = cpu_rdtsc();
		t = (double)((int64_t)(measure - start));
		t /= ticks_per_sec;

		printf("\x0D" "0x%llX = %.3f   ",measure,t);
#if !defined(WINFCON_STOCK_WIN_MAIN)
		fflush(stdout); /* FIXME: The fake console code should intercept fflush() too */
#endif

		if (kbhit()) {
			c = getch();
			if (c == 0) c = getch() << 8;

			if (c == 27)
				break;
			else if (c == 'r' || c == 'R') {
				if (c == 'r' || (cpu_flags & CPU_FLAG_DONT_WRITE_RDTSC)) {
					printf("\nI am not able to write the TSC register within this environment\nYou can force me by typing SHIFT+R, don't blame me when I crash...\n");
				}
				else {
					printf("\nUsing MSR to reset TSC to 0\n");
					/* demonstrating WRMSR to write the TSC (yes, you can!) */
					cpu_rdtsc_write(start = 0ULL);
					printf("Result: 0x%llX\n",cpu_rdtsc());
				}
			}
			else if (c == 's') {
				if (c == 's' && (cpu_flags & CPU_FLAG_DONT_WRITE_RDTSC)) {
					printf("\nI am not able to write the TSC register within this environment\nYou can force me by typing SHIFT+S, don't blame me when I crash...\n");
				}
				else {
					printf("\nUsing MSR to reset TSC to 0x123456789ABCDEF\n");
					/* demonstrating WRMSR to write the TSC (yes, you can!) */
					cpu_rdtsc_write(start = 0x123456789ABCDEFULL);
					printf("Result: 0x%llX\n",cpu_rdtsc());
				}
			}
		}
	}
	printf("\n");

	return 0;
}
Ejemplo n.º 7
0
int main(int argc,char **argv,char **envp) {
	unsigned int patience;
	char tmps[128];
	uint32_t tmp;

	probe_dos();
	detect_windows();

    if (windows_mode == WINDOWS_NT) {
        printf("This program is not compatible with Windows NT\n");
        return 1;
    }

#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386)
#else
	if (!probe_8254()) {
		printf("8254 not found (I need this for time-sensitive portions of the driver)\n");
		return 1;
	}
#endif

	if (!probe_dosbox_id()) {
		printf("DOSBox integration device not found\n");
		return 1;
	}
	printf("DOSBox integration device found at I/O port %xh\n",dosbox_id_baseio);

	if (probe_dosbox_id_version_string(tmps,sizeof(tmps)))
		printf("DOSBox version string: '%s'\n",tmps);
	else
		printf("DOSBox version string N/A\n");

	/* first check that the screenshot function is available */
	dosbox_id_write_regsel(DOSBOX_ID_REG_SCREENSHOT_TRIGGER);
	tmp = dosbox_id_read_data();
	if (tmp & DOSBOX_ID_SCREENSHOT_STATUS_NOT_AVAILABLE) {
		printf("DOSBox screenshot control register not available\n");
		return 1;
	}
	else if (tmp & DOSBOX_ID_SCREENSHOT_STATUS_NOT_ENABLED) {
		printf("DOSBox screenshot control register not enabled\n");
		return 1;
	}

	if (tmp & DOSBOX_ID_SCREENSHOT_STATUS_IMAGE_IN_PROGRESS)
		printf("WARNING: Screenshot already in progress\n");

	printf("Triggering DOSBox screenshot function\n");
	dosbox_id_debug_message("Triggering screenshot function\n");

	/* trigger it */
	dosbox_id_write_regsel(DOSBOX_ID_REG_SCREENSHOT_TRIGGER);
	dosbox_id_write_data(DOSBOX_ID_SCREENSHOT_IMAGE);

	/* did it trigger it? */
	dosbox_id_write_regsel(DOSBOX_ID_REG_SCREENSHOT_TRIGGER);
	tmp = dosbox_id_read_data();
	if (!(tmp & DOSBOX_ID_SCREENSHOT_STATUS_IMAGE_IN_PROGRESS)) {
		printf("DOSBox screenshot trigger failed.\n");
		return 1;
	}

	/* wait for the screenshot to happen.
	 * DOSBox will write the screenshot when VGA vertical retrace happens, which should be 1/70th of a second.
	 * So if it doesn't happen within 1 second, then it failed. */
#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386)
	patience = 10; /* 1 second (10 x 100ms) (Windows 9x scheduler isn't THAT good!) */
#else
	patience = 1000; /* 1 second (1000 x 1ms) */
#endif
	do {
		if (--patience == 0) {
			printf("DOSBox failed to take screenshot (timeout)\n");
			return 1;
		}

#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386)
		Sleep(100); /* 100ms */
#else
		t8254_wait(t8254_us2ticks(1000)); /* 1ms */
#endif

		dosbox_id_write_regsel(DOSBOX_ID_REG_SCREENSHOT_TRIGGER);
		tmp = dosbox_id_read_data();
	} while (tmp & DOSBOX_ID_SCREENSHOT_STATUS_IMAGE_IN_PROGRESS);

	printf("Screenshot done\n");
	return 0;
}