Work in progress on xHCI bus driver.

* added more traces, coding style
* added xhci_td, xhci_endpoint structs.
* SubmitRequest: this links a 3-stage TD control request into
    the endpoint ring.
* _InsertEndpointForPipe: when a pipe is created, configure the
    endpoint and set up the controller cookie.
* CreateDescriptor and FreeDescriptor: allocates memory for a TD.
* _LinkDescriptorForPipe: link a TD in an endpoint ring.
* _UnlinkDescriptorForPipe: unlink a TD
* AllocateDevice:
    slot number zero isn't valid.
    stick the slot number to the device struct.
    configure the default endpoint before calling SetAddress.
    address is found in the device context instead of the input context.
    device address passed to the USB stack has to begin with 1.
* Ring:
    check for invalid slot/endpoint combination.
    ring the slot doorbell instead of the doorbell 0.
* Root hub: fixed USB version.
* HandleTransferComplete: finds out the TD which submitted a
    transfer.
This commit is contained in:
Jérôme Duval 2012-05-01 22:03:31 +02:00
parent 319a3798bc
commit 2b31b4a88c
6 changed files with 368 additions and 35 deletions

View File

@ -12,7 +12,7 @@
Device::Device(Object *parent, int8 hubAddress, uint8 hubPort,
usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
bool isRootHub)
bool isRootHub, void *controllerCookie)
: Object(parent),
fDeviceDescriptor(desc),
fInitOK(false),
@ -23,7 +23,8 @@ Device::Device(Object *parent, int8 hubAddress, uint8 hubPort,
fSpeed(speed),
fDeviceAddress(deviceAddress),
fHubAddress(hubAddress),
fHubPort(hubPort)
fHubPort(hubPort),
fControllerCookie(controllerCookie)
{
TRACE("creating device\n");
@ -455,20 +456,20 @@ Device::InitEndpoints(int32 interfaceIndex)
direction = Pipe::In;
switch (endpoint->descr->attributes & 0x03) {
case 0x00: /* Control Endpoint */
case USB_ENDPOINT_ATTR_CONTROL: /* Control Endpoint */
pipe = new(std::nothrow) ControlPipe(this);
direction = Pipe::Default;
break;
case 0x01: /* Isochronous Endpoint */
case USB_ENDPOINT_ATTR_ISOCHRONOUS: /* Isochronous Endpoint */
pipe = new(std::nothrow) IsochronousPipe(this);
break;
case 0x02: /* Bulk Endpoint */
case USB_ENDPOINT_ATTR_BULK: /* Bulk Endpoint */
pipe = new(std::nothrow) BulkPipe(this);
break;
case 0x03: /* Interrupt Endpoint */
case USB_ENDPOINT_ATTR_INTERRUPT: /* Interrupt Endpoint */
pipe = new(std::nothrow) InterruptPipe(this);
break;
}

View File

@ -480,7 +480,8 @@ public:
uint8 hubPort,
usb_device_descriptor &desc,
int8 deviceAddress,
usb_speed speed, bool isRootHub);
usb_speed speed, bool isRootHub,
void *controllerCookie = NULL);
virtual ~Device();
status_t InitCheck();
@ -535,6 +536,11 @@ virtual status_t BuildDeviceName(char *string,
{ return fHubAddress; }
uint8 HubPort() const { return fHubPort; }
void SetControllerCookie(void *cookie)
{ fControllerCookie = cookie; }
void * ControllerCookie() const
{ return fControllerCookie; }
// Convenience functions for standard requests
virtual status_t SetFeature(uint16 selector);
virtual status_t ClearFeature(uint16 selector);
@ -554,6 +560,7 @@ private:
int8 fHubAddress;
uint8 fHubPort;
ControlPipe * fDefaultPipe;
void * fControllerCookie;
};

View File

