summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/pci.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/pci.cpp')
-rw-r--r--src/devices/machine/pci.cpp305
1 files changed, 202 insertions, 103 deletions
diff --git a/src/devices/machine/pci.cpp b/src/devices/machine/pci.cpp
index 7148c37ee81..e4c582e29a8 100644
--- a/src/devices/machine/pci.cpp
+++ b/src/devices/machine/pci.cpp
@@ -1,7 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
+/*
+ * References:
+ * - PCI local bus (rev 2.x)
+ * - https://wiki.osdev.org/PCI
+ */
#include "emu.h"
#include "pci.h"
+#include "bus/pci/pci_slot.h"
DEFINE_DEVICE_TYPE(PCI_ROOT, pci_root_device, "pci_root", "PCI virtual root")
DEFINE_DEVICE_TYPE(PCI_BRIDGE, pci_bridge_device, "pci_bridge", "PCI-PCI Bridge")
@@ -72,11 +78,27 @@ pci_device::pci_device(const machine_config &mconfig, device_type type, const ch
revision = 0x00;
pclass = 0xffffff;
subsystem_id = 0xffffffff;
+ expansion_rom = nullptr;
+ expansion_rom_size = 0;
+ expansion_rom_base = 0;
is_multifunction_device = false;
intr_pin = 0x0;
intr_line = 0xff;
+ for(int i=0; i<6; i++) {
+ bank_infos[i].adr = -1;
+ bank_infos[i].size = 0;
+ bank_infos[i].flags = 0;
+ bank_reg_infos[i].bank = -1;
+ bank_reg_infos[i].hi = 0;
+ }
}
+// main_id << 16 = vendor ID ($00-$01)
+// main_id & 0xffff = device ID ($02-$03)
+// revision = board versioning ($08)
+// pclass = programming interface/sub class code/base class code ($09-$0b)
+// subsystem_id << 16 = sub vendor ID ($2c-$2d) - NB: not all cards have these
+// subsystem_id & 0xffff = sub device ID ($2e-$2f) /
void pci_device::set_ids(uint32_t _main_id, uint8_t _revision, uint32_t _pclass, uint32_t _subsystem_id)
{
main_id = _main_id;
@@ -87,33 +109,27 @@ void pci_device::set_ids(uint32_t _main_id, uint8_t _revision, uint32_t _pclass,
void pci_device::device_start()
{
- command = 0x0080;
+ command = 0x0000;
command_mask = 0x01bf;
status = 0x0000;
- for(int i=0; i<6; i++) {
- bank_infos[i].adr = -1;
- bank_infos[i].size = 0;
- bank_infos[i].flags = 0;
- bank_reg_infos[i].bank = -1;
- bank_reg_infos[i].hi = 0;
- }
-
bank_count = 0;
bank_reg_count = 0;
- expansion_rom = nullptr;
- expansion_rom_size = 0;
- expansion_rom_base = 0;
-
- for (int i = 0; i < ARRAY_LENGTH(bank_infos); i++) {
- save_item(NAME(bank_infos[i].adr), i);
- }
+ save_item(STRUCT_MEMBER(bank_infos, adr));
save_item(NAME(command));
save_item(NAME(command_mask));
save_item(NAME(status));
save_item(NAME(intr_line));
save_item(NAME(intr_pin));
+
+ device_t *root = owner();
+ while(root && root->type() != PCI_ROOT)
+ root = root->owner();
+ if(!root)
+ fatalerror("PCI device %s is without a PCI root\n", tag());
+
+ m_pci_root = downcast<pci_root_device *>(root);
}
void pci_device::device_reset()
@@ -131,21 +147,21 @@ void pci_device::unmapped_w(offs_t offset, uint32_t data, uint32_t mem_mask, int
logerror("%s: unmapped write to %08x = %08x & %08x (%s)\n", machine().describe_context(), offset*4, data, mem_mask, bank_infos[bank].map.name());
}
-READ32_MEMBER(pci_device::unmapped0_r) { return unmapped_r(offset, mem_mask, 0); }
-WRITE32_MEMBER(pci_device::unmapped0_w) { return unmapped_w(offset, data, mem_mask, 0); }
-READ32_MEMBER(pci_device::unmapped1_r) { return unmapped_r(offset, mem_mask, 1); }
-WRITE32_MEMBER(pci_device::unmapped1_w) { return unmapped_w(offset, data, mem_mask, 1); }
-READ32_MEMBER(pci_device::unmapped2_r) { return unmapped_r(offset, mem_mask, 2); }
-WRITE32_MEMBER(pci_device::unmapped2_w) { return unmapped_w(offset, data, mem_mask, 2); }
-READ32_MEMBER(pci_device::unmapped3_r) { return unmapped_r(offset, mem_mask, 3); }
-WRITE32_MEMBER(pci_device::unmapped3_w) { return unmapped_w(offset, data, mem_mask, 3); }
-READ32_MEMBER(pci_device::unmapped4_r) { return unmapped_r(offset, mem_mask, 4); }
-WRITE32_MEMBER(pci_device::unmapped4_w) { return unmapped_w(offset, data, mem_mask, 4); }
-READ32_MEMBER(pci_device::unmapped5_r) { return unmapped_r(offset, mem_mask, 5); }
-WRITE32_MEMBER(pci_device::unmapped5_w) { return unmapped_w(offset, data, mem_mask, 5); }
+uint32_t pci_device::unmapped0_r(offs_t offset, uint32_t mem_mask) { return unmapped_r(offset, mem_mask, 0); }
+void pci_device::unmapped0_w(offs_t offset, uint32_t data, uint32_t mem_mask) { return unmapped_w(offset, data, mem_mask, 0); }
+uint32_t pci_device::unmapped1_r(offs_t offset, uint32_t mem_mask) { return unmapped_r(offset, mem_mask, 1); }
+void pci_device::unmapped1_w(offs_t offset, uint32_t data, uint32_t mem_mask) { return unmapped_w(offset, data, mem_mask, 1); }
+uint32_t pci_device::unmapped2_r(offs_t offset, uint32_t mem_mask) { return unmapped_r(offset, mem_mask, 2); }
+void pci_device::unmapped2_w(offs_t offset, uint32_t data, uint32_t mem_mask) { return unmapped_w(offset, data, mem_mask, 2); }
+uint32_t pci_device::unmapped3_r(offs_t offset, uint32_t mem_mask) { return unmapped_r(offset, mem_mask, 3); }
+void pci_device::unmapped3_w(offs_t offset, uint32_t data, uint32_t mem_mask) { return unmapped_w(offset, data, mem_mask, 3); }
+uint32_t pci_device::unmapped4_r(offs_t offset, uint32_t mem_mask) { return unmapped_r(offset, mem_mask, 4); }
+void pci_device::unmapped4_w(offs_t offset, uint32_t data, uint32_t mem_mask) { return unmapped_w(offset, data, mem_mask, 4); }
+uint32_t pci_device::unmapped5_r(offs_t offset, uint32_t mem_mask) { return unmapped_r(offset, mem_mask, 5); }
+void pci_device::unmapped5_w(offs_t offset, uint32_t data, uint32_t mem_mask) { return unmapped_w(offset, data, mem_mask, 5); }
-READ32_MEMBER(pci_device::address_base_r)
+uint32_t pci_device::address_base_r(offs_t offset)
{
if(bank_reg_infos[offset].bank == -1)
return 0;
@@ -156,7 +172,7 @@ READ32_MEMBER(pci_device::address_base_r)
return (bank_infos[bid].adr & ~(bank_infos[bid].size - 1)) | (flags & M_IO ? 1 : 0) | (flags & M_64A ? 4 : 0) | (flags & M_PREF ? 8 : 0);
}
-WRITE32_MEMBER(pci_device::address_base_w)
+void pci_device::address_base_w(offs_t offset, uint32_t data)
{
if(bank_reg_infos[offset].bank == -1) {
logerror("write to address base (%d, %08x) not linked to any bank\n", offset, data);
@@ -172,22 +188,22 @@ WRITE32_MEMBER(pci_device::address_base_w)
remap_cb();
}
-READ16_MEMBER(pci_device::vendor_r)
+uint16_t pci_device::vendor_r()
{
return main_id >> 16;
}
-READ16_MEMBER(pci_device::device_r)
+uint16_t pci_device::device_r()
{
return main_id;
}
-READ16_MEMBER(pci_device::command_r)
+uint16_t pci_device::command_r()
{
return command;
}
-WRITE16_MEMBER(pci_device::command_w)
+void pci_device::command_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
uint16_t old = command;
@@ -198,22 +214,22 @@ WRITE16_MEMBER(pci_device::command_w)
remap_cb();
}
-READ16_MEMBER(pci_device::status_r)
+uint16_t pci_device::status_r()
{
return status;
}
-READ32_MEMBER(pci_device::class_rev_r)
+uint32_t pci_device::class_rev_r()
{
return (pclass << 8) | revision;
}
-READ8_MEMBER(pci_device::cache_line_size_r)
+uint8_t pci_device::cache_line_size_r()
{
return 0x00;
}
-READ8_MEMBER(pci_device::latency_timer_r)
+uint8_t pci_device::latency_timer_r()
{
return 0x00;
}
@@ -223,33 +239,33 @@ void pci_device::set_multifunction_device(bool enable)
is_multifunction_device = enable;
}
-READ8_MEMBER(pci_device::header_type_r)
+uint8_t pci_device::header_type_r()
{
return is_multifunction_device ? 0x80 : 0x00;
}
-READ8_MEMBER(pci_device::bist_r)
+uint8_t pci_device::bist_r()
{
return 0x00;
}
-READ16_MEMBER(pci_device::subvendor_r)
+uint16_t pci_device::subvendor_r()
{
return subsystem_id >> 16;
}
-READ16_MEMBER(pci_device::subsystem_r)
+uint16_t pci_device::subsystem_r()
{
return subsystem_id;
}
-READ32_MEMBER(pci_device::expansion_base_r)
+uint32_t pci_device::expansion_base_r()
{
return expansion_rom_base;
}
-WRITE32_MEMBER(pci_device::expansion_base_w)
+void pci_device::expansion_base_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&expansion_rom_base);
if(!expansion_rom_size)
@@ -261,30 +277,41 @@ WRITE32_MEMBER(pci_device::expansion_base_w)
remap_cb();
}
-READ8_MEMBER(pci_device::capptr_r)
+// if non-zero a CAPability PoinTeR marks an offset in PCI config space where a standard extension is located
+// For example if capptr_r is 0xc0 then [offset+0xc0] has a capability identifier that is set with:
+// bits 31-16 <capability dependant, usually revision and supported sub-features>
+// bits 15-8 next capptr offset, 0x00 to determine the given item as last
+// bits 7-0 capability ID:
+// - 0x01 PMI Power Management Interface
+// - 0x02 AGP Accelerated Graphics Port
+// - 0x03 VPD Vital Product Data
+// - 0x04 Slot Identification
+// - 0x05 MSI Message Signaled Interrupts
+// - 0x06 CompactPCI Hot Swap
+uint8_t pci_device::capptr_r()
{
return 0x00;
}
-READ8_MEMBER(pci_device::interrupt_line_r)
+uint8_t pci_device::interrupt_line_r()
{
logerror("interrupt_line_r = %02x\n", intr_line);
return intr_line;
}
-WRITE8_MEMBER(pci_device::interrupt_line_w)
+void pci_device::interrupt_line_w(offs_t offset, uint8_t data, uint8_t mem_mask)
{
COMBINE_DATA(&intr_line);
logerror("interrupt_line_w %02x\n", data);
}
-READ8_MEMBER(pci_device::interrupt_pin_r)
+uint8_t pci_device::interrupt_pin_r()
{
logerror("interrupt_pin_r = %02x\n", intr_pin);
return intr_pin;
}
-WRITE8_MEMBER(pci_device::interrupt_pin_w)
+void pci_device::interrupt_pin_w(offs_t offset, uint8_t data, uint8_t mem_mask)
{
COMBINE_DATA(&intr_pin);
logerror("interrupt_pin_w = %02x\n", data);
@@ -328,12 +355,12 @@ void pci_device::map_device(uint64_t memory_window_start, uint64_t memory_window
}
uint64_t end = start + bi.size-1;
switch(i) {
- case 0: space->install_readwrite_handler(start, end, read32_delegate(FUNC(pci_device::unmapped0_r), this), write32_delegate(FUNC(pci_device::unmapped0_w), this)); break;
- case 1: space->install_readwrite_handler(start, end, read32_delegate(FUNC(pci_device::unmapped1_r), this), write32_delegate(FUNC(pci_device::unmapped1_w), this)); break;
- case 2: space->install_readwrite_handler(start, end, read32_delegate(FUNC(pci_device::unmapped2_r), this), write32_delegate(FUNC(pci_device::unmapped2_w), this)); break;
- case 3: space->install_readwrite_handler(start, end, read32_delegate(FUNC(pci_device::unmapped3_r), this), write32_delegate(FUNC(pci_device::unmapped3_w), this)); break;
- case 4: space->install_readwrite_handler(start, end, read32_delegate(FUNC(pci_device::unmapped4_r), this), write32_delegate(FUNC(pci_device::unmapped4_w), this)); break;
- case 5: space->install_readwrite_handler(start, end, read32_delegate(FUNC(pci_device::unmapped5_r), this), write32_delegate(FUNC(pci_device::unmapped5_w), this)); break;
+ case 0: space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(pci_device::unmapped0_r)), write32s_delegate(*this, FUNC(pci_device::unmapped0_w))); break;
+ case 1: space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(pci_device::unmapped1_r)), write32s_delegate(*this, FUNC(pci_device::unmapped1_w))); break;
+ case 2: space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(pci_device::unmapped2_r)), write32s_delegate(*this, FUNC(pci_device::unmapped2_w))); break;
+ case 3: space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(pci_device::unmapped3_r)), write32s_delegate(*this, FUNC(pci_device::unmapped3_w))); break;
+ case 4: space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(pci_device::unmapped4_r)), write32s_delegate(*this, FUNC(pci_device::unmapped4_w))); break;
+ case 5: space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(pci_device::unmapped5_r)), write32s_delegate(*this, FUNC(pci_device::unmapped5_w))); break;
}
space->install_device_delegate(start, end, *bi.device, bi.map);
@@ -457,7 +484,7 @@ pci_bridge_device::pci_bridge_device(const machine_config &mconfig, device_type
{
}
-READ8_MEMBER(pci_bridge_device::header_type_r)
+uint8_t pci_bridge_device::header_type_r()
{
return 0x01;
}
@@ -491,13 +518,25 @@ void pci_bridge_device::device_start()
for (device_t &d : bus_root()->subdevices())
{
- const char *t = d.tag();
- int l = strlen(t);
- if(l <= 4 || t[l-5] != ':' || t[l-2] != '.')
- continue;
- int id = strtol(t+l-4, nullptr, 16);
- int fct = t[l-1] - '0';
- sub_devices[(id << 3) | fct] = downcast<pci_device *>(&d);
+ if(d.type() == PCI_SLOT) {
+ pci_slot_device &slot = downcast<pci_slot_device &>(d);
+ pci_device *card = slot.get_card();
+ if(card) {
+ int id = slot.get_slot();
+ sub_devices[id << 3] = card;
+ }
+
+ } else {
+ const char *t = d.tag();
+ int l = strlen(t);
+ if(l <= 4 || t[l-5] != ':' || t[l-2] != '.') {
+ logerror("Device %s unhandled\n", t);
+ continue;
+ }
+ int id = strtol(t+l-4, nullptr, 16);
+ int fct = t[l-1] - '0';
+ sub_devices[(id << 3) | fct] = downcast<pci_device *>(&d);
+ }
}
mapper_cb cf_cb(&pci_bridge_device::regenerate_config_mapping, this);
@@ -526,6 +565,10 @@ void pci_bridge_device::device_reset()
primary_bus = 0x00;
secondary_bus = 0x00;
subordinate_bus = 0x00;
+}
+
+void pci_bridge_device::interface_post_reset()
+{
regenerate_config_mapping();
}
@@ -631,191 +674,191 @@ void pci_bridge_device::config_write(uint8_t bus, uint8_t device, uint16_t reg,
propagate_config_write(bus, device, reg, data, mem_mask);
}
-READ32_MEMBER (pci_bridge_device::b_address_base_r)
+uint32_t pci_bridge_device::b_address_base_r(offs_t offset)
{
logerror("b_address_base_r %d\n", offset);
return 0xffffffff;
}
-WRITE32_MEMBER(pci_bridge_device::b_address_base_w)
+void pci_bridge_device::b_address_base_w(offs_t offset, uint32_t data)
{
logerror("b_address_base_w %d, %08x\n", offset, data);
}
-READ8_MEMBER (pci_bridge_device::primary_bus_r)
+uint8_t pci_bridge_device::primary_bus_r()
{
logerror("primary_bus_r\n");
return primary_bus;
}
-WRITE8_MEMBER (pci_bridge_device::primary_bus_w)
+void pci_bridge_device::primary_bus_w(uint8_t data)
{
primary_bus = data;
logerror("primary_bus_w %02x\n", data);
}
-READ8_MEMBER (pci_bridge_device::secondary_bus_r)
+uint8_t pci_bridge_device::secondary_bus_r()
{
logerror("secondary_bus_r\n");
return secondary_bus;
}
-WRITE8_MEMBER (pci_bridge_device::secondary_bus_w)
+void pci_bridge_device::secondary_bus_w(uint8_t data)
{
secondary_bus = data;
logerror("secondary_bus_w %02x\n", data);
}
-READ8_MEMBER (pci_bridge_device::subordinate_bus_r)
+uint8_t pci_bridge_device::subordinate_bus_r()
{
logerror("subordinate_bus_r\n");
return subordinate_bus;
}
-WRITE8_MEMBER (pci_bridge_device::subordinate_bus_w)
+void pci_bridge_device::subordinate_bus_w(uint8_t data)
{
subordinate_bus = data;
logerror("subordinate_bus_w %02x\n", data);
}
-READ8_MEMBER (pci_bridge_device::secondary_latency_r)
+uint8_t pci_bridge_device::secondary_latency_r()
{
logerror("secondary_latency_r\n");
return 0xff;
}
-WRITE8_MEMBER (pci_bridge_device::secondary_latency_w)
+void pci_bridge_device::secondary_latency_w(uint8_t data)
{
logerror("secondary_latency_w %02x\n", data);
}
-READ8_MEMBER (pci_bridge_device::iobase_r)
+uint8_t pci_bridge_device::iobase_r()
{
return iobase;
}
-WRITE8_MEMBER (pci_bridge_device::iobase_w)
+void pci_bridge_device::iobase_w(uint8_t data)
{
iobase = data;
logerror("iobase_w %02x\n", data);
}
-READ8_MEMBER (pci_bridge_device::iolimit_r)
+uint8_t pci_bridge_device::iolimit_r()
{
return iolimit;
}
-WRITE8_MEMBER (pci_bridge_device::iolimit_w)
+void pci_bridge_device::iolimit_w(uint8_t data)
{
iolimit = data;
logerror("iolimit_w %02x\n", data);
}
-READ16_MEMBER (pci_bridge_device::secondary_status_r)
+uint16_t pci_bridge_device::secondary_status_r()
{
logerror("secondary_status_r\n");
return 0xffff;
}
-WRITE16_MEMBER(pci_bridge_device::secondary_status_w)
+void pci_bridge_device::secondary_status_w(uint16_t data)
{
logerror("secondary_status_w %04x\n", data);
}
-READ16_MEMBER (pci_bridge_device::memory_base_r)
+uint16_t pci_bridge_device::memory_base_r()
{
return memory_base;
}
-WRITE16_MEMBER(pci_bridge_device::memory_base_w)
+void pci_bridge_device::memory_base_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&memory_base);
logerror("memory_base_w %04x\n", memory_base);
}
-READ16_MEMBER (pci_bridge_device::memory_limit_r)
+uint16_t pci_bridge_device::memory_limit_r()
{
return memory_limit;
}
-WRITE16_MEMBER(pci_bridge_device::memory_limit_w)
+void pci_bridge_device::memory_limit_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&memory_limit);
logerror("memory_limit_w %04x\n", memory_limit);
}
-READ16_MEMBER (pci_bridge_device::prefetch_base_r)
+uint16_t pci_bridge_device::prefetch_base_r()
{
return prefetch_base;
}
-WRITE16_MEMBER(pci_bridge_device::prefetch_base_w)
+void pci_bridge_device::prefetch_base_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&prefetch_base);
logerror("prefetch_base_w %04x\n", prefetch_base);
}
-READ16_MEMBER (pci_bridge_device::prefetch_limit_r)
+uint16_t pci_bridge_device::prefetch_limit_r()
{
return prefetch_limit;
}
-WRITE16_MEMBER(pci_bridge_device::prefetch_limit_w)
+void pci_bridge_device::prefetch_limit_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&prefetch_limit);
logerror("prefetch_limit_w %04x\n", prefetch_limit);
}
-READ32_MEMBER (pci_bridge_device::prefetch_baseu_r)
+uint32_t pci_bridge_device::prefetch_baseu_r()
{
return prefetch_baseu;
}
-WRITE32_MEMBER(pci_bridge_device::prefetch_baseu_w)
+void pci_bridge_device::prefetch_baseu_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&prefetch_baseu);
logerror("prefetch_baseu_w %08x\n", prefetch_baseu);
}
-READ32_MEMBER (pci_bridge_device::prefetch_limitu_r)
+uint32_t pci_bridge_device::prefetch_limitu_r()
{
return prefetch_limitu;
}
-WRITE32_MEMBER(pci_bridge_device::prefetch_limitu_w)
+void pci_bridge_device::prefetch_limitu_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&prefetch_limitu);
logerror("prefetch_limitu_w %08x\n", prefetch_limitu);
}
-READ16_MEMBER (pci_bridge_device::iobaseu_r)
+uint16_t pci_bridge_device::iobaseu_r()
{
return iobaseu;
}
-WRITE16_MEMBER(pci_bridge_device::iobaseu_w)
+void pci_bridge_device::iobaseu_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&iobaseu);
logerror("iobaseu_w %04x\n", iobaseu);
}
-READ16_MEMBER (pci_bridge_device::iolimitu_r)
+uint16_t pci_bridge_device::iolimitu_r()
{
return iolimitu;
}
-WRITE16_MEMBER(pci_bridge_device::iolimitu_w)
+void pci_bridge_device::iolimitu_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&iolimitu);
logerror("iolimitu_w %04x\n", iolimitu);
}
-READ16_MEMBER (pci_bridge_device::bridge_control_r)
+uint16_t pci_bridge_device::bridge_control_r()
{
return bridge_control;
}
-WRITE16_MEMBER(pci_bridge_device::bridge_control_w)
+void pci_bridge_device::bridge_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&bridge_control);
logerror("bridge_control_w %04x\n", bridge_control);
@@ -845,6 +888,12 @@ void pci_host_device::io_configuration_access_map(address_map &map)
map(0xcfc, 0xcff).rw(FUNC(pci_host_device::config_data_r), FUNC(pci_host_device::config_data_w));
}
+void pci_host_device::set_spaces(address_space *memory, address_space *io, address_space *busmaster)
+{
+ memory_space = memory;
+ io_space = io ? io : memory;
+ m_pci_root->set_pci_busmaster_space(busmaster ? busmaster : memory);
+}
pci_host_device::pci_host_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: pci_bridge_device(mconfig, type, tag, owner, clock)
@@ -875,11 +924,16 @@ void pci_host_device::device_reset()
{
pci_bridge_device::device_reset();
reset_all_mappings();
- regenerate_mapping();
config_address = 0;
}
+void pci_host_device::interface_post_reset()
+{
+ pci_bridge_device::interface_post_reset();
+ regenerate_mapping();
+}
+
void pci_host_device::regenerate_mapping()
{
logerror("Regenerating mapping\n");
@@ -890,27 +944,59 @@ void pci_host_device::regenerate_mapping()
io_window_start, io_window_end, io_offset, io_space);
}
-READ32_MEMBER(pci_host_device::config_address_r)
+uint32_t pci_host_device::config_address_r()
{
return config_address;
}
-WRITE32_MEMBER(pci_host_device::config_address_w)
+void pci_host_device::config_address_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&config_address);
}
-READ32_MEMBER(pci_host_device::config_data_r)
+uint32_t pci_host_device::config_data_r(offs_t offset, uint32_t mem_mask)
{
return config_address & 0x80000000 ? root_config_read((config_address >> 16) & 0xff, (config_address >> 8) & 0xff, config_address & 0xfc, mem_mask) : 0xffffffff;
}
-WRITE32_MEMBER(pci_host_device::config_data_w)
+void pci_host_device::config_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if(config_address & 0x80000000)
root_config_write((config_address >> 16) & 0xff, (config_address >> 8) & 0xff, config_address & 0xfc, data, mem_mask);
}
+uint32_t pci_host_device::config_data_ex_r(offs_t offset, uint32_t mem_mask)
+{
+ // is this a Type 0 or Type 1 configuration address? (page 31, PCI 2.2 Specification)
+ if ((config_address & 3) == 0)
+ {
+ const int devnum = 31 - count_leading_zeros_32(config_address & 0xfffff800);
+ return root_config_read(0, devnum << 3, config_address & 0xfc, mem_mask);
+ }
+ else if ((config_address & 3) == 1)
+ return config_address & 0x80000000 ? root_config_read((config_address >> 16) & 0xff, (config_address >> 8) & 0xff, config_address & 0xfc, mem_mask) : 0xffffffff;
+
+ logerror("pci: configuration address format %d unsupported", config_address & 3);
+ return 0xffffffff;
+}
+
+void pci_host_device::config_data_ex_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ // is this a Type 0 or Type 1 configuration address? (page 31, PCI 2.2 Specification)
+ if ((config_address & 3) == 0)
+ {
+ const int devnum = 31 - count_leading_zeros_32(config_address & 0xfffff800);
+ root_config_write(0, devnum << 3, config_address & 0xfc, data, mem_mask);
+ }
+ else if ((config_address & 3) == 1)
+ {
+ if (config_address & 0x80000000)
+ root_config_write((config_address >> 16) & 0xff, (config_address >> 8) & 0xff, config_address & 0xfc, data, mem_mask);
+ }
+ else
+ logerror("pci: configuration address format %d unsupported", config_address & 3);
+}
+
uint32_t pci_host_device::root_config_read(uint8_t bus, uint8_t device, uint16_t reg, uint32_t mem_mask)
{
if(bus == 0x00)
@@ -930,7 +1016,10 @@ void pci_host_device::root_config_write(uint8_t bus, uint8_t device, uint16_t re
pci_root_device::pci_root_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, PCI_ROOT, tag, owner, clock)
+ : device_t(mconfig, PCI_ROOT, tag, owner, clock),
+ m_pin_mapper(*this),
+ m_irq_handler(*this),
+ m_pci_busmaster_space(nullptr)
{
}
@@ -941,3 +1030,13 @@ void pci_root_device::device_start()
void pci_root_device::device_reset()
{
}
+
+void pci_root_device::irq_pin_w(int pin, int state)
+{
+ m_irq_handler(m_pin_mapper(pin), state);
+}
+
+void pci_root_device::irq_w(int line, int state)
+{
+ m_irq_handler(line, state);
+}