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