diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp b/src/add-ons/kernel/busses/usb/uhci.cpp index d125fb9eb5..e8b7366d71 100644 --- a/src/add-ons/kernel/busses/usb/uhci.cpp +++ b/src/add-ons/kernel/busses/usb/uhci.cpp @@ -367,6 +367,7 @@ UHCI::UHCI(pci_info *info, Stack *stack) // 1: low speed control transfers // 2: full speed control transfers // 3: bulk transfers + // TODO: 4: bandwidth reclamation queue fQueueCount = 4; fQueues = new(std::nothrow) Queue *[fQueueCount]; if (!fQueues) { @@ -389,8 +390,14 @@ UHCI::UHCI(pci_info *info, Stack *stack) // Make sure the last queue terminates fQueues[fQueueCount - 1]->TerminateByStrayDescriptor(); - for (int32 i = 0; i < 1024; i++) - fFrameList[i] = fQueues[0]->PhysicalAddress() | FRAMELIST_NEXT_IS_QH; + // Create the array that will keep bandwidth information + fFrameBandwidth = new(std::nothrow) int32[NUMBER_OF_FRAMES]; + + for (int32 i = 0; i < NUMBER_OF_FRAMES; i++) { + fFrameList[i] = fQueues[UHCI_INTERRUPT_QUEUE]->PhysicalAddress() + | FRAMELIST_NEXT_IS_QH; + fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH; + } // create semaphore the finisher thread will wait for fFinishTransfersSem = create_sem(0, "UHCI Finish Transfers"); @@ -437,6 +444,7 @@ UHCI::~UHCI() delete fQueues[i]; delete [] fQueues; + delete [] fFrameBandwidth; delete fRootHub; delete_area(fFrameArea); @@ -506,6 +514,10 @@ UHCI::SubmitTransfer(Transfer *transfer) if (transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) return SubmitRequest(transfer); + // Process isochronous transfers + if (transfer->TransferPipe()->Type() & USB_OBJECT_ISO_PIPE) + return SubmitIsochronous(transfer); + uhci_td *firstDescriptor = NULL; uhci_qh *transferQueue = NULL; status_t result = CreateFilledTransfer(transfer, &firstDescriptor, @@ -516,11 +528,9 @@ UHCI::SubmitTransfer(Transfer *transfer) Queue *queue = NULL; Pipe *pipe = transfer->TransferPipe(); if (pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) { - // use interrupt queue - queue = fQueues[0]; + queue = fQueues[UHCI_INTERRUPT_QUEUE]; } else { - // use bulk queue - queue = fQueues[3]; + queue = fQueues[UHCI_BULK_QUEUE]; } bool directionIn = (pipe->Direction() == Pipe::In); @@ -634,11 +644,9 @@ UHCI::SubmitRequest(Transfer *transfer) Queue *queue = NULL; if (pipe->Speed() == USB_SPEED_LOWSPEED) { - // use the low speed control queue - queue = fQueues[1]; + queue = fQueues[UHCI_LOW_SPEED_CONTROL_QUEUE]; } else { - // use the full speed control queue - queue = fQueues[2]; + queue = fQueues[UHCI_FULL_SPEED_CONTROL_QUEUE]; } uhci_qh *transferQueue = CreateTransferQueue(setupDescriptor); @@ -697,6 +705,26 @@ UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue, } +status_t +UHCI::SubmitIsochronous(Transfer *transfer) +{ + /* + * This is the main isochronous method. + * Here we attach one Transfer Descriptor (TD) per frame by starting + * at the position specified by StartingFrameNumber. If there is + * not enought bandwidth at that entry number, we find the next + * available one. + * The TD is obviously appended to the latest existing isochronous + * TD (if any) in that frame. + * Everytime a TD is added, fFrameBandiwidth[i] is decremented by + * the TD bandwidth, while it is incremented once the TD has been + * processed by the controller + */ + + return B_ERROR; +} + + int32 UHCI::FinishThread(void *data) { diff --git a/src/add-ons/kernel/busses/usb/uhci.h b/src/add-ons/kernel/busses/usb/uhci.h index 2f22db92e4..5fda3cc351 100644 --- a/src/add-ons/kernel/busses/usb/uhci.h +++ b/src/add-ons/kernel/busses/usb/uhci.h @@ -14,6 +14,12 @@ #include "uhci_hardware.h" #include +#define UHCI_INTERRUPT_QUEUE 0 +#define UHCI_LOW_SPEED_CONTROL_QUEUE 1 +#define UHCI_FULL_SPEED_CONTROL_QUEUE 2 +#define UHCI_BULK_QUEUE 3 +#define UHCI_BANDWIDTH_RECLAMATION_QUEUE 4 + struct pci_info; struct pci_module_info; class UHCIRootHub; @@ -70,6 +76,7 @@ public: virtual status_t SubmitTransfer(Transfer *transfer); virtual status_t CancelQueuedTransfers(Pipe *pipe); status_t SubmitRequest(Transfer *transfer); + status_t SubmitIsochronous(Transfer *transfer); static status_t AddTo(Stack *stack); @@ -149,6 +156,10 @@ static pci_module_info *sPCIModule; area_id fFrameArea; addr_t *fFrameList; + // fFrameBandwidth[n] holds the available bandwidth + // of the nth frame in microseconds + int32 *fFrameBandwidth; + // Queues int32 fQueueCount; Queue **fQueues; diff --git a/src/add-ons/kernel/busses/usb/uhci_hardware.h b/src/add-ons/kernel/busses/usb/uhci_hardware.h index 2656c05407..a29c25f03d 100644 --- a/src/add-ons/kernel/busses/usb/uhci_hardware.h +++ b/src/add-ons/kernel/busses/usb/uhci_hardware.h @@ -79,15 +79,18 @@ #define FRAMELIST_TERMINATE 0x1 #define FRAMELIST_NEXT_IS_QH 0x2 +// Number of frames +#define NUMBER_OF_FRAMES 1024 +#define MAX_AVAILABLE_BANDWIDTH 900 // Microseconds // Represents a Transfer Descriptor (TD) typedef struct { // Hardware part - addr_t link_phy; // Link to the next TD/QH + uint32 link_phy; // Link to the next TD/QH uint32 status; // Status field uint32 token; // Contains the packet header (where it needs to be sent) - void *buffer_phy; // A pointer to the buffer with the actual packet + uint32 buffer_phy; // A pointer to the buffer with the actual packet // Software part addr_t this_phy; // A physical pointer to this address void *link_log; // Pointer to the next logical TD/QT @@ -139,8 +142,8 @@ typedef struct typedef struct { // Hardware part - addr_t link_phy; // Link to the next TD/QH - addr_t element_phy; // Pointer to the first element in the queue + uint32 link_phy; // Link to the next TD/QH + uint32 element_phy; // Pointer to the first element in the queue // Software part addr_t this_phy; // The physical pointer to this address void *link_log; // Pointer to the next logical TD/QH