Fixed the MC146818 modernisation so that local/utc & whether a century is stored in nvram can be specified in a sane way. Removed the century updating as this chip doesn't do that, but each driver can specify where the century should be stored. Fixed off by one errors in the date/time updating. Added support for different external clock speeds and dividers, the clock speeds have been set based on guesswork that the code would set the chip to update at 1hz but this isn't necessarily true. Most flags have been implemented, so that timer updating can be disabled & irq generation should be correct. [smf]

This commit is contained in:
smf- 2013-11-01 18:17:55 +00:00
parent f4ff52905a
commit e7517ea39e
23 changed files with 525 additions and 372 deletions

View File

@ -296,7 +296,8 @@ static MACHINE_CONFIG_FRAGMENT( e01 )
MCFG_CPU_ADD(R65C102_TAG, M65C02, XTAL_8MHz/4) // Rockwell R65C102P3
MCFG_CPU_PROGRAM_MAP(e01_mem)
MCFG_MC146818_IRQ_ADD(HD146818_TAG, MC146818_STANDARD, WRITELINE(e01_device, rtc_irq_w))
MCFG_MC146818_ADD(HD146818_TAG, XTAL_32_768kHz)
MCFG_MC146818_IRQ_HANDLER(WRITELINE(e01_device, rtc_irq_w))
// devices
MCFG_VIA6522_ADD(R6522_TAG, XTAL_8MHz/4, via_intf)

View File

@ -62,6 +62,7 @@ enum
XTAL_4MHz = 4000000,
XTAL_4_028MHz = 4028000, /* Sony SMC-777 */
XTAL_4_096MHz = 4096000, /* Used to drive OKI M9810 chips */
XTAL_4_194304Mhz = 4194304, /* Used to drive MC146818 */
XTAL_4_224MHz = 4224000, /* Used to drive OKI M6295 chips, usually with /4 divider */
XTAL_4_41MHz = 4410000, /* Pioneer PR-8210 ldplayer */
XTAL_4_43361MHz = 4433610, /* Cidelsa Draco */

View File

