AMIC: process VIA2 interrupts.

This commit is contained in:
Maxim Poliakovski 2022-02-06 01:47:54 +01:00
parent 7c53620a40
commit 298135fd7a
3 changed files with 62 additions and 10 deletions

View File

@ -27,10 +27,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** Enumerator for various interrupt sources. */
enum IntSrc : int {
VIA_CUDA = 1,
VIA2 = 2,
SCC = 3,
ETHERNET = 4,
NMI = 5,
SCSI1 = 2,
SWIM3 = 3,
SCC = 4,
ETHERNET = 5,
NMI = 6,
};
/** Base class for interrupt controllers. */
@ -48,4 +49,4 @@ public:
virtual void ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) = 0;
};
#endif // HW_INTERRUPT_H
#endif // HW_INTERRUPT_H

View File

@ -52,6 +52,8 @@ AMIC::AMIC() : MMIODevice()
// register I/O devices
this->scsi = std::unique_ptr<Sc53C94> (new Sc53C94());
gMachineObj->add_subdevice("Curio_SCSI0", this->scsi.get());
this->escc = std::unique_ptr<EsccController> (new EsccController());
this->mace = std::unique_ptr<MaceController> (new MaceController(MACE_ID));
this->viacuda = std::unique_ptr<ViaCuda> (new ViaCuda());
@ -135,6 +137,12 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
switch(offset) {
case AMICReg::Ariel_Config:
return this->def_vid->get_vdac_config();
case AMICReg::VIA2_IFR:
case AMICReg::VIA2_IFR_RBV:
return this->via2_ifr;
case AMICReg::VIA2_IER:
case AMICReg::VIA2_IER_RBV:
return this->via2_ier;
case AMICReg::Video_Mode:
return this->def_vid->get_video_mode();
case AMICReg::Monitor_Id:
@ -228,7 +236,11 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
LOG_F(INFO, "AMIC VIA2 Slot Interrupt Enable Register updated, val=%x", value);
break;
case AMICReg::VIA2_IER:
LOG_F(INFO, "AMIC VIA2 Interrupt Enable Register updated, val=%x", value);
if (value & 0x80) {
this->via2_ier |= value & 0x7F;
} else {
this->via2_ier &= ~value;
}
break;
case AMICReg::Ariel_Clut_Index:
this->def_vid->set_clut_index(value);
@ -313,6 +325,8 @@ uint32_t AMIC::register_dev_int(IntSrc src_id) {
switch (src_id) {
case IntSrc::VIA_CUDA:
return 1;
case IntSrc::SCSI1:
return 0x800;
default:
ABORT_F("AMIC: unknown interrupt source %d", src_id);
}
@ -325,6 +339,31 @@ uint32_t AMIC::register_dma_int(IntSrc src_id) {
}
void AMIC::ack_int(uint32_t irq_id, uint8_t irq_line_state) {
// dispatch AMIC interrupts from various sources
if (irq_id < 0x100) {
this->ack_cpu_int(irq_id, irq_line_state);
} else if (irq_id < 0x10000) {
this->ack_via2_int(irq_id >> 8, irq_line_state);
} else {
ABORT_F("AMIC: unknown interrupt source ID 0x%X", irq_id);
}
}
void AMIC::ack_via2_int(uint32_t irq_id, uint8_t irq_line_state) {
if (irq_line_state) {
this->via2_ifr |= irq_id;
} else {
this->via2_ifr &= ~irq_id;
}
uint8_t new_irq = !!(this->via2_ifr & this->via2_ier & 0x7F);
this->via2_ifr = (this->via2_ifr & 0x7F) | (new_irq << 7);
if (new_irq != this->via2_irq) {
this->via2_irq = new_irq;
this->ack_cpu_int(2, new_irq);
}
}
void AMIC::ack_cpu_int(uint32_t irq_id, uint8_t irq_line_state) {
if (this->int_ctrl & AMIC_INT_MODE) { // 68k interrupt emulation mode?
this->int_ctrl |= 0x80; // set CPU interrupt bit
if (irq_line_state) {

View File

@ -101,15 +101,18 @@ enum AMICReg : uint32_t {
Snd_In_DMA = 0x14014, // sound input DMA status/control register
Snd_Out_DMA = 0x14018, // sound output DMA status/control register
// VIA2 registers
VIA2_Slot_IER = 0x26012,
VIA2_IER = 0x26013,
// Video DAC (Ariel II) control registers
Ariel_Clut_Index = 0x24000,
Ariel_Clut_Color = 0x24001,
Ariel_Config = 0x24002,
// VIA2 registers
VIA2_IFR = 0x26003,
VIA2_Slot_IER = 0x26012,
VIA2_IER = 0x26013,
VIA2_IFR_RBV = 0x27A03, // RBV-compatible mirror for the VIA2_IFR
VIA2_IER_RBV = 0x27C13, // RBV-compatible mirror for the VIA2_IER
// Video control registers
Video_Mode = 0x28000,
Pixel_Depth = 0x28001,
@ -155,6 +158,10 @@ public:
void ack_int(uint32_t irq_id, uint8_t irq_line_state);
void ack_dma_int(uint32_t irq_id, uint8_t irq_line_state);
protected:
void ack_via2_int(uint32_t irq_id, uint8_t irq_line_state);
void ack_cpu_int(uint32_t irq_id, uint8_t irq_line_state);
private:
uint8_t imm_snd_regs[4]; // temporary storage for sound control registers
@ -167,6 +174,11 @@ private:
uint8_t int_ctrl = 0;
uint8_t dev_irq_lines = 0; // state of the IRQ lines
// pseudo VIA2 state
uint8_t via2_ier = 0;
uint8_t via2_ifr = 0;
uint8_t via2_irq = 0;
uint32_t pseudo_vbl_tid; // ID for the pseudo-VBL timer
// AMIC subdevices instances