summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author yz70s <yz70s@users.noreply.github.com>2016-01-11 22:20:33 +0100
committer yz70s <yz70s@users.noreply.github.com>2016-01-11 23:01:50 +0100
commit0802d60f8a943f078d89c4c072233ca422ecc84c (patch)
treebf033c5c9ff9e96b468d727b441e407d1bfb30ad /src
parent9a9a89c716bc703455764be9163a88ff10ffa156 (diff)
xbox.cpp: add simple superio support and more usb (nw)
Bytes sent to the supoerio's first rs232 port wil be echoed on the console, this way it is possible to see the ouput of the OutputDebugString function.
Diffstat (limited to 'src')
-rw-r--r--src/mame/drivers/chihiro.cpp3
-rw-r--r--src/mame/includes/xbox.h20
-rw-r--r--src/mame/machine/xbox.cpp189
3 files changed, 187 insertions, 25 deletions
diff --git a/src/mame/drivers/chihiro.cpp b/src/mame/drivers/chihiro.cpp
index 624c58b7b95..7e7a6e96a23 100644
--- a/src/mame/drivers/chihiro.cpp
+++ b/src/mame/drivers/chihiro.cpp
@@ -364,14 +364,11 @@ Thanks to Alex, Mr Mudkips, and Philip Burke for this info.
#include "emu.h"
#include "cpu/i386/i386.h"
-#include "machine/lpci.h"
#include "machine/pic8259.h"
-#include "machine/pit8253.h"
#include "machine/idectrl.h"
#include "machine/idehd.h"
#include "machine/naomigd.h"
#include "video/poly.h"
-#include "bitmap.h"
#include "debug/debugcon.h"
#include "debug/debugcmd.h"
#include "debug/debugcpu.h"
diff --git a/src/mame/includes/xbox.h b/src/mame/includes/xbox.h
index eec1d3655de..ea4db5c7db4 100644
--- a/src/mame/includes/xbox.h
+++ b/src/mame/includes/xbox.h
@@ -39,6 +39,8 @@ struct OHCIIsochronousTransferDescriptor {
UINT32 nexttd; // NextTD
UINT32 be; // BufferEnd
UINT32 offset[8]; // Offset/PacketStatusWord
+ UINT32 word0;
+ UINT32 word1;
};
enum OHCIRegisters {
@@ -193,7 +195,11 @@ public:
int execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size);
private:
int address;
- int controldir;
+ int newaddress;
+ int controldirection;
+ int controltype;
+ int controlrecipient;
+ bool settingaddress;
int remain;
UINT8 *position;
};
@@ -214,6 +220,10 @@ public:
DECLARE_WRITE32_MEMBER(usbctrl_w);
DECLARE_READ32_MEMBER(smbus_r);
DECLARE_WRITE32_MEMBER(smbus_w);
+ DECLARE_READ8_MEMBER(superio_read);
+ DECLARE_WRITE8_MEMBER(superio_write);
+ DECLARE_READ8_MEMBER(superiors232_read);
+ DECLARE_WRITE8_MEMBER(superiors232_write);
DECLARE_READ32_MEMBER(audio_apu_r);
DECLARE_WRITE32_MEMBER(audio_apu_w);
DECLARE_READ32_MEMBER(audio_ac93_r);
@@ -232,6 +242,7 @@ public:
void usb_ohci_read_transfer_descriptor(UINT32 address);
void usb_ohci_writeback_transfer_descriptor(UINT32 address);
void usb_ohci_read_isochronous_transfer_descriptor(UINT32 address);
+ void usb_ohci_writeback_isochronous_transfer_descriptor(UINT32 address);
void dword_write_le(UINT8 *addr, UINT32 d);
void word_write_le(UINT8 *addr, UINT16 d);
void debug_generate_irq(int irq, bool active);
@@ -309,6 +320,13 @@ public:
OHCITransferDescriptor transfer_descriptor;
OHCIIsochronousTransferDescriptor isochronous_transfer_descriptor;
} ohcist;
+ struct superio_state
+ {
+ bool configuration_mode;
+ int index;
+ int selected;
+ UINT8 registers[16][256]; // 256 registers for up to 16 devices, registers 0-0x2f common to all
+ } superiost;
UINT8 pic16lc_buffer[0xff];
std::unique_ptr<nv2a_renderer> nvidia_nv2a;
bool debug_irq_active;
diff --git a/src/mame/machine/xbox.cpp b/src/mame/machine/xbox.cpp
index 73cbb24a406..7740b1545b0 100644
--- a/src/mame/machine/xbox.cpp
+++ b/src/mame/machine/xbox.cpp
@@ -7,7 +7,6 @@
#include "machine/pic8259.h"
#include "machine/pit8253.h"
#include "machine/idectrl.h"
-#include "machine/idehd.h"
#include "video/poly.h"
#include "bitmap.h"
#include "debug/debugcon.h"
@@ -17,6 +16,7 @@
#include "includes/xbox.h"
#define LOG_PCI
+//#define LOG_AUDIO
//#define LOG_OHCI
//#define USB_ENABLED
@@ -827,14 +827,17 @@ static USBStandardDeviceDscriptor devdesc = {18,1,0x201,0xff,0x34,0x56,64,0x100,
ohci_function_device::ohci_function_device()
{
address = 0;
- controldir = 0;
+ newaddress = 0;
+ controldirection = 0;
remain = 0;
position = nullptr;
+ settingaddress = false;
}
void ohci_function_device::execute_reset()
{
address = 0;
+ newaddress = 0;
}
int ohci_function_device::execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size)
@@ -842,35 +845,69 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
if (endpoint == 0) {
if (pid == SetupPid) {
struct USBSetupPacket *p=(struct USBSetupPacket *)buffer;
- // define direction
- controldir = p->bmRequestType & 128;
- // case !=0, in data stage and out status stage
- // case ==0, out data stage and in status stage
+ // define direction 0:host->device 1:device->host
+ controldirection = (p->bmRequestType & 128) >> 7;
+ // case ==1, IN data stage and OUT status stage
+ // case ==0, OUT data stage and IN status stage
+ // data stage is optional, IN status stage
+ controltype = (p->bmRequestType & 0x60) >> 5;
+ controlrecipient = p->bmRequestType & 0x1f;
position = nullptr;
remain = p->wLength;
- if ((p->bmRequestType & 0x60) == 0) {
+ // if standard
+ if (controltype == 0) {
switch (p->bRequest) {
+ case GET_STATUS:
+ case CLEAR_FEATURE:
+ case SET_FEATURE:
+ break;
+ case SET_ADDRESS:
+ newaddress = p->wValue;
+ settingaddress = true;
+ break;
case GET_DESCRIPTOR:
- if ((p->wValue >> 8) == 1) { // device descriptor
+ if ((p->wValue >> 8) == DEVICE) { // device descriptor
//p->wValue & 255;
position = (UINT8 *)&devdesc;
remain = sizeof(devdesc);
}
+ else if ((p->wValue >> 8) == CONFIGURATION) { // configuration descriptor
+ remain = 0;
+ }
+ if (remain > p->wLength)
+ remain = p->wLength;
break;
- case SET_ADDRESS:
- //p->wValue;
- break;
+ case SET_DESCRIPTOR:
+ case GET_CONFIGURATION:
+ case SET_CONFIGURATION:
+ case GET_INTERFACE:
+ case SET_INTERFACE:
+ case SYNCH_FRAME:
default:
break;
}
}
}
else if (pid == InPid) {
- // case !=0, give data
+ // if no data has been transferred (except for the setup stage)
+ // and the lenght of this IN transaction is 0
+ // assume this is the status stage
+ if (size == 0) {
+ if (settingaddress == true)
+ {
+ // set of address is active at end of status stage
+ address = newaddress;
+ settingaddress = false;
+ }
+ return 0;
+ }
+ // case ==1, give data
// case ==0, nothing
- if (size > remain)
- size = remain;
- if (controldir != 0) {
+ // if device->host
+ if (controldirection == 1) {
+ // data stage
+ if (size > remain)
+ size = remain;
if (position != nullptr)
memcpy(buffer, position, size);
position = position + size;
@@ -878,11 +915,13 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
}
}
else if (pid == OutPid) {
- // case !=0, nothing
+ // case ==1, nothing
// case ==0, give data
- if (size > remain)
- size = remain;
- if (controldir == 0) {
+ // if host->device
+ if (controldirection == 0) {
+ // data stage
+ if (size > remain)
+ size = remain;
if (position != nullptr)
memcpy(position, buffer, size);
position = position + size;
@@ -966,11 +1005,14 @@ void xbox_base_state::usb_ohci_read_isochronous_transfer_descriptor(UINT32 addre
UINT32 w;
w = ohcist.space->read_dword(address);
+ ohcist.isochronous_transfer_descriptor.word0 = w;
ohcist.isochronous_transfer_descriptor.cc = (w >> 28) & 15;
ohcist.isochronous_transfer_descriptor.fc = (w >> 24) & 7;
ohcist.isochronous_transfer_descriptor.di = (w >> 21) & 7;
ohcist.isochronous_transfer_descriptor.sf = w & 0xffff;
- ohcist.isochronous_transfer_descriptor.bp0 = ohcist.space->read_dword(address + 4) & 0xfffff000;
+ w = ohcist.space->read_dword(address + 4);
+ ohcist.isochronous_transfer_descriptor.word1 = w;
+ ohcist.isochronous_transfer_descriptor.bp0 = w & 0xfffff000;
ohcist.isochronous_transfer_descriptor.nexttd = ohcist.space->read_dword(address + 8);
ohcist.isochronous_transfer_descriptor.be = ohcist.space->read_dword(address + 12);
w = ohcist.space->read_dword(address + 16);
@@ -987,13 +1029,37 @@ void xbox_base_state::usb_ohci_read_isochronous_transfer_descriptor(UINT32 addre
ohcist.isochronous_transfer_descriptor.offset[7] = (w >> 16) & 0xffff;
}
+void xbox_base_state::usb_ohci_writeback_isochronous_transfer_descriptor(UINT32 address)
+{
+ UINT32 w;
+
+ w = ohcist.isochronous_transfer_descriptor.word0 & 0x1f0000;
+ w = w | (ohcist.isochronous_transfer_descriptor.cc << 28) | (ohcist.isochronous_transfer_descriptor.fc << 24) | (ohcist.isochronous_transfer_descriptor.di << 21) | ohcist.isochronous_transfer_descriptor.sf;
+ ohcist.space->write_dword(address, w);
+ w = ohcist.isochronous_transfer_descriptor.word1 & 0xfff;
+ w = w | ohcist.isochronous_transfer_descriptor.bp0;
+ ohcist.space->write_dword(address + 4, w);
+ ohcist.space->write_dword(address + 8, ohcist.isochronous_transfer_descriptor.nexttd);
+ ohcist.space->write_dword(address + 12, ohcist.isochronous_transfer_descriptor.be);
+ w = (ohcist.isochronous_transfer_descriptor.offset[1] << 16) | ohcist.isochronous_transfer_descriptor.offset[0];
+ ohcist.space->write_dword(address + 16, w);
+ w = (ohcist.isochronous_transfer_descriptor.offset[3] << 16) | ohcist.isochronous_transfer_descriptor.offset[2];
+ ohcist.space->write_dword(address + 20, w);
+ w = (ohcist.isochronous_transfer_descriptor.offset[5] << 16) | ohcist.isochronous_transfer_descriptor.offset[4];
+ ohcist.space->write_dword(address + 24, w);
+ w = (ohcist.isochronous_transfer_descriptor.offset[7] << 16) | ohcist.isochronous_transfer_descriptor.offset[6];
+ ohcist.space->write_dword(address + 28, w);
+}
+
/*
* Audio
*/
READ32_MEMBER(xbox_base_state::audio_apu_r)
{
+#ifdef LOG_AUDIO
logerror("Audio_APU: read from %08X mask %08X\n", 0xfe800000 + offset * 4, mem_mask);
+#endif
if (offset == 0x20010 / 4) // some kind of internal counter or state value
return 0x20 + 4 + 8 + 0x48 + 0x80;
return apust.memory[offset];
@@ -1004,7 +1070,9 @@ WRITE32_MEMBER(xbox_base_state::audio_apu_w)
//UINT32 old;
UINT32 v;
+#ifdef LOG_AUDIO
logerror("Audio_APU: write at %08X mask %08X value %08X\n", 0xfe800000 + offset * 4, mem_mask, data);
+#endif
//old = apust.memory[offset];
apust.memory[offset] = data;
if (offset == 0x02040 / 4) // address of memory area with scatter-gather info (gpdsp scratch dma)
@@ -1110,7 +1178,9 @@ READ32_MEMBER(xbox_base_state::audio_ac93_r)
{
UINT32 ret = 0;
+#ifdef LOG_AUDIO
logerror("Audio_AC3: read from %08X mask %08X\n", 0xfec00000 + offset * 4, mem_mask);
+#endif
if (offset < 0x80 / 4)
{
ret = ac97st.mixer_regs[offset];
@@ -1137,7 +1207,9 @@ READ32_MEMBER(xbox_base_state::audio_ac93_r)
WRITE32_MEMBER(xbox_base_state::audio_ac93_w)
{
+#ifdef LOG_AUDIO
logerror("Audio_AC3: write at %08X mask %08X value %08X\n", 0xfec00000 + offset * 4, mem_mask, data);
+#endif
if (offset < 0x80 / 4)
{
COMBINE_DATA(ac97st.mixer_regs + offset);
@@ -1421,6 +1493,76 @@ WRITE32_MEMBER(xbox_base_state::smbus_w)
smbusst.command = data;
}
+/*
+ * SuperIO
+ */
+READ8_MEMBER(xbox_base_state::superio_read)
+{
+ if (superiost.configuration_mode == false)
+ return 0;
+ if (offset == 0) // index port 0x2e
+ return superiost.index;
+ if (offset == 1)
+ {
+ // data port 0x2f
+ if (superiost.index < 0x30)
+ return superiost.registers[0][superiost.index];
+ return superiost.registers[superiost.selected][superiost.index];
+ }
+ return 0;
+}
+
+WRITE8_MEMBER(xbox_base_state::superio_write)
+{
+ if (superiost.configuration_mode == false)
+ {
+ // config port 0x2e
+ if ((offset == 0) && (data == 0x55))
+ superiost.configuration_mode = true;
+ return;
+ }
+ if ((offset == 0) && (data == 0xaa))
+ {
+ // config port 0x2e
+ superiost.configuration_mode = false;
+ return;
+ }
+ if (offset == 0)
+ {
+ // index port 0x2e
+ superiost.index = data;
+ }
+ if (offset == 1)
+ {
+ // data port 0x2f
+ if (superiost.index < 0x30)
+ {
+ superiost.registers[0][superiost.index] = data;
+ superiost.selected = superiost.registers[0][7];
+ } else
+ {
+ superiost.registers[superiost.selected][superiost.index] = data;
+ //if ((superiost.selected == 4) && (superiost.index == 0x30) && (data != 0))
+ // ; // add handlers 0x3f8- +7
+ }
+ }
+}
+
+READ8_MEMBER(xbox_base_state::superiors232_read)
+{
+ if (offset == 5)
+ return 0x20;
+ return 0;
+}
+
+WRITE8_MEMBER(xbox_base_state::superiors232_write)
+{
+ if (offset == 0)
+ {
+ printf("%c", data);
+ }
+}
+
ADDRESS_MAP_START(xbox_base_map, AS_PROGRAM, 32, xbox_base_state)
AM_RANGE(0x00000000, 0x07ffffff) AM_RAM AM_SHARE("nv2a_share") // 128 megabytes
AM_RANGE(0xf0000000, 0xf7ffffff) AM_RAM AM_SHARE("nv2a_share") // 3d accelerator wants this
@@ -1433,9 +1575,11 @@ ADDRESS_MAP_END
ADDRESS_MAP_START(xbox_base_map_io, AS_IO, 32, xbox_base_state)
AM_RANGE(0x0020, 0x0023) AM_DEVREADWRITE8("pic8259_1", pic8259_device, read, write, 0xffffffff)
+ AM_RANGE(0x002c, 0x002f) AM_READWRITE8(superio_read, superio_write, 0xffff0000)
AM_RANGE(0x0040, 0x0043) AM_DEVREADWRITE8("pit8254", pit8254_device, read, write, 0xffffffff)
AM_RANGE(0x00a0, 0x00a3) AM_DEVREADWRITE8("pic8259_2", pic8259_device, read, write, 0xffffffff)
AM_RANGE(0x01f0, 0x01f7) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, read_cs0, write_cs0)
+ AM_RANGE(0x03f8, 0x03ff) AM_READWRITE8(superiors232_read, superiors232_write, 0xffffffff)
AM_RANGE(0x0cf8, 0x0cff) AM_DEVREADWRITE("pcibus", pci_bus_legacy_device, read, write)
AM_RANGE(0x8000, 0x80ff) AM_READWRITE(dummy_r, dummy_w)
AM_RANGE(0xc000, 0xc0ff) AM_READWRITE(smbus_r, smbus_w)
@@ -1472,11 +1616,11 @@ void xbox_base_state::machine_start()
pic16lc_buffer[0x1d] = 0x0d;
pic16lc_buffer[0x1e] = 0x0e;
pic16lc_buffer[0x1f] = 0x0f;
-#ifdef USB_ENABLED
ohcist.hc_regs[HcRevision] = 0x10;
ohcist.hc_regs[HcFmInterval] = 0x2edf;
ohcist.hc_regs[HcLSThreshold] = 0x628;
ohcist.hc_regs[HcRhDescriptorA] = 4;
+#ifdef USB_ENABLED
ohcist.interruptbulkratio = 1;
ohcist.writebackdonehadcounter = 7;
ohcist.space = &m_maincpu->space();
@@ -1484,6 +1628,9 @@ void xbox_base_state::machine_start()
ohcist.timer->enable(false);
usb_ohci_plug(1, new ohci_function_device()); // test connect
#endif
+ memset(&superiost, 0, sizeof(superiost));
+ superiost.configuration_mode = false;
+ superiost.registers[0][0x26] = 0x2e; // Configuration port address byte 0
// savestates
save_item(NAME(debug_irq_active));
save_item(NAME(debug_irq_number));