@ -4,74 +4,11 @@
Implementation of the MC146818 chip
Real time clock chip with battery backed ram (or CMOS)
Real time clock chip with CMOS battery backed ram
Used in IBM PC/AT, several PC clones, Amstrad NC200, Apollo workstations
Nathan Woods (npwoods@mess.org)
Peter Trauner (peter.trauner@jk.uni-linz.ac.at)
PC CMOS info (based on info from Padgett Peterson):
Clock Related:
0x00 Seconds (BCD 00-59, Hex 00-3B) Note: Bit 7 is read only
0x01 Second Alarm (BCD 00-59, Hex 00-3B; "don't care" if C0-FF)
0x02 Minutes (BCD 00-59, Hex 00-3B)
0x03 Minute Alarm (BCD 00-59, Hex 00-3B; "don't care" if C0-FF))
0x04 Hours (BCD 00-23, Hex 00-17 if 24 hr mode)
(BCD 01-12, Hex 01-0C if 12 hr am)
(BCD 81-92. Hex 81-8C if 12 hr pm)
0x05 Hour Alarm (same as hours; "don't care" if C0-FF))
0x06 Day of Week (01-07 Sunday=1)
0x07 Date of Month (BCD 01-31, Hex 01-1F)
0x08 Month (BCD 01-12, Hex 01-0C)
0x09 Year (BCD 00-99, Hex 00-63)
0x0B Status Register B (read/write)
Bit 7 - 1 enables cycle update, 0 disables
Bit 6 - 1 enables periodic interrupt
Bit 5 - 1 enables alarm interrupt
Bit 4 - 1 enables update-ended interrupt
Bit 3 - 1 enables square wave output
Bit 2 - Data Mode - 0: BCD, 1: Binary
Bit 1 - 24/12 hour selection - 1 enables 24 hour mode
Bit 0 - Daylight Savings Enable - 1 enables
0x0C Status Register C (Read only)
Bit 7 - Interrupt request flag - 1 when any or all of bits 6-4 are
1 and appropriate enables (Register B) are set to 1. Generates
IRQ 8 when triggered.
Bit 6 - Periodic Interrupt flag
Bit 5 - Alarm Interrupt flag
Bit 4 - Update-Ended Interrupt Flag
Bit 3-0 ???
0x0D Status Register D (read only)
Bit 7 - Valid RAM - 1 indicates batery power good, 0 if dead or
disconnected.
Bit 6-0 ???
Non-clock related:
0x0E (PS/2) Diagnostic Status Byte
Bit 7 - When set (1) indicates clock has lost power
Bit 6 - (1) indicates incorrect checksum
Bit 5 - (1) indicates that equipment configuration is incorrect
power-on check requires that atleast one floppy be installed
Bit 4 - (1) indicates error in memory size
Bit 3 - (1) indicates that controller or disk drive failed initialization
Bit 2 - (1) indicates that time is invalid
Bit 1 - (1) indicates installed adaptors do not match configuration
Bit 0 - (1) indicates a time-out while reading adaptor ID
0x0E (AMSTRAD) 6 BYTEs time and date machine last used
0x0F Reset Code (IBM PS/2 "Shutdown Status Byte")
0x00-0x03 perform power-on reset
0x04 INT 19h reboot
0x05 flush keyboard and jump via 0040:0067
0x06-0x07 reserved
0x08 used by POST during protected-mode RAM test
0x09 used for INT 15/87h (block move) support
0x0A jump via 0040:0067
0x0B-0xFF perform power-on reset
*********************************************************************/
#include "emu.h"
#include "coreutil.h"
#include "machine/mc146818.h"
@ -84,28 +21,6 @@
//**************************************************************************
// MACROS
//**************************************************************************
#define USE_UTC 1
#define HOURS_24 (m_data[0xb]&2)
#define BCD_MODE !(m_data[0xb]&4) // book has other description!
#define CENTURY m_data[72]
#define YEAR m_data[9]
#define MONTH m_data[8]
#define DAY m_data[7]
#define WEEK_DAY m_data[6]
#define HOUR m_data[4]
#define MINUTE m_data[2]
#define SECOND m_data[0]
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
// device type definition
const device_type MC146818 = &device_creator<mc146818_device>;
@ -115,29 +30,16 @@ const device_type MC146818 = &device_creator<mc146818_device>;
mc146818_device::mc146818_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MC146818, "MC146818", tag, owner, clock, "mc146818", __FILE__),
device_rtc_interface(mconfig, *this),
device_nvram_interface(mconfig, *this),
m_write_irq(*this),
m_type(MC146818_STANDARD),
m_index(0),
m_eindex(0),
m_updated(false),
m_last_refresh(attotime::zero)
m_last_refresh(attotime::zero),
m_write_irq(*this),
m_century_index(-1),
m_use_utc(false)
{
}
//-------------------------------------------------
// static_set_interface - configuration helper
// to set the interface
//-------------------------------------------------
void mc146818_device::static_set_type(device_t &device, mc146818_type type)
{
downcast<mc146818_device &>(device).m_type = type;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@ -148,154 +50,115 @@ void mc146818_device::device_start()
m_clock_timer = timer_alloc(TIMER_CLOCK);
m_periodic_timer = timer_alloc(TIMER_PERIODIC);
memset(m_data, 0, sizeof(m_data));
m_clock_timer->adjust(attotime::from_hz(1), 0, attotime::from_hz(1));
m_periodic_timer->adjust(attotime::never);
m_period = attotime::never;
set_base_datetime();
m_write_irq.resolve_safe();
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mc146818_device::device_reset()
{
m_data[REG_B] &= ~(REG_B_UIE | REG_B_AIE | REG_B_PIE | REG_B_SQWE);
m_data[REG_C] = 0;
}
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
int year/*, month*/;
if (id == TIMER_PERIODIC) {
m_data[0x0c] |= 0xc0;
m_write_irq(CLEAR_LINE);
return;
}
if (BCD_MODE)
switch (id)
{
SECOND=bcd_adjust(SECOND+1);
if (SECOND>=0x60)
case TIMER_PERIODIC:
m_data[REG_C] |= REG_C_PF;
update_irq();
break;
case TIMER_CLOCK:
if (!(m_data[REG_B] & REG_B_SET))
{
SECOND=0;
MINUTE=bcd_adjust(MINUTE+1);
if (MINUTE>=0x60)
/// TODO: find out how the real chip deals with updates when binary/bcd values are already outside the normal range
int seconds = get_seconds() + 1;
if (seconds < 60)
{
MINUTE=0;
HOUR=bcd_adjust(HOUR+1);
// different handling of hours
if (HOUR>=0x24)
set_seconds(seconds);
}
else
{
set_seconds(0);
int minutes = get_minutes() + 1;
if (minutes < 60)
{
HOUR=0;
WEEK_DAY=bcd_adjust(WEEK_DAY+1)%7;
DAY=bcd_adjust(DAY+1);
//month=bcd_2_dec(MONTH);
year=bcd_2_dec(YEAR);
if (m_type!=MC146818_IGNORE_CENTURY) year+=bcd_2_dec(CENTURY)*100;
else year+=2000; // save for julian_days_in_month calculation
DAY=bcd_adjust(DAY+1);
if (DAY>gregorian_days_in_month(MONTH, year))
set_minutes(minutes);
}
else
{
set_minutes(0);
int hours = get_hours() + 1;
if (hours < 24)
{
DAY=1;
MONTH=bcd_adjust(MONTH+1);
if (MONTH>0x12)
set_hours(hours);
}
else
{
set_hours(0);
int dayofweek = get_dayofweek() + 1;
if (dayofweek <= 7)
{
MONTH=1;
YEAR=year=bcd_adjust(YEAR+1);
if (m_type!=MC146818_IGNORE_CENTURY)
set_dayofweek(dayofweek);
}
else
{
set_dayofweek(1);
}
int dayofmonth = get_dayofmonth() + 1;
if (dayofmonth <= gregorian_days_in_month(get_month(), get_year() + 2000))
{
set_dayofmonth(dayofmonth);
}
else
{
set_dayofmonth(1);
int month = get_month() + 1;
if (month <= 12)
{
if (year>=0x100)
{
CENTURY=bcd_adjust(CENTURY+1);
}
set_month(month);
}
else
{
set_month(1);
set_year((get_year() + 1) % 100);
}
}
}
}
}
}
}
else
{
SECOND=SECOND+1;
if (SECOND>=60)
{
SECOND=0;
MINUTE=MINUTE+1;
if (MINUTE>=60) {
MINUTE=0;
HOUR=HOUR+1;
// different handling of hours //?
if (HOUR>=24) {
HOUR=0;
WEEK_DAY=(WEEK_DAY+1)%7;
year=YEAR;
if (m_type!=MC146818_IGNORE_CENTURY) year+=CENTURY*100;
else year+=2000; // save for julian_days_in_month calculation
if (++DAY>gregorian_days_in_month(MONTH, year)) {
DAY=1;
if (++MONTH>12) {
MONTH=1;
YEAR++;
if (m_type!=MC146818_IGNORE_CENTURY) {
if (YEAR>=100) { CENTURY++;YEAR=0; }
} else {
YEAR%=100;
}
}
}
}
if ((m_data[REG_ALARM_SECONDS] == m_data[REG_SECONDS] || (m_data[REG_ALARM_SECONDS] & ALARM_DONTCARE) == ALARM_DONTCARE) &&
(m_data[REG_ALARM_MINUTES] == m_data[REG_MINUTES] || (m_data[REG_ALARM_MINUTES] & ALARM_DONTCARE) == ALARM_DONTCARE) &&
(m_data[REG_ALARM_HOURS] == m_data[REG_HOURS] || (m_data[REG_ALARM_HOURS] & ALARM_DONTCARE) == ALARM_DONTCARE))
{
// set the alarm interrupt flag AF
m_data[REG_C] |= REG_C_AF;
}
// set the update-ended interrupt Flag UF
m_data[REG_C] |= REG_C_UF;
update_irq();
m_last_refresh = machine().time();
}
break;
}
if (m_data[1] == SECOND && //
m_data[3] == MINUTE && //
m_data[5] == HOUR) {
// set the alarm interrupt flag AF
m_data[0x0c] |= 0x20;
} else {
// clear the alarm interrupt flag AF
m_data[0x0c] &= ~0x20;
if ((m_data[0x0c] & 0x70) == 0) {
// clear IRQF
m_data[0x0c] &= ~0x80;
}
}
// set the update-ended interrupt Flag UF
m_data[0x0c] |= 0x10;
// set the interrupt request flag IRQF
// FIXME: should throw IRQ line as well
if ((m_data[0x0b] & m_data[0x0c] & 0x30) != 0) {
m_data[0x0c] |= 0x80;
}
// IRQ line is active low
m_write_irq((m_data[0x0c] & 0x80) ? CLEAR_LINE : ASSERT_LINE);
m_updated = true; /* clock has been updated */
m_last_refresh = machine().time();
}
//-------------------------------------------------
// rtc_clock_updated -
//-------------------------------------------------
void mc146818_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
{
YEAR = year;
MONTH = month;
DAY = day;
WEEK_DAY = day_of_week;
HOUR = hour;
MINUTE = minute;
SECOND = second;
}
@ -316,7 +179,14 @@ void mc146818_device::nvram_default()
memcpy(m_data, m_region->base(), bytes);
}
else
{
memset(m_data, 0, sizeof(m_data));
}
set_base_datetime();
update_timer();
update_irq();
}
@ -328,7 +198,10 @@ void mc146818_device::nvram_default()
void mc146818_device::nvram_read(emu_file &file)
{
file.read(m_data, sizeof(m_data));
set_base_datetime();
update_timer();
update_irq();
}
@ -344,19 +217,144 @@ void mc146818_device::nvram_write(emu_file &file)
//-------------------------------------------------
// dec_2_local - convert from decimal to BCD if
// necessary
// to_ram - convert value to current ram format
//-------------------------------------------------
inline int mc146818_device::dec_2_local(int a)
int mc146818_device::to_ram(int a)
{
return BCD_MODE ? dec_2_bcd(a) : a;
if (!(m_data[REG_B] & REG_B_DM))
return dec_2_bcd(a);
return a;
}
//-------------------------------------------------
// dec_2_local - convert from decimal to BCD if
// necessary
// from_ram - convert value from current ram format
//-------------------------------------------------
int mc146818_device::from_ram(int a)
{
if (!(m_data[REG_B] & REG_B_DM))
return bcd_2_dec(a);
return a;
}
int mc146818_device::get_seconds()
{
return from_ram(m_data[REG_SECONDS]);
}
void mc146818_device::set_seconds(int seconds)
{
m_data[REG_SECONDS] = to_ram(seconds);
}
int mc146818_device::get_minutes()
{
return from_ram(m_data[REG_MINUTES]);
}
void mc146818_device::set_minutes(int minutes)
{
m_data[REG_MINUTES] = to_ram(minutes);
}
int mc146818_device::get_hours()
{
if (!(m_data[REG_B] & REG_B_24_12))
{
int hours = from_ram(m_data[REG_HOURS] & ~HOURS_PM);
if (hours == 12)
{
hours = 0;
}
if (m_data[REG_HOURS] & HOURS_PM)
{
hours += 12;
}
return hours;
}
else
{
return from_ram(m_data[REG_HOURS]);
}
}
void mc146818_device::set_hours(int hours)
{
if (!(m_data[REG_B] & REG_B_24_12))
{
int pm = 0;
if (hours >= 12)
{
hours -= 12;
pm = HOURS_PM;
}
if (hours == 0)
{
hours = 12;
}
m_data[REG_HOURS] = to_ram(hours) | pm;
}
else
{
m_data[REG_HOURS] = to_ram(hours);
}
}
int mc146818_device::get_dayofweek()
{
return from_ram(m_data[REG_DAYOFWEEK]);
}
void mc146818_device::set_dayofweek(int dayofweek)
{
m_data[REG_DAYOFWEEK] = to_ram(dayofweek);
}
int mc146818_device::get_dayofmonth()
{
return from_ram(m_data[REG_DAYOFMONTH]);
}
void mc146818_device::set_dayofmonth(int dayofmonth)
{
m_data[REG_DAYOFMONTH] = to_ram(dayofmonth);
}
int mc146818_device::get_month()
{
return from_ram(m_data[REG_MONTH]);
}
void mc146818_device::set_month(int month)
{
m_data[REG_MONTH] = to_ram(month);
}
int mc146818_device::get_year()
{
return from_ram(m_data[REG_YEAR]);
}
void mc146818_device::set_year(int year)
{
m_data[REG_YEAR] = to_ram(year);
}
//-------------------------------------------------
// set_base_datetime - update clock with real time
//-------------------------------------------------
void mc146818_device::set_base_datetime()
@ -366,34 +364,117 @@ void mc146818_device::set_base_datetime()
machine().base_datetime(systime);
current_time = (m_type == MC146818_UTC) ? systime.utc_time: systime.local_time;
current_time = (m_use_utc) ? systime.utc_time: systime.local_time;
// logerror("mc146818_set_base_datetime %02d/%02d/%02d %02d:%02d:%02d\n",
// current_time.year % 100, current_time.month + 1, current_time.mday,
// current_time.hour,current_time.minute, current_time.second);
if (HOURS_24 || (current_time.hour < 12))
HOUR = dec_2_local(current_time.hour);
else
HOUR = dec_2_local(current_time.hour - 12) | 0x80;
set_seconds(current_time.second);
set_minutes(current_time.minute);
set_hours(current_time.hour);
set_dayofweek(current_time.weekday + 1);
set_dayofmonth(current_time.mday);
set_month(current_time.month + 1);
set_year(current_time.year % 100);
if (m_type != MC146818_IGNORE_CENTURY)
CENTURY = dec_2_local(current_time.year /100);
SECOND = dec_2_local(current_time.second);
MINUTE = dec_2_local(current_time.minute);
DAY = dec_2_local(current_time.mday);
MONTH = dec_2_local(current_time.month + 1);
YEAR = dec_2_local(current_time.year % 100);
WEEK_DAY = current_time.weekday;
if (current_time.is_dst)
m_data[0xb] |= 1;
else
m_data[0xb] &= ~1;
if (m_century_index >= 0)
m_data[m_century_index] = to_ram(current_time.year / 100);
}
//-------------------------------------------------
// update_timer - update timer based on A register
//-------------------------------------------------
void mc146818_device::update_timer()
{
int bypass;
switch (m_data[REG_A] & (REG_A_DV2 | REG_A_DV1 | REG_A_DV0))
{
case 0:
bypass = 0;
break;
case REG_A_DV0:
bypass = 2;
break;
case REG_A_DV1:
bypass = 7;
break;
case REG_A_DV2 | REG_A_DV1:
case REG_A_DV2 | REG_A_DV1 | REG_A_DV0:
bypass = 22;
break;
default:
// TODO: other combinations of divider bits are used for test purposes only
bypass = 22;
break;
}
attotime update_period = attotime::never;
attotime update_interval = attotime::never;
attotime periodic_period = attotime::never;
attotime periodic_interval = attotime::never;
if (bypass < 22)
{
int shift = 22 - bypass;
double update_hz = (double) clock() / (1 << shift);
// TODO: take the time since last timer into account
update_period = attotime::from_hz(update_hz * 2);
update_interval = attotime::from_hz(update_hz);
int rate_select = m_data[REG_A] & (REG_A_RS3 | REG_A_RS2 | REG_A_RS1 | REG_A_RS0);
if (rate_select != 0)
{
shift = (rate_select + 6) - bypass;
if (shift <= 1)
shift += 7;
double periodic_hz = (double) clock() / (1 << shift);
// TODO: take the time since last timer into account
periodic_period = attotime::from_hz(periodic_hz * 2);
periodic_interval = attotime::from_hz(periodic_hz);
}
}
m_clock_timer->adjust(update_period, 0, update_interval);
m_periodic_timer->adjust(periodic_period, 0, periodic_interval);
}
//-------------------------------------------------
// update_irq - Update irq based on B & C register
//-------------------------------------------------
void mc146818_device::update_irq()
{
// IRQ line is active low
if (((m_data[REG_C] & REG_C_UF) && (m_data[REG_B] & REG_B_UIE)) ||
((m_data[REG_C] & REG_C_AF) && (m_data[REG_B] & REG_B_AIE)) ||
((m_data[REG_C] & REG_C_PF) && (m_data[REG_B] & REG_B_PIE)))
{
m_data[REG_C] |= REG_C_IRQF;
m_write_irq(CLEAR_LINE);
}
else
{
m_data[REG_C] &= REG_C_IRQF;
m_write_irq(ASSERT_LINE);
}
}
//-------------------------------------------------
// read - I/O handler for reading
//-------------------------------------------------
@ -401,42 +482,38 @@ void mc146818_device::set_base_datetime()
READ8_MEMBER( mc146818_device::read )
{
UINT8 data = 0;
switch (offset) {
switch (offset)
{
case 0:
data = m_index;
break;
case 1:
switch (m_index % MC146818_DATA_SIZE) {
case 0xa:
data = m_data[m_index % MC146818_DATA_SIZE];
switch (m_index)
{
case REG_A:
data = m_data[REG_A];
// Update In Progress (UIP) time for 32768 Hz is 244+1984usec
/// TODO: support other dividers
if ((space.machine().time() - m_last_refresh) < attotime::from_usec(244+1984))
data |= 0x80;
#if 0
/* for pc1512 bios realtime clock test */
m_data[m_index % MC146818_DATA_SIZE] ^= 0x80; /* 0x80 update in progress */
#endif
data |= REG_A_UIP;
break;
case 0xc:
// if(m_updated) /* the clock has been updated */
// data = 0x10;
// else
// data = 0x00;
case REG_C:
// the unused bits b0 ... b3 are always read as 0
data = m_data[m_index % MC146818_DATA_SIZE] & 0xf0;
data = m_data[REG_C] & (REG_C_IRQF | REG_C_PF | REG_C_AF | REG_C_UF);
// read 0x0c will clear all IRQ flags in register 0x0c
m_data[m_index % MC146818_DATA_SIZE] &= 0x0f;
m_write_irq(ASSERT_LINE);
m_data[REG_C] &= ~(REG_C_IRQF | REG_C_PF | REG_C_AF | REG_C_UF);
update_irq();
break;
case 0xd:
case REG_D:
/* battery ok */
data = m_data[m_index % MC146818_DATA_SIZE] | 0x80;
data = m_data[REG_D] | REG_D_VRT;
break;
default:
data = m_data[m_index % MC146818_DATA_SIZE];
data = m_data[m_index];
break;
}
break;
@ -444,6 +521,7 @@ READ8_MEMBER( mc146818_device::read )
if (LOG_MC146818)
logerror("mc146818_port_r(): index=0x%02x data=0x%02x\n", m_index, data);
return data;
}
@ -454,51 +532,45 @@ READ8_MEMBER( mc146818_device::read )
WRITE8_MEMBER( mc146818_device::write )
{
attotime rate;
if (LOG_MC146818)
logerror("mc146818_port_w(): index=0x%02x data=0x%02x\n", m_index, data);
switch (offset) {
switch (offset)
{
case 0:
m_index = data;
m_index = data % MC146818_DATA_SIZE;
break;
case 1:
switch(m_index % MC146818_DATA_SIZE)
switch (m_index)
{
case 0x0a:
// fixme: allow different time base
data &= 0x0f;
if (data > 2)
m_period = attotime::from_hz(32768 >> (data - 1));
else if (data > 0)
m_period = attotime::from_hz(32768 >> (data + 6));
else m_period = attotime::never;
case REG_SECONDS:
// top bit of SECONDS is read only
m_data[REG_SECONDS] = data & ~0x80;
break;
if(m_data[0x0b] & 0x40)
rate = attotime::zero;
else rate = attotime::never;
case REG_A:
// top bit of A is read only
m_data[REG_A] = data & ~REG_A_UIP;
update_timer();
break;
m_periodic_timer->adjust(rate, 0, m_period);
data |= m_data[m_index % MC146818_DATA_SIZE] & 0xf0;
m_data[m_index % MC146818_DATA_SIZE] = data;
case REG_B:
if ((data & REG_B_SET) && !(m_data[REG_B] & REG_B_SET))
data &= ~REG_B_UIE;
m_data[REG_B] = data;
update_irq();
break;
case 0x0b:
if(data & 0x80)
m_updated = false;
// this probably isn't right but otherwise
// you'll be making a lot of unnecessary callbacks
if (data & 0x40)
m_periodic_timer->adjust(attotime::zero, 0, m_period);
else
m_periodic_timer->adjust(attotime::never);
m_data[m_index % MC146818_DATA_SIZE] = data;
break;
case 0x0c:
// register 0x0c is readonly
case REG_C:
case REG_D:
// register C & D is readonly
break;
default:
m_data[m_index % MC146818_DATA_SIZE] = data;
m_data[m_index] = data;
break;
}
break;
}

View File

@ -4,29 +4,33 @@
Implementation of the MC146818 chip
Real time clock chip with battery backed ram
Used in IBM PC/AT, several PC clones, Amstrad NC200
Peter Trauner (peter.trauner@jk.uni-linz.ac.at)
Real time clock chip with CMOS battery backed ram
Used in IBM PC/AT, several PC clones, Amstrad NC200, Apollo workstations
*********************************************************************/
#ifndef __MC146818_H__
#define __MC146818_H__
#include "emu.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_MC146818_IRQ_ADD(_tag, _type, _irq) \
MCFG_DEVICE_ADD(_tag, MC146818, 0) \
mc146818_device::static_set_type(*device, mc146818_device::_type); \
#define MCFG_MC146818_ADD(_tag, _xtal) \
MCFG_DEVICE_ADD(_tag, MC146818, _xtal)
#define MCFG_MC146818_IRQ_HANDLER(_irq) \
downcast<mc146818_device *>(device)->set_irq_callback(DEVCB2_##_irq);
#define MCFG_MC146818_ADD(_tag, _type) \
MCFG_DEVICE_ADD(_tag, MC146818, 0) \
mc146818_device::static_set_type(*device, mc146818_device::_type);
// The MC146818 doesn't have century support, but when syncing the date & time at startup we can optionally store the century.
#define MCFG_MC146818_CENTURY_INDEX(_century_index) \
downcast<mc146818_device *>(device)->set_century_index(_century_index);
// The MC146818 doesn't have UTC support, but when syncing the data & time at startup we can use UTC instead of local time.
#define MCFG_MC146818_UTC(_utc) \
downcast<mc146818_device *>(device)->set_use_utc(_utc);
//**************************************************************************
// TYPE DEFINITIONS
@ -35,76 +39,134 @@
// ======================> mc146818_device
class mc146818_device : public device_t,
public device_rtc_interface,
public device_nvram_interface
{
public:
// values
enum mc146818_type
{
MC146818_STANDARD,
MC146818_IGNORE_CENTURY, // century is NOT set, for systems having other usage of this byte
MC146818_ENHANCED,
MC146818_UTC
};
// construction/destruction
mc146818_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// inline configuration helpers
static void static_set_type(device_t &device, mc146818_type type);
// callbacks
template<class _irq> void set_irq_callback(_irq irq) { m_write_irq.set_callback(irq); }
void set_century_index(int century_index) { m_century_index = century_index; }
void set_use_utc(bool use_utc) { m_use_utc = use_utc; }
// read/write access
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
DECLARE_WRITE8_MEMBER( address_w ) { write(space, 0, data); }
DECLARE_READ8_MEMBER( data_r ) { return read(space, 1); }
DECLARE_WRITE8_MEMBER( data_w ) { write(space, 1, data); }
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
// device_rtc_interface overrides
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second);
// device_nvram_interface overrides
virtual void nvram_default();
virtual void nvram_read(emu_file &file);
virtual void nvram_write(emu_file &file);
// internal helpers
int dec_2_local(int a);
void set_base_datetime();
static const unsigned char ALARM_DONTCARE = 0xc0;
static const unsigned char HOURS_PM = 0x80;
devcb2_write_line m_write_irq;
private:
enum
{
REG_SECONDS = 0,
REG_ALARM_SECONDS = 1,
REG_MINUTES = 2,
REG_ALARM_MINUTES = 3,
REG_HOURS = 4,
REG_ALARM_HOURS = 5,
REG_DAYOFWEEK = 6,
REG_DAYOFMONTH = 7,
REG_MONTH = 8,
REG_YEAR = 9,
REG_A = 0xa,
REG_B = 0xb,
REG_C = 0xc,
REG_D = 0xd
};
enum
{
REG_A_RS0 = 1,
REG_A_RS1 = 2,
REG_A_RS2 = 4,
REG_A_RS3 = 8,
REG_A_DV0 = 16,
REG_A_DV1 = 32,
REG_A_DV2 = 64,
REG_A_UIP = 128
};
enum
{
REG_B_DSE = 1, // TODO: When set the chip will adjust the clock by an hour at start and end of DST
REG_B_24_12 = 2,
REG_B_DM = 4,
REG_B_SQWE = 8, // TODO: When set the chip will output a square wave on SQW pin
REG_B_UIE = 16,
REG_B_AIE = 32,
REG_B_PIE = 64,
REG_B_SET = 128,
};
enum
{
REG_C_UF = 16,
REG_C_AF = 32,
REG_C_PF = 64,
REG_C_IRQF = 128
};
enum
{
REG_D_VRT = 128
};
// internal helpers
int to_ram(int a);
int from_ram(int a);
void set_base_datetime();
void update_irq();
void update_timer();
int get_seconds();
void set_seconds(int seconds);
int get_minutes();
void set_minutes(int minutes);
int get_hours();
void set_hours(int hours);
int get_dayofweek();
void set_dayofweek(int dayofweek);
int get_dayofmonth();
void set_dayofmonth(int dayofmonth);
int get_month();
void set_month(int month);
int get_year();
void set_year(int year);
// internal state
static const int MC146818_DATA_SIZE = 0x80;
mc146818_type m_type;
// TODO: MC146818 only has 64 bytes, but semi-compatible chips have more.
// drivers are using this device when the actual hardware uses a different
// chip (which in most cases also has additional functionality).
static const int MC146818_DATA_SIZE = 128;
UINT8 m_index;
UINT8 m_data[MC146818_DATA_SIZE];
UINT16 m_eindex;
UINT8 m_edata[0x2000];
bool m_updated; /* update ended interrupt flag */
attotime m_last_refresh;
attotime m_period;
static const device_timer_id TIMER_CLOCK = 0;
static const device_timer_id TIMER_PERIODIC = 1;
emu_timer *m_clock_timer;
emu_timer *m_periodic_timer;
devcb2_write_line m_write_irq;
int m_century_index;
bool m_use_utc;
};

View File

@ -1709,7 +1709,7 @@ static MACHINE_CONFIG_START( aristmk4, aristmk4_state )
MCFG_VIA6522_ADD("via6522_0", 0, via_interface) /* 1 MHz.(only 1 or 2 MHz.are valid) */
MCFG_PIA6821_ADD("pia6821_0", aristmk4_pia1_intf)
MCFG_MC6845_ADD("crtc", C6545_1, "screen", MAIN_CLOCK/8, mc6845_intf) // TODO: type is unknown
MCFG_MC146818_ADD("rtc", MC146818_IGNORE_CENTURY)
MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz )
MCFG_SPEAKER_STANDARD_MONO("mono")

View File

@ -891,7 +891,7 @@ static MACHINE_CONFIG_START( rastersp, rastersp_state )
/* Devices */
MCFG_TIMER_DRIVER_ADD("tms_timer1", rastersp_state, tms_timer1)
MCFG_TIMER_DRIVER_ADD("tms_tx_timer", rastersp_state, tms_tx_timer)
MCFG_MC146818_ADD("rtc", MC146818_STANDARD)
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
MCFG_NVRAM_HANDLER(rastersp)
MCFG_NSCSI_BUS_ADD("scsibus")

View File

@ -228,7 +228,9 @@ MACHINE_CONFIG_FRAGMENT(pcat_common)
MCFG_I8237_ADD( "dma8237_1", XTAL_14_31818MHz/3, dma8237_1_config )
MCFG_I8237_ADD( "dma8237_2", XTAL_14_31818MHz/3, dma8237_2_config )
MCFG_PIT8254_ADD( "pit8254", at_pit8254_config )
MCFG_MC146818_IRQ_ADD("rtc", MC146818_STANDARD, DEVWRITELINE("pic8259_2", pic8259_device, ir0_w))
MCFG_MC146818_ADD("rtc", XTAL_32_768kHz)
MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic8259_2", pic8259_device, ir0_w))
MCFG_MC146818_CENTURY_INDEX(0x32)
MCFG_KBDC8042_ADD("kbdc", at8042)
MACHINE_CONFIG_END

View File

@ -372,7 +372,7 @@ static MACHINE_CONFIG_START( ppc512, amstrad_pc_state )
MCFG_FLOPPY_DRIVE_ADD("fdc:0", ibmpc_floppies, "525dd", ibmpc_floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("fdc:1", ibmpc_floppies, "525dd", ibmpc_floppy_formats)
MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY )
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
/* internal ram */
MCFG_RAM_ADD(RAM_TAG)

View File

@ -1016,7 +1016,7 @@ static MACHINE_CONFIG_DERIVED( aleste, amstrad )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MCFG_PALETTE_LENGTH(32+64)
MCFG_PALETTE_INIT_OVERRIDE(amstrad_state,aleste)
MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY )
MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz )
MCFG_DEVICE_REMOVE("upd765")
MCFG_I8272A_ADD("upd765", true)

View File

@ -339,7 +339,9 @@ static MACHINE_CONFIG_FRAGMENT( at_motherboard )
MCFG_AT_KEYBOARD_CONTROLLER_ADD("keybc", XTAL_12MHz, keyboard_controller_intf)
MCFG_PC_KBDC_ADD("pc_kbdc", pc_kbdc_intf)
MCFG_MC146818_IRQ_ADD( "rtc", MC146818_STANDARD, WRITELINE(at_state, at_mc146818_irq))
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
MCFG_MC146818_IRQ_HANDLER(WRITELINE(at_state, at_mc146818_irq))
MCFG_MC146818_CENTURY_INDEX(0x32)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")

View File

@ -872,7 +872,7 @@ static MACHINE_CONFIG_START( bbcm, bbc_state )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
/* rtc and cmos */
MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY )
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
/* printer */
MCFG_CENTRONICS_PRINTER_ADD("centronics", bbcb_centronics_config)

View File

@ -233,7 +233,7 @@ static MACHINE_CONFIG_START( bebox, bebox_state )
MCFG_SMC37C78_ADD("smc37c78")
MCFG_FLOPPY_DRIVE_ADD("smc37c78:0", bebox_floppies, "35hd", bebox_state::floppy_formats)
MCFG_MC146818_ADD( "rtc", MC146818_STANDARD )
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
MCFG_KBDC8042_ADD("kbdc", bebox_8042_interface)
/* internal ram */

View File

@ -860,7 +860,8 @@ static MACHINE_CONFIG_START( hx20, hx20_state )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
// devices
MCFG_MC146818_IRQ_ADD(MC146818_TAG, MC146818_STANDARD, WRITELINE(hx20_state, rtc_irq_w))
MCFG_MC146818_ADD(MC146818_TAG, XTAL_4_194304Mhz)
MCFG_MC146818_IRQ_HANDLER(WRITELINE(hx20_state, rtc_irq_w))
MCFG_RS232_PORT_ADD(RS232_TAG, rs232_intf, default_rs232_devices, NULL)
MCFG_CASSETTE_ADD(CASSETTE_TAG, default_cassette_interface)
MCFG_EPSON_SIO_ADD("sio", "tf20")

View File

@ -855,7 +855,7 @@ static MACHINE_CONFIG_DERIVED( mbee256, mbee128 )
MCFG_CPU_MODIFY( "maincpu" )
MCFG_CPU_IO_MAP(mbee256_io)
MCFG_MACHINE_RESET_OVERRIDE(mbee_state, mbee256 )
MCFG_MC146818_ADD( "rtc", MC146818_STANDARD )
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
MCFG_DEVICE_REMOVE("crtc")
MCFG_MC6845_ADD("crtc", SY6545_1, "screen", XTAL_13_5MHz / 8, mbee256_crtc)
MACHINE_CONFIG_END
@ -865,7 +865,7 @@ static MACHINE_CONFIG_DERIVED( mbeett, mbeeppc )
MCFG_CPU_PROGRAM_MAP(mbeett_mem)
MCFG_CPU_IO_MAP(mbeett_io)
MCFG_MACHINE_RESET_OVERRIDE(mbee_state, mbeett )
MCFG_MC146818_ADD( "rtc", MC146818_STANDARD )
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
MCFG_DEVICE_REMOVE("crtc")
MCFG_MC6845_ADD("crtc", SY6545_1, "screen", XTAL_13_5MHz / 8, mbee256_crtc)
MACHINE_CONFIG_END

View File

@ -391,7 +391,8 @@ static MACHINE_CONFIG_START( micronic, micronic_state )
MCFG_NVRAM_HANDLER(micronic)
MCFG_MC146818_IRQ_ADD( MC146818_TAG, MC146818_IGNORE_CENTURY, WRITELINE(micronic_state, mc146818_irq))
MCFG_MC146818_ADD( MC146818_TAG, XTAL_4_194304Mhz )
MCFG_MC146818_IRQ_HANDLER(WRITELINE(micronic_state, mc146818_irq))
MACHINE_CONFIG_END
/* ROM definition */

View File

@ -1644,7 +1644,7 @@ static MACHINE_CONFIG_DERIVED( nc200, nc100 )
MCFG_FLOPPY_DRIVE_ADD("upd765:0", ibmpc_floppies, "525dd", ibmpc_floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("upd765:1", ibmpc_floppies, "525dd", ibmpc_floppy_formats)
MCFG_MC146818_ADD( "mc", MC146818_STANDARD )
MCFG_MC146818_ADD( "mc", XTAL_4_194304Mhz )
/* internal ram */
MCFG_RAM_MODIFY(RAM_TAG)

View File

@ -179,7 +179,7 @@ static MACHINE_CONFIG_START( orionz80, orion_state )
MCFG_VIDEO_START_OVERRIDE(orion_state,orion128)
MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY )
MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz )
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)

