Work in progress on xHCI bus driver, testing on emulation.

* Initial testing with QEmu emulation works with interrupt/bulk,
   testing on real hardware still not working. Small bulk requests work
   OK, not bigger ones (for instance it can't load the MediaPlayer
   application at 800KB).
* QEmu doesn't support byte read in the MMIO space, switch to double word.
* added SubmitNormalRequest() for interrupt and bulk endpoints.
* AllocateDevice(): fixed the physical address of the link TRB pointing
   to the beginning of the ring.
* _InsertEndpointForPipe(): setup context for non-default endpoints
   on creation. This should get the device to the configured state.
* _UnlinkDescriptorForPipe(): the next pointer wasn't null after unlinking.
* HandleTransferComplete(): add descriptor to a list to be processed by the
   finisher thread.
* FinishThread(): process finished transfers and call the callback,
   then free the TRB.
This commit is contained in:
Jérôme Duval 2012-05-02 23:10:49 +02:00
parent 6457a6517e
commit 77a7e76cc1
3 changed files with 262 additions and 86 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2011, Haiku Inc. All rights reserved.
* Copyright 2006-2012, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Some code borrowed from the Haiku EHCI driver
@ -42,6 +42,51 @@ xhci_std_ops(int32 op, ...)
}
static const char*
xhci_error_string(uint32 error)
{
switch (error) {
case COMP_INVALID: return "Invalid";
case COMP_SUCCESS: return "Success";
case COMP_DATA_BUFFER: return "Data buffer";
case COMP_BABBLE: return "Babble detected";
case COMP_USB_TRANSACTION: return "USB transaction";
case COMP_TRB: return "TRB";
case COMP_STALL: return "Stall";
case COMP_RESOURCE: return "Resource";
case COMP_BANDWIDTH: return "Bandwidth";
case COMP_NO_SLOTS: return "No slots";
case COMP_INVALID_STREAM: return "Invalid stream";
case COMP_SLOT_NOT_ENABLED: return "Slot not enabled";
case COMP_ENDPOINT_NOT_ENABLED: return "Endpoint not enabled";
case COMP_SHORT_PACKET: return "Short packet";
case COMP_RING_UNDERRUN: return "Ring underrun";
case COMP_RING_OVERRUN: return "Ring overrun";
case COMP_VF_RING_FULL: return "VF Event Ring Full";
case COMP_PARAMETER: return "Parameter";
case COMP_BANDWIDTH_OVERRUN: return "Bandwidth overrun";
case COMP_CONTEXT_STATE: return "Context state";
case COMP_NO_PING_RESPONSE: return "No ping response";
case COMP_EVENT_RING_FULL: return "Event ring full";
case COMP_INCOMPATIBLE_DEVICE: return "Incompatible device";
case COMP_MISSED_SERVICE: return "Missed service";
case COMP_COMMAND_RING_STOPPED: return "Command ring stopped";
case COMP_COMMAND_ABORTED: return "Command aborted";
case COMP_STOPPED: return "Stopped";
case COMP_LENGTH_INVALID: return "Length invalid";
case COMP_MAX_EXIT_LATENCY: return "Max exit latency too large";
case COMP_ISOC_OVERRUN: return "Isoch buffer overrun";
case COMP_EVENT_LOST: return "Event lost";
case COMP_UNDEFINED: return "Undefined";
case COMP_INVALID_STREAM_ID: return "Invalid stream ID";
case COMP_SECONDARY_BANDWIDTH: return "Secondary bandwidth";
case COMP_SPLIT_TRANSACTION: return "Split transaction";
default: return "Undefined";
}
}
usb_host_controller_info xhci_module = {
{
"busses/usb/xhci",
@ -73,6 +118,7 @@ XHCI::XHCI(pci_info *info, Stack *stack)
fFinishTransfersSem(-1),
fFinishThread(-1),
fStopThreads(false),
fFinishedHead(NULL),
fRootHub(NULL),
fRootHubAddress(0),
fPortCount(0),
@ -119,13 +165,15 @@ XHCI::XHCI(pci_info *info, Stack *stack)
return;
}
uint32 hciCapLength = ReadCapReg32(XHCI_HCI_CAPLENGTH);
fCapabilityRegisters += offset;
fOperationalRegisters = fCapabilityRegisters + ReadCapReg8(XHCI_CAPLENGTH);
TRACE("mapped capability length: 0x%lx\n", fCapabilityLength);
fOperationalRegisters = fCapabilityRegisters + HCI_CAPLENGTH(hciCapLength);
fRuntimeRegisters = fCapabilityRegisters + ReadCapReg32(XHCI_RTSOFF);
fDoorbellRegisters = fCapabilityRegisters + ReadCapReg32(XHCI_DBOFF);
TRACE("mapped capability registers: 0x%08lx\n", (uint32)fCapabilityRegisters);
TRACE("mapped operational registers: 0x%08lx\n", (uint32)fOperationalRegisters);
TRACE("mapped rumtime registers: 0x%08lx\n", (uint32)fRuntimeRegisters);
TRACE("mapped runtime registers: 0x%08lx\n", (uint32)fRuntimeRegisters);
TRACE("mapped doorbell registers: 0x%08lx\n", (uint32)fDoorbellRegisters);
TRACE("structural parameters1: 0x%08lx\n", ReadCapReg32(XHCI_HCSPARAMS1));
@ -141,6 +189,7 @@ XHCI::XHCI(pci_info *info, Stack *stack)
if (XECP_ID(eec) != XHCI_LEGSUP_CAPID)
continue;
}
TRACE("eecp register: 0x%04lx\n", eecp);
if (eec & XHCI_LEGSUP_BIOSOWNED) {
TRACE_ALWAYS("the host controller is bios owned, claiming"
" ownership\n");
@ -363,7 +412,8 @@ XHCI::Start()
WriteRunReg32(XHCI_ERSTBA_LO(0), (uint32)dmaAddress);
WriteRunReg32(XHCI_ERSTBA_HI(0), /*(uint32)(dmaAddress >> 32)*/0);
dmaAddress += sizeof(xhci_erst_element) + XHCI_MAX_EVENTS * sizeof(xhci_trb);
dmaAddress += sizeof(xhci_erst_element) + XHCI_MAX_EVENTS
* sizeof(xhci_trb);
TRACE("setting CRCR addr = 0x%lx\n", dmaAddress);
WriteOpReg(XHCI_CRCR_LO, (uint32)dmaAddress | CRCR_RCS);
WriteOpReg(XHCI_CRCR_HI, /*(uint32)(dmaAddress >> 32)*/0);
@ -420,24 +470,24 @@ XHCI::SubmitTransfer(Transfer *transfer)
TRACE("SubmitTransfer()\n");
Pipe *pipe = transfer->TransferPipe();
if (pipe->Type() & USB_OBJECT_ISO_PIPE)
if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0)
return B_UNSUPPORTED;
if (pipe->Type() & USB_OBJECT_CONTROL_PIPE)
return SubmitRequest(transfer);
return B_OK;
if ((pipe->Type() & USB_OBJECT_CONTROL_PIPE) != 0)
return SubmitControlRequest(transfer);
return SubmitNormalRequest(transfer);
}
status_t
XHCI::SubmitRequest(Transfer *transfer)
XHCI::SubmitControlRequest(Transfer *transfer)
{
Pipe *pipe = transfer->TransferPipe();
usb_request_data *requestData = transfer->RequestData();
bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) != 0;
TRACE("SubmitRequest()\n");
TRACE("SubmitControlRequest()\n");
xhci_td *setupDescriptor = CreateDescriptor(sizeof(usb_request_data));
xhci_td *setupDescriptor = CreateDescriptor(requestData->Length);
// set SetupStage
uint8 index = 0;
@ -453,11 +503,24 @@ XHCI::SubmitRequest(Transfer *transfer)
index++;
// set DataStage if any
if (requestData->Length > 0) {
// set DataStage if any
setupDescriptor->trbs[index].qwtrb0 = setupDescriptor->buffer_phy;
setupDescriptor->trbs[index].dwtrb2 = TRB_2_IRQ(0)
| TRB_2_BYTES(requestData->Length)
| TRB_2_TD_SIZE(transfer->VectorCount());
setupDescriptor->trbs[index].dwtrb3 = TRB_3_TYPE(TRB_TYPE_DATA_STAGE)
| (directionIn ? TRB_3_DIR_IN : 0) | TRB_3_CYCLE_BIT;
// TODO copy data for out transfers
index++;
}
// 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;
| ((directionIn && requestData->Length > 0) ? 0 : TRB_3_DIR_IN)
| TRB_3_IOC_BIT | TRB_3_CYCLE_BIT;
setupDescriptor->last_used = index;
@ -468,7 +531,46 @@ XHCI::SubmitRequest(Transfer *transfer)
setupDescriptor->transfer = transfer;
_LinkDescriptorForPipe(setupDescriptor, endpoint);
TRACE("SubmitRequest() request linked\n");
TRACE("SubmitControlRequest() request linked\n");
Ring(endpoint->device->slot, id);
return B_OK;
}
status_t
XHCI::SubmitNormalRequest(Transfer *transfer)
{
TRACE("SubmitNormalRequest()\n");
Pipe *pipe = transfer->TransferPipe();
bool directionIn = (pipe->Direction() == Pipe::In);
xhci_td *normalDescriptor = CreateDescriptor(transfer->VectorLength());
// set NormalStage
uint8 index = 0;
normalDescriptor->trbs[index].qwtrb0 = normalDescriptor->buffer_phy;
normalDescriptor->trbs[index].dwtrb2 = TRB_2_IRQ(0)
| TRB_2_BYTES(transfer->VectorLength())
| TRB_2_TD_SIZE(transfer->VectorCount());
normalDescriptor->trbs[index].dwtrb3 = TRB_3_TYPE(TRB_TYPE_NORMAL)
| TRB_3_CYCLE_BIT | TRB_3_IOC_BIT;
if (!directionIn) {
memcpy(normalDescriptor->buffer_log,
(uint8 *)transfer->Vector()[0].iov_base, transfer->VectorLength());
}
normalDescriptor->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;
normalDescriptor->transfer = transfer;
_LinkDescriptorForPipe(normalDescriptor, endpoint);
TRACE("SubmitNormalRequest() request linked\n");
Ring(endpoint->device->slot, id);
@ -486,7 +588,8 @@ XHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
status_t
XHCI::NotifyPipeChange(Pipe *pipe, usb_change change)
{
TRACE("pipe change %d for pipe %p\n", change, pipe);
TRACE("pipe change %d for pipe %p (%d)\n", change, pipe,
pipe->EndpointAddress());
switch (change) {
case USB_CHANGE_CREATED:
_InsertEndpointForPipe(pipe);
@ -511,9 +614,6 @@ XHCI::AddTo(Stack *stack)
{
#ifdef TRACE_USB
set_dprintf_enabled(true);
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
load_driver_symbols("xhci");
#endif
#endif
if (!sPCIModule) {
@ -602,9 +702,10 @@ XHCI::CreateDescriptor(size_t bufferSize)
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");
if (fStack->AllocateChunk(&result->buffer_log,
(void **)&result->buffer_phy, bufferSize) < B_OK) {
TRACE_ERROR("unable to allocate space for the buffer (size %ld)\n",
bufferSize);
fStack->FreeChunk(result, (void *)result->this_phy, sizeof(xhci_td));
return NULL;
}
@ -624,7 +725,8 @@ XHCI::FreeDescriptor(xhci_td *descriptor)
(void *)descriptor->buffer_phy, descriptor->buffer_size);
}
fStack->FreeChunk(descriptor, (void *)descriptor->this_phy, sizeof(xhci_td));
fStack->FreeChunk(descriptor, (void *)descriptor->this_phy,
sizeof(xhci_td));
}
@ -734,8 +836,9 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
}
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]);
struct xhci_trb *linkTrb = device->trbs + (i + 1) * XHCI_MAX_TRANSFERS - 1;
linkTrb->qwtrb0 = device->trb_addr
+ i * XHCI_MAX_TRANSFERS * sizeof(xhci_trb);
linkTrb->dwtrb2 = TRB_2_IRQ(0);
linkTrb->dwtrb3 = TRB_3_CYCLE_BIT | TRB_3_TYPE(TRB_TYPE_LINK);
}
@ -766,18 +869,18 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
device->endpoints[0].device = device;
device->endpoints[0].td_head = NULL;
device->endpoints[0].trbs = device->trbs[0];
device->endpoints[0].trbs = device->trbs;
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) {
// device should get to addressed state (bsr = 0)
if (SetAddress(device->input_ctx_addr, false, slot) != B_OK) {
TRACE_ERROR("unable to set address\n");
return NULL;
}
device->state = XHCI_STATE_DEFAULT;
device->state = XHCI_STATE_ADDRESSED;
device->address = SLOT_3_DEVICE_ADDRESS_GET(device->device_ctx->slot.dwslot3);
TRACE("device: address 0x%x state 0x%lx\n", device->address,
@ -866,18 +969,62 @@ XHCI::_InsertEndpointForPipe(Pipe *pipe)
return B_OK;
}
uint8 id = XHCI_ENDPOINT_ID(pipe);
uint8 id = XHCI_ENDPOINT_ID(pipe) - 1;
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]);
if (id > 0) {
device->endpoints[id].device = device;
device->endpoints[id].trbs = device->trbs
+ id * XHCI_MAX_TRANSFERS;
device->endpoints[id].td_head = NULL;
device->endpoints[id].used = 0;
device->endpoints[id].trb_addr = device->trb_addr
+ id * XHCI_MAX_TRANSFERS * sizeof(xhci_trb);
TRACE("_InsertEndpointForPipe trbs device %p endpoint %p\n",
device->trbs, device->endpoints[id].trbs);
TRACE("_InsertEndpointForPipe trb_addr device 0x%lx endpoint 0x%lx\n",
device->trb_addr, device->endpoints[id].trb_addr);
uint8 endpoint = id + 1;
StopEndpoint(false, endpoint, device->slot);
ResetEndpoint(false, endpoint, device->slot);
SetTRDequeue(device->endpoints[id].trb_addr, 0, endpoint,
device->slot);
device->input_ctx->input.dropFlags = 0;
device->input_ctx->input.addFlags = (1 << endpoint) | (1 << 0);
// configure the Control endpoint 0 (type 4)
uint32 type = 4;
if ((pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) != 0)
type = 3;
if ((pipe->Type() & USB_OBJECT_BULK_PIPE) != 0)
type = 2;
if ((pipe->Type() & USB_OBJECT_ISO_PIPE) != 0)
type = 1;
type |= (pipe->Direction() == Pipe::In) ? (1 << 2) : 0;
TRACE("trb_addr 0x%lx\n", device->endpoints[id].trb_addr);
if (ConfigureEndpoint(device->slot, id, type,
device->endpoints[id].trb_addr, pipe->Interval(),
1, 1, 0, pipe->MaxPacketSize(), pipe->MaxPacketSize()) != B_OK) {
TRACE_ERROR("unable to configure endpoint\n");
return B_ERROR;
}
EvaluateContext(device->input_ctx_addr, device->slot);
ConfigureEndpoint(device->input_ctx_addr, false, device->slot);
device->state = XHCI_STATE_CONFIGURED;
}
pipe->SetControllerCookie(&device->endpoints[id]);
TRACE("_InsertEndpointForPipe for pipe %p at id %d\n", pipe, id);
return B_OK;
@ -904,7 +1051,7 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
endpoint->used++;
if (endpoint->td_head == NULL)
descriptor-> next = NULL;
descriptor->next = NULL;
else
descriptor->next = endpoint->td_head;
endpoint->td_head = descriptor;
@ -912,6 +1059,8 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
uint8 current = endpoint->current;
uint8 next = (current + 1) % (XHCI_MAX_TRANSFERS - 1);
TRACE("_LinkDescriptorForPipe current %d, next %d\n", current, next);
// compute next link
uint8 lastUsed = descriptor->last_used;
addr_t addr = endpoint->trb_addr + next * sizeof(struct xhci_trb);
@ -920,14 +1069,19 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
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[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)
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;
TRACE("_LinkDescriptorForPipe pCurrent %p phys 0x%lx 0x%llx 0x%lx\n",
&endpoint->trbs[current],
endpoint->trb_addr + current * sizeof(struct xhci_trb),
endpoint->trbs[current].qwtrb0, endpoint->trbs[current].dwtrb3);
endpoint->current = next;
return B_OK;
@ -939,12 +1093,15 @@ XHCI::_UnlinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
{
TRACE("_UnlinkDescriptorForPipe\n");
endpoint->used--;
if (descriptor == endpoint->td_head)
if (descriptor == endpoint->td_head) {
endpoint->td_head = descriptor->next;
else {
descriptor->next = NULL;
return B_OK;
} else {
for (xhci_td *td = endpoint->td_head; td->next != NULL; td = td->next) {
if (td->next == descriptor) {
td->next = descriptor->next;
descriptor->next = NULL;
return B_OK;
}
}
@ -978,16 +1135,16 @@ XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, u
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;
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,
@ -1378,9 +1535,9 @@ 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);
//uint32 remainder = TRB_2_REM_GET(trb->dwtrb2);
uint8 endpointNumber = TRB_3_ENDPOINT_GET(trb->dwtrb3);
uint8 slot = TRB_3_SLOT_GET(trb->dwtrb3);
if (slot > fSlotCount)
TRACE_ERROR("invalid slot\n");
@ -1388,12 +1545,17 @@ XHCI::HandleTransferComplete(xhci_trb *trb)
TRACE_ERROR("invalid endpoint\n");
xhci_device *device = &fDevices[slot];
xhci_endpoint *endpoint = &device->endpoints[endpointNumber];
xhci_endpoint *endpoint = &device->endpoints[endpointNumber - 1];
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);
// add descriptor to finished list (to be processed and freed)
td->next = fFinishedHead;
fFinishedHead = td;
release_sem(fFinishTransfersSem);
break;
}
}
@ -1420,8 +1582,9 @@ XHCI::DoCommand(xhci_trb *trb)
status_t status = B_OK;
TRACE("Command Complete\n");
if (TRB_2_COMP_CODE_GET(fCmdResult[0]) != COMP_SUCCESS) {
TRACE_ERROR("unsuccessful no-op command %ld\n",
TRB_2_COMP_CODE_GET(fCmdResult[0]));
uint32 errorCode = TRB_2_COMP_CODE_GET(fCmdResult[0]);
TRACE_ERROR("unsuccessful command %s (%ld)\n",
xhci_error_string(errorCode), errorCode);
status = B_IO_ERROR;
}
@ -1573,7 +1736,7 @@ XHCI::ResetDevice(uint8 slot)
int32
XHCI::FinishThread(void *data)
XHCI::FinishThread(void* data)
{
((XHCI *)data)->FinishTransfers();
return B_OK;
@ -1594,6 +1757,28 @@ XHCI::FinishTransfers()
acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
TRACE("finishing transfers\n");
while (fFinishedHead != NULL) {
xhci_td* td = fFinishedHead;
fFinishedHead = td->next;
td->next = NULL;
Transfer* transfer = td->transfer;
bool directionIn = (transfer->TransferPipe()->Direction() != Pipe::Out);
usb_request_data *requestData = transfer->RequestData();
// TODO check event
status_t callbackStatus = B_OK;
size_t actualLength = requestData ? requestData->Length
: transfer->VectorLength();
if (directionIn) {
memcpy((uint8 *)transfer->Vector()[0].iov_base,
td->buffer_log, actualLength);
}
transfer->Finished(callbackStatus, actualLength);
FreeDescriptor(td);
}
}
}
@ -1611,20 +1796,6 @@ XHCI::ReadOpReg(uint32 reg)
}
inline uint8
XHCI::ReadCapReg8(uint32 reg)
{
return *(volatile uint8 *)(fCapabilityRegisters + reg);
}
inline uint16
XHCI::ReadCapReg16(uint32 reg)
{
return *(volatile uint16 *)(fCapabilityRegisters + reg);
}
inline uint32
XHCI::ReadCapReg32(uint32 reg)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2011, Haiku Inc. All rights reserved.
* Copyright 2006-2012, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -49,7 +49,7 @@ typedef struct xhci_td {
typedef struct xhci_endpoint {
xhci_device *device;
xhci_td *td_head;
struct xhci_trb (*trbs)[XHCI_MAX_TRANSFERS];
struct xhci_trb *trbs; // [XHCI_MAX_TRANSFERS]
addr_t trb_addr;
uint8 used;
uint8 current;
@ -62,7 +62,7 @@ typedef 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];
struct xhci_trb (*trbs); // [XHCI_MAX_ENDPOINTS - 1][XHCI_MAX_TRANSFERS]
area_id input_ctx_area;
addr_t input_ctx_addr;
@ -83,7 +83,8 @@ public:
status_t Start();
virtual status_t SubmitTransfer(Transfer *transfer);
status_t SubmitRequest(Transfer *transfer);
status_t SubmitControlRequest(Transfer *transfer);
status_t SubmitNormalRequest(Transfer *transfer);
virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force);
virtual status_t NotifyPipeChange(Pipe *pipe,
@ -168,8 +169,6 @@ private:
inline uint32 ReadOpReg(uint32 reg);
// Capability register functions
inline uint8 ReadCapReg8(uint32 reg);
inline uint16 ReadCapReg16(uint32 reg);
inline uint32 ReadCapReg32(uint32 reg);
inline void WriteCapReg32(uint32 reg, uint32 value);
@ -184,8 +183,11 @@ private:
static pci_module_info * sPCIModule;
uint8 * fCapabilityRegisters;
uint32 fCapabilityLength;
uint8 * fOperationalRegisters;
uint32 fOperationalLength;
uint8 * fRuntimeRegisters;
uint32 fRuntimeLength;
uint8 * fDoorbellRegisters;
area_id fRegisterArea;
pci_info * fPCIInfo;
@ -208,6 +210,8 @@ private:
thread_id fFinishThread;
bool fStopThreads;
xhci_td * fFinishedHead;
// Root Hub
XHCIRootHub * fRootHub;
uint8 fRootHubAddress;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2011, Haiku Inc. All rights reserved.
* Copyright 2011-2012, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -11,8 +11,9 @@
// Host Controller Capability Registers
#define XHCI_CAPLENGTH 0x00 // Capability Register Length
#define XHCI_HCIVERSION 0x02 // Interface Version Number
#define XHCI_HCI_CAPLENGTH 0x00 // HCI Capability Register Length
#define HCI_CAPLENGTH(p) (((p) >> 0) & 0xff)
#define HCI_VERSION(p) (((p) >> 16) & 0xffff) // HCI Version
#define XHCI_HCSPARAMS1 0x04 // Structural Parameters 1
// HCSPARAMS1
#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff)