* Implemented most qTD and qH functions for EHCI async transfers.
* Implementing control and bulk (async) transfers. They don't work yet though. * Corrected the legacy support handling in EHCI * Fixed the bit mask for total bytes in qTDs and added the data toggle bit * Changed the boolean low speed flags to usb_speed enum that allows for low, full and highspeed Also wrote a memory allocator that takes over memory management from the stack. It is similar to a buddy allocator. This does on the one hand remove some ugly code from the stack and is on the other hand far more scalable than the previous free list approach. This scalability is needed for proper EHCI support where buffers can go up to a size of 5 pages. The allocator is not perfect and it's memory overhead is quite high compared to the managed memory (depends on the managed block sizes), but it's quik and works well so far. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18849 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
770684cf94
commit
f452f9dc78
@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
BusManager::BusManager(Stack *stack)
|
BusManager::BusManager(Stack *stack)
|
||||||
: fInitOK(false),
|
: fInitOK(false),
|
||||||
fDefaultPipe(NULL),
|
|
||||||
fDefaultPipeLowSpeed(NULL),
|
|
||||||
fRootHub(NULL),
|
fRootHub(NULL),
|
||||||
fExploreThread(-1)
|
fExploreThread(-1)
|
||||||
{
|
{
|
||||||
@ -31,15 +29,14 @@ BusManager::BusManager(Stack *stack)
|
|||||||
fDeviceMap[i] = false;
|
fDeviceMap[i] = false;
|
||||||
|
|
||||||
// Set up the default pipes
|
// Set up the default pipes
|
||||||
fDefaultPipe = new(std::nothrow) ControlPipe(fRootObject, 0, 0,
|
for (int32 i = 0; i <= USB_SPEED_MAX; i++) {
|
||||||
Pipe::FullSpeed, 8);
|
fDefaultPipes[i] = new(std::nothrow) ControlPipe(fRootObject, 0, 0,
|
||||||
if (!fDefaultPipe)
|
(usb_speed)i, 8);
|
||||||
return;
|
if (!fDefaultPipes[i]) {
|
||||||
|
TRACE_ERROR(("usb BusManager: failed to allocate default pipes\n"));
|
||||||
fDefaultPipeLowSpeed = new(std::nothrow) ControlPipe(fRootObject, 0, 0,
|
return;
|
||||||
Pipe::LowSpeed, 8);
|
}
|
||||||
if (!fDefaultPipeLowSpeed)
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
fInitOK = true;
|
fInitOK = true;
|
||||||
}
|
}
|
||||||
@ -118,7 +115,7 @@ BusManager::AllocateAddress()
|
|||||||
|
|
||||||
|
|
||||||
Device *
|
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)
|
// Check if there is a free entry in the device map (for the device number)
|
||||||
int8 deviceAddress = AllocateAddress();
|
int8 deviceAddress = AllocateAddress();
|
||||||
@ -128,7 +125,7 @@ BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("usb BusManager::AllocateNewDevice(): setting device address to %d\n", deviceAddress));
|
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;
|
status_t result = B_ERROR;
|
||||||
for (int32 i = 0; i < 15; i++) {
|
for (int32 i = 0; i < 15; i++) {
|
||||||
@ -158,8 +155,7 @@ BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed)
|
|||||||
snooze(USB_DELAY_SET_ADDRESS);
|
snooze(USB_DELAY_SET_ADDRESS);
|
||||||
|
|
||||||
// Create a temporary pipe with the new address
|
// Create a temporary pipe with the new address
|
||||||
ControlPipe pipe(parent, deviceAddress, 0,
|
ControlPipe pipe(parent, deviceAddress, 0, speed, 8);
|
||||||
lowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed, 8);
|
|
||||||
|
|
||||||
// Get the device descriptor
|
// Get the device descriptor
|
||||||
// Just retrieve the first 8 bytes of the descriptor -> minimum supported
|
// 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) {
|
if (deviceDescriptor.device_class == 0x09) {
|
||||||
TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n"));
|
TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n"));
|
||||||
Hub *hub = new(std::nothrow) Hub(parent, deviceDescriptor,
|
Hub *hub = new(std::nothrow) Hub(parent, deviceDescriptor,
|
||||||
deviceAddress, lowSpeed);
|
deviceAddress, speed);
|
||||||
if (!hub) {
|
if (!hub) {
|
||||||
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate hub\n"));
|
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate hub\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -214,7 +210,7 @@ BusManager::AllocateNewDevice(Hub *parent, bool lowSpeed)
|
|||||||
|
|
||||||
TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n"));
|
TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n"));
|
||||||
Device *device = new(std::nothrow) Device(parent, deviceDescriptor,
|
Device *device = new(std::nothrow) Device(parent, deviceDescriptor,
|
||||||
deviceAddress, lowSpeed);
|
deviceAddress, speed);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate device\n"));
|
TRACE_ERROR(("usb BusManager::AllocateNewDevice(): no memory to allocate device\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -11,13 +11,13 @@
|
|||||||
|
|
||||||
|
|
||||||
Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
||||||
bool lowSpeed)
|
usb_speed speed)
|
||||||
: Object(parent),
|
: Object(parent),
|
||||||
fDeviceDescriptor(desc),
|
fDeviceDescriptor(desc),
|
||||||
fInitOK(false),
|
fInitOK(false),
|
||||||
fConfigurations(NULL),
|
fConfigurations(NULL),
|
||||||
fCurrentConfiguration(NULL),
|
fCurrentConfiguration(NULL),
|
||||||
fLowSpeed(lowSpeed),
|
fSpeed(speed),
|
||||||
fDeviceAddress(deviceAddress),
|
fDeviceAddress(deviceAddress),
|
||||||
fLock(-1),
|
fLock(-1),
|
||||||
fNotifyCookie(NULL)
|
fNotifyCookie(NULL)
|
||||||
@ -33,8 +33,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
|||||||
set_sem_owner(fLock, B_SYSTEM_TEAM);
|
set_sem_owner(fLock, B_SYSTEM_TEAM);
|
||||||
|
|
||||||
fDefaultPipe = new(std::nothrow) ControlPipe(this, deviceAddress, 0,
|
fDefaultPipe = new(std::nothrow) ControlPipe(this, deviceAddress, 0,
|
||||||
fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed,
|
fSpeed, fDeviceDescriptor.max_packet_size_0);
|
||||||
fDeviceDescriptor.max_packet_size_0);
|
|
||||||
if (!fDefaultPipe) {
|
if (!fDefaultPipe) {
|
||||||
TRACE_ERROR(("USB Device: could not allocate default pipe\n"));
|
TRACE_ERROR(("USB Device: could not allocate default pipe\n"));
|
||||||
return;
|
return;
|
||||||
@ -189,8 +188,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
|||||||
endpoint = new(std::nothrow) ControlPipe(this,
|
endpoint = new(std::nothrow) ControlPipe(this,
|
||||||
fDeviceAddress,
|
fDeviceAddress,
|
||||||
endpointDescriptor->endpoint_address & 0x0f,
|
endpointDescriptor->endpoint_address & 0x0f,
|
||||||
fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed,
|
fSpeed, endpointDescriptor->max_packet_size);
|
||||||
endpointDescriptor->max_packet_size);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x01: /* Isochronous Endpoint */
|
case 0x01: /* Isochronous Endpoint */
|
||||||
@ -198,8 +196,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
|||||||
fDeviceAddress,
|
fDeviceAddress,
|
||||||
endpointDescriptor->endpoint_address & 0x0f,
|
endpointDescriptor->endpoint_address & 0x0f,
|
||||||
(endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out,
|
(endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out,
|
||||||
fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed,
|
fSpeed, endpointDescriptor->max_packet_size);
|
||||||
endpointDescriptor->max_packet_size);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02: /* Bulk Endpoint */
|
case 0x02: /* Bulk Endpoint */
|
||||||
@ -207,8 +204,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
|||||||
fDeviceAddress,
|
fDeviceAddress,
|
||||||
endpointDescriptor->endpoint_address & 0x0f,
|
endpointDescriptor->endpoint_address & 0x0f,
|
||||||
(endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out,
|
(endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out,
|
||||||
fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed,
|
fSpeed, endpointDescriptor->max_packet_size);
|
||||||
endpointDescriptor->max_packet_size);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03: /* Interrupt Endpoint */
|
case 0x03: /* Interrupt Endpoint */
|
||||||
@ -216,8 +212,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
|||||||
fDeviceAddress,
|
fDeviceAddress,
|
||||||
endpointDescriptor->endpoint_address & 0x0f,
|
endpointDescriptor->endpoint_address & 0x0f,
|
||||||
(endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out,
|
(endpointDescriptor->endpoint_address & 0x80) > 0 ? Pipe::In : Pipe::Out,
|
||||||
fLowSpeed ? Pipe::LowSpeed : Pipe::FullSpeed,
|
fSpeed, endpointDescriptor->max_packet_size);
|
||||||
endpointDescriptor->max_packet_size);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
|
|
||||||
Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
||||||
bool lowSpeed)
|
usb_speed speed)
|
||||||
: Device(parent, desc, deviceAddress, lowSpeed)
|
: Device(parent, desc, deviceAddress, speed)
|
||||||
{
|
{
|
||||||
TRACE(("USB Hub is being initialised\n"));
|
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.
|
// Set to false again for the hub init.
|
||||||
fInitOK = false;
|
fInitOK = false;
|
||||||
|
|
||||||
for (int32 i = 0; i < 8; i++)
|
for (int32 i = 0; i < 8; i++)
|
||||||
fChildren[i] = NULL;
|
fChildren[i] = NULL;
|
||||||
@ -178,8 +178,14 @@ Hub::Explore()
|
|||||||
continue;
|
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,
|
Device *newDevice = GetBusManager()->AllocateNewDevice(this,
|
||||||
(fPortStatus[i].status & PORT_STATUS_LOW_SPEED) > 0);
|
speed);
|
||||||
|
|
||||||
if (newDevice) {
|
if (newDevice) {
|
||||||
fChildren[i] = newDevice;
|
fChildren[i] = newDevice;
|
||||||
|
@ -19,6 +19,7 @@ KernelStaticLibrary libusb.a :
|
|||||||
Pipe.cpp
|
Pipe.cpp
|
||||||
Interface.cpp
|
Interface.cpp
|
||||||
Object.cpp
|
Object.cpp
|
||||||
|
PhysicalMemoryAllocator.cpp
|
||||||
: -fno-pic
|
: -fno-pic
|
||||||
;
|
;
|
||||||
|
|
||||||
|
340
src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.cpp
Normal file
340
src/add-ons/kernel/bus_managers/usb/PhysicalMemoryAllocator.cpp
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Michael Lotz <mmlr@mlotz.ch>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#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");
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Michael Lotz <mmlr@mlotz.ch>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PHYSICAL_MEMORY_ALLOCATOR_H_
|
||||||
|
#define _PHYSICAL_MEMORY_ALLOCATOR_H_
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
|
|
||||||
|
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_
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
Pipe::Pipe(Object *parent, int8 deviceAddress, uint8 endpointAddress,
|
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),
|
: Object(parent),
|
||||||
fDeviceAddress(deviceAddress),
|
fDeviceAddress(deviceAddress),
|
||||||
fEndpointAddress(endpointAddress),
|
fEndpointAddress(endpointAddress),
|
||||||
@ -94,7 +94,7 @@ Pipe::GetStatus(uint16 *status)
|
|||||||
|
|
||||||
|
|
||||||
InterruptPipe::InterruptPipe(Object *parent, int8 deviceAddress,
|
InterruptPipe::InterruptPipe(Object *parent, int8 deviceAddress,
|
||||||
uint8 endpointAddress, pipeDirection direction, pipeSpeed speed,
|
uint8 endpointAddress, pipeDirection direction, usb_speed speed,
|
||||||
size_t maxPacketSize)
|
size_t maxPacketSize)
|
||||||
: Pipe(parent, deviceAddress, endpointAddress, direction, speed,
|
: Pipe(parent, deviceAddress, endpointAddress, direction, speed,
|
||||||
maxPacketSize)
|
maxPacketSize)
|
||||||
@ -126,7 +126,7 @@ InterruptPipe::QueueInterrupt(void *data, size_t dataLength,
|
|||||||
|
|
||||||
|
|
||||||
BulkPipe::BulkPipe(Object *parent, int8 deviceAddress, uint8 endpointAddress,
|
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,
|
: Pipe(parent, deviceAddress, endpointAddress, direction, speed,
|
||||||
maxPacketSize)
|
maxPacketSize)
|
||||||
{
|
{
|
||||||
@ -175,7 +175,7 @@ BulkPipe::QueueBulkV(iovec *vector, size_t vectorCount,
|
|||||||
|
|
||||||
|
|
||||||
IsochronousPipe::IsochronousPipe(Object *parent, int8 deviceAddress,
|
IsochronousPipe::IsochronousPipe(Object *parent, int8 deviceAddress,
|
||||||
uint8 endpointAddress, pipeDirection direction, pipeSpeed speed,
|
uint8 endpointAddress, pipeDirection direction, usb_speed speed,
|
||||||
size_t maxPacketSize)
|
size_t maxPacketSize)
|
||||||
: Pipe(parent, deviceAddress, endpointAddress, direction, speed,
|
: Pipe(parent, deviceAddress, endpointAddress, direction, speed,
|
||||||
maxPacketSize)
|
maxPacketSize)
|
||||||
@ -206,7 +206,7 @@ typedef struct transfer_result_data_s {
|
|||||||
|
|
||||||
|
|
||||||
ControlPipe::ControlPipe(Object *parent, int8 deviceAddress,
|
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,
|
: Pipe(parent, deviceAddress, endpointAddress, Default, speed,
|
||||||
maxPacketSize)
|
maxPacketSize)
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <module.h>
|
#include <module.h>
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
|
#include "PhysicalMemoryAllocator.h"
|
||||||
|
|
||||||
|
|
||||||
Stack::Stack()
|
Stack::Stack()
|
||||||
@ -29,96 +30,13 @@ Stack::Stack()
|
|||||||
fObjectArray = (Object **)malloc(objectArraySize);
|
fObjectArray = (Object **)malloc(objectArraySize);
|
||||||
memset(fObjectArray, 0, objectArraySize);
|
memset(fObjectArray, 0, objectArraySize);
|
||||||
|
|
||||||
// Initialise the memory chunks: create 8, 16 and 32 byte-heaps
|
fAllocator = new(std::nothrow) PhysicalMemoryAllocator("USB Stack Allocator",
|
||||||
// NOTE: This is probably the most ugly code you will see in the
|
8, B_PAGE_SIZE * 4, 50);
|
||||||
// whole stack. Unfortunately this is needed because of the fact
|
if (!fAllocator) {
|
||||||
// that the compiler doesn't like us to apply pointer arithmethic
|
TRACE_ERROR(("usb stack: failed to allocate the allocator\n"));
|
||||||
// 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"));
|
|
||||||
return;
|
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
|
// Check for host controller modules
|
||||||
void *moduleList = open_module_list("busses/usb");
|
void *moduleList = open_module_list("busses/usb");
|
||||||
char moduleName[B_PATH_NAME_LENGTH];
|
char moduleName[B_PATH_NAME_LENGTH];
|
||||||
@ -155,9 +73,7 @@ Stack::~Stack()
|
|||||||
delete (*i);
|
delete (*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_area(fAreas[0]);
|
delete fAllocator;
|
||||||
delete_area(fAreas[1]);
|
|
||||||
delete_area(fAreas[2]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -255,93 +171,16 @@ Stack::IndexOfBusManager(BusManager *busManager)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, uint8 size)
|
Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, size_t size)
|
||||||
{
|
{
|
||||||
Lock();
|
return fAllocator->Allocate(size, logicalAddress, physicalAddress);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Stack::FreeChunk(void *logicalAddress, void *physicalAddress, uint8 size)
|
Stack::FreeChunk(void *logicalAddress, void *physicalAddress, size_t size)
|
||||||
{
|
{
|
||||||
Lock();
|
return fAllocator->Deallocate(size, logicalAddress, physicalAddress);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ class Transfer;
|
|||||||
class BusManager;
|
class BusManager;
|
||||||
class ControlPipe;
|
class ControlPipe;
|
||||||
class Object;
|
class Object;
|
||||||
|
class PhysicalMemoryAllocator;
|
||||||
|
|
||||||
|
|
||||||
struct host_controller_info {
|
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_NONE 0x00000000
|
||||||
#define USB_OBJECT_PIPE 0x00000001
|
#define USB_OBJECT_PIPE 0x00000001
|
||||||
#define USB_OBJECT_CONTROL_PIPE 0x00000002
|
#define USB_OBJECT_CONTROL_PIPE 0x00000002
|
||||||
@ -80,9 +89,9 @@ public:
|
|||||||
int32 IndexOfBusManager(BusManager *bus);
|
int32 IndexOfBusManager(BusManager *bus);
|
||||||
|
|
||||||
status_t AllocateChunk(void **logicalAddress,
|
status_t AllocateChunk(void **logicalAddress,
|
||||||
void **physicalAddress, uint8 size);
|
void **physicalAddress, size_t size);
|
||||||
status_t FreeChunk(void *logicalAddress,
|
status_t FreeChunk(void *logicalAddress,
|
||||||
void *physicalAddress, uint8 size);
|
void *physicalAddress, size_t size);
|
||||||
|
|
||||||
area_id AllocateArea(void **logicalAddress,
|
area_id AllocateArea(void **logicalAddress,
|
||||||
void **physicalAddress,
|
void **physicalAddress,
|
||||||
@ -105,15 +114,7 @@ private:
|
|||||||
Vector<BusManager *> fBusManagers;
|
Vector<BusManager *> fBusManagers;
|
||||||
|
|
||||||
benaphore fLock;
|
benaphore fLock;
|
||||||
area_id fAreas[USB_MAX_AREAS];
|
PhysicalMemoryAllocator *fAllocator;
|
||||||
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;
|
|
||||||
|
|
||||||
uint32 fObjectIndex;
|
uint32 fObjectIndex;
|
||||||
uint32 fObjectMaxCount;
|
uint32 fObjectMaxCount;
|
||||||
@ -140,7 +141,7 @@ virtual status_t InitCheck();
|
|||||||
|
|
||||||
int8 AllocateAddress();
|
int8 AllocateAddress();
|
||||||
Device *AllocateNewDevice(Hub *parent,
|
Device *AllocateNewDevice(Hub *parent,
|
||||||
bool lowSpeed);
|
usb_speed speed);
|
||||||
|
|
||||||
virtual status_t Start();
|
virtual status_t Start();
|
||||||
virtual status_t Stop();
|
virtual status_t Stop();
|
||||||
@ -160,8 +161,7 @@ static int32 ExploreThread(void *data);
|
|||||||
|
|
||||||
benaphore fLock;
|
benaphore fLock;
|
||||||
bool fDeviceMap[128];
|
bool fDeviceMap[128];
|
||||||
ControlPipe *fDefaultPipe;
|
ControlPipe *fDefaultPipes[USB_SPEED_MAX + 1];
|
||||||
ControlPipe *fDefaultPipeLowSpeed;
|
|
||||||
Hub *fRootHub;
|
Hub *fRootHub;
|
||||||
thread_id fExploreThread;
|
thread_id fExploreThread;
|
||||||
Object *fRootObject;
|
Object *fRootObject;
|
||||||
@ -202,20 +202,19 @@ private:
|
|||||||
class Pipe : public Object {
|
class Pipe : public Object {
|
||||||
public:
|
public:
|
||||||
enum pipeDirection { In, Out, Default };
|
enum pipeDirection { In, Out, Default };
|
||||||
enum pipeSpeed { LowSpeed, FullSpeed, HighSpeed };
|
|
||||||
|
|
||||||
Pipe(Object *parent,
|
Pipe(Object *parent,
|
||||||
int8 deviceAddress,
|
int8 deviceAddress,
|
||||||
uint8 endpointAddress,
|
uint8 endpointAddress,
|
||||||
pipeDirection direction,
|
pipeDirection direction,
|
||||||
pipeSpeed speed,
|
usb_speed speed,
|
||||||
size_t maxPacketSize);
|
size_t maxPacketSize);
|
||||||
virtual ~Pipe();
|
virtual ~Pipe();
|
||||||
|
|
||||||
virtual uint32 Type() { return USB_OBJECT_PIPE; };
|
virtual uint32 Type() { return USB_OBJECT_PIPE; };
|
||||||
|
|
||||||
int8 DeviceAddress() { return fDeviceAddress; };
|
int8 DeviceAddress() { return fDeviceAddress; };
|
||||||
pipeSpeed Speed() { return fSpeed; };
|
usb_speed Speed() { return fSpeed; };
|
||||||
pipeDirection Direction() { return fDirection; };
|
pipeDirection Direction() { return fDirection; };
|
||||||
int8 EndpointAddress() { return fEndpointAddress; };
|
int8 EndpointAddress() { return fEndpointAddress; };
|
||||||
size_t MaxPacketSize() { return fMaxPacketSize; };
|
size_t MaxPacketSize() { return fMaxPacketSize; };
|
||||||
@ -235,7 +234,7 @@ private:
|
|||||||
int8 fDeviceAddress;
|
int8 fDeviceAddress;
|
||||||
uint8 fEndpointAddress;
|
uint8 fEndpointAddress;
|
||||||
pipeDirection fDirection;
|
pipeDirection fDirection;
|
||||||
pipeSpeed fSpeed;
|
usb_speed fSpeed;
|
||||||
size_t fMaxPacketSize;
|
size_t fMaxPacketSize;
|
||||||
bool fDataToggle;
|
bool fDataToggle;
|
||||||
};
|
};
|
||||||
@ -246,7 +245,7 @@ public:
|
|||||||
ControlPipe(Object *parent,
|
ControlPipe(Object *parent,
|
||||||
int8 deviceAddress,
|
int8 deviceAddress,
|
||||||
uint8 endpointAddress,
|
uint8 endpointAddress,
|
||||||
pipeSpeed speed,
|
usb_speed speed,
|
||||||
size_t maxPacketSize);
|
size_t maxPacketSize);
|
||||||
|
|
||||||
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_CONTROL_PIPE; };
|
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_CONTROL_PIPE; };
|
||||||
@ -283,7 +282,7 @@ public:
|
|||||||
int8 deviceAddress,
|
int8 deviceAddress,
|
||||||
uint8 endpointAddress,
|
uint8 endpointAddress,
|
||||||
pipeDirection direction,
|
pipeDirection direction,
|
||||||
pipeSpeed speed,
|
usb_speed speed,
|
||||||
size_t maxPacketSize);
|
size_t maxPacketSize);
|
||||||
|
|
||||||
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_INTERRUPT_PIPE; };
|
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_INTERRUPT_PIPE; };
|
||||||
@ -301,7 +300,7 @@ public:
|
|||||||
int8 deviceAddress,
|
int8 deviceAddress,
|
||||||
uint8 endpointAddress,
|
uint8 endpointAddress,
|
||||||
pipeDirection direction,
|
pipeDirection direction,
|
||||||
pipeSpeed speed,
|
usb_speed speed,
|
||||||
size_t maxPacketSize);
|
size_t maxPacketSize);
|
||||||
|
|
||||||
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_BULK_PIPE; };
|
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_BULK_PIPE; };
|
||||||
@ -323,7 +322,7 @@ public:
|
|||||||
int8 deviceAddress,
|
int8 deviceAddress,
|
||||||
uint8 endpointAddress,
|
uint8 endpointAddress,
|
||||||
pipeDirection direction,
|
pipeDirection direction,
|
||||||
pipeSpeed speed,
|
usb_speed speed,
|
||||||
size_t maxPacketSize);
|
size_t maxPacketSize);
|
||||||
|
|
||||||
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_ISO_PIPE; };
|
virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_ISO_PIPE; };
|
||||||
@ -356,7 +355,8 @@ class Device : public Object {
|
|||||||
public:
|
public:
|
||||||
Device(Object *parent,
|
Device(Object *parent,
|
||||||
usb_device_descriptor &desc,
|
usb_device_descriptor &desc,
|
||||||
int8 deviceAddress, bool lowSpeed);
|
int8 deviceAddress,
|
||||||
|
usb_speed speed);
|
||||||
|
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
usb_configuration_info *fConfigurations;
|
usb_configuration_info *fConfigurations;
|
||||||
usb_configuration_info *fCurrentConfiguration;
|
usb_configuration_info *fCurrentConfiguration;
|
||||||
bool fLowSpeed;
|
usb_speed fSpeed;
|
||||||
int8 fDeviceAddress;
|
int8 fDeviceAddress;
|
||||||
size_t fMaxPacketIn[16];
|
size_t fMaxPacketIn[16];
|
||||||
size_t fMaxPacketOut[16];
|
size_t fMaxPacketOut[16];
|
||||||
@ -411,7 +411,8 @@ class Hub : public Device {
|
|||||||
public:
|
public:
|
||||||
Hub(Object *parent,
|
Hub(Object *parent,
|
||||||
usb_device_descriptor &desc,
|
usb_device_descriptor &desc,
|
||||||
int8 deviceAddress, bool lowSpeed);
|
int8 deviceAddress,
|
||||||
|
usb_speed speed);
|
||||||
|
|
||||||
virtual uint32 Type() { return USB_OBJECT_DEVICE | USB_OBJECT_HUB; };
|
virtual uint32 Type() { return USB_OBJECT_DEVICE | USB_OBJECT_HUB; };
|
||||||
|
|
||||||
|
@ -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)
|
EHCI::EHCI(pci_info *info, Stack *stack)
|
||||||
: BusManager(stack),
|
: BusManager(stack),
|
||||||
fPCIInfo(info),
|
fPCIInfo(info),
|
||||||
@ -79,10 +121,6 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
|||||||
TRACE(("usb_ehci: constructing new EHCI Host Controller Driver\n"));
|
TRACE(("usb_ehci: constructing new EHCI Host Controller Driver\n"));
|
||||||
fInitOK = false;
|
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
|
// enable busmaster and memory mapped access
|
||||||
uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
|
uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
|
||||||
fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
|
fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
|
||||||
@ -116,9 +154,52 @@ EHCI::EHCI(pci_info *info, Stack *stack)
|
|||||||
// read port count from capability register
|
// read port count from capability register
|
||||||
fPortCount = ReadCapReg32(EHCI_HCSPARAMS) & 0x0f;
|
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
|
// disable interrupts
|
||||||
WriteOpReg(EHCI_USBINTR, 0);
|
WriteOpReg(EHCI_USBINTR, 0);
|
||||||
|
|
||||||
|
// reset the segment register
|
||||||
|
WriteOpReg(EHCI_CTRDSSEGMENT, 0);
|
||||||
|
|
||||||
// reset the host controller
|
// reset the host controller
|
||||||
if (ControllerReset() < B_OK) {
|
if (ControllerReset() < B_OK) {
|
||||||
TRACE_ERROR(("usb_ehci: host controller failed to reset\n"));
|
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);
|
WriteOpReg(EHCI_PERIODICLISTBASE, (uint32)physicalAddress);
|
||||||
|
|
||||||
// route all ports to us
|
// allocate a queue head that will always stay in the async frame list
|
||||||
WriteOpReg(EHCI_CONFIGFLAG, EHCI_CONFIGFLAG_FLAG);
|
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;
|
fInitOK = true;
|
||||||
|
TRACE(("usb_ehci: EHCI Host Controller Driver constructed\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -167,6 +263,8 @@ EHCI::~EHCI()
|
|||||||
wait_for_thread(fFinishThread, &result);
|
wait_for_thread(fFinishThread, &result);
|
||||||
|
|
||||||
CancelAllPendingTransfers();
|
CancelAllPendingTransfers();
|
||||||
|
WriteOpReg(EHCI_USBCMD, 0);
|
||||||
|
WriteOpReg(EHCI_CONFIGFLAG, 0);
|
||||||
|
|
||||||
delete fRootHub;
|
delete fRootHub;
|
||||||
delete_area(fPeriodicFrameListArea);
|
delete_area(fPeriodicFrameListArea);
|
||||||
@ -181,7 +279,15 @@ EHCI::Start()
|
|||||||
TRACE(("usb_ehci: starting EHCI Host Controller\n"));
|
TRACE(("usb_ehci: starting EHCI Host Controller\n"));
|
||||||
TRACE(("usb_ehci: usbcmd: 0x%08x; usbsts: 0x%08x\n", ReadOpReg(EHCI_USBCMD), ReadOpReg(EHCI_USBSTS)));
|
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;
|
bool running = false;
|
||||||
for (int32 i = 0; i < 10; i++) {
|
for (int32 i = 0; i < 10; i++) {
|
||||||
@ -226,10 +332,108 @@ EHCI::SubmitTransfer(Transfer *transfer)
|
|||||||
if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
|
if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
|
||||||
return fRootHub->ProcessTransfer(this, transfer);
|
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;
|
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
|
status_t
|
||||||
EHCI::AddTo(Stack *stack)
|
EHCI::AddTo(Stack *stack)
|
||||||
{
|
{
|
||||||
@ -472,6 +676,11 @@ EHCI::SuspendPort(uint8 index)
|
|||||||
status_t
|
status_t
|
||||||
EHCI::ControllerReset()
|
EHCI::ControllerReset()
|
||||||
{
|
{
|
||||||
|
// halt the controller first
|
||||||
|
WriteOpReg(EHCI_USBCMD, 0);
|
||||||
|
snooze(10000);
|
||||||
|
|
||||||
|
// then reset it
|
||||||
WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET);
|
WriteOpReg(EHCI_USBCMD, EHCI_USBCMD_HCRESET);
|
||||||
|
|
||||||
int32 tries = 5;
|
int32 tries = 5;
|
||||||
@ -510,14 +719,58 @@ EHCI::InterruptHandler(void *data)
|
|||||||
int32
|
int32
|
||||||
EHCI::Interrupt()
|
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
|
status_t
|
||||||
EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
|
EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
|
||||||
ehci_qtd *firstDescriptor, ehci_qtd *dataDescriptor,
|
ehci_qtd *dataDescriptor, bool directionIn)
|
||||||
ehci_qtd *lastDescriptor, bool directionIn)
|
|
||||||
{
|
{
|
||||||
transfer_data *data = new(std::nothrow) transfer_data();
|
transfer_data *data = new(std::nothrow) transfer_data();
|
||||||
if (!data)
|
if (!data)
|
||||||
@ -525,9 +778,7 @@ EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
|
|||||||
|
|
||||||
data->transfer = transfer;
|
data->transfer = transfer;
|
||||||
data->queue_head = queueHead;
|
data->queue_head = queueHead;
|
||||||
data->first_descriptor = firstDescriptor;
|
|
||||||
data->data_descriptor = dataDescriptor;
|
data->data_descriptor = dataDescriptor;
|
||||||
data->last_descriptor = lastDescriptor;
|
|
||||||
data->incoming = directionIn;
|
data->incoming = directionIn;
|
||||||
data->link = NULL;
|
data->link = NULL;
|
||||||
|
|
||||||
@ -599,6 +850,8 @@ EHCI::CancelAllPendingTransfers()
|
|||||||
transfer = next;
|
transfer = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fFirstTransfer = NULL;
|
||||||
|
fLastTransfer = NULL;
|
||||||
Unlock();
|
Unlock();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -661,38 +914,298 @@ EHCI::FinishTransfers()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ehci_qtd *
|
ehci_qh *
|
||||||
EHCI::CreateDescriptor(Pipe *pipe, size_t bufferSize)
|
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
|
status_t
|
||||||
EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **firstDescriptor,
|
EHCI::LinkQueueHead(ehci_qh *queueHead)
|
||||||
ehci_qtd **lastDescriptor, size_t bufferSize)
|
{
|
||||||
|
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;
|
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
|
void
|
||||||
EHCI::FreeDescriptor(ehci_qtd *descriptor)
|
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
|
void
|
||||||
EHCI::FreeDescriptorChain(ehci_qtd *topDescriptor)
|
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
|
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,
|
EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
|
||||||
size_t vectorCount)
|
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,
|
EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
|
||||||
size_t vectorCount, uint8 *lastDataToggle)
|
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
|
size_t
|
||||||
EHCI::ReadActualLength(ehci_qtd *topDescriptor, uint8 *lastDataToggle)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,9 +22,7 @@ class EHCIRootHub;
|
|||||||
typedef struct transfer_data_s {
|
typedef struct transfer_data_s {
|
||||||
Transfer *transfer;
|
Transfer *transfer;
|
||||||
ehci_qh *queue_head;
|
ehci_qh *queue_head;
|
||||||
ehci_qtd *first_descriptor;
|
|
||||||
ehci_qtd *data_descriptor;
|
ehci_qtd *data_descriptor;
|
||||||
ehci_qtd *last_descriptor;
|
|
||||||
bool incoming;
|
bool incoming;
|
||||||
transfer_data_s *link;
|
transfer_data_s *link;
|
||||||
} transfer_data;
|
} transfer_data;
|
||||||
@ -37,6 +35,8 @@ public:
|
|||||||
|
|
||||||
status_t Start();
|
status_t Start();
|
||||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||||
|
status_t SubmitPeriodicTransfer(Transfer *transfer);
|
||||||
|
status_t SubmitAsyncTransfer(Transfer *transfer);
|
||||||
|
|
||||||
static status_t AddTo(Stack *stack);
|
static status_t AddTo(Stack *stack);
|
||||||
|
|
||||||
@ -61,9 +61,7 @@ static int32 InterruptHandler(void *data);
|
|||||||
// Transfer management
|
// Transfer management
|
||||||
status_t AddPendingTransfer(Transfer *transfer,
|
status_t AddPendingTransfer(Transfer *transfer,
|
||||||
ehci_qh *queueHead,
|
ehci_qh *queueHead,
|
||||||
ehci_qtd *firstDescriptor,
|
|
||||||
ehci_qtd *dataDescriptor,
|
ehci_qtd *dataDescriptor,
|
||||||
ehci_qtd *lastDescriptor,
|
|
||||||
bool directionIn);
|
bool directionIn);
|
||||||
status_t CancelPendingTransfer(Transfer *transfer);
|
status_t CancelPendingTransfer(Transfer *transfer);
|
||||||
status_t CancelAllPendingTransfers();
|
status_t CancelAllPendingTransfers();
|
||||||
@ -71,19 +69,38 @@ static int32 InterruptHandler(void *data);
|
|||||||
static int32 FinishThread(void *data);
|
static int32 FinishThread(void *data);
|
||||||
void FinishTransfers();
|
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
|
// Descriptor functions
|
||||||
ehci_qtd *CreateDescriptor(Pipe *pipe,
|
ehci_qtd *CreateDescriptor(size_t bufferSizeToAllocate,
|
||||||
size_t bufferSizeToAllocate);
|
uint8 pid);
|
||||||
status_t CreateDescriptorChain(Pipe *pipe,
|
status_t CreateDescriptorChain(Pipe *pipe,
|
||||||
ehci_qtd **firstDescriptor,
|
ehci_qtd **firstDescriptor,
|
||||||
ehci_qtd **lastDescriptor,
|
ehci_qtd **lastDescriptor,
|
||||||
size_t bufferSizeToAllocate);
|
ehci_qtd *strayDescriptor,
|
||||||
|
size_t bufferSizeToAllocate,
|
||||||
|
uint8 pid);
|
||||||
|
|
||||||
void FreeDescriptor(ehci_qtd *descriptor);
|
void FreeDescriptor(ehci_qtd *descriptor);
|
||||||
void FreeDescriptorChain(ehci_qtd *topDescriptor);
|
void FreeDescriptorChain(ehci_qtd *topDescriptor);
|
||||||
|
|
||||||
void LinkDescriptors(ehci_qtd *first,
|
void LinkDescriptors(ehci_qtd *first,
|
||||||
ehci_qtd *last);
|
ehci_qtd *last, ehci_qtd *alt);
|
||||||
|
|
||||||
size_t WriteDescriptorChain(ehci_qtd *topDescriptor,
|
size_t WriteDescriptorChain(ehci_qtd *topDescriptor,
|
||||||
iovec *vector, size_t vectorCount);
|
iovec *vector, size_t vectorCount);
|
||||||
@ -114,6 +131,9 @@ static pci_module_info *sPCIModule;
|
|||||||
area_id fPeriodicFrameListArea;
|
area_id fPeriodicFrameListArea;
|
||||||
addr_t *fPeriodicFrameList;
|
addr_t *fPeriodicFrameList;
|
||||||
|
|
||||||
|
// Async frame list
|
||||||
|
ehci_qh *fAsyncQueueHead;
|
||||||
|
|
||||||
// Maintain a linked list of transfers
|
// Maintain a linked list of transfers
|
||||||
transfer_data *fFirstTransfer;
|
transfer_data *fFirstTransfer;
|
||||||
transfer_data *fLastTransfer;
|
transfer_data *fLastTransfer;
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#define EHCI_USBSTS_PORTCHANGE (1 << 2) // Port Change Detected
|
#define EHCI_USBSTS_PORTCHANGE (1 << 2) // Port Change Detected
|
||||||
#define EHCI_USBSTS_USBERRINT (1 << 1) // USB Error Interrupt
|
#define EHCI_USBSTS_USBERRINT (1 << 1) // USB Error Interrupt
|
||||||
#define EHCI_USBSTS_USBINT (1 << 0) // USB Interrupt
|
#define EHCI_USBSTS_USBINT (1 << 0) // USB Interrupt
|
||||||
|
#define EHCI_USBSTS_INTMASK 0x3f
|
||||||
|
|
||||||
|
|
||||||
// USB Interrupt Enable Register (EHCI Spec 2.3.3)
|
// USB Interrupt Enable Register (EHCI Spec 2.3.3)
|
||||||
@ -96,9 +97,13 @@
|
|||||||
#define EHCI_PORTSC_DATAMASK 0xffffffd5
|
#define EHCI_PORTSC_DATAMASK 0xffffffd5
|
||||||
|
|
||||||
|
|
||||||
// PCI Registers
|
// Extended Capabilities
|
||||||
#define PCI_LEGSUP 0xc0 // PCI Legacy Support
|
#define EHCI_ECP_SHIFT 8 // Extended Capability Pointer
|
||||||
#define PCI_LEGSUP_USBPIRQDEN 0x2000 // USB PIRQ
|
#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)
|
// Data Structures (EHCI Spec 3)
|
||||||
@ -119,7 +124,7 @@ typedef struct {
|
|||||||
// Hardware Part
|
// Hardware Part
|
||||||
addr_t next_phy;
|
addr_t next_phy;
|
||||||
addr_t alt_next_phy;
|
addr_t alt_next_phy;
|
||||||
uint32 status_token;
|
uint32 token;
|
||||||
addr_t buffer_phy[5];
|
addr_t buffer_phy[5];
|
||||||
|
|
||||||
// Software Part
|
// Software Part
|
||||||
@ -132,15 +137,19 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
#define EHCI_QTD_TERMINATE (1 << 0)
|
#define EHCI_QTD_TERMINATE (1 << 0)
|
||||||
|
#define EHCI_QTD_DATA_TOGGLE (1 << 31)
|
||||||
#define EHCI_QTD_BYTES_SHIFT 16
|
#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_IOC (1 << 15)
|
||||||
#define EHCI_QTD_PAGE_SHIFT 12
|
#define EHCI_QTD_CPAGE_SHIFT 12
|
||||||
#define EHCI_QTD_PAGE_MASK 0x07
|
#define EHCI_QTD_CPAGE_MASK 0x07
|
||||||
#define EHCI_QTD_ERRCOUNT_SHIFT 10
|
#define EHCI_QTD_ERRCOUNT_SHIFT 10
|
||||||
#define EHCI_QTD_ERRCOUNT_MASK 0x03
|
#define EHCI_QTD_ERRCOUNT_MASK 0x03
|
||||||
#define EHCI_QTD_PID_SHIFT 8
|
#define EHCI_QTD_PID_SHIFT 8
|
||||||
#define EHCI_QTD_PID_MASK 0x03
|
#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_SHIFT 0
|
||||||
#define EHCI_QTD_STATUS_MASK 0x7f
|
#define EHCI_QTD_STATUS_MASK 0x7f
|
||||||
#define EHCI_QTD_STATUS_ACTIVE (1 << 7) // Active
|
#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_MISSED (1 << 2) // Missed Micro-Frame
|
||||||
#define EHCI_QTD_STATUS_SPLIT (1 << 1) // Split Transaction State
|
#define EHCI_QTD_STATUS_SPLIT (1 << 1) // Split Transaction State
|
||||||
#define EHCI_QTD_STATUS_PING (1 << 0) // Ping State
|
#define EHCI_QTD_STATUS_PING (1 << 0) // Ping State
|
||||||
|
#define EHCI_QTD_PAGE_MASK 0xfffff000
|
||||||
|
|
||||||
|
|
||||||
// Queue Head (QH, EHCI Spec 3.6)
|
// Queue Head (QH, EHCI Spec 3.6)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// Hardware Part
|
// Hardware Part
|
||||||
addr_t link_phy;
|
addr_t next_phy;
|
||||||
uint32 endpoint_chars;
|
uint32 endpoint_chars;
|
||||||
uint32 endpoint_caps;
|
uint32 endpoint_caps;
|
||||||
addr_t current_qtd_phy;
|
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
|
// Software Part
|
||||||
addr_t this_phy;
|
addr_t this_phy;
|
||||||
void *link_log;
|
void *next_log;
|
||||||
|
void *prev_log;
|
||||||
|
void *stray_log;
|
||||||
void *element_log;
|
void *element_log;
|
||||||
} ehci_qh;
|
} ehci_qh;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ static ehci_root_hub_string_s sEHCIRootHubStrings[3] = {
|
|||||||
|
|
||||||
|
|
||||||
EHCIRootHub::EHCIRootHub(Object *rootObject, int8 deviceAddress)
|
EHCIRootHub::EHCIRootHub(Object *rootObject, int8 deviceAddress)
|
||||||
: Hub(rootObject, sEHCIRootHubDevice, deviceAddress, false)
|
: Hub(rootObject, sEHCIRootHubDevice, deviceAddress, USB_SPEED_HIGHSPEED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ usb_hub_descriptor ohci_hubd =
|
|||||||
|
|
||||||
//Implementation
|
//Implementation
|
||||||
OHCIRootHub::OHCIRootHub( OHCI *ohci , int8 devicenum )
|
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;
|
m_ohci = ohci;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,8 @@ Queue::Queue(Stack *stack)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *physicalAddress;
|
void *physicalAddress;
|
||||||
fStatus = fStack->AllocateChunk((void **)&fQueueHead, &physicalAddress, 32);
|
fStatus = fStack->AllocateChunk((void **)&fQueueHead, &physicalAddress,
|
||||||
|
sizeof(uhci_qh));
|
||||||
if (fStatus < B_OK)
|
if (fStatus < B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -116,10 +117,11 @@ Queue::~Queue()
|
|||||||
Lock();
|
Lock();
|
||||||
benaphore_destroy(&fLock);
|
benaphore_destroy(&fLock);
|
||||||
|
|
||||||
fStack->FreeChunk(fQueueHead, (void *)fQueueHead->this_phy, 32);
|
fStack->FreeChunk(fQueueHead, (void *)fQueueHead->this_phy, sizeof(uhci_qh));
|
||||||
|
|
||||||
if (fStrayDescriptor)
|
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).
|
// descriptor in order to get some chipset to work nicely (like the PIIX).
|
||||||
void *physicalAddress;
|
void *physicalAddress;
|
||||||
status_t result = fStack->AllocateChunk((void **)&fStrayDescriptor,
|
status_t result = fStack->AllocateChunk((void **)&fStrayDescriptor,
|
||||||
&physicalAddress, 32);
|
&physicalAddress, sizeof(uhci_td));
|
||||||
if (result < B_OK) {
|
if (result < B_OK) {
|
||||||
TRACE_ERROR(("usb_uhci: failed to allocate a stray transfer descriptor\n"));
|
TRACE_ERROR(("usb_uhci: failed to allocate a stray transfer descriptor\n"));
|
||||||
return result;
|
return result;
|
||||||
@ -186,7 +188,7 @@ Queue::TerminateByStrayDescriptor()
|
|||||||
|
|
||||||
if (!Lock()) {
|
if (!Lock()) {
|
||||||
fStack->FreeChunk(fStrayDescriptor, (void *)fStrayDescriptor->this_phy,
|
fStack->FreeChunk(fStrayDescriptor, (void *)fStrayDescriptor->this_phy,
|
||||||
32);
|
sizeof(uhci_td));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,14 +1106,15 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, size_t bufferSize)
|
|||||||
uhci_td *result;
|
uhci_td *result;
|
||||||
void *physicalAddress;
|
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"));
|
TRACE_ERROR(("usb_uhci: failed to allocate a transfer descriptor\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
result->this_phy = (addr_t)physicalAddress;
|
result->this_phy = (addr_t)physicalAddress;
|
||||||
result->status = TD_STATUS_ACTIVE | TD_CONTROL_3_ERRORS | TD_CONTROL_SPD;
|
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->status |= TD_CONTROL_LOWSPEED;
|
||||||
|
|
||||||
result->buffer_size = bufferSize;
|
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,
|
if (fStack->AllocateChunk(&result->buffer_log, &result->buffer_phy,
|
||||||
bufferSize) < B_OK) {
|
bufferSize) < B_OK) {
|
||||||
TRACE_ERROR(("usb_uhci: unable to allocate space for the buffer\n"));
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1192,7 +1195,7 @@ UHCI::FreeDescriptor(uhci_td *descriptor)
|
|||||||
(void *)descriptor->buffer_phy, descriptor->buffer_size);
|
(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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ static uhci_root_hub_string_s sUHCIRootHubStrings[3] = {
|
|||||||
|
|
||||||
|
|
||||||
UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress)
|
UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress)
|
||||||
: Hub(rootObject, sUHCIRootHubDevice, deviceAddress, false)
|
: Hub(rootObject, sUHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user