View File

@ -14,7 +14,6 @@
TODO:
- adjust mouse speed
- RTC should not be y2k compliant
- pc1512 V3 VDU check fails
- Amstrad SM2400 internal modem
- Amstrad RP4 diagnostic ISA card (PC1512)
@ -1305,7 +1304,8 @@ static MACHINE_CONFIG_START( pc1512, pc1512_state )
MCFG_I8237_ADD(I8237A5_TAG, XTAL_24MHz/6, dmac_intf)
MCFG_PIC8259_ADD(I8259A2_TAG, INPUTLINE(I8086_TAG, INPUT_LINE_IRQ0), VCC, NULL)
MCFG_PIT8253_ADD(I8253_TAG, pit_intf)
MCFG_MC146818_IRQ_ADD(MC146818_TAG, MC146818_STANDARD, DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w))
MCFG_MC146818_ADD(MC146818_TAG, XTAL_32_768kHz)
MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w))
MCFG_PC_FDC_XT_ADD(PC_FDC_XT_TAG)
MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":0", pc1512_floppies, "525dd", pc1512_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":1", pc1512_floppies, NULL, pc1512_state::floppy_formats)
@ -1368,7 +1368,8 @@ static MACHINE_CONFIG_START( pc1640, pc1640_state )
MCFG_I8237_ADD(I8237A5_TAG, XTAL_24MHz/6, dmac_intf)
MCFG_PIC8259_ADD(I8259A2_TAG, INPUTLINE(I8086_TAG, INPUT_LINE_IRQ0), VCC, NULL)
MCFG_PIT8253_ADD(I8253_TAG, pit_intf)
MCFG_MC146818_IRQ_ADD(MC146818_TAG, MC146818_STANDARD, DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w))
MCFG_MC146818_ADD(MC146818_TAG, XTAL_32_768kHz)
MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w))
MCFG_PC_FDC_XT_ADD(PC_FDC_XT_TAG)
MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":0", pc1512_floppies, "525dd", pc1512_state::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":1", pc1512_floppies, NULL, pc1512_state::floppy_formats)

