Work in progress on XHCI bus driver.

* USB Core:
Hub: pass more correct speed, port and address for USB3 devices.
Transfer: doesn't care for bandwidth computation for super speed.
BusManager: Make AllocateDevice() and FreeDevice() virtual, XHCI needs to setup
	a slot and an address for the device.
Add USB_SPEED_WIRELESS usb_speed definition.
Add USB2.0 erratum definition and some USB3 definitions
* XHCI:
Find outs which port supports SuperSpeed or not.
Override AllocateDevice() to configure slot and address for a connected device.
Override FreeDevice() to free ressources associated to a slot.
Add context struct definitions.
This commit is contained in:
Jérôme Duval 2011-12-22 21:40:10 +01:00
parent d11be97572
commit 319a3798bc
8 changed files with 528 additions and 21 deletions

View File

@ -7,6 +7,7 @@
* Niels S. Reedijk
*/
#include "usb_private.h"
#include <stdio.h>
@ -128,7 +129,7 @@ Hub::UpdatePortStatus(uint8 index)
// get the current port status
size_t actualLength = 0;
status_t result = DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN,
USB_REQUEST_GET_STATUS, 0, index + 1, sizeof(usb_port_status),
USB_REQUEST_GET_STATUS, 0, index + 1, sizeof(usb_port_status),
(void *)&fPortStatus[index], sizeof(usb_port_status), &actualLength);
if (result < B_OK || actualLength < sizeof(usb_port_status)) {
@ -247,9 +248,11 @@ Hub::Explore(change_item **changeList)
}
usb_speed speed = USB_SPEED_FULLSPEED;
if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED)
if (fDeviceDescriptor.usb_version == 0x300)
speed = USB_SPEED_SUPER;
else if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED)
speed = USB_SPEED_LOWSPEED;
if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED)
else if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED)
speed = USB_SPEED_HIGHSPEED;
// either let the device inherit our addresses (if we are
@ -258,7 +261,7 @@ Hub::Explore(change_item **changeList)
// transaction translator for the device.
int8 hubAddress = HubAddress();
uint8 hubPort = HubPort();
if (Speed() == USB_SPEED_HIGHSPEED) {
if (Speed() == USB_SPEED_HIGHSPEED || fDeviceDescriptor.usb_version == 0x300) {
hubAddress = DeviceAddress();
hubPort = i + 1;
}

View File

@ -274,6 +274,13 @@ Transfer::_CalculateBandwidth()
break;
}
case USB_SPEED_SUPER:
{
// TODO it should only be useful for isochronous type
bandwidthNS = 0;
break;
}
default:
// We should never get here
TRACE("speed unknown");

View File

