Skip to content

Commit a13670d

Browse files
Refactor MC146818 periodic interrupt code
Move code from a standalone block into a function and a static variable from it into the ALi's state.
1 parent 0fca5b2 commit a13670d

File tree

2 files changed

+43
-62
lines changed

2 files changed

+43
-62
lines changed

src/AliM1543C.cpp

Lines changed: 36 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ void CAliM1543C::init() {
446446
state.toy_stored_data[0x17] = 0;
447447
}
448448

449+
state.toy_pi_last_fire = 0;
450+
449451
ResetPCI();
450452

451453
// PIT Setup
@@ -760,7 +762,6 @@ void CAliM1543C::toy_write(u32 address, u8 data) {
760762
// periodic interrupt rate divisor of 32 = interrupt every 976.562 ms
761763
// (1024Hz clock)
762764
if (state.toy_stored_data[0x0a] & 0x80) {
763-
764765
// Once the UIP line goes high, we have to stay high for 2228us.
765766
hold_count--;
766767
if (hold_count == 0) {
@@ -782,67 +783,9 @@ void CAliM1543C::toy_write(u32 address, u8 data) {
782783
(2228 / (IPus * 3)) + 1; // .876 @ 847IPus, so we add one.
783784
}
784785
}
785-
786-
//# /****************************************************/
787-
//# #define RTC_CONTROL RTC_REG_B
788-
//# # define RTC_SET 0x80 /* disable updates for clock setting */
789-
//# # define RTC_PIE 0x40 /* periodic interrupt enable */
790-
//# # define RTC_AIE 0x20 /* alarm interrupt enable */
791-
//# # define RTC_UIE 0x10 /* update-finished interrupt enable */
792-
//# # define RTC_SQWE 0x08 /* enable square-wave output */
793-
//# # define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear
794-
//*/ # # define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm
795-
//*/ # # define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
796-
//#
797-
// this is set (by the srm?) to 0x0e = SQWE | DM_BINARY | 24H
798-
// linux sets the PIE bit later.
799-
//# /***********************************************************/
800-
//# #define RTC_INTR_FLAGS RTC_REG_C
801-
//# /* caution - cleared by read */
802-
//# # define RTC_IRQF 0x80 /* any of the following 3 is active */
803-
//# # define RTC_PF 0x40
804-
//# # define RTC_AF 0x20
805-
//# # define RTC_UF 0x10
806-
//#
807786
}
808787

809-
{
810-
/*
811-
See sys/dev/ic/mc146818reg.h and sys/arch/alpha/alpha/mcclock.c
812-
*/
813-
static clock_t last_fire = 0;
814-
clock_t now = clock();
815-
double timedelta = (now - last_fire) / (double)CLOCKS_PER_SEC;
816-
int rate_pow = state.toy_stored_data[0x0a] & 0x0f;
817-
double period = (1 << rate_pow)/65536.0;
818-
#define MC_BASE_32_KHz 0x20
819-
#define RTC_PF 0x40
820-
821-
if (state.toy_stored_data[0x0a] & MC_BASE_32_KHz)
822-
{
823-
if (rate_pow == 0x1)
824-
{
825-
period = 1/256.0;
826-
}
827-
else if (rate_pow == 0x2)
828-
{
829-
period = 1/128.0;
830-
}
831-
}
832-
833-
if (rate_pow && (timedelta >= period))
834-
{
835-
state.toy_stored_data[0x0c] |= RTC_PF;
836-
last_fire = now;
837-
}
838-
}
839-
840-
state.toy_access_ports[1] = state.toy_stored_data[data & 0x7f];
841-
842-
// register C is cleared after a read, and we don't care if its a write
843-
if (data == 0x0c)
844-
state.toy_stored_data[data & 0x7f] = 0;
845-
break;
788+
toy_handle_periodic_interrupt(data);
846789

847790
case 1:
848791
if (state.toy_access_ports[0] == 0x0b &&
@@ -862,6 +805,39 @@ void CAliM1543C::toy_write(u32 address, u8 data) {
862805
}
863806
}
864807

808+
/**
809+
* Handle RTC periodic interrupt.
810+
**/
811+
void CAliM1543C::toy_handle_periodic_interrupt(u8 data) {
812+
/*
813+
See sys/dev/ic/mc146818reg.h and sys/arch/alpha/alpha/mcclock.c in NetBSD and
814+
the RTC datasheet: https://www.nxp.com/docs/en/data-sheet/MC146818.pdf.
815+
*/
816+
clock_t now = clock();
817+
double timedelta = (now - state.toy_pi_last_fire) / (double)CLOCKS_PER_SEC;
818+
int rate_pow = state.toy_stored_data[0x0a] & 0x0f;
819+
double period = (1 << rate_pow) / 65536.0;
820+
821+
if (state.toy_stored_data[0x0a] & MC_BASE_32_KHz) {
822+
if (rate_pow == 0x1) {
823+
period = 1 / 256.0;
824+
} else if (rate_pow == 0x2) {
825+
period = 1 / 128.0;
826+
}
827+
}
828+
829+
if (rate_pow && (timedelta >= period)) {
830+
state.toy_stored_data[0x0c] |= RTC_PF;
831+
state.toy_pi_last_fire = now;
832+
}
833+
834+
state.toy_access_ports[1] = state.toy_stored_data[data & 0x7f];
835+
836+
// register C is cleared after a read, and we don't care if it's a write
837+
if (data == 0x0c)
838+
state.toy_stored_data[data & 0x7f] = 0;
839+
}
840+
865841
/**
866842
* Read from the programmable interrupt timer ports (40h-43h)
867843
*
@@ -960,7 +936,6 @@ void CAliM1543C::pit_write(u32 address, u8 data) {
960936
void CAliM1543C::pit_clock() {
961937
int i;
962938
for (i = 0; i < 3; i++) {
963-
964939
// decrement the counter.
965940
if (state.pit_status[i] & 0x40)
966941
continue;

src/AliM1543C.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@
143143

144144
#define PIT_OFFSET_MAX 6
145145

146+
#define MC_BASE_32_KHz 0x20
147+
#define RTC_PF 0x40
148+
146149
/**
147150
* \brief Emulated ISA part of the ALi M1543C chipset.
148151
*
@@ -189,6 +192,7 @@ class CAliM1543C : public CPCIDevice, public CRunnable {
189192
// REGISTERS 70 - 73: TOY
190193
u8 toy_read(u32 address);
191194
void toy_write(u32 address, u8 data);
195+
void toy_handle_periodic_interrupt(u8 data);
192196

193197
// Timer/Counter
194198
u8 pit_read(u32 address);
@@ -210,14 +214,16 @@ class CAliM1543C : public CPCIDevice, public CRunnable {
210214
/// The state structure contains all elements that need to be saved to the
211215
/// statefile.
212216
struct SAli_state {
213-
214217
// REGISTER 61 (NMI)
215218
u8 reg_61;
216219

217220
// REGISTERS 70 - 73: TOY
218221
u8 toy_stored_data[256];
219222
u8 toy_access_ports[4];
220223

224+
// TOY periodic interrupt last fire
225+
clock_t toy_pi_last_fire;
226+
221227
// Timer/Counter
222228
u32 pit_counter[9];
223229
u8 pit_status[4];

0 commit comments

Comments
 (0)