View File

@ -882,7 +882,8 @@ static MACHINE_CONFIG_START( qx10, qx10_state )
MCFG_I8237_ADD("8237dma_1", MAIN_CLK/4, qx10_dma8237_1_interface)
MCFG_I8237_ADD("8237dma_2", MAIN_CLK/4, qx10_dma8237_2_interface)
MCFG_UPD7220_ADD("upd7220", MAIN_CLK/6, hgdc_intf, upd7220_map) // unk clock
MCFG_MC146818_IRQ_ADD( "rtc", MC146818_STANDARD, DEVWRITELINE("pic8259_slave", pic8259_device, ir2_w))
MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz )
MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir2_w))
MCFG_UPD765A_ADD("upd765", true, true)
MCFG_FLOPPY_DRIVE_ADD("upd765:0", qx10_floppies, "525dd", floppy_image_device::default_floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("upd765:1", qx10_floppies, "525dd", floppy_image_device::default_floppy_formats)

View File

@ -490,7 +490,7 @@ static MACHINE_CONFIG_START( sgi_ip2, sgi_ip2_state )
MCFG_DUART68681_ADD( "duart68681a", XTAL_3_6864MHz, sgi_ip2_duart68681a_config ) /* Y3 3.6864MHz Xtal ??? copy-over from dectalk */
MCFG_DUART68681_ADD( "duart68681b", XTAL_3_6864MHz, sgi_ip2_duart68681b_config ) /* Y3 3.6864MHz Xtal ??? copy-over from dectalk */
MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY )
MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")

