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:
169
src/nvr_at.c
169
src/nvr_at.c
@@ -189,16 +189,16 @@
|
||||
* including the later update (DS12887A) which implemented a
|
||||
* "century" register to be compatible with Y2K.
|
||||
*
|
||||
* Version: @(#)nvr_at.c 1.0.14 2018/10/06
|
||||
* Version: @(#)nvr_at.c 1.0.15 2019/03/16
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Mahod,
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -232,9 +232,9 @@
|
||||
#include "mem.h"
|
||||
#include "nmi.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "pit.h"
|
||||
#include "rom.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "nvr.h"
|
||||
|
||||
@@ -292,8 +292,10 @@ typedef struct {
|
||||
|
||||
uint8_t addr;
|
||||
|
||||
int64_t ecount,
|
||||
rtctime;
|
||||
uint64_t ecount,
|
||||
rtc_time;
|
||||
pc_timer_t update_timer,
|
||||
rtc_timer;
|
||||
} local_t;
|
||||
|
||||
|
||||
@@ -406,6 +408,8 @@ timer_update(void *priv)
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
struct tm tm;
|
||||
|
||||
local->ecount = 0LL;
|
||||
|
||||
if (! (nvr->regs[RTC_REGB] & REGB_SET)) {
|
||||
/* Get the current time from the internal clock. */
|
||||
nvr_time_get(&tm);
|
||||
@@ -443,27 +447,47 @@ timer_update(void *priv)
|
||||
picint(1 << nvr->irq);
|
||||
}
|
||||
}
|
||||
|
||||
local->ecount = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Re-calculate the timer values. */
|
||||
static void
|
||||
timer_recalc(nvr_t *nvr, int add)
|
||||
static double
|
||||
timer_nvr_period(nvr_t *nvr)
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
int64_t c, nt;
|
||||
double dusec = (double) TIMER_USEC;
|
||||
|
||||
c = 1ULL << ((nvr->regs[RTC_REGA] & REGA_RS) - 1);
|
||||
nt = (int64_t)(RTCCONST * c * (1<<TIMER_SHIFT));
|
||||
if (add == 2) {
|
||||
local->rtctime = nt;
|
||||
return;
|
||||
} else if (add == 1)
|
||||
local->rtctime += nt;
|
||||
else if (local->rtctime > nt)
|
||||
local->rtctime = nt;
|
||||
switch (nvr->regs[RTC_REGA] & REGA_RS) {
|
||||
case 0:
|
||||
default:
|
||||
return 0.0;
|
||||
case 1:
|
||||
case 8:
|
||||
return 3906.25 * dusec;
|
||||
case 2:
|
||||
case 9:
|
||||
return 7812.5 * dusec;
|
||||
case 3:
|
||||
return 122.070 * dusec;
|
||||
case 4:
|
||||
return 244.141 * dusec;
|
||||
case 5:
|
||||
return 488.281 * dusec;
|
||||
case 6:
|
||||
return 976.5625 * dusec;
|
||||
case 7:
|
||||
return 1953.125 * dusec;
|
||||
case 10:
|
||||
return 15625.0 * dusec;
|
||||
case 11:
|
||||
return 31250.0 * dusec;
|
||||
case 12:
|
||||
return 62500.0 * dusec;
|
||||
case 13:
|
||||
return 125000.0 * dusec;
|
||||
case 14:
|
||||
return 250000.0 * dusec;
|
||||
case 15:
|
||||
return 500000.0 * dusec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -473,14 +497,14 @@ timer_intr(void *priv)
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
|
||||
if (! (nvr->regs[RTC_REGA] & REGA_RS)) {
|
||||
local->rtctime = 0x7fffffff;
|
||||
if (nvr->regs[RTC_REGA] & REGA_RS) {
|
||||
local->rtc_time = timer_nvr_period(nvr);
|
||||
timer_advance_u64(&local->rtc_timer, (uint64_t) local->rtc_time);
|
||||
} else {
|
||||
local->rtc_time = 0ULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update our timer interval. */
|
||||
timer_recalc(nvr, 1);
|
||||
|
||||
nvr->regs[RTC_REGC] |= REGC_PF;
|
||||
if (nvr->regs[RTC_REGB] & REGB_PIE) {
|
||||
nvr->regs[RTC_REGC] |= REGC_IRQF;
|
||||
@@ -506,7 +530,22 @@ timer_tick(nvr_t *nvr)
|
||||
rtc_tick();
|
||||
|
||||
/* Schedule the actual update. */
|
||||
local->ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC);
|
||||
local->ecount = (244ULL + 1984ULL) * TIMER_USEC;
|
||||
timer_set_delay_u64(&local->update_timer, local->ecount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nvr_pie_start(nvr_t *nvr)
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
|
||||
local->rtc_time = 0ULL;
|
||||
timer_disable(&local->rtc_timer);
|
||||
if ((nvr->regs[RTC_REGA] & REGA_RS) && ((nvr->regs[RTC_REGA] & 0x70) == 0x20)) {
|
||||
local->rtc_time = timer_nvr_period(nvr);
|
||||
timer_set_delay_u64(&local->rtc_timer, local->rtc_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,17 +559,14 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
struct tm tm;
|
||||
uint8_t old;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
sub_cycles(ISA_CYCLES(8));
|
||||
|
||||
if (addr & 1) {
|
||||
old = nvr->regs[local->addr];
|
||||
switch(local->addr) {
|
||||
case RTC_REGA:
|
||||
nvr->regs[RTC_REGA] = val;
|
||||
if (val & REGA_RS)
|
||||
timer_recalc(nvr, 1);
|
||||
else
|
||||
local->rtctime = 0x7fffffff;
|
||||
nvr_pie_start(nvr);
|
||||
break;
|
||||
|
||||
case RTC_REGB:
|
||||
@@ -544,7 +580,7 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
case RTC_REGC: /* R/O */
|
||||
case RTC_REGD: /* R/O */
|
||||
break;
|
||||
break;
|
||||
|
||||
default: /* non-RTC registers are just NVRAM */
|
||||
if (nvr->regs[local->addr] != val) {
|
||||
@@ -567,7 +603,7 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
} else {
|
||||
local->addr = (val & (nvr->size - 1));
|
||||
if (!(machines[machine].flags & MACHINE_MCA) &&
|
||||
(machines[machine].flags & MACHINE_NONMI))
|
||||
!(machines[machine].flags & MACHINE_NONMI))
|
||||
nmi_mask = (~val & 0x80);
|
||||
}
|
||||
}
|
||||
@@ -581,9 +617,9 @@ nvr_read(uint16_t addr, void *priv)
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
uint8_t ret;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
sub_cycles(ISA_CYCLES(8));
|
||||
|
||||
if (addr & 1) switch(local->addr) {
|
||||
if (addr & 1) switch(local->addr) {
|
||||
case RTC_REGA:
|
||||
ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat;
|
||||
break;
|
||||
@@ -602,9 +638,8 @@ nvr_read(uint16_t addr, void *priv)
|
||||
default:
|
||||
ret = nvr->regs[local->addr];
|
||||
break;
|
||||
} else {
|
||||
} else
|
||||
ret = local->addr;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
@@ -630,7 +665,20 @@ nvr_reset(nvr_t *nvr)
|
||||
static void
|
||||
nvr_start(nvr_t *nvr)
|
||||
{
|
||||
int i;
|
||||
local_t *local = (local_t *) nvr->data;
|
||||
|
||||
struct tm tm;
|
||||
int default_found = 0;
|
||||
|
||||
for (i = 0; i < nvr->size; i++) {
|
||||
if (nvr->regs[i] == local->def)
|
||||
default_found++;
|
||||
}
|
||||
|
||||
if (default_found == nvr->size)
|
||||
nvr->regs[0x0e] = 0xff; /* If load failed or it loaded an uninitialized NVR,
|
||||
mark everything as bad. */
|
||||
|
||||
/* Initialize the internal and chip times. */
|
||||
if (time_sync & TIME_SYNC_ENABLED) {
|
||||
@@ -646,14 +694,25 @@ nvr_start(nvr_t *nvr)
|
||||
/* Start the RTC. */
|
||||
nvr->regs[RTC_REGA] = (REGA_RS2|REGA_RS1);
|
||||
nvr->regs[RTC_REGB] = REGB_2412;
|
||||
timer_recalc(nvr, 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nvr_recalc(nvr_t *nvr)
|
||||
nvr_at_speed_changed(void *priv)
|
||||
{
|
||||
timer_recalc(nvr, 0);
|
||||
nvr_t *nvr = (nvr_t *) priv;
|
||||
local_t *local = (local_t *) nvr->data;
|
||||
|
||||
timer_disable(&local->rtc_timer);
|
||||
if (local->rtc_time > 0ULL)
|
||||
timer_set_delay_u64(&local->rtc_timer, local->rtc_time);
|
||||
|
||||
timer_disable(&local->update_timer);
|
||||
if (local->ecount > 0ULL)
|
||||
timer_set_delay_u64(&local->update_timer, local->ecount);
|
||||
|
||||
timer_disable(&nvr->onesec_time);
|
||||
timer_set_delay_u64(&nvr->onesec_time, (10000ULL * TIMER_USEC));
|
||||
}
|
||||
|
||||
|
||||
@@ -709,14 +768,13 @@ nvr_at_init(const device_t *info)
|
||||
nvr->reset = nvr_reset;
|
||||
nvr->start = nvr_start;
|
||||
nvr->tick = timer_tick;
|
||||
nvr->recalc = nvr_recalc;
|
||||
|
||||
/* Initialize the generic NVR. */
|
||||
nvr_init(nvr);
|
||||
|
||||
/* Start the timers. */
|
||||
timer_add(timer_update, &local->ecount, &local->ecount, nvr);
|
||||
timer_add(timer_intr, &local->rtctime, TIMER_ALWAYS_ENABLED, nvr);
|
||||
timer_add(&local->update_timer, timer_update, nvr, 0);
|
||||
timer_add(&local->rtc_timer, timer_intr, nvr, 0);
|
||||
|
||||
/* Set up the I/O handler for this device. */
|
||||
io_sethandler(0x0070, 2,
|
||||
@@ -729,7 +787,14 @@ nvr_at_init(const device_t *info)
|
||||
static void
|
||||
nvr_at_close(void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
nvr_t *nvr = (nvr_t *) priv;
|
||||
local_t *local = (local_t *) nvr->data;
|
||||
|
||||
nvr_close();
|
||||
|
||||
timer_disable(&local->rtc_timer);
|
||||
timer_disable(&local->update_timer);
|
||||
timer_disable(&nvr->onesec_time);
|
||||
|
||||
if (nvr->fn != NULL)
|
||||
free(nvr->fn);
|
||||
@@ -746,7 +811,7 @@ const device_t at_nvr_old_device = {
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
0,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL,
|
||||
NULL, nvr_at_speed_changed,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -755,7 +820,7 @@ const device_t at_nvr_device = {
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
1,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL,
|
||||
NULL, nvr_at_speed_changed,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -764,7 +829,7 @@ const device_t ps_nvr_device = {
|
||||
DEVICE_PS2,
|
||||
2,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL,
|
||||
NULL, nvr_at_speed_changed,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -773,7 +838,7 @@ const device_t amstrad_nvr_device = {
|
||||
MACHINE_ISA | MACHINE_AT,
|
||||
3,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL,
|
||||
NULL, nvr_at_speed_changed,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -782,6 +847,6 @@ const device_t ibmat_nvr_device = {
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
4,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL,
|
||||
NULL, nvr_at_speed_changed,
|
||||
NULL
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user