Heathrow: interrupt registers & mode 1 interrupts.

This commit is contained in:
Maxim Poliakovski 2022-03-14 18:09:11 +01:00
parent 617f75851b
commit 8be44dad82
2 changed files with 76 additions and 41 deletions

View File

@ -209,28 +209,22 @@ uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) {
uint32_t res = 0; uint32_t res = 0;
switch (offset & 0xFC) { switch (offset & 0xFC) {
case 0x14: case MIO_INT_EVENTS2:
LOG_F(9, "read from MIO:Int_Mask2 register \n"); res = this->int_events2;
break;
case MIO_INT_MASK2:
res = this->int_mask2; res = this->int_mask2;
break; break;
case 0x18: case MIO_INT_LEVELS2:
LOG_F(9, "read from MIO:Int_Clear2 register \n");
res = this->int_clear2;
break;
case 0x1C:
LOG_F(9, "read from MIO:Int_Levels2 register \n");
res = this->int_levels2; res = this->int_levels2;
break; break;
case 0x24: case MIO_INT_EVENTS1:
LOG_F(9, "read from MIO:Int_Mask1 register \n"); res = this->int_events1;
break;
case MIO_INT_MASK1:
res = this->int_mask1; res = this->int_mask1;
break; break;
case 0x28: case MIO_INT_LEVELS1:
LOG_F(9, "read from MIO:Int_Clear1 register \n");
res = this->int_clear1;
break;
case 0x2C:
LOG_F(9, "read from MIO:Int_Levels1 register \n");
res = this->int_levels1; res = this->int_levels1;
break; break;
case 0x34: /* heathrowIDs / HEATHROW_MBCR (Linux): media bay config reg? */ case 0x34: /* heathrowIDs / HEATHROW_MBCR (Linux): media bay config reg? */
@ -239,41 +233,39 @@ uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) {
break; break;
case 0x38: case 0x38:
LOG_F(9, "read from MIO:Feat_Ctrl register \n"); LOG_F(9, "read from MIO:Feat_Ctrl register \n");
res = BYTESWAP_32(this->feat_ctrl); res = this->feat_ctrl;
break; break;
default: default:
LOG_F(WARNING, "read from unknown MIO register at %x \n", offset); LOG_F(WARNING, "read from unknown MIO register at %x \n", offset);
break; break;
} }
return res; return BYTESWAP_32(res);
} }
void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size) { void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size) {
switch (offset & 0xFC) { switch (offset & 0xFC) {
case 0x14: case MIO_INT_MASK2:
LOG_F(9, "write %x to MIO:Int_Mask2 register \n", value); this->int_mask2 |= BYTESWAP_32(value) & ~MACIO_INT_MODE;
this->int_mask2 = value;
break; break;
case 0x18: case MIO_INT_CLEAR2:
LOG_F(9, "write %x to MIO:Int_Clear2 register \n", value); if (value & MACIO_INT_CLR) {
this->int_clear2 = value; this->int_events2 = 0;
} else {
this->int_events2 &= BYTESWAP_32(value);
}
break; break;
case 0x1C: case MIO_INT_MASK1:
LOG_F(9, "write %x to MIO:Int_Levels2 register \n", value); this->int_mask1 = BYTESWAP_32(value);
this->int_levels2 = value; // copy IntMode bit to InterruptMask2 register
this->int_mask2 = (this->int_mask2 & ~MACIO_INT_MODE) | (this->int_mask1 & MACIO_INT_MODE);
break; break;
case 0x24: case MIO_INT_CLEAR1:
LOG_F(9, "write %x to MIO:Int_Mask1 register \n", value); if (value & MACIO_INT_CLR) {
this->int_mask1 = value; this->int_events1 = 0;
break; } else {
case 0x28: this->int_events1 &= BYTESWAP_32(value);
LOG_F(9, "write %x to MIO:Int_Clear1 register \n", value); }
this->int_clear1 = value;
break;
case 0x2C:
LOG_F(9, "write %x to MIO:Int_Levels1 register \n", value);
this->int_levels1 = value;
break; break;
case 0x34: case 0x34:
LOG_F(WARNING, "Attempted to write %x to MIO:ID at %x; Address : %x \n", value, offset, ppc_state.pc); LOG_F(WARNING, "Attempted to write %x to MIO:ID at %x; Address : %x \n", value, offset, ppc_state.pc);
@ -306,6 +298,16 @@ void HeathrowIC::feature_control(const uint32_t value)
uint32_t HeathrowIC::register_dev_int(IntSrc src_id) uint32_t HeathrowIC::register_dev_int(IntSrc src_id)
{ {
switch (src_id) {
case IntSrc::VIA_CUDA:
return 1 << 7;
case IntSrc::SCSI1:
return 1 << 1;
case IntSrc::SWIM3:
return 1 << 8;
default:
ABORT_F("Heathrow: unknown interrupt source %d", src_id);
}
return 0; return 0;
} }
@ -316,6 +318,35 @@ uint32_t HeathrowIC::register_dma_int(IntSrc src_id)
void HeathrowIC::ack_int(uint32_t irq_id, uint8_t irq_line_state) void HeathrowIC::ack_int(uint32_t irq_id, uint8_t irq_line_state)
{ {
if (this->int_mask1 & MACIO_INT_MODE) { // 68k interrupt emulation mode?
if (irq_id > 0x200000) {
irq_id >>= 21;
this->int_events2 |= irq_id; // signal IRQ line change
this->int_events2 &= this->int_mask2;
// update IRQ line state
if (irq_line_state) {
this->int_levels2 |= irq_id;
} else {
this->int_levels2 &= ~irq_id;
}
} else {
irq_id <<= 11;
this->int_events1 |= irq_id; // signal IRQ line change
this->int_events1 &= this->int_mask1;
// update IRQ line state
if (irq_line_state) {
this->int_levels1 |= irq_id;
} else {
this->int_levels1 &= ~irq_id;
}
}
// signal CPU interrupt
if (this->int_events1 || this->int_events2) {
ppc_ext_int();
}
} else {
ABORT_F("Heathrow: native interrupt mode not implemented");
}
} }
void HeathrowIC::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) void HeathrowIC::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state)

View File

@ -1,6 +1,6 @@
/* /*
DingusPPC - The Experimental PowerPC Macintosh emulator DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-21 divingkatae and maximum Copyright (C) 2018-22 divingkatae and maximum
(theweirdo) spatium (theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info) (Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@ -67,6 +67,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes> #include <cinttypes>
#include <memory> #include <memory>
/** Interrupt related constants. */
#define MACIO_INT_CLR 0x80UL // clears bits in the interrupt events registers
#define MACIO_INT_MODE 0x80000000UL // interrupt mode: 0 - native, 1 - 68k-style
/** Offsets to common MacIO interrupt registers. */ /** Offsets to common MacIO interrupt registers. */
enum { enum {
MIO_INT_EVENTS2 = 0x10, MIO_INT_EVENTS2 = 0x10,
@ -164,11 +168,11 @@ protected:
private: private:
uint32_t base_addr = 0; uint32_t base_addr = 0;
uint32_t int_events2 = 0;
uint32_t int_mask2 = 0; uint32_t int_mask2 = 0;
uint32_t int_clear2 = 0;
uint32_t int_levels2 = 0; uint32_t int_levels2 = 0;
uint32_t int_events1 = 0;
uint32_t int_mask1 = 0; uint32_t int_mask1 = 0;
uint32_t int_clear1 = 0;
uint32_t int_levels1 = 0; uint32_t int_levels1 = 0;
uint32_t macio_id = 0xF0700008UL; uint32_t macio_id = 0xF0700008UL;
uint32_t feat_ctrl = 0; // features control register uint32_t feat_ctrl = 0; // features control register