View File

@ -1394,7 +1394,8 @@ MACHINE_CONFIG_FRAGMENT( apollo )
MCFG_PIC8259_ADD( APOLLO_PIC2_TAG, WRITELINE(apollo_state,apollo_pic8259_slave_set_int_line), GND, NULL)
MCFG_PTM6840_ADD(APOLLO_PTM_TAG, apollo_ptm_config)
MCFG_MC146818_ADD( APOLLO_RTC_TAG, MC146818_UTC )
MCFG_MC146818_ADD( APOLLO_RTC_TAG, XTAL_4_194304Mhz )
MCFG_MC146818_UTC( true )
MCFG_DUART68681_ADD( APOLLO_SIO_TAG, XTAL_3_6864MHz, apollo_sio_config )
MCFG_DUART68681_ADD( APOLLO_SIO2_TAG, XTAL_3_6864MHz, apollo_sio2_config )

View File

@ -170,7 +170,9 @@ static MACHINE_CONFIG_FRAGMENT( cs4031 )
MCFG_PIC8259_ADD("intc1", WRITELINE(cs4031_device, intc1_int_w), VCC, READ8(cs4031_device, intc1_slave_ack_r))
MCFG_PIC8259_ADD("intc2", DEVWRITELINE("intc1", pic8259_device, ir2_w), GND, NULL)
MCFG_PIT8254_ADD("ctc", cs4031_pit_config)
MCFG_MC146818_IRQ_ADD("rtc", MC146818_STANDARD, WRITELINE(cs4031_device, rtc_irq_w))
MCFG_MC146818_ADD("rtc", XTAL_32_768kHz)
MCFG_MC146818_IRQ_HANDLER(WRITELINE(cs4031_device, rtc_irq_w))
MCFG_MC146818_CENTURY_INDEX(0x32)
MACHINE_CONFIG_END
machine_config_constructor cs4031_device::device_mconfig_additions() const
@ -317,8 +319,7 @@ void cs4031_device::device_start()
m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(cs4031_device::keyb_data_r), this), write8_delegate(FUNC(cs4031_device::keyb_data_w), this), 0x000000ff);
m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(cs4031_device::portb_r), this), write8_delegate(FUNC(cs4031_device::portb_w), this), 0x0000ff00);
m_space_io->install_readwrite_handler(0x0064, 0x0067, read8_delegate(FUNC(cs4031_device::keyb_status_r), this), write8_delegate(FUNC(cs4031_device::keyb_command_w), this), 0x000000ff);
m_space_io->install_write_handler(0x0070, 0x0073, write8_delegate(FUNC(cs4031_device::rtc_w), this), 0x000000ff);
m_space_io->install_readwrite_handler(0x0070, 0x0073, read8_delegate(FUNC(mc146818_device::data_r), &(*m_rtc)), write8_delegate(FUNC(mc146818_device::data_w), &(*m_rtc)), 0x0000ff00);
m_space_io->install_readwrite_handler(0x0070, 0x0073, read8_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8_delegate(FUNC(cs4031_device::rtc_w), this), 0x0000ffff);
m_space_io->install_readwrite_handler(0x0080, 0x008f, read8_delegate(FUNC(cs4031_device::dma_page_r), this), write8_delegate(FUNC(cs4031_device::dma_page_w), this), 0xffffffff);
m_space_io->install_readwrite_handler(0x0090, 0x0093, read8_delegate(FUNC(cs4031_device::sysctrl_r), this), write8_delegate(FUNC(cs4031_device::sysctrl_w), this), 0x00ff0000);
m_space_io->install_readwrite_handler(0x00a0, 0x00a3, read8_delegate(FUNC(pic8259_device::read), &(*m_intc2)), write8_delegate(FUNC(pic8259_device::write), &(*m_intc2)), 0x0000ffff);
@ -993,6 +994,11 @@ WRITE8_MEMBER( cs4031_device::rtc_w )
if (0)
logerror("cs4031_device::rtc_w: %02x\n", data);
m_nmi_mask = !BIT(data, 7);
m_rtc->address_w(space, 0, data & 0x7f);
if (offset == 0)
{
m_nmi_mask = !BIT(data, 7);
data &= 0x7f;
}
m_rtc->write(space, offset, data);
}

View File

@ -114,7 +114,9 @@ static MACHINE_CONFIG_FRAGMENT( southbridge )
MCFG_PC_KBDC_ADD("pc_kbdc", pc_kbdc_intf)
MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL)
MCFG_MC146818_IRQ_ADD("rtc", MC146818_STANDARD, DEVWRITELINE("pic8259_slave", pic8259_device, ir0_w))
MCFG_MC146818_ADD("rtc", XTAL_32_768kHz)
MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir0_w))
MCFG_MC146818_CENTURY_INDEX(0x32)
MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", NULL, false)
MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir6_w))