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:
joevt 2024-04-15 14:00:32 -07:00 committed by dingusdev
parent e707d1f27a
commit e7eb1c8a66
24 changed files with 251 additions and 146 deletions

View File

@ -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 = {

View File

@ -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

View File

@ -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. */

View File

@ -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 = {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 = {

View File

@ -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

View File

@ -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"));

View File

@ -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"},

View File

@ -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(

View File

@ -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

View File

@ -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),

View File

@ -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",

View File

@ -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 = {