summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/xbox_usb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/xbox_usb.cpp')
-rw-r--r--src/mame/machine/xbox_usb.cpp1555
1 files changed, 0 insertions, 1555 deletions
diff --git a/src/mame/machine/xbox_usb.cpp b/src/mame/machine/xbox_usb.cpp
deleted file mode 100644
index 59883d2ca0b..00000000000
--- a/src/mame/machine/xbox_usb.cpp
+++ /dev/null
@@ -1,1555 +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()
-{
-}
-
-uint32_t ohci_usb_controller::read(offs_t offset)
-{
- 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;
-}
-
-void ohci_usb_controller::write(offs_t offset, uint32_t data)
-{
- 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) {
- ohcist.hc_regs[HcCommandStatus] |= data;
- if (data & 1) // HostControllerReset
- {
- ohcist.hc_regs[HcControl] |= 3 << 6;
- ohcist.hc_regs[HcCommandStatus] &= ~1;
- }
- 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;
- if (hcca)
- 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
- }
- else
- list = 0;
- }
- }
- 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;
- if (hcca)
- 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, device_usb_ohci_function_interface *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
- */
-
-device_usb_ohci_function_interface::device_usb_ohci_function_interface(machine_config const &mconfig, device_t &device)
- : device_interface(device, "usbohci")
-{
-}
-
-void device_usb_ohci_function_interface::initialize()
-{
- state = DefaultState;
- descriptors = std::make_unique<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 device_usb_ohci_function_interface::set_bus_manager(ohci_usb_controller *usb_bus_manager)
-{
- busmanager = usb_bus_manager;
-}
-
-
-void device_usb_ohci_function_interface::add_device_descriptor(const USBStandardDeviceDescriptor &descriptor)
-{
- uint8_t *const 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 device_usb_ohci_function_interface::add_configuration_descriptor(const USBStandardConfigurationDescriptor &descriptor)
-{
- uint8_t *const 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;
- descriptors_pos += descriptor.bLength;
-
- configurations.emplace_front();
- usb_device_configuration &c(configurations.front());
- c.position = p;
- c.size = descriptor.bLength;
- memcpy(&c.configuration_descriptor, &descriptor, sizeof(USBStandardConfigurationDescriptor));
- latest_configuration = &c;
- latest_alternate = nullptr;
-}
-
-void device_usb_ohci_function_interface::add_interface_descriptor(const USBStandardInterfaceDescriptor &descriptor)
-{
- if (latest_configuration == nullptr)
- return;
-
- uint8_t *const p = &descriptors[descriptors_pos];
- 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)
- {
- if (i.alternate_settings.front().interface_descriptor.bInterfaceNumber == descriptor.bInterfaceNumber)
- {
- i.size += descriptor.bLength;
- latest_configuration->interfaces.front().size += descriptor.bLength;
-
- i.alternate_settings.emplace_front();
- usb_device_interfac_alternate &aa(i.alternate_settings.front());
- memcpy(&aa.interface_descriptor, &descriptor, sizeof(USBStandardInterfaceDescriptor));
- aa.position = p;
- aa.size = descriptor.bLength;
- latest_alternate = &aa;
- return;
- }
- }
-
- latest_configuration->interfaces.emplace_front();
- usb_device_interfac &ii(latest_configuration->interfaces.front());
- ii.position = p;
- ii.size = descriptor.bLength;
- ii.selected_alternate = -1;
-
- ii.alternate_settings.emplace_front();
- usb_device_interfac_alternate &aa(ii.alternate_settings.front());
- memcpy(&aa.interface_descriptor, &descriptor, sizeof(USBStandardInterfaceDescriptor));
- aa.position = p;
- aa.size = descriptor.bLength;
- latest_alternate = &aa;
-}
-
-void device_usb_ohci_function_interface::add_endpoint_descriptor(const USBStandardEndpointDescriptor &descriptor)
-{
- if (latest_alternate == nullptr)
- return;
-
- uint8_t *const p = &descriptors[descriptors_pos];
- 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 device_usb_ohci_function_interface::add_string_descriptor(const uint8_t *descriptor)
-{
- int len = descriptor[0];
- uint8_t *const p = &descriptors[descriptors_pos];
- memcpy(p, descriptor, len);
- descriptors_pos += len;
-
- device_strings.emplace_front();
- usb_device_string &ss(device_strings.front());
- ss.size = len;
- ss.position = p;
- //latest_configuration->size += len;
-}
-
-void device_usb_ohci_function_interface::select_configuration(int index)
-{
- configurationvalue = index;
- for (auto &c : configurations)
- {
- if (c.configuration_descriptor.bConfigurationValue == index)
- {
- selected_configuration = &c;
- // by default, activate alternate setting 0 in each interface
- for (auto &i : c.interfaces)
- {
- i.selected_alternate = 0;
- for (auto &a : i.alternate_settings)
- {
- if (a.interface_descriptor.bAlternateSetting == 0)
- {
- // activate the endpoints in interface i alternate setting 0
- for (auto &e : a.endpoint_descriptors)
- {
- endpoints[e.bEndpointAddress].type = e.bmAttributes & 3;
- endpoints[e.bEndpointAddress].remain = 0;
- }
- break;
- }
- }
- }
- break;
- }
- }
-}
-
-void device_usb_ohci_function_interface::select_alternate(int interfacei, int index)
-{
- // among all the interfaces in the currently selected configuration, consider interface interfacei
- for (auto &i : selected_configuration->interfaces)
- {
- // deactivate the endpoints in the currently selected alternate setting for interface interfacei
- for (auto &a : i.alternate_settings)
- {
- if ((a.interface_descriptor.bInterfaceNumber == interfacei) && (a.interface_descriptor.bAlternateSetting == i.selected_alternate))
- {
- for (auto &e : a.endpoint_descriptors)
- {
- endpoints[e.bEndpointAddress].type = -1;
- }
- break;
- }
- }
- // activate the endpoints in the newly selected alternate setting
- for (auto &a : i.alternate_settings)
- {
- if ((a.interface_descriptor.bInterfaceNumber == interfacei) && (a.interface_descriptor.bAlternateSetting == index))
- {
- i.selected_alternate = index;
- for (auto &e : a.endpoint_descriptors)
- {
- endpoints[e.bEndpointAddress].type = e.bmAttributes & 3;
- endpoints[e.bEndpointAddress].remain = 0;
- }
- break;
- }
- }
- }
-}
-
-int device_usb_ohci_function_interface::find_alternate(int interfacei)
-{
- // find the active alternate setting for interface inteerfacei
- for (const auto &i : selected_configuration->interfaces)
- {
- for (const auto &a : i.alternate_settings)
- {
- if (a.interface_descriptor.bInterfaceNumber == interfacei)
- {
- return i.selected_alternate;
- }
- }
- }
- return 0;
-}
-
-uint8_t *device_usb_ohci_function_interface::position_device_descriptor(int &size)
-{
- size = descriptors_pos; // descriptors[0];
- return &descriptors[0];
-}
-
-uint8_t *device_usb_ohci_function_interface::position_configuration_descriptor(int index, int &size)
-{
- for (const auto &c : configurations)
- {
- if (c.configuration_descriptor.bConfigurationValue == (index + 1))
- {
- size = c.size;
- return c.position;
- }
- }
- size = 0;
- return nullptr;
-}
-
-uint8_t *device_usb_ohci_function_interface::position_string_descriptor(int index, int &size)
-{
- int i = 0;
-
- for (const auto &s : device_strings)
- {
- if (index == i)
- {
- size = s.size;
- return s.position;
- }
- i++;
- }
- size = 0;
- return nullptr;
-}
-
-void device_usb_ohci_function_interface::execute_reset()
-{
- address = 0;
- newaddress = 0;
-}
-
-int device_usb_ohci_function_interface::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_single_card_slot_interface<device_usb_ohci_function_interface>(mconfig, *this)
-{
-}
-
-ohci_usb_connector::~ohci_usb_connector()
-{
-}
-
-void ohci_usb_connector::device_start()
-{
-}
-
-/*
- * 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),
- device_usb_ohci_function_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()
-{
- device_usb_ohci_function_interface::initialize();
- 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();
-}
-
-ioport_constructor ohci_game_controller_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(xbox_controller);
-}