From 8754f4bbbf00da701b0c47850218c0312885af23 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Tue, 11 Nov 2014 20:41:30 +0100 Subject: [PATCH] pci: generic mapping [O. Galibert] --- src/emu/machine/pci-smbus.c | 1 + src/emu/machine/pci.c | 144 +++++++++++++++++++++++++++++++++--- src/emu/machine/pci.h | 35 +++++++++ 3 files changed, 168 insertions(+), 12 deletions(-) diff --git a/src/emu/machine/pci-smbus.c b/src/emu/machine/pci-smbus.c index bc631951808..bf03c79210a 100644 --- a/src/emu/machine/pci-smbus.c +++ b/src/emu/machine/pci-smbus.c @@ -13,6 +13,7 @@ smbus_device::smbus_device(const machine_config &mconfig, const char *tag, devic void smbus_device::device_start() { pci_device::device_start(); + skip_map_regs(4); add_map(32, M_IO, FUNC(smbus_device::map)); } diff --git a/src/emu/machine/pci.c b/src/emu/machine/pci.c index 13ae0cd26a2..4faf56b79ff 100644 --- a/src/emu/machine/pci.c +++ b/src/emu/machine/pci.c @@ -4,21 +4,21 @@ const device_type PCI_ROOT = &device_creator; const device_type PCI_BRIDGE = &device_creator; DEVICE_ADDRESS_MAP_START(config_map, 32, pci_device) - AM_RANGE(0x00, 0x03) AM_READ16 (vendor_r, 0x0000ffff) - AM_RANGE(0x00, 0x03) AM_READ16 (device_r, 0xffff0000) - AM_RANGE(0x04, 0x07) AM_READWRITE16(command_r, command_w, 0x0000ffff) - AM_RANGE(0x04, 0x07) AM_READ16 (status_r, 0xffff0000) - + AM_RANGE(0x00, 0x03) AM_READ16 (vendor_r, 0x0000ffff) + AM_RANGE(0x00, 0x03) AM_READ16 (device_r, 0xffff0000) + AM_RANGE(0x04, 0x07) AM_READWRITE16(command_r, command_w, 0x0000ffff) + AM_RANGE(0x04, 0x07) AM_READ16 (status_r, 0xffff0000) AM_RANGE(0x08, 0x0b) AM_READ (class_rev_r) - AM_RANGE(0x0c, 0x0f) AM_READ8 (cache_line_size_r, 0x000000ff) - AM_RANGE(0x0c, 0x0f) AM_READ8 (latency_timer_r, 0x0000ff00) - AM_RANGE(0x0c, 0x0f) AM_READ8 (header_type_r, 0x00ff0000) - AM_RANGE(0x0c, 0x0f) AM_READ8 (bist_r, 0xff000000) + AM_RANGE(0x0c, 0x0f) AM_READ8 (cache_line_size_r, 0x000000ff) + AM_RANGE(0x0c, 0x0f) AM_READ8 (latency_timer_r, 0x0000ff00) + AM_RANGE(0x0c, 0x0f) AM_READ8 (header_type_r, 0x00ff0000) + AM_RANGE(0x0c, 0x0f) AM_READ8 (bist_r, 0xff000000) + AM_RANGE(0x10, 0x27) AM_READWRITE (address_base_r, address_base_w) - AM_RANGE(0x2c, 0x2f) AM_READ16 (subvendor_r, 0x0000ffff) - AM_RANGE(0x2c, 0x2f) AM_READ16 (subsystem_r, 0xffff0000) + AM_RANGE(0x2c, 0x2f) AM_READ16 (subvendor_r, 0x0000ffff) + AM_RANGE(0x2c, 0x2f) AM_READ16 (subsystem_r, 0xffff0000) - AM_RANGE(0x34, 0x37) AM_READ8 (capptr_r, 0x000000ff) + AM_RANGE(0x34, 0x37) AM_READ8 (capptr_r, 0x000000ff) ADDRESS_MAP_END pci_device::pci_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) @@ -43,12 +43,76 @@ void pci_device::device_start() command = 0x0080; command_mask = 0x01bf; status = 0x0000; + + for(int i=0; i<6; i++) { + bank_infos[i].adr = 0; + 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; } void pci_device::device_reset() { } +UINT32 pci_device::unmapped_r(offs_t offset, UINT32 mem_mask, int bank) +{ + logerror("%s: unmapped read from %08x & %08x (%s)\n", machine().describe_context(), offset*4, mem_mask, bank_infos[bank].map.name()); + return 0; +} + +void pci_device::unmapped_w(offs_t offset, UINT32 data, UINT32 mem_mask, int bank) +{ + 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); } + + +READ32_MEMBER(pci_device::address_base_r) +{ + if(bank_reg_infos[offset].bank == -1) + return 0; + int bid = bank_reg_infos[offset].bank; + if(bank_reg_infos[offset].hi) + return bank_infos[bid].adr >> 32; + int flags = bank_infos[bid].flags; + return bank_infos[bid].adr | (flags & M_IO ? 1 : 0) | (flags & M_64A ? 4 : 0) | (flags & M_PREF ? 8 : 0); +} + +WRITE32_MEMBER(pci_device::address_base_w) +{ + if(bank_reg_infos[offset].bank == -1) { + logerror("%s: write to address base (%d, %08x) not linked to any bank\n", tag(), offset, data); + return; + } + + int bid = bank_reg_infos[offset].bank; + if(bank_reg_infos[offset].hi) + bank_infos[bid].adr = (bank_infos[bid].adr & 0xffffffff) | (UINT64(data) << 32); + else { + data &= ~(bank_infos[bid].size - 1); + bank_infos[bid].adr = (bank_infos[bid].adr & U64(0xffffffff00000000)) | data; + } + remap_cb(); +} + READ16_MEMBER(pci_device::vendor_r) { return main_id >> 16; @@ -132,6 +196,34 @@ void pci_device::reset_all_mappings() void pci_device::map_device(UINT64 memory_window_start, UINT64 memory_window_end, UINT64 memory_offset, address_space *memory_space, UINT64 io_window_start, UINT64 io_window_end, UINT64 io_offset, address_space *io_space) { + for(int i=0; iinstall_readwrite_handler(start, end, 0, 0, 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, 0, 0, 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, 0, 0, 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, 0, 0, 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, 0, 0, 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, 0, 0, read32_delegate(FUNC(pci_device::unmapped5_r), this), write32_delegate(FUNC(pci_device::unmapped5_w), this)); break; + } + space->install_device_delegate(start, end, *this, bi.map); + } + map_extra(memory_window_start, memory_window_end, memory_offset, memory_space, io_window_start, io_window_end, io_offset, io_space); } @@ -146,8 +238,36 @@ void pci_device::map_config(UINT8 device, address_space *config_space) config_space->install_device(device << 12, (device << 12) | 0xfff, *this, &pci_device::config_map); } +void pci_device::skip_map_regs(int count) +{ + bank_reg_count += count; + assert(bank_reg_count <= 6); +} + void pci_device::add_map(UINT64 size, int flags, address_map_delegate &map) { + assert(bank_count < 6); + int bid = bank_count++; + bank_infos[bid].map = map; + bank_infos[bid].adr = 0; + bank_infos[bid].size = size; + bank_infos[bid].flags = flags; + + if(flags & M_64A) { + assert(bank_reg_count < 5); + int breg = bank_reg_count; + bank_reg_infos[breg].bank = bid; + bank_reg_infos[breg].hi = 0; + bank_reg_infos[breg+1].bank = bid; + bank_reg_infos[breg+1].hi = 1; + bank_reg_count += 2; + } else { + assert(bank_reg_count < 6); + int breg = bank_reg_count++; + bank_reg_infos[breg].bank = bid; + bank_reg_infos[breg].hi = 0; + } + logerror("Device %s (%s) has 0x%" I64FMT "x bytes of %s named %s\n", tag(), name(), size, flags & M_IO ? "io" : "memory", map.name()); } diff --git a/src/emu/machine/pci.h b/src/emu/machine/pci.h index 456a15b672e..ea6d861311c 100644 --- a/src/emu/machine/pci.h +++ b/src/emu/machine/pci.h @@ -43,6 +43,23 @@ public: virtual DECLARE_ADDRESS_MAP(config_map, 32); + UINT32 unmapped_r(offs_t offset, UINT32 mem_mask, int bank); + void unmapped_w(offs_t offset, UINT32 data, UINT32 mem_mask, int bank); + + READ32_MEMBER (unmapped0_r); + WRITE32_MEMBER(unmapped0_w); + READ32_MEMBER (unmapped1_r); + WRITE32_MEMBER(unmapped1_w); + READ32_MEMBER (unmapped2_r); + WRITE32_MEMBER(unmapped2_w); + READ32_MEMBER (unmapped3_r); + WRITE32_MEMBER(unmapped3_w); + READ32_MEMBER (unmapped4_r); + WRITE32_MEMBER(unmapped4_w); + READ32_MEMBER (unmapped5_r); + WRITE32_MEMBER(unmapped5_w); + + DECLARE_READ16_MEMBER(vendor_r); DECLARE_READ16_MEMBER(device_r); DECLARE_READ16_MEMBER(command_r); @@ -53,6 +70,8 @@ public: virtual DECLARE_READ8_MEMBER(latency_timer_r); virtual DECLARE_READ8_MEMBER(header_type_r); virtual DECLARE_READ8_MEMBER(bist_r); + DECLARE_READ32_MEMBER(address_base_r); + DECLARE_WRITE32_MEMBER(address_base_w); DECLARE_READ16_MEMBER(subvendor_r); DECLARE_READ16_MEMBER(subsystem_r); virtual DECLARE_READ8_MEMBER(capptr_r); @@ -66,6 +85,21 @@ protected: M_PREF = 8 }; + struct bank_info { + address_map_delegate map; + UINT64 adr; + UINT32 size; + int flags; + }; + + struct bank_reg_info { + int bank, hi; + }; + + bank_info bank_infos[6]; + int bank_count, bank_reg_count; + bank_reg_info bank_reg_infos[6]; + UINT32 main_id, subsystem_id; UINT32 pclass; UINT8 revision; @@ -76,6 +110,7 @@ protected: static void scan_sub_devices(pci_device **devices, dynamic_array &all, dynamic_array &bridges, device_t *root); + void skip_map_regs(int count); void add_map(UINT64 size, int flags, address_map_delegate &map); template void add_map(UINT64 size, int flags, void (T::*map)(address_map &map, device_t &device), const char *name) { address_map_delegate delegate(map, name, static_cast(this));