pci: generic mapping [O. Galibert]

This commit is contained in:
Olivier Galibert 2014-11-11 20:41:30 +01:00
parent df943244cb
commit 8754f4bbbf
3 changed files with 168 additions and 12 deletions

View File

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

View File

@ -4,21 +4,21 @@ const device_type PCI_ROOT = &device_creator<pci_root_device>;
const device_type PCI_BRIDGE = &device_creator<pci_bridge_device>;
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; i<bank_count; i++) {
bank_info &bi = bank_infos[i];
if(!bi.adr)
continue;
if(UINT32(bi.adr) == UINT32(~(bi.size - 1)))
continue;
UINT64 start;
address_space *space;
if(bi.flags & M_IO) {
space = io_space;
start = bi.adr + io_offset;
} else {
space = memory_space;
start = bi.adr + memory_offset;
}
UINT64 end = start + bi.size-1;
switch(i) {
case 0: space->install_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());
}

View File

@ -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<pci_device *> &all, dynamic_array<pci_device *> &bridges, device_t *root);
void skip_map_regs(int count);
void add_map(UINT64 size, int flags, address_map_delegate &map);
template <typename T> 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<T *>(this));