Added skeleton HC initialization
This commit is contained in:
parent
403f9cb710
commit
b61339f0ea
|
@ -35,7 +35,60 @@
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
||||||
#include "OHCI.h"
|
#include "OHCI.h"
|
||||||
|
#include "..\CxbxKrnl\CxbxKrnl.h"
|
||||||
|
|
||||||
// global pointers to the two USB host controllers available on the Xbox
|
// global pointers to the two USB host controllers available on the Xbox
|
||||||
OHCI_State* g_pHostController1 = nullptr;
|
OHCI_State* g_pHostController1 = nullptr;
|
||||||
OHCI_State* g_pHostController2 = 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 <stdint.h>
|
||||||
#include "Cxbx.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
|
// All these registers are well documented in the OHCI standard
|
||||||
typedef struct _OHCI_Registers
|
typedef struct _OHCI_Registers
|
||||||
{
|
{
|
||||||
|
@ -71,11 +112,20 @@ typedef struct _OHCI_Registers
|
||||||
uint32_t HcRhDescriptorA;
|
uint32_t HcRhDescriptorA;
|
||||||
uint32_t HcRhDescriptorB;
|
uint32_t HcRhDescriptorB;
|
||||||
uint32_t HcRhStatus;
|
uint32_t HcRhStatus;
|
||||||
uint32_t HcRhPortStatus1; // 2 ports per HC, for a total of 4 USB ports
|
OHCIPort RhPort[2]; // 2 ports per HC, for a total of 4 USB ports
|
||||||
uint32_t HcRhPortStatus2;
|
|
||||||
}
|
}
|
||||||
OHCI_Registers;
|
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 */
|
/* OHCI class representing the state of the HC */
|
||||||
class OHCI_State
|
class OHCI_State
|
||||||
|
@ -86,13 +136,15 @@ class OHCI_State
|
||||||
// destructor
|
// destructor
|
||||||
~OHCI_State() {}
|
~OHCI_State() {}
|
||||||
// read a register
|
// read a register
|
||||||
uint32_t ReadRegister(xbaddr addr);
|
uint32_t HC_ReadRegister(xbaddr addr);
|
||||||
// write a register
|
// 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:
|
private:
|
||||||
// all the registers available on the OHCI standard
|
// all the registers available on the OHCI standard
|
||||||
OHCI_Registers Registers;
|
OHCI_Registers HC_Registers;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern OHCI_State* g_pHostController1;
|
extern OHCI_State* g_pHostController1;
|
||||||
|
|
|
@ -51,7 +51,12 @@ void USBDevice::Init(unsigned int address)
|
||||||
m_DeviceId = 0x01C2;
|
m_DeviceId = 0x01C2;
|
||||||
m_VendorId = PCI_VENDOR_ID_NVIDIA;
|
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)
|
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
|
// Figure out the correct OHCI object and read the register
|
||||||
if (addr >= USB1_BASE) {
|
if (addr >= USB1_BASE) {
|
||||||
// USB1 queried
|
// USB1 queried
|
||||||
return g_pHostController2->ReadRegister(addr);
|
return g_pHostController2->HC_ReadRegister(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// USB0 queried
|
// 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)
|
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
|
// Figure out the correct OHCI object and write the value to the register
|
||||||
if (addr >= USB1_BASE) {
|
if (addr >= USB1_BASE) {
|
||||||
// USB1 queried
|
// USB1 queried
|
||||||
g_pHostController2->WriteRegister(addr, value);
|
g_pHostController2->HC_WriteRegister(addr, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// USB0 queried
|
// USB0 queried
|
||||||
g_pHostController1->WriteRegister(addr, value);
|
g_pHostController1->HC_WriteRegister(addr, value);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue