Started adding AMIC interrupt support

This commit is contained in:
dingusdev 2021-12-12 14:50:11 -07:00
parent 3db6d07060
commit 9291a093d5
4 changed files with 106 additions and 11 deletions

View File

@ -68,9 +68,75 @@ bool AMIC::supports_type(HWCompType type) {
return false;
}
}
void AMIC::process_interrupt(uint32_t cookie) {
bool confirm_interrupt = false;
uint32_t bit_field = 0;
uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
{
switch (cookie) {
case DEV_ID::PDM_HZTICK:
case DEV_ID::VIA_CUDA:
case DEV_ID::PDM_TIMER2:
case DEV_ID::PDM_TIMER1:
bit_field = (1 << VIA1_Interrupt);
confirm_interrupt = true;
break;
case DEV_ID::NUBUS_SLOT3:
case DEV_ID::NUBUS_SLOT0:
case DEV_ID::NUBUS_SLOT1:
case DEV_ID::NUBUS_SLOT2:
case DEV_ID::SCSI0:
case DEV_ID::SWIM3:
case DEV_ID::SCSI1:
bit_field = (1 << VIA2_Interrupt);
confirm_interrupt = true;
break;
case DEV_ID::SCC_B:
case DEV_ID::SCC_A:
bit_field = (1 << SCC_Interrupt);
confirm_interrupt = true;
break;
case DEV_ID::BMAC:
bit_field = (1 << Eth_Interrupt);
confirm_interrupt = true;
break;
case DEV_ID::SCSI_DMA:
case DEV_ID::Swim3_DMA:
case DEV_ID::IDE0_DMA:
case DEV_ID::IDE1_DMA:
case DEV_ID::SCC_A_DMA_OUT:
case DEV_ID::SCC_A_DMA_IN:
case DEV_ID::SCC_B_DMA_OUT:
case DEV_ID::SCC_B_DMA_IN:
case DEV_ID::SOUND_DMA_OUT:
case DEV_ID::SOUND_DMA_IN:
case DEV_ID::PERCH_DMA:
bit_field = (1 << DMA_Interrupt);
confirm_interrupt = true;
break;
case DEV_ID::NMI:
bit_field = (1 << NMI_Interrupt);
confirm_interrupt = true;
break;
}
if (confirm_interrupt)
ack_interrupt(bit_field);
}
uint32_t AMIC::ack_interrupt(uint32_t device_bits) {
bool confirm_interrupt = false;
bool ack_bit = this->int_mask1 & 0x80;
if (device_bits & int_mask1)
confirm_interrupt = true;
if (confirm_interrupt && ack_bit)
ack_cpu_interrupt();
return 0;
}
uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size) {
uint32_t phase_val;
// subdevices registers
@ -113,6 +179,8 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
return 0xFFU; // this value allows the machine to boot normally
case AMICReg::SCSI_DMA_Ctrl:
return this->scsi_dma_cs;
case AMICReg::Int_Ctrl:
return this->int_mask1;
default:
LOG_F(WARNING, "Unknown AMIC register read, offset=%x", offset);
}
@ -152,6 +220,7 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
((this->imm_snd_regs[1] & 0xF) << 8) | this->imm_snd_regs[2]
);
}
this->process_interrupt(DEV_ID::DAVBUS);
return;
case AMICReg::Snd_Buf_Size_Hi:
case AMICReg::Snd_Buf_Size_Lo:
@ -160,6 +229,7 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
((value & 0xFF) << (8 * ((offset & 1) ^1)));
this->snd_buf_size &= ~3; // sound buffer size is always a multiple of 4
LOG_F(9, "AMIC: Sound buffer size set to 0x%X", this->snd_buf_size);
this->process_interrupt(DEV_ID::DAVBUS);
return;
case AMICReg::Snd_Out_Ctrl:
LOG_F(9, "AMIC Sound Out Ctrl updated, val=%x", value);
@ -183,6 +253,7 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
return;
case AMICReg::Snd_Out_DMA:
this->snd_out_dma->write_dma_out_ctrl(value);
this->process_interrupt(DEV_ID::SOUND_DMA_OUT);
return;
}
}
@ -199,6 +270,7 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
break;
case AMICReg::Int_Ctrl:
LOG_F(INFO, "AMIC Interrupt Control Register set to %X", value);
this->int_mask1 = value;
break;
case AMICReg::DMA_Base_Addr_0:
case AMICReg::DMA_Base_Addr_1:
@ -208,6 +280,7 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
this->dma_base = (this->dma_base & ~mask) |
((value & 0xFF) << (8 * (3 - (offset & 3))));
LOG_F(9, "AMIC: DMA base address set to 0x%X", this->dma_base);
this->process_interrupt(DEV_ID::PERCH_DMA);
break;
case AMICReg::Enet_DMA_Xmt_Ctrl:
LOG_F(INFO, "AMIC Ethernet Transmit DMA Ctrl updated, val=%x", value);

