* Fixing my previous attempt at fixing cookie handling. Device addresses cannot be used, since there may be devices with the same address across different busses. A linked list of usb_driver_cookies is maintained now that relates devices and cookies.

* Fixed endpoint halt clearing. The data toggle has to be reset when we clear a stall.
* Now using up to B_PAGE_SIZE * 4 sized buffers in EHCI. They are split automatically by the host controller. This further pushes throughput.
* Optimize memory allocator settings for the above case. Enlarging it's managed space to 1MB
* Ignore the transaction error bit in EHCI. It is only of informational character as it also idicates errors that were recovered automatically. If an unrecoverable error occures, other bits will indicate this.
* Fixed some more print formats in debug output.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18915 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2006-09-24 15:30:04 +00:00
parent 9f6275e0e4
commit 8a278a1bb7
9 changed files with 85 additions and 51 deletions

View File

@ -350,12 +350,11 @@ Device::DeviceDescriptor() const
status_t
Device::ReportDevice(usb_support_descriptor *supportDescriptors,
uint32 supportDescriptorCount, const usb_notify_hooks *hooks,
void *cookies[], bool added)
usb_driver_cookie **cookies, bool added)
{
TRACE(("USB Device ReportDevice\n"));
if ((added && hooks->device_added == NULL)
|| (!added && hooks->device_removed == NULL)
|| (!added && cookies[fDeviceAddress] == NULL))
|| (!added && hooks->device_removed == NULL))
return B_BAD_VALUE;
bool supported = false;
@ -397,16 +396,31 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
}
if (supported) {
usb_id id = USBID();
if (added) {
status_t result = hooks->device_added(USBID(), &cookies[fDeviceAddress]);
if (result != B_OK)
cookies[fDeviceAddress] = NULL;
usb_driver_cookie *cookie = new(std::nothrow) usb_driver_cookie;
status_t result = hooks->device_added(id, &cookie->cookie);
cookie->device = id;
cookie->link = *cookies;
*cookies = cookie;
return result;
}
hooks->device_removed(cookies[fDeviceAddress]);
cookies[fDeviceAddress] = NULL;
return B_OK;
usb_driver_cookie **pointer = cookies;
usb_driver_cookie *cookie = *cookies;
while (cookie) {
if (cookie->device == id)
break;
pointer = &cookie->link;
cookie = cookie->link;
}
if (cookie) {
hooks->device_removed(cookie->cookie);
*pointer = cookie->link;
delete cookie;
return B_OK;
}
}
return B_UNSUPPORTED;

View File

@ -256,7 +256,7 @@ Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
status_t
Hub::ReportDevice(usb_support_descriptor *supportDescriptors,
uint32 supportDescriptorCount, const usb_notify_hooks *hooks,
void *cookies[], bool added)
usb_driver_cookie **cookies, bool added)
{
TRACE(("USB Hub ReportDevice\n"));

View File

@ -62,6 +62,10 @@ Pipe::SetFeature(uint16 selector)
status_t
Pipe::ClearFeature(uint16 selector)
{
// clearing a stalled condition resets the data toggle
if (selector == USB_FEATURE_ENDPOINT_HALT)
SetDataToggle(false);
return ((Device *)Parent())->DefaultPipe()->SendRequest(
USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT,
USB_REQUEST_CLEAR_FEATURE,

View File

@ -32,7 +32,7 @@ Stack::Stack()
memset(fObjectArray, 0, objectArraySize);
fAllocator = new(std::nothrow) PhysicalMemoryAllocator("USB Stack Allocator",
8, B_PAGE_SIZE * 4, 50);
8, B_PAGE_SIZE * 4, 64);
if (!fAllocator) {
TRACE_ERROR(("usb stack: failed to allocate the allocator\n"));
return;
@ -233,7 +233,7 @@ Stack::NotifyDeviceChange(Device *device, bool added)
|| (!added && element->notify_hooks.device_removed != NULL)) {
status_t result = device->ReportDevice(element->support_descriptors,
element->support_descriptor_count,
&element->notify_hooks, element->cookies, added);
&element->notify_hooks, &element->cookies, added);
if (result == B_OK) {
const char *name = element->driver_name;
@ -268,9 +268,9 @@ Stack::RegisterDriver(const char *driverName,
memcpy(info->support_descriptors, descriptors, descriptorsSize);
info->support_descriptor_count = descriptorCount;
memset(info->cookies, 0, sizeof(void *) * 128);
info->notify_hooks.device_added = NULL;
info->notify_hooks.device_removed = NULL;
info->cookies = NULL;
info->link = NULL;
if (!Lock()) {
@ -310,7 +310,7 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
// Report device will recurse down the whole tree
rootHub->ReportDevice(element->support_descriptors,
element->support_descriptor_count, hooks,
element->cookies, true);
&element->cookies, true);
}
}
@ -342,7 +342,7 @@ Stack::UninstallNotify(const char *driverName)
if (rootHub)
rootHub->ReportDevice(element->support_descriptors,
element->support_descriptor_count,
&element->notify_hooks, element->cookies, false);
&element->notify_hooks, &element->cookies, false);
}
element->notify_hooks.device_added = NULL;

