xbox_pci.cpp: smbus controller actually supports two buses (nw)

This commit is contained in:
yz70s 2019-03-16 14:38:44 +01:00
parent a5d6b7c5b8
commit 6605110fad
3 changed files with 64 additions and 35 deletions

View File

@ -119,8 +119,10 @@ public:
auto interrupt_handler() { return m_interrupt_handler.bind(); }
DECLARE_READ32_MEMBER(smbus_r);
DECLARE_WRITE32_MEMBER(smbus_w);
DECLARE_READ32_MEMBER(smbus0_r);
DECLARE_WRITE32_MEMBER(smbus0_w);
DECLARE_READ32_MEMBER(smbus1_r);
DECLARE_WRITE32_MEMBER(smbus1_w);
protected:
virtual void device_start() override;
@ -137,10 +139,12 @@ private:
int rw;
smbus_interface *devices[128];
uint32_t words[256 / 4];
} smbusst;
} smbusst[2];
void smbus_io0(address_map &map);
void smbus_io1(address_map &map);
void smbus_io2(address_map &map);
uint32_t smbus_read(int bus, offs_t offset, uint32_t mem_mask);
void smbus_write(int bus, offs_t offset, uint32_t data, uint32_t mem_mask);
};
DECLARE_DEVICE_TYPE(MCPX_SMBUS, mcpx_smbus_device)

View File

@ -853,9 +853,9 @@ void xbox_base_state::xbox_base(machine_config &config)
NV2A_RAM(config, ":pci:00.3", 0);
MCPX_ISALPC(config, ":pci:01.0", 0, 0).interrupt_output().set(FUNC(xbox_base_state::maincpu_interrupt));
MCPX_SMBUS(config, ":pci:01.1", 0).interrupt_handler().set(FUNC(xbox_base_state::smbus_interrupt_changed));
XBOX_PIC16LC(config, ":pci:01.1:10", 0);
XBOX_CX25871(config, ":pci:01.1:45", 0);
XBOX_EEPROM(config, ":pci:01.1:54", 0);
XBOX_PIC16LC(config, ":pci:01.1:110", 0); // these 3 are on smbus number 1
XBOX_CX25871(config, ":pci:01.1:145", 0);
XBOX_EEPROM(config, ":pci:01.1:154", 0);
MCPX_OHCI(config, ":pci:02.0", 0).interrupt_handler().set(FUNC(xbox_base_state::ohci_usb_interrupt_changed));
MCPX_OHCI(config, ":pci:03.0", 0);
MCPX_ETH(config, ":pci:04.0", 0);

View File

@ -291,12 +291,12 @@ DEFINE_DEVICE_TYPE(MCPX_SMBUS, mcpx_smbus_device, "mcpx_smbus", "MCPX SMBus Cont
void mcpx_smbus_device::smbus_io0(address_map &map)
{
map(0x00000000, 0x0000000f).noprw();
map(0x00000000, 0x0000000f).rw(FUNC(mcpx_smbus_device::smbus0_r), FUNC(mcpx_smbus_device::smbus0_w));
}
void mcpx_smbus_device::smbus_io1(address_map &map)
{
map(0x00000000, 0x0000000f).rw(FUNC(mcpx_smbus_device::smbus_r), FUNC(mcpx_smbus_device::smbus_w));
map(0x00000000, 0x0000000f).rw(FUNC(mcpx_smbus_device::smbus1_r), FUNC(mcpx_smbus_device::smbus1_w));
}
void mcpx_smbus_device::smbus_io2(address_map &map)
@ -322,8 +322,9 @@ void mcpx_smbus_device::device_start()
add_map(0x00000020, M_IO, FUNC(mcpx_smbus_device::smbus_io2));
bank_infos[2].adr = 0xc200;
memset(&smbusst, 0, sizeof(smbusst));
for (int n = 0; n < 128; n++)
smbusst.devices[n] = nullptr;
for (int b = 0; b < 2; b++)
for (int a = 0; a < 128; a++)
smbusst[b].devices[a] = nullptr;
for (device_t &d : subdevices())
{
const char *t = d.tag();
@ -336,12 +337,16 @@ void mcpx_smbus_device::device_start()
{
l++;
int address = strtol(t + l, nullptr, 16);
if ((address > 0) && (address < 128))
int bus;
bus = address >> 8;
address = address & 0xff;
if ((address > 0) && (address < 128) && (bus >= 0) && (bus <= 1))
{
if (smbusst.devices[address] == nullptr)
if (smbusst[bus].devices[address] == nullptr)
{
smbus_interface *i = dynamic_cast<smbus_interface *>(&d);
smbusst.devices[address] = i;
smbusst[bus].devices[address] = i;
}
else
logerror("Duplicate address for SMBus device with tag %s\n", t);
@ -359,44 +364,44 @@ void mcpx_smbus_device::device_reset()
pci_device::device_reset();
}
READ32_MEMBER(mcpx_smbus_device::smbus_r)
uint32_t mcpx_smbus_device::smbus_read(int bus, offs_t offset, uint32_t mem_mask)
{
if (offset == 0) // 0 smbus status
smbusst.words[offset] = (smbusst.words[offset] & ~0xffff) | ((smbusst.status & 0xffff) << 0);
smbusst[bus].words[offset] = (smbusst[bus].words[offset] & ~0xffff) | ((smbusst[bus].status & 0xffff) << 0);
if (offset == 1) // 6 smbus data
smbusst.words[offset] = (smbusst.words[offset] & ~(0xffff << 16)) | ((smbusst.data & 0xffff) << 16);
return smbusst.words[offset];
smbusst[bus].words[offset] = (smbusst[bus].words[offset] & ~(0xffff << 16)) | ((smbusst[bus].data & 0xffff) << 16);
return smbusst[bus].words[offset];
}
WRITE32_MEMBER(mcpx_smbus_device::smbus_w)
void mcpx_smbus_device::smbus_write(int bus, offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(smbusst.words);
COMBINE_DATA(smbusst[bus].words);
if ((offset == 0) && (ACCESSING_BITS_0_7 || ACCESSING_BITS_8_15)) // 0 smbus status
{
if (!((smbusst.status ^ data) & 0x10)) // clearing interrupt
if (!((smbusst[bus].status ^ data) & 0x10)) // clearing interrupt
{
if (m_interrupt_handler)
m_interrupt_handler(0);
}
smbusst.status &= ~data;
smbusst[bus].status &= ~data;
}
if ((offset == 0) && ACCESSING_BITS_16_23) // 2 smbus control
{
data = data >> 16;
smbusst.control = data;
int cycletype = smbusst.control & 7;
if (smbusst.control & 8) { // start
smbusst[bus].control = data;
int cycletype = smbusst[bus].control & 7;
if (smbusst[bus].control & 8) { // start
if ((cycletype & 6) == 2)
{
if (smbusst.devices[smbusst.address])
if (smbusst.rw == 0)
smbusst.devices[smbusst.address]->execute_command(smbusst.command, smbusst.rw, smbusst.data);
if (smbusst[bus].devices[smbusst[bus].address])
if (smbusst[bus].rw == 0)
smbusst[bus].devices[smbusst[bus].address]->execute_command(smbusst[bus].command, smbusst[bus].rw, smbusst[bus].data);
else
smbusst.data = smbusst.devices[smbusst.address]->execute_command(smbusst.command, smbusst.rw, smbusst.data);
smbusst[bus].data = smbusst[bus].devices[smbusst[bus].address]->execute_command(smbusst[bus].command, smbusst[bus].rw, smbusst[bus].data);
else
logerror("SMBUS: access to missing device at address %d\n", smbusst.address);
smbusst.status |= 0x10;
if (smbusst.control & 0x10)
logerror("SMBUS: access to missing device at bus %d address %d\n", bus, smbusst[bus].address);
smbusst[bus].status |= 0x10;
if (smbusst[bus].control & 0x10)
{
if (m_interrupt_handler)
m_interrupt_handler(1);
@ -406,16 +411,36 @@ WRITE32_MEMBER(mcpx_smbus_device::smbus_w)
}
if ((offset == 1) && ACCESSING_BITS_0_7) // 4 smbus address
{
smbusst.address = data >> 1;
smbusst.rw = data & 1;
smbusst[bus].address = data >> 1;
smbusst[bus].rw = data & 1;
}
if ((offset == 1) && (ACCESSING_BITS_16_23 || ACCESSING_BITS_16_31)) // 6 smbus data
{
data = data >> 16;
smbusst.data = data;
smbusst[bus].data = data;
}
if ((offset == 2) && ACCESSING_BITS_0_7) // 8 smbus command
smbusst.command = data;
smbusst[bus].command = data;
}
READ32_MEMBER(mcpx_smbus_device::smbus0_r)
{
return smbus_read(0, offset, mem_mask);
}
WRITE32_MEMBER(mcpx_smbus_device::smbus0_w)
{
smbus_write(0, offset, data, mem_mask);
}
READ32_MEMBER(mcpx_smbus_device::smbus1_r)
{
return smbus_read(1, offset, mem_mask);
}
WRITE32_MEMBER(mcpx_smbus_device::smbus1_w)
{
smbus_write(1, offset, data, mem_mask);
}
/*