mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-08-05 02:24:41 +00:00
Make irq_id 64 bits.
- So that DMA and other interrupts can fit without overlap. - To simplify conversion to interrupt mask. - To reduce variables, defines, and code.
This commit is contained in:
@@ -95,7 +95,7 @@ private:
|
||||
|
||||
// interrupt stuff
|
||||
InterruptCtrl* int_ctrl = nullptr;
|
||||
uint32_t irq_id = 0;
|
||||
uint64_t irq_id = 0;
|
||||
};
|
||||
|
||||
#endif // IDE_CHANNEL_H
|
||||
|
@@ -123,7 +123,7 @@ public:
|
||||
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;
|
||||
};
|
||||
@@ -163,7 +163,7 @@ private:
|
||||
|
||||
// Interrupt related stuff
|
||||
InterruptCtrl* int_ctrl = nullptr;
|
||||
uint32_t irq_id = 0;
|
||||
uint64_t irq_id = 0;
|
||||
};
|
||||
|
||||
#endif // DB_DMA_H
|
||||
|
@@ -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,
|
||||
@@ -58,6 +60,7 @@ enum IntSrc : uint32_t {
|
||||
PLANB,
|
||||
VCI,
|
||||
PLATINUM,
|
||||
DMA_ALL,
|
||||
DMA_SCSI_MESH,
|
||||
DMA_SCSI_CURIO,
|
||||
DMA_SWIM3,
|
||||
@@ -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. */
|
||||
@@ -89,17 +102,17 @@ public:
|
||||
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
|
||||
|
@@ -290,7 +290,7 @@ private:
|
||||
|
||||
// interrupt related stuff
|
||||
InterruptCtrl* int_ctrl = nullptr;
|
||||
uint32_t irq_id = 0;
|
||||
uint64_t irq_id = 0;
|
||||
uint8_t irq = 0;
|
||||
|
||||
// DMA related stuff
|
||||
|
@@ -113,7 +113,7 @@ protected:
|
||||
|
||||
// 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;
|
||||
|
@@ -207,7 +207,7 @@ private:
|
||||
|
||||
// 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;
|
||||
|
@@ -147,7 +147,7 @@ private:
|
||||
|
||||
// Interrupt related stuff
|
||||
InterruptCtrl* int_ctrl = nullptr;
|
||||
uint32_t irq_id = 0;
|
||||
uint64_t irq_id = 0;
|
||||
uint8_t irq = 0;
|
||||
};
|
||||
|
||||
|
@@ -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());
|
||||
|
||||
@@ -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) {
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -104,9 +114,9 @@ public:
|
||||
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:
|
||||
@@ -120,7 +130,7 @@ private:
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -288,22 +298,22 @@ public:
|
||||
}
|
||||
|
||||
// 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:
|
||||
|
@@ -434,7 +434,7 @@ void GrandCentral::attach_iodevice(int dev_num, IobusDevice* dev_obj)
|
||||
|
||||
#define INT_TO_IRQ_ID(intx) (1 << intx)
|
||||
|
||||
uint32_t GrandCentral::register_dev_int(IntSrc src_id) {
|
||||
uint64_t GrandCentral::register_dev_int(IntSrc src_id) {
|
||||
switch (src_id) {
|
||||
case IntSrc::SCSI_CURIO : return INT_TO_IRQ_ID(0x0C);
|
||||
case IntSrc::SCSI_MESH : return INT_TO_IRQ_ID(0x0D);
|
||||
@@ -473,61 +473,60 @@ uint32_t GrandCentral::register_dev_int(IntSrc src_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DMA_INT_TO_IRQ_ID(intx) (1 << intx)
|
||||
|
||||
uint32_t GrandCentral::register_dma_int(IntSrc src_id) {
|
||||
uint64_t GrandCentral::register_dma_int(IntSrc src_id) {
|
||||
switch (src_id) {
|
||||
case IntSrc::DMA_SCSI_CURIO : return DMA_INT_TO_IRQ_ID(0x00);
|
||||
case IntSrc::DMA_SWIM3 : return DMA_INT_TO_IRQ_ID(0x01);
|
||||
case IntSrc::DMA_ETHERNET_Tx : return DMA_INT_TO_IRQ_ID(0x02);
|
||||
case IntSrc::DMA_ETHERNET_Rx : return DMA_INT_TO_IRQ_ID(0x03);
|
||||
case IntSrc::DMA_SCCA_Tx : return DMA_INT_TO_IRQ_ID(0x04);
|
||||
case IntSrc::DMA_SCCA_Rx : return DMA_INT_TO_IRQ_ID(0x05);
|
||||
case IntSrc::DMA_SCCB_Tx : return DMA_INT_TO_IRQ_ID(0x06);
|
||||
case IntSrc::DMA_SCCB_Rx : return DMA_INT_TO_IRQ_ID(0x07);
|
||||
case IntSrc::DMA_DAVBUS_Tx : return DMA_INT_TO_IRQ_ID(0x08);
|
||||
case IntSrc::DMA_DAVBUS_Rx : return DMA_INT_TO_IRQ_ID(0x09);
|
||||
case IntSrc::DMA_SCSI_MESH : return DMA_INT_TO_IRQ_ID(0x0A);
|
||||
case IntSrc::DMA_SCSI_CURIO : return INT_TO_IRQ_ID(0x00);
|
||||
case IntSrc::DMA_SWIM3 : return INT_TO_IRQ_ID(0x01);
|
||||
case IntSrc::DMA_ETHERNET_Tx: return INT_TO_IRQ_ID(0x02);
|
||||
case IntSrc::DMA_ETHERNET_Rx: return INT_TO_IRQ_ID(0x03);
|
||||
case IntSrc::DMA_SCCA_Tx : return INT_TO_IRQ_ID(0x04);
|
||||
case IntSrc::DMA_SCCA_Rx : return INT_TO_IRQ_ID(0x05);
|
||||
case IntSrc::DMA_SCCB_Tx : return INT_TO_IRQ_ID(0x06);
|
||||
case IntSrc::DMA_SCCB_Rx : return INT_TO_IRQ_ID(0x07);
|
||||
case IntSrc::DMA_DAVBUS_Tx : return INT_TO_IRQ_ID(0x08);
|
||||
case IntSrc::DMA_DAVBUS_Rx : return INT_TO_IRQ_ID(0x09);
|
||||
case IntSrc::DMA_SCSI_MESH : return INT_TO_IRQ_ID(0x0A);
|
||||
default:
|
||||
ABORT_F("%s: unknown DMA interrupt source %d", this->name.c_str(), src_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GrandCentral::ack_int_common(uint32_t irq_id, uint8_t irq_line_state) {
|
||||
void GrandCentral::ack_int_common(uint64_t irq_id, uint8_t irq_line_state) {
|
||||
// native mode: set IRQ bits in int_events on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events on all transitions
|
||||
|
||||
if ((this->int_mask & MACIO_INT_MODE) ||
|
||||
(irq_line_state && !(this->int_levels & irq_id))) {
|
||||
this->int_events |= irq_id;
|
||||
this->int_events |= (uint32_t)irq_id;
|
||||
} else {
|
||||
this->int_events &= ~irq_id;
|
||||
this->int_events &= ~(uint32_t)irq_id;
|
||||
}
|
||||
|
||||
// update IRQ line state
|
||||
if (irq_line_state) {
|
||||
this->int_levels |= irq_id;
|
||||
this->int_levels |= (uint32_t)irq_id;
|
||||
} else {
|
||||
this->int_levels &= ~irq_id;
|
||||
this->int_levels &= ~(uint32_t)irq_id;
|
||||
}
|
||||
|
||||
this->signal_cpu_int(irq_id);
|
||||
}
|
||||
|
||||
void GrandCentral::ack_int(uint32_t irq_id, uint8_t irq_line_state) {
|
||||
void GrandCentral::ack_int(uint64_t irq_id, uint8_t irq_line_state) {
|
||||
this->ack_int_common(irq_id, irq_line_state);
|
||||
}
|
||||
|
||||
void GrandCentral::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) {
|
||||
void GrandCentral::ack_dma_int(uint64_t irq_id, uint8_t irq_line_state) {
|
||||
this->ack_int_common(irq_id, irq_line_state);
|
||||
}
|
||||
|
||||
void GrandCentral::signal_cpu_int(uint32_t irq_id) {
|
||||
void GrandCentral::signal_cpu_int(uint64_t irq_id) {
|
||||
if (this->int_events & this->int_mask) {
|
||||
if (!this->cpu_int_latch) {
|
||||
this->cpu_int_latch = true;
|
||||
ppc_assert_int();
|
||||
LOG_F(5, "%s: CPU INT asserted, source: %d", this->name.c_str(), irq_id);
|
||||
LOG_F(5, "%s: CPU INT asserted, source: 0x%08llx", this->name.c_str(), irq_id);
|
||||
} else {
|
||||
LOG_F(5, "%s: CPU INT already latched", this->name.c_str());
|
||||
}
|
||||
|
@@ -299,22 +299,22 @@ uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) {
|
||||
|
||||
switch (offset & 0xFC) {
|
||||
case MIO_INT_EVENTS2:
|
||||
value = this->int_events2;
|
||||
value = this->int_events >> 32;
|
||||
break;
|
||||
case MIO_INT_MASK2:
|
||||
value = this->int_mask2;
|
||||
value = this->int_mask >> 32;
|
||||
break;
|
||||
case MIO_INT_LEVELS2:
|
||||
value = this->int_levels2;
|
||||
value = this->int_levels >> 32;
|
||||
break;
|
||||
case MIO_INT_EVENTS1:
|
||||
value = this->int_events1;
|
||||
value = uint32_t(this->int_events);
|
||||
break;
|
||||
case MIO_INT_MASK1:
|
||||
value = this->int_mask1;
|
||||
value = uint32_t(this->int_mask);
|
||||
break;
|
||||
case MIO_INT_LEVELS1:
|
||||
value = this->int_levels1;
|
||||
value = uint32_t(int_levels);
|
||||
break;
|
||||
case MIO_INT_CLEAR1:
|
||||
case MIO_INT_CLEAR2:
|
||||
@@ -343,25 +343,24 @@ uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) {
|
||||
void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size) {
|
||||
switch (offset & 0xFC) {
|
||||
case MIO_INT_MASK2:
|
||||
this->int_mask2 |= BYTESWAP_32(value) & ~MACIO_INT_MODE;
|
||||
this->int_mask |= uint64_t(BYTESWAP_32(value) & ~MACIO_INT_MODE) << 32;
|
||||
this->signal_cpu_int();
|
||||
break;
|
||||
case MIO_INT_CLEAR2:
|
||||
this->int_events2 &= ~(BYTESWAP_32(value) & 0x7FFFFFFFUL);
|
||||
this->int_events &= ~(uint64_t(BYTESWAP_32(value) & 0x7FFFFFFFUL) << 32);
|
||||
clear_cpu_int();
|
||||
break;
|
||||
case MIO_INT_MASK1:
|
||||
this->int_mask1 = BYTESWAP_32(value);
|
||||
this->int_mask = (this->int_mask & 0x7FFFFFFF00000000ULL) | BYTESWAP_32(value);
|
||||
// copy IntMode bit to InterruptMask2 register
|
||||
this->int_mask2 = (this->int_mask2 & ~MACIO_INT_MODE) | (this->int_mask1 & MACIO_INT_MODE);
|
||||
this->int_mask |= uint64_t(this->int_mask & MACIO_INT_MODE) << 32;
|
||||
this->signal_cpu_int();
|
||||
break;
|
||||
case MIO_INT_CLEAR1:
|
||||
if ((this->int_mask1 & MACIO_INT_MODE) && (value & MACIO_INT_CLR)) {
|
||||
this->int_events1 = 0;
|
||||
this->int_events2 = 0;
|
||||
if ((this->int_mask & MACIO_INT_MODE) && (value & MACIO_INT_CLR)) {
|
||||
this->int_events = 0;
|
||||
} else {
|
||||
this->int_events1 &= ~(BYTESWAP_32(value) & 0x7FFFFFFFUL);
|
||||
this->int_events &= ~uint64_t(BYTESWAP_32(value) & 0x7FFFFFFFUL);
|
||||
}
|
||||
clear_cpu_int();
|
||||
break;
|
||||
@@ -381,7 +380,7 @@ void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size) {
|
||||
}
|
||||
}
|
||||
|
||||
void HeathrowIC::feature_control(const uint32_t value)
|
||||
void HeathrowIC::feature_control(uint32_t value)
|
||||
{
|
||||
LOG_F(9, "write %x to MIO:Feat_Ctrl register", value);
|
||||
|
||||
@@ -394,22 +393,9 @@ void HeathrowIC::feature_control(const uint32_t value)
|
||||
}
|
||||
}
|
||||
|
||||
#define FIRST_INT1_BIT 12 // The first ten are DMA, the next 2 appear to be unused.
|
||||
// We'll map 1:1 the INT1 bits 31..12 (0x1F..0x0C) as IRQ_ID bits.
|
||||
#define FIRST_INT2_BIT 2 // Skip the first two which are Ethernet DMA.
|
||||
// We'll map INT2 bits 13..2 (interrupts 45..34 or 0x2D..0x22) as IRQ_ID bits 11..0.
|
||||
#define FIRST_INT1_IRQ_ID_BIT 12 // Same as INT1_BIT so there won't be any shifting required.
|
||||
#define FIRST_INT2_IRQ_ID_BIT 0
|
||||
#define INT_TO_IRQ_ID(intx) (1ULL << intx)
|
||||
|
||||
#define INT1_TO_IRQ_ID(int1) (1 << (int1 - FIRST_INT1_BIT + FIRST_INT1_IRQ_ID_BIT))
|
||||
#define INT2_TO_IRQ_ID(int2) (1 << (int2 - FIRST_INT2_BIT + FIRST_INT2_IRQ_ID_BIT - 32))
|
||||
#define INT_TO_IRQ_ID(intx) (intx < 32 ? INT1_TO_IRQ_ID(intx) : INT2_TO_IRQ_ID(intx))
|
||||
|
||||
#define IS_INT1(irq_id) (irq_id >= 1 << FIRST_INT1_IRQ_ID_BIT)
|
||||
#define IRQ_ID_TO_INT1_MASK(irq_id) (irq_id <<= (FIRST_INT1_BIT - FIRST_INT1_IRQ_ID_BIT))
|
||||
#define IRQ_ID_TO_INT2_MASK(irq_id) (irq_id <<= (FIRST_INT2_BIT - FIRST_INT2_IRQ_ID_BIT))
|
||||
|
||||
uint32_t HeathrowIC::register_dev_int(IntSrc src_id)
|
||||
uint64_t HeathrowIC::register_dev_int(IntSrc src_id)
|
||||
{
|
||||
switch (src_id) {
|
||||
case IntSrc::SCSI_MESH : return INT_TO_IRQ_ID(0x0C);
|
||||
@@ -446,193 +432,65 @@ uint32_t HeathrowIC::register_dev_int(IntSrc src_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FIRST_DMA_INT1_BIT 0 // bit 0 is SCSI DMA
|
||||
#define FIRST_DMA_INT2_BIT 0 // bit 0 is Ethernet DMA Tx
|
||||
#define FIRST_DMA_INT1_IRQ_ID_BIT 0
|
||||
#define FIRST_DMA_INT2_IRQ_ID_BIT 16 // There's only 10 INT1 DMA bits but we'll put INT2 DMA bits in the upper 16 bits
|
||||
|
||||
#define DMA_INT1_TO_IRQ_ID(int1) (1 << (int1 - FIRST_DMA_INT1_BIT + FIRST_DMA_INT1_IRQ_ID_BIT))
|
||||
#define DMA_INT2_TO_IRQ_ID(int2) (1 << (int2 - FIRST_DMA_INT2_BIT + FIRST_DMA_INT2_IRQ_ID_BIT - 32))
|
||||
#define DMA_INT_TO_IRQ_ID(intx) (intx < 32 ? DMA_INT1_TO_IRQ_ID(intx) : DMA_INT2_TO_IRQ_ID(intx))
|
||||
|
||||
#define IS_DMA_INT1(irq_id) (irq_id < 1 << FIRST_DMA_INT2_IRQ_ID_BIT)
|
||||
#define DMA_IRQ_ID_TO_INT1_MASK(irq_id) (irq_id <<= (FIRST_DMA_INT1_BIT - FIRST_DMA_INT1_IRQ_ID_BIT))
|
||||
#define DMA_IRQ_ID_TO_INT2_MASK(irq_id) (irq_id >>= (FIRST_DMA_INT2_IRQ_ID_BIT - FIRST_DMA_INT2_BIT))
|
||||
|
||||
uint32_t HeathrowIC::register_dma_int(IntSrc src_id)
|
||||
uint64_t HeathrowIC::register_dma_int(IntSrc src_id)
|
||||
{
|
||||
switch (src_id) {
|
||||
case IntSrc::DMA_SCSI_MESH : return DMA_INT_TO_IRQ_ID(0x00);
|
||||
case IntSrc::DMA_SWIM3 : return DMA_INT_TO_IRQ_ID(0x01);
|
||||
case IntSrc::DMA_IDE0 : return DMA_INT_TO_IRQ_ID(0x02);
|
||||
case IntSrc::DMA_IDE1 : return DMA_INT_TO_IRQ_ID(0x03);
|
||||
case IntSrc::DMA_SCCA_Tx : return DMA_INT_TO_IRQ_ID(0x04);
|
||||
case IntSrc::DMA_SCCA_Rx : return DMA_INT_TO_IRQ_ID(0x05);
|
||||
case IntSrc::DMA_SCCB_Tx : return DMA_INT_TO_IRQ_ID(0x06);
|
||||
case IntSrc::DMA_SCCB_Rx : return DMA_INT_TO_IRQ_ID(0x07);
|
||||
case IntSrc::DMA_DAVBUS_Tx : return DMA_INT_TO_IRQ_ID(0x08);
|
||||
case IntSrc::DMA_DAVBUS_Rx : return DMA_INT_TO_IRQ_ID(0x09);
|
||||
case IntSrc::DMA_ETHERNET_Tx : return DMA_INT_TO_IRQ_ID(0x20);
|
||||
case IntSrc::DMA_ETHERNET_Rx : return DMA_INT_TO_IRQ_ID(0x21);
|
||||
case IntSrc::DMA_SCSI_MESH : return INT_TO_IRQ_ID(0x00);
|
||||
case IntSrc::DMA_SWIM3 : return INT_TO_IRQ_ID(0x01);
|
||||
case IntSrc::DMA_IDE0 : return INT_TO_IRQ_ID(0x02);
|
||||
case IntSrc::DMA_IDE1 : return INT_TO_IRQ_ID(0x03);
|
||||
case IntSrc::DMA_SCCA_Tx : return INT_TO_IRQ_ID(0x04);
|
||||
case IntSrc::DMA_SCCA_Rx : return INT_TO_IRQ_ID(0x05);
|
||||
case IntSrc::DMA_SCCB_Tx : return INT_TO_IRQ_ID(0x06);
|
||||
case IntSrc::DMA_SCCB_Rx : return INT_TO_IRQ_ID(0x07);
|
||||
case IntSrc::DMA_DAVBUS_Tx : return INT_TO_IRQ_ID(0x08);
|
||||
case IntSrc::DMA_DAVBUS_Rx : return INT_TO_IRQ_ID(0x09);
|
||||
case IntSrc::DMA_ETHERNET_Tx : return INT_TO_IRQ_ID(0x20);
|
||||
case IntSrc::DMA_ETHERNET_Rx : return INT_TO_IRQ_ID(0x21);
|
||||
default:
|
||||
ABORT_F("Heathrow: unknown DMA interrupt source %d", src_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HeathrowIC::ack_int(uint32_t irq_id, uint8_t irq_line_state)
|
||||
void HeathrowIC::ack_int_common(uint64_t irq_id, uint8_t irq_line_state)
|
||||
{
|
||||
#if 1
|
||||
if (!IS_INT1(irq_id)) { // does this irq_id belong to the second set?
|
||||
IRQ_ID_TO_INT2_MASK(irq_id);
|
||||
// native mode: set IRQ bits in int_events on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events on all transitions
|
||||
#if 0
|
||||
LOG_F(INFO, "%s: native interrupt events:%08x.%08x levels:%08x.%08x change2:%08x state:%d",
|
||||
this->name.c_str(), this->int_events1 + 0, this->int_events2 + 0,
|
||||
this->int_levels1 + 0, this->int_levels2 + 0, irq_id, irq_line_state
|
||||
);
|
||||
LOG_F(INTERRUPT, "%s: native interrupt events:%08x.%08x levels:%08x.%08x change:%08x.%08x state:%d",
|
||||
this->name.c_str(), uint32_t(this->int_events >> 32), uint32_t(this->int_events), uint32_t(this->int_levels >> 32),
|
||||
uint32_t(this->int_levels), uint32_t(irq_id >> 32), uint32_t(irq_id), irq_line_state
|
||||
);
|
||||
#endif
|
||||
// native mode: set IRQ bits in int_events2 on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events2 on all transitions
|
||||
if ((this->int_mask1 & MACIO_INT_MODE) ||
|
||||
(irq_line_state && !(this->int_levels2 & irq_id))) {
|
||||
this->int_events2 |= irq_id;
|
||||
} else {
|
||||
this->int_events2 &= ~irq_id;
|
||||
}
|
||||
// update IRQ line state
|
||||
if (irq_line_state) {
|
||||
this->int_levels2 |= irq_id;
|
||||
} else {
|
||||
this->int_levels2 &= ~irq_id;
|
||||
}
|
||||
if ((this->int_mask & MACIO_INT_MODE) ||
|
||||
(irq_line_state && !(this->int_levels & irq_id))) {
|
||||
this->int_events |= irq_id;
|
||||
} else {
|
||||
IRQ_ID_TO_INT1_MASK(irq_id);
|
||||
// native mode: set IRQ bits in int_events1 on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events1 on all transitions
|
||||
#if 0
|
||||
LOG_F(INFO, "%s: native interrupt events:%08x.%08x levels:%08x.%08x change1:%08x state:%d",
|
||||
this->name.c_str(), this->int_events1 + 0, this->int_events2 + 0,
|
||||
this->int_levels1 + 0, this->int_levels2 + 0, irq_id, irq_line_state);
|
||||
#endif
|
||||
if ((this->int_mask1 & MACIO_INT_MODE) ||
|
||||
(irq_line_state && !(this->int_levels1 & irq_id))) {
|
||||
this->int_events1 |= irq_id;
|
||||
} else {
|
||||
this->int_events1 &= ~irq_id;
|
||||
}
|
||||
// update IRQ line state
|
||||
if (irq_line_state) {
|
||||
this->int_levels1 |= irq_id;
|
||||
} else {
|
||||
this->int_levels1 &= ~irq_id;
|
||||
}
|
||||
this->int_events &= ~irq_id;
|
||||
}
|
||||
// update IRQ line state
|
||||
if (irq_line_state) {
|
||||
this->int_levels |= irq_id;
|
||||
} else {
|
||||
this->int_levels &= ~irq_id;
|
||||
}
|
||||
|
||||
this->signal_cpu_int();
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (this->int_mask1 & MACIO_INT_MODE) { // 68k interrupt emulation mode?
|
||||
if (!IS_INT1(irq_id)) {
|
||||
IRQ_ID_TO_INT2_MASK(irq_id);
|
||||
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_TO_INT1_MASK(irq_id);
|
||||
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;
|
||||
}
|
||||
}
|
||||
this->signal_cpu_int();
|
||||
} else {
|
||||
LOG_F(WARNING, "%s: native interrupt mode not implemented", this->name.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HeathrowIC::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state)
|
||||
void HeathrowIC::ack_int(uint64_t irq_id, uint8_t irq_line_state)
|
||||
{
|
||||
#if 1
|
||||
if (!IS_DMA_INT1(irq_id)) {
|
||||
DMA_IRQ_ID_TO_INT2_MASK(irq_id);
|
||||
// native mode: set IRQ bits in int_events2 on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events2 on all transitions
|
||||
if ((this->int_mask1 & MACIO_INT_MODE) ||
|
||||
(irq_line_state && !(this->int_levels2 & irq_id))) {
|
||||
this->int_events2 |= irq_id;
|
||||
} else {
|
||||
this->int_events2 &= ~irq_id;
|
||||
}
|
||||
// update IRQ line state
|
||||
if (irq_line_state) {
|
||||
this->int_levels2 |= irq_id;
|
||||
} else {
|
||||
this->int_levels2 &= ~irq_id;
|
||||
}
|
||||
} else {
|
||||
DMA_IRQ_ID_TO_INT1_MASK(irq_id);
|
||||
// native mode: set IRQ bits in int_events1 on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events1 on all transitions
|
||||
if ((this->int_mask1 & MACIO_INT_MODE) ||
|
||||
(irq_line_state && !(this->int_levels1 & irq_id))) {
|
||||
this->int_events1 |= irq_id;
|
||||
} else {
|
||||
this->int_events1 &= ~irq_id;
|
||||
}
|
||||
// update IRQ line state
|
||||
if (irq_line_state) {
|
||||
this->int_levels1 |= irq_id;
|
||||
} else {
|
||||
this->int_levels1 &= ~irq_id;
|
||||
}
|
||||
}
|
||||
this->ack_int_common(irq_id, irq_line_state);
|
||||
}
|
||||
|
||||
this->signal_cpu_int();
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (this->int_mask1 & MACIO_INT_MODE) { // 68k interrupt emulation mode?
|
||||
if (!IS_DMA_INT1(irq_id)) {
|
||||
DMA_IRQ_ID_TO_INT2_MASK(irq_id);
|
||||
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 {
|
||||
DMA_IRQ_ID_TO_INT1_MASK(irq_id);
|
||||
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;
|
||||
}
|
||||
}
|
||||
this->signal_cpu_int();
|
||||
} else {
|
||||
ABORT_F("%s: native interrupt mode not implemented", this->name.c_str());
|
||||
}
|
||||
#endif
|
||||
void HeathrowIC::ack_dma_int(uint64_t irq_id, uint8_t irq_line_state)
|
||||
{
|
||||
this->ack_int_common(irq_id, irq_line_state);
|
||||
}
|
||||
|
||||
void HeathrowIC::signal_cpu_int() {
|
||||
if ((this->int_events1 & this->int_mask1) || (this->int_events2 & this->int_mask2)) {
|
||||
if (this->int_events & this->int_mask) {
|
||||
if (!this->cpu_int_latch) {
|
||||
this->cpu_int_latch = true;
|
||||
ppc_assert_int();
|
||||
@@ -644,8 +502,7 @@ void HeathrowIC::signal_cpu_int() {
|
||||
|
||||
void HeathrowIC::clear_cpu_int()
|
||||
{
|
||||
if (!(this->int_events1 & this->int_mask1) && !(this->int_events2 & this->int_mask2) &&
|
||||
this->cpu_int_latch) {
|
||||
if (!(this->int_events & this->int_mask) && this->cpu_int_latch) {
|
||||
this->cpu_int_latch = false;
|
||||
ppc_release_int();
|
||||
LOG_F(5, "Heathrow: CPU INT latch cleared");
|
||||
|
@@ -144,17 +144,17 @@ public:
|
||||
void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size);
|
||||
|
||||
// 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);
|
||||
|
||||
void attach_iodevice(int dev_num, IobusDevice* dev_obj);
|
||||
|
||||
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 notify_bar_change(int bar_num);
|
||||
void ack_int_common(uint32_t irq_id, uint8_t irq_line_state);
|
||||
void signal_cpu_int(uint32_t irq_id);
|
||||
void ack_int_common(uint64_t irq_id, uint8_t irq_line_state);
|
||||
void signal_cpu_int(uint64_t irq_id);
|
||||
void clear_cpu_int();
|
||||
|
||||
private:
|
||||
@@ -208,19 +208,26 @@ public:
|
||||
}
|
||||
|
||||
// MMIO device 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 notify_bar_change(int bar_num);
|
||||
|
||||
uint32_t read_ctrl(uint32_t offset, int size);
|
||||
void write_ctrl(uint32_t offset, uint32_t value, int size);
|
||||
|
||||
void ack_int_common(uint64_t irq_id, uint8_t irq_line_state);
|
||||
uint32_t mio_ctrl_read(uint32_t offset, int size);
|
||||
uint32_t mio_ctrl_read_aligned(uint32_t offset);
|
||||
void mio_ctrl_write(uint32_t offset, uint32_t value, int size);
|
||||
|
||||
uint32_t dma_read(uint32_t offset, int size);
|
||||
void dma_write(uint32_t offset, uint32_t value, int size);
|
||||
|
||||
@@ -235,6 +242,7 @@ private:
|
||||
std::atomic<uint32_t> int_levels{0};
|
||||
std::atomic<uint32_t> int_events{0};
|
||||
bool cpu_int_latch = false;
|
||||
uint32_t feat_ctrl = 0; // features control register
|
||||
|
||||
std::unique_ptr<AwacsScreamer> awacs; // AWACS audio codec instance
|
||||
std::unique_ptr<DMAChannel> snd_out_dma;
|
||||
@@ -350,14 +358,14 @@ public:
|
||||
void set_media_bay_id(uint8_t id);
|
||||
|
||||
// MMIO device 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:
|
||||
uint32_t dma_read(uint32_t offset, int size);
|
||||
@@ -367,23 +375,24 @@ protected:
|
||||
void mio_ctrl_write(uint32_t offset, uint32_t value, int size);
|
||||
|
||||
void notify_bar_change(int bar_num);
|
||||
void ack_int_common(uint64_t irq_id, uint8_t irq_line_state);
|
||||
|
||||
void feature_control(const uint32_t value);
|
||||
void feature_control(uint32_t value);
|
||||
|
||||
void signal_cpu_int();
|
||||
void clear_cpu_int();
|
||||
|
||||
private:
|
||||
uint32_t base_addr = 0;
|
||||
std::atomic<uint32_t> int_events2{0};
|
||||
uint32_t int_mask2 = 0;
|
||||
std::atomic<uint32_t> int_levels2{0};
|
||||
std::atomic<uint32_t> int_events1{0};
|
||||
uint32_t int_mask1 = 0;
|
||||
std::atomic<uint32_t> int_levels1{0};
|
||||
|
||||
// interrupt state
|
||||
uint64_t int_mask = 0;
|
||||
std::atomic<uint64_t> int_levels{0};
|
||||
std::atomic<uint64_t> int_events{0};
|
||||
bool cpu_int_latch = false;
|
||||
|
||||
uint32_t feat_ctrl = 0; // features control register
|
||||
uint32_t aux_ctrl = 0; // aux features control register
|
||||
bool cpu_int_latch = false;
|
||||
|
||||
uint8_t cpu_id = 0xE0; // CPUID field (LSB of the MIO_HEAT_ID)
|
||||
uint8_t mb_id = 0x70; // Media Bay ID (bits 15:8 of the MIO_HEAT_ID)
|
||||
|
@@ -217,19 +217,51 @@ void OHare::dma_write(uint32_t offset, uint32_t value, int size)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t OHare::register_dev_int(IntSrc src_id)
|
||||
/*
|
||||
Commenting out temporarily due to compile issues
|
||||
|
||||
void OHare::feature_control(uint32_t value)
|
||||
{
|
||||
LOG_F(9, "write %x to MIO:Feat_Ctrl register", value);
|
||||
|
||||
this->feat_ctrl = value;
|
||||
|
||||
if (!(this->feat_ctrl & 1)) {
|
||||
LOG_F(9, "%s: Monitor sense enabled", this->get_name().c_str());
|
||||
} else {
|
||||
LOG_F(9, "%s: Monitor sense disabled", this->get_name().c_str());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#define INT_TO_IRQ_ID(intx) (1 << intx)
|
||||
|
||||
uint64_t OHare::register_dev_int(IntSrc src_id)
|
||||
{
|
||||
LOG_F(ERROR, "OHare: register_dev_int() not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t OHare::register_dma_int(IntSrc src_id)
|
||||
uint64_t OHare::register_dma_int(IntSrc src_id)
|
||||
{
|
||||
LOG_F(ERROR, "OHare: register_dma_int() not implemented");
|
||||
switch (src_id) {
|
||||
case IntSrc::DMA_SCSI_MESH: return INT_TO_IRQ_ID(0x00);
|
||||
case IntSrc::DMA_SWIM3 : return INT_TO_IRQ_ID(0x01);
|
||||
case IntSrc::DMA_IDE0 : return INT_TO_IRQ_ID(0x02);
|
||||
//
|
||||
case IntSrc::DMA_SCCA_Tx : return INT_TO_IRQ_ID(0x04);
|
||||
case IntSrc::DMA_SCCA_Rx : return INT_TO_IRQ_ID(0x05);
|
||||
case IntSrc::DMA_SCCB_Tx : return INT_TO_IRQ_ID(0x06);
|
||||
case IntSrc::DMA_SCCB_Rx : return INT_TO_IRQ_ID(0x07);
|
||||
case IntSrc::DMA_DAVBUS_Tx: return INT_TO_IRQ_ID(0x08);
|
||||
case IntSrc::DMA_DAVBUS_Rx: return INT_TO_IRQ_ID(0x09);
|
||||
default:
|
||||
ABORT_F("%s: unknown DMA interrupt source %d", this->name.c_str(), src_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OHare::ack_int(uint32_t irq_id, uint8_t irq_line_state)
|
||||
void OHare::ack_int_common(uint64_t irq_id, uint8_t irq_line_state)
|
||||
{
|
||||
// native mode: set IRQ bits in int_events1 on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events1 on all transitions
|
||||
@@ -240,22 +272,22 @@ void OHare::ack_int(uint32_t irq_id, uint8_t irq_line_state)
|
||||
#endif
|
||||
if ((this->int_mask & MACIO_INT_MODE) ||
|
||||
(irq_line_state && !(this->int_levels & irq_id))) {
|
||||
this->int_events |= irq_id;
|
||||
this->int_events |= (uint32_t)irq_id;
|
||||
} else {
|
||||
this->int_events &= ~irq_id;
|
||||
this->int_events &= ~(uint32_t)irq_id;
|
||||
}
|
||||
this->int_events &= this->int_mask;
|
||||
// update IRQ line state
|
||||
if (irq_line_state) {
|
||||
this->int_levels |= irq_id;
|
||||
this->int_levels |= (uint32_t)irq_id;
|
||||
} else {
|
||||
this->int_levels &= ~irq_id;
|
||||
this->int_levels &= ~(uint32_t)irq_id;
|
||||
}
|
||||
|
||||
this->signal_cpu_int();
|
||||
}
|
||||
|
||||
void OHare::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state)
|
||||
void OHare::ack_int(uint64_t irq_id, uint8_t irq_line_state)
|
||||
{
|
||||
// native mode: set IRQ bits in int_events1 on a 0-to-1 transition
|
||||
// emulated mode: set IRQ bits in int_events1 on all transitions
|
||||
@@ -272,8 +304,12 @@ void OHare::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state)
|
||||
} else {
|
||||
this->int_levels &= ~irq_id;
|
||||
}
|
||||
this->ack_int_common(irq_id, irq_line_state);
|
||||
}
|
||||
|
||||
this->signal_cpu_int();
|
||||
void OHare::ack_dma_int(uint64_t irq_id, uint8_t irq_line_state)
|
||||
{
|
||||
this->ack_int_common(irq_id, irq_line_state);
|
||||
}
|
||||
|
||||
void OHare::signal_cpu_int() {
|
||||
@@ -301,7 +337,7 @@ static const std::vector<std::string> OHare_Subdevices = {
|
||||
};
|
||||
|
||||
static const DeviceDescription OHare_Descriptor = {
|
||||
OHare::create, OHare_Subdevices, {}
|
||||
};
|
||||
OHare::create, OHare_Subdevices, {
|
||||
}};
|
||||
|
||||
REGISTER_DEVICE(OHare, OHare_Descriptor);
|
||||
|
@@ -103,7 +103,7 @@ protected:
|
||||
|
||||
// interrupt suff
|
||||
InterruptCtrl* int_ctrl = nullptr;
|
||||
uint32_t irq_id = 0;
|
||||
uint64_t irq_id = 0;
|
||||
std::function<void(uint8_t irq_line_state)> vbl_cb = [this](uint8_t irq_line_state) {
|
||||
if (this->int_ctrl)
|
||||
this->int_ctrl->ack_int(this->irq_id, irq_line_state);
|
||||
|
Reference in New Issue
Block a user