View File

@ -42,13 +42,20 @@ struct host_controller_info {
};
struct usb_driver_cookie {
usb_id device;
void *cookie;
usb_driver_cookie *link;
};
struct usb_driver_info {
const char *driver_name;
usb_support_descriptor *support_descriptors;
uint32 support_descriptor_count;
const char *republish_driver_name;
usb_notify_hooks notify_hooks;
void *cookies[128];
usb_driver_cookie *cookies;
usb_driver_info *link;
};
@ -385,7 +392,8 @@ virtual status_t ReportDevice(
usb_support_descriptor *supportDescriptors,
uint32 supportDescriptorCount,
const usb_notify_hooks *hooks,
void *cookies[], bool added);
usb_driver_cookie **cookies,
bool added);
virtual status_t BuildDeviceName(char *string,
uint32 *index, size_t bufferSize,
Device *device);
@ -436,7 +444,8 @@ virtual status_t ReportDevice(
usb_support_descriptor *supportDescriptors,
uint32 supportDescriptorCount,
const usb_notify_hooks *hooks,
void *cookies[], bool added);
usb_driver_cookie **cookies,
bool added);
virtual status_t BuildDeviceName(char *string,
uint32 *index, size_t bufferSize,
Device *device);

View File

@ -942,6 +942,12 @@ EHCI::FinishTransfers()
if (acquire_sem(fFinishTransfersSem) < B_OK)
continue;
// eat up sems that have been released by multiple interrupts
int32 semCount = 0;
get_sem_count(fFinishTransfersSem, &semCount);
if (semCount > 0)
acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
if (!Lock())
continue;
@ -993,7 +999,7 @@ EHCI::FinishTransfers()
TRACE(("usb_ehci: qtd (0x%08lx) done\n", descriptor->this_phy));
size_t actualLength = 0;
uint8 lastDataToggle = 0;
bool nextDataToggle = false;
if (transfer->data_descriptor && transfer->incoming) {
// data to read out
iovec *vector = transfer->transfer->Vector();
@ -1019,7 +1025,7 @@ EHCI::FinishTransfers()
actualLength = ReadDescriptorChain(
transfer->data_descriptor,
vector, vectorCount,
&lastDataToggle);
&nextDataToggle);
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
if (clonedArea >= B_OK)
@ -1029,11 +1035,11 @@ EHCI::FinishTransfers()
// calculate transfered length
actualLength = ReadActualLength(
(ehci_qtd *)transfer->queue_head->element_log,
&lastDataToggle);
&nextDataToggle);
}
UnlinkQueueHead(transfer->queue_head, &freeListHead);
transfer->transfer->TransferPipe()->SetDataToggle(lastDataToggle);
transfer->transfer->TransferPipe()->SetDataToggle(nextDataToggle);
transfer->transfer->Finished(B_USB_STATUS_SUCCESS, actualLength);
transferDone = true;
break;
@ -1324,7 +1330,7 @@ EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor,
ehci_qtd **_lastDescriptor, ehci_qtd *strayDescriptor, size_t bufferSize,
uint8 pid)
{
size_t packetSize = pipe->MaxPacketSize();
size_t packetSize = B_PAGE_SIZE * 4;
int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize;
bool dataToggle = pipe->DataToggle();
@ -1345,7 +1351,6 @@ EHCI::CreateDescriptorChain(Pipe *pipe, ehci_qtd **_firstDescriptor,
if (lastDescriptor)
LinkDescriptors(lastDescriptor, descriptor, strayDescriptor);
dataToggle = !dataToggle;
bufferSize -= packetSize;
lastDescriptor = descriptor;
if (!firstDescriptor)
@ -1456,7 +1461,7 @@ EHCI::WriteDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
size_t
EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
size_t vectorCount, uint8 *lastDataToggle)
size_t vectorCount, bool *nextDataToggle)
{
uint32 dataToggle = 0;
ehci_qtd *current = topDescriptor;
@ -1487,8 +1492,7 @@ EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
if (vectorOffset >= vector[vectorIndex].iov_len) {
if (++vectorIndex >= vectorCount) {
TRACE(("usb_ehci: read descriptor chain (%ld bytes, no more vectors)\n", actualLength));
if (lastDataToggle)
*lastDataToggle = dataToggle > 0 ? 1 : 0;
*nextDataToggle = dataToggle > 0 ? true : false;
return actualLength;
}
@ -1508,14 +1512,13 @@ EHCI::ReadDescriptorChain(ehci_qtd *topDescriptor, iovec *vector,
}
TRACE(("usb_ehci: read descriptor chain (%ld bytes)\n", actualLength));
if (lastDataToggle)
*lastDataToggle = dataToggle > 0 ? 1 : 0;
*nextDataToggle = dataToggle > 0 ? true : false;
return actualLength;
}
size_t
EHCI::ReadActualLength(ehci_qtd *topDescriptor, uint8 *lastDataToggle)
EHCI::ReadActualLength(ehci_qtd *topDescriptor, bool *nextDataToggle)
{
size_t actualLength = 0;
ehci_qtd *current = topDescriptor;
@ -1534,8 +1537,7 @@ EHCI::ReadActualLength(ehci_qtd *topDescriptor, uint8 *lastDataToggle)
}
TRACE(("usb_ehci: read actual length (%ld bytes)\n", actualLength));
if (lastDataToggle)
*lastDataToggle = dataToggle > 0 ? 1 : 0;
*nextDataToggle = dataToggle > 0 ? true : false;
return actualLength;
}

