Added skeleton HC initialization
This commit is contained in:
parent
403f9cb710
commit
b61339f0ea
|
@ -35,7 +35,60 @@
|
|||
// ******************************************************************
|
||||
|
||||
#include "OHCI.h"
|
||||
#include "..\CxbxKrnl\CxbxKrnl.h"
|
||||
|
||||
// global pointers to the two USB host controllers available on the Xbox
|
||||
OHCI_State* g_pHostController1 = nullptr;
|
||||
OHCI_State* g_pHostController2 = nullptr;
|
||||
|
||||
|
||||
void OHCI_State::HC_Reset(USB_State new_state)
|
||||
{
|
||||
// The usb state can be USB_Suspend if it is a software reset, and USB_Reset if it is a hardware
|
||||
// reset or cold boot
|
||||
|
||||
// TODO: stop all the list processing here
|
||||
|
||||
// Reset all registers
|
||||
if (new_state == USB_Reset) {
|
||||
// Remark: the standard says that RemoteWakeupConnected bit should be set during POST, cleared during hw reset
|
||||
// and ignored during a sw reset. However, VBox sets it on hw reset and XQEMU clears it. Considering that the Xbox
|
||||
// doesn't do POST, I will clear it.
|
||||
HC_Registers.HcControl = 0;
|
||||
}
|
||||
else {
|
||||
HC_Registers.HcControl &= (OHCI_CTL_IR | OHCI_CTL_RWC);
|
||||
}
|
||||
HC_Registers.HcControl = ~OHCI_CTL_HCFS;
|
||||
HC_Registers.HcControl = new_state;
|
||||
HC_Registers.HcCommandStatus = 0;
|
||||
HC_Registers.HcInterruptStatus = 0;
|
||||
HC_Registers.HcInterruptEnable = OHCI_INTR_MASTER_INTERRUPT_ENABLED; // enable interrupts
|
||||
|
||||
HC_Registers.HcHCCA = 0;
|
||||
HC_Registers.HcPeriodCurrentED = 0;
|
||||
HC_Registers.HcControlHeadED = HC_Registers.HcControlCurrentED = 0;
|
||||
HC_Registers.HcBulkHeadED = HC_Registers.HcBulkCurrentED = 0;
|
||||
HC_Registers.HcDoneHead = 0;
|
||||
|
||||
HC_Registers.HcFmInterval = 0;
|
||||
HC_Registers.HcFmInterval |= (0x2778 << 16); // TBD according to the standard, using what XQEMU sets (FSLargestDataPacket)
|
||||
HC_Registers.HcFmInterval |= (0 << 31); // redundant, but we'll do it for the sake of completeness (FrameIntervalToggle)
|
||||
HC_Registers.HcFmInterval |= 0x2EDF; // bit-time of a frame. 1 frame = 1 ms (FrameInterval)
|
||||
HC_Registers.HcFmRemaining = 0;
|
||||
HC_Registers.HcFmNumber = 0;
|
||||
HC_Registers.HcPeriodicStart = 0;
|
||||
|
||||
HC_Registers.HcRhDescriptorA = OHCI_RHA_NPS | 2; // The xbox lacks the hw to switch off the power on the ports and has 2 ports per HC
|
||||
HC_Registers.HcRhDescriptorB = 0; // The attached devices are removable and use PowerSwitchingMode to control the power on the ports
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
OHCIPort* Port = &HC_Registers.RhPort[i];
|
||||
Port->HcRhPortStatus = 0;
|
||||
//if (Port->port.device && Port->port.device->attached) {
|
||||
//usb_port_reset(&Port->port);
|
||||
//}
|
||||
}
|
||||
|
||||
DbgPrintf("usb-ohci: Reset\n");
|
||||
}
|
|
@ -40,6 +40,47 @@
|
|||
#include <stdint.h>
|
||||
#include "Cxbx.h"
|
||||
|
||||
|
||||
// Abbreviations used:
|
||||
// OHCI: Open Host Controller Interface; the standard used on the xbox to comunicate with the usb devices
|
||||
// HC: Host Controller; the hardware which interfaces with the usb device and the usb driver
|
||||
// HCD: Host Controller Driver; software which talks to the HC, it's linked in the xbe
|
||||
|
||||
|
||||
// These macros are used to access the bits in the various registers
|
||||
// HcControl
|
||||
#define OHCI_CTL_CBSR ((1<<0)|(1<<1)) // ControlBulkServiceRatio
|
||||
#define OHCI_CTL_PLE (1<<2) // PeriodicListEnable
|
||||
#define OHCI_CTL_IE (1<<3) // IsochronousEnable
|
||||
#define OHCI_CTL_CLE (1<<4) // ControlListEnable
|
||||
#define OHCI_CTL_BLE (1<<5) // BulkListEnable
|
||||
#define OHCI_CTL_HCFS ((1<<6)|(1<<7)) // HostControllerFunctionalState
|
||||
#define OHCI_CTL_IR (1<<8) // InterruptRouting
|
||||
#define OHCI_CTL_RWC (1<<9) // RemoteWakeupConnected
|
||||
#define OHCI_CTL_RWE (1<<10) // RemoteWakeupEnable
|
||||
// HcInterruptEnable, HcInterruptDisable
|
||||
#define OHCI_INTR_MASTER_INTERRUPT_ENABLED (1<<31) // MasterInterruptEnable
|
||||
// HcRhDescriptorA
|
||||
#define OHCI_RHA_PSM (1<<8) // PowerSwitchingMode
|
||||
#define OHCI_RHA_NPS (1<<9) // NoPowerSwitching
|
||||
#define OHCI_RHA_DT (1<<10) // DeviceType
|
||||
#define OHCI_RHA_OCPM (1<<11) // OverCurrentProtectionMode
|
||||
#define OHCI_RHA_NOCP (1<<12) // NoOverCurrentProtection
|
||||
|
||||
// Struct describing the status of a usb port
|
||||
struct USBPort {
|
||||
//USBDevice* device;
|
||||
//TODO
|
||||
};
|
||||
|
||||
// Small struct used to hold the HcRhPortStatus register and the usb port status
|
||||
typedef struct _OHCIPort
|
||||
{
|
||||
USBPort port;
|
||||
uint32_t HcRhPortStatus;
|
||||
}
|
||||
OHCIPort;
|
||||
|
||||
// All these registers are well documented in the OHCI standard
|
||||
typedef struct _OHCI_Registers
|
||||
{
|
||||
|
@ -71,11 +112,20 @@ typedef struct _OHCI_Registers
|
|||
uint32_t HcRhDescriptorA;
|
||||
uint32_t HcRhDescriptorB;
|
||||
uint32_t HcRhStatus;
|
||||
uint32_t HcRhPortStatus1; // 2 ports per HC, for a total of 4 USB ports
|
||||
uint32_t HcRhPortStatus2;
|
||||
OHCIPort RhPort[2]; // 2 ports per HC, for a total of 4 USB ports
|
||||
}
|
||||
OHCI_Registers;
|
||||
|
||||
// enum indicating the current HC state
|
||||
typedef enum _USB_State
|
||||
{
|
||||
USB_Reset = 0x00,
|
||||
USB_Resume = 0x40,
|
||||
USB_Operational = 0x80,
|
||||
USB_Suspend = 0xC0,
|
||||
}
|
||||
USB_State;
|
||||
|
||||
|
||||
/* OHCI class representing the state of the HC */
|
||||
class OHCI_State
|
||||
|
@ -86,13 +136,15 @@ class OHCI_State
|
|||
// destructor
|
||||
~OHCI_State() {}
|
||||
// read a register
|
||||
uint32_t ReadRegister(xbaddr addr);
|
||||
uint32_t HC_ReadRegister(xbaddr addr);
|
||||
// write a register
|
||||
void WriteRegister(xbaddr addr, uint32_t value);
|
||||
void HC_WriteRegister(xbaddr addr, uint32_t value);
|
||||
// reset the HC to the default state
|
||||
void HC_Reset(USB_State new_state);
|
||||
|
||||
private:
|
||||
// all the registers available on the OHCI standard
|
||||
OHCI_Registers Registers;
|
||||
OHCI_Registers HC_Registers;
|
||||
};
|
||||
|
||||
extern OHCI_State* g_pHostController1;
|
||||
|
|
|
@ -51,7 +51,12 @@ void USBDevice::Init(unsigned int address)
|
|||
m_DeviceId = 0x01C2;
|
||||
m_VendorId = PCI_VENDOR_ID_NVIDIA;
|
||||
|
||||
// TODO: construct the OHCI object
|
||||
g_pHostController1 = new OHCI_State;
|
||||
g_pHostController2 = new OHCI_State;
|
||||
|
||||
// We can use the USB_Reset state to also cold boot the HC during initialization
|
||||
g_pHostController1->HC_Reset(USB_Reset);
|
||||
g_pHostController2->HC_Reset(USB_Reset);
|
||||
}
|
||||
|
||||
uint32_t USBDevice::MMIORead(int barIndex, uint32_t addr, unsigned size)
|
||||
|
@ -62,11 +67,11 @@ uint32_t USBDevice::MMIORead(int barIndex, uint32_t addr, unsigned size)
|
|||
// Figure out the correct OHCI object and read the register
|
||||
if (addr >= USB1_BASE) {
|
||||
// USB1 queried
|
||||
return g_pHostController2->ReadRegister(addr);
|
||||
return g_pHostController2->HC_ReadRegister(addr);
|
||||
}
|
||||
|
||||
// USB0 queried
|
||||
return g_pHostController1->ReadRegister(addr);
|
||||
return g_pHostController1->HC_ReadRegister(addr);
|
||||
}
|
||||
|
||||
void USBDevice::MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size)
|
||||
|
@ -77,10 +82,10 @@ void USBDevice::MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned
|
|||
// Figure out the correct OHCI object and write the value to the register
|
||||
if (addr >= USB1_BASE) {
|
||||
// USB1 queried
|
||||
g_pHostController2->WriteRegister(addr, value);
|
||||
g_pHostController2->HC_WriteRegister(addr, value);
|
||||
return;
|
||||
}
|
||||
|
||||
// USB0 queried
|
||||
g_pHostController1->WriteRegister(addr, value);
|
||||
g_pHostController1->HC_WriteRegister(addr, value);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue