mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-18 04:31:16 +00:00
Fix PCI interrupts and add devices.
- Use interrupt source instead of IRQ ID in the IrqMap. - Add a get_interrupt_controller method to mirror the set_interrupt_controller method. - Have PCI hosts use pcihost_device_postinit to add PCI devices. This was moved from bandit's device_postinit and allows for duplicate devices by appending the slot to the registered device name. - Fix interrupts of Pippin. Fix interrupts of cmd646 - Make it work like other PCI devices. - IntDetails is built into the pcibase base class. - IntDetails is initialized by calling pci_interrupt. - pci_interrupt checks the "enable interrupts" flag before doing an interrupt.
This commit is contained in:
parent
e707d1f27a
commit
e7eb1c8a66
@ -228,7 +228,7 @@ void CmdIdeCtrl::update_irq(const int ch_num, const uint8_t irq_level) {
|
||||
this->mrdmode &= ~(ch_num ? BM_CH1_INT : BM_CH0_INT);
|
||||
|
||||
if (!irq_level || forward_irq)
|
||||
this->irq_info.int_ctrl_obj->ack_int(this->irq_info.irq_id, irq_level);
|
||||
this->pci_interrupt(irq_level);
|
||||
}
|
||||
|
||||
static const DeviceDescription CmdIde_Descriptor = {
|
||||
|
@ -78,11 +78,6 @@ public:
|
||||
bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res) override;
|
||||
bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size) override;
|
||||
|
||||
int device_postinit() override {
|
||||
this->irq_info = this->host_instance->register_pci_int(this);
|
||||
return 0;
|
||||
};
|
||||
|
||||
private:
|
||||
void notify_bar_change(int bar_num);
|
||||
uint8_t read_config_reg(uint32_t reg_offset);
|
||||
@ -108,8 +103,6 @@ private:
|
||||
|
||||
uint8_t mrdmode = 0;
|
||||
uint8_t udma_time_cr = 0;
|
||||
|
||||
IntDetails irq_info = {};
|
||||
};
|
||||
|
||||
#endif // CMD646_IDE_H
|
||||
|
@ -71,6 +71,15 @@ enum IntSrc : uint32_t {
|
||||
DMA_DAVBUS_Rx,
|
||||
DMA_ETHERNET_Tx,
|
||||
DMA_ETHERNET_Rx,
|
||||
FIREWIRE,
|
||||
PCI_J12,
|
||||
PCI_J11,
|
||||
PCI_J10,
|
||||
PCI_J9,
|
||||
ATA,
|
||||
USB,
|
||||
PIPPIN_E,
|
||||
PIPPIN_F,
|
||||
};
|
||||
|
||||
/** Base class for interrupt controllers. */
|
||||
|
@ -235,32 +235,7 @@ inline void BanditHost::cfg_setup(uint32_t offset, int size, int &bus_num,
|
||||
}
|
||||
|
||||
int BanditHost::device_postinit() {
|
||||
std::string pci_dev_name;
|
||||
|
||||
static const std::map<std::string, int> pci_slots1 = {
|
||||
{"pci_A1", DEV_FUN(0xD,0)}, {"pci_B1", DEV_FUN(0xE,0)}, {"pci_C1", DEV_FUN(0xF,0)}
|
||||
};
|
||||
|
||||
static const std::map<std::string, int> pci_slots2 = {
|
||||
{"pci_D2", DEV_FUN(0xD,0)}, {"pci_E2", DEV_FUN(0xE,0)}, {"pci_F2", DEV_FUN(0xF,0)}
|
||||
};
|
||||
|
||||
static const std::map<std::string, int> vci_slots = {
|
||||
{"vci_D", DEV_FUN(0xD,0)}, {"vci_E", DEV_FUN(0xE,0)}, {"vci_F", DEV_FUN(0xF,0)}
|
||||
};
|
||||
|
||||
for (auto& slot :
|
||||
this->bridge_num == 0 ? vci_slots :
|
||||
this->bridge_num == 1 ? pci_slots1 :
|
||||
this->bridge_num == 2 ? pci_slots2 :
|
||||
pci_slots1
|
||||
) {
|
||||
pci_dev_name = GET_STR_PROP(slot.first);
|
||||
if (!pci_dev_name.empty()) {
|
||||
this->attach_pci_device(pci_dev_name, slot.second);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return this->pcihost_device_postinit();
|
||||
}
|
||||
|
||||
Bandit::Bandit(int bridge_num, std::string name, int dev_id, int rev)
|
||||
@ -346,7 +321,18 @@ static const PropMap Chaos_Properties = {
|
||||
new StrProperty("")},
|
||||
{"vci_E",
|
||||
new StrProperty("")},
|
||||
{"vci_F",
|
||||
};
|
||||
|
||||
static const PropMap PsxPci1_Properties = {
|
||||
{"pci_A1",
|
||||
new StrProperty("")},
|
||||
{"pci_B1",
|
||||
new StrProperty("")},
|
||||
{"pci_C1",
|
||||
new StrProperty("")},
|
||||
{"pci_E1",
|
||||
new StrProperty("")},
|
||||
{"pci_F1",
|
||||
new StrProperty("")},
|
||||
};
|
||||
|
||||
@ -359,7 +345,7 @@ static const DeviceDescription Bandit2_Descriptor = {
|
||||
};
|
||||
|
||||
static const DeviceDescription PsxPci1_Descriptor = {
|
||||
Bandit::create_psx_first, {}, Bandit1_Properties
|
||||
Bandit::create_psx_first, {}, PsxPci1_Properties
|
||||
};
|
||||
|
||||
static const DeviceDescription Chaos_Descriptor = {
|
||||
|
@ -73,9 +73,6 @@ class BanditHost : public PCIHost, public MMIODevice {
|
||||
public:
|
||||
BanditHost(int bridge_num) { this->bridge_num = bridge_num; };
|
||||
|
||||
// PCIHost methods
|
||||
virtual void pci_interrupt(uint8_t irq_line_state, PCIBase *dev) {}
|
||||
|
||||
// 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);
|
||||
|
@ -86,8 +86,28 @@ void DecPciBridge::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetail
|
||||
}
|
||||
}
|
||||
|
||||
static const PropMap Dec21154Yosemite_Properties = {
|
||||
{"pci_FireWire",
|
||||
new StrProperty("")},
|
||||
{"pci_UltraATA",
|
||||
new StrProperty("")},
|
||||
{"pci_J11",
|
||||
new StrProperty("")},
|
||||
{"pci_J10",
|
||||
new StrProperty("")},
|
||||
{"pci_J9",
|
||||
new StrProperty("")},
|
||||
{"pci_USB",
|
||||
new StrProperty("")},
|
||||
};
|
||||
|
||||
static const DeviceDescription Dec21154_Descriptor = {
|
||||
DecPciBridge::create, {}, {}
|
||||
};
|
||||
|
||||
static const DeviceDescription Dec21154Yosemite_Descriptor = {
|
||||
DecPciBridge::create_yosemite, {}, Dec21154Yosemite_Properties
|
||||
};
|
||||
|
||||
REGISTER_DEVICE(Dec21154, Dec21154_Descriptor);
|
||||
REGISTER_DEVICE(Dec21154Yosemite, Dec21154Yosemite_Descriptor);
|
||||
|
@ -44,6 +44,10 @@ public:
|
||||
return std::unique_ptr<DecPciBridge>(new DecPciBridge("DEC21154"));
|
||||
}
|
||||
|
||||
static std::unique_ptr<HWComponent> create_yosemite() {
|
||||
return std::unique_ptr<DecPciBridge>(new DecPciBridge("DEC21154Yosemite"));
|
||||
}
|
||||
|
||||
// PCIDevice methods
|
||||
uint32_t pci_cfg_read(uint32_t reg_offs, AccessDetails &details);
|
||||
void pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details);
|
||||
|
@ -301,3 +301,21 @@ void PCIBase::pci_wr_exp_rom_bar(uint32_t data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PCIBase::pci_interrupt(uint8_t irq_line_state) {
|
||||
if (!(this->command & 0x0400)) {
|
||||
if (!this->int_details.int_ctrl_obj)
|
||||
this->host_instance->register_pci_int(this);
|
||||
if (this->int_details.int_ctrl_obj && this->int_details.irq_id)
|
||||
this->int_details.int_ctrl_obj->ack_int(this->int_details.irq_id, irq_line_state);
|
||||
else
|
||||
LOG_F(ERROR, "Unhandled interrupt from device %s", this->get_name().c_str());
|
||||
/* A pci device should set the interrupt status bit when an interrupt occurs
|
||||
* and it should clear the interrupt status bit when its interrupt bits are cleared.
|
||||
* The interrupt status bit is new to PCI Local Bus Specification Revision 2.3
|
||||
* and Power Macs use PCI Local Bus Specification Revision 2.0. Some PCI cards
|
||||
* might not implement this bit.
|
||||
*/
|
||||
//this->status |= 0x0008;
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ typedef struct {
|
||||
} BarConfig;
|
||||
|
||||
class PCIBase : public MMIODevice {
|
||||
friend class PCIHost;
|
||||
public:
|
||||
PCIBase(std::string name, PCIHeaderType hdr_type, int num_bars);
|
||||
virtual ~PCIBase() = default;
|
||||
@ -126,10 +127,12 @@ public:
|
||||
this->irq_pin = irq_pin;
|
||||
}
|
||||
|
||||
virtual void pci_interrupt(uint8_t irq_line_state) {
|
||||
this->host_instance->pci_interrupt(irq_line_state, this);
|
||||
virtual void set_int_details(IntDetails &int_details) {
|
||||
this->int_details = int_details;
|
||||
}
|
||||
|
||||
virtual void pci_interrupt(uint8_t irq_line_state);
|
||||
|
||||
// MMIODevice methods
|
||||
virtual uint32_t read(uint32_t rgn_start, uint32_t offset, int size) { return 0; }
|
||||
virtual void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size) { }
|
||||
@ -174,6 +177,8 @@ protected:
|
||||
|
||||
// 0 = not writable; 1 = bit is enabled in command register
|
||||
uint16_t command_cfg = 0xffff - (1<<3) - (1<<7); // disable: special cycles and stepping
|
||||
|
||||
IntDetails int_details = { 0 };
|
||||
};
|
||||
|
||||
inline uint32_t pci_cfg_log(uint32_t value, AccessDetails &details) {
|
||||
|
@ -85,3 +85,7 @@ void PCIBridgeBase::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetai
|
||||
return PCIBase::pci_cfg_write(reg_offs, value, details);
|
||||
}
|
||||
}
|
||||
|
||||
int PCIBridgeBase::device_postinit() {
|
||||
return this->pcihost_device_postinit();
|
||||
}
|
||||
|
@ -68,6 +68,9 @@ public:
|
||||
std::function<uint16_t()> pci_rd_bridge_control;
|
||||
std::function<void(uint16_t)> pci_wr_bridge_control;
|
||||
|
||||
// HWComponent methods
|
||||
virtual int device_postinit();
|
||||
|
||||
protected:
|
||||
// PCI configuration space state
|
||||
uint8_t primary_bus = 0;
|
||||
|
@ -145,7 +145,16 @@ PCIBase *PCIHost::attach_pci_device(const std::string& dev_name, int slot_id, co
|
||||
return dev;
|
||||
}
|
||||
|
||||
IntDetails PCIHost::register_pci_int(PCIBase* dev_instance) {
|
||||
InterruptCtrl *PCIHost::get_interrupt_controller() {
|
||||
if (!this->int_ctrl) {
|
||||
InterruptCtrl *int_ctrl_obj =
|
||||
dynamic_cast<InterruptCtrl*>(gMachineObj->get_comp_by_type(HWCompType::INT_CTRL));
|
||||
this->int_ctrl = int_ctrl_obj;
|
||||
}
|
||||
return this->int_ctrl;
|
||||
}
|
||||
|
||||
bool PCIHost::register_pci_int(PCIBase* dev_instance) {
|
||||
bool dev_found = false;
|
||||
int dev_fun_num = 0;
|
||||
|
||||
@ -160,10 +169,24 @@ IntDetails PCIHost::register_pci_int(PCIBase* dev_instance) {
|
||||
ABORT_F("register_pci_int: requested device not found");
|
||||
|
||||
for (auto& irq : this->my_irq_map) {
|
||||
if (irq.dev_fun_num == dev_fun_num)
|
||||
return {this->int_ctrl, irq.irq_id};
|
||||
if (irq.dev_fun_num == dev_fun_num) {
|
||||
IntDetails new_int_detail;
|
||||
new_int_detail.int_ctrl_obj = this->get_interrupt_controller();
|
||||
if (new_int_detail.int_ctrl_obj && irq.int_src)
|
||||
new_int_detail.irq_id = new_int_detail.int_ctrl_obj->register_dev_int(irq.int_src);
|
||||
dev_instance->set_int_details(new_int_detail);
|
||||
return true;
|
||||
}
|
||||
ABORT_F("register_pci_int: no IRQ map for device 0x%X", dev_fun_num);
|
||||
}
|
||||
|
||||
PCIBridgeBase *self = dynamic_cast<PCIBridgeBase*>(this);
|
||||
if (self) {
|
||||
if (!self->int_details.int_ctrl_obj)
|
||||
self->host_instance->register_pci_int(self);
|
||||
dev_instance->set_int_details(self->int_details);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PCIHost::pci_io_read_loop(uint32_t offset, int size, uint32_t &res)
|
||||
@ -245,3 +268,19 @@ PCIBase *PCIHost::pci_find_device(uint8_t dev_num, uint8_t fun_num)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int PCIHost::pcihost_device_postinit()
|
||||
{
|
||||
std::string pci_dev_name;
|
||||
|
||||
for (auto& slot : this->my_irq_map) {
|
||||
if (slot.slot_name) {
|
||||
pci_dev_name = GET_STR_PROP(slot.slot_name);
|
||||
if (!pci_dev_name.empty()) {
|
||||
this->attach_pci_device(pci_dev_name, slot.dev_fun_num, std::string("@") + slot.slot_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ typedef struct AccessDetails {
|
||||
typedef struct {
|
||||
const char * slot_name;
|
||||
int dev_fun_num;
|
||||
uint32_t irq_id;
|
||||
IntSrc int_src;
|
||||
} PciIrqMap;
|
||||
|
||||
class PCIBase;
|
||||
@ -86,16 +86,16 @@ public:
|
||||
virtual PCIBase *pci_find_device(uint8_t bus_num, uint8_t dev_num, uint8_t fun_num);
|
||||
virtual PCIBase *pci_find_device(uint8_t dev_num, uint8_t fun_num);
|
||||
|
||||
virtual void pci_interrupt(uint8_t irq_line_state, PCIBase *dev) {}
|
||||
|
||||
virtual void set_irq_map(const std::vector<PciIrqMap> &irq_map) {
|
||||
this->my_irq_map = irq_map;
|
||||
};
|
||||
virtual int pcihost_device_postinit();
|
||||
|
||||
virtual IntDetails register_pci_int(PCIBase* dev_instance);
|
||||
virtual bool register_pci_int(PCIBase* dev_instance);
|
||||
virtual void set_interrupt_controller(InterruptCtrl * int_ctrl_obj) {
|
||||
this->int_ctrl = int_ctrl_obj;
|
||||
};
|
||||
virtual InterruptCtrl *get_interrupt_controller();
|
||||
|
||||
protected:
|
||||
std::unordered_map<int, PCIBase*> dev_map;
|
||||
|
@ -450,6 +450,9 @@ uint32_t GrandCentral::register_dev_int(IntSrc src_id) {
|
||||
|
||||
case IntSrc::PLATINUM : return INT_TO_IRQ_ID(0x1E); // EXT10
|
||||
|
||||
case IntSrc::PIPPIN_F : return INT_TO_IRQ_ID(0x1D); // EXT9
|
||||
case IntSrc::PIPPIN_E : return INT_TO_IRQ_ID(0x1E); // EXT10
|
||||
|
||||
default:
|
||||
ABORT_F("%s: unknown interrupt source %d", this->name.c_str(), src_id);
|
||||
}
|
||||
|
@ -383,14 +383,15 @@ uint32_t HeathrowIC::register_dev_int(IntSrc src_id)
|
||||
{
|
||||
switch (src_id) {
|
||||
case IntSrc::SCSI_MESH : return INT_TO_IRQ_ID(0x0C);
|
||||
case IntSrc::IDE0 : return INT_TO_IRQ_ID(0x0D);
|
||||
case IntSrc::IDE0 : return INT_TO_IRQ_ID(0x0D); // Beige G3 first IDE controller, or Yosemite ata-3
|
||||
case IntSrc::IDE1 : return INT_TO_IRQ_ID(0x0E);
|
||||
case IntSrc::SCCA : return INT_TO_IRQ_ID(0x0F);
|
||||
case IntSrc::SCCB : return INT_TO_IRQ_ID(0x10);
|
||||
case IntSrc::DAVBUS : return INT_TO_IRQ_ID(0x11);
|
||||
case IntSrc::VIA_CUDA : return INT_TO_IRQ_ID(0x12);
|
||||
case IntSrc::SWIM3 : return INT_TO_IRQ_ID(0x13);
|
||||
case IntSrc::NMI : return INT_TO_IRQ_ID(0x14); // nmiSource in AppleHeathrow/Heathrow.cpp
|
||||
case IntSrc::NMI : return INT_TO_IRQ_ID(0x14); // nmiSource in AppleHeathrow/Heathrow.cpp; programmer-switch in B&W G3
|
||||
|
||||
case IntSrc::PERCH2 : return INT_TO_IRQ_ID(0x15);
|
||||
case IntSrc::PCI_GPU : return INT_TO_IRQ_ID(0x16);
|
||||
case IntSrc::PCI_A : return INT_TO_IRQ_ID(0x17);
|
||||
@ -398,7 +399,17 @@ uint32_t HeathrowIC::register_dev_int(IntSrc src_id)
|
||||
case IntSrc::PCI_C : return INT_TO_IRQ_ID(0x19);
|
||||
case IntSrc::PERCH1 : return INT_TO_IRQ_ID(0x1A);
|
||||
case IntSrc::PCI_PERCH : return INT_TO_IRQ_ID(0x1C);
|
||||
|
||||
case IntSrc::FIREWIRE : return INT_TO_IRQ_ID(0x15); // Yosemite built-in PCI FireWire
|
||||
case IntSrc::PCI_J12 : return INT_TO_IRQ_ID(0x16); // Yosemite 32-bit 66MHz slot for GPU
|
||||
case IntSrc::PCI_J11 : return INT_TO_IRQ_ID(0x17); // Yosemite 64-bit 33MHz slot
|
||||
case IntSrc::PCI_J10 : return INT_TO_IRQ_ID(0x18); // Yosemite 64-bit 33MHz slot
|
||||
case IntSrc::PCI_J9 : return INT_TO_IRQ_ID(0x19); // Yosemite 64-bit 33MHz slot
|
||||
case IntSrc::ATA : return INT_TO_IRQ_ID(0x1A); // Yosemite PCI pci-ata
|
||||
case IntSrc::USB : return INT_TO_IRQ_ID(0x1C); // Yosemite PCI usb
|
||||
|
||||
case IntSrc::ETHERNET : return INT_TO_IRQ_ID(0x2A);
|
||||
|
||||
default:
|
||||
ABORT_F("Heathrow: unknown interrupt source %d", src_id);
|
||||
}
|
||||
|
@ -45,9 +45,6 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle"), PCIHost()
|
||||
this->command = 6;
|
||||
this->status = 0x80;
|
||||
|
||||
// assign PCI device number zero to myself
|
||||
this->pci_register_device(DEV_FUN(0,0), this);
|
||||
|
||||
// add PCI/ISA I/O space, 64K for now
|
||||
add_mmio_region(0xFE000000, 0x10000, this);
|
||||
|
||||
@ -57,59 +54,9 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle"), PCIHost()
|
||||
|
||||
int MPC106::device_postinit()
|
||||
{
|
||||
std::string pci_dev_name;
|
||||
|
||||
static const std::map<std::string, int> pci_slots = {
|
||||
{"pci_PERCH", DEV_FUN(0xC,0)}, {"pci_A1", DEV_FUN(0xD,0)},
|
||||
{"pci_B1", DEV_FUN(0xE,0)}, {"pci_C1", DEV_FUN(0xF,0)},
|
||||
{"pci_GPU", DEV_FUN(0x12,0)}
|
||||
};
|
||||
|
||||
for (auto& slot : pci_slots) {
|
||||
pci_dev_name = GET_STR_PROP(slot.first);
|
||||
if (!pci_dev_name.empty()) {
|
||||
this->attach_pci_device(pci_dev_name, slot.second, std::string("@") + slot.first);
|
||||
}
|
||||
}
|
||||
|
||||
this->int_ctrl = dynamic_cast<InterruptCtrl*>(
|
||||
gMachineObj->get_comp_by_type(HWCompType::INT_CTRL));
|
||||
|
||||
this->irq_id_PCI_A = this->int_ctrl->register_dev_int(IntSrc::PCI_A );
|
||||
this->irq_id_PCI_B = this->int_ctrl->register_dev_int(IntSrc::PCI_B );
|
||||
this->irq_id_PCI_C = this->int_ctrl->register_dev_int(IntSrc::PCI_C );
|
||||
this->irq_id_PCI_GPU = this->int_ctrl->register_dev_int(IntSrc::PCI_GPU );
|
||||
this->irq_id_PCI_PERCH = this->int_ctrl->register_dev_int(IntSrc::PCI_PERCH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MPC106::pci_interrupt(uint8_t irq_line_state, PCIBase *dev) {
|
||||
auto it = std::find_if(dev_map.begin(), dev_map.end(),
|
||||
[&dev](const std::pair<int, PCIBase*> &p) {
|
||||
return p.second == dev;
|
||||
}
|
||||
);
|
||||
|
||||
if (it == dev_map.end()) {
|
||||
LOG_F(ERROR, "Interrupt from unknown device %s", dev->get_name().c_str());
|
||||
}
|
||||
else {
|
||||
uint32_t irq_id;
|
||||
switch (it->first) {
|
||||
case DEV_FUN(0x0C,0): irq_id = this->irq_id_PCI_PERCH; break;
|
||||
case DEV_FUN(0x0D,0): irq_id = this->irq_id_PCI_A ; break;
|
||||
case DEV_FUN(0x0E,0): irq_id = this->irq_id_PCI_B ; break;
|
||||
case DEV_FUN(0x0F,0): irq_id = this->irq_id_PCI_C ; break;
|
||||
case DEV_FUN(0x12,0): irq_id = this->irq_id_PCI_GPU ; break;
|
||||
default:
|
||||
LOG_F(ERROR, "Interrupt from device %s at unexpected device/function %02x.%x",
|
||||
dev->get_name().c_str(), it->first >> 3, it->first & 7);
|
||||
return;
|
||||
}
|
||||
if (this->int_ctrl)
|
||||
this->int_ctrl->ack_int(irq_id, irq_line_state);
|
||||
}
|
||||
// assign PCI device number zero to myself
|
||||
this->pci_register_device(DEV_FUN(0,0), this);
|
||||
return this->pcihost_device_postinit();
|
||||
}
|
||||
|
||||
uint32_t MPC106::read(uint32_t rgn_start, uint32_t offset, int size) {
|
||||
@ -357,6 +304,8 @@ static const PropMap Grackle_Properties = {
|
||||
new StrProperty("")},
|
||||
{"pci_GPU",
|
||||
new StrProperty("")},
|
||||
{"pci_J12",
|
||||
new StrProperty("")},
|
||||
};
|
||||
|
||||
static const DeviceDescription Grackle_Descriptor = {
|
||||
|
@ -82,8 +82,6 @@ public:
|
||||
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);
|
||||
|
||||
virtual void pci_interrupt(uint8_t irq_line_state, PCIBase *dev);
|
||||
|
||||
int device_postinit();
|
||||
|
||||
protected:
|
||||
@ -115,14 +113,6 @@ private:
|
||||
uint32_t mem_end[2] = {};
|
||||
uint32_t ext_mem_end[2] = {};
|
||||
uint8_t mem_bank_en = 0;
|
||||
|
||||
// interrupt related stuff
|
||||
InterruptCtrl* int_ctrl = nullptr;
|
||||
uint32_t irq_id_PCI_A = 0;
|
||||
uint32_t irq_id_PCI_B = 0;
|
||||
uint32_t irq_id_PCI_C = 0;
|
||||
uint32_t irq_id_PCI_GPU = 0;
|
||||
uint32_t irq_id_PCI_PERCH = 0;
|
||||
};
|
||||
|
||||
#endif // MPC106_H
|
||||
|
@ -36,6 +36,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <string>
|
||||
|
||||
static std::vector<PciIrqMap> bandit1_irq_map = {
|
||||
{nullptr , DEV_FUN(0x0B,0), IntSrc::BANDIT1},
|
||||
{"pci_A1", DEV_FUN(0x0D,0), IntSrc::PCI_A},
|
||||
{"pci_B1", DEV_FUN(0x0E,0), IntSrc::PCI_B},
|
||||
{"pci_C1", DEV_FUN(0x0F,0), IntSrc::PCI_C},
|
||||
{nullptr , DEV_FUN(0x10,0), }, // GrandCentral
|
||||
};
|
||||
|
||||
int initialize_catalyst(std::string& id)
|
||||
{
|
||||
LOG_F(INFO, "Building machine Catalyst...");
|
||||
@ -43,6 +51,7 @@ int initialize_catalyst(std::string& id)
|
||||
PlatinumCtrl* platinum_obj;
|
||||
|
||||
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Bandit1"));
|
||||
pci_host->set_irq_map(bandit1_irq_map);
|
||||
|
||||
// get (raw) pointer to the I/O controller
|
||||
GrandCentral* gc_obj = dynamic_cast<GrandCentral*>(gMachineObj->get_comp_by_name("GrandCentral"));
|
||||
|
@ -85,16 +85,25 @@ static const map<string, string> PropHelp = {
|
||||
{"cdr_img", "specifies path(s) to CD-ROM image(s)"},
|
||||
{"cdr_img2", "specifies path(s) to secondary CD-ROM image(s)"},
|
||||
{"mon_id", "specifies which monitor to emulate"},
|
||||
{"pci_GPU", "specifies PCI device for Beige G3 grackle device @12"},
|
||||
{"pci_J12", "insert a PCI device into 32-bit 66MHz slot J12"},
|
||||
{"pci_J11", "insert a PCI device into 64-bit 33MHz slot J11"},
|
||||
{"pci_J10", "insert a PCI device into 64-bit 33MHz slot J10"},
|
||||
{"pci_J9", "insert a PCI device into 64-bit 33MHz slot J9"},
|
||||
{"pci_FireWire", "insert a PCI device into PCI slot reserved for Yosemite FireWire"},
|
||||
{"pci_UltraATA", "insert a PCI device into PCI slot reserved for Yosemite Ultra ATA"},
|
||||
{"pci_USB", "insert a PCI device into PCI slot reserved for Yosemite USB"},
|
||||
{"pci_PERCH", "insert a PCI device into PERCH slot"},
|
||||
{"pci_A1", "insert a PCI device into A1 slot"},
|
||||
{"pci_B1", "insert a PCI device into B1 slot"},
|
||||
{"pci_C1", "insert a PCI device into C1 slot"},
|
||||
{"pci_E1", "insert a PCI device into E1 slot"},
|
||||
{"pci_F1", "insert a PCI device into F1 slot"},
|
||||
{"pci_D2", "insert a PCI device into D2 slot"},
|
||||
{"pci_E2", "insert a PCI device into E2 slot"},
|
||||
{"pci_F2", "insert a PCI device into F2 slot"},
|
||||
{"vci_D", "insert a VCI device 0x0D"},
|
||||
{"vci_E", "insert a VCI device 0x0E"},
|
||||
{"vci_F", "insert a VCI device 0x0F"},
|
||||
{"serial_backend", "specifies the backend for the serial port"},
|
||||
{"emmo", "enables/disables factory HW tests during startup"},
|
||||
{"cpu", "specifies CPU"},
|
||||
|
@ -34,6 +34,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <memctrl/memctrlbase.h>
|
||||
#include <loguru.hpp>
|
||||
|
||||
static std::vector<PciIrqMap> psx_irq_map = {
|
||||
{nullptr , DEV_FUN(0x0B,0), IntSrc::BANDIT1},
|
||||
{"pci_A1", DEV_FUN(0x0D,0), IntSrc::PCI_A},
|
||||
{"pci_B1", DEV_FUN(0x0E,0), IntSrc::PCI_B},
|
||||
{"pci_C1", DEV_FUN(0x0F,0), IntSrc::PCI_C},
|
||||
{nullptr , DEV_FUN(0x10,0), }, // OHare
|
||||
{"pci_E1", DEV_FUN(0x11,0), IntSrc::PCI_E},
|
||||
{"pci_F1", DEV_FUN(0x12,0), IntSrc::PCI_F},
|
||||
};
|
||||
|
||||
// TODO: move it to /cpu/ppc
|
||||
int get_cpu_pll_value(const uint64_t cpu_freq_hz) {
|
||||
switch (cpu_freq_hz / 1000000) {
|
||||
@ -53,6 +63,7 @@ int initialize_gazelle(std::string& id)
|
||||
LOG_F(INFO, "Building machine Gazelle...");
|
||||
|
||||
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("PsxPci1"));
|
||||
pci_host->set_irq_map(psx_irq_map);
|
||||
|
||||
// register O'Hare I/O controller with the main PCI bus
|
||||
pci_host->pci_register_device(
|
||||
|
@ -41,6 +41,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
|
||||
static const std::vector<PciIrqMap> grackle_irq_map = {
|
||||
{nullptr , DEV_FUN(0x00,0), }, // Grackle
|
||||
{"pci_PERCH", DEV_FUN(0x0C,0), IntSrc::PCI_PERCH },
|
||||
{"pci_A1" , DEV_FUN(0x0D,0), IntSrc::PCI_A },
|
||||
{"pci_B1" , DEV_FUN(0x0E,0), IntSrc::PCI_B },
|
||||
{"pci_C1" , DEV_FUN(0x0F,0), IntSrc::PCI_C },
|
||||
{nullptr , DEV_FUN(0x10,0), }, // Heathrow
|
||||
{"pci_GPU" , DEV_FUN(0x12,0), IntSrc::PCI_GPU },
|
||||
};
|
||||
|
||||
// Bit definitions for the Gossamer system register at 0xFF000004
|
||||
enum : uint16_t {
|
||||
FDC_TYPE_SWIM3 = (1 << 15), // Macintosh style floppy disk controller
|
||||
@ -96,6 +106,7 @@ int initialize_gossamer(std::string& id)
|
||||
|
||||
// get pointer to the memory controller/PCI host bridge object
|
||||
MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle"));
|
||||
grackle_obj->set_irq_map(grackle_irq_map);
|
||||
|
||||
// configure the Gossamer system register
|
||||
uint16_t sys_reg = FDC_TYPE_SWIM3 | BURST_ROM_TRUE
|
||||
|
@ -33,10 +33,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <machines/machinefactory.h>
|
||||
#include <loguru.hpp>
|
||||
|
||||
static std::vector<PciIrqMap> aspen_irq_map = {
|
||||
// {nullptr , DEV_FUN(0x0B,0), IntSrc::BANDIT1 },
|
||||
// {"pci_A1", DEV_FUN(0x0D,0), IntSrc::PCI_A },
|
||||
{"pci_B1", DEV_FUN(0x0E,0), IntSrc::PIPPIN_E},
|
||||
{"pci_C1", DEV_FUN(0x0F,0), IntSrc::PIPPIN_F},
|
||||
{nullptr , DEV_FUN(0x10,0), }, // GrandCentral
|
||||
};
|
||||
|
||||
int initialize_pippin(std::string& id) {
|
||||
LOG_F(INFO, "Building machine Pippin...");
|
||||
|
||||
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("AspenPci1"));
|
||||
pci_host->set_irq_map(aspen_irq_map);
|
||||
|
||||
// connect GrandCentral I/O controller to the PCI1 bus
|
||||
pci_host->pci_register_device(DEV_FUN(0x10,0),
|
||||
|
@ -35,6 +35,27 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <string>
|
||||
|
||||
static std::vector<PciIrqMap> bandit1_irq_map = {
|
||||
{nullptr , DEV_FUN(0x0B,0), IntSrc::BANDIT1},
|
||||
{"pci_A1", DEV_FUN(0x0D,0), IntSrc::PCI_A},
|
||||
{"pci_B1", DEV_FUN(0x0E,0), IntSrc::PCI_B},
|
||||
{"pci_C1", DEV_FUN(0x0F,0), IntSrc::PCI_C},
|
||||
{nullptr , DEV_FUN(0x10,0), }, // GrandCentral
|
||||
};
|
||||
|
||||
static std::vector<PciIrqMap> bandit2_irq_map = {
|
||||
{nullptr , DEV_FUN(0x0B,0), IntSrc::BANDIT2},
|
||||
{"pci_D2", DEV_FUN(0x0D,0), IntSrc::PCI_D},
|
||||
{"pci_E2", DEV_FUN(0x0E,0), IntSrc::PCI_E},
|
||||
{"pci_F2", DEV_FUN(0x0F,0), IntSrc::PCI_F},
|
||||
};
|
||||
|
||||
static std::vector<PciIrqMap> chaos_irq_map = {
|
||||
{nullptr, DEV_FUN(0x0B,0), IntSrc::CONTROL},
|
||||
{"vci_D", DEV_FUN(0x0D,0), IntSrc::PLANB},
|
||||
{"vci_E", DEV_FUN(0x0E,0), IntSrc::VCI },
|
||||
};
|
||||
|
||||
int initialize_tnt(std::string& id)
|
||||
{
|
||||
LOG_F(INFO, "Building machine TNT...");
|
||||
@ -42,6 +63,7 @@ int initialize_tnt(std::string& id)
|
||||
HammerheadCtrl* memctrl_obj;
|
||||
|
||||
PCIHost *pci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Bandit1"));
|
||||
pci_host->set_irq_map(bandit1_irq_map);
|
||||
|
||||
// get (raw) pointer to the I/O controller
|
||||
GrandCentral* gc_obj = dynamic_cast<GrandCentral*>(gMachineObj->get_comp_by_name("GrandCentral"));
|
||||
@ -53,6 +75,7 @@ int initialize_tnt(std::string& id)
|
||||
// get video PCI controller object
|
||||
PCIHost *vci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Chaos"));
|
||||
if (vci_host) {
|
||||
vci_host->set_irq_map(chaos_irq_map);
|
||||
// connect built-in video device to the VCI bus
|
||||
vci_host->pci_register_device(
|
||||
DEV_FUN(0x0B,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("ControlVideo")));
|
||||
@ -71,6 +94,7 @@ int initialize_tnt(std::string& id)
|
||||
|
||||
PCIHost *pci2_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name_optional("Bandit2"));
|
||||
if (pci2_host) {
|
||||
pci2_host->set_irq_map(bandit2_irq_map);
|
||||
// attach IOBus Device #3 0xF301C000
|
||||
gMachineObj->add_device("BoardReg2", std::unique_ptr<BoardRegister>(
|
||||
new BoardRegister("Board Register 2",
|
||||
|
@ -29,6 +29,23 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <machines/machinefactory.h>
|
||||
#include <machines/machineproperties.h>
|
||||
|
||||
static const std::vector<PciIrqMap> grackle_irq_map = {
|
||||
{nullptr , DEV_FUN(0x00,0) }, // Grackle
|
||||
{nullptr , DEV_FUN(0x0D,0) }, // Dec21154Yosemite
|
||||
{"pci_J12", DEV_FUN(0x10,0), IntSrc::PCI_J12}, // GPU PCI slot, 66 MHz
|
||||
};
|
||||
|
||||
// 33 MHz PCI devices behind the DEC21154 PCI-to-PCI bridge
|
||||
static const std::vector<PciIrqMap> pci_bridge_irq_map = {
|
||||
{"pci_FireWire", DEV_FUN(0x00,0), IntSrc::FIREWIRE},
|
||||
{"pci_UltraATA", DEV_FUN(0x01,0), IntSrc::ATA },
|
||||
{"pci_J11" , DEV_FUN(0x02,0), IntSrc::PCI_J11 },
|
||||
{"pci_J10" , DEV_FUN(0x03,0), IntSrc::PCI_J10 },
|
||||
{"pci_J9" , DEV_FUN(0x04,0), IntSrc::PCI_J9 },
|
||||
{nullptr , DEV_FUN(0x05,0) }, // Heathrow
|
||||
{"pci_USB" , DEV_FUN(0x06,0), IntSrc::USB },
|
||||
};
|
||||
|
||||
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) {
|
||||
if (!capacity_megs)
|
||||
return;
|
||||
@ -48,16 +65,18 @@ int initialize_yosemite(std::string& id)
|
||||
|
||||
// get pointer to the memory controller/primary PCI bridge object
|
||||
MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle"));
|
||||
grackle_obj->set_irq_map(grackle_irq_map);
|
||||
|
||||
// get pointer to the bridge of the secondary PCI bus
|
||||
DecPciBridge *sec_bridge = dynamic_cast<DecPciBridge*>(gMachineObj->get_comp_by_name("Dec21154"));
|
||||
DecPciBridge *sec_bridge = dynamic_cast<DecPciBridge*>(gMachineObj->get_comp_by_name("Dec21154Yosemite"));
|
||||
sec_bridge->set_irq_map(pci_bridge_irq_map);
|
||||
|
||||
// attach PCI devices to the PCI bridges
|
||||
grackle_obj->pci_register_device(DEV_FUN(16,0),
|
||||
dynamic_cast<PCIBase*>(gMachineObj->get_comp_by_name("AtiRage128")));
|
||||
|
||||
grackle_obj->pci_register_device(DEV_FUN(13,0),
|
||||
dynamic_cast<PCIBase*>(gMachineObj->get_comp_by_name("Dec21154")));
|
||||
// 00:0D.0 PCI Bridge
|
||||
grackle_obj->pci_register_device(DEV_FUN(0x0D,0), dynamic_cast<PCIBase*>(sec_bridge));
|
||||
|
||||
// register CMD646U2 PCI Ultra ATA Controller
|
||||
sec_bridge->pci_register_device(DEV_FUN(1,0),
|
||||
@ -66,29 +85,6 @@ int initialize_yosemite(std::string& id)
|
||||
sec_bridge->pci_register_device(DEV_FUN(5,0),
|
||||
dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("Heathrow")));
|
||||
|
||||
InterruptCtrl *int_ctrl_obj =
|
||||
dynamic_cast<InterruptCtrl*>(gMachineObj->get_comp_by_type(HWCompType::INT_CTRL));
|
||||
|
||||
static const std::vector<PciIrqMap> grackle_irq_map = {
|
||||
{"pci_J12", DEV_FUN(0x10,0), 1 << 22} // GPU PCI slot, 66 MHz
|
||||
};
|
||||
|
||||
grackle_obj->set_interrupt_controller(int_ctrl_obj);
|
||||
grackle_obj->set_irq_map(grackle_irq_map);
|
||||
|
||||
// 33 MHz PCI devices behind the DEC21154 PCI-to-PCI bridge
|
||||
static const std::vector<PciIrqMap> pci_bridge_irq_map = {
|
||||
{"pci_FireWire", DEV_FUN(0x00,0), 1 << 21},
|
||||
{"pci_UltraATA", DEV_FUN(0x01,0), 1 << 26},
|
||||
{"pci_J11", DEV_FUN(0x02,0), 1 << 23},
|
||||
{"pci_J10", DEV_FUN(0x03,0), 1 << 24},
|
||||
{"pci_J9", DEV_FUN(0x04,0), 1 << 25},
|
||||
{"pci_USB", DEV_FUN(0x06,0), 1 << 28}
|
||||
};
|
||||
|
||||
sec_bridge->set_interrupt_controller(int_ctrl_obj);
|
||||
sec_bridge->set_irq_map(pci_bridge_irq_map);
|
||||
|
||||
// allocate ROM region
|
||||
if (!grackle_obj->add_rom_region(0xFFF00000, 0x100000)) {
|
||||
LOG_F(ERROR, "Could not allocate ROM region!");
|
||||
@ -132,8 +128,13 @@ static const PropMap yosemite_settings = {
|
||||
};
|
||||
|
||||
static vector<string> yosemite_devices = {
|
||||
"Grackle", "Dec21154", "CmdAta", "BurgundySnd", "Heathrow", "AtaHardDisk",
|
||||
"AtapiCdrom"
|
||||
"Grackle",
|
||||
"Dec21154Yosemite",
|
||||
"CmdAta",
|
||||
"BurgundySnd",
|
||||
"Heathrow",
|
||||
"AtaHardDisk",
|
||||
"AtapiCdrom",
|
||||
};
|
||||
|
||||
static const MachineDescription yosemite_descriptor = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user