Applied all relevant PCem commits;
Extensively cleaned up and changed the CD-ROM code; Removed CD-ROM IOCTTL (it was causing performance and stability issues); Turned a lot of things into device_t's; Added the PS/1 Model 2011 XTA and standalone XTA hard disk controllers, ported from Varcem; Numerous FDC fixes for the PS/1 Model 2121; NVR changes ported from Varcem; The PCap code no longer requires libpcap to be compiled; Numerous fixes to various SCSI controllers; Updated NukedOPL to 1.8; Fixes to OpenAL initialization and closing, should give less Audio issues now; Revorked parts of the common (S)VGA code (also based on code from QEMU); Removed the Removable SCSI hard disks (they were a never finished experiment so there was no need to keep them there); Cleaned up the SCSI hard disk and Iomega ZIP code (but more cleanups of that are coming in the future); In some occasions (IDE hard disks in multiple sector mode and SCSI hard disks) the status bar icon is no longer updated, should improve performance a bit; Redid the way the tertiary and quaternary IDE controllers are configured (and they are now device_t's); Extensively reworked the IDE code and fixed quite a few bugs; Fixes to XT MFM, AT MFM, and AT ESDI code; Some changes to XTIDE and MCA ESDI code; Some fixes to the CD-ROM image handler.
This commit is contained in:
311
src/nvr_at.c
311
src/nvr_at.c
@@ -189,7 +189,7 @@
|
||||
* including the later update (DS12887A) which implemented a
|
||||
* "century" register to be compatible with Y2K.
|
||||
*
|
||||
* Version: @(#)nvr_at.c 1.0.3 2018/03/11
|
||||
* Version: @(#)nvr_at.c 1.0.5 2018/04/09
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -218,6 +218,7 @@
|
||||
* Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -228,19 +229,20 @@
|
||||
#include "cpu/cpu.h"
|
||||
#include "machine/machine.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "pit.h"
|
||||
#include "mem.h"
|
||||
#include "nmi.h"
|
||||
#include "pic.h"
|
||||
#include "pit.h"
|
||||
#include "rom.h"
|
||||
#include "timer.h"
|
||||
#include "device.h"
|
||||
#include "nvr.h"
|
||||
#include "rom.h"
|
||||
|
||||
|
||||
/* RTC registers and bit definitions. */
|
||||
#define RTC_SECONDS 0
|
||||
#define RTC_ALSECONDS 1
|
||||
# define AL_DONTCARE 0xc0 /* Alarm time is not set */
|
||||
#define RTC_MINUTES 2
|
||||
#define RTC_ALMINUTES 3
|
||||
#define RTC_HOURS 4
|
||||
@@ -277,43 +279,53 @@
|
||||
# define REGC_UF 0x10
|
||||
#define RTC_REGD 13
|
||||
# define REGD_VRT 0x80
|
||||
#define RTC_CENTURY 0x32 /* century register */
|
||||
#define RTC_CENTURY_AT 0x32 /* century register for AT etc */
|
||||
#define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */
|
||||
#define RTC_REGS 14 /* number of registers */
|
||||
|
||||
|
||||
static nvr_t *nvrp;
|
||||
typedef struct {
|
||||
int8_t stat;
|
||||
uint8_t cent;
|
||||
|
||||
uint16_t addr;
|
||||
|
||||
int64_t ecount,
|
||||
rtctime;
|
||||
} local_t;
|
||||
|
||||
|
||||
/* Get the current NVR time. */
|
||||
static void
|
||||
time_get(uint8_t *regs, struct tm *tm)
|
||||
time_get(nvr_t *nvr, struct tm *tm)
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
int8_t temp;
|
||||
|
||||
if (regs[RTC_REGB] & REGB_DM) {
|
||||
if (nvr->regs[RTC_REGB] & REGB_DM) {
|
||||
/* NVR is in Binary data mode. */
|
||||
tm->tm_sec = regs[RTC_SECONDS];
|
||||
tm->tm_min = regs[RTC_MINUTES];
|
||||
temp = regs[RTC_HOURS];
|
||||
tm->tm_wday = (regs[RTC_DOW] - 1);
|
||||
tm->tm_mday = regs[RTC_DOM];
|
||||
tm->tm_mon = (regs[RTC_MONTH] - 1);
|
||||
tm->tm_year = regs[RTC_YEAR];
|
||||
tm->tm_year += (regs[RTC_CENTURY] * 100) - 1900;
|
||||
tm->tm_sec = nvr->regs[RTC_SECONDS];
|
||||
tm->tm_min = nvr->regs[RTC_MINUTES];
|
||||
temp = nvr->regs[RTC_HOURS];
|
||||
tm->tm_wday = (nvr->regs[RTC_DOW] - 1);
|
||||
tm->tm_mday = nvr->regs[RTC_DOM];
|
||||
tm->tm_mon = (nvr->regs[RTC_MONTH] - 1);
|
||||
tm->tm_year = nvr->regs[RTC_YEAR];
|
||||
tm->tm_year += (nvr->regs[local->cent] * 100) - 1900;
|
||||
} else {
|
||||
/* NVR is in BCD data mode. */
|
||||
tm->tm_sec = RTC_DCB(regs[RTC_SECONDS]);
|
||||
tm->tm_min = RTC_DCB(regs[RTC_MINUTES]);
|
||||
temp = RTC_DCB(regs[RTC_HOURS]);
|
||||
tm->tm_wday = (RTC_DCB(regs[RTC_DOW]) - 1);
|
||||
tm->tm_mday = RTC_DCB(regs[RTC_DOM]);
|
||||
tm->tm_mon = (RTC_DCB(regs[RTC_MONTH]) - 1);
|
||||
tm->tm_year = RTC_DCB(regs[RTC_YEAR]);
|
||||
tm->tm_year += (RTC_DCB(regs[RTC_CENTURY]) * 100) - 1900;
|
||||
tm->tm_sec = RTC_DCB(nvr->regs[RTC_SECONDS]);
|
||||
tm->tm_min = RTC_DCB(nvr->regs[RTC_MINUTES]);
|
||||
temp = RTC_DCB(nvr->regs[RTC_HOURS]);
|
||||
tm->tm_wday = (RTC_DCB(nvr->regs[RTC_DOW]) - 1);
|
||||
tm->tm_mday = RTC_DCB(nvr->regs[RTC_DOM]);
|
||||
tm->tm_mon = (RTC_DCB(nvr->regs[RTC_MONTH]) - 1);
|
||||
tm->tm_year = RTC_DCB(nvr->regs[RTC_YEAR]);
|
||||
tm->tm_year += (RTC_DCB(nvr->regs[local->cent]) * 100) - 1900;
|
||||
}
|
||||
|
||||
/* Adjust for 12/24 hour mode. */
|
||||
if (regs[RTC_REGB] & REGB_2412)
|
||||
if (nvr->regs[RTC_REGB] & REGB_2412)
|
||||
tm->tm_hour = temp;
|
||||
else
|
||||
tm->tm_hour = ((temp & ~RTC_AMPM)%12) + ((temp&RTC_AMPM) ? 12 : 0);
|
||||
@@ -322,49 +334,50 @@ time_get(uint8_t *regs, struct tm *tm)
|
||||
|
||||
/* Set the current NVR time. */
|
||||
static void
|
||||
time_set(uint8_t *regs, struct tm *tm)
|
||||
time_set(nvr_t *nvr, struct tm *tm)
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
int year = (tm->tm_year + 1900);
|
||||
|
||||
if (regs[RTC_REGB] & REGB_DM) {
|
||||
if (nvr->regs[RTC_REGB] & REGB_DM) {
|
||||
/* NVR is in Binary data mode. */
|
||||
regs[RTC_SECONDS] = tm->tm_sec;
|
||||
regs[RTC_MINUTES] = tm->tm_min;
|
||||
regs[RTC_DOW] = (tm->tm_wday + 1);
|
||||
regs[RTC_DOM] = tm->tm_mday;
|
||||
regs[RTC_MONTH] = (tm->tm_mon + 1);
|
||||
regs[RTC_YEAR] = (year % 100);
|
||||
regs[RTC_CENTURY] = (year / 100);
|
||||
nvr->regs[RTC_SECONDS] = tm->tm_sec;
|
||||
nvr->regs[RTC_MINUTES] = tm->tm_min;
|
||||
nvr->regs[RTC_DOW] = (tm->tm_wday + 1);
|
||||
nvr->regs[RTC_DOM] = tm->tm_mday;
|
||||
nvr->regs[RTC_MONTH] = (tm->tm_mon + 1);
|
||||
nvr->regs[RTC_YEAR] = (year % 100);
|
||||
nvr->regs[local->cent] = (year / 100);
|
||||
|
||||
if (regs[RTC_REGB] & REGB_2412) {
|
||||
if (nvr->regs[RTC_REGB] & REGB_2412) {
|
||||
/* NVR is in 24h mode. */
|
||||
regs[RTC_HOURS] = tm->tm_hour;
|
||||
nvr->regs[RTC_HOURS] = tm->tm_hour;
|
||||
} else {
|
||||
/* NVR is in 12h mode. */
|
||||
regs[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12;
|
||||
nvr->regs[RTC_HOURS] = (tm->tm_hour % 12) ? (tm->tm_hour % 12) : 12;
|
||||
if (tm->tm_hour > 11)
|
||||
regs[RTC_HOURS] |= RTC_AMPM;
|
||||
nvr->regs[RTC_HOURS] |= RTC_AMPM;
|
||||
}
|
||||
} else {
|
||||
/* NVR is in BCD data mode. */
|
||||
regs[RTC_SECONDS] = RTC_BCD(tm->tm_sec);
|
||||
regs[RTC_MINUTES] = RTC_BCD(tm->tm_min);
|
||||
regs[RTC_DOW] = (RTC_BCD(tm->tm_wday) + 1);
|
||||
regs[RTC_DOM] = RTC_BCD(tm->tm_mday);
|
||||
regs[RTC_MONTH] = (RTC_BCD(tm->tm_mon) + 1);
|
||||
regs[RTC_YEAR] = RTC_BCD(year % 100);
|
||||
regs[RTC_CENTURY] = RTC_BCD(year / 100);
|
||||
nvr->regs[RTC_SECONDS] = RTC_BCD(tm->tm_sec);
|
||||
nvr->regs[RTC_MINUTES] = RTC_BCD(tm->tm_min);
|
||||
nvr->regs[RTC_DOW] = (RTC_BCD(tm->tm_wday) + 1);
|
||||
nvr->regs[RTC_DOM] = RTC_BCD(tm->tm_mday);
|
||||
nvr->regs[RTC_MONTH] = (RTC_BCD(tm->tm_mon) + 1);
|
||||
nvr->regs[RTC_YEAR] = RTC_BCD(year % 100);
|
||||
nvr->regs[local->cent] = RTC_BCD(year / 100);
|
||||
|
||||
if (regs[RTC_REGB] & REGB_2412) {
|
||||
if (nvr->regs[RTC_REGB] & REGB_2412) {
|
||||
/* NVR is in 24h mode. */
|
||||
regs[RTC_HOURS] = RTC_BCD(tm->tm_hour);
|
||||
nvr->regs[RTC_HOURS] = RTC_BCD(tm->tm_hour);
|
||||
} else {
|
||||
/* NVR is in 12h mode. */
|
||||
regs[RTC_HOURS] = (tm->tm_hour % 12)
|
||||
nvr->regs[RTC_HOURS] = (tm->tm_hour % 12)
|
||||
? RTC_BCD(tm->tm_hour % 12)
|
||||
: RTC_BCD(12);
|
||||
if (tm->tm_hour > 11)
|
||||
regs[RTC_HOURS] |= RTC_AMPM;
|
||||
nvr->regs[RTC_HOURS] |= RTC_AMPM;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -372,19 +385,19 @@ time_set(uint8_t *regs, struct tm *tm)
|
||||
|
||||
/* Check if the current time matches a set alarm time. */
|
||||
static int8_t
|
||||
check_alarm(uint8_t *regs, int8_t addr)
|
||||
check_alarm(nvr_t *nvr, int8_t addr)
|
||||
{
|
||||
#define ALARM_DONTCARE 0xc0
|
||||
return((regs[addr+1] == regs[addr]) ||
|
||||
((regs[addr+1] & ALARM_DONTCARE) == ALARM_DONTCARE));
|
||||
return((nvr->regs[addr+1] == nvr->regs[addr]) ||
|
||||
((nvr->regs[addr+1] & AL_DONTCARE) == AL_DONTCARE));
|
||||
}
|
||||
|
||||
|
||||
/* Update the NVR registers from the internal clock. */
|
||||
static void
|
||||
update_timer(void *priv)
|
||||
timer_update(void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
struct tm tm;
|
||||
|
||||
if (! (nvr->regs[RTC_REGB] & REGB_SET)) {
|
||||
@@ -392,22 +405,22 @@ update_timer(void *priv)
|
||||
nvr_time_get(&tm);
|
||||
|
||||
/* Update registers with current time. */
|
||||
time_set(nvr->regs, &tm);
|
||||
|
||||
time_set(nvr, &tm);
|
||||
|
||||
/* Clear update status. */
|
||||
/* Clear update status. */
|
||||
local->stat = 0x00;
|
||||
|
||||
/* Check for any alarms we need to handle. */
|
||||
/* Check for any alarms we need to handle. */
|
||||
if (check_alarm(nvr->regs, RTC_SECONDS) &&
|
||||
check_alarm(nvr->regs, RTC_MINUTES) &&
|
||||
if (check_alarm(nvr, RTC_SECONDS) &&
|
||||
check_alarm(nvr, RTC_MINUTES) &&
|
||||
check_alarm(nvr, RTC_HOURS)) {
|
||||
nvr->regs[RTC_REGC] |= REGC_AF;
|
||||
if (nvr->regs[RTC_REGB] & REGB_AIE) {
|
||||
nvr->regs[RTC_REGC] |= REGC_IRQF;
|
||||
|
||||
/* Generate an interrupt. */
|
||||
if (nvr->irq != -1)
|
||||
if (nvr->irq != -1)
|
||||
picint(1 << nvr->irq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,41 +434,43 @@ update_timer(void *priv)
|
||||
|
||||
/* Generate an interrupt. */
|
||||
if (nvr->irq != -1)
|
||||
if (nvr->irq != -1)
|
||||
picint(1 << nvr->irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
local->ecount = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Re-calculate the timer values. */
|
||||
static void
|
||||
static void
|
||||
timer_recalc(nvr_t *nvr, int add)
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
int64_t c, nt;
|
||||
|
||||
|
||||
c = 1ULL << ((nvr->regs[RTC_REGA] & REGA_RS) - 1);
|
||||
nt = (int64_t)(RTCCONST * c * (1<<TIMER_SHIFT));
|
||||
if (add)
|
||||
if (add)
|
||||
nvr->rtctime += nt;
|
||||
else if (nvr->rtctime > nt)
|
||||
local->rtctime += nt;
|
||||
else if (local->rtctime > nt)
|
||||
local->rtctime = nt;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static void
|
||||
timer_intr(void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
|
||||
if (! (nvr->regs[RTC_REGA] & REGA_RS)) {
|
||||
if (! (nvr->regs[RTC_REGA] & REGA_RS)) {
|
||||
local->rtctime = 0x7fffffff;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update our timer interval. */
|
||||
/* Update our timer interval. */
|
||||
timer_recalc(nvr, 1);
|
||||
|
||||
nvr->regs[RTC_REGC] |= REGC_PF;
|
||||
if (nvr->regs[RTC_REGB] & REGB_PIE) {
|
||||
@@ -463,20 +478,27 @@ rtc_timer(void *priv)
|
||||
|
||||
/* Generate an interrupt. */
|
||||
if (nvr->irq != -1)
|
||||
if (nvr->irq != -1)
|
||||
picint(1 << nvr->irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Callback from internal clock, another second passed. */
|
||||
static void
|
||||
static void
|
||||
timer_tick(nvr_t *nvr)
|
||||
{
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
|
||||
|
||||
/* Only update it there is no SET in progress. */
|
||||
if (! (nvr->regs[RTC_REGB] & REGB_SET)) {
|
||||
/* Set the UIP bit, announcing the update. */
|
||||
local->stat = REGA_UIP;
|
||||
|
||||
|
||||
timer_recalc(nvr, 0);
|
||||
|
||||
/* Schedule the actual update. */
|
||||
local->ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -485,20 +507,21 @@ static void
|
||||
nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
struct tm tm;
|
||||
uint8_t old;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
if (addr & 1) {
|
||||
if (addr & 1) {
|
||||
old = nvr->regs[nvr->addr];
|
||||
old = nvr->regs[local->addr];
|
||||
switch(local->addr) {
|
||||
case RTC_REGA:
|
||||
nvr->regs[RTC_REGA] = val;
|
||||
if (val & REGA_RS)
|
||||
if (val & REGA_RS)
|
||||
timer_recalc(nvr, 1);
|
||||
else
|
||||
else
|
||||
local->rtctime = 0x7fffffff;
|
||||
break;
|
||||
|
||||
case RTC_REGB:
|
||||
@@ -515,25 +538,25 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
default: /* non-RTC registers are just NVRAM */
|
||||
default: /* non-RTC registers are just NVRAM */
|
||||
if (nvr->regs[nvr->addr] != val) {
|
||||
if (nvr->regs[local->addr] != val) {
|
||||
nvr->regs[local->addr] = val;
|
||||
nvr_dosave = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ((nvr->addr < RTC_REGA) || (nvr->addr == RTC_CENTURY)) {
|
||||
if ((local->addr < RTC_REGA) || (local->addr == local->cent)) {
|
||||
if ((local->addr != 1) && (local->addr != 3) && (local->addr != 5)) {
|
||||
if ((old != val) && !enable_sync) {
|
||||
/* Update internal clock. */
|
||||
/* Update internal clock. */
|
||||
time_get(nvr, &tm);
|
||||
nvr_time_set(&tm);
|
||||
nvr_dosave = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
local->addr = (val & (nvr->size - 1));
|
||||
if (!(machines[machine].flags & MACHINE_MCA) &&
|
||||
(romset != ROM_IBMPS1_2133))
|
||||
nmi_mask = (~val & 0x80);
|
||||
@@ -546,17 +569,18 @@ static uint8_t
|
||||
nvr_read(uint16_t addr, void *priv)
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
uint8_t ret;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
|
||||
if (addr & 1) switch(local->addr) {
|
||||
case RTC_REGA:
|
||||
case RTC_REGA:
|
||||
ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat;
|
||||
break;
|
||||
|
||||
case RTC_REGC:
|
||||
case RTC_REGC:
|
||||
picintc(1 << nvr->irq);
|
||||
ret = nvr->regs[RTC_REGC];
|
||||
nvr->regs[RTC_REGC] = 0x00;
|
||||
break;
|
||||
@@ -567,10 +591,10 @@ nvr_read(uint16_t addr, void *priv)
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
ret = nvr->regs[local->addr];
|
||||
break;
|
||||
} else {
|
||||
} else {
|
||||
ret = local->addr;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
@@ -579,19 +603,21 @@ nvr_read(uint16_t addr, void *priv)
|
||||
|
||||
/* Reset the RTC state to 1980/01/01 00:00. */
|
||||
static void
|
||||
static void
|
||||
nvr_reset(nvr_t *nvr)
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
|
||||
memset(nvr->regs, 0x00, RTC_REGS);
|
||||
nvr->regs[RTC_DOM] = 1;
|
||||
nvr->regs[RTC_MONTH] = 1;
|
||||
nvr->regs[RTC_YEAR] = RTC_BCD(80);
|
||||
nvr->regs[RTC_YEAR] = RTC_BCD(80);
|
||||
nvr->regs[local->cent] = RTC_BCD(19);
|
||||
}
|
||||
|
||||
|
||||
/* Process after loading from file. */
|
||||
static void
|
||||
static void
|
||||
nvr_start(nvr_t *nvr)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
@@ -599,63 +625,120 @@ nvr_at_start(nvr_t *nvr)
|
||||
if (enable_sync) {
|
||||
/* Use the internal clock's time. */
|
||||
nvr_time_get(&tm);
|
||||
nvr_time_get(&tm);
|
||||
time_set(nvr, &tm);
|
||||
} else {
|
||||
/* Set the internal clock from the chip time. */
|
||||
/* Set the internal clock from the chip time. */
|
||||
time_get(nvr, &tm);
|
||||
nvr_time_set(&tm);
|
||||
}
|
||||
|
||||
/* Start the RTC. */
|
||||
nvr->regs[RTC_REGA] = (REGA_RS2|REGA_RS1);
|
||||
nvr->regs[RTC_REGB] = REGB_2412;
|
||||
nvr->regs[RTC_REGB] = REGB_2412;
|
||||
timer_recalc(nvr, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
nvr_recalc(nvr_t *nvr)
|
||||
{
|
||||
timer_recalc(nvr, 0);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
nvr_at_init(const device_t *info)
|
||||
{
|
||||
local_t *local;
|
||||
nvr_t *nvr;
|
||||
|
||||
/* Allocate an NVR for this machine. */
|
||||
nvr = (nvr_t *)malloc(sizeof(nvr_t));
|
||||
nvr = (nvr_t *)malloc(sizeof(nvr_t));
|
||||
if (nvr == NULL) return(NULL);
|
||||
memset(nvr, 0x00, sizeof(nvr_t));
|
||||
|
||||
local = (local_t *)malloc(sizeof(local_t));
|
||||
memset(local, 0xff, sizeof(local_t));
|
||||
nvr->data = local;
|
||||
|
||||
/* This is machine specific. */
|
||||
nvr->size = machines[machine].nvrmask + 1;
|
||||
nvr->size = machines[machine].nvrmask + 1;
|
||||
switch(info->local) {
|
||||
case 0: /* standard AT */
|
||||
nvr->irq = 8;
|
||||
local->cent = RTC_CENTURY_AT;
|
||||
break;
|
||||
|
||||
case 1: /* PS/1 or PS/2 */
|
||||
nvr->irq = 8;
|
||||
local->cent = RTC_CENTURY_PS;
|
||||
break;
|
||||
|
||||
case 2: /* Amstrad PC's */
|
||||
nvr->irq = 1;
|
||||
local->cent = RTC_CENTURY_AT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set up any local handlers here. */
|
||||
/* Set up any local handlers here. */
|
||||
nvr->reset = nvr_at_reset;
|
||||
nvr->start = nvr_at_start;
|
||||
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. */
|
||||
/* Start the timers. */
|
||||
timer_add(update_timer, &nvr->upd_ecount, &nvr->upd_ecount, nvr);
|
||||
timer_add(timer_update, &local->ecount, &local->ecount, nvr);
|
||||
timer_add(timer_intr, &local->rtctime, TIMER_ALWAYS_ENABLED, nvr);
|
||||
|
||||
/* Set up the I/O handler for this device. */
|
||||
io_sethandler(0x0070, 2,
|
||||
nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr);
|
||||
|
||||
|
||||
return(nvr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
nvr_at_close(void *priv)
|
||||
{
|
||||
{
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
|
||||
|
||||
if (nvrp->fn != NULL)
|
||||
if (nvr->fn != NULL)
|
||||
free(nvr->fn);
|
||||
|
||||
|
||||
if (nvr->data != NULL)
|
||||
free(nvr->data);
|
||||
|
||||
|
||||
free(nvr);
|
||||
}
|
||||
|
||||
|
||||
const device_t at_nvr_device = {
|
||||
"PC/AT NVRAM",
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
0,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t ps_nvr_device = {
|
||||
"PS/1 or PS/2 NVRAM",
|
||||
DEVICE_PS2,
|
||||
1,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t amstrad_nvr_device = {
|
||||
"Amstrad NVRAM",
|
||||
MACHINE_ISA | MACHINE_AT,
|
||||
2,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user