xbox: first step in using real devices with smbus (nw)

This commit is contained in:
yz70s 2018-10-04 15:32:05 +02:00
parent 2e8cd56eb2
commit 8d28538134
7 changed files with 256 additions and 105 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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<void(void)> 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;

View File

@ -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<int(int command, int rw, int data)> callback) { if (address < 128) smbusst.devices[address] = callback; }
template<class Object> devcb_base &set_interrupt_handler(Object &&cb) { return m_interrupt_handler.set_callback(std::forward<Object>(cb)); }
@ -101,7 +105,7 @@ private:
int data;
int command;
int rw;
std::function<int(int command, int rw, int data)> devices[128];
smbus_interface *devices[128];
uint32_t words[256 / 4];
} smbusst;
void smbus_io0(address_map &map);

View File

@ -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<std::string>
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<nv2a_gpu_device>("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<mcpx_smbus_device>("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_device>("pic8259_1");
xbox_base_devs.pic8259_2 = subdevice<pic8259_device>("pic8259_2");
xbox_base_devs.ide = subdevice<bus_master_ide_controller_device>("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<xbox_eeprom_device>("pci:01.1:54")->hack_eeprom =
[&](void)
{
hack_eeprom();
};
subdevice<mcpx_ohci_device>("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)

View File

@ -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 <functional>
@ -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<smbus_interface *>(&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;

View File

@ -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"