[haiku-commits] haiku: hrev44093 - src/add-ons/kernel/busses/usb

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 2 May 2012 23:45:41 +0200 (CEST)

hrev44093 adds 1 changeset to branch 'master'
old head: 6457a6517eaa53baeb531ce9995617c3caa7010e
new head: 77a7e76cc13ba10f354d1cf43467b612149e04ab

----------------------------------------------------------------------------

77a7e76: 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.

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev44093
Commit:      77a7e76cc13ba10f354d1cf43467b612149e04ab
URL:         http://cgit.haiku-os.org/haiku/commit/?id=77a7e76
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Wed May  2 21:10:49 2012 UTC

----------------------------------------------------------------------------

3 files changed, 262 insertions(+), 86 deletions(-)
src/add-ons/kernel/busses/usb/xhci.cpp        |  325 ++++++++++++++++-----
src/add-ons/kernel/busses/usb/xhci.h          |   16 +-
src/add-ons/kernel/busses/usb/xhci_hardware.h |    7 +-

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp 
b/src/add-ons/kernel/busses/usb/xhci.cpp
index edddab0..2348264 100644
--- a/src/add-ons/kernel/busses/usb/xhci.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci.cpp
@@ -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)
 {
diff --git a/src/add-ons/kernel/busses/usb/xhci.h 
b/src/add-ons/kernel/busses/usb/xhci.h
index f872dba..0fa92eb 100644
--- a/src/add-ons/kernel/busses/usb/xhci.h
+++ b/src/add-ons/kernel/busses/usb/xhci.h
@@ -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;
diff --git a/src/add-ons/kernel/busses/usb/xhci_hardware.h 
b/src/add-ons/kernel/busses/usb/xhci_hardware.h
index 348cadc..82fffaf 100644
--- a/src/add-ons/kernel/busses/usb/xhci_hardware.h
+++ b/src/add-ons/kernel/busses/usb/xhci_hardware.h
@@ -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)


Other related posts:

  • » [haiku-commits] haiku: hrev44093 - src/add-ons/kernel/busses/usb - korli