diff options
Diffstat (limited to 'src/mame/machine/xbox_usb.cpp')
-rw-r--r-- | src/mame/machine/xbox_usb.cpp | 1553 |
1 files changed, 0 insertions, 1553 deletions
diff --git a/src/mame/machine/xbox_usb.cpp b/src/mame/machine/xbox_usb.cpp deleted file mode 100644 index 88c49ea22ce..00000000000 --- a/src/mame/machine/xbox_usb.cpp +++ /dev/null @@ -1,1553 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Samuele Zannoli - -#include "emu.h" -#include "machine/pci.h" -#include "machine/idectrl.h" -#include "includes/xbox_pci.h" -#include "includes/xbox_usb.h" -#include "includes/xbox.h" - -//#define LOG_OHCI - -/* - * OHCI usb controller - */ - -#ifdef LOG_OHCI -static const char *const usbregnames[] = { - "HcRevision", - "HcControl", - "HcCommandStatus", - "HcInterruptStatus", - "HcInterruptEnable", - "HcInterruptDisable", - "HcHCCA", - "HcPeriodCurrentED", - "HcControlHeadED", - "HcControlCurrentED", - "HcBulkHeadED", - "HcBulkCurrentED", - "HcDoneHead", - "HcFmInterval", - "HcFmRemaining", - "HcFmNumber", - "HcPeriodicStart", - "HcLSThreshold", - "HcRhDescriptorA", - "HcRhDescriptorB", - "HcRhStatus", - "HcRhPortStatus[1]" -}; -#endif - -ohci_usb_controller::ohci_usb_controller() -{ - memset(&ohcist, 0, sizeof(ohcist)); - m_maincpu = nullptr; - irq_callback = nullptr; -} - -void ohci_usb_controller::start() -{ - ohcist.hc_regs[HcRevision] = 0x10; - ohcist.hc_regs[HcFmInterval] = 0x2edf; - ohcist.hc_regs[HcLSThreshold] = 0x628; - ohcist.hc_regs[HcRhDescriptorA] = 4; - ohcist.hc_regs[HcControl] = UsbReset << 6; - ohcist.state = UsbReset; - ohcist.interruptbulkratio = 1; - ohcist.writebackdonehadcounter = 7; - for (int n = 0; n <= 4; n++) - ohcist.ports[n].address = -1; - for (int n = 0; n < 256; n++) - ohcist.address[n].port = -1; - ohcist.space = &(m_maincpu->space()); - ohcist.timer->enable(false); -} - -void ohci_usb_controller::reset() -{ -} - -READ32_MEMBER(ohci_usb_controller::read) -{ - uint32_t ret; - -#ifdef LOG_OHCI - if (offset >= 0x54 / 4) - logerror("usb controller 0 register HcRhPortStatus[%d] read\n", (offset - 0x54 / 4) + 1); - else - logerror("usb controller 0 register %s read\n", usbregnames[offset]); -#endif - ret = ohcist.hc_regs[offset]; - return ret; -} - -WRITE32_MEMBER(ohci_usb_controller::write) -{ - uint32_t old = ohcist.hc_regs[offset]; - -#ifdef LOG_OHCI - if (offset >= 0x54 / 4) - logerror("usb controller 0 register HcRhPortStatus[%d] write %08X\n", (offset - 0x54 / 4) + 1, data); - else - logerror("usb controller 0 register %s write %08X\n", usbregnames[offset], data); -#endif - if (offset == HcRhStatus) { - if (data & CRWE) - ohcist.hc_regs[HcRhStatus] &= ~DRWE; - if (data & OCIC) - ohcist.hc_regs[HcRhStatus] &= ~OCI; - if (data & LPSC) - ohcist.hc_regs[HcRhStatus] &= ~LPS; - return; - } - if (offset == HcControl) { - int hcfs; - - hcfs = (data >> 6) & 3; // HostControllerFunctionalState - if (hcfs == UsbOperational) { - ohcist.timer->enable(); - ohcist.timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1)); - ohcist.writebackdonehadcounter = 7; - // need to load the FrameRemaining field of HcFmRemaining with the value of the FrameInterval field in HcFmInterval - } - else - ohcist.timer->enable(false); - ohcist.interruptbulkratio = (data & 3) + 1; - if ((hcfs != UsbReset) && (ohcist.state == UsbReset)) - { - ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; - usb_ohci_interrupts(); - } - ohcist.state = hcfs; - } - if (offset == HcCommandStatus) { - if (data & 1) // HostControllerReset - ohcist.hc_regs[HcControl] |= 3 << 6; - ohcist.hc_regs[HcCommandStatus] |= data; - return; - } - if (offset == HcInterruptStatus) { - ohcist.hc_regs[HcInterruptStatus] &= ~data; - usb_ohci_interrupts(); - return; - } - if (offset == HcInterruptEnable) { - ohcist.hc_regs[HcInterruptEnable] |= data; - usb_ohci_interrupts(); - return; - } - if (offset == HcInterruptDisable) { - ohcist.hc_regs[HcInterruptEnable] &= ~data; - usb_ohci_interrupts(); - return; - } - if (offset >= HcRhPortStatus1) { - int port = offset - HcRhPortStatus1 + 1; // port 0 not used - // bit 0 R:CurrentConnectStatus W:ClearPortEnable: 1 clears PortEnableStatus - if (data & CCS) { - ohcist.hc_regs[offset] &= ~PES; - ohcist.address[ohcist.ports[port].address].port = -1; - } - // bit 1 R:PortEnableStatus W:SetPortEnable: 1 sets PortEnableStatus - if (data & PES) { - ohcist.hc_regs[offset] |= PES; - // the port is enabled, so the device connected to it can communicate on the bus - ohcist.address[ohcist.ports[port].address].function = ohcist.ports[port].function; - ohcist.address[ohcist.ports[port].address].port = port; - } - // bit 2 R:PortSuspendStatus W:SetPortSuspend: 1 sets PortSuspendStatus - if (data & PSS) { - ohcist.hc_regs[offset] |= PSS; - } - // bit 3 R:PortOverCurrentIndicator W:ClearSuspendStatus: 1 clears PortSuspendStatus - if (data & POCI) { - ohcist.hc_regs[offset] &= ~PSS; - } - // bit 4 R: PortResetStatus W:SetPortReset: 1 sets PortResetStatus - if (data & PRS) { - ohcist.hc_regs[offset] |= PRS; - if (ohcist.ports[port].address >= 0) - ohcist.address[ohcist.ports[port].address].port = -1; - ohcist.ports[port].address = 0; - if (ohcist.hc_regs[offset] & PES) - { - ohcist.address[0].function = ohcist.ports[port].function; - ohcist.address[0].port = port; - } - ohcist.ports[port].function->execute_reset(); - // after 10ms set PortResetStatusChange and clear PortResetStatus and set PortEnableStatus - ohcist.ports[port].delay = 10; - } - // bit 8 R:PortPowerStatus W:SetPortPower: 1 sets PortPowerStatus - if (data & PPS) { - ohcist.hc_regs[offset] |= PPS; - } - // bit 9 R:LowSpeedDeviceAttached W:ClearPortPower: 1 clears PortPowerStatus - if (data & LSDA) { - ohcist.hc_regs[offset] &= ~PPS; - } - // bit 16 R:ConnectStatusChange W: 1 clears ConnectStatusChange - if (data & CSC) { - ohcist.hc_regs[offset] &= ~CSC; - } - // bit 17 R:PortEnableStatusChange W: 1 clears PortEnableStatusChange - if (data & PESC) { - ohcist.hc_regs[offset] &= ~PESC; - } - // bit 18 R:PortSuspendStatusChange W: 1 clears PortSuspendStatusChange - if (data & PSSC) { - ohcist.hc_regs[offset] &= ~PSSC; - } - // bit 19 R:PortOverCurrentIndicatorChange W: 1 clears PortOverCurrentIndicatorChange - if (data & POCIC) { - ohcist.hc_regs[offset] &= ~POCIC; - } - // bit 20 R:PortResetStatusChange W: 1 clears PortResetStatusChange - if (data & PRSC) { - ohcist.hc_regs[offset] &= ~PRSC; - } - if (ohcist.hc_regs[offset] != old) - ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; - usb_ohci_interrupts(); - return; - } - ohcist.hc_regs[offset] = data; -} - -void ohci_usb_controller::timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - uint32_t hcca; - uint32_t plh; - int changed = 0; - int list = 1; - bool cont = false; - bool retire = false; - int pid, remain, mps, done; - - hcca = ohcist.hc_regs[HcHCCA]; - if (ohcist.state == UsbOperational) { - // increment frame number - ohcist.framenumber = (ohcist.framenumber + 1) & 0xffff; - ohcist.space->write_dword(hcca + 0x80, ohcist.framenumber); - ohcist.hc_regs[HcFmNumber] = ohcist.framenumber; - } - // port reset delay - for (int p = 1; p <= 4; p++) { - if (ohcist.ports[p].delay > 0) { - ohcist.ports[p].delay--; - if (ohcist.ports[p].delay == 0) { - ohcist.hc_regs[HcRhPortStatus1 + p - 1] = (ohcist.hc_regs[HcRhPortStatus1 + p - 1] & ~PRS) | PRSC | PES; - ohcist.address[ohcist.ports[p].address].function = ohcist.ports[p].function; - ohcist.address[ohcist.ports[p].address].port = p; - changed = 1; - } - } - } - if (ohcist.state == UsbOperational) { - while (list >= 0) - { - // select list, do transfer - if (list == 0) { - if (ohcist.hc_regs[HcControl] & PLE) { - // periodic list - plh = ohcist.space->read_dword(hcca + (ohcist.framenumber & 0x1f) * 4); - cont = true; - while (cont == true) { - if (plh != 0) { - usb_ohci_read_endpoint_descriptor(plh); - // if this an isochronous endpoint and isochronous list not enabled, stop list processing - if (((ohcist.hc_regs[HcControl] & IE) == 0) && (ohcist.endpoint_descriptor.f == 1)) - cont = false; - } - else - cont = false; - if (cont == false) - break; - // service endpoint descriptor - // only if it is not halted and not to be skipped - if (!(ohcist.endpoint_descriptor.h | ohcist.endpoint_descriptor.k)) { - // compare the Endpoint Descriptor TailPointer and NextTransferDescriptor fields. - if (ohcist.endpoint_descriptor.headp != ohcist.endpoint_descriptor.tailp) { - uint32_t a, b; - int R = 0; - - // service transfer descriptor - if (ohcist.endpoint_descriptor.f != 1) { - usb_ohci_read_transfer_descriptor(ohcist.endpoint_descriptor.headp); - // get pid - if (ohcist.endpoint_descriptor.d == 1) - pid = OutPid; // out - else if (ohcist.endpoint_descriptor.d == 2) - pid = InPid; // in - else { - pid = ohcist.transfer_descriptor.dp; // 0 setup 1 out 2 in - } - a = ohcist.transfer_descriptor.be; - b = ohcist.transfer_descriptor.cbp; - } - else { - usb_ohci_read_isochronous_transfer_descriptor(ohcist.endpoint_descriptor.headp); - // get pid - if (ohcist.endpoint_descriptor.d == 1) - pid = OutPid; // out - else if (ohcist.endpoint_descriptor.d == 2) - pid = InPid; // in - else - pid = InPid; // in - R = (int)ohcist.framenumber - (int)ohcist.isochronous_transfer_descriptor.sf; - //if ((R < 0) || (R > (int)ohcist.isochronous_transfer_descriptor.fc)) - // ; // greater than fc should be an error - if (R == (int)ohcist.isochronous_transfer_descriptor.fc) - a = ohcist.isochronous_transfer_descriptor.be; - else { - a = ohcist.isochronous_transfer_descriptor.offset[R + 1] - 1; - if (a & (1 << 12)) - a = (ohcist.isochronous_transfer_descriptor.be & 0xfffff000) | (a & 0xfff); - else - a = ohcist.isochronous_transfer_descriptor.bp0 | (a & 0xfff); - } - b = ohcist.isochronous_transfer_descriptor.offset[R]; - if (b & (1 << 12)) - b = (ohcist.isochronous_transfer_descriptor.be & 0xfffff000) | (b & 0xfff); - else - b = ohcist.isochronous_transfer_descriptor.bp0 | (b & 0xfff); - } - if ((a ^ b) & 0xfffff000) - remain = ((a | 0x1000) & 0x1fff) - (b & 0xfff) + 1; - else - remain = a - b + 1; - mps = ohcist.endpoint_descriptor.mps; - if (remain < mps) - mps = remain; - // if sending ... - if (pid != InPid) { - // ... get mps bytes - for (int c = 0; c < remain; c++) { - ohcist.buffer[c] = ohcist.space->read_byte(b); - b++; - if ((b & 0xfff) == 0) - b = ohcist.transfer_descriptor.be & 0xfffff000; - } - } - // should check for time available - // execute transaction - done = ohcist.address[ohcist.endpoint_descriptor.fa].function->execute_transfer(ohcist.endpoint_descriptor.en, pid, ohcist.buffer, mps); - // if receiving ... - if (pid == InPid) { - // ... store done bytes - for (int c = 0; c < done; c++) { - ohcist.space->write_byte(b, ohcist.buffer[c]); - b++; - if ((b & 0xfff) == 0) - b = a & 0xfffff000; - } - } - if (ohcist.endpoint_descriptor.f != 1) { - // status writeback (CompletionCode field, DataToggleControl field, CurrentBufferPointer field, ErrorCount field) - ohcist.transfer_descriptor.cc = NoError; - ohcist.transfer_descriptor.t = (ohcist.transfer_descriptor.t ^ 1) | 2; - // if all data is transferred (or there was no data to transfer) cbp must be 0, otherwise it must be updated - if (done == remain) - b = 0; - ohcist.transfer_descriptor.cbp = b; - ohcist.transfer_descriptor.ec = 0; - retire = false; - if ((done == mps) && (done == remain)) { - retire = true; - } - if ((done != mps) && (done <= remain)) - retire = true; - if (done == 0) - retire = true; - if (retire == true) { - // retire transfer descriptor - a = ohcist.endpoint_descriptor.headp; - ohcist.endpoint_descriptor.headp = ohcist.transfer_descriptor.nexttd; - ohcist.transfer_descriptor.nexttd = ohcist.hc_regs[HcDoneHead]; - ohcist.hc_regs[HcDoneHead] = a; - ohcist.endpoint_descriptor.c = ohcist.transfer_descriptor.t & 1; - if (ohcist.transfer_descriptor.di != 7) { - if (ohcist.transfer_descriptor.di < ohcist.writebackdonehadcounter) - ohcist.writebackdonehadcounter = ohcist.transfer_descriptor.di; - } - usb_ohci_writeback_transfer_descriptor(a); - usb_ohci_writeback_endpoint_descriptor(plh); - } - else { - usb_ohci_writeback_transfer_descriptor(ohcist.endpoint_descriptor.headp); - } - } - else - { - // status writeback - ohcist.isochronous_transfer_descriptor.cc = NoError; - if (done == remain) - b = 0; - ohcist.isochronous_transfer_descriptor.offset[R] = b; - retire = false; - if ((done == mps) && (done == remain)) { - retire = true; - } - if ((done != mps) && (done <= remain)) - retire = true; - if (done == 0) - retire = true; - if (retire == true) { - // retire transfer descriptor - } - else { - usb_ohci_writeback_isochronous_transfer_descriptor(ohcist.endpoint_descriptor.headp); - } - } - } - } - // go to next endpoint - if (ohcist.endpoint_descriptor.nexted != 0) - { - plh = ohcist.endpoint_descriptor.nexted; - } - else - cont = false; - } - } - list = -1; - } - if (list == 1) { - // control list - // check if control list active - if (ohcist.hc_regs[HcControl] & CLE) { - cont = true; - while (cont == true) { - // if current endpoint descriptor is not 0 use it, otherwise ... - if (ohcist.hc_regs[HcControlCurrentED] == 0) { - // ... check the filled bit ... - if (ohcist.hc_regs[HcCommandStatus] & CLF) { - // ... if 1 start processing from the head of the list - ohcist.hc_regs[HcControlCurrentED] = ohcist.hc_regs[HcControlHeadED]; - // clear CLF (ControlListFilled) - ohcist.hc_regs[HcCommandStatus] &= ~CLF; - // but if the list is empty, go to the next list - if (ohcist.hc_regs[HcControlCurrentED] == 0) - cont = false; - else - cont = true; - } - else - cont = false; - } - else - cont = true; - if (cont == false) - break; - // service endpoint descriptor - usb_ohci_read_endpoint_descriptor(ohcist.hc_regs[HcControlCurrentED]); - // only if it is not halted and not to be skipped - if (!(ohcist.endpoint_descriptor.h | ohcist.endpoint_descriptor.k)) { - // compare the Endpoint Descriptor TailPointer and NextTransferDescriptor fields. - if (ohcist.endpoint_descriptor.headp != ohcist.endpoint_descriptor.tailp) { - uint32_t a, b; - // set CLF (ControlListFilled) - ohcist.hc_regs[HcCommandStatus] |= CLF; - // service transfer descriptor - usb_ohci_read_transfer_descriptor(ohcist.endpoint_descriptor.headp); - // get pid - if (ohcist.endpoint_descriptor.d == 1) - pid = OutPid; // out - else if (ohcist.endpoint_descriptor.d == 2) - pid = InPid; // in - else { - pid = ohcist.transfer_descriptor.dp; // 0 setup 1 out 2 in - } - // determine how much data to transfer - // setup pid must be 8 bytes - a = ohcist.transfer_descriptor.be & 0xfff; - b = ohcist.transfer_descriptor.cbp & 0xfff; - if ((ohcist.transfer_descriptor.be ^ ohcist.transfer_descriptor.cbp) & 0xfffff000) - a |= 0x1000; - remain = a - b + 1; - mps = ohcist.endpoint_descriptor.mps; - if ((pid == InPid) || (pid == OutPid)) { - if (remain < mps) - mps = remain; - } - if (ohcist.transfer_descriptor.cbp == 0) { - remain = 0; - mps = 0; - } - b = ohcist.transfer_descriptor.cbp; - // if sending ... - if (pid != InPid) { - // ... get mps bytes - for (int c = 0; c < remain; c++) { - ohcist.buffer[c] = ohcist.space->read_byte(b); - b++; - if ((b & 0xfff) == 0) - b = ohcist.transfer_descriptor.be & 0xfffff000; - } - } - // should check for time available - // execute transaction - done = ohcist.address[ohcist.endpoint_descriptor.fa].function->execute_transfer(ohcist.endpoint_descriptor.en, pid, ohcist.buffer, mps); - // if receiving ... - if (pid == InPid) { - // ... store done bytes - for (int c = 0; c < done; c++) { - ohcist.space->write_byte(b, ohcist.buffer[c]); - b++; - if ((b & 0xfff) == 0) - b = ohcist.transfer_descriptor.be & 0xfffff000; - } - } - // status writeback (CompletionCode field, DataToggleControl field, CurrentBufferPointer field, ErrorCount field) - ohcist.transfer_descriptor.cc = NoError; - ohcist.transfer_descriptor.t = (ohcist.transfer_descriptor.t ^ 1) | 2; - // if all data is transferred (or there was no data to transfer) cbp must be 0, otherwise it must be updated - if ((done == remain) || (pid == SetupPid)) - b = 0; - ohcist.transfer_descriptor.cbp = b; - ohcist.transfer_descriptor.ec = 0; - retire = false; - if ((done == mps) && (done == remain)) { - retire = true; - } - if ((done != mps) && (done <= remain)) - retire = true; - if (done == 0) - retire = true; - if (retire == true) { - // retire transfer descriptor - a = ohcist.endpoint_descriptor.headp; - ohcist.endpoint_descriptor.headp = ohcist.transfer_descriptor.nexttd; - ohcist.transfer_descriptor.nexttd = ohcist.hc_regs[HcDoneHead]; - ohcist.hc_regs[HcDoneHead] = a; - ohcist.endpoint_descriptor.c = ohcist.transfer_descriptor.t & 1; - if (ohcist.transfer_descriptor.di != 7) { - if (ohcist.transfer_descriptor.di < ohcist.writebackdonehadcounter) - ohcist.writebackdonehadcounter = ohcist.transfer_descriptor.di; - } - usb_ohci_writeback_transfer_descriptor(a); - usb_ohci_writeback_endpoint_descriptor(ohcist.hc_regs[HcControlCurrentED]); - } - else { - usb_ohci_writeback_transfer_descriptor(ohcist.endpoint_descriptor.headp); - } - } - else { - // no transfer descriptors for this endpoint, so go to next endpoint - ohcist.hc_regs[HcControlCurrentED] = ohcist.endpoint_descriptor.nexted; - } - } - else { - // not enabled, so go to next endpoint - ohcist.hc_regs[HcControlCurrentED] = ohcist.endpoint_descriptor.nexted; - } - // one bulk every n control transfers - ohcist.interruptbulkratio--; - if (ohcist.interruptbulkratio <= 0) { - ohcist.interruptbulkratio = (ohcist.hc_regs[HcControl] & 3) + 1; // ControlBulkServiceRatio - cont = false; - } - } - } - list = 2; - } - if (list == 2) { - // bulk list - // check if bulk list active - if (ohcist.hc_regs[HcControl] & BLE) { - // if current endpoint descriptor is not 0 use it, otherwise ... - if (ohcist.hc_regs[HcBulkCurrentED] == 0) { - // ... check the filled bit ... - if (ohcist.hc_regs[HcCommandStatus] & BLF) { - // ... if 1 start processing from the head of the list - ohcist.hc_regs[HcBulkCurrentED] = ohcist.hc_regs[HcBulkHeadED]; - // clear BLF (BulkListFilled) - ohcist.hc_regs[HcCommandStatus] &= ~BLF; - // but if the list is empty, go to the next list - if (ohcist.hc_regs[HcBulkCurrentED] == 0) - cont = false; - else - cont = true; - } - else - cont = false; - } - else - cont = true; - if (cont == true) { - // service endpoint descriptor - usb_ohci_read_endpoint_descriptor(ohcist.hc_regs[HcBulkCurrentED]); - // only if it is not halted and not to be skipped - if (!(ohcist.endpoint_descriptor.h | ohcist.endpoint_descriptor.k)) { - // compare the Endpoint Descriptor TailPointer and NextTransferDescriptor fields. - if (ohcist.endpoint_descriptor.headp != ohcist.endpoint_descriptor.tailp) { - uint32_t a, b; - // set BLF (BulkListFilled) - ohcist.hc_regs[HcCommandStatus] |= BLF; - // service transfer descriptor - usb_ohci_read_transfer_descriptor(ohcist.endpoint_descriptor.headp); - // get pid - if (ohcist.endpoint_descriptor.d == 1) - pid = OutPid; // out - else if (ohcist.endpoint_descriptor.d == 2) - pid = InPid; // in - else { - pid = ohcist.transfer_descriptor.dp; // 0 setup 1 out 2 in - } - // determine how much data to transfer - a = ohcist.transfer_descriptor.be & 0xfff; - b = ohcist.transfer_descriptor.cbp & 0xfff; - if ((ohcist.transfer_descriptor.be ^ ohcist.transfer_descriptor.cbp) & 0xfffff000) - a |= 0x1000; - remain = a - b + 1; - mps = ohcist.endpoint_descriptor.mps; - if (remain < mps) - mps = remain; - b = ohcist.transfer_descriptor.cbp; - // if sending ... - if (pid != InPid) { - // ... get mps bytes - for (int c = 0; c < remain; c++) { - ohcist.buffer[c] = ohcist.space->read_byte(b); - b++; - if ((b & 0xfff) == 0) - b = ohcist.transfer_descriptor.be & 0xfffff000; - } - } - // should check for time available - // execute transaction - done = ohcist.address[ohcist.endpoint_descriptor.fa].function->execute_transfer(ohcist.endpoint_descriptor.en, pid, ohcist.buffer, mps); - // if receiving ... - if (pid == InPid) { - // ... store done bytes - for (int c = 0; c < done; c++) { - ohcist.space->write_byte(b, ohcist.buffer[c]); - b++; - if ((b & 0xfff) == 0) - b = ohcist.transfer_descriptor.be & 0xfffff000; - } - } - // status writeback (CompletionCode field, DataToggleControl field, CurrentBufferPointer field, ErrorCount field) - ohcist.transfer_descriptor.cc = NoError; - ohcist.transfer_descriptor.t = (ohcist.transfer_descriptor.t ^ 1) | 2; - // if all data is transferred (or there was no data to transfer) cbp must be 0, otherwise it must be updated - if (done == remain) - b = 0; - ohcist.transfer_descriptor.cbp = b; - ohcist.transfer_descriptor.ec = 0; - retire = false; - if ((done == mps) && (done == remain)) { - retire = true; - } - if ((done != mps) && (done <= remain)) - retire = true; - if (done == 0) - retire = true; - if (retire == true) { - // retire transfer descriptor - a = ohcist.endpoint_descriptor.headp; - ohcist.endpoint_descriptor.headp = ohcist.transfer_descriptor.nexttd; - ohcist.transfer_descriptor.nexttd = ohcist.hc_regs[HcDoneHead]; - ohcist.hc_regs[HcDoneHead] = a; - ohcist.endpoint_descriptor.c = ohcist.transfer_descriptor.t & 1; - if (ohcist.transfer_descriptor.di != 7) { - if (ohcist.transfer_descriptor.di < ohcist.writebackdonehadcounter) - ohcist.writebackdonehadcounter = ohcist.transfer_descriptor.di; - } - usb_ohci_writeback_transfer_descriptor(a); - usb_ohci_writeback_endpoint_descriptor(ohcist.hc_regs[HcBulkCurrentED]); - } - else { - usb_ohci_writeback_transfer_descriptor(ohcist.endpoint_descriptor.headp); - } - } - else { - // no transfer descriptors for this endpoint, so go to next endpoint - ohcist.hc_regs[HcBulkCurrentED] = ohcist.endpoint_descriptor.nexted; - } - } - else { - // not enabled, so go to next endpoint - ohcist.hc_regs[HcBulkCurrentED] = ohcist.endpoint_descriptor.nexted; - } - } - // go to the next list - if ((ohcist.hc_regs[HcCommandStatus] & CLF) && (ohcist.hc_regs[HcControl] & CLE)) - list = 1; // go to control list if enabled and filled - else if ((ohcist.hc_regs[HcCommandStatus] & BLF) && (ohcist.hc_regs[HcControl] & BLE)) - list = 2; // otherwise stay in bulk list if enabled and filled - else - list = 0; // if no control or bulk lists, go to periodic list - } - } - } - if (ohcist.framenumber == 0) - ohcist.hc_regs[HcInterruptStatus] |= FrameNumberOverflow; - ohcist.hc_regs[HcInterruptStatus] |= StartofFrame; - if ((ohcist.writebackdonehadcounter != 0) && (ohcist.writebackdonehadcounter != 7)) - ohcist.writebackdonehadcounter--; - if ((ohcist.writebackdonehadcounter == 0) && ((ohcist.hc_regs[HcInterruptStatus] & WritebackDoneHead) == 0)) { - uint32_t b = 0; - - if ((ohcist.hc_regs[HcInterruptStatus] & ohcist.hc_regs[HcInterruptEnable]) != WritebackDoneHead) - b = 1; - ohcist.hc_regs[HcInterruptStatus] |= WritebackDoneHead; - ohcist.space->write_dword(hcca + 0x84, ohcist.hc_regs[HcDoneHead] | b); - ohcist.hc_regs[HcDoneHead] = 0; - ohcist.writebackdonehadcounter = 7; - } - } - if (changed != 0) { - ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; - } - usb_ohci_interrupts(); -} - -void ohci_usb_controller::usb_ohci_plug(int port, ohci_function *function) -{ - if ((port > 0) && (port <= 4)) { - ohcist.ports[port].function = function; - ohcist.ports[port].address = -1; - ohcist.hc_regs[HcRhPortStatus1 + port - 1] = CCS | CSC; - if (ohcist.state != UsbReset) - { - ohcist.hc_regs[HcInterruptStatus] |= RootHubStatusChange; - usb_ohci_interrupts(); - } - } -} - -void ohci_usb_controller::usb_ohci_interrupts() -{ - if (((ohcist.hc_regs[HcInterruptStatus] & ohcist.hc_regs[HcInterruptEnable]) != 0) && ((ohcist.hc_regs[HcInterruptEnable] & MasterInterruptEnable) != 0)) - { - irq_callback(1); - } else - { - irq_callback(0); - } -} - -void ohci_usb_controller::usb_ohci_read_endpoint_descriptor(uint32_t address) -{ - uint32_t w; - - w = ohcist.space->read_dword(address); - ohcist.endpoint_descriptor.word0 = w; - ohcist.endpoint_descriptor.fa = w & 0x7f; - ohcist.endpoint_descriptor.en = (w >> 7) & 15; - ohcist.endpoint_descriptor.d = (w >> 11) & 3; - ohcist.endpoint_descriptor.s = (w >> 13) & 1; - ohcist.endpoint_descriptor.k = (w >> 14) & 1; - ohcist.endpoint_descriptor.f = (w >> 15) & 1; - ohcist.endpoint_descriptor.mps = (w >> 16) & 0x7ff; - ohcist.endpoint_descriptor.tailp = ohcist.space->read_dword(address + 4); - w = ohcist.space->read_dword(address + 8); - ohcist.endpoint_descriptor.headp = w & 0xfffffffc; - ohcist.endpoint_descriptor.h = w & 1; - ohcist.endpoint_descriptor.c = (w >> 1) & 1; - ohcist.endpoint_descriptor.nexted = ohcist.space->read_dword(address + 12); -} - -void ohci_usb_controller::usb_ohci_writeback_endpoint_descriptor(uint32_t address) -{ - uint32_t w; - - w = ohcist.endpoint_descriptor.word0 & 0xf8000000; - w = w | (ohcist.endpoint_descriptor.mps << 16) | (ohcist.endpoint_descriptor.f << 15) | (ohcist.endpoint_descriptor.k << 14) | (ohcist.endpoint_descriptor.s << 13) | (ohcist.endpoint_descriptor.d << 11) | (ohcist.endpoint_descriptor.en << 7) | ohcist.endpoint_descriptor.fa; - ohcist.space->write_dword(address, w); - w = ohcist.endpoint_descriptor.headp | (ohcist.endpoint_descriptor.c << 1) | ohcist.endpoint_descriptor.h; - ohcist.space->write_dword(address + 8, w); -} - -void ohci_usb_controller::usb_ohci_read_transfer_descriptor(uint32_t address) -{ - uint32_t w; - - w = ohcist.space->read_dword(address); - ohcist.transfer_descriptor.word0 = w; - ohcist.transfer_descriptor.cc = (w >> 28) & 15; - ohcist.transfer_descriptor.ec = (w >> 26) & 3; - ohcist.transfer_descriptor.t = (w >> 24) & 3; - ohcist.transfer_descriptor.di = (w >> 21) & 7; - ohcist.transfer_descriptor.dp = (w >> 19) & 3; - ohcist.transfer_descriptor.r = (w >> 18) & 1; - ohcist.transfer_descriptor.cbp = ohcist.space->read_dword(address + 4); - ohcist.transfer_descriptor.nexttd = ohcist.space->read_dword(address + 8); - ohcist.transfer_descriptor.be = ohcist.space->read_dword(address + 12); -} - -void ohci_usb_controller::usb_ohci_writeback_transfer_descriptor(uint32_t address) -{ - uint32_t w; - - w = ohcist.transfer_descriptor.word0 & 0x0003ffff; - w = w | (ohcist.transfer_descriptor.cc << 28) | (ohcist.transfer_descriptor.ec << 26) | (ohcist.transfer_descriptor.t << 24) | (ohcist.transfer_descriptor.di << 21) | (ohcist.transfer_descriptor.dp << 19) | (ohcist.transfer_descriptor.r << 18); - ohcist.space->write_dword(address, w); - ohcist.space->write_dword(address + 4, ohcist.transfer_descriptor.cbp); - ohcist.space->write_dword(address + 8, ohcist.transfer_descriptor.nexttd); -} - -void ohci_usb_controller::usb_ohci_read_isochronous_transfer_descriptor(uint32_t address) -{ - uint32_t 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; - 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); - ohcist.isochronous_transfer_descriptor.offset[0] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[1] = (w >> 16) & 0xffff; - w = ohcist.space->read_dword(address + 20); - ohcist.isochronous_transfer_descriptor.offset[2] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[3] = (w >> 16) & 0xffff; - w = ohcist.space->read_dword(address + 24); - ohcist.isochronous_transfer_descriptor.offset[4] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[5] = (w >> 16) & 0xffff; - w = ohcist.space->read_dword(address + 28); - ohcist.isochronous_transfer_descriptor.offset[6] = w & 0xffff; - ohcist.isochronous_transfer_descriptor.offset[7] = (w >> 16) & 0xffff; -} - -void ohci_usb_controller::usb_ohci_writeback_isochronous_transfer_descriptor(uint32_t address) -{ - uint32_t 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); -} - -void ohci_usb_controller::usb_ohci_device_address_changed(int old_address, int new_address) -{ - ohcist.address[new_address].function = ohcist.address[old_address].function; - ohcist.address[new_address].port = ohcist.address[old_address].port; - ohcist.address[old_address].port = -1; -} - -/* - * Base class for usb devices - */ - -ohci_function::ohci_function() -{ -} - -void ohci_function::initialize(running_machine &machine) -{ - state = DefaultState; - descriptors = auto_alloc_array(machine, uint8_t, 1024); - descriptors_pos = 0; - address = 0; - newaddress = 0; - for (int e = 0; e < 256;e++) { - endpoints[e].type = -1; - endpoints[e].controldirection = 0; - endpoints[e].controltype = 0; - endpoints[e].controlrecipient = 0; - endpoints[e].remain = 0; - endpoints[e].position = nullptr; - } - endpoints[0].type = ControlEndpoint; - wantstatuscallback = false; - settingaddress = false; - configurationvalue = 0; - selected_configuration = nullptr; - latest_configuration = nullptr; - latest_alternate = nullptr; -} - -void ohci_function::set_bus_manager(ohci_usb_controller *usb_bus_manager) -{ - busmanager = usb_bus_manager; -} - - -void ohci_function::add_device_descriptor(const USBStandardDeviceDescriptor &descriptor) -{ - uint8_t *p = descriptors + descriptors_pos; - - p[0] = descriptor.bLength; - p[1] = descriptor.bDescriptorType; - p[2] = descriptor.bcdUSB & 255; - p[3] = descriptor.bcdUSB >> 8; - p[4] = descriptor.bDeviceClass; - p[5] = descriptor.bDeviceSubClass; - p[6] = descriptor.bDeviceProtocol; - p[7] = descriptor.bMaxPacketSize0; - p[8] = descriptor.idVendor & 255; - p[9] = descriptor.idVendor >> 8; - p[10] = descriptor.idProduct & 255; - p[11] = descriptor.idProduct >> 8; - p[12] = descriptor.bcdDevice & 255; - p[13] = descriptor.bcdDevice >> 8; - p[14] = descriptor.iManufacturer; - p[15] = descriptor.iProduct; - p[16] = descriptor.iSerialNumber; - p[17] = descriptor.bNumConfigurations; - descriptors_pos += descriptor.bLength; - memcpy(&device_descriptor, &descriptor, sizeof(USBStandardDeviceDescriptor)); -} - -void ohci_function::add_configuration_descriptor(const USBStandardConfigurationDescriptor &descriptor) -{ - usb_device_configuration *c = new usb_device_configuration; - uint8_t *p = descriptors + descriptors_pos; - - p[0] = descriptor.bLength; - p[1] = descriptor.bDescriptorType; - p[2] = descriptor.wTotalLength & 255; - p[3] = descriptor.wTotalLength >> 8; - p[4] = descriptor.bNumInterfaces; - p[5] = descriptor.bConfigurationValue; - p[6] = descriptor.iConfiguration; - p[7] = descriptor.bmAttributes; - p[8] = descriptor.MaxPower; - c->position = p; - c->size = descriptor.bLength; - descriptors_pos += descriptor.bLength; - memcpy(&c->configuration_descriptor, &descriptor, sizeof(USBStandardConfigurationDescriptor)); - configurations.push_front(c); - latest_configuration = c; - latest_alternate = nullptr; -} - -void ohci_function::add_interface_descriptor(const USBStandardInterfaceDescriptor &descriptor) -{ - usb_device_interfac *ii; - usb_device_interfac_alternate *aa; - uint8_t *p = descriptors + descriptors_pos; - - if (latest_configuration == nullptr) - return; - p[0] = descriptor.bLength; - p[1] = descriptor.bDescriptorType; - p[2] = descriptor.bInterfaceNumber; - p[3] = descriptor.bAlternateSetting; - p[4] = descriptor.bNumEndpoints; - p[5] = descriptor.bInterfaceClass; - p[6] = descriptor.bInterfaceSubClass; - p[7] = descriptor.bInterfaceProtocol; - p[8] = descriptor.iInterface; - descriptors_pos += descriptor.bLength; - latest_configuration->size += descriptor.bLength; - for (auto i = latest_configuration->interfaces.begin(); i != latest_configuration->interfaces.end(); ++i) - { - if ((*i)->alternate_settings.front()->interface_descriptor.bInterfaceNumber == descriptor.bInterfaceNumber) - { - (*i)->size += descriptor.bLength; - latest_configuration->interfaces.front()->size += descriptor.bLength; - aa = new usb_device_interfac_alternate; - memcpy(&aa->interface_descriptor, &descriptor, sizeof(USBStandardInterfaceDescriptor)); - aa->position = p; - aa->size = descriptor.bLength; - (*i)->alternate_settings.push_front(aa); - latest_alternate = aa; - return; - } - } - ii = new usb_device_interfac; - aa = new usb_device_interfac_alternate; - memcpy(&aa->interface_descriptor, &descriptor, sizeof(USBStandardInterfaceDescriptor)); - aa->position = p; - aa->size = descriptor.bLength; - ii->position = p; - ii->size = descriptor.bLength; - ii->selected_alternate = -1; - ii->alternate_settings.push_front(aa); - latest_alternate = aa; - latest_configuration->interfaces.push_front(ii); -} - -void ohci_function::add_endpoint_descriptor(const USBStandardEndpointDescriptor &descriptor) -{ - uint8_t *p = descriptors + descriptors_pos; - - if (latest_alternate == nullptr) - return; - p[0] = descriptor.bLength; - p[1] = descriptor.bDescriptorType; - p[2] = descriptor.bEndpointAddress; - p[3] = descriptor.bmAttributes; - p[4] = descriptor.wMaxPacketSize & 255; - p[5] = descriptor.wMaxPacketSize >> 8; - p[6] = descriptor.bInterval; - descriptors_pos += descriptor.bLength; - latest_alternate->endpoint_descriptors.push_front(descriptor); - latest_alternate->size += descriptor.bLength; - latest_configuration->interfaces.front()->size += descriptor.bLength; - latest_configuration->size += descriptor.bLength; -} - -void ohci_function::add_string_descriptor(const uint8_t *descriptor) -{ - usb_device_string *ss; - int len = descriptor[0]; - uint8_t *p = descriptors + descriptors_pos; - - - ss = new usb_device_string; - memcpy(p, descriptor, len); - descriptors_pos += len; - ss->size = len; - ss->position = p; - device_strings.push_front(ss); - //latest_configuration->size += len; -} - -void ohci_function::select_configuration(int index) -{ - configurationvalue = index; - for (auto c = configurations.begin(); c != configurations.end(); ++c) - { - if ((*c)->configuration_descriptor.bConfigurationValue == index) - { - selected_configuration = *c; - // by default, activate alternate setting 0 in each interface - for (auto i = (*c)->interfaces.begin(); i != (*c)->interfaces.end(); ++i) - { - (*i)->selected_alternate = 0; - for (auto a = (*i)->alternate_settings.begin(); a != (*i)->alternate_settings.end(); ++a) - { - if ((*a)->interface_descriptor.bAlternateSetting == 0) - { - // activate the endpoints in interface i alternate setting 0 - for (auto e = (*a)->endpoint_descriptors.begin(); e != (*a)->endpoint_descriptors.end(); ++e) - { - endpoints[e->bEndpointAddress].type = e->bmAttributes & 3; - endpoints[e->bEndpointAddress].remain = 0; - } - break; - } - } - } - break; - } - } -} - -void ohci_function::select_alternate(int interfacei, int index) -{ - // among all the interfaces in the currently selected configuration, consider interface interfacei - for (auto i = selected_configuration->interfaces.begin(); i != selected_configuration->interfaces.end(); ++i) - { - // deactivate the endpoints in the currently selected alternate setting for interface interfacei - for (auto a = (*i)->alternate_settings.begin(); a != (*i)->alternate_settings.end(); ++a) - { - if (((*a)->interface_descriptor.bInterfaceNumber == interfacei) && ((*a)->interface_descriptor.bAlternateSetting == (*i)->selected_alternate)) - { - for (auto e = (*a)->endpoint_descriptors.begin(); e != (*a)->endpoint_descriptors.end(); ++e) - { - endpoints[e->bEndpointAddress].type = -1; - } - break; - } - } - // activate the endpoints in the newly selected alternate setting - for (auto a = (*i)->alternate_settings.begin(); a != (*i)->alternate_settings.end(); ++a) - { - if (((*a)->interface_descriptor.bInterfaceNumber == interfacei) && ((*a)->interface_descriptor.bAlternateSetting == index)) - { - (*i)->selected_alternate = index; - for (auto e = (*a)->endpoint_descriptors.begin(); e != (*a)->endpoint_descriptors.end(); ++e) - { - endpoints[e->bEndpointAddress].type = e->bmAttributes & 3; - endpoints[e->bEndpointAddress].remain = 0; - } - break; - } - } - } -} - -int ohci_function::find_alternate(int interfacei) -{ - // find the active alternate setting for interface inteerfacei - for (auto i = selected_configuration->interfaces.begin(); i != selected_configuration->interfaces.end(); ++i) - { - for (auto a = (*i)->alternate_settings.begin(); a != (*i)->alternate_settings.end(); ++a) - { - if ((*a)->interface_descriptor.bInterfaceNumber == interfacei) - { - return (*i)->selected_alternate; - } - } - } - return 0; -} - -uint8_t *ohci_function::position_device_descriptor(int &size) -{ - size = descriptors_pos; // descriptors[0]; - return descriptors; -} - -uint8_t *ohci_function::position_configuration_descriptor(int index, int &size) -{ - for (auto c = configurations.begin(); c != configurations.end(); ++c) - { - if ((*c)->configuration_descriptor.bConfigurationValue == (index + 1)) - { - size = (*c)->size; - return (*c)->position; - } - } - size = 0; - return nullptr; -} - -uint8_t *ohci_function::position_string_descriptor(int index, int &size) -{ - int i = 0; - - for (auto s = device_strings.begin(); s != device_strings.end(); ++s) - { - if (index == i) - { - size = (*s)->size; - return (*s)->position; - } - i++; - } - size = 0; - return nullptr; -} - -void ohci_function::execute_reset() -{ - address = 0; - newaddress = 0; -} - -int ohci_function::execute_transfer(int endpoint, int pid, uint8_t *buffer, int size) -{ - int descriptortype, descriptorindex; - - if (pid == SetupPid) { - USBSetupPacket *p=(USBSetupPacket *)buffer; - // control transfers are done in 3 stages: first the setup stage, then an optional data stage, then a status stage - // so there are 3 cases: - // 1- control transfer with a data stage where the host sends data to the device - // in this case the sequence of pids transferred is control pid, data out pid, data in pid - // 2- control transfer with a data stage where the host receives data from the device - // in this case the sequence of pids transferred is control pid, data in pid, data out pid - // 3- control transfer without a data stage - // in this case the sequence of pids transferred is control pid, data in pid - // define direction 0:host->device 1:device->host - // direction == 1 -> IN data stage and OUT status stage - // direction == 0 -> OUT data stage and IN status stage - // data stage not present -> IN status stage - endpoints[endpoint].controldirection = (p->bmRequestType & 128) >> 7; - endpoints[endpoint].controltype = (p->bmRequestType & 0x60) >> 5; - endpoints[endpoint].controlrecipient = p->bmRequestType & 0x1f; - wantstatuscallback = false; - if (endpoint == 0) { - endpoints[endpoint].position = nullptr; - // number of byte to transfer in data stage (0 no data stage) - endpoints[endpoint].remain = p->wLength; - // if standard device request - if ((endpoints[endpoint].controltype == StandardType) && (endpoints[endpoint].controlrecipient == DeviceRecipient)) { - switch (p->bRequest) { - case GET_STATUS: - return handle_get_status_request(endpoint, p); - break; - case CLEAR_FEATURE: - return handle_clear_feature_request(endpoint, p); - break; - case SET_FEATURE: - return handle_set_feature_request(endpoint, p); - break; - case SET_ADDRESS: - newaddress = p->wValue; - settingaddress = true; - break; - case GET_DESCRIPTOR: - descriptortype = p->wValue >> 8; - descriptorindex = p->wValue & 255; - if (descriptortype == DEVICE) { // device descriptor - endpoints[endpoint].position = position_device_descriptor(endpoints[endpoint].remain); - } - else if (descriptortype == CONFIGURATION) { // configuration descriptor - endpoints[endpoint].position = position_configuration_descriptor(descriptorindex, endpoints[endpoint].remain); - } - else if (descriptortype == STRING) { // string descriptor - //p->wIndex; language id - endpoints[endpoint].position = position_string_descriptor(descriptorindex, endpoints[endpoint].remain); - } - else - endpoints[endpoint].remain = 0; - if (endpoints[endpoint].remain > p->wLength) - endpoints[endpoint].remain = p->wLength; - break; - case SET_CONFIGURATION: - if (p->wValue == 0) - state = AddressState; - else { - select_configuration(p->wValue); - state = ConfiguredState; - } - break; - case SET_INTERFACE: - select_alternate(p->wIndex, p->wValue); - break; - case SET_DESCRIPTOR: - return handle_set_descriptor_request(endpoint, p); - break; - case GET_CONFIGURATION: - endpoints[endpoint].buffer[0] = (uint8_t)configurationvalue; - endpoints[endpoint].position = endpoints[endpoint].buffer; - endpoints[endpoint].remain = 1; - if (p->wLength == 0) - endpoints[endpoint].remain = 0; - break; - case GET_INTERFACE: - endpoints[endpoint].buffer[0] = (uint8_t)find_alternate(p->wIndex); - endpoints[endpoint].position = endpoints[endpoint].buffer; - endpoints[endpoint].remain = 1; - if (p->wLength == 0) - endpoints[endpoint].remain = 0; - break; - case SYNCH_FRAME: - return handle_synch_frame_request(endpoint, p); - default: - return handle_nonstandard_request(endpoint, p); - break; - } - } - else - return handle_nonstandard_request(endpoint, p); - size = 0; - } - else - return handle_nonstandard_request(endpoint, p); - } - else if (pid == InPid) { - if (endpoints[endpoint].type == ControlEndpoint) { //if (endpoint == 0) { - // 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 ((endpoints[endpoint].remain == 0) && (size == 0)) { - if ((endpoint == 0) && (settingaddress == true)) - { - // set of address is active at end of status stage - busmanager->usb_ohci_device_address_changed(address, newaddress); - address = newaddress; - settingaddress = false; - state = AddressState; - } - if (wantstatuscallback == true) - handle_status_stage(endpoint); - wantstatuscallback = false; - return 0; - } - // case ==1, give data - // case ==0, nothing - // if device->host, since InPid then this is data stage - if (endpoints[endpoint].controldirection == DeviceToHost) { - // data stage - if (size > endpoints[endpoint].remain) - size = endpoints[endpoint].remain; - if (endpoints[endpoint].position != nullptr) - memcpy(buffer, endpoints[endpoint].position, size); - endpoints[endpoint].position = endpoints[endpoint].position + size; - endpoints[endpoint].remain = endpoints[endpoint].remain - size; - } - else { - if (wantstatuscallback == true) - handle_status_stage(endpoint); - wantstatuscallback = false; - } - } - else if (endpoints[endpoint].type == BulkEndpoint) - return handle_bulk_pid(endpoint, pid, buffer, size); - else if (endpoints[endpoint].type == InterruptEndpoint) - return handle_interrupt_pid(endpoint, pid, buffer, size); - else if (endpoints[endpoint].type == IsochronousEndpoint) - return handle_isochronous_pid(endpoint, pid, buffer, size); - else - return -1; - } - else if (pid == OutPid) { - if (endpoints[endpoint].type == ControlEndpoint) { - // case ==1, nothing - // case ==0, give data - // if host->device, since OutPid then this is data stage - if (endpoints[endpoint].controldirection == HostToDevice) { - // data stage - if (size > endpoints[endpoint].remain) - size = endpoints[endpoint].remain; - if (endpoints[endpoint].position != nullptr) - memcpy(endpoints[endpoint].position, buffer, size); - endpoints[endpoint].position = endpoints[endpoint].position + size; - endpoints[endpoint].remain = endpoints[endpoint].remain - size; - } - else { - if (wantstatuscallback == true) - handle_status_stage(endpoint); - wantstatuscallback = false; - } - } - else if (endpoints[endpoint].type == BulkEndpoint) - return handle_bulk_pid(endpoint, pid, buffer, size); - else if (endpoints[endpoint].type == InterruptEndpoint) - return handle_interrupt_pid(endpoint, pid, buffer, size); - else if (endpoints[endpoint].type == IsochronousEndpoint) - return handle_isochronous_pid(endpoint, pid, buffer, size); - else - return -1; - } - return size; -} - -/* - * Usb port connector - */ - -DEFINE_DEVICE_TYPE(OHCI_USB_CONNECTOR, ohci_usb_connector, "usb_connector", "Usb Connector Abstraction"); - -ohci_usb_connector::ohci_usb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, OHCI_USB_CONNECTOR, tag, owner, clock), - device_slot_interface(mconfig, *this) -{ -} - -ohci_usb_connector::~ohci_usb_connector() -{ -} - -void ohci_usb_connector::device_start() -{ -} - -ohci_function* ohci_usb_connector::get_device() -{ - return dynamic_cast<ohci_function *>(get_card_device()); -} - -/* - * Game controller usb device - */ - -INPUT_PORTS_START(xbox_controller) - PORT_START("ThumbstickLh") // left analog thumbstick horizontal movement - PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("ThumbstickLh") PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_J) PORT_CODE_INC(KEYCODE_L) - PORT_START("ThumbstickLv") // left analog thumbstick vertical movement - PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("ThumbstickLv") PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_K) PORT_CODE_INC(KEYCODE_I) - - PORT_START("ThumbstickRh") // right analog thumbstick horizontal movement - PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("ThumbstickRh") PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_4_PAD) PORT_CODE_INC(KEYCODE_6_PAD) - PORT_START("ThumbstickRv") // right analog thumbstick vertical movement - PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("ThumbstickRv") PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_2_PAD) PORT_CODE_INC(KEYCODE_8_PAD) - - PORT_START("DPad") // pressure sensitive directional pad - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_NAME("DPad Up") - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_NAME("DPad Down") - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_NAME("DPad Left") - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_NAME("DPad Right") - - PORT_START("TriggerL") // analog trigger - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("TriggerL") PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_1_PAD) PORT_CODE_INC(KEYCODE_7_PAD) - - PORT_START("TriggerR") // analog trigger - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("TriggerR") PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_3_PAD) PORT_CODE_INC(KEYCODE_9_PAD) - - PORT_START("Buttons") // digital buttons - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Start") // Start button - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Back") // Back button - - PORT_START("AGreen") // analog button - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("A-Green") PORT_SENSITIVITY(100) PORT_KEYDELTA(32) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_A) PORT_CODE_INC(KEYCODE_Q) - - PORT_START("BRed") // analog button - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("B-Red") PORT_SENSITIVITY(100) PORT_KEYDELTA(32) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_S) PORT_CODE_INC(KEYCODE_W) - - PORT_START("XBlue") // analog button - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("X-Blue") PORT_SENSITIVITY(100) PORT_KEYDELTA(32) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_D) PORT_CODE_INC(KEYCODE_E) - - PORT_START("YYellow") // analog button - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("Y-Yellow") PORT_SENSITIVITY(100) PORT_KEYDELTA(32) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_F) PORT_CODE_INC(KEYCODE_R) - - PORT_START("Black") // analog button - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("Black") PORT_SENSITIVITY(100) PORT_KEYDELTA(32) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_G) PORT_CODE_INC(KEYCODE_T) - - PORT_START("White") // analog button - PORT_BIT(0xff, 0x00, IPT_PEDAL) PORT_NAME("White") PORT_SENSITIVITY(100) PORT_KEYDELTA(32) PORT_MINMAX(0, 0xff) - PORT_CODE_DEC(KEYCODE_H) PORT_CODE_INC(KEYCODE_Y) -INPUT_PORTS_END - -const USBStandardDeviceDescriptor ohci_game_controller_device::devdesc = { 18,1,0x110,0x00,0x00,0x00,64,0x45e,0x202,0x100,0,0,0,1 }; -const USBStandardConfigurationDescriptor ohci_game_controller_device::condesc = { 9,2,0x20,1,1,0,0x80,50 }; -const USBStandardInterfaceDescriptor ohci_game_controller_device::intdesc = { 9,4,0,0,2,0x58,0x42,0,0 }; -const USBStandardEndpointDescriptor ohci_game_controller_device::enddesc82 = { 7,5,0x82,3,0x20,4 }; -const USBStandardEndpointDescriptor ohci_game_controller_device::enddesc02 = { 7,5,0x02,3,0x20,4 }; - -DEFINE_DEVICE_TYPE(OHCI_GAME_CONTROLLER, ohci_game_controller_device, "ohci_gc", "OHCI Game Controller") - -ohci_game_controller_device::ohci_game_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, OHCI_GAME_CONTROLLER, tag, owner, clock), - ohci_function(), - device_slot_card_interface(mconfig, *this), - m_ThumbstickLh(*this, "ThumbstickLh"), - m_ThumbstickLv(*this, "ThumbstickLv"), - m_ThumbstickRh(*this, "ThumbstickRh"), - m_ThumbstickRv(*this, "ThumbstickRv"), - m_DPad(*this, "DPad"), - m_TriggerL(*this, "TriggerL"), - m_TriggerR(*this, "TriggerR"), - m_Buttons(*this, "Buttons"), - m_AGreen(*this, "AGreen"), - m_BRed(*this, "BRed"), - m_XBlue(*this, "XBlue"), - m_YYellow(*this, "YYellow"), - m_Black(*this, "Black"), - m_White(*this, "White") -{ -} - -void ohci_game_controller_device::initialize(running_machine &machine) -{ - ohci_function::initialize(machine); - add_device_descriptor(devdesc); - add_configuration_descriptor(condesc); - add_interface_descriptor(intdesc); - add_endpoint_descriptor(enddesc82); - add_endpoint_descriptor(enddesc02); -} - -int ohci_game_controller_device::handle_nonstandard_request(int endpoint, USBSetupPacket *setup) -{ - // >=8 ==42 !=0 !=0 1,3 2<20 <=20 - static const uint8_t reportinfo[16] = { 0x10,0x42 ,0x32,0x43,1 ,0x65,0x14,0x20,0x98,0xa9,0xba,0xcb,0xdc,0xed,0xfe }; - - if (endpoint != 0) - return -1; - if ((endpoints[endpoint].controltype == VendorType) && (endpoints[endpoint].controlrecipient == InterfaceRecipient)) - { - if ((setup->bRequest == GET_DESCRIPTOR) && (setup->wValue == 0x4200)) - { - endpoints[endpoint].position = (uint8_t *)reportinfo; - endpoints[endpoint].remain = 16; - return 0; - } - } - if ((endpoints[endpoint].controltype == ClassType) && (endpoints[endpoint].controlrecipient == InterfaceRecipient)) - { - if ((setup->bRequest == 1) && (setup->wValue == 0x0100)) - { - endpoints[endpoint].position = endpoints[endpoint].buffer; - endpoints[endpoint].remain = setup->wLength; - for (int n = 0; n < setup->wLength; n++) - endpoints[endpoint].buffer[n] = 0x10 ^ n; - endpoints[endpoint].buffer[2] = 0; - return 0; - } - } - if ((endpoints[endpoint].controltype == VendorType) && (endpoints[endpoint].controlrecipient == InterfaceRecipient)) - { - if ((setup->bRequest == 1) && (setup->wValue == 0x0200)) - { - endpoints[endpoint].position = endpoints[endpoint].buffer; - endpoints[endpoint].remain = setup->wLength; - for (int n = 0; n < setup->wLength; n++) - endpoints[endpoint].buffer[n] = 0x20 ^ n; - return 0; - } - } - if ((endpoints[endpoint].controltype == VendorType) && (endpoints[endpoint].controlrecipient == InterfaceRecipient)) - { - if ((setup->bRequest == 1) && (setup->wValue == 0x0100)) - { - endpoints[endpoint].position = endpoints[endpoint].buffer; - endpoints[endpoint].remain = setup->wLength; - for (int n = 0; n < setup->wLength; n++) - endpoints[endpoint].buffer[n] = 0x30 ^ n; - return 0; - } - } - return -1; -} - -int ohci_game_controller_device::handle_interrupt_pid(int endpoint, int pid, uint8_t *buffer, int size) -{ - if ((endpoint == 2) && (pid == InPid)) { - int v; - - buffer[0] = 0; - buffer[1] = 20; - v = m_DPad->read(); - v = v | (m_Buttons->read() << 4); - buffer[2] = (uint8_t)v; - buffer[3] = 0; - buffer[4] = m_AGreen->read(); - buffer[5] = m_BRed->read(); - buffer[6] = m_XBlue->read(); - buffer[7] = m_YYellow->read(); - buffer[8] = m_Black->read(); - buffer[9] = m_White->read(); - buffer[10] = m_TriggerL->read(); - buffer[11] = m_TriggerR->read(); - v = m_ThumbstickLh->read(); - v = (v - 128) * 256; - buffer[12] = (uint16_t)v & 255; - buffer[13] = (uint16_t)v >> 8; - v = m_ThumbstickLv->read(); - v = (v - 128) * 256; - buffer[14] = (uint16_t)v & 255; - buffer[15] = (uint16_t)v >> 8; - v = m_ThumbstickRh->read(); - v = (v - 128) * 256; - buffer[16] = (uint16_t)v & 255; - buffer[17] = (uint16_t)v >> 8; - v = m_ThumbstickRv->read(); - v = (v - 128) * 256; - buffer[18] = (uint16_t)v & 255; - buffer[19] = (uint16_t)v >> 8; - return size; - } - return -1; -} - -void ohci_game_controller_device::device_start() -{ - initialize(machine()); -} - -ioport_constructor ohci_game_controller_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(xbox_controller); -} |