@ -91,7 +91,8 @@ typedef enum {
USB_SPEED_FULLSPEED,
USB_SPEED_HIGHSPEED,
USB_SPEED_SUPER,
USB_SPEED_MAX = USB_SPEED_SUPER
USB_SPEED_WIRELESS,
USB_SPEED_MAX = USB_SPEED_WIRELESS
} usb_speed;
@ -201,10 +202,10 @@ virtual status_t InitCheck();
int8 AllocateAddress();
void FreeAddress(int8 address);
Device * AllocateDevice(Hub *parent,
virtual Device * AllocateDevice(Hub *parent,
int8 hubAddress, uint8 hubPort,
usb_speed speed);
void FreeDevice(Device *device);
virtual void FreeDevice(Device *device);
virtual status_t Start();
virtual status_t Stop();

View File

@ -87,16 +87,23 @@ struct usb_port_status
//The bits in the usb_port_status struct
// USB 1.1 spec page 274
// USB2_LinkPowerMangement_ECN[final].pdf page 25
#define PORT_STATUS_CONNECTION 0x0001
#define PORT_STATUS_ENABLE 0x0002
#define PORT_STATUS_SUSPEND 0x0004
#define PORT_STATUS_OVER_CURRENT 0x0008
#define PORT_STATUS_RESET 0x0010
#define PORT_STATUS_L1 0x0020
#define PORT_STATUS_POWER 0x0100
#define PORT_STATUS_LOW_SPEED 0x0200
#define PORT_STATUS_HIGH_SPEED 0x0400
#define PORT_STATUS_TEST 0x0800
#define PORT_STATUS_INDICATOR 0x1000
// USB 3.0 spec table 10-11
#define PORT_STATUS_SS_LINK_STATE 0x01e0
#define PORT_STATUS_SS_POWER 0x0200
#define PORT_STATUS_SS_SPEED 0x1c00
//The feature requests with ports
@ -114,4 +121,16 @@ struct usb_port_status
#define C_PORT_OVER_CURRENT 19
#define C_PORT_RESET 20
// USB 3.0 spec table 10-8
#define PORT_LINK_STATE 5
#define PORT_U1_TIMEOUT 23
#define PORT_U2_TIMEOUT 24
#define C_PORT_LINK_STATE 25
#define C_PORT_CONFIG_ERROR 26
#define C_PORT_REMOTE_WAKE_MASK 27
#define PORT_BH_PORT_RESET 28
#define C_PORT_BH_PORT_RESET 29
#define PORT_FORCE_LINKPM_STATE 30
#endif // _USBSPEC_PRIVATE_H

View File

@ -7,6 +7,7 @@
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* Jian Chiang <j.jian.chiang@gmail.com>
* Jérôme Duval <jerome.duval@gmail.com>
*/
@ -198,6 +199,10 @@ XHCI::XHCI(pci_info *info, Stack *stack)
install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
InterruptHandler, (void *)this, 0);
memset(fPortSpeeds, 0, sizeof(fPortSpeeds));
memset(fPortSlots, 0, sizeof(fPortSlots));
memset(fDevices, 0, sizeof(fDevices));
fInitOK = true;
TRACE("XHCI host controller driver constructed\n");
}
@ -247,6 +252,35 @@ XHCI::Start()
fSlotCount = HCS_MAX_SLOTS(capabilities);
WriteOpReg(XHCI_CONFIG, fSlotCount);
// find out which protocol is used for each port
uint8 portFound = 0;
uint32 cparams = ReadCapReg32(XHCI_HCCPARAMS);
uint32 eec = 0xffffffff;
uint32 eecp = HCS0_XECP(cparams) << 2;
for (; eecp != 0 && XECP_NEXT(eec) && portFound < fPortCount;
eecp += XECP_NEXT(eec) << 2) {
eec = ReadCapReg32(eecp);
if (XECP_ID(eec) != XHCI_SUPPORTED_PROTOCOLS_CAPID)
continue;
if (XHCI_SUPPORTED_PROTOCOLS_0_MAJOR(eec) > 3)
continue;
uint32 temp = ReadCapReg32(eecp + 8);
uint32 offset = XHCI_SUPPORTED_PROTOCOLS_1_OFFSET(temp);
uint32 count = XHCI_SUPPORTED_PROTOCOLS_1_COUNT(temp);
if (offset == 0 || count == 0)
continue;
offset--;
for (uint32 i = offset; i < offset + count; i++) {
if (XHCI_SUPPORTED_PROTOCOLS_0_MAJOR(eec) == 0x3)
fPortSpeeds[i] = USB_SPEED_SUPER;
else
fPortSpeeds[i] = USB_SPEED_HIGHSPEED;
TRACE("speed for port %ld is %s\n", i,
fPortSpeeds[i] == USB_SPEED_SUPER ? "super" : "high");
}
portFound += count;
}
uint32 params2 = ReadCapReg32(XHCI_HCSPARAMS2);
fScratchpadCount = HCS_MAX_SC_BUFFERS(params2);
if (fScratchpadCount > XHCI_MAX_SCRATCHPADS) {
@ -254,6 +288,10 @@ XHCI::Start()
return B_ERROR;
}
uint32 params3 = ReadCapReg32(XHCI_HCSPARAMS3);
fExitLatMax = HCS_U1_DEVICE_LATENCY(params3)
+ HCS_U2_DEVICE_LATENCY(params3);
WriteOpReg(XHCI_DNCTRL, 0);
// allocate Device Context Base Address array
@ -495,6 +533,272 @@ XHCI::AddTo(Stack *stack)
}
Device *
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
usb_speed speed)
{
TRACE("AllocateDevice hubAddress %d hubPort %d speed %d\n", hubAddress,
hubPort, speed);
GetPortSpeed(hubPort - 1, &speed);
TRACE("speed %d\n", speed);
uint8 slot = XHCI_MAX_SLOTS;
if (EnableSlot(&slot) != B_OK) {
TRACE_ERROR("AllocateDevice() failed enable slot\n");
return NULL;
}
if (slot > fSlotCount) {
TRACE_ERROR("AllocateDevice() bad slot\n");
return NULL;
}
if (fDevices[slot].state != XHCI_STATE_DISABLED) {
TRACE_ERROR("AllocateDevice() slot already used\n");
return NULL;
}
struct xhci_device *device = &fDevices[slot];
memset(device, 0, sizeof(struct xhci_device));
device->state = XHCI_STATE_ENABLED;
device->input_ctx_area = fStack->AllocateArea((void **)&device->input_ctx,
(void**)&device->input_ctx_addr, sizeof(*device->input_ctx), "XHCI input context");
if (device->input_ctx_area < B_OK) {
TRACE_ERROR("unable to create a input context area\n");
return NULL;
}
device->input_ctx->input.dropFlags = 0;
device->input_ctx->input.addFlags = 3;
uint32 route = 0;
uint8 routePort = hubPort;
uint8 rhPort = 0;
for (Device *hubDevice = parent; hubDevice != RootObject();
hubDevice = (Device *)hubDevice->Parent()) {
route *= 16;
if (hubPort > 15)
route += 15;
else
route += routePort;
rhPort = routePort;
routePort = hubDevice->HubPort();
}
device->input_ctx->slot.dwslot0 = SLOT_0_NUM_ENTRIES(1) | SLOT_0_ROUTE(route);
// add the speed
switch (speed) {
case USB_SPEED_LOWSPEED:
device->input_ctx->slot.dwslot0 |= SLOT_0_SPEED(2);
break;
case USB_SPEED_HIGHSPEED:
device->input_ctx->slot.dwslot0 |= SLOT_0_SPEED(3);
break;
case USB_SPEED_FULLSPEED:
device->input_ctx->slot.dwslot0 |= SLOT_0_SPEED(1);
break;
case USB_SPEED_SUPER:
device->input_ctx->slot.dwslot0 |= SLOT_0_SPEED(4);
break;
default:
TRACE_ERROR("unknown usb speed\n");
break;
}
device->input_ctx->slot.dwslot1 = SLOT_1_RH_PORT(rhPort);
device->input_ctx->slot.dwslot2 = SLOT_2_IRQ_TARGET(0);
if (0)
device->input_ctx->slot.dwslot2 |= SLOT_2_PORT_NUM(hubPort);
device->input_ctx->slot.dwslot3 = SLOT_3_SLOT_STATE(0) | SLOT_3_DEVICE_ADDRESS(0);
TRACE("slot 0x%lx 0x%lx 0x%lx 0x%lx\n", device->input_ctx->slot.dwslot0,
device->input_ctx->slot.dwslot1, device->input_ctx->slot.dwslot2,
device->input_ctx->slot.dwslot3);
device->device_ctx_area = fStack->AllocateArea((void **)&device->device_ctx,
(void**)&device->device_ctx_addr, sizeof(*device->device_ctx), "XHCI device context");
if (device->device_ctx_area < B_OK) {
TRACE_ERROR("unable to create a device context area\n");
delete_area(device->input_ctx_area);
return NULL;
}
device->trb_area = fStack->AllocateArea((void **)&device->trbs,
(void**)&device->trb_addr, sizeof(*device->trbs), "XHCI endpoint trbs");
if (device->trb_area < B_OK) {
TRACE_ERROR("unable to create a device trbs area\n");
delete_area(device->input_ctx_area);
delete_area(device->device_ctx_area);
return NULL;
}
for (uint32 i = 0; i < XHCI_MAX_ENDPOINTS; i++) {
struct xhci_trb *linkTrb = &(*device->trbs)[i][XHCI_MAX_TRANSFERS - 1];
linkTrb->qwtrb0 = device->trb_addr + i * sizeof(device->trbs[0]);
linkTrb->dwtrb2 = TRB_2_IRQ(0);
linkTrb->dwtrb3 = TRB_3_CYCLE_BIT | TRB_3_TYPE(TRB_TYPE_LINK);
}
// set up slot pointer to device context
fDcba->baseAddress[slot] = device->device_ctx_addr;
size_t maxPacketSize;
switch (speed) {
case USB_SPEED_LOWSPEED:
case USB_SPEED_FULLSPEED:
maxPacketSize = 8;
break;
case USB_SPEED_HIGHSPEED:
maxPacketSize = 64;
break;
default:
maxPacketSize = 512;
break;
}
// configure the Control endpoint 0 (type 4)
if (ConfigureEndpoint(slot, 0, 4, device->trb_addr, 0, 1, 1, 0,
maxPacketSize, maxPacketSize) != B_OK) {
TRACE_ERROR("unable to configure default control endpoint\n");
return NULL;
}
if (SetAddress(device->input_ctx_addr, 1, slot) != B_OK) {
TRACE_ERROR("unable to set address\n");
return NULL;
}
uint8 deviceAddress = SLOT_3_DEVICE_ADDRESS(device->input_ctx->slot.dwslot3);
TRACE("deviceAddress 0x%x\n", deviceAddress);
// Create a temporary pipe with the new address
ControlPipe pipe(parent);
pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0, hubAddress,
hubPort);
// Get the device descriptor
// Just retrieve the first 8 bytes of the descriptor -> minimum supported
// size of any device. It is enough because it includes the device type.
size_t actualLength = 0;
usb_device_descriptor deviceDescriptor;
TRACE("getting the device descriptor\n");
pipe.SendRequest(
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
USB_REQUEST_GET_DESCRIPTOR, // request
USB_DESCRIPTOR_DEVICE << 8, // value
0, // index
8, // length
(void *)&deviceDescriptor, // buffer
8, // buffer length
&actualLength); // actual length
if (actualLength != 8) {
TRACE_ERROR("error while getting the device descriptor\n");
FreeAddress(deviceAddress);
return NULL;
}
TRACE("creating new device\n");
Device *deviceObject = new(std::nothrow) Device(parent, hubAddress, hubPort,
deviceDescriptor, deviceAddress, speed, false);
if (!deviceObject) {
TRACE_ERROR("no memory to allocate device\n");
return NULL;
}
fPortSlots[hubPort] = slot;
TRACE("AllocateDevice() port %d slot %d\n", hubPort, slot);
return deviceObject;
}
void
XHCI::FreeDevice(Device *device)
{
uint8 slot = fPortSlots[device->HubPort()];
TRACE("FreeDevice() port %d slot %d\n", device->HubPort(), slot);
DisableSlot(slot);
fDcba->baseAddress[slot] = 0;
fPortSlots[device->HubPort()] = 0;
delete_area(fDevices[slot].trb_area);
delete_area(fDevices[slot].input_ctx_area);
delete_area(fDevices[slot].device_ctx_area);
fDevices[slot].state = XHCI_STATE_DISABLED;
delete device;
}
status_t
XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, uint16 interval,
uint8 maxPacketCount, uint8 mult, uint8 fpsShift, uint16 maxPacketSize,
uint16 maxFrameSize)
{
struct xhci_device *device = &fDevices[slot];
struct xhci_endpoint_ctx *endpoint = &device->input_ctx->endpoints[number];
if (mult == 0 || maxPacketCount == 0)
return B_BAD_VALUE;
maxPacketCount--;
endpoint->dwendpoint0 = ENDPOINT_0_STATE(0) | ENDPOINT_0_MAXPSTREAMS(0);
// add mult for isochronous and interrupt types
// add interval
endpoint->dwendpoint1 = ENDPOINT_1_EPTYPE(type)
| ENDPOINT_1_MAXBURST(maxPacketCount)
| ENDPOINT_1_MAXPACKETSIZE(maxPacketSize)
| ENDPOINT_1_CERR(3);
endpoint->qwendpoint2 = ENDPOINT_2_DCS_BIT | ringAddr;
// 8 for Control endpoint
switch (type) {
case 4:
endpoint->dwendpoint4 = ENDPOINT_4_AVGTRBLENGTH(8);
break;
case 1:
case 3:
case 5:
case 7:
endpoint->dwendpoint4 = ENDPOINT_4_AVGTRBLENGTH(maxFrameSize)
| ENDPOINT_4_MAXESITPAYLOAD(maxFrameSize);
break;
}
TRACE("endpoint 0x%lx 0x%lx 0x%llx 0x%lx\n", endpoint->dwendpoint0,
endpoint->dwendpoint1, endpoint->qwendpoint2, endpoint->dwendpoint4);
return B_OK;
}
status_t
XHCI::GetPortSpeed(uint8 index, usb_speed *speed)
{
if (fPortSpeeds[index] == USB_SPEED_SUPER)
*speed = USB_SPEED_SUPER;
else {
uint32 portStatus = ReadOpReg(XHCI_PORTSC(index));
switch (PS_SPEED_GET(portStatus)) {
case 3:
*speed = USB_SPEED_HIGHSPEED;
break;
case 2:
*speed = USB_SPEED_LOWSPEED;
break;
case 1:
*speed = USB_SPEED_FULLSPEED;
break;
default:
*speed = USB_SPEED_SUPER;
}
}
return B_OK;
}
status_t
XHCI::GetPortStatus(uint8 index, usb_port_status *status)
{
@ -503,7 +807,7 @@ XHCI::GetPortStatus(uint8 index, usb_port_status *status)
status->status = status->change = 0;
uint32 portStatus = ReadOpReg(XHCI_PORTSC(index));
TRACE("port status=0x%08lx\n", portStatus);
//TRACE("port status=0x%08lx\n", portStatus);
// build the status
switch (PS_SPEED_GET(portStatus)) {
@ -525,8 +829,12 @@ XHCI::GetPortStatus(uint8 index, usb_port_status *status)
status->status |= PORT_STATUS_OVER_CURRENT;
if (portStatus & PS_PR)
status->status |= PORT_STATUS_RESET;
if (portStatus & PS_PP)
status->status |= PORT_STATUS_POWER;
if (portStatus & PS_PP) {
if (fPortSpeeds[index] == USB_SPEED_SUPER)
status->status |= PORT_STATUS_SS_POWER;
else
status->status |= PORT_STATUS_POWER;
}
// build the change
if (portStatus & PS_CSC)
@ -538,6 +846,13 @@ XHCI::GetPortStatus(uint8 index, usb_port_status *status)
if (portStatus & PS_PRC)
status->change |= PORT_STATUS_RESET;
if (fPortSpeeds[index] == USB_SPEED_SUPER) {
if (portStatus & PS_PLC)
status->change |= PORT_LINK_STATE;
if (portStatus & PS_WRC)
status->change |= PORT_BH_PORT_RESET;
}
return B_OK;
}
@ -573,6 +888,7 @@ XHCI::SetPortFeature(uint8 index, uint16 feature)
default:
return B_BAD_VALUE;
}
ReadOpReg(portRegister);
return B_OK;
}
@ -598,28 +914,31 @@ XHCI::ClearPortFeature(uint8 index, uint16 feature)
portStatus &= ~PS_PLS_MASK;
WriteOpReg(portRegister, portStatus | PS_XDEV_U0 | PS_LWS);
}
return B_OK;
break;
case PORT_ENABLE:
WriteOpReg(portRegister, portStatus | PS_PED);
return B_OK;
break;
case PORT_POWER:
WriteOpReg(portRegister, portStatus & ~PS_PP);
return B_OK;
break;
case C_PORT_CONNECTION:
WriteOpReg(portRegister, portStatus | PS_CSC);
return B_OK;
break;
case C_PORT_ENABLE:
WriteOpReg(portRegister, portStatus | PS_PEC);
return B_OK;
break;
case C_PORT_OVER_CURRENT:
WriteOpReg(portRegister, portStatus | PS_OCC);
return B_OK;
break;
case C_PORT_RESET:
WriteOpReg(portRegister, portStatus | PS_PRC);
return B_OK;
break;
default:
return B_BAD_VALUE;
}
return B_BAD_VALUE;
ReadOpReg(portRegister);
return B_OK;
}

View File

@ -5,6 +5,7 @@
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
* Jian Chiang <j.jian.chiang@gmail.com>
* Jérôme Duval <jerome.duval@gmail.com>
*/
#ifndef XHCI_H
#define XHCI_H
@ -19,6 +20,30 @@ struct pci_module_info;
class XHCIRootHub;
enum xhci_state {
XHCI_STATE_DISABLED = 0,
XHCI_STATE_ENABLED,
XHCI_STATE_ADDRESSED,
XHCI_STATE_CONFIGURED,
};
struct xhci_device {
enum xhci_state state;
area_id trb_area;
addr_t trb_addr;
struct xhci_trb (*trbs)[XHCI_MAX_ENDPOINTS - 1][XHCI_MAX_TRANSFERS];
area_id input_ctx_area;
addr_t input_ctx_addr;
struct xhci_input_device_ctx *input_ctx;
area_id device_ctx_area;
addr_t device_ctx_addr;
struct xhci_device_ctx *device_ctx;
};
class XHCI : public BusManager {
public:
XHCI(pci_info *info, Stack *stack);
@ -33,12 +58,25 @@ public:
static status_t AddTo(Stack *stack);
virtual Device * AllocateDevice(Hub *parent,
int8 hubAddress, uint8 hubPort,
usb_speed speed);
status_t ConfigureEndpoint(uint8 slot, uint8 number,
uint8 type, uint64 ringAddr,
uint16 interval, uint8 maxPacketCount,
uint8 mult, uint8 fpsShift,
uint16 maxPacketSize, uint16 maxFrameSize);
virtual void FreeDevice(Device *device);
// Port operations for root hub
uint8 PortCount() const { return fPortCount; }
status_t GetPortStatus(uint8 index, usb_port_status *status);
status_t GetPortStatus(uint8 index,
usb_port_status *status);
status_t SetPortFeature(uint8 index, uint16 feature);
status_t ClearPortFeature(uint8 index, uint16 feature);
status_t GetPortSpeed(uint8 index, usb_speed *speed);
virtual const char * TypeName() const { return "xhci"; }
private:
@ -131,16 +169,23 @@ private:
// Port management
uint8 fPortCount;
uint8 fSlotCount;
usb_speed fPortSpeeds[XHCI_MAX_PORTS];
uint8 fPortSlots[XHCI_MAX_PORTS];
// Scratchpad
uint8 fScratchpadCount;
area_id fScratchpadArea[XHCI_MAX_SCRATCHPADS];
void * fScratchpad[XHCI_MAX_SCRATCHPADS];
// Devices
struct xhci_device fDevices[XHCI_MAX_DEVICES];
uint16 fEventIdx;
uint16 fCmdIdx;
uint8 fEventCcs;
uint8 fCmdCcs;
uint32 fExitLatMax;
};

