diff --git a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp index 5f696cb51c..87762cd3d0 100644 --- a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp +++ b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp @@ -12,8 +12,6 @@ BusManager::BusManager(Stack *stack) : fInitOK(false), - fDefaultPipe(NULL), - fDefaultPipeLowSpeed(NULL), fRootHub(NULL), fExploreThread(-1) { @@ -31,15 +29,14 @@ BusManager::BusManager(Stack *stack) fDeviceMap[i] = false; // Set up the default pipes - fDefaultPipe = new(std::nothrow) ControlPipe(fRootObject, 0, 0, - Pipe::FullSpeed, 8); - if (!fDefaultPipe) - return; - - fDefaultPipeLowSpeed = new(std::nothrow) ControlPipe(fRootObject, 0, 0, - Pipe::LowSpeed, 8); - if (!fDefaultPipeLowSpeed) - return; + for (int32 i = 0; i <= USB_SPEED_MAX; i++) { + fDefaultPipes[i] = new(std::nothrow) ControlPipe(fRootObject, 0, 0, + (usb_speed)i, 8); + if (!fDefaultPipes[i]) { + TRACE_ERROR(("usb BusManager: failed to allocate default pipes\n")); + return; + } + } fInitOK = true; } @@ -118,7 +115,7 @@ BusManager::AllocateAddress() Device * -BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed) +BusManager::AllocateNewDevice(Hub *parent, usb_speed speed) { // Check if there is a free entry in the device map (for the device number) int8 deviceAddress = AllocateAddress(); @@ -128,7 +125,7 @@ BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed) } TRACE(("usb BusManager::AllocateNewDevice(): setting device address to %d\n", deviceAddress)); - ControlPipe *defaultPipe = (lowSpeed ? fDefaultPipeLowSpeed : fDefaultPipe); + ControlPipe *defaultPipe = fDefaultPipes[speed]; status_t result = B_ERROR; for (int32 i = 0; i < 15; i++) { @@ -158,8 +155,7 @@ BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed) snooze(USB_DELAY_SET_ADDRESS); // Create a temporary pipe with the new address - ControlPipe pipe(parent, deviceAddress, 0, - lowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed, 8); + ControlPipe pipe(parent, deviceAddress, 0, speed, 8); // Get the device descriptor // Just retrieve the first 8 bytes of the descriptor -> minimum supported @@ -197,7 +193,7 @@ BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed) if (deviceDescriptor.device_class == 0x09) { TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n")); Hub *hub = new(std::nothrow) Hub(parent, deviceDescriptor, - deviceAddress, lowSpeed); + deviceAddress, speed); if (!hub) { TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate hub\n")); return NULL; @@ -214,7 +210,7 @@ BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed) TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n")); Device *device = new(std::nothrow) Device(parent, deviceDescriptor, - deviceAddress, lowSpeed); + deviceAddress, speed); if (!device) { TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate device\n")); return NULL; diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index cff1f91ac9..d4f4917ea2 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -11,13 +11,13 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, - bool lowSpeed) + usb_speed speed) : Object(parent), fDeviceDescriptor(desc), fInitOK(false), fConfigurations(NULL), fCurrentConfiguration(NULL), - fLowSpeed(lowSpeed), + fSpeed(speed), fDeviceAddress(deviceAddress), fLock(-1), fNotifyCookie(NULL) @@ -33,8 +33,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, set_sem_owner(fLock, B_SYSTEM_TEAM); fDefaultPipe = new(std::nothrow) ControlPipe(this, deviceAddress, 0, - fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed, - fDeviceDescriptor.max_packet_size_0); + fSpeed, fDeviceDescriptor.max_packet_size_0); if (!fDefaultPipe) { TRACE_ERROR(("USB Device: could not allocate default pipe\n")); return; @@ -189,8 +188,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, endpoint = new(std::nothrow) ControlPipe(this, fDeviceAddress, endpointDescriptor->endpoint_address & 0x0f, - fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed, - endpointDescriptor->max_packet_size); + fSpeed, endpointDescriptor->max_packet_size); break; case 0x01: /* Isochronous Endpoint */ @@ -198,8 +196,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, fDeviceAddress, endpointDescriptor->endpoint_address & 0x0f, (endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, - fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed, - endpointDescriptor->max_packet_size); + fSpeed, endpointDescriptor->max_packet_size); break; case 0x02: /* Bulk Endpoint */ @@ -207,8 +204,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, fDeviceAddress, endpointDescriptor->endpoint_address & 0x0f, (endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, - fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed, - endpointDescriptor->max_packet_size); + fSpeed, endpointDescriptor->max_packet_size); break; case 0x03: /* Interrupt Endpoint */ @@ -216,8 +212,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, fDeviceAddress, endpointDescriptor->endpoint_address & 0x0f, (endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out, - fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed, - endpointDescriptor->max_packet_size); + fSpeed, endpointDescriptor->max_packet_size); break; } diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 50bf169e61..a5a74b711f 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -12,8 +12,8 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, - bool lowSpeed) - : Device(parent, desc, deviceAddress, lowSpeed) + usb_speed speed) + : Device(parent, desc, deviceAddress, speed) { TRACE(("USB Hub is being initialised\n")); @@ -23,7 +23,7 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, } // Set to false again for the hub init. - fInitOK = false; + fInitOK = false; for (int32 i = 0; i < 8; i++) fChildren[i] = NULL; @@ -178,8 +178,14 @@ Hub::Explore() continue; } + usb_speed speed = USB_SPEED_FULLSPEED; + if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED) + speed = USB_SPEED_LOWSPEED; + if (fPortStatus[i].status & PORT_STATUS_HIGH_SPEED) + speed = USB_SPEED_HIGHSPEED; + Device *newDevice = GetBusManager()->AllocateNewDevice(this, - (fPortStatus[i].status & PORT_STATUS_LOW_SPEED) > 0); + speed); if (newDevice) { fChildren[i] = newDevice; diff --git a/src/add-ons/kernel/bus_managers/usb/Jamfile b/src/add-ons/kernel/bus_managers/usb/Jamfile index 0ebf047ad1..b785af828a 100644 --- a/src/add-ons/kernel/bus_managers/usb/Jamfile +++ b/src/add-ons/kernel/bus_managers/usb/Jamfile @@ -19,6 +19,7 @@ KernelStaticLibrary libusb.a : Pipe.cpp Interface.cpp Object.cpp + PhysicalMemoryAllocator.cpp : -fno-pic ; diff --git a/src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.cpp b/src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.cpp new file mode 100644 index 0000000000..8897dc4e98 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.cpp @@ -0,0 +1,340 @@ +/* + * Copyright 2006, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + +#include +#include +#include +#include "PhysicalMemoryAllocator.h" + + +//#define TRACE_PHYSICAL_MEMORY_ALLOCATOR +#ifdef TRACE_PHYSICAL_MEMORY_ALLOCATOR +#define TRACE(x) dprintf x +#define TRACE_ERROR(x) dprintf x +#else +#define TRACE(x) /* nothing */ +#define TRACE_ERROR(x) dprintf x +#endif + + +PhysicalMemoryAllocator::PhysicalMemoryAllocator(const char *name, + size_t minSize, size_t maxSize, uint32 minCountPerBlock) + : fOverhead(0) +{ + fName = strdup(name); + if (benaphore_init(&fLock, fName) < B_OK) { + TRACE_ERROR(("PMA: failed to create benaphore lock\n")); + return; + } + + fArrayCount = 1; + size_t biggestSize = minSize; + while (biggestSize < maxSize) { + fArrayCount++; + biggestSize *= 2; + } + + size_t size = fArrayCount * sizeof(uint8 *); + fArray = (uint8 **)malloc(size); + fOverhead += size; + + size = fArrayCount * sizeof(size_t); + fBlockSize = (size_t *)malloc(size); + fArrayLength = (size_t *)malloc(size); + fArrayOffset = (size_t *)malloc(size); + fOverhead += size * 3; + + size_t arraySlots = biggestSize / minSize; + for (int32 i = 0; i < fArrayCount; i++) { + size = arraySlots * minCountPerBlock * sizeof(uint8); + fArrayLength[i] = arraySlots * minCountPerBlock; + fBlockSize[i] = biggestSize / arraySlots; + fArrayOffset[i] = fArrayLength[i] - 1; + + fArray[i] = (uint8 *)malloc(size); + memset(fArray[i], 0, fArrayLength[i]); + + fOverhead += size; + arraySlots /= 2; + } + + fManagedMemory = fBlockSize[0] * fArrayLength[0]; + + size_t roundedSize = biggestSize * minCountPerBlock; + roundedSize = (roundedSize + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); + + fArea = create_area(fName, &fLogicalBase, B_ANY_KERNEL_ADDRESS, + roundedSize, B_FULL_LOCK | B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); + if (fArea < B_OK) { + TRACE_ERROR(("PMA: failed to create memory area\n")); + return; + } + + physical_entry physicalEntry; + if (get_memory_map(fLogicalBase, roundedSize, &physicalEntry, 1) < B_OK) { + TRACE_ERROR(("PMA: failed to get memory map\n")); + return; + } + + fPhysicalBase = physicalEntry.address; +} + + +PhysicalMemoryAllocator::~PhysicalMemoryAllocator() +{ + _Lock(); + + for (int32 i = 0; i < fArrayCount; i++) + free(fArray[i]); + + free(fArray); + free(fArrayLength); + free(fBlockSize); + free(fArrayOffset); + free(fName); + + delete_area(fArea); + benaphore_destroy(&fLock); +} + + +bool +PhysicalMemoryAllocator::_Lock() +{ + return (benaphore_lock(&fLock) == B_OK); +} + + +void +PhysicalMemoryAllocator::_Unlock() +{ + benaphore_unlock(&fLock); +} + + +status_t +PhysicalMemoryAllocator::Allocate(size_t size, void **logicalAddress, + void **physicalAddress) +{ + if (size == 0 || size > fBlockSize[fArrayCount - 1]) { + TRACE_ERROR(("PMA: bad value for allocate (%ld bytes)\n", size)); + return B_BAD_VALUE; + } + + size_t arrayLength = 0; + int32 arrayToUse = 0; + for (int32 i = 0; i < fArrayCount; i++) { + if (fBlockSize[i] >= size) { + arrayToUse = i; + arrayLength = fArrayLength[i]; + break; + } + } + + if (!_Lock()) + return B_ERROR; + + TRACE(("PMA: will use array %ld (blocksize: %ld) to allocate %ld bytes\n", arrayToUse, fBlockSize[arrayToUse], size)); + uint8 *targetArray = fArray[arrayToUse]; + uint32 arrayOffset = fArrayOffset[arrayToUse] % arrayLength; + for (size_t i = arrayOffset + 1; i != arrayOffset; i++) { + if (i >= arrayLength) + i -= arrayLength; + + if (targetArray[i] == 0) { + // found a free slot + fArrayOffset[arrayToUse] = i; + + // fill upwards to the smallest block + uint32 fillSize = 1; + uint32 arrayIndex = i; + for (int32 j = arrayToUse; j >= 0; j--) { + memset(&fArray[j][arrayIndex], 1, fillSize); + fillSize <<= 1; + arrayIndex <<= 1; + } + + // fill downwards to the biggest block + arrayIndex = i >> 1; + for (int32 j = arrayToUse + 1; j < fArrayCount; j++) { + fArray[j][arrayIndex]++; + if (fArray[j][arrayIndex] > 1) + break; + + arrayIndex >>= 1; + } + + _Unlock(); + size_t offset = fBlockSize[arrayToUse] * i; + *logicalAddress = (void *)((uint8 *)fLogicalBase + offset); + *physicalAddress = (void *)((uint8 *)fPhysicalBase + offset); + return B_OK; + } + } + + // no slot found + _Unlock(); + TRACE_ERROR(("PMA: found no free slot to store %ld bytes\n", size)); + return B_NO_MEMORY; +} + + +status_t +PhysicalMemoryAllocator::Deallocate(size_t size, void *logicalAddress, + void *physicalAddress) +{ + if (size == 0 || size > fBlockSize[fArrayCount - 1]) { + TRACE_ERROR(("PMA: bad value for deallocate (%ld bytes)\n", size)); + return B_BAD_VALUE; + } + + int32 arrayToUse = 0; + for (int32 i = 0; i < fArrayCount; i++) { + if (fBlockSize[i] >= size) { + arrayToUse = i; + break; + } + } + + uint32 offset; + if (logicalAddress) + offset = (uint32)logicalAddress - (uint32)fLogicalBase; + else if (physicalAddress) + offset = (uint32)physicalAddress - (uint32)fPhysicalBase; + else { + TRACE_ERROR(("PMA: no value given for either physical or logical address\n")); + return B_BAD_VALUE; + } + + uint32 index = offset / fBlockSize[arrayToUse]; + if (index >= fArrayLength[arrayToUse]) { + TRACE_ERROR(("PMA: provided address resulted in invalid index\n")); + return B_BAD_VALUE; + } + + TRACE(("PMA: will use array %ld (index: %ld) to deallocate %ld bytes\n", arrayToUse, index, size)); + if (fArray[arrayToUse][index] == 0) { + TRACE_ERROR(("PMA: address was not allocated!\n")); + return B_BAD_VALUE; + } + + if (!_Lock()) + return B_ERROR; + + // clear upwards to the smallest block + uint32 fillSize = 1; + uint32 arrayIndex = index; + for (int32 i = arrayToUse; i >= 0; i--) { + memset(&fArray[i][arrayIndex], 0, fillSize); + fillSize <<= 1; + arrayIndex <<= 1; + } + + // clear downwards to the biggest block + arrayIndex = index >> 1; + for (int32 i = arrayToUse + 1; i < fArrayCount; i++) { + fArray[i][arrayIndex]--; + if (fArray[i][arrayIndex] > 0) + break; + + arrayIndex >>= 1; + } + + _Unlock(); + return B_OK; +} + + +void +PhysicalMemoryAllocator::PrintToStream() +{ + dprintf("PhysicalMemoryAllocator \"%s\":\n", fName); + dprintf("\tMin block size:\t\t\t%ld bytes\n", fBlockSize[0]); + dprintf("\tMax block size:\t\t\t%ld bytes\n", fBlockSize[fArrayCount - 1]); + dprintf("\tMin count per block:\t%ld\n\n", fArrayLength[fArrayCount - 1]); + dprintf("\tArray count:\t\t\t%ld\n", fArrayCount); + + dprintf("\tArray slots:\t\t\t% 8ld", fArrayLength[0]); + for (int32 i = 1; i < fArrayCount; i++) + dprintf(", % 8ld", fArrayLength[i]); + dprintf("\n"); + DumpFreeSlots(); + + dprintf("\tBlock sizes:\t\t\t% 8ld", fBlockSize[0]); + for (int32 i = 1; i < fArrayCount; i++) + dprintf(", % 8ld", fBlockSize[i]); + dprintf("\n"); + DumpLastArray(); + dprintf("\n"); + + dprintf("\tManaged memory:\t\t\t%ld bytes\n", fManagedMemory); + dprintf("\tGranularity:\t\t\t%ld bytes\n", fBlockSize[0]); + dprintf("\tMemory overhead:\t\t%ld bytes\n", fOverhead); +} + + +void +PhysicalMemoryAllocator::DumpArrays() +{ + uint32 padding = 2; + for (int32 i = 0; i < fArrayCount; i++) { + dprintf("\tArray(%ld):\t", i); + for (size_t j = 0; j < fArrayLength[i]; j++) { + if (padding > 2) { + for (uint32 k = 0; k < (padding - 2) / 4; k++) + dprintf(" "); + dprintf("\\"); + for (uint32 k = 0; k < (padding - 2) / 4; k++) + dprintf("-"); + dprintf("%d", fArray[i][j]); + for (uint32 k = 0; k < (padding - 2) / 4; k++) + dprintf("-"); + dprintf("/"); + for (uint32 k = 0; k < (padding - 2) / 4 + 1; k++) + dprintf(" "); + } else { + dprintf("%d ", fArray[i][j]); + } + } + + padding *= 2; + dprintf("\n"); + } + + dprintf("\n"); +} + + +void +PhysicalMemoryAllocator::DumpLastArray() +{ + dprintf("\tLast array:\t\t\t\t"); + for (size_t i = 0; i < fArrayLength[fArrayCount - 1]; i++) + dprintf("%d", fArray[fArrayCount - 1][i]); + dprintf("\n"); +} + + +void +PhysicalMemoryAllocator::DumpFreeSlots() +{ + dprintf("\tFree slots:\t\t\t\t"); + for (int32 i = 0; i < fArrayCount; i++) { + uint32 freeSlots = 0; + for (size_t j = 0; j < fArrayLength[i]; j++) { + if (fArray[i][j] == 0) + freeSlots++; + } + + if (i > 0) + dprintf(", % 8ld", freeSlots); + else + dprintf("% 8ld", freeSlots); + } + dprintf("\n"); +} diff --git a/src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.h b/src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.h new file mode 100644 index 0000000000..4ed06bf020 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.h @@ -0,0 +1,59 @@ +/* + * Copyright 2006, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + +#ifndef _PHYSICAL_MEMORY_ALLOCATOR_H_ +#define _PHYSICAL_MEMORY_ALLOCATOR_H_ + +#include +#include + + +class PhysicalMemoryAllocator { +public: + PhysicalMemoryAllocator(const char *name, + size_t minSize, + size_t maxSize, + uint32 minCountPerBlock); + ~PhysicalMemoryAllocator(); + + status_t Allocate(size_t size, + void **logicalAddress, + void **physicalAddress); + + // one of both addresses needs to be provided, the other may be NULL + status_t Deallocate(size_t size, + void *logicalAddress, + void *physicalAddress); + + void PrintToStream(); + void DumpArrays(); + void DumpLastArray(); + void DumpFreeSlots(); + +private: + bool _Lock(); + void _Unlock(); + + char *fName; + + size_t fOverhead; + size_t fManagedMemory; + + benaphore fLock; + area_id fArea; + void *fLogicalBase; + void *fPhysicalBase; + + int32 fArrayCount; + size_t *fBlockSize; + size_t *fArrayLength; + size_t *fArrayOffset; + uint8 **fArray; +}; + +#endif // !_PHYSICAL_MEMORY_ALLOCATOR_H_ diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index d63ddf6401..28bcc36f35 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -11,7 +11,7 @@ Pipe::Pipe(Object *parent, int8 deviceAddress, uint8 endpointAddress, - pipeDirection direction, pipeSpeed speed, size_t maxPacketSize) + pipeDirection direction, usb_speed speed, size_t maxPacketSize) : Object(parent), fDeviceAddress(deviceAddress), fEndpointAddress(endpointAddress), @@ -94,7 +94,7 @@ Pipe::GetStatus(uint16 *status) InterruptPipe::InterruptPipe(Object *parent, int8 deviceAddress, - uint8 endpointAddress, pipeDirection direction, pipeSpeed speed, + uint8 endpointAddress, pipeDirection direction, usb_speed speed, size_t maxPacketSize) : Pipe(parent, deviceAddress, endpointAddress, direction, speed, maxPacketSize) @@ -126,7 +126,7 @@ InterruptPipe::QueueInterrupt(void *data, size_t dataLength, BulkPipe::BulkPipe(Object *parent, int8 deviceAddress, uint8 endpointAddress, - pipeDirection direction, pipeSpeed speed, size_t maxPacketSize) + pipeDirection direction, usb_speed speed, size_t maxPacketSize) : Pipe(parent, deviceAddress, endpointAddress, direction, speed, maxPacketSize) { @@ -175,7 +175,7 @@ BulkPipe::QueueBulkV(iovec *vector, size_t vectorCount, IsochronousPipe::IsochronousPipe(Object *parent, int8 deviceAddress, - uint8 endpointAddress, pipeDirection direction, pipeSpeed speed, + uint8 endpointAddress, pipeDirection direction, usb_speed speed, size_t maxPacketSize) : Pipe(parent, deviceAddress, endpointAddress, direction, speed, maxPacketSize) @@ -206,7 +206,7 @@ typedef struct transfer_result_data_s { ControlPipe::ControlPipe(Object *parent, int8 deviceAddress, - uint8 endpointAddress, pipeSpeed speed, size_t maxPacketSize) + uint8 endpointAddress, usb_speed speed, size_t maxPacketSize) : Pipe(parent, deviceAddress, endpointAddress, Default, speed, maxPacketSize) { diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index 6a19a5f1e8..7e910ba834 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -10,6 +10,7 @@ #include #include #include "usb_p.h" +#include "PhysicalMemoryAllocator.h" Stack::Stack() @@ -29,96 +30,13 @@ Stack::Stack() fObjectArray = (Object **)malloc(objectArraySize); memset(fObjectArray, 0, objectArraySize); - // Initialise the memory chunks: create 8, 16 and 32 byte-heaps - // NOTE: This is probably the most ugly code you will see in the - // whole stack. Unfortunately this is needed because of the fact - // that the compiler doesn't like us to apply pointer arithmethic - // to (void *) pointers. - - // 8-byte heap - fAreaFreeCount[0] = 0; - fAreas[0] = AllocateArea(&fLogical[0], &fPhysical[0], B_PAGE_SIZE, - "8-byte chunk area"); - - if (fAreas[0] < B_OK) { - TRACE_ERROR(("usb stack: 8-byte chunk area failed to initialise\n")); + fAllocator = new(std::nothrow) PhysicalMemoryAllocator("USB Stack Allocator", + 8, B_PAGE_SIZE * 4, 50); + if (!fAllocator) { + TRACE_ERROR(("usb stack: failed to allocate the allocator\n")); return; } - fListhead8 = (addr_t)fLogical[0]; - for (int32 i = 0; i < B_PAGE_SIZE / 8; i++) { - memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[0] + 8 * i); - chunk->physical = (addr_t)fPhysical[0] + 8 * i; - - if (i < B_PAGE_SIZE / 8 - 1) - chunk->next_item = (addr_t)fLogical[0] + 8 * (i + 1); - else - chunk->next_item = 0; - } - - // 16-byte heap - fAreaFreeCount[1] = 0; - fAreas[1] = AllocateArea(&fLogical[1], &fPhysical[1], B_PAGE_SIZE, - "16-byte chunk area"); - - if (fAreas[1] < B_OK) { - TRACE_ERROR(("usb stack: 16-byte chunk area failed to initialise\n")); - return; - } - - fListhead16 = (addr_t)fLogical[1]; - for (int32 i = 0; i < B_PAGE_SIZE / 16; i++) { - memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[1] + 16 * i); - chunk->physical = (addr_t)fPhysical[1] + 16 * i; - - if (i < B_PAGE_SIZE / 16 - 1) - chunk->next_item = (addr_t)fLogical[1] + 16 * (i + 1); - else - chunk->next_item = 0; - } - - // 32-byte heap - fAreaFreeCount[2] = 0; - fAreas[2] = AllocateArea(&fLogical[2], &fPhysical[2], B_PAGE_SIZE, - "32-byte chunk area"); - - if (fAreas[2] < B_OK) { - TRACE_ERROR(("usb stack: 32-byte chunk area failed to initialise\n")); - return; - } - - fListhead32 = (addr_t)fLogical[2]; - for (int32 i = 0; i < B_PAGE_SIZE / 32; i++) { - memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[2] + 32 * i); - chunk->physical = (addr_t)fPhysical[2] + 32 * i; - - if (i < B_PAGE_SIZE / 32 - 1) - chunk->next_item = (addr_t)fLogical[2] + 32 * (i + 1); - else - chunk->next_item = 0; - } - - // 64-byte heap - fAreaFreeCount[3] = 0; - fAreas[3] = AllocateArea(&fLogical[3], &fPhysical[3], B_PAGE_SIZE, - "64-byte chunk area"); - - if (fAreas[3] < B_OK) { - TRACE_ERROR(("usb stack: 64-byte chunk area failed to initialise\n")); - return; - } - - fListhead64 = (addr_t)fLogical[3]; - for (int32 i = 0; i < B_PAGE_SIZE / 64; i++) { - memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[3] + 64 * i); - chunk->physical = (addr_t)fPhysical[3] + 64 * i; - - if (i < B_PAGE_SIZE / 64 - 1) - chunk->next_item = (addr_t)fLogical[3] + 64 * (i + 1); - else - chunk->next_item = 0; - } - // Check for host controller modules void *moduleList = open_module_list("busses/usb"); char moduleName[B_PATH_NAME_LENGTH]; @@ -155,9 +73,7 @@ Stack::~Stack() delete (*i); } - delete_area(fAreas[0]); - delete_area(fAreas[1]); - delete_area(fAreas[2]); + delete fAllocator; } @@ -255,93 +171,16 @@ Stack::IndexOfBusManager(BusManager *busManager) status_t -Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, uint8 size) +Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, size_t size) { - Lock(); - - addr_t listhead; - if (size <= 8) - listhead = fListhead8; - else if (size <= 16) - listhead = fListhead16; - else if (size <= 32) - listhead = fListhead32; - else if (size <= 64) - listhead = fListhead64; - else { - TRACE_ERROR(("usb stack: Chunk size %d to big\n", size)); - Unlock(); - return B_ERROR; - } - - if (listhead == 0) { - TRACE_ERROR(("usb stack: Out of memory on this list\n")); - Unlock(); - return B_ERROR; - } - - TRACE(("usb stack: Stack::Allocate() listhead: 0x%08x\n", listhead)); - memory_chunk *chunk = (memory_chunk *)listhead; - *logicalAddress = (void *)listhead; - *physicalAddress = (void *)chunk->physical; - if (chunk->next_item == 0) { - //TODO: allocate more memory - listhead = 0; - } else { - listhead = chunk->next_item; - } - - // Update our listhead pointers - if (size <= 8) - fListhead8 = listhead; - else if (size <= 16) - fListhead16 = listhead; - else if (size <= 32) - fListhead32 = listhead; - else if (size <= 64) - fListhead64 = listhead; - - Unlock(); - TRACE(("usb stack: allocated a new chunk with size %u\n", size)); - return B_OK; + return fAllocator->Allocate(size, logicalAddress, physicalAddress); } status_t -Stack::FreeChunk(void *logicalAddress, void *physicalAddress, uint8 size) +Stack::FreeChunk(void *logicalAddress, void *physicalAddress, size_t size) { - Lock(); - - addr_t listhead; - if (size <= 8) - listhead = fListhead8; - else if (size <= 16) - listhead = fListhead16; - else if (size <= 32) - listhead = fListhead32; - else if (size <= 64) - listhead = fListhead64; - else { - TRACE_ERROR(("usb stack: Chunk size %d invalid\n", size)); - Unlock(); - return B_ERROR; - } - - memory_chunk *chunk = (memory_chunk *)logicalAddress; - chunk->next_item = listhead; - chunk->physical = (addr_t)physicalAddress; - - if (size <= 8) - fListhead8 = (addr_t)logicalAddress; - else if (size <= 16) - fListhead16 = (addr_t)logicalAddress; - else if (size <= 32) - fListhead32 = (addr_t)logicalAddress; - else if (size <= 64) - fListhead64 = (addr_t)logicalAddress; - - Unlock(); - return B_OK; + return fAllocator->Deallocate(size, logicalAddress, physicalAddress); } diff --git a/src/add-ons/kernel/bus_managers/usb/usb_p.h b/src/add-ons/kernel/bus_managers/usb/usb_p.h index e7e7911a4b..0625239b27 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -32,6 +32,7 @@ class Transfer; class BusManager; class ControlPipe; class Object; +class PhysicalMemoryAllocator; struct host_controller_info { @@ -51,6 +52,14 @@ struct usb_driver_info { }; +typedef enum { + USB_SPEED_LOWSPEED = 0, + USB_SPEED_FULLSPEED, + USB_SPEED_HIGHSPEED, + USB_SPEED_MAX = USB_SPEED_HIGHSPEED +} usb_speed; + + #define USB_OBJECT_NONE 0x00000000 #define USB_OBJECT_PIPE 0x00000001 #define USB_OBJECT_CONTROL_PIPE 0x00000002 @@ -80,9 +89,9 @@ public: int32 IndexOfBusManager(BusManager *bus); status_t AllocateChunk(void **logicalAddress, - void **physicalAddress, uint8 size); + void **physicalAddress, size_t size); status_t FreeChunk(void *logicalAddress, - void *physicalAddress, uint8 size); + void *physicalAddress, size_t size); area_id AllocateArea(void **logicalAddress, void **physicalAddress, @@ -105,15 +114,7 @@ private: Vector fBusManagers; benaphore fLock; - area_id fAreas[USB_MAX_AREAS]; - void *fLogical[USB_MAX_AREAS]; - void *fPhysical[USB_MAX_AREAS]; - uint16 fAreaFreeCount[USB_MAX_AREAS]; - - addr_t fListhead8; - addr_t fListhead16; - addr_t fListhead32; - addr_t fListhead64; + PhysicalMemoryAllocator *fAllocator; uint32 fObjectIndex; uint32 fObjectMaxCount; @@ -140,7 +141,7 @@ virtual status_t InitCheck(); int8 AllocateAddress(); Device *AllocateNewDevice(Hub *parent, - bool lowSpeed); + usb_speed speed); virtual status_t Start(); virtual status_t Stop(); @@ -160,8 +161,7 @@ static int32 ExploreThread(void *data); benaphore fLock; bool fDeviceMap[128]; - ControlPipe *fDefaultPipe; - ControlPipe *fDefaultPipeLowSpeed; + ControlPipe *fDefaultPipes[USB_SPEED_MAX + 1]; Hub *fRootHub; thread_id fExploreThread; Object *fRootObject; @@ -202,20 +202,19 @@ private: class Pipe : public Object { public: enum pipeDirection { In, Out, Default }; -enum pipeSpeed { LowSpeed, FullSpeed, HighSpeed }; Pipe(Object *parent, int8 deviceAddress, uint8 endpointAddress, pipeDirection direction, - pipeSpeed speed, + usb_speed speed, size_t maxPacketSize); virtual ~Pipe(); virtual uint32 Type() { return USB_OBJECT_PIPE; }; int8 DeviceAddress() { return fDeviceAddress; }; - pipeSpeed Speed() { return fSpeed; }; + usb_speed Speed() { return fSpeed; }; pipeDirection Direction() { return fDirection; }; int8 EndpointAddress() { return fEndpointAddress; }; size_t MaxPacketSize() { return fMaxPacketSize; }; @@ -235,7 +234,7 @@ private: int8 fDeviceAddress; uint8 fEndpointAddress; pipeDirection fDirection; - pipeSpeed fSpeed; + usb_speed fSpeed; size_t fMaxPacketSize; bool fDataToggle; }; @@ -246,7 +245,7 @@ public: ControlPipe(Object *parent, int8 deviceAddress, uint8 endpointAddress, - pipeSpeed speed, + usb_speed speed, size_t maxPacketSize); virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_CONTROL_PIPE; }; @@ -283,7 +282,7 @@ public: int8 deviceAddress, uint8 endpointAddress, pipeDirection direction, - pipeSpeed speed, + usb_speed speed, size_t maxPacketSize); virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_INTERRUPT_PIPE; }; @@ -301,7 +300,7 @@ public: int8 deviceAddress, uint8 endpointAddress, pipeDirection direction, - pipeSpeed speed, + usb_speed speed, size_t maxPacketSize); virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_BULK_PIPE; }; @@ -323,7 +322,7 @@ public: int8 deviceAddress, uint8 endpointAddress, pipeDirection direction, - pipeSpeed speed, + usb_speed speed, size_t maxPacketSize); virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_ISO_PIPE; }; @@ -356,7 +355,8 @@ class Device : public Object { public: Device(Object *parent, usb_device_descriptor &desc, - int8 deviceAddress, bool lowSpeed); + int8 deviceAddress, + usb_speed speed); status_t InitCheck(); @@ -397,7 +397,7 @@ protected: private: usb_configuration_info *fConfigurations; usb_configuration_info *fCurrentConfiguration; - bool fLowSpeed; + usb_speed fSpeed; int8 fDeviceAddress; size_t fMaxPacketIn[16]; size_t fMaxPacketOut[16]; @@ -411,7 +411,8 @@ class Hub : public Device { public: Hub(Object *parent, usb_device_descriptor &desc, - int8 deviceAddress, bool lowSpeed); + int8 deviceAddress, + usb_speed speed); virtual uint32 Type() { return USB_OBJECT_DEVICE | USB_OBJECT_HUB; }; diff --git a/src/add-ons/kernel/busses/usb/ehci.cpp b/src/add-ons/kernel/busses/usb/ehci.cpp index 720019bb21..afbdb69de3 100644 --- a/src/add-ons/kernel/busses/usb/ehci.cpp +++ b/src/add-ons/kernel/busses/usb/ehci.cpp @@ -54,6 +54,48 @@ module_info *modules[] = { // +#ifdef TRACE_USB + +void +print_descriptor_chain(ehci_qtd *descriptor) +{ + while (descriptor) { + dprintf(" %08x n%08x a%08x t%08x %08x %08x %08x %08x %08x s%d\n", + descriptor->this_phy, descriptor->next_phy, + descriptor->alt_next_phy, descriptor->token, + descriptor->buffer_phy[0], descriptor->buffer_phy[1], + descriptor->buffer_phy[2], descriptor->buffer_phy[3], + descriptor->buffer_phy[4], descriptor->buffer_size); + + if (descriptor->next_phy & EHCI_QTD_TERMINATE) + break; + + descriptor = (ehci_qtd *)descriptor->next_log; + } +} + +void +print_queue(ehci_qh *queueHead) +{ + dprintf("queue: t%08x n%08x ch%08x ca%08x cu%08x\n", + queueHead->this_phy, queueHead->next_phy, queueHead->endpoint_chars, + queueHead->endpoint_caps, queueHead->current_qtd_phy); + dprintf("overlay: n%08x a%08x t%08x %08x %08x %08x %08x %08x\n", + queueHead->overlay.next_phy, queueHead->overlay.alt_next_phy, + queueHead->overlay.token, queueHead->overlay.buffer_phy[0], + queueHead->overlay.buffer_phy[1], queueHead->overlay.buffer_phy[2], + queueHead->overlay.buffer_phy[3], queueHead->overlay.buffer_phy[4]); + print_descriptor_chain((ehci_qtd *)queueHead->element_log); +} + +#endif // TRACE_USB + + +// +// #pragma mark - +// + + EHCI::EHCI(pci_info *info, Stack *stack) : BusManager(stack), fPCIInfo(info), @@ -79,10 +121,6 @@ EHCI::EHCI(pci_info *info, Stack *stack) TRACE(("usb_ehci: constructing new EHCI Host Controller Driver\n")); fInitOK = false; - // make sure we take the controller away from BIOS - sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, 2, - PCI_LEGSUP, 2, PCI_LEGSUP_USBPIRQDEN); - // enable busmaster and memory mapped access uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function, PCI_command, 2); @@ -116,9 +154,52 @@ EHCI::EHCI(pci_info *info, Stack *stack) // read port count from capability register fPortCount = ReadCapReg32(EHCI_HCSPARAMS) & 0x0f; + uint32 extendedCapPointer = ReadCapReg32(EHCI_HCCPARAMS) >> EHCI_ECP_SHIFT; + extendedCapPointer &= EHCI_ECP_MASK; + if (extendedCapPointer > 0) { + TRACE(("usb_ehci: extended capabilities register at %d\n", extendedCapPointer)); + + uint32 legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus, + fPCIInfo->device, fPCIInfo->function, extendedCapPointer, 4); + if ((legacySupport & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID) { + if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { + TRACE(("usb_ehci: the host controller is bios owned\n")); + } + + TRACE(("usb_ehci: claiming ownership of the host controller\n")); + sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, + fPCIInfo->function, extendedCapPointer, 4, EHCI_LEGSUP_OSOWNED); + + for (int32 i = 0; i < 10; i++) { + legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus, + fPCIInfo->device, fPCIInfo->function, extendedCapPointer, 4); + + if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { + TRACE(("usb_ehci: controller is still bios owned, waiting\n")); + snooze(50000); + } else + break; + } + + if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { + TRACE_ERROR(("usb_ehci: bios won't give up control over the host controller\n")); + return; + } else if (legacySupport & EHCI_LEGSUP_OSOWNED) { + TRACE(("usb_ehci: successfully took ownership of the host controller\n")); + } + } else { + TRACE(("usb_ehci: extended capability is not a legacy support register\n")); + } + } else { + TRACE(("usb_ehci: no extended capabilities register\n")); + } + // disable interrupts WriteOpReg(EHCI_USBINTR, 0); + // reset the segment register + WriteOpReg(EHCI_CTRDSSEGMENT, 0); + // reset the host controller if (ControllerReset() < B_OK) { TRACE_ERROR(("usb_ehci: host controller failed to reset\n")); @@ -150,11 +231,26 @@ EHCI::EHCI(pci_info *info, Stack *stack) WriteOpReg(EHCI_PERIODICLISTBASE, (uint32)physicalAddress); - // route all ports to us - WriteOpReg(EHCI_CONFIGFLAG, EHCI_CONFIGFLAG_FLAG); + // allocate a queue head that will always stay in the async frame list + fAsyncQueueHead = CreateQueueHead(); + if (!fAsyncQueueHead) { + TRACE_ERROR(("usb_ehci: unable to allocate stray async queue head\n")); + return; + } + + fAsyncQueueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH; + fAsyncQueueHead->next_log = fAsyncQueueHead; + fAsyncQueueHead->prev_log = fAsyncQueueHead; + fAsyncQueueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH | EHCI_QH_CHARS_RECHEAD; + fAsyncQueueHead->endpoint_caps = 1 << EHCI_QH_CAPS_MULT_SHIFT; + fAsyncQueueHead->current_qtd_phy = EHCI_QTD_TERMINATE; + fAsyncQueueHead->overlay.next_phy = EHCI_QTD_TERMINATE; + + WriteOpReg(EHCI_ASYNCLISTADDR, (uint32)fAsyncQueueHead->this_phy + | EHCI_QH_TYPE_QH); - TRACE(("usb_ehci: EHCI Host Controller Driver constructed\n")); fInitOK = true; + TRACE(("usb_ehci: EHCI Host Controller Driver constructed\n")); } @@ -167,6 +263,8 @@ EHCI::~EHCI() wait_for_thread(fFinishThread, &result); CancelAllPendingTransfers(); + WriteOpReg(EHCI_USBCMD, 0); + WriteOpReg(EHCI_CONFIGFLAG, 0); delete fRootHub; delete_area(fPeriodicFrameListArea); @@ -181,7 +279,15 @@ EHCI::Start() TRACE(("usb_ehci: starting EHCI Host Controller\n")); TRACE(("usb_ehci: usbcmd: 0x%08x; usbsts: 0x%08x\n", ReadOpReg(EHCI_USBCMD), ReadOpReg(EHCI_USBSTS))); - WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_RUNSTOP); + uint32 frameListSize = (ReadOpReg(EHCI_USBCMD) >> EHCI_USBCMD_FLS_SHIFT) + & EHCI_USBCMD_FLS_MASK; + WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_RUNSTOP + | EHCI_USBCMD_ASENABLE /*| EHCI_USBCMD_PSENABLE*/ + | (frameListSize << EHCI_USBCMD_FLS_SHIFT) + | (2 << EHCI_USBCMD_ITC_SHIFT)); + + // route all ports to us + WriteOpReg(EHCI_CONFIGFLAG, EHCI_CONFIGFLAG_FLAG); bool running = false; for (int32 i = 0; i < 10; i++) { @@ -226,10 +332,108 @@ EHCI::SubmitTransfer(Transfer *transfer) if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress) return fRootHub->ProcessTransfer(this, transfer); + uint32 type = transfer->TransferPipe()->Type(); + if ((type & USB_OBJECT_CONTROL_PIPE) > 0 + || (type & USB_OBJECT_BULK_PIPE) > 0) { + TRACE(("usb_ehci: submitting async transfer\n")); + return SubmitAsyncTransfer(transfer); + } + + if ((type & USB_OBJECT_INTERRUPT_PIPE) > 0 + || (type & USB_OBJECT_ISO_PIPE) > 0) { + TRACE(("usb_ehci: submitting periodic transfer\n")); + return SubmitPeriodicTransfer(transfer); + } + + TRACE_ERROR(("usb_ehci: tried to submit transfer for unknown pipe type %lu\n", type)); return B_ERROR; } +status_t +EHCI::SubmitAsyncTransfer(Transfer *transfer) +{ + ehci_qh *queueHead = CreateQueueHead(); + if (!queueHead) { + TRACE_ERROR(("usb_ehci: failed to allocate async queue head\n")); + return B_NO_MEMORY; + } + + Pipe *pipe = transfer->TransferPipe(); + switch (pipe->Speed()) { + case USB_SPEED_LOWSPEED: + queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_LOW; + break; + case USB_SPEED_FULLSPEED: + queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_FULL; + break; + case USB_SPEED_HIGHSPEED: + queueHead->endpoint_chars = EHCI_QH_CHARS_EPS_HIGH; + break; + default: + TRACE_ERROR(("usb_ehci: unknown pipe speed\n")); + FreeQueueHead(queueHead); + return B_ERROR; + } + + if (pipe->Type() & USB_OBJECT_CONTROL_PIPE) { + queueHead->endpoint_chars |= EHCI_QH_CHARS_TOGGLE + | (pipe->Speed() != USB_SPEED_HIGHSPEED ? EHCI_QH_CHARS_CONTROL : 0); + } + + queueHead->endpoint_chars |= (3 << EHCI_QH_CHARS_RL_SHIFT) + | (pipe->MaxPacketSize() << EHCI_QH_CHARS_MPL_SHIFT) + | (pipe->EndpointAddress() << EHCI_QH_CHARS_EPT_SHIFT) + | (pipe->DeviceAddress() << EHCI_QH_CHARS_DEV_SHIFT); + queueHead->endpoint_caps = (1 << EHCI_QH_CAPS_MULT_SHIFT) + | (0x1c << EHCI_QH_CAPS_SCM_SHIFT); + + status_t result; + bool directionIn; + ehci_qtd *dataDescriptor; + if (pipe->Type() & USB_OBJECT_CONTROL_PIPE) + result = FillQueueWithRequest(transfer, queueHead, &dataDescriptor, + &directionIn); + else + result = FillQueueWithData(transfer, queueHead, &dataDescriptor, + &directionIn); + + if (result < B_OK) { + TRACE_ERROR(("usb_ehci: failed to fill transfer queue with data\n")); + FreeQueueHead(queueHead); + return result; + } + + result = AddPendingTransfer(transfer, queueHead, dataDescriptor, directionIn); + if (result < B_OK) { + TRACE_ERROR(("usb_ehci: failed to add pending transfer\n")); + FreeQueueHead(queueHead); + return result; + } + +#ifdef TRACE_USB + TRACE(("usb_ehci: linking queue\n")); + print_queue(queueHead); +#endif + + result = LinkQueueHead(queueHead); + if (result < B_OK) { + TRACE_ERROR(("usb_ehci: failed to link queue head to the async list\n")); + FreeQueueHead(queueHead); + return result; + } + + return B_OK; +} + + +status_t +EHCI::SubmitPeriodicTransfer(Transfer *transfer) +{ + return B_ERROR; +} + + status_t EHCI::AddTo(Stack *stack) { @@ -472,6 +676,11 @@ EHCI::SuspendPort(uint8 index) status_t EHCI::ControllerReset() { + // halt the controller first + WriteOpReg(EHCI_USBCMD, 0); + snooze(10000); + + // then reset it WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET); int32 tries = 5; @@ -510,14 +719,58 @@ EHCI::InterruptHandler(void *data) int32 EHCI::Interrupt() { - return B_UNHANDLED_INTERRUPT; + // check if any interrupt was generated + uint32 status = ReadOpReg(EHCI_USBSTS); + if ((status & EHCI_USBSTS_INTMASK) == 0) + return B_UNHANDLED_INTERRUPT; + + uint32 acknowledge = 0; + if (status & EHCI_USBSTS_USBINT) { + TRACE(("usb_ehci: transfer finished\n")); + acknowledge |= EHCI_USBSTS_USBINT; + fFinishTransfers = true; + } + + if (status & EHCI_USBSTS_USBERRINT) { + TRACE(("usb_ehci: transfer error\n")); + acknowledge |= EHCI_USBSTS_USBERRINT; + fFinishTransfers = true; + } + + if (status & EHCI_USBSTS_PORTCHANGE) { + TRACE(("usb_ehci: port change detected\n")); + acknowledge |= EHCI_USBSTS_PORTCHANGE; + } + + if (status & EHCI_USBSTS_FLROLLOVER) { + TRACE(("usb_ehci: frame list rolled over\n")); + acknowledge |= EHCI_USBSTS_FLROLLOVER; + } + + if (status & EHCI_USBSTS_INTONAA) { + TRACE(("usb_ehci: interrupt on async advance\n")); + acknowledge |= EHCI_USBSTS_INTONAA; + } + + if (status & EHCI_USBSTS_HOSTSYSERR) { + TRACE_ERROR(("usb_ehci: host system error!\n")); + acknowledge |= EHCI_USBSTS_HOSTSYSERR; + print_queue(fAsyncQueueHead); + if (fAsyncQueueHead->next_log) { + print_queue((ehci_qh *)fAsyncQueueHead->next_log); + } + } + + if (acknowledge) + WriteOpReg(EHCI_USBSTS, acknowledge); + + return B_HANDLED_INTERRUPT; } status_t EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead, - ehci_qtd *firstDescriptor, ehci_qtd *dataDescriptor, - ehci_qtd *lastDescriptor, bool directionIn) + ehci_qtd *dataDescriptor, bool directionIn) { transfer_data *data = new(std::nothrow) transfer_data(); if (!data) @@ -525,9 +778,7 @@ EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead, data->transfer = transfer; data->queue_head = queueHead; - data->first_descriptor = firstDescriptor; data->data_descriptor = dataDescriptor; - data->last_descriptor = lastDescriptor; data->incoming = directionIn; data->link = NULL; @@ -599,6 +850,8 @@ EHCI::CancelAllPendingTransfers() transfer = next; } + fFirstTransfer = NULL; + fLastTransfer = NULL; Unlock(); return B_OK; } @@ -661,38 +914,298 @@ EHCI::FinishTransfers() } -ehci_qtd * -EHCI::CreateDescriptor(Pipe *pipe, size_t bufferSize) +ehci_qh * +EHCI::CreateQueueHead() { - return NULL; + ehci_qh *result; + void *physicalAddress; + if (fStack->AllocateChunk((void **)&result, &physicalAddress, + sizeof(ehci_qh)) < B_OK) { + TRACE_ERROR(("usb_ehci: failed to allocate queue head\n")); + return NULL; + } + + result->this_phy = (addr_t)physicalAddress; + result->next_phy = EHCI_QH_TERMINATE; + result->next_log = NULL; + result->prev_log = NULL; + + ehci_qtd *descriptor = CreateDescriptor(0, 0); + if (!descriptor) { + TRACE_ERROR(("usb_ehci: failed to allocate initial qtd for queue head\n")); + fStack->FreeChunk(result, (void *)result->this_phy, sizeof(ehci_qh)); + return NULL; + } + + descriptor->token &= ~EHCI_QTD_STATUS_ACTIVE; + result->stray_log = descriptor; + result->element_log = descriptor; + result->current_qtd_phy = EHCI_QTD_TERMINATE; + result->overlay.next_phy = descriptor->this_phy; + result->overlay.alt_next_phy = EHCI_QTD_TERMINATE; + result->overlay.token = 0; + result->overlay.buffer_phy[0] = 0; + result->overlay.buffer_phy[1] = 0; + result->overlay.buffer_phy[2] = 0; + result->overlay.buffer_phy[3] = 0; + result->overlay.buffer_phy[4] = 0; + return result; +} + + +void +EHCI::FreeQueueHead(ehci_qh *queueHead) +{ + if (!queueHead) + return; + + FreeDescriptor((ehci_qtd *)queueHead->stray_log); + fStack->FreeChunk(queueHead, (void *)queueHead->this_phy, sizeof(ehci_qh)); + } status_t -EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **firstDescriptor, - ehci_qtd **lastDescriptor, size_t bufferSize) +EHCI::LinkQueueHead(ehci_qh *queueHead) +{ + if (!Lock()) + return B_ERROR; + + ehci_qh *prevHead = (ehci_qh *)fAsyncQueueHead->prev_log; + queueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH; + queueHead->next_log = fAsyncQueueHead; + queueHead->prev_log = prevHead; + fAsyncQueueHead->prev_log = queueHead; + prevHead->next_log = queueHead; + prevHead->next_phy = queueHead->this_phy | EHCI_QH_TYPE_QH; + + Unlock(); + return B_OK; +} + + +status_t +EHCI::UnlinkQueueHead(ehci_qh *queueHead) +{ + if (!Lock()) + return B_ERROR; + + ehci_qh *prevHead = (ehci_qh *)queueHead->prev_log; + ehci_qh *nextHead = (ehci_qh *)queueHead->next_log; + prevHead->next_phy = queueHead->next_phy | EHCI_QH_TYPE_QH; + prevHead->next_log = queueHead->next_log; + nextHead->prev_log = queueHead->prev_log; + queueHead->next_phy = fAsyncQueueHead->this_phy | EHCI_QH_TYPE_QH; + queueHead->next_log = NULL; + queueHead->prev_log = NULL; + + Unlock(); + return B_OK; +} + + +status_t +EHCI::FillQueueWithRequest(Transfer *transfer, ehci_qh *queueHead, + ehci_qtd **_dataDescriptor, bool *_directionIn) +{ + Pipe *pipe = transfer->TransferPipe(); + usb_request_data *requestData = transfer->RequestData(); + bool directionIn = (requestData->RequestType & USB_REQTYPE_DEVICE_IN) > 0; + + ehci_qtd *setupDescriptor = CreateDescriptor(sizeof(usb_request_data), + EHCI_QTD_PID_SETUP); + ehci_qtd *statusDescriptor = CreateDescriptor(0, + directionIn ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN); + + if (!setupDescriptor || !statusDescriptor) { + TRACE_ERROR(("usb_ehci: failed to allocate descriptors\n")); + FreeDescriptor(setupDescriptor); + FreeDescriptor(statusDescriptor); + return B_NO_MEMORY; + } + + iovec vector; + vector.iov_base = requestData; + vector.iov_len = sizeof(usb_request_data); + WriteDescriptorChain(setupDescriptor, &vector, 1); + + ehci_qtd *strayDescriptor = (ehci_qtd *)queueHead->stray_log; + statusDescriptor->token |= EHCI_QTD_IOC | EHCI_QTD_DATA_TOGGLE; + LinkDescriptors(statusDescriptor, strayDescriptor, strayDescriptor); + + ehci_qtd *dataDescriptor = NULL; + if (transfer->VectorCount() > 0) { + ehci_qtd *lastDescriptor = NULL; + status_t result = CreateDescriptorChain(pipe, &dataDescriptor, + &lastDescriptor, strayDescriptor, transfer->VectorLength(), + directionIn ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT); + + if (result < B_OK) { + FreeDescriptor(setupDescriptor); + FreeDescriptor(statusDescriptor); + return result; + } + + if (!directionIn) { + WriteDescriptorChain(dataDescriptor, transfer->Vector(), + transfer->VectorCount()); + } + + LinkDescriptors(setupDescriptor, dataDescriptor, strayDescriptor); + LinkDescriptors(lastDescriptor, statusDescriptor, strayDescriptor); + } else { + // no data: link setup and status descriptors directly + LinkDescriptors(setupDescriptor, statusDescriptor, strayDescriptor); + } + + queueHead->element_log = setupDescriptor; + queueHead->overlay.next_phy = setupDescriptor->this_phy; + queueHead->overlay.alt_next_phy = EHCI_QTD_TERMINATE; + + *_dataDescriptor = dataDescriptor; + *_directionIn = directionIn; + return B_OK; +} + + +status_t +EHCI::FillQueueWithData(Transfer *transfer, ehci_qh *queueHead, + ehci_qtd **dataDescriptor, bool *directionIn) { - *firstDescriptor = NULL; - *lastDescriptor = NULL; return B_ERROR; } +ehci_qtd * +EHCI::CreateDescriptor(size_t bufferSize, uint8 pid) +{ + ehci_qtd *result; + void *physicalAddress; + if (fStack->AllocateChunk((void **)&result, &physicalAddress, + sizeof(ehci_qtd)) < B_OK) { + TRACE_ERROR(("usb_ehci: failed to allocate a qtd\n")); + return NULL; + } + + result->this_phy = (addr_t)physicalAddress; + result->next_phy = EHCI_QTD_TERMINATE; + result->next_log = NULL; + result->alt_next_phy = EHCI_QTD_TERMINATE; + result->alt_next_log = NULL; + result->buffer_size = bufferSize; + result->token = bufferSize << EHCI_QTD_BYTES_SHIFT; + result->token |= 3 << EHCI_QTD_ERRCOUNT_SHIFT; + result->token |= pid << EHCI_QTD_PID_SHIFT; + result->token |= EHCI_QTD_STATUS_ACTIVE; + if (bufferSize == 0) { + result->buffer_log = NULL; + result->buffer_phy[0] = 0; + result->buffer_phy[1] = 0; + result->buffer_phy[2] = 0; + result->buffer_phy[3] = 0; + result->buffer_phy[4] = 0; + return result; + } + + if (fStack->AllocateChunk(&result->buffer_log, &physicalAddress, + bufferSize) < B_OK) { + TRACE_ERROR(("usb_ehci: unable to allocate qtd buffer\n")); + fStack->FreeChunk(result, (void *)result->this_phy, sizeof(ehci_qtd)); + return NULL; + } + + addr_t physicalBase = (addr_t)physicalAddress; + result->buffer_phy[0] = physicalBase; + for (int32 i = 1; i < 5; i++) { + physicalBase += B_PAGE_SIZE; + result->buffer_phy[i] = physicalBase & EHCI_QTD_PAGE_MASK; + } + + return result; +} + + +status_t +EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor, + ehci_qtd **_lastDescriptor, ehci_qtd *strayDescriptor, size_t bufferSize, + uint8 pid) +{ + size_t packetSize = pipe->MaxPacketSize(); + int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize; + + bool dataToggle = pipe->DataToggle(); + ehci_qtd *firstDescriptor = NULL; + ehci_qtd *lastDescriptor = *_firstDescriptor; + for (int32 i = 0; i < descriptorCount; i++) { + ehci_qtd *descriptor = CreateDescriptor(min_c(packetSize, bufferSize), + pid); + + if (!descriptor) { + FreeDescriptorChain(firstDescriptor); + return B_NO_MEMORY; + } + + if (dataToggle) + descriptor->token |= EHCI_QTD_DATA_TOGGLE; + + if (lastDescriptor) + LinkDescriptors(lastDescriptor, descriptor, strayDescriptor); + + dataToggle = !dataToggle; + bufferSize -= packetSize; + lastDescriptor = descriptor; + if (!firstDescriptor) + firstDescriptor = descriptor; + } + + *_firstDescriptor = firstDescriptor; + *_lastDescriptor = lastDescriptor; + return B_OK; +} + + void EHCI::FreeDescriptor(ehci_qtd *descriptor) { + if (!descriptor) + return; + + if (descriptor->buffer_log) { + fStack->FreeChunk(descriptor->buffer_log, + (void *)descriptor->buffer_phy[0], descriptor->buffer_size); + } + + fStack->FreeChunk(descriptor, (void *)descriptor->this_phy, sizeof(ehci_qtd)); } void EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor) { + ehci_qtd *current = topDescriptor; + ehci_qtd *next = NULL; + + while (current) { + next = (ehci_qtd *)current->next_log; + FreeDescriptor(current); + current = next; + } } void -EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last) +EHCI::LinkDescriptors(ehci_qtd *first, ehci_qtd *last, ehci_qtd *alt) { + first->next_phy = last->this_phy; + first->next_log = last; + + if (alt) { + first->alt_next_phy = alt->this_phy; + first->alt_next_log = alt; + } else { + first->alt_next_phy = EHCI_QTD_TERMINATE; + first->alt_next_log = NULL; + } } @@ -700,7 +1213,50 @@ size_t EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector, size_t vectorCount) { - return 0; + ehci_qtd *current = topDescriptor; + size_t actualLength = 0; + size_t vectorIndex = 0; + size_t vectorOffset = 0; + size_t bufferOffset = 0; + + while (current) { + if (!current->buffer_log) + break; + + while (true) { + size_t length = min_c(current->buffer_size - bufferOffset, + vector[vectorIndex].iov_len - vectorOffset); + + memcpy((uint8 *)current->buffer_log + bufferOffset, + (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length); + + actualLength += length; + vectorOffset += length; + bufferOffset += length; + + if (vectorOffset >= vector[vectorIndex].iov_len) { + if (++vectorIndex >= vectorCount) { + TRACE(("usb_ehci: wrote descriptor chain (%d bytes, no more vectors)\n", actualLength)); + return actualLength; + } + + vectorOffset = 0; + } + + if (bufferOffset >= current->buffer_size) { + bufferOffset = 0; + break; + } + } + + if (current->next_phy & EHCI_QTD_TERMINATE) + break; + + current = (ehci_qtd *)current->next_log; + } + + TRACE(("usb_ehci: wrote descriptor chain (%d bytes)\n", actualLength)); + return actualLength; } @@ -708,14 +1264,83 @@ size_t EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector, size_t vectorCount, uint8 *lastDataToggle) { - return 0; + uint32 dataToggle = 0; + ehci_qtd *current = topDescriptor; + size_t actualLength = 0; + size_t vectorIndex = 0; + size_t vectorOffset = 0; + size_t bufferOffset = 0; + + while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) > 0) { + if (!current->buffer_log) + break; + + dataToggle = current->token & EHCI_QTD_DATA_TOGGLE; + size_t bufferSize = 0; // ToDo + + while (true) { + size_t length = min_c(bufferSize - bufferOffset, + vector[vectorIndex].iov_len - vectorOffset); + + memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset, + (uint8 *)current->buffer_log + bufferOffset, length); + + actualLength += length; + vectorOffset += length; + bufferOffset += length; + + if (vectorOffset >= vector[vectorIndex].iov_len) { + if (++vectorIndex >= vectorCount) { + TRACE(("usb_ehci: read descriptor chain (%d bytes, no more vectors)\n", actualLength)); + if (lastDataToggle) + *lastDataToggle = dataToggle > 0 ? 1 : 0; + return actualLength; + } + + vectorOffset = 0; + } + + if (bufferOffset >= bufferSize) { + bufferOffset = 0; + break; + } + } + + if (current->next_phy & EHCI_QTD_TERMINATE) + break; + + current = (ehci_qtd *)current->next_log; + } + + TRACE(("usb_ehci: read descriptor chain (%d bytes)\n", actualLength)); + if (lastDataToggle) + *lastDataToggle = dataToggle > 0 ? 1 : 0; + return actualLength; } size_t EHCI::ReadActualLength(ehci_qtd *topDescriptor, uint8 *lastDataToggle) { - return 0; + size_t actualLength = 0; + ehci_qtd *current = topDescriptor; + uint32 dataToggle = 0; + + while (current && (current->token & EHCI_QTD_STATUS_ACTIVE) > 0) { + dataToggle = current->token & EHCI_QTD_DATA_TOGGLE; + size_t length = 0; // ToDo + actualLength += length; + + if (current->next_phy & EHCI_QTD_TERMINATE) + break; + + current = (ehci_qtd *)current->next_log; + } + + TRACE(("usb_ehci: read actual length (%d bytes)\n", actualLength)); + if (lastDataToggle) + *lastDataToggle = dataToggle > 0 ? 1 : 0; + return actualLength; } diff --git a/src/add-ons/kernel/busses/usb/ehci.h b/src/add-ons/kernel/busses/usb/ehci.h index e610a34060..280c4cd24a 100644 --- a/src/add-ons/kernel/busses/usb/ehci.h +++ b/src/add-ons/kernel/busses/usb/ehci.h @@ -22,9 +22,7 @@ class EHCIRootHub; typedef struct transfer_data_s { Transfer *transfer; ehci_qh *queue_head; - ehci_qtd *first_descriptor; ehci_qtd *data_descriptor; - ehci_qtd *last_descriptor; bool incoming; transfer_data_s *link; } transfer_data; @@ -37,6 +35,8 @@ public: status_t Start(); virtual status_t SubmitTransfer(Transfer *transfer); + status_t SubmitPeriodicTransfer(Transfer *transfer); + status_t SubmitAsyncTransfer(Transfer *transfer); static status_t AddTo(Stack *stack); @@ -61,9 +61,7 @@ static int32 InterruptHandler(void *data); // Transfer management status_t AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead, - ehci_qtd *firstDescriptor, ehci_qtd *dataDescriptor, - ehci_qtd *lastDescriptor, bool directionIn); status_t CancelPendingTransfer(Transfer *transfer); status_t CancelAllPendingTransfers(); @@ -71,19 +69,38 @@ static int32 InterruptHandler(void *data); static int32 FinishThread(void *data); void FinishTransfers(); + // Queue Head functions + ehci_qh *CreateQueueHead(); + void FreeQueueHead(ehci_qh *queueHead); + + status_t LinkQueueHead(ehci_qh *queueHead); + status_t UnlinkQueueHead(ehci_qh *queueHead); + + // Queue functions + status_t FillQueueWithRequest(Transfer *transfer, + ehci_qh *queueHead, + ehci_qtd **dataDescriptor, + bool *directionIn); + status_t FillQueueWithData(Transfer *transfer, + ehci_qh *queueHead, + ehci_qtd **dataDescriptor, + bool *directionIn); + // Descriptor functions - ehci_qtd *CreateDescriptor(Pipe *pipe, - size_t bufferSizeToAllocate); + ehci_qtd *CreateDescriptor(size_t bufferSizeToAllocate, + uint8 pid); status_t CreateDescriptorChain(Pipe *pipe, ehci_qtd **firstDescriptor, ehci_qtd **lastDescriptor, - size_t bufferSizeToAllocate); + ehci_qtd *strayDescriptor, + size_t bufferSizeToAllocate, + uint8 pid); void FreeDescriptor(ehci_qtd *descriptor); void FreeDescriptorChain(ehci_qtd *topDescriptor); void LinkDescriptors(ehci_qtd *first, - ehci_qtd *last); + ehci_qtd *last, ehci_qtd *alt); size_t WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector, size_t vectorCount); @@ -114,6 +131,9 @@ static pci_module_info *sPCIModule; area_id fPeriodicFrameListArea; addr_t *fPeriodicFrameList; + // Async frame list + ehci_qh *fAsyncQueueHead; + // Maintain a linked list of transfers transfer_data *fFirstTransfer; transfer_data *fLastTransfer; diff --git a/src/add-ons/kernel/busses/usb/ehci_hardware.h b/src/add-ons/kernel/busses/usb/ehci_hardware.h index 786330e14e..a85171ab3a 100644 --- a/src/add-ons/kernel/busses/usb/ehci_hardware.h +++ b/src/add-ons/kernel/busses/usb/ehci_hardware.h @@ -56,6 +56,7 @@ #define EHCI_USBSTS_PORTCHANGE (1 << 2) // Port Change Detected #define EHCI_USBSTS_USBERRINT (1 << 1) // USB Error Interrupt #define EHCI_USBSTS_USBINT (1 << 0) // USB Interrupt +#define EHCI_USBSTS_INTMASK 0x3f // USB Interrupt Enable Register (EHCI Spec 2.3.3) @@ -96,9 +97,13 @@ #define EHCI_PORTSC_DATAMASK 0xffffffd5 -// PCI Registers -#define PCI_LEGSUP 0xc0 // PCI Legacy Support -#define PCI_LEGSUP_USBPIRQDEN 0x2000 // USB PIRQ +// Extended Capabilities +#define EHCI_ECP_SHIFT 8 // Extended Capability Pointer +#define EHCI_ECP_MASK 0xff +#define EHCI_LEGSUP_CAPID_MASK 0xff +#define EHCI_LEGSUP_CAPID 0x01 +#define EHCI_LEGSUP_OSOWNED (1 << 24) // OS Owned Semaphore +#define EHCI_LEGSUP_BIOSOWNED (1 << 16) // BIOS Owned Semaphore // Data Structures (EHCI Spec 3) @@ -119,7 +124,7 @@ typedef struct { // Hardware Part addr_t next_phy; addr_t alt_next_phy; - uint32 status_token; + uint32 token; addr_t buffer_phy[5]; // Software Part @@ -132,15 +137,19 @@ typedef struct { #define EHCI_QTD_TERMINATE (1 << 0) +#define EHCI_QTD_DATA_TOGGLE (1 << 31) #define EHCI_QTD_BYTES_SHIFT 16 -#define EHCI_QTD_BYTES_MASK 0xffff +#define EHCI_QTD_BYTES_MASK 0x7fff #define EHCI_QTD_IOC (1 << 15) -#define EHCI_QTD_PAGE_SHIFT 12 -#define EHCI_QTD_PAGE_MASK 0x07 +#define EHCI_QTD_CPAGE_SHIFT 12 +#define EHCI_QTD_CPAGE_MASK 0x07 #define EHCI_QTD_ERRCOUNT_SHIFT 10 #define EHCI_QTD_ERRCOUNT_MASK 0x03 #define EHCI_QTD_PID_SHIFT 8 #define EHCI_QTD_PID_MASK 0x03 +#define EHCI_QTD_PID_OUT 0x00 +#define EHCI_QTD_PID_IN 0x01 +#define EHCI_QTD_PID_SETUP 0x02 #define EHCI_QTD_STATUS_SHIFT 0 #define EHCI_QTD_STATUS_MASK 0x7f #define EHCI_QTD_STATUS_ACTIVE (1 << 7) // Active @@ -151,19 +160,29 @@ typedef struct { #define EHCI_QTD_STATUS_MISSED (1 << 2) // Missed Micro-Frame #define EHCI_QTD_STATUS_SPLIT (1 << 1) // Split Transaction State #define EHCI_QTD_STATUS_PING (1 << 0) // Ping State +#define EHCI_QTD_PAGE_MASK 0xfffff000 // Queue Head (QH, EHCI Spec 3.6) typedef struct { // Hardware Part - addr_t link_phy; + addr_t next_phy; uint32 endpoint_chars; uint32 endpoint_caps; addr_t current_qtd_phy; - uint32 overlay[8]; + + struct { + addr_t next_phy; + addr_t alt_next_phy; + uint32 token; + addr_t buffer_phy[5]; + } overlay; + // Software Part addr_t this_phy; - void *link_log; + void *next_log; + void *prev_log; + void *stray_log; void *element_log; } ehci_qh; diff --git a/src/add-ons/kernel/busses/usb/ehci_rh.cpp b/src/add-ons/kernel/busses/usb/ehci_rh.cpp index ca93003477..3afe5e88ed 100644 --- a/src/add-ons/kernel/busses/usb/ehci_rh.cpp +++ b/src/add-ons/kernel/busses/usb/ehci_rh.cpp @@ -122,7 +122,7 @@ static ehci_root_hub_string_s sEHCIRootHubStrings[3] = { EHCIRootHub::EHCIRootHub(Object *rootObject, int8 deviceAddress) - : Hub(rootObject, sEHCIRootHubDevice, deviceAddress, false) + : Hub(rootObject, sEHCIRootHubDevice, deviceAddress, USB_SPEED_HIGHSPEED) { } diff --git a/src/add-ons/kernel/busses/usb/ohci_rh.cpp b/src/add-ons/kernel/busses/usb/ohci_rh.cpp index 9b47c2f00b..b063bd9587 100644 --- a/src/add-ons/kernel/busses/usb/ohci_rh.cpp +++ b/src/add-ons/kernel/busses/usb/ohci_rh.cpp @@ -88,7 +88,7 @@ usb_hub_descriptor ohci_hubd = //Implementation OHCIRootHub::OHCIRootHub( OHCI *ohci , int8 devicenum ) - : Hub( ohci->RootObject() , ohci_devd , devicenum , false ) + : Hub( ohci->RootObject() , ohci_devd , devicenum , USB_SPEED_FULLSPEED ) { m_ohci = ohci; } diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp b/src/add-ons/kernel/busses/usb/uhci.cpp index fffff7e5a2..e2f621d0f2 100644 --- a/src/add-ons/kernel/busses/usb/uhci.cpp +++ b/src/add-ons/kernel/busses/usb/uhci.cpp @@ -99,7 +99,8 @@ Queue::Queue(Stack *stack) } void *physicalAddress; - fStatus = fStack->AllocateChunk((void **)&fQueueHead, &physicalAddress, 32); + fStatus = fStack->AllocateChunk((void **)&fQueueHead, &physicalAddress, + sizeof(uhci_qh)); if (fStatus < B_OK) return; @@ -116,10 +117,11 @@ Queue::~Queue() Lock(); benaphore_destroy(&fLock); - fStack->FreeChunk(fQueueHead, (void *)fQueueHead->this_phy, 32); + fStack->FreeChunk(fQueueHead, (void *)fQueueHead->this_phy, sizeof(uhci_qh)); if (fStrayDescriptor) - fStack->FreeChunk(fStrayDescriptor, (void *)fStrayDescriptor->this_phy, 32); + fStack->FreeChunk(fStrayDescriptor, (void *)fStrayDescriptor->this_phy, + sizeof(uhci_td)); } @@ -168,7 +170,7 @@ Queue::TerminateByStrayDescriptor() // descriptor in order to get some chipset to work nicely (like the PIIX). void *physicalAddress; status_t result = fStack->AllocateChunk((void **)&fStrayDescriptor, - &physicalAddress, 32); + &physicalAddress, sizeof(uhci_td)); if (result < B_OK) { TRACE_ERROR(("usb_uhci: failed to allocate a stray transfer descriptor\n")); return result; @@ -186,7 +188,7 @@ Queue::TerminateByStrayDescriptor() if (!Lock()) { fStack->FreeChunk(fStrayDescriptor, (void *)fStrayDescriptor->this_phy, - 32); + sizeof(uhci_td)); return B_ERROR; } @@ -1104,14 +1106,15 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, size_t bufferSize) uhci_td *result; void *physicalAddress; - if (fStack->AllocateChunk((void **)&result, &physicalAddress, 32) < B_OK) { + if (fStack->AllocateChunk((void **)&result, &physicalAddress, + sizeof(uhci_td)) < B_OK) { TRACE_ERROR(("usb_uhci: failed to allocate a transfer descriptor\n")); return NULL; } result->this_phy = (addr_t)physicalAddress; result->status = TD_STATUS_ACTIVE | TD_CONTROL_3_ERRORS | TD_CONTROL_SPD; - if (pipe->Speed() == Pipe::LowSpeed) + if (pipe->Speed() == USB_SPEED_LOWSPEED) result->status |= TD_CONTROL_LOWSPEED; result->buffer_size = bufferSize; @@ -1134,7 +1137,7 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, size_t bufferSize) if (fStack->AllocateChunk(&result->buffer_log, &result->buffer_phy, bufferSize) < B_OK) { TRACE_ERROR(("usb_uhci: unable to allocate space for the buffer\n")); - fStack->FreeChunk(result, (void *)result->this_phy, 32); + fStack->FreeChunk(result, (void *)result->this_phy, sizeof(uhci_td)); return NULL; } @@ -1192,7 +1195,7 @@ UHCI::FreeDescriptor(uhci_td *descriptor) (void *)descriptor->buffer_phy, descriptor->buffer_size); } - fStack->FreeChunk(descriptor, (void *)descriptor->this_phy, 32); + fStack->FreeChunk(descriptor, (void *)descriptor->this_phy, sizeof(uhci_td)); } diff --git a/src/add-ons/kernel/busses/usb/uhci_rh.cpp b/src/add-ons/kernel/busses/usb/uhci_rh.cpp index 49743853d0..7989714f25 100644 --- a/src/add-ons/kernel/busses/usb/uhci_rh.cpp +++ b/src/add-ons/kernel/busses/usb/uhci_rh.cpp @@ -126,7 +126,7 @@ static uhci_root_hub_string_s sUHCIRootHubStrings[3] = { UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress) - : Hub(rootObject, sUHCIRootHubDevice, deviceAddress, false) + : Hub(rootObject, sUHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED) { }