diff --git a/devices/common/hwinterrupt.h b/devices/common/hwinterrupt.h
index d897f42..b451af7 100644
--- a/devices/common/hwinterrupt.h
+++ b/devices/common/hwinterrupt.h
@@ -27,10 +27,11 @@ along with this program. If not, see .
/** 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
\ No newline at end of file
+#endif // HW_INTERRUPT_H
diff --git a/devices/ioctrl/amic.cpp b/devices/ioctrl/amic.cpp
index d998e0e..d1e7f5c 100644
--- a/devices/ioctrl/amic.cpp
+++ b/devices/ioctrl/amic.cpp
@@ -52,6 +52,8 @@ AMIC::AMIC() : MMIODevice()
// register I/O devices
this->scsi = std::unique_ptr (new Sc53C94());
+ gMachineObj->add_subdevice("Curio_SCSI0", this->scsi.get());
+
this->escc = std::unique_ptr (new EsccController());
this->mace = std::unique_ptr (new MaceController(MACE_ID));
this->viacuda = std::unique_ptr (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) {
diff --git a/devices/ioctrl/amic.h b/devices/ioctrl/amic.h
index c4eee6f..79c55b1 100644
--- a/devices/ioctrl/amic.h
+++ b/devices/ioctrl/amic.h
@@ -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