View File

@ -4,6 +4,7 @@
*
* Authors:
* Jian Chiang <j.jian.chiang@gmail.com>
* Jérôme Duval <jerome.duval@gmail.com>
*/
#ifndef XHCI_HARDWARE_H
#define XHCI_HARDWARE_H
@ -92,6 +93,14 @@
#define XHCI_LEGCTLSTS 0x04
#define XHCI_LEGCTLSTS_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
#define XHCI_SUPPORTED_PROTOCOLS_CAPID 0x02
#define XHCI_SUPPORTED_PROTOCOLS_0_MINOR(x) (((x) >> 16) & 0xff)
#define XHCI_SUPPORTED_PROTOCOLS_0_MAJOR(x) (((x) >> 24) & 0xff)
#define XHCI_SUPPORTED_PROTOCOLS_1_COUNT(x) (((x) >> 8) & 0xff)
#define XHCI_SUPPORTED_PROTOCOLS_1_OFFSET(x) (((x) >> 0) & 0xff)
// Port status Registers
// Section 5.4.8
@ -244,9 +253,12 @@
#define XHCI_MAX_EVENTS (16 * 13)
#define XHCI_MAX_COMMANDS (16 * 1)
#define XHCI_MAX_SLOTS 256
#define XHCI_MAX_SLOTS 255
#define XHCI_MAX_PORTS 127
#define XHCI_MAX_ENDPOINTS 32
#define XHCI_MAX_SCRATCHPADS 32
#define XHCI_MAX_DEVICES 128
#define XHCI_MAX_TRANSFERS 4
struct xhci_trb {
@ -286,4 +298,106 @@ struct xhci_device_context_array {
};
struct xhci_slot_ctx {
uint32 dwslot0;
uint32 dwslot1;
uint32 dwslot2;
uint32 dwslot3;
uint32 reserved[4];
};
#define SLOT_0_ROUTE(x) ((x) & 0xFFFFF)
#define SLOT_0_ROUTE_GET(x) ((x) & 0xFFFFF)
#define SLOT_0_SPEED(x) (((x) & 0xF) << 20)
#define SLOT_0_SPEED_GET(x) (((x) >> 20) & 0xF)
#define SLOT_0_MTT_BIT (1U << 25)
#define SLOT_0_HUB_BIT (1U << 26)
#define SLOT_0_NUM_ENTRIES(x) (((x) & 0x1F) << 27)
#define SLOT_0_NUM_ENTRIES_GET(x) (((x) >> 27) & 0x1F)
#define SLOT_1_MAX_EXIT_LATENCY(x) ((x) & 0xFFFF)
#define SLOT_1_MAX_EXIT_LATENCY_GET(x) ((x) & 0xFFFF)
#define SLOT_1_RH_PORT(x) (((x) & 0xFF) << 16)
#define SLOT_1_RH_PORT_GET(x) (((x) >> 16) & 0xFF)
#define SLOT_1_NUM_PORTS(x) (((x) & 0xFF) << 24)
#define SLOT_1_NUM_PORTS_GET(x) (((x) >> 24) & 0xFF)
#define SLOT_2_TT_HUB_SLOT(x) ((x) & 0xFF)
#define SLOT_2_TT_HUB_SLOT(x) ((x) & 0xFF)
#define SLOT_2_PORT_NUM(x) (((x) & 0xFF) << 8)
#define SLOT_2_PORT_NUM_GET(x) (((x) >> 8) & 0xFF)
#define SLOT_2_TT_TIME(x) (((x) & 0x3) << 16)
#define SLOT_2_TT_TIME_GET(x) (((x) >> 16) & 0x3)
#define SLOT_2_IRQ_TARGET(x) (((x) & 0x1F) << 27)
#define SLOT_2_IRQ_TARGET_GET(x) (((x) >> 27) & 0x1f)
#define SLOT_3_DEVICE_ADDRESS(x) ((x) & 0xFF)
#define SLOT_3_DEVICE_ADDRESS_GET(x) ((x) & 0xFF)
#define SLOT_3_SLOT_STATE(x) (((x) & 0x1F) << 27)
#define SLOT_3_SLOT_STATE_GET(x) (((x) >> 27) & 0x1F)
struct xhci_endpoint_ctx {
uint32 dwendpoint0;
uint32 dwendpoint1;
uint64 qwendpoint2;
uint32 dwendpoint4;
uint32 reserved[3];
};
#define ENDPOINT_0_STATE(x) ((x) & 0x3)
#define ENDPOINT_0_STATE_GET(x) ((x) & 0x3)
#define ENDPOINT_0_MULT(x) (((x) & 0x3) << 8)
#define ENDPOINT_0_MULT_GET(x) (((x) >> 8) & 0x3)
#define ENDPOINT_0_MAXPSTREAMS(x) (((x) & 0x1F) << 10)
#define ENDPOINT_0_MAXPSTREAMS_GET(x) (((x) >> 10) & 0x1F)
#define ENDPOINT_0_LSA_BIT (1U << 15)
#define ENDPOINT_0_INTERVAL(x) (((x) & 0xFF) << 16)
#define ENDPOINT_0_INTERVAL_GET(x) (((x) >> 16) & 0xFF)
#define ENDPOINT_1_CERR(x) (((x) & 0x3) << 1)
#define ENDPOINT_1_CERR_GET(x) (((x) >> 1) & 0x3)
#define ENDPOINT_1_EPTYPE(x) (((x) & 0x7) << 3)
#define ENDPOINT_1_EPTYPE_GET(x) (((x) >> 3) & 0x7)
#define ENDPOINT_1_HID_BIT (1U << 7)
#define ENDPOINT_1_MAXBURST(x) (((x) & 0xFF) << 8)
#define ENDPOINT_1_MAXBURST_GET(x) (((x) >> 8) & 0xFF)
#define ENDPOINT_1_MAXPACKETSIZE(x) (((x) & 0xFFFF) << 16)
#define ENDPOINT_1_MAXPACKETSIZE_GET(x) (((x) >> 16) & 0xFFFF)
#define ENDPOINT_2_DCS_BIT (1U << 0)
#define ENDPOINT_4_AVGTRBLENGTH(x) ((x) & 0xFFFF)
#define ENDPOINT_4_AVGTRBLENGTH_GET(x) ((x) & 0xFFFF)
#define ENDPOINT_4_MAXESITPAYLOAD(x) (((x) & 0xFFFF) << 16)
#define ENDPOINT_4_MAXESITPAYLOAD_GET(x) (((x) >> 16) & 0xFFFF)
struct xhci_stream_ctx {
uint64 qwstream0;
uint32 reserved[2];
};
struct xhci_input_ctx {
uint32 dropFlags;
uint32 addFlags;
uint32 reserved[6];
};
struct xhci_input_device_ctx {
struct xhci_input_ctx input;
struct xhci_slot_ctx slot;
struct xhci_endpoint_ctx endpoints[XHCI_MAX_ENDPOINTS - 1];
};
struct xhci_device_ctx {
struct xhci_slot_ctx slot;
struct xhci_endpoint_ctx endpoints[XHCI_MAX_ENDPOINTS - 1];
};
#endif // !XHCI_HARDWARE_H

View File

@ -8,7 +8,6 @@
*/
#define TRACE_USB
#include "xhci.h"
#define USB_MODULE_NAME "xhci roothub"