Finished the VIA machine.
This commit is contained in:
84
src/nvr_at.c
84
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.16 2019/11/19
|
||||
* Version: @(#)nvr_at.c 1.0.17 2020/01/13
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Mahod,
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
*
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2017-2020 Fred N. van Kempen.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2008-2020 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
|
||||
@@ -281,6 +281,9 @@
|
||||
# define REGD_VRT 0x80
|
||||
#define RTC_CENTURY_AT 0x32 /* century register for AT etc */
|
||||
#define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */
|
||||
#define RTC_ALDAY 0x7D /* VIA VT82C586B - alarm day */
|
||||
#define RTC_ALMONTH 0x7E /* VIA VT82C586B - alarm month */
|
||||
#define RTC_CENTURY_VIA 0x7F /* century register for VIA VT82C586B */
|
||||
#define RTC_REGS 14 /* number of registers */
|
||||
|
||||
|
||||
@@ -290,7 +293,7 @@ typedef struct {
|
||||
uint8_t cent;
|
||||
uint8_t def;
|
||||
|
||||
uint8_t addr;
|
||||
uint8_t addr[8];
|
||||
|
||||
int16_t count, state;
|
||||
|
||||
@@ -402,6 +405,20 @@ check_alarm(nvr_t *nvr, int8_t addr)
|
||||
}
|
||||
|
||||
|
||||
/* Check for VIA stuff. */
|
||||
static int8_t
|
||||
check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2)
|
||||
{
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
|
||||
if (local->cent == RTC_CENTURY_VIA) {
|
||||
return((nvr->regs[addr_2] == nvr->regs[addr]) ||
|
||||
((nvr->regs[addr_2] & AL_DONTCARE) == AL_DONTCARE));
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Update the NVR registers from the internal clock. */
|
||||
static void
|
||||
timer_update(void *priv)
|
||||
@@ -425,7 +442,9 @@ timer_update(void *priv)
|
||||
/* Check for any alarms we need to handle. */
|
||||
if (check_alarm(nvr, RTC_SECONDS) &&
|
||||
check_alarm(nvr, RTC_MINUTES) &&
|
||||
check_alarm(nvr, RTC_HOURS)) {
|
||||
check_alarm(nvr, RTC_HOURS) &&
|
||||
check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) &&
|
||||
check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH)) {
|
||||
nvr->regs[RTC_REGC] |= REGC_AF;
|
||||
if (nvr->regs[RTC_REGB] & REGB_AIE) {
|
||||
nvr->regs[RTC_REGC] |= REGC_IRQF;
|
||||
@@ -535,12 +554,13 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
struct tm tm;
|
||||
uint8_t old;
|
||||
uint8_t addr_id = (addr & 0x0e) >> 1;
|
||||
|
||||
sub_cycles(ISA_CYCLES(8));
|
||||
|
||||
if (addr & 1) {
|
||||
old = nvr->regs[local->addr];
|
||||
switch(local->addr) {
|
||||
old = nvr->regs[local->addr[addr_id]];
|
||||
switch(local->addr[addr_id]) {
|
||||
case RTC_REGA:
|
||||
nvr->regs[RTC_REGA] = val;
|
||||
timer_load_count(nvr);
|
||||
@@ -560,15 +580,15 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
default: /* non-RTC registers are just NVRAM */
|
||||
if (nvr->regs[local->addr] != val) {
|
||||
nvr->regs[local->addr] = val;
|
||||
if (nvr->regs[local->addr[addr_id]] != val) {
|
||||
nvr->regs[local->addr[addr_id]] = val;
|
||||
nvr_dosave = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((local->addr < RTC_REGA) || ((local->cent != 0xff) && (local->addr == local->cent))) {
|
||||
if ((local->addr != 1) && (local->addr != 3) && (local->addr != 5)) {
|
||||
if ((local->addr[addr_id] < RTC_REGA) || ((local->cent != 0xff) && (local->addr[addr_id] == local->cent))) {
|
||||
if ((local->addr[addr_id] != 1) && (local->addr[addr_id] != 3) && (local->addr[addr_id] != 5)) {
|
||||
if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) {
|
||||
/* Update internal clock. */
|
||||
time_get(nvr, &tm);
|
||||
@@ -578,7 +598,10 @@ nvr_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
local->addr = (val & (nvr->size - 1));
|
||||
local->addr[addr_id] = (val & (nvr->size - 1));
|
||||
/* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */
|
||||
if (addr_id == 0x0)
|
||||
local->addr[addr_id] &= 0x7f;
|
||||
if (!(machines[machine].flags & MACHINE_MCA) &&
|
||||
!(machines[machine].flags & MACHINE_NONMI))
|
||||
nmi_mask = (~val & 0x80);
|
||||
@@ -593,10 +616,11 @@ nvr_read(uint16_t addr, void *priv)
|
||||
nvr_t *nvr = (nvr_t *)priv;
|
||||
local_t *local = (local_t *)nvr->data;
|
||||
uint8_t ret;
|
||||
uint8_t addr_id = (addr & 0x0e) >> 1;
|
||||
|
||||
sub_cycles(ISA_CYCLES(8));
|
||||
|
||||
if (addr & 1) switch(local->addr) {
|
||||
if (addr & 1) switch(local->addr[addr_id]) {
|
||||
case RTC_REGA:
|
||||
ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat;
|
||||
break;
|
||||
@@ -613,10 +637,10 @@ nvr_read(uint16_t addr, void *priv)
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = nvr->regs[local->addr];
|
||||
ret = nvr->regs[local->addr[addr_id]];
|
||||
break;
|
||||
} else
|
||||
ret = local->addr;
|
||||
ret = local->addr[addr_id];
|
||||
|
||||
return(ret);
|
||||
}
|
||||
@@ -692,6 +716,14 @@ nvr_at_speed_changed(void *priv)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nvr_at_handler(int set, uint16_t base, nvr_t *nvr)
|
||||
{
|
||||
io_handler(set, base, 2,
|
||||
nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
nvr_at_init(const device_t *info)
|
||||
{
|
||||
@@ -710,7 +742,7 @@ nvr_at_init(const device_t *info)
|
||||
/* This is machine specific. */
|
||||
nvr->size = machines[machine].nvrmask + 1;
|
||||
local->def = 0x00;
|
||||
switch(info->local) {
|
||||
switch(info->local & 7) {
|
||||
case 0: /* standard AT, no century register */
|
||||
nvr->irq = 8;
|
||||
local->cent = 0xff;
|
||||
@@ -738,6 +770,10 @@ nvr_at_init(const device_t *info)
|
||||
local->def = 0xff;
|
||||
break;
|
||||
|
||||
case 5: /* VIA VT82C586B */
|
||||
nvr->irq = 8;
|
||||
local->cent = RTC_CENTURY_VIA;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set up any local handlers here. */
|
||||
@@ -758,6 +794,10 @@ nvr_at_init(const device_t *info)
|
||||
/* Set up the I/O handler for this device. */
|
||||
io_sethandler(0x0070, 2,
|
||||
nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr);
|
||||
if (info->local & 8) {
|
||||
io_sethandler(0x0072, 2,
|
||||
nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr);
|
||||
}
|
||||
|
||||
return(nvr);
|
||||
}
|
||||
@@ -829,3 +869,13 @@ const device_t ibmat_nvr_device = {
|
||||
NULL, nvr_at_speed_changed,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t via_nvr_device = {
|
||||
"VIA PC/AT NVRAM",
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
9,
|
||||
nvr_at_init, nvr_at_close, NULL,
|
||||
NULL, nvr_at_speed_changed,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user