USB/HC initialization stuff
This commit is contained in:
parent
6aafb25dee
commit
7f0bea988c
|
@ -1239,7 +1239,9 @@ __declspec(noreturn) void CxbxKrnlInit
|
||||||
|
|
||||||
// for unicode conversions
|
// for unicode conversions
|
||||||
setlocale(LC_ALL, "English");
|
setlocale(LC_ALL, "English");
|
||||||
|
// Initialize time-related variables for the kernel and the timers
|
||||||
CxbxInitPerformanceCounters();
|
CxbxInitPerformanceCounters();
|
||||||
|
Timer_Init();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
// CxbxPopupMessage("Attach a Debugger");
|
// CxbxPopupMessage("Attach a Debugger");
|
||||||
// Debug child processes using https://marketplace.visualstudio.com/items?itemName=GreggMiskelly.MicrosoftChildProcessDebuggingPowerTool
|
// Debug child processes using https://marketplace.visualstudio.com/items?itemName=GreggMiskelly.MicrosoftChildProcessDebuggingPowerTool
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
|
|
||||||
// Vector storing all the timers created
|
// Vector storing all the timers created
|
||||||
static std::vector<TimerObject*> TimerList;
|
static std::vector<TimerObject*> TimerList;
|
||||||
// The frequency of the high resolution timer of the host
|
// The frequency of the high resolution clock of the host
|
||||||
static uint64_t ClockFrequency;
|
static uint64_t ClockFrequency;
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ void Timer_Start(TimerObject* Timer, uint64_t Expire_MS)
|
||||||
std::thread(ClockThread, Timer).detach();
|
std::thread(ClockThread, Timer).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrives the frequency of the high resolution timer of the host
|
// Retrives the frequency of the high resolution clock of the host
|
||||||
void Timer_Init()
|
void Timer_Init()
|
||||||
{
|
{
|
||||||
LARGE_INTEGER freq;
|
LARGE_INTEGER freq;
|
||||||
|
|
|
@ -54,8 +54,8 @@ TimerObject;
|
||||||
|
|
||||||
|
|
||||||
/* Timer exported functions */
|
/* Timer exported functions */
|
||||||
TimerObject* Timer_Create(pTimerCB callback, void* arg, unsigned int Factor);
|
TimerObject* Timer_Create(pTimerCB Callback, void* Arg, unsigned int Factor);
|
||||||
void Timer_Start(TimerObject* timer, uint64_t Expire_MS);
|
void Timer_Start(TimerObject* Timer, uint64_t Expire_MS);
|
||||||
void Timer_Exit(TimerObject* Timer);
|
void Timer_Exit(TimerObject* Timer);
|
||||||
void Timer_ChangeExpireTime(TimerObject* Timer, uint64_t Expire_ms);
|
void Timer_ChangeExpireTime(TimerObject* Timer, uint64_t Expire_ms);
|
||||||
void Timer_Init();
|
void Timer_Init();
|
||||||
|
|
|
@ -37,12 +37,46 @@
|
||||||
#include "OHCI.h"
|
#include "OHCI.h"
|
||||||
#include "..\CxbxKrnl\CxbxKrnl.h"
|
#include "..\CxbxKrnl\CxbxKrnl.h"
|
||||||
|
|
||||||
|
#define USB_HZ 12000000
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum _USB_SPEED
|
||||||
|
{
|
||||||
|
USB_SPEED_MASK_LOW = 1 << 0,
|
||||||
|
USB_SPEED_MASK_FULL = 1 << 1,
|
||||||
|
}
|
||||||
|
USB_SPEED;
|
||||||
|
|
||||||
// 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* g_pHostController1 = nullptr;
|
||||||
OHCI_State* g_pHostController2 = nullptr;
|
OHCI* g_pHostController2 = nullptr;
|
||||||
|
|
||||||
|
|
||||||
void OHCI_State::HC_ChangeState(USB_State new_state)
|
OHCI::OHCI(USBDevice* UsbObj)
|
||||||
|
{
|
||||||
|
UsbInstance = UsbObj;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
UsbInstance->USB_RegisterPort(&Registers.RhPort[i].Port, this, i, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
|
||||||
|
}
|
||||||
|
USB_PacketInit(&UsbPacket);
|
||||||
|
|
||||||
|
// Create the end-of-frame timer. Let's try a factor of 50 (1 virtual ms -> 50 real ms)
|
||||||
|
pEndOfFrameTimer = Timer_Create(OHCI_FrameBoundaryWrapper, this, 50);
|
||||||
|
|
||||||
|
UsbFrameTime = 1000000ULL; // 1 ms
|
||||||
|
TicksPerUsbTick = 1000000000ULL / USB_HZ; // 83
|
||||||
|
|
||||||
|
// Do a hardware reset
|
||||||
|
OHCI_StateReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OHCI::OHCI_FrameBoundaryWrapper(void* pVoid)
|
||||||
|
{
|
||||||
|
static_cast<OHCI*>(pVoid)->OHCI_FrameBoundaryWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OHCI::OHCI_StateReset()
|
||||||
{
|
{
|
||||||
// The usb state can be USB_Suspend if it is a software reset, and USB_Reset if it is a hardware
|
// 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
|
// reset or cold boot
|
||||||
|
@ -50,39 +84,34 @@ void OHCI_State::HC_ChangeState(USB_State new_state)
|
||||||
// TODO: stop all the list processing here
|
// TODO: stop all the list processing here
|
||||||
|
|
||||||
// Reset all registers
|
// Reset all registers
|
||||||
if (new_state == USB_Reset) {
|
// Remark: the standard says that RemoteWakeupConnected bit should be set during POST, cleared during hw 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
|
||||||
// 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.
|
||||||
// doesn't do POST, I will clear it.
|
Registers.HcControl = 0;
|
||||||
HC_Registers.HcControl = 0;
|
Registers.HcControl &= ~OHCI_CTL_HCFS;
|
||||||
}
|
Registers.HcControl |= Reset;
|
||||||
else {
|
Registers.HcCommandStatus = 0;
|
||||||
HC_Registers.HcControl &= (OHCI_CTL_IR | OHCI_CTL_RWC);
|
Registers.HcInterruptStatus = 0;
|
||||||
}
|
Registers.HcInterruptEnable = OHCI_INTR_MASTER_INTERRUPT_ENABLED; // enable interrupts
|
||||||
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;
|
Registers.HcHCCA = 0;
|
||||||
HC_Registers.HcPeriodCurrentED = 0;
|
Registers.HcPeriodCurrentED = 0;
|
||||||
HC_Registers.HcControlHeadED = HC_Registers.HcControlCurrentED = 0;
|
Registers.HcControlHeadED = Registers.HcControlCurrentED = 0;
|
||||||
HC_Registers.HcBulkHeadED = HC_Registers.HcBulkCurrentED = 0;
|
Registers.HcBulkHeadED = Registers.HcBulkCurrentED = 0;
|
||||||
HC_Registers.HcDoneHead = 0;
|
Registers.HcDoneHead = 0;
|
||||||
|
|
||||||
HC_Registers.HcFmInterval = 0;
|
Registers.HcFmInterval = 0;
|
||||||
HC_Registers.HcFmInterval |= (0x2778 << 16); // TBD according to the standard, using what XQEMU sets (FSLargestDataPacket)
|
Registers.HcFmInterval |= (0x2778 << 16); // TBD according to the standard, using what XQEMU sets (FSLargestDataPacket)
|
||||||
HC_Registers.HcFmInterval |= 0x2EDF; // bit-time of a frame. 1 frame = 1 ms (FrameInterval)
|
Registers.HcFmInterval |= 0x2EDF; // bit-time of a frame. 1 frame = 1 ms (FrameInterval)
|
||||||
HC_Registers.HcFmRemaining = 0;
|
Registers.HcFmRemaining = 0;
|
||||||
HC_Registers.HcFmNumber = 0;
|
Registers.HcFmNumber = 0;
|
||||||
HC_Registers.HcPeriodicStart = 0;
|
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
|
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
|
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++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
OHCIPort* Port = &HC_Registers.RhPort[i];
|
OHCIPort* Port = &Registers.RhPort[i];
|
||||||
Port->HcRhPortStatus = 0;
|
Port->HcRhPortStatus = 0;
|
||||||
//if (Port->port.device && Port->port.device->attached) {
|
//if (Port->port.device && Port->port.device->attached) {
|
||||||
//usb_port_reset(&Port->port);
|
//usb_port_reset(&Port->port);
|
||||||
|
@ -90,4 +119,13 @@ void OHCI_State::HC_ChangeState(USB_State new_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgPrintf("Usb-Ohci: Reset\n");
|
DbgPrintf("Usb-Ohci: Reset\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OHCI::USB_PacketInit(USBPacket* packet)
|
||||||
|
{
|
||||||
|
IOVector* vec = &packet->IoVec;
|
||||||
|
vec->IoVec = new IoVec;
|
||||||
|
vec->IoVecNumber = 0;
|
||||||
|
vec->AllocNumber = 1;
|
||||||
|
vec->Size = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "Cxbx.h"
|
#include "Cxbx.h"
|
||||||
|
#include "USBDevice.h"
|
||||||
|
#include "..\CxbxKrnl\Timer.h"
|
||||||
|
|
||||||
|
|
||||||
// Abbreviations used:
|
// Abbreviations used:
|
||||||
|
@ -67,16 +69,21 @@
|
||||||
#define OHCI_RHA_OCPM (1<<11) // OverCurrentProtectionMode
|
#define OHCI_RHA_OCPM (1<<11) // OverCurrentProtectionMode
|
||||||
#define OHCI_RHA_NOCP (1<<12) // NoOverCurrentProtection
|
#define OHCI_RHA_NOCP (1<<12) // NoOverCurrentProtection
|
||||||
|
|
||||||
// Struct describing the status of a usb port
|
|
||||||
struct USBPort {
|
// enum indicating the current HC state
|
||||||
//USBDevice* device;
|
typedef enum _OHCI_State
|
||||||
//TODO
|
{
|
||||||
};
|
Reset = 0x00,
|
||||||
|
Resume = 0x40,
|
||||||
|
Operational = 0x80,
|
||||||
|
Suspend = 0xC0,
|
||||||
|
}
|
||||||
|
OHCI_State;
|
||||||
|
|
||||||
// Small struct used to hold the HcRhPortStatus register and the usb port status
|
// Small struct used to hold the HcRhPortStatus register and the usb port status
|
||||||
typedef struct _OHCIPort
|
typedef struct _OHCIPort
|
||||||
{
|
{
|
||||||
USBPort port;
|
USBPort Port;
|
||||||
uint32_t HcRhPortStatus;
|
uint32_t HcRhPortStatus;
|
||||||
}
|
}
|
||||||
OHCIPort;
|
OHCIPort;
|
||||||
|
@ -116,38 +123,46 @@ typedef struct _OHCI_Registers
|
||||||
}
|
}
|
||||||
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
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
OHCI_State() {}
|
OHCI(USBDevice* UsbObj);
|
||||||
// destructor
|
// destructor
|
||||||
~OHCI_State() {}
|
~OHCI() {}
|
||||||
// read a register
|
// read a register
|
||||||
uint32_t HC_ReadRegister(xbaddr addr);
|
uint32_t OHCI_ReadRegister(xbaddr Addr);
|
||||||
// write a register
|
// write a register
|
||||||
void HC_WriteRegister(xbaddr addr, uint32_t value);
|
void OHCI_WriteRegister(xbaddr Addr, uint32_t Value);
|
||||||
// reset the HC to the default state
|
// switch the HC to the reset state
|
||||||
void HC_ChangeState(USB_State new_state);
|
void OHCI_StateReset();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// all the registers available on the OHCI standard
|
// all the registers available on the OHCI standard
|
||||||
OHCI_Registers HC_Registers;
|
OHCI_Registers Registers;
|
||||||
|
// end-of-frame timer
|
||||||
|
TimerObject* pEndOfFrameTimer;
|
||||||
|
// the duration of a usb frame
|
||||||
|
uint64_t UsbFrameTime;
|
||||||
|
// ticks per usb tick
|
||||||
|
uint64_t TicksPerUsbTick;
|
||||||
|
// the usb device instance of this HC
|
||||||
|
USBDevice* UsbInstance;
|
||||||
|
// usb packet
|
||||||
|
USBPacket UsbPacket;
|
||||||
|
|
||||||
|
// end-of-frame callback wrapper
|
||||||
|
static void OHCI_FrameBoundaryWrapper(void* pVoid);
|
||||||
|
// end-of-frame callback function
|
||||||
|
void OHCI_FrameBoundaryWorker();
|
||||||
|
// initialize packet struct
|
||||||
|
void USB_PacketInit(USBPacket* packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern OHCI_State* g_pHostController1;
|
extern OHCI* g_pHostController1;
|
||||||
extern OHCI_State* g_pHostController2;
|
extern OHCI* g_pHostController2;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -52,13 +52,11 @@ void USBDevice::Init(unsigned int address)
|
||||||
m_VendorId = PCI_VENDOR_ID_NVIDIA;
|
m_VendorId = PCI_VENDOR_ID_NVIDIA;
|
||||||
|
|
||||||
if (address == USB0_BASE) {
|
if (address == USB0_BASE) {
|
||||||
g_pHostController1 = new OHCI_State;
|
g_pHostController1 = new OHCI(this);
|
||||||
g_pHostController1->HC_ChangeState(USB_Reset);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pHostController2 = new OHCI_State;
|
g_pHostController2 = new OHCI(this);
|
||||||
g_pHostController2->HC_ChangeState(USB_Reset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t USBDevice::MMIORead(int barIndex, uint32_t addr, unsigned size)
|
uint32_t USBDevice::MMIORead(int barIndex, uint32_t addr, unsigned size)
|
||||||
|
@ -69,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->HC_ReadRegister(addr);
|
return g_pHostController2->OHCI_ReadRegister(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// USB0 queried
|
// USB0 queried
|
||||||
return g_pHostController1->HC_ReadRegister(addr);
|
return g_pHostController1->OHCI_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)
|
||||||
|
@ -84,10 +82,19 @@ 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->HC_WriteRegister(addr, value);
|
g_pHostController2->OHCI_WriteRegister(addr, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// USB0 queried
|
// USB0 queried
|
||||||
g_pHostController1->HC_WriteRegister(addr, value);
|
g_pHostController1->OHCI_WriteRegister(addr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBDevice::USB_RegisterPort(USBPort* Port, OHCI* Obj, int Index, int SpeedMask)
|
||||||
|
{
|
||||||
|
Port->Opaque = Obj;
|
||||||
|
Port->PortIndex = Index;
|
||||||
|
Port->SpeedMask = SpeedMask;
|
||||||
|
Port->HubCount = 0;
|
||||||
|
std::snprintf(Port->Path, sizeof(Port->Path), "%d", Index + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,126 @@
|
||||||
#include "..\PCIDevice.h"
|
#include "..\PCIDevice.h"
|
||||||
#include "OHCI.h"
|
#include "OHCI.h"
|
||||||
|
|
||||||
|
|
||||||
|
// This is a linux struct for vectored I/O. See readv() and writev()
|
||||||
|
typedef struct _IoVec
|
||||||
|
{
|
||||||
|
void* Iov_Base;
|
||||||
|
size_t Iov_Len;
|
||||||
|
}
|
||||||
|
IoVec;
|
||||||
|
|
||||||
|
typedef struct _IOVector
|
||||||
|
{
|
||||||
|
IoVec* IoVec;
|
||||||
|
int IoVecNumber; // TODO
|
||||||
|
int AllocNumber; // TODO
|
||||||
|
size_t Size;
|
||||||
|
}
|
||||||
|
IOVector;
|
||||||
|
|
||||||
|
// definition of a USB device
|
||||||
|
typedef struct _USBDev
|
||||||
|
{
|
||||||
|
DeviceState qdev;
|
||||||
|
USBPort *port;
|
||||||
|
char *port_path;
|
||||||
|
char *serial;
|
||||||
|
void *opaque;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
// Actual connected speed
|
||||||
|
int speed;
|
||||||
|
// Supported speeds, not in info because it may be variable (hostdevs)
|
||||||
|
int speedmask;
|
||||||
|
uint8_t addr;
|
||||||
|
char product_desc[32];
|
||||||
|
int auto_attach;
|
||||||
|
int attached;
|
||||||
|
|
||||||
|
int32_t state;
|
||||||
|
uint8_t setup_buf[8];
|
||||||
|
uint8_t data_buf[4096];
|
||||||
|
int32_t remote_wakeup;
|
||||||
|
int32_t setup_state;
|
||||||
|
int32_t setup_len;
|
||||||
|
int32_t setup_index;
|
||||||
|
|
||||||
|
USBEndpoint ep_ctl;
|
||||||
|
USBEndpoint ep_in[USB_MAX_ENDPOINTS];
|
||||||
|
USBEndpoint ep_out[USB_MAX_ENDPOINTS];
|
||||||
|
|
||||||
|
//QLIST_HEAD(, USBDescString) strings;
|
||||||
|
const USBDesc *usb_desc; // Overrides class usb_desc if not NULL
|
||||||
|
const USBDescDevice *device;
|
||||||
|
|
||||||
|
int configuration;
|
||||||
|
int ninterfaces;
|
||||||
|
int altsetting[USB_MAX_INTERFACES];
|
||||||
|
const USBDescConfig *config;
|
||||||
|
const USBDescIface *ifaces[USB_MAX_INTERFACES];
|
||||||
|
}
|
||||||
|
USBDev;
|
||||||
|
|
||||||
|
typedef struct _USBEndpoint
|
||||||
|
{
|
||||||
|
uint8_t nr;
|
||||||
|
uint8_t pid;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t ifnum;
|
||||||
|
int max_packet_size;
|
||||||
|
bool pipeline;
|
||||||
|
bool halted;
|
||||||
|
USBDevice *dev;
|
||||||
|
//QTAILQ_HEAD(, USBPacket) queue;
|
||||||
|
}
|
||||||
|
USBEndpoint;
|
||||||
|
|
||||||
|
// Structure used to hold information about an active USB packet
|
||||||
|
typedef struct _USBPacket
|
||||||
|
{
|
||||||
|
// Data fields for use by the driver
|
||||||
|
int Pid;
|
||||||
|
uint64_t Id;
|
||||||
|
USBEndpoint* Endpoint;
|
||||||
|
unsigned int stream;
|
||||||
|
IOVector IoVec; // used to perform vectored I/O
|
||||||
|
uint64_t parameter; // control transfers
|
||||||
|
bool short_not_ok;
|
||||||
|
bool int_req;
|
||||||
|
int status; // USB_RET_* status code
|
||||||
|
int actual_length; // Number of bytes actually transferred
|
||||||
|
// Internal use by the USB layer
|
||||||
|
USBPacketState state;
|
||||||
|
USBCombinedPacket *combined;
|
||||||
|
//QTAILQ_ENTRY(USBPacket) queue;
|
||||||
|
//QTAILQ_ENTRY(USBPacket) combined_entry;
|
||||||
|
}
|
||||||
|
USBPacket;
|
||||||
|
|
||||||
|
// Struct describing the status of a usb port
|
||||||
|
typedef struct _USBPort {
|
||||||
|
USBDev *Dev;
|
||||||
|
int SpeedMask; // usb speeds supported
|
||||||
|
int HubCount; // number of hubs attached
|
||||||
|
char Path[16]; // the number of the port
|
||||||
|
OHCI* Opaque; // OHCI* to let USBPort access it
|
||||||
|
int PortIndex; // internal port index, may be used with the Opaque
|
||||||
|
//QTAILQ_ENTRY(USBPort) next;
|
||||||
|
// a device is attched
|
||||||
|
void Attach(USBPort* port);
|
||||||
|
// a device is detached
|
||||||
|
void Detach(USBPort* port);
|
||||||
|
// a device downstream from the device attached to the port (attached through a hub) is detached
|
||||||
|
void ChildDetach(USBPort* port, USBDev* child);
|
||||||
|
// TODO
|
||||||
|
void Wakeup(USBPort* port);
|
||||||
|
// TODO
|
||||||
|
void Complete(USBPort* port, USBPacket *p);
|
||||||
|
}
|
||||||
|
USBPort;
|
||||||
|
|
||||||
|
|
||||||
class USBDevice : public PCIDevice {
|
class USBDevice : public PCIDevice {
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
|
@ -54,6 +174,10 @@ class USBDevice : public PCIDevice {
|
||||||
void IOWrite(int barIndex, uint32_t port, uint32_t value, unsigned size) {}
|
void IOWrite(int barIndex, uint32_t port, uint32_t value, unsigned size) {}
|
||||||
uint32_t MMIORead(int barIndex, uint32_t addr, unsigned size);
|
uint32_t MMIORead(int barIndex, uint32_t addr, unsigned size);
|
||||||
void MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size);
|
void MMIOWrite(int barIndex, uint32_t addr, uint32_t value, unsigned size);
|
||||||
|
|
||||||
|
// USB specific functions
|
||||||
|
// register a port with the HC
|
||||||
|
void USB_RegisterPort(USBPort* Port, OHCI* Obj, int Index, int SpeedMask);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue