From 8d28538134cd8415ab3e27f4663793fdd3bd9d55 Mon Sep 17 00:00:00 2001 From: yz70s Date: Thu, 4 Oct 2018 15:32:05 +0200 Subject: [PATCH] xbox: first step in using real devices with smbus (nw) --- src/mame/drivers/chihiro.cpp | 3 +- src/mame/drivers/xbox.cpp | 3 +- src/mame/includes/xbox.h | 66 +++++++++- src/mame/includes/xbox_pci.h | 8 +- src/mame/machine/xbox.cpp | 242 ++++++++++++++++++++-------------- src/mame/machine/xbox_pci.cpp | 37 +++++- src/mame/machine/xbox_usb.cpp | 2 + 7 files changed, 256 insertions(+), 105 deletions(-) diff --git a/src/mame/drivers/chihiro.cpp b/src/mame/drivers/chihiro.cpp index fc410064974..32beb7c23ae 100644 --- a/src/mame/drivers/chihiro.cpp +++ b/src/mame/drivers/chihiro.cpp @@ -374,8 +374,9 @@ Thanks to Alex, Mr Mudkips, and Philip Burke for this info. */ #include "emu.h" -#include "includes/xbox.h" +#include "machine/pci.h" #include "includes/xbox_pci.h" +#include "includes/xbox.h" #include "cpu/i386/i386.h" #include "machine/idehd.h" diff --git a/src/mame/drivers/xbox.cpp b/src/mame/drivers/xbox.cpp index fa93e2c975a..1822dbe3419 100644 --- a/src/mame/drivers/xbox.cpp +++ b/src/mame/drivers/xbox.cpp @@ -10,8 +10,9 @@ #include "emu.h" -#include "includes/xbox.h" +#include "machine/pci.h" #include "includes/xbox_pci.h" +#include "includes/xbox.h" #include "cpu/i386/i386.h" #include "machine/atapicdr.h" diff --git a/src/mame/includes/xbox.h b/src/mame/includes/xbox.h index 26388e6e159..47910468c2e 100644 --- a/src/mame/includes/xbox.h +++ b/src/mame/includes/xbox.h @@ -10,7 +10,70 @@ #include "machine/idectrl.h" #include "machine/pic8259.h" -#include "machine/pci.h" + +/* + * PIC16LC connected to SMBus + */ + +class xbox_pic16lc_device : public device_t, public smbus_interface +{ +public: + xbox_pic16lc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual int execute_command(int command, int rw, int data) override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + +private: + uint8_t buffer[0xff]; +}; + +DECLARE_DEVICE_TYPE(XBOX_PIC16LC, xbox_pic16lc_device) + +/* + * CX25871 connected to SMBus + */ + +class xbox_cx25871_device : public device_t, public smbus_interface +{ +public: + xbox_cx25871_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual int execute_command(int command, int rw, int data) override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + +private: +}; + +DECLARE_DEVICE_TYPE(XBOX_CX25871, xbox_cx25871_device) + +/* + * EEPROM connected to SMBus + */ + +class xbox_eeprom_device : public device_t, public smbus_interface +{ +public: + xbox_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual int execute_command(int command, int rw, int data) override; + + std::function hack_eeprom; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + +private: +}; + +DECLARE_DEVICE_TYPE(XBOX_EEPROM, xbox_eeprom_device) + +/* + * Base + */ class xbox_base_state : public driver_device { @@ -63,7 +126,6 @@ protected: int selected; uint8_t registers[16][256]; // 256 registers for up to 16 devices, registers 0-0x2f common to all } superiost; - uint8_t pic16lc_buffer[0xff]; nv2a_renderer *nvidia_nv2a; bool debug_irq_active; int debug_irq_number; diff --git a/src/mame/includes/xbox_pci.h b/src/mame/includes/xbox_pci.h index 7d4f69dfd62..d1488cb0c37 100644 --- a/src/mame/includes/xbox_pci.h +++ b/src/mame/includes/xbox_pci.h @@ -78,10 +78,14 @@ DECLARE_DEVICE_TYPE(MCPX_LPC, mcpx_lpc_device) * SMBus */ +class smbus_interface { +public: + virtual int execute_command(int command, int rw, int data) = 0; +}; + class mcpx_smbus_device : public pci_device { public: mcpx_smbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void register_device(int address, std::function callback) { if (address < 128) smbusst.devices[address] = callback; } template devcb_base &set_interrupt_handler(Object &&cb) { return m_interrupt_handler.set_callback(std::forward(cb)); } @@ -101,7 +105,7 @@ private: int data; int command; int rw; - std::function devices[128]; + smbus_interface *devices[128]; uint32_t words[256 / 4]; } smbusst; void smbus_io0(address_map &map); diff --git a/src/mame/machine/xbox.cpp b/src/mame/machine/xbox.cpp index 2e2bc7bdaa2..83fa5549c52 100644 --- a/src/mame/machine/xbox.cpp +++ b/src/mame/machine/xbox.cpp @@ -2,8 +2,9 @@ // copyright-holders:Samuele Zannoli #include "emu.h" -#include "includes/xbox.h" +#include "machine/pci.h" #include "includes/xbox_pci.h" +#include "includes/xbox.h" #include "cpu/i386/i386.h" #include "machine/pit8253.h" @@ -389,7 +390,8 @@ void xbox_base_state::grab_vprog_command(int ref, const std::vector return; if ((fil = fopen(params[1].c_str(), "wb")) == nullptr) return; - for (int n = 0; n < 136; n++) { + for (int n = 0; n < 136; n++) + { nvidia_nv2a->debug_grab_vertex_program_slot(n, instruction); fwrite(instruction, sizeof(uint32_t), 4, fil); } @@ -635,72 +637,6 @@ WRITE_LINE_MEMBER(xbox_base_state::xbox_nv2a_interrupt_changed) xbox_base_devs.pic8259_1->ir3_w(state); } -/* - * SMbus devices - */ - -int xbox_base_state::smbus_pic16lc(int command, int rw, int data) -{ - if (rw == 1) { // read - if (command == 0) { - if (pic16lc_buffer[0] == 'D') - pic16lc_buffer[0] = 'X'; - else if (pic16lc_buffer[0] == 'X') - pic16lc_buffer[0] = 'B'; - else if (pic16lc_buffer[0] == 'B') - pic16lc_buffer[0] = 'D'; - } - logerror("pic16lc: %d %d %d\n", command, rw, pic16lc_buffer[command]); - return pic16lc_buffer[command]; - } - else - if (command == 0) - pic16lc_buffer[0] = 'B'; - else - pic16lc_buffer[command] = (uint8_t)data; - logerror("pic16lc: %d %d %d\n", command, rw, data); - return 0; -} - -int xbox_base_state::smbus_cx25871(int command, int rw, int data) -{ - logerror("cx25871: %d %d %d\n", command, rw, data); - return 0; -} - -// let's try to fake the missing eeprom, make sure its ntsc, otherwise chihiro will show an error -static int dummyeeprom[256] = { - 0x39, 0xe3, 0xcc, 0x81, 0xb0, 0xa9, 0x97, 0x09, 0x57, 0xac, 0x57, 0x12, 0xf7, 0xc2, 0xc0, 0x21, 0xce, 0x0d, 0x0a, 0xdb, 0x20, 0x7a, 0xf3, 0xff, - 0xdf, 0x67, 0xed, 0xf4, 0xf8, 0x95, 0x5c, 0xd0, 0x9b, 0xef, 0x7b, 0x81, 0xda, 0xd5, 0x98, 0xc1, 0xb1, 0xb3, 0x74, 0x18, 0x86, 0x05, 0xe2, 0x7c, - 0xd1, 0xad, 0xc9, 0x90, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x00, 0x00, - 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0xab, 0xcd, 0xef, 0xba, 0xdc, 0xfe, 0xa1, 0xb2, 0xc3, 0xd3, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -int xbox_base_state::smbus_eeprom(int command, int rw, int data) -{ - if (command >= 112) - return 0; - if (rw == 1) { // if reading - // hack to avoid hanging if eeprom contents are not correct - // this would need dumping the serial eeprom on the xbox board - if (command == 0) { - hack_eeprom(); - } - data = dummyeeprom[command] + dummyeeprom[command + 1] * 256; - logerror("eeprom: %d %d %d\n", command, rw, data); - return data; - } - logerror("eeprom: %d %d %d\n", command, rw, data); - dummyeeprom[command] = data; - return 0; -} - /* * SuperIO */ @@ -772,37 +708,144 @@ WRITE8_MEMBER(xbox_base_state::superiors232_write) } } +/* + * SMbus devices + */ + +/* + * PIC16LC + */ + +DEFINE_DEVICE_TYPE(XBOX_PIC16LC, xbox_pic16lc_device, "pic16lc", "XBOX PIC16LC") + +xbox_pic16lc_device::xbox_pic16lc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, XBOX_PIC16LC, tag, owner, clock) +{ +} + +int xbox_pic16lc_device::execute_command(int command, int rw, int data) +{ + if (rw == 1) { // read + if (command == 0) + { + if (buffer[0] == 'D') + buffer[0] = 'X'; + else if (buffer[0] == 'X') + buffer[0] = 'B'; + else if (buffer[0] == 'B') + buffer[0] = 'D'; + } + logerror("pic16lc: %d %d %d\n", command, rw, buffer[command]); + return buffer[command]; + } + else + if (command == 0) + buffer[0] = 'B'; + else + buffer[command] = (uint8_t)data; + logerror("pic16lc: %d %d %d\n", command, rw, data); + return 0; +} + +void xbox_pic16lc_device::device_start() +{ + memset(buffer, 0, sizeof(buffer)); + buffer[0] = 'B'; + buffer[4] = 0; // A/V connector, 0=scart 2=vga 4=svideo 7=none + // PIC challenge handshake data + buffer[0x1c] = 0x0c; + buffer[0x1d] = 0x0d; + buffer[0x1e] = 0x0e; + buffer[0x1f] = 0x0f; +} + +void xbox_pic16lc_device::device_reset() +{ +} + +/* + * CX25871 + */ + +DEFINE_DEVICE_TYPE(XBOX_CX25871, xbox_cx25871_device, "cx25871", "XBOX CX25871") + +xbox_cx25871_device::xbox_cx25871_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, XBOX_CX25871, tag, owner, clock) +{ +} + +int xbox_cx25871_device::execute_command(int command, int rw, int data) +{ + logerror("cx25871: %d %d %d\n", command, rw, data); + return 0; +} + +void xbox_cx25871_device::device_start() +{ +} + +void xbox_cx25871_device::device_reset() +{ +} + +/* + * EEPROM + */ + +// let's try to fake the missing eeprom, make sure its ntsc, otherwise chihiro will show an error +static int dummyeeprom[256] = { + 0x39, 0xe3, 0xcc, 0x81, 0xb0, 0xa9, 0x97, 0x09, 0x57, 0xac, 0x57, 0x12, 0xf7, 0xc2, 0xc0, 0x21, 0xce, 0x0d, 0x0a, 0xdb, 0x20, 0x7a, 0xf3, 0xff, + 0xdf, 0x67, 0xed, 0xf4, 0xf8, 0x95, 0x5c, 0xd0, 0x9b, 0xef, 0x7b, 0x81, 0xda, 0xd5, 0x98, 0xc1, 0xb1, 0xb3, 0x74, 0x18, 0x86, 0x05, 0xe2, 0x7c, + 0xd1, 0xad, 0xc9, 0x90, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x00, 0x00, + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0xab, 0xcd, 0xef, 0xba, 0xdc, 0xfe, 0xa1, 0xb2, 0xc3, 0xd3, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +DEFINE_DEVICE_TYPE(XBOX_EEPROM, xbox_eeprom_device, "eeprom", "XBOX EEPROM") + +xbox_eeprom_device::xbox_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, XBOX_EEPROM, tag, owner, clock) +{ +} + +int xbox_eeprom_device::execute_command(int command, int rw, int data) +{ + if (command >= 112) + return 0; + if (rw == 1) // if reading + { + // hack to avoid hanging if eeprom contents are not correct + // removing this would need dumping the serial eeprom on the chihiro xbox board + if (command == 0) + { + hack_eeprom(); + } + data = dummyeeprom[command] + dummyeeprom[command + 1] * 256; + logerror("eeprom: %d %d %d\n", command, rw, data); + return data; + } + logerror("eeprom: %d %d %d\n", command, rw, data); + dummyeeprom[command] = data; + return 0; +} + +void xbox_eeprom_device::device_start() +{ +} + +void xbox_eeprom_device::device_reset() +{ +} + void xbox_base_state::machine_start() { find_debug_params(); nvidia_nv2a = subdevice("pci:1e.0:00.0")->debug_get_renderer(); - memset(pic16lc_buffer, 0, sizeof(pic16lc_buffer)); - pic16lc_buffer[0] = 'B'; - pic16lc_buffer[4] = 0; // A/V connector, 0=scart 2=vga 4=svideo 7=none - // PIC challenge handshake data - pic16lc_buffer[0x1c] = 0x0c; - pic16lc_buffer[0x1d] = 0x0d; - pic16lc_buffer[0x1e] = 0x0e; - pic16lc_buffer[0x1f] = 0x0f; - mcpx_smbus_device *smbus = subdevice("pci:01.1"); - smbus->register_device(0x10, - [&](int command, int rw, int data) - { - return smbus_pic16lc(command, rw, data); - } - ); - smbus->register_device(0x45, - [&](int command, int rw, int data) - { - return smbus_cx25871(command, rw, data); - } - ); - smbus->register_device(0x54, - [&](int command, int rw, int data) - { - return smbus_eeprom(command, rw, data); - } - ); xbox_base_devs.pic8259_1 = subdevice("pic8259_1"); xbox_base_devs.pic8259_2 = subdevice("pic8259_2"); xbox_base_devs.ide = subdevice("ide"); @@ -811,6 +854,11 @@ void xbox_base_state::machine_start() using namespace std::placeholders; machine().debugger().console().register_command("xbox", CMDFLAG_NONE, 0, 1, 4, std::bind(&xbox_base_state::xbox_debug_commands, this, _1, _2)); } + subdevice("pci:01.1:54")->hack_eeprom = + [&](void) + { + hack_eeprom(); + }; subdevice("pci:02.0")->set_hack_callback( [&](void) { @@ -824,7 +872,6 @@ void xbox_base_state::machine_start() // savestates save_item(NAME(debug_irq_active)); save_item(NAME(debug_irq_number)); - save_item(NAME(pic16lc_buffer)); } void xbox_base_state::xbox_base_map(address_map &map) @@ -876,6 +923,9 @@ MACHINE_CONFIG_START(xbox_base_state::xbox_base) MCFG_DEVICE_ADD(":pci:01.0", MCPX_LPC, 0) MCFG_DEVICE_ADD(":pci:01.1", MCPX_SMBUS, 0) MCFG_MCPX_SMBUS_INTERRUPT_HANDLER(WRITELINE(*this, xbox_base_state, xbox_smbus_interrupt_changed)) + MCFG_DEVICE_ADD(":pci:01.1:10", XBOX_PIC16LC, 0) + MCFG_DEVICE_ADD(":pci:01.1:45", XBOX_CX25871, 0) + MCFG_DEVICE_ADD(":pci:01.1:54", XBOX_EEPROM, 0) MCFG_DEVICE_ADD(":pci:02.0", MCPX_OHCI, 0) MCFG_MCPX_OHCI_INTERRUPT_HANDLER(WRITELINE(*this, xbox_base_state, xbox_ohci_usb_interrupt_changed)) MCFG_DEVICE_ADD(":pci:03.0", MCPX_OHCI, 0) diff --git a/src/mame/machine/xbox_pci.cpp b/src/mame/machine/xbox_pci.cpp index 0045fc9f990..8e856de385e 100644 --- a/src/mame/machine/xbox_pci.cpp +++ b/src/mame/machine/xbox_pci.cpp @@ -2,8 +2,9 @@ // copyright-holders:Samuele Zannoli #include "emu.h" -#include "includes/xbox.h" +#include "machine/pci.h" #include "includes/xbox_pci.h" +#include "includes/xbox.h" #include @@ -153,6 +154,36 @@ 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 (device_t &d : subdevices()) + { + const char *t = d.tag(); + int l = strlen(t); + + while (l > 0) + { + l--; + if (t[l] == ':') + { + l++; + int address = strtol(t + l, nullptr, 16); + if ((address > 0) && (address < 128)) + { + if (smbusst.devices[address] == nullptr) + { + smbus_interface *i = dynamic_cast(&d); + smbusst.devices[address] = i; + } + else + logerror("Duplicate address for SMBus device with tag %s\n", t); + } + else + logerror("Invalid address for SMBus device with tag %s\n", t); + break; + } + } + } } void mcpx_smbus_device::device_reset() @@ -190,9 +221,9 @@ WRITE32_MEMBER(mcpx_smbus_device::smbus_w) { if (smbusst.devices[smbusst.address]) if (smbusst.rw == 0) - smbusst.devices[smbusst.address](smbusst.command, smbusst.rw, smbusst.data); + smbusst.devices[smbusst.address]->execute_command(smbusst.command, smbusst.rw, smbusst.data); else - smbusst.data = smbusst.devices[smbusst.address](smbusst.command, smbusst.rw, smbusst.data); + smbusst.data = smbusst.devices[smbusst.address]->execute_command(smbusst.command, smbusst.rw, smbusst.data); else logerror("SMBUS: access to missing device at address %d\n", smbusst.address); smbusst.status |= 0x10; diff --git a/src/mame/machine/xbox_usb.cpp b/src/mame/machine/xbox_usb.cpp index 5a7a167ee49..edfb254f85c 100644 --- a/src/mame/machine/xbox_usb.cpp +++ b/src/mame/machine/xbox_usb.cpp @@ -2,6 +2,8 @@ // copyright-holders:Samuele Zannoli #include "emu.h" +#include "machine/pci.h" +#include "includes/xbox_pci.h" #include "includes/xbox_usb.h" #include "includes/xbox.h"