View File

@ -121,13 +121,26 @@ enum AMICReg : uint32_t {
SCC_DMA_Rcv_B_Ctrl = 0x320B8,
};
/** Apple Memory-mapped I/O controller device. */
enum AMICIntReg : uint32_t {
VIA1_Interrupt = 0,
VIA2_Interrupt = 1,
SCC_Interrupt = 2,
Eth_Interrupt = 3,
DMA_Interrupt = 4,
NMI_Interrupt = 5,
INT_Mode = 6,
ACK_Bit = 7,
};
/** Apple Memory-mapped I/O controller device. */
class AMIC : public MMIODevice, public InterruptCtrl {
public:
AMIC();
~AMIC() = default;
bool supports_type(HWCompType type);
void process_interrupt(uint32_t cookie);
uint32_t ack_interrupt(uint32_t device_bits);
/* MMIODevice methods */
uint32_t read(uint32_t reg_start, uint32_t offset, int size);

View File

@ -70,8 +70,8 @@ void HeathrowIC::process_interrupt(uint32_t cookie) {
uint32_t bit_field = 0;
switch (cookie) {
case DEV_ID::DAVBUS_DMA_OUT:
bit_field = (1 << DEV_ID::DAVBUS_DMA_OUT);
case DEV_ID::SOUND_DMA_OUT:
bit_field = (1 << DEV_ID::SOUND_DMA_OUT);
break;
case DEV_ID::SCSI0:
bit_field = (1 << DEV_ID::SCSI0);
@ -124,7 +124,7 @@ uint32_t HeathrowIC::dma_read(uint32_t offset, int size) {
switch (offset >> 8) {
case 8:
res = this->snd_out_dma->reg_read(offset & 0xFF, size);
this->ack_interrupt(DEV_ID::DAVBUS_DMA_OUT);
this->ack_interrupt(DEV_ID::SOUND_DMA_OUT);
break;
default:
LOG_F(WARNING, "Unsupported DMA channel read, offset=0x%X", offset);

View File

@ -35,8 +35,8 @@ enum DEV_ID {
SCC_A_DMA_IN = 5,
SCC_B_DMA_OUT = 6,
SCC_B_DMA_IN = 7,
DAVBUS_DMA_OUT = 8,
DAVBUS_DMA_IN = 9,
SOUND_DMA_OUT = 8,
SOUND_DMA_IN = 9,
VIDEO_OUT = 10,
VIDEO_IN = 11,
SCSI0 = 12,
@ -50,9 +50,18 @@ enum DEV_ID {
NMI = 20,
PERCH_DMA = 21,
PERCH = 22,
BMAC_DMA_OUT = 0,
BMAC_DMA_IN = 1,
BMAC = 10,
BMAC_DMA_OUT = 23,
BMAC_DMA_IN = 24,
BMAC = 25,
PDM_HZTICK = 26,
PDM_TIMER2 = 27,
PDM_TIMER1 = 28,
SCSI1 = 29,
NUBUS_SLOT3 = 30,
NUBUS_SLOT0 = 31,
NUBUS_SLOT1 = 32,
NUBUS_SLOT2 = 33,
PDM_VBL = 34,
};
enum REG_ID {