Skip to content

Commit

Permalink
Make irq_id 64 bits.
Browse files Browse the repository at this point in the history
- So that DMA and other interrupts can fit without overlap.
- To simplify conversion to interrupt mask.
- To reduce variables, defines, and code.
  • Loading branch information
joevt authored and dingusdev committed Feb 10, 2025
1 parent 662166d commit 101bb82
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 325 deletions.
2 changes: 1 addition & 1 deletion devices/common/ata/idechannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class MacioIdeChannel : public IdeChannel

// interrupt stuff
InterruptCtrl* int_ctrl = nullptr;
uint32_t irq_id = 0;
uint64_t irq_id = 0;
};

#endif // IDE_CHANNEL_H
4 changes: 2 additions & 2 deletions devices/common/dbdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class DMAChannel : public DmaBidirChannel, public DmaChannel {
void end_pull_data();
void end_push_data();

void register_dma_int(InterruptCtrl* int_ctrl_obj, uint32_t irq_id) {
void register_dma_int(InterruptCtrl* int_ctrl_obj, uint64_t irq_id) {
this->int_ctrl = int_ctrl_obj;
this->irq_id = irq_id;
};
Expand Down Expand Up @@ -163,7 +163,7 @@ class DMAChannel : public DmaBidirChannel, public DmaChannel {

// Interrupt related stuff
InterruptCtrl* int_ctrl = nullptr;
uint32_t irq_id = 0;
uint64_t irq_id = 0;
};

#endif // DB_DMA_H
23 changes: 18 additions & 5 deletions devices/common/hwinterrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
enum IntSrc : uint32_t {
INT_UNKNOWN = 0,
VIA_CUDA,
VIA2,
SCSI_MESH,
SCSI_CURIO,
SWIM3,
ESCC,
SCCA,
SCCB,
ETHERNET,
Expand All @@ -58,6 +60,7 @@ enum IntSrc : uint32_t {
PLANB,
VCI,
PLATINUM,
DMA_ALL,
DMA_SCSI_MESH,
DMA_SCSI_CURIO,
DMA_SWIM3,
Expand All @@ -80,6 +83,16 @@ enum IntSrc : uint32_t {
USB,
PIPPIN_E,
PIPPIN_F,
ZIVA,
PCI_CARDBUS,
MEDIA_BAY,
SLOT_ALL,
SLOT_0,
SLOT_1,
SLOT_2,
SLOT_PDS,
SLOT_VDS,
VBL,
};

/** Base class for interrupt controllers. */
Expand All @@ -89,17 +102,17 @@ class InterruptCtrl {
virtual ~InterruptCtrl() = default;

// register interrupt sources for a device
virtual uint32_t register_dev_int(IntSrc src_id) = 0;
virtual uint32_t register_dma_int(IntSrc src_id) = 0;
virtual uint64_t register_dev_int(IntSrc src_id) = 0;
virtual uint64_t register_dma_int(IntSrc src_id) = 0;

// acknowledge HW interrupt
virtual void ack_int(uint32_t irq_id, uint8_t irq_line_state) = 0;
virtual void ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) = 0;
virtual void ack_int(uint64_t irq_id, uint8_t irq_line_state) = 0;
virtual void ack_dma_int(uint64_t irq_id, uint8_t irq_line_state) = 0;
};

typedef struct {
InterruptCtrl *int_ctrl_obj;
uint32_t irq_id;
uint64_t irq_id;
} IntDetails;

#endif // HW_INTERRUPT_H
2 changes: 1 addition & 1 deletion devices/common/scsi/sc53c94.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ class Sc53C94 : public ScsiDevice, public DmaDevice {

// interrupt related stuff
InterruptCtrl* int_ctrl = nullptr;
uint32_t irq_id = 0;
uint64_t irq_id = 0;
uint8_t irq = 0;

// DMA related stuff
Expand Down
2 changes: 1 addition & 1 deletion devices/common/scsi/scsibusctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class ScsiBusController : public ScsiDevice, public DmaDevice {

// interrupt related stuff
InterruptCtrl* int_ctrl = nullptr;
uint32_t irq_id = 0;
uint64_t irq_id = 0;
uint8_t irq = 0;
uint8_t int_mask = 0;
uint8_t int_stat = 0;
Expand Down
2 changes: 1 addition & 1 deletion devices/common/viacuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class ViaCuda : public HWComponent, public I2CBus {

// VIA interrupt related stuff
InterruptCtrl* int_ctrl;
uint32_t irq_id;
uint64_t irq_id;
uint8_t _via_ifr;
uint8_t _via_ier;
uint8_t old_ifr = 0;
Expand Down
2 changes: 1 addition & 1 deletion devices/floppy/swim3.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class Swim3Ctrl : public HWComponent {

// Interrupt related stuff
InterruptCtrl* int_ctrl = nullptr;
uint32_t irq_id = 0;
uint64_t irq_id = 0;
uint8_t irq = 0;
};

Expand Down
85 changes: 49 additions & 36 deletions devices/ioctrl/amic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ AMIC::AMIC() : MMIODevice()
this->viacuda = dynamic_cast<ViaCuda*>(gMachineObj->get_comp_by_name("ViaCuda"));

// initialize sound HW
this->snd_out_dma = std::unique_ptr<AmicSndOutDma> (new AmicSndOutDma());
this->snd_out_dma->init_interrupts(this, 2 << 8);
this->snd_out_dma = std::unique_ptr<AmicSndOutDma>(new AmicSndOutDma());
this->snd_out_dma->init_interrupts(this, DMA1_INT_SOUND << DMA1_INT_SHIFT);
this->awacs = std::unique_ptr<AwacDevicePdm> (new AwacDevicePdm());
this->awacs->set_dma_out(this->snd_out_dma.get());

Expand Down Expand Up @@ -448,50 +448,63 @@ void AMIC::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
}

// ======================== Interrupt related stuff ==========================
uint32_t AMIC::register_dev_int(IntSrc src_id) {
uint64_t AMIC::register_dev_int(IntSrc src_id) {
switch (src_id) {
case IntSrc::VIA_CUDA:
return CPU_INT_VIA1;
case IntSrc::SCSI_CURIO:
return VIA2_INT_SCSI_IRQ << 8;
case IntSrc::SWIM3:
return VIA2_INT_SWIM3 << 8;
case IntSrc::NMI:
return CPU_INT_NMI;
case IntSrc::VIA_CUDA : return CPU_INT_VIA1 << CPU_INT_SHIFT;
case IntSrc::VIA2 : return CPU_INT_VIA2 << CPU_INT_SHIFT;
case IntSrc::ESCC : return CPU_INT_ESCC << CPU_INT_SHIFT;
case IntSrc::ETHERNET : return CPU_INT_ENET << CPU_INT_SHIFT;
case IntSrc::DMA_ALL : return CPU_INT_ALL_DMA << CPU_INT_SHIFT;
case IntSrc::NMI : return CPU_INT_NMI << CPU_INT_SHIFT;

case IntSrc::DMA_SCSI_CURIO: return VIA2_INT_SCSI_DRQ << VIA2_INT_SHIFT;
case IntSrc::SLOT_ALL : return VIA2_INT_ALL_SLOT << VIA2_INT_SHIFT;
case IntSrc::SCSI_CURIO : return VIA2_INT_SCSI_IRQ << VIA2_INT_SHIFT;
case IntSrc::DAVBUS : return VIA2_INT_SOUND << VIA2_INT_SHIFT;
case IntSrc::SWIM3 : return VIA2_INT_SWIM3 << VIA2_INT_SHIFT;

case IntSrc::SLOT_0 : return SLOT_INT_SLOT_0 << SLOT_INT_SHIFT;
case IntSrc::SLOT_1 : return SLOT_INT_SLOT_1 << SLOT_INT_SHIFT;
case IntSrc::SLOT_2 : return SLOT_INT_SLOT_2 << SLOT_INT_SHIFT;
case IntSrc::SLOT_PDS : return SLOT_INT_SLOT_PDS << SLOT_INT_SHIFT;
case IntSrc::SLOT_VDS : return SLOT_INT_SLOT_VDS << SLOT_INT_SHIFT;
case IntSrc::VBL : return SLOT_INT_VBL << SLOT_INT_SHIFT;

case IntSrc::DMA_DAVBUS_Tx : return DMA1_INT_SOUND << DMA1_INT_SHIFT;
default:
ABORT_F("AMIC: unknown interrupt source %d", src_id);
}
return 0;
}

uint32_t AMIC::register_dma_int(IntSrc src_id) {
uint64_t AMIC::register_dma_int(IntSrc src_id) {
ABORT_F("AMIC: register_dma_int() not implemented");
return 0;
}

void AMIC::ack_int(uint32_t irq_id, uint8_t irq_line_state) {
void AMIC::ack_int(uint64_t irq_id, uint8_t irq_line_state) {
// dispatch cascaded AMIC interrupts from various sources
// irq_id format: 00DDCCBBAA where
// - AA -> CPU interrupts
// - BB -> pseudo VIA2 interrupts
// - CC -> slot interrupts
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 if (irq_id < 0x1000000) {
this->ack_slot_int(irq_id >> 16, irq_line_state);
if (irq_id >> SLOT_INT_SHIFT) {
this->ack_slot_int(irq_id >> SLOT_INT_SHIFT, irq_line_state);
} else if (irq_id >> VIA2_INT_SHIFT) {
this->ack_via2_int(irq_id >> VIA2_INT_SHIFT, irq_line_state);
} else if (irq_id >> CPU_INT_SHIFT) {
this->ack_cpu_int(irq_id >> CPU_INT_SHIFT, irq_line_state);
} else {
ABORT_F("AMIC: unknown interrupt source ID 0x%X", irq_id);
ABORT_F("AMIC: unknown interrupt source ID 0x%llX", irq_id);
}
}

void AMIC::ack_slot_int(uint32_t irq_id, uint8_t irq_line_state) {
void AMIC::ack_slot_int(uint8_t slot_int, uint8_t irq_line_state) {
// CAUTION: reverse logic (0 - true, 1 - false) in the IFR register!
if (irq_line_state) {
this->via2_slot_ifr &= ~irq_id;
this->via2_slot_ifr &= ~slot_int;
} else {
this->via2_slot_ifr |= irq_id;
this->via2_slot_ifr |= slot_int;
}
uint8_t new_irq = !!(~this->via2_slot_ifr & this->via2_slot_ier & 0x7F);
if (new_irq != this->via2_slot_irq) {
Expand All @@ -509,26 +522,26 @@ void AMIC::update_via2_irq() {
}
}

void AMIC::ack_via2_int(uint32_t irq_id, uint8_t irq_line_state) {
void AMIC::ack_via2_int(uint8_t via2_int, uint8_t irq_line_state) {
if (irq_line_state) {
this->via2_ifr |= irq_id;
this->via2_ifr |= via2_int;
} else {
this->via2_ifr &= ~irq_id;
this->via2_ifr &= ~via2_int;
}
this->update_via2_irq();
}

void AMIC::ack_cpu_int(uint32_t irq_id, uint8_t irq_line_state) {
void AMIC::ack_cpu_int(uint8_t cpu_int, uint8_t irq_line_state) {
if (this->int_ctrl & CPU_INT_MODE) { // 68k interrupt emulation mode?
if (irq_line_state) {
this->dev_irq_lines |= irq_id;
this->dev_irq_lines |= cpu_int;
} else {
this->dev_irq_lines &= ~irq_id;
this->dev_irq_lines &= ~cpu_int;
}
if (!(this->int_ctrl & CPU_INT_FLAG)) {
this->int_ctrl |= CPU_INT_FLAG;
ppc_assert_int();
LOG_F(5, "AMIC: CPU INT asserted, source: %d", irq_id);
LOG_F(5, "AMIC: CPU INT asserted, source: 0x%02x", cpu_int);
} else {
LOG_F(5, "AMIC: CPU INT already latched");
}
Expand All @@ -538,15 +551,15 @@ void AMIC::ack_cpu_int(uint32_t irq_id, uint8_t irq_line_state) {
}
}

void AMIC::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) {
if (irq_id >= 0x100) { // DMA Interrupt Flags 1
irq_id = (irq_id >> 8) & 0xFFU;
void AMIC::ack_dma_int(uint64_t irq_id, uint8_t irq_line_state) {
if (irq_id >> DMA1_INT_SHIFT) { // DMA Interrupt Flags 1
irq_id = (irq_id >> DMA1_INT_SHIFT) & 0xFFU;
if (irq_line_state)
this->dma_ifr1 |= irq_id;
else
this->dma_ifr1 &= ~irq_id;
} else { // DMA Interrupt Flags 0
irq_id &= 0xFFU;
} else if (irq_id >> DMA0_INT_SHIFT) { // DMA Interrupt Flags 0
irq_id = (irq_id >> DMA0_INT_SHIFT) & 0xFFU;
if (irq_line_state)
this->dma_ifr0 |= irq_id;
else
Expand Down Expand Up @@ -588,7 +601,7 @@ void AmicSndOutDma::update_irq() {
if (new_level != this->irq_level) {
this->irq_level = new_level;
TimerManager::get_instance()->add_immediate_timer([this] {
this->int_ctrl->ack_dma_int(this->irq_id, this->irq_level);
this->int_ctrl->ack_dma_int(this->snd_dma_irq_id, this->irq_level);
});
}
}
Expand Down
42 changes: 26 additions & 16 deletions devices/ioctrl/amic.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ namespace Swim3 { class Swim3Ctrl; }
/** Interrupt related constants. */

/** CPU interrupt register bits. */
enum : uint8_t {
enum : uint64_t {
CPU_INT_SHIFT = 0,
CPU_INT_VIA1 = 1 << 0, // (R) VIA1 interrupts
CPU_INT_VIA2 = 1 << 1, // (R) pseudo VIA2 interrupts
CPU_INT_ESCC = 1 << 2, // (R) ESCC interrupt
Expand All @@ -56,7 +57,8 @@ enum : uint8_t {
};

/** Pseudo VIA2 interrupt flag/enable register bits. */
enum : uint8_t {
enum : uint64_t {
VIA2_INT_SHIFT = 8,
VIA2_INT_SCSI_DRQ = 1 << 0, // (R) SCSI DRQ interrupt
VIA2_INT_ALL_SLOT = 1 << 1, // (R) all slot interrupts are signalled here
VIA2_INT_SCSI_IRQ = 1 << 3, // (R) SCSI IRQ interrupt
Expand All @@ -66,7 +68,8 @@ enum : uint8_t {
};

/** Slot interrupt flag/enable register bits. */
enum : uint8_t {
enum : uint64_t {
SLOT_INT_SHIFT = 16,
SLOT_INT_SLOT_0 = 1 << 2, // (R) ColdFusion Nubus slot 0 interrupt
SLOT_INT_SLOT_1 = 1 << 3, // (R) ColdFusion Nubus slot 1 interrupt
SLOT_INT_SLOT_2 = 1 << 4, // (R) ColdFusion Nubus slot 2 interrupt
Expand All @@ -75,6 +78,13 @@ enum : uint8_t {
SLOT_INT_VBL = 1 << 6, // (R) built-in video VBL interrupt
};

/** DMA interrupt bits. */
enum : uint64_t {
DMA0_INT_SHIFT = 24,
DMA1_INT_SHIFT = 32,
DMA1_INT_SOUND = 1 << 1,
};

/** AMIC sound buffers are located at fixed offsets from DMA base. */
#define AMIC_SND_BUF0_OFFS 0x10000
#define AMIC_SND_BUF1_OFFS 0x12000
Expand Down Expand Up @@ -104,9 +114,9 @@ class AmicSndOutDma : public DmaOutChannel {
DmaPullResult pull_data(uint32_t req_len, uint32_t *avail_len,
uint8_t **p_data);

void init_interrupts(InterruptCtrl *int_ctrl, uint32_t irq_id) {
void init_interrupts(InterruptCtrl *int_ctrl, uint64_t irq_id) {
this->int_ctrl = int_ctrl;
this->irq_id = irq_id;
this->snd_dma_irq_id = irq_id;
};

private:
Expand All @@ -120,7 +130,7 @@ class AmicSndOutDma : public DmaOutChannel {
uint32_t cur_buf_pos;

InterruptCtrl *int_ctrl = nullptr;
uint32_t irq_id = 0;
uint64_t snd_dma_irq_id = 0;
uint8_t irq_level = 0;
};

Expand Down Expand Up @@ -288,22 +298,22 @@ class AMIC : public MMIODevice, public InterruptCtrl {
}

// HWComponent methods
int device_postinit();
int device_postinit() override;

/* MMIODevice methods */
uint32_t read(uint32_t rgn_start, uint32_t offset, int size);
void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size);
uint32_t read(uint32_t rgn_start, uint32_t offset, int size) override;
void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size) override;

// InterruptCtrl methods
uint32_t register_dev_int(IntSrc src_id);
uint32_t register_dma_int(IntSrc src_id);
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);
uint64_t register_dev_int(IntSrc src_id) override;
uint64_t register_dma_int(IntSrc src_id) override;
void ack_int(uint64_t irq_id, uint8_t irq_line_state) override;
void ack_dma_int(uint64_t irq_id, uint8_t irq_line_state) override;

protected:
void ack_slot_int(uint32_t irq_id, uint8_t irq_line_state);
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);
void ack_slot_int(uint8_t slot_int, uint8_t irq_line_state);
void ack_via2_int(uint8_t via2_int, uint8_t irq_line_state);
void ack_cpu_int(uint8_t cpu_int, uint8_t irq_line_state);
void update_via2_irq();

private:
Expand Down
Loading

0 comments on commit 101bb82

Please sign in to comment.