@ -422,6 +422,55 @@ XHCI::SubmitTransfer(Transfer *transfer)
Pipe *pipe = transfer->TransferPipe();
if (pipe->Type() & USB_OBJECT_ISO_PIPE)
return B_UNSUPPORTED;
if (pipe->Type() & USB_OBJECT_CONTROL_PIPE)
return SubmitRequest(transfer);
return B_OK;
}
status_t
XHCI::SubmitRequest(Transfer *transfer)
{
Pipe *pipe = transfer->TransferPipe();
usb_request_data *requestData = transfer->RequestData();
bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) != 0;
TRACE("SubmitRequest()\n");
xhci_td *setupDescriptor = CreateDescriptor(sizeof(usb_request_data));
// set SetupStage
uint8 index = 0;
setupDescriptor->trbs[index].dwtrb2 = TRB_2_IRQ(0) | TRB_2_BYTES(8);
setupDescriptor->trbs[index].dwtrb3 = TRB_3_TYPE(TRB_TYPE_SETUP_STAGE)
| TRB_3_IDT_BIT | TRB_3_CYCLE_BIT;
if (requestData->Length > 0) {
setupDescriptor->trbs[index].dwtrb3 |= directionIn ? TRB_3_TRT_IN
: TRB_3_TRT_OUT;
}
memcpy(&setupDescriptor->trbs[index].qwtrb0, requestData,
sizeof(usb_request_data));
index++;
// set DataStage if any
// set StatusStage
setupDescriptor->trbs[index].dwtrb2 = TRB_2_IRQ(0);
setupDescriptor->trbs[index].dwtrb3 = TRB_3_TYPE(TRB_TYPE_STATUS_STAGE)
| (directionIn ? 0 : TRB_3_DIR_IN) | TRB_3_CYCLE_BIT | TRB_3_IOC_BIT;
setupDescriptor->last_used = index;
xhci_endpoint *endpoint = (xhci_endpoint *)pipe->ControllerCookie();
uint8 id = XHCI_ENDPOINT_ID(pipe);
if (id >= XHCI_MAX_ENDPOINTS)
return B_BAD_VALUE;
setupDescriptor->transfer = transfer;
_LinkDescriptorForPipe(setupDescriptor, endpoint);
TRACE("SubmitRequest() request linked\n");
Ring(endpoint->device->slot, id);
return B_OK;
}
@ -440,11 +489,11 @@ XHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
TRACE("pipe change %d for pipe %p\n", change, pipe);
switch (change) {
case USB_CHANGE_CREATED:
case USB_CHANGE_DESTROYED: {
// ToDo: we should create and keep a single queue head
// for all transfers to/from this pipe
_InsertEndpointForPipe(pipe);
break;
case USB_CHANGE_DESTROYED:
_RemoveEndpointForPipe(pipe);
break;
}
case USB_CHANGE_PIPE_POLICY_CHANGED: {
// ToDo: for isochronous pipes we might need to adapt to new
@ -533,6 +582,52 @@ XHCI::AddTo(Stack *stack)
}
xhci_td *
XHCI::CreateDescriptor(size_t bufferSize)
{
xhci_td *result;
addr_t physicalAddress;
if (fStack->AllocateChunk((void **)&result, (void**)&physicalAddress,
sizeof(xhci_td)) < B_OK) {
TRACE_ERROR("failed to allocate a transfer descriptor\n");
return NULL;
}
result->this_phy = (addr_t)physicalAddress;
result->buffer_size = bufferSize;
if (bufferSize <= 0) {
result->buffer_log = NULL;
result->buffer_phy = 0;
return result;
}
if (fStack->AllocateChunk(&result->buffer_log, (void **)&result->buffer_phy,
bufferSize) < B_OK) {
TRACE_ERROR("unable to allocate space for the buffer\n");
fStack->FreeChunk(result, (void *)result->this_phy, sizeof(xhci_td));
return NULL;
}
return result;
}
void
XHCI::FreeDescriptor(xhci_td *descriptor)
{
if (!descriptor)
return;
if (descriptor->buffer_log) {
fStack->FreeChunk(descriptor->buffer_log,
(void *)descriptor->buffer_phy, descriptor->buffer_size);
}
fStack->FreeChunk(descriptor, (void *)descriptor->this_phy, sizeof(xhci_td));
}
Device *
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
usb_speed speed)
@ -548,7 +643,7 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
return NULL;
}
if (slot > fSlotCount) {
if (slot == 0 || slot > fSlotCount) {
TRACE_ERROR("AllocateDevice() bad slot\n");
return NULL;
}
@ -561,9 +656,11 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
struct xhci_device *device = &fDevices[slot];
memset(device, 0, sizeof(struct xhci_device));
device->state = XHCI_STATE_ENABLED;
device->slot = slot;
device->input_ctx_area = fStack->AllocateArea((void **)&device->input_ctx,
(void**)&device->input_ctx_addr, sizeof(*device->input_ctx), "XHCI input context");
(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;
@ -587,6 +684,9 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
}
device->input_ctx->slot.dwslot0 = SLOT_0_NUM_ENTRIES(1) | SLOT_0_ROUTE(route);
//device->input_ctx->slot.dwslot0 =
// SLOT_0_NUM_ENTRIES(XHCI_MAX_ENDPOINTS - 1) | SLOT_0_ROUTE(route);
// add the speed
switch (speed) {
case USB_SPEED_LOWSPEED:
@ -606,7 +706,7 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
break;
}
device->input_ctx->slot.dwslot1 = SLOT_1_RH_PORT(rhPort);
device->input_ctx->slot.dwslot1 = SLOT_1_RH_PORT(rhPort); // TODO enable power save
device->input_ctx->slot.dwslot2 = SLOT_2_IRQ_TARGET(0);
if (0)
device->input_ctx->slot.dwslot2 |= SLOT_2_PORT_NUM(hubPort);
@ -664,18 +764,31 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
return NULL;
}
if (SetAddress(device->input_ctx_addr, 1, slot) != B_OK) {
device->endpoints[0].device = device;
device->endpoints[0].td_head = NULL;
device->endpoints[0].trbs = device->trbs[0];
device->endpoints[0].used = 0;
device->endpoints[0].current = 0;
device->endpoints[0].trb_addr = device->trb_addr;
// device should get to default state (bsr = 1)
if (SetAddress(device->input_ctx_addr, 0, slot) != B_OK) {
TRACE_ERROR("unable to set address\n");
return NULL;
}
uint8 deviceAddress = SLOT_3_DEVICE_ADDRESS(device->input_ctx->slot.dwslot3);
device->state = XHCI_STATE_DEFAULT;
device->address = SLOT_3_DEVICE_ADDRESS_GET(device->device_ctx->slot.dwslot3);
TRACE("deviceAddress 0x%x\n", deviceAddress);
TRACE("device: address 0x%x state 0x%lx\n", device->address,
SLOT_3_SLOT_STATE_GET(device->device_ctx->slot.dwslot3));
TRACE("endpoint0 state 0x%lx\n",
ENDPOINT_0_STATE_GET(device->device_ctx->endpoints[0].dwendpoint0));
// Create a temporary pipe with the new address
ControlPipe pipe(parent);
pipe.InitCommon(deviceAddress, 0, speed, Pipe::Default, 8, 0, hubAddress,
pipe.SetControllerCookie(&device->endpoints[0]);
pipe.InitCommon(device->address + 1, 0, speed, Pipe::Default, 8, 0, hubAddress,
hubPort);
// Get the device descriptor
@ -698,13 +811,16 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
if (actualLength != 8) {
TRACE_ERROR("error while getting the device descriptor\n");
FreeAddress(deviceAddress);
return NULL;
}
TRACE("device_class: %d device_subclass %d device_protocol %d\n",
deviceDescriptor.device_class, deviceDescriptor.device_subclass,
deviceDescriptor.device_protocol);
TRACE("creating new device\n");
Device *deviceObject = new(std::nothrow) Device(parent, hubAddress, hubPort,
deviceDescriptor, deviceAddress, speed, false);
deviceDescriptor, device->address + 1, speed, false, device);
if (!deviceObject) {
TRACE_ERROR("no memory to allocate device\n");
return NULL;
@ -731,6 +847,114 @@ XHCI::FreeDevice(Device *device)
}
status_t
XHCI::_InsertEndpointForPipe(Pipe *pipe)
{
if (pipe->ControllerCookie() != NULL
|| pipe->Parent()->Type() != USB_OBJECT_DEVICE) {
// default pipe is already referenced
return B_OK;
}
Device* usbDevice = (Device *)pipe->Parent();
struct xhci_device *device = (struct xhci_device *)
usbDevice->ControllerCookie();
if (usbDevice->Parent() == RootObject())
return B_OK;
if (device == NULL) {
panic("_InsertEndpointForPipe device is NULL\n");
return B_OK;
}
uint8 id = XHCI_ENDPOINT_ID(pipe);
if (id >= XHCI_MAX_ENDPOINTS)
return B_BAD_VALUE;
device->endpoints[id].device = device;
device->endpoints[id].trbs = device->trbs[id];
device->endpoints[id].td_head = NULL;
device->endpoints[id].used = 0;
device->endpoints[id].trb_addr = device->trb_addr
+ id * sizeof(device->trbs[0]);
pipe->SetControllerCookie(&device->endpoints[id]);
TRACE("_InsertEndpointForPipe for pipe %p at id %d\n", pipe, id);
return B_OK;
}
status_t
XHCI::_RemoveEndpointForPipe(Pipe *pipe)
{
if (pipe->Parent()->Type() != USB_OBJECT_DEVICE)
return B_OK;
//Device* device = (Device *)pipe->Parent();
return B_OK;
}
status_t
XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
{
TRACE("_LinkDescriptorForPipe\n");
if (endpoint->used >= XHCI_MAX_TRANSFERS)
return B_BAD_VALUE;
endpoint->used++;
if (endpoint->td_head == NULL)
descriptor-> next = NULL;
else
descriptor->next = endpoint->td_head;
endpoint->td_head = descriptor;
uint8 current = endpoint->current;
uint8 next = (current + 1) % (XHCI_MAX_TRANSFERS - 1);
// compute next link
uint8 lastUsed = descriptor->last_used;
addr_t addr = endpoint->trb_addr + next * sizeof(struct xhci_trb);
descriptor->trbs[lastUsed + 1].qwtrb0 = addr;
descriptor->trbs[lastUsed + 1].dwtrb2 = TRB_2_IRQ(0);
descriptor->trbs[lastUsed + 1].dwtrb3 = TRB_3_TYPE(TRB_TYPE_LINK)
| TRB_3_IOC_BIT | TRB_3_CYCLE_BIT;
endpoint->trbs[next]->qwtrb0 = 0;
endpoint->trbs[next]->dwtrb2 = 0;
endpoint->trbs[next]->dwtrb3 = 0;
endpoint->trbs[current]->qwtrb0 = descriptor->this_phy;
endpoint->trbs[current]->dwtrb2 = TRB_2_IRQ(0);
endpoint->trbs[current]->dwtrb3 = TRB_3_TYPE(TRB_TYPE_LINK)
| TRB_3_CYCLE_BIT;
endpoint->current = next;
return B_OK;
}
status_t
XHCI::_UnlinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
{
TRACE("_UnlinkDescriptorForPipe\n");
endpoint->used--;
if (descriptor == endpoint->td_head)
endpoint->td_head = descriptor->next;
else {
for (xhci_td *td = endpoint->td_head; td->next != NULL; td = td->next) {
if (td->next == descriptor) {
td->next = descriptor->next;
return B_OK;
}
}
}
endpoint->used++;
return B_ERROR;
}
status_t
XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, uint16 interval,
uint8 maxPacketCount, uint8 mult, uint8 fpsShift, uint16 maxPacketSize,
@ -1003,22 +1227,28 @@ XHCI::Interrupt()
uint32 temp = ReadRunReg32(XHCI_IMAN(0));
WriteOpReg(XHCI_STS, status);
WriteRunReg32(XHCI_IMAN(0), temp);
TRACE("STS: %lx IRQ_PENDING: %lx\n", status, temp);
int32 result = B_HANDLED_INTERRUPT;
if (status & STS_HCH) {
if ((status & STS_HCH) != 0) {
TRACE_ERROR("Host Controller halted\n");
return result;
}
if (status & STS_HSE) {
if ((status & STS_HSE) != 0) {
TRACE_ERROR("Host System Error\n");
return result;
}
if (status & STS_HCE) {
if ((status & STS_HCE) != 0) {
TRACE_ERROR("Host Controller Error\n");
return result;
}
if ((status & STS_EINT) == 0) {
TRACE("STS: %lx IRQ_PENDING: %lx\n", status, temp);
return B_UNHANDLED_INTERRUPT;
}
TRACE("Event Interrupt\n");
uint16 i = fEventIdx;
uint8 j = fEventCcs;
uint8 t = 2;
@ -1038,6 +1268,13 @@ XHCI::Interrupt()
HandleCmdComplete(&fEventRing[i]);
result = B_INVOKE_SCHEDULER;
break;
case TRB_TYPE_TRANSFER:
HandleTransferComplete(&fEventRing[i]);
result = B_INVOKE_SCHEDULER;
break;
case TRB_TYPE_PORT_STATUS_CHANGE:
TRACE("port change detected\n");
break;
default:
TRACE_ERROR("Unhandled event = %u\n", event);
break;
@ -1065,12 +1302,17 @@ XHCI::Interrupt()
void
XHCI::Ring()
XHCI::Ring(uint8 slot, uint8 endpoint)
{
TRACE("Ding Dong!\n")
WriteDoorReg32(XHCI_DOORBELL(0), 0);
TRACE("Ding Dong! slot:%d endpoint %d\n", slot, endpoint)
if ((slot == 0 && endpoint > 0) || (slot > 0 && endpoint == 0))
panic("Ring() invalid slot/endpoint combination\n");
if (slot > fSlotCount || endpoint > XHCI_MAX_ENDPOINTS)
panic("Ring() invalid slot or endpoint\n");
WriteDoorReg32(XHCI_DOORBELL(slot), XHCI_DOORBELL_TARGET(endpoint)
| XHCI_DOORBELL_STREAMID(0));
/* Flush PCI posted writes */
ReadDoorReg32(XHCI_DOORBELL(0));
ReadDoorReg32(XHCI_DOORBELL(slot));
}
@ -1130,6 +1372,32 @@ XHCI::HandleCmdComplete(xhci_trb *trb)
}
void
XHCI::HandleTransferComplete(xhci_trb *trb)
{
TRACE("HandleTransferComplete trb %p\n", trb);
addr_t source = trb->qwtrb0;
//uint8 completionCode = TRB_2_COMP_CODE_GET(trb->dwtrb2);
//uint32 remainder = TRB_2_REM(trb->dwtrb2);
uint8 endpointNumber = TRB_3_ENDPOINT(trb->dwtrb3);
uint8 slot = TRB_3_SLOT(trb->dwtrb3);
if (slot > fSlotCount)
TRACE_ERROR("invalid slot\n");
if (endpointNumber == 0 || endpointNumber > XHCI_MAX_ENDPOINTS)
TRACE_ERROR("invalid endpoint\n");
xhci_device *device = &fDevices[slot];
xhci_endpoint *endpoint = &device->endpoints[endpointNumber];
for (xhci_td *td = endpoint->td_head; td != NULL; td = td->next) {
int64 offset = source - td->this_phy;
TRACE("HandleTransferComplete td %p offset %lld\n", td, offset);
_UnlinkDescriptorForPipe(td, endpoint);
FreeDescriptor(td);
}
}
status_t
XHCI::DoCommand(xhci_trb *trb)
{
@ -1137,7 +1405,7 @@ XHCI::DoCommand(xhci_trb *trb)
return B_ERROR;
QueueCommand(trb);
Ring();
Ring(0, 0);
if (acquire_sem(fCmdCompSem) < B_OK) {
Unlock();
@ -1159,6 +1427,7 @@ XHCI::DoCommand(xhci_trb *trb)
trb->dwtrb2 = fCmdResult[0];
trb->dwtrb3 = fCmdResult[1];
TRACE("Storing trb 0x%08lx 0x%08lx\n", trb->dwtrb2, trb->dwtrb3);
Unlock();
return status;
@ -1190,7 +1459,7 @@ XHCI::EnableSlot(uint8 *slot)
return status;
*slot = TRB_3_SLOT_GET(trb.dwtrb3);
return B_OK;
return *slot != 0 ? B_OK : B_BAD_VALUE;
}

View File

@ -17,18 +17,48 @@
struct pci_info;
struct pci_module_info;
struct xhci_td;
struct xhci_device;
struct xhci_endpoint;
class XHCIRootHub;
enum xhci_state {
XHCI_STATE_DISABLED = 0,
XHCI_STATE_ENABLED,
XHCI_STATE_DEFAULT,
XHCI_STATE_ADDRESSED,
XHCI_STATE_CONFIGURED,
};
struct xhci_device {
typedef struct xhci_td {
struct xhci_trb trbs[18];
addr_t buffer_phy;
addr_t this_phy; // A physical pointer to this address
void *buffer_log; // Pointer to the logical buffer
size_t buffer_size; // Size of the buffer
struct xhci_td *next;
uint8 last_used;
Transfer *transfer;
} xhci_td __attribute__((__aligned__(16)));
typedef struct xhci_endpoint {
xhci_device *device;
xhci_td *td_head;
struct xhci_trb (*trbs)[XHCI_MAX_TRANSFERS];
addr_t trb_addr;
uint8 used;
uint8 current;
} xhci_endpoint;
typedef struct xhci_device {
uint8 slot;
uint8 address;
enum xhci_state state;
area_id trb_area;
addr_t trb_addr;
@ -41,7 +71,9 @@ struct xhci_device {
area_id device_ctx_area;
addr_t device_ctx_addr;
struct xhci_device_ctx *device_ctx;
};
xhci_endpoint endpoints[XHCI_MAX_ENDPOINTS - 1];
} xhci_device;
class XHCI : public BusManager {
@ -51,6 +83,7 @@ public:
status_t Start();
virtual status_t SubmitTransfer(Transfer *transfer);
status_t SubmitRequest(Transfer *transfer);
virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force);
virtual status_t NotifyPipeChange(Pipe *pipe,
@ -68,6 +101,9 @@ public:
uint16 maxPacketSize, uint16 maxFrameSize);
virtual void FreeDevice(Device *device);
status_t _InsertEndpointForPipe(Pipe *pipe);
status_t _RemoveEndpointForPipe(Pipe *pipe);
// Port operations for root hub
uint8 PortCount() const { return fPortCount; }
status_t GetPortStatus(uint8 index,
@ -92,12 +128,22 @@ private:
static int32 FinishThread(void *data);
void FinishTransfers();
// Descriptor
xhci_td * CreateDescriptor(size_t bufferSize);
void FreeDescriptor(xhci_td *descriptor);
status_t _LinkDescriptorForPipe(xhci_td *descriptor,
xhci_endpoint *endpoint);
status_t _UnlinkDescriptorForPipe(xhci_td *descriptor,
xhci_endpoint *endpoint);
// Command
void QueueCommand(xhci_trb *trb);
void HandleCmdComplete(xhci_trb *trb);
void HandleTransferComplete(xhci_trb *trb);
status_t DoCommand(xhci_trb *trb);
//Doorbell
void Ring();
void Ring(uint8 slot, uint8 endpoint);
// Commands
status_t Noop();

View File

@ -42,8 +42,9 @@
// USB Status Register
#define STS_HCH (1 << 0)
#define STS_HSE (1 << 2)
#define STS_EINT (1 << 3)
#define STS_PCD (1 << 4)
#define STS_CNR (1<<11)
#define STS_CNR (1 << 11)
#define STS_HCE (1 << 12)
#define XHCI_PAGESIZE 0x08 // PAGE SIZE
#define XHCI_DNCTRL 0x14
@ -81,6 +82,11 @@
// Host Controller Doorbell Registers
#define XHCI_DOORBELL(n) (0x0000 + (4 * (n)))
#define XHCI_DOORBELL_TARGET(x) ((x) & 0xff)
#define XHCI_DOORBELL_TARGET_GET(x) ((x) & 0xff)
#define XHCI_DOORBELL_STREAMID(x) (((x) & 0xffff) << 16)
#define XHCI_DOORBELL_STREAMID_GET(x) (((x) >> 16) & 0xffff)
// Extended Capabilities
#define XECP_ID(x) ((x) & 0xff)
@ -400,4 +406,8 @@ struct xhci_device_ctx {
};
#define XHCI_ENDPOINT_ID(pipe) (2 * pipe->EndpointAddress() \
+ (pipe->Direction() != Pipe::Out ? 1 : 0))
#endif // !XHCI_HARDWARE_H

View File

@ -23,7 +23,7 @@ static usb_device_descriptor sXHCIRootHubDevice =
9, // Max packet size on endpoint 0
0, // Vendor ID
0, // Product ID
0x003, // Version
0x300, // Version
1, // Index of manufacturer string
2, // Index of product string
0, // Index of serial number string