View File

@ -107,9 +107,9 @@ static int32 FinishThread(void *data);
iovec *vector, size_t vectorCount);
size_t ReadDescriptorChain(ehci_qtd *topDescriptor,
iovec *vector, size_t vectorCount,
uint8 *lastDataToggle);
bool *nextDataToggle);
size_t ReadActualLength(ehci_qtd *topDescriptor,
uint8 *lastDataToggle);
bool *nextDataToggle);
// Operational register functions
inline void WriteOpReg(uint32 reg, uint32 value);

View File

@ -153,7 +153,7 @@ typedef struct {
#define EHCI_QTD_PID_SETUP 0x02
#define EHCI_QTD_STATUS_SHIFT 0
#define EHCI_QTD_STATUS_MASK 0x7f
#define EHCI_QTD_STATUS_ERRMASK 0x78
#define EHCI_QTD_STATUS_ERRMASK 0x70
#define EHCI_QTD_STATUS_ACTIVE (1 << 7) // Active
#define EHCI_QTD_STATUS_HALTED (1 << 6) // Halted
#define EHCI_QTD_STATUS_BUFFER (1 << 5) // Data Buffer Error

View File

@ -67,7 +67,7 @@ void
print_descriptor_chain(uhci_td *descriptor)
{
while (descriptor) {
dprintf("ph: 0x%08x; lp: 0x%08x; vf: %s; q: %s; t: %s; st: 0x%08x; to: 0x%08x\n",
dprintf("ph: 0x%08lx; lp: 0x%08lx; vf: %s; q: %s; t: %s; st: 0x%08lx; to: 0x%08lx\n",
descriptor->this_phy & 0xffffffff, descriptor->link_phy & 0xfffffff0,
descriptor->link_phy & 0x4 ? "y" : "n",
descriptor->link_phy & 0x2 ? "qh" : "td",
@ -301,8 +301,8 @@ Queue::PrintToStream()
{
#ifdef TRACE_USB
dprintf("USB UHCI Queue:\n");
dprintf("link phy: 0x%08x; link type: %s; terminate: %s\n", fQueueHead->link_phy & 0xfff0, fQueueHead->link_phy & 0x0002 ? "QH" : "TD", fQueueHead->link_phy & 0x0001 ? "yes" : "no");
dprintf("elem phy: 0x%08x; elem type: %s; terminate: %s\n", fQueueHead->element_phy & 0xfff0, fQueueHead->element_phy & 0x0002 ? "QH" : "TD", fQueueHead->element_phy & 0x0001 ? "yes" : "no");
dprintf("link phy: 0x%08lx; link type: %s; terminate: %s\n", fQueueHead->link_phy & 0xfff0, fQueueHead->link_phy & 0x0002 ? "QH" : "TD", fQueueHead->link_phy & 0x0001 ? "yes" : "no");
dprintf("elem phy: 0x%08lx; elem type: %s; terminate: %s\n", fQueueHead->element_phy & 0xfff0, fQueueHead->element_phy & 0x0002 ? "QH" : "TD", fQueueHead->element_phy & 0x0001 ? "yes" : "no");
dprintf("elements:\n");
print_descriptor_chain(fQueueTop);
#endif
@ -476,7 +476,7 @@ UHCI::Start()
bool running = false;
for (int32 i = 0; i < 10; i++) {
uint16 status = ReadReg16(UHCI_USBSTS);
TRACE(("usb_uhci: current loop %u, status 0x%04x\n", i, status));
TRACE(("usb_uhci: current loop %ld, status 0x%04x\n", i, status));
if (status & UHCI_USBSTS_HCHALT)
snooze(10000);
@ -515,12 +515,11 @@ UHCI::Start()
status_t
UHCI::SubmitTransfer(Transfer *transfer)
{
TRACE(("usb_uhci: submit transfer called for device %d\n", transfer->TransferPipe()->DeviceAddress()));
// Short circuit the root hub
if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
return fRootHub->ProcessTransfer(this, transfer);
TRACE(("usb_uhci: submit transfer called for device %d\n", transfer->TransferPipe()->DeviceAddress()));
if (transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE)
return SubmitRequest(transfer);
@ -740,10 +739,16 @@ UHCI::FinishTransfers()
if (acquire_sem(fFinishTransfersSem) < B_OK)
continue;
// eat up sems that have been released by multiple interrupts
int32 semCount = 0;
get_sem_count(fFinishTransfersSem, &semCount);
if (semCount > 0)
acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
if (!Lock())
continue;
TRACE(("usb_uhci: finishing transfers (first transfer: 0x%08x; last transfer: 0x%08x)\n", fFirstTransfer, fLastTransfer));
TRACE(("usb_uhci: finishing transfers (first transfer: 0x%08lx; last transfer: 0x%08lx)\n", (uint32)fFirstTransfer, (uint32)fLastTransfer));
transfer_data *lastTransfer = NULL;
transfer_data *transfer = fFirstTransfer;
Unlock();
@ -755,7 +760,7 @@ UHCI::FinishTransfers()
while (descriptor) {
uint32 status = descriptor->status;
if (status & TD_STATUS_ACTIVE) {
TRACE(("usb_uhci: td (0x%08x) still active\n", descriptor->this_phy));
TRACE(("usb_uhci: td (0x%08lx) still active\n", descriptor->this_phy));
// still in progress
break;
}
@ -789,7 +794,7 @@ UHCI::FinishTransfers()
if (descriptor == transfer->last_descriptor
|| (descriptor->status & TD_STATUS_ACTLEN_MASK)
< (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT)) {
TRACE(("usb_uhci: td (0x%08x) ok\n", descriptor->this_phy));
TRACE(("usb_uhci: td (0x%08lx) ok\n", descriptor->this_phy));
// we got through without errors so we are finished
transfer->queue->RemoveDescriptorChain(
transfer->first_descriptor,
@ -1317,7 +1322,7 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, iovec *vector,
size_t length = min_c(current->buffer_size - bufferOffset,
vector[vectorIndex].iov_len - vectorOffset);
TRACE(("usb_uhci: copying %d bytes to bufferOffset %d from vectorOffset %d at index %d of %d\n", length, bufferOffset, vectorOffset, vectorIndex, vectorCount));
TRACE(("usb_uhci: copying %ld bytes to bufferOffset %ld from vectorOffset %ld at index %ld of %ld\n", length, bufferOffset, vectorOffset, vectorIndex, vectorCount));
memcpy((uint8 *)current->buffer_log + bufferOffset,
(uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
@ -1327,7 +1332,7 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, iovec *vector,
if (vectorOffset >= vector[vectorIndex].iov_len) {
if (++vectorIndex >= vectorCount) {
TRACE(("usb_uhci: wrote descriptor chain (%d bytes, no more vectors)\n", actualLength));
TRACE(("usb_uhci: wrote descriptor chain (%ld bytes, no more vectors)\n", actualLength));
return actualLength;
}
@ -1346,7 +1351,7 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, iovec *vector,
current = (uhci_td *)current->link_log;
}
TRACE(("usb_uhci: wrote descriptor chain (%d bytes)\n", actualLength));
TRACE(("usb_uhci: wrote descriptor chain (%ld bytes)\n", actualLength));
return actualLength;
}
@ -1375,7 +1380,7 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, iovec *vector,
size_t length = min_c(bufferSize - bufferOffset,
vector[vectorIndex].iov_len - vectorOffset);
TRACE(("usb_uhci: copying %d bytes to vectorOffset %d from bufferOffset %d at index %d of %d\n", length, vectorOffset, bufferOffset, vectorIndex, vectorCount));
TRACE(("usb_uhci: copying %ld bytes to vectorOffset %ld from bufferOffset %ld at index %ld of %ld\n", length, vectorOffset, bufferOffset, vectorIndex, vectorCount));
memcpy((uint8 *)vector[vectorIndex].iov_base + vectorOffset,
(uint8 *)current->buffer_log + bufferOffset, length);
@ -1385,7 +1390,7 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, iovec *vector,
if (vectorOffset >= vector[vectorIndex].iov_len) {
if (++vectorIndex >= vectorCount) {
TRACE(("usb_uhci: read descriptor chain (%d bytes, no more vectors)\n", actualLength));
TRACE(("usb_uhci: read descriptor chain (%ld bytes, no more vectors)\n", actualLength));
if (lastDataToggle)
*lastDataToggle = dataToggle;
return actualLength;
@ -1409,7 +1414,7 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, iovec *vector,
if (lastDataToggle)
*lastDataToggle = dataToggle;
TRACE(("usb_uhci: read descriptor chain (%d bytes)\n", actualLength));
TRACE(("usb_uhci: read descriptor chain (%ld bytes)\n", actualLength));
return actualLength;
}
@ -1438,7 +1443,7 @@ UHCI::ReadActualLength(uhci_td *topDescriptor, uint8 *lastDataToggle)
if (lastDataToggle)
*lastDataToggle = dataToggle;
TRACE(("usb_uhci: read actual length (%d bytes)\n", actualLength));
TRACE(("usb_uhci: read actual length (%ld bytes)\n", actualLength));
return actualLength;
}