* Implemented iovec based data handling in Transfer and UHCI

* Implemented QueueBulkV of the v3 API that uses it

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18540 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2006-08-20 01:07:15 +00:00
parent 5b0ec61f97
commit 1e8c0b3649
7 changed files with 148 additions and 46 deletions
@@ -207,6 +207,7 @@ Hub::Explore()
TRACE(("USB Hub Explore(): Device removed\n")); TRACE(("USB Hub Explore(): Device removed\n"));
if (fChildren[i]) { if (fChildren[i]) {
GetStack()->NotifyDeviceChange(fChildren[i], false); GetStack()->NotifyDeviceChange(fChildren[i], false);
GetStack()->PutUSBID(fChildren[i]->USBID());
delete fChildren[i]; delete fChildren[i];
fChildren[i] = NULL; fChildren[i] = NULL;
} }
@@ -184,6 +184,24 @@ BulkPipe::QueueBulk(void *data, size_t dataLength, usb_callback_func callback,
} }
status_t
BulkPipe::QueueBulkV(iovec *vector, size_t vectorCount,
usb_callback_func callback, void *callbackCookie)
{
Transfer *transfer = new(std::nothrow) Transfer(this);
if (!transfer)
return B_NO_MEMORY;
transfer->SetVector(vector, vectorCount);
transfer->SetCallback(callback, callbackCookie);
status_t result = SubmitTransfer(transfer);
if (result < B_OK)
delete transfer;
return result;
}
// //
// #pragma mark - // #pragma mark -
// //
@@ -11,8 +11,8 @@
Transfer::Transfer(Pipe *pipe) Transfer::Transfer(Pipe *pipe)
: fPipe(pipe), : fPipe(pipe),
fData(NULL), fVector(&fData),
fDataLength(0), fVectorCount(0),
fCallback(NULL), fCallback(NULL),
fCallbackCookie(NULL), fCallbackCookie(NULL),
fRequestData(NULL) fRequestData(NULL)
@@ -38,8 +38,29 @@ Transfer::SetRequestData(usb_request_data *data)
void void
Transfer::SetData(uint8 *data, size_t dataLength) Transfer::SetData(uint8 *data, size_t dataLength)
{ {
fData = data; fData.iov_base = data;
fDataLength = dataLength; fData.iov_len = dataLength;
if (data && dataLength > 0)
fVectorCount = 1;
}
void
Transfer::SetVector(iovec *vector, size_t vectorCount)
{
fVector = vector;
fVectorCount = vectorCount;
}
size_t
Transfer::VectorLength()
{
size_t length = 0;
for (int32 i = 0; i < fVectorCount; i++)
length += fVector[i].iov_len;
return length;
} }
@@ -55,5 +76,5 @@ void
Transfer::Finished(uint32 status, size_t actualLength) Transfer::Finished(uint32 status, size_t actualLength)
{ {
if (fCallback) if (fCallback)
fCallback(fCallbackCookie, status, fData, actualLength); fCallback(fCallbackCookie, status, fVector[0].iov_base, actualLength);
} }
+2 -1
View File
@@ -267,7 +267,8 @@ queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
return B_BAD_VALUE; return B_BAD_VALUE;
return B_ERROR; return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
callbackCookie);
} }
+15 -4
View File
@@ -300,6 +300,10 @@ virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_BULK_PIPE; };
size_t dataLength, size_t dataLength,
usb_callback_func callback, usb_callback_func callback,
void *callbackCookie); void *callbackCookie);
status_t QueueBulkV(iovec *vector,
size_t vectorCount,
usb_callback_func callback,
void *callbackCookie);
}; };
@@ -451,8 +455,13 @@ public:
usb_request_data *RequestData() { return fRequestData; }; usb_request_data *RequestData() { return fRequestData; };
void SetData(uint8 *buffer, size_t length); void SetData(uint8 *buffer, size_t length);
uint8 *Data() { return fData; }; uint8 *Data() { return (uint8 *)fData.iov_base; };
size_t DataLength() { return fDataLength; }; size_t DataLength() { return fData.iov_len; };
void SetVector(iovec *vector, size_t vectorCount);
iovec *Vector() { return fVector; };
size_t VectorCount() { return fVectorCount; };
size_t VectorLength();
void SetCallback(usb_callback_func callback, void SetCallback(usb_callback_func callback,
void *cookie); void *cookie);
@@ -462,8 +471,10 @@ public:
private: private:
// Data that is related to the transfer // Data that is related to the transfer
Pipe *fPipe; Pipe *fPipe;
uint8 *fData; iovec fData;
size_t fDataLength; iovec *fVector;
size_t fVectorCount;
usb_callback_func fCallback; usb_callback_func fCallback;
void *fCallbackCookie; void *fCallbackCookie;
+84 -34
View File
@@ -523,7 +523,7 @@ UHCI::SubmitTransfer(Transfer *transfer)
if (transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) if (transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE)
return SubmitRequest(transfer); return SubmitRequest(transfer);
if (!transfer->Data() || transfer->DataLength() == 0) if (transfer->VectorCount() == 0)
return B_BAD_VALUE; return B_BAD_VALUE;
Pipe *pipe = transfer->TransferPipe(); Pipe *pipe = transfer->TransferPipe();
@@ -533,7 +533,7 @@ UHCI::SubmitTransfer(Transfer *transfer)
uhci_td *lastDescriptor = NULL; uhci_td *lastDescriptor = NULL;
status_t result = CreateDescriptorChain(pipe, &firstDescriptor, status_t result = CreateDescriptorChain(pipe, &firstDescriptor,
&lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, &lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT,
transfer->DataLength()); transfer->VectorLength());
if (result < B_OK) if (result < B_OK)
return result; return result;
@@ -545,8 +545,8 @@ UHCI::SubmitTransfer(Transfer *transfer)
lastDescriptor->link_log = 0; lastDescriptor->link_log = 0;
if (!directionIn) { if (!directionIn) {
WriteDescriptorChain(firstDescriptor, transfer->Data(), WriteDescriptorChain(firstDescriptor, transfer->Vector(),
transfer->DataLength()); transfer->VectorCount());
} }
Queue *queue = fQueues[3]; Queue *queue = fQueues[3];
@@ -592,8 +592,10 @@ UHCI::SubmitRequest(Transfer *transfer)
return B_NO_MEMORY; return B_NO_MEMORY;
} }
WriteDescriptorChain(setupDescriptor, (const uint8 *)requestData, iovec vector;
sizeof(usb_request_data)); vector.iov_base = requestData;
vector.iov_len = sizeof(usb_request_data);
WriteDescriptorChain(setupDescriptor, &vector, 1);
statusDescriptor->status |= TD_CONTROL_IOC; statusDescriptor->status |= TD_CONTROL_IOC;
statusDescriptor->token |= TD_TOKEN_DATA1; statusDescriptor->token |= TD_TOKEN_DATA1;
@@ -601,11 +603,11 @@ UHCI::SubmitRequest(Transfer *transfer)
statusDescriptor->link_log = NULL; statusDescriptor->link_log = NULL;
uhci_td *dataDescriptor = NULL; uhci_td *dataDescriptor = NULL;
if (transfer->Data() && transfer->DataLength() > 0) { if (transfer->VectorCount() > 0) {
uhci_td *lastDescriptor = NULL; uhci_td *lastDescriptor = NULL;
status_t result = CreateDescriptorChain(pipe, &dataDescriptor, status_t result = CreateDescriptorChain(pipe, &dataDescriptor,
&lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT, &lastDescriptor, directionIn ? TD_TOKEN_IN : TD_TOKEN_OUT,
transfer->DataLength()); transfer->VectorLength());
if (result < B_OK) { if (result < B_OK) {
FreeDescriptor(setupDescriptor); FreeDescriptor(setupDescriptor);
@@ -614,8 +616,8 @@ UHCI::SubmitRequest(Transfer *transfer)
} }
if (!directionIn) { if (!directionIn) {
WriteDescriptorChain(dataDescriptor, transfer->Data(), WriteDescriptorChain(dataDescriptor, transfer->Vector(),
transfer->DataLength()); transfer->VectorCount());
} }
LinkDescriptors(setupDescriptor, dataDescriptor); LinkDescriptors(setupDescriptor, dataDescriptor);
@@ -759,8 +761,8 @@ UHCI::FinishTransfers()
// data to read out // data to read out
actualLength = ReadDescriptorChain( actualLength = ReadDescriptorChain(
transfer->data_descriptor, transfer->data_descriptor,
transfer->transfer->Data(), transfer->transfer->Vector(),
transfer->transfer->DataLength(), transfer->transfer->VectorCount(),
&lastDataToggle); &lastDataToggle);
} else { } else {
// read the actual length that was sent // read the actual length that was sent
@@ -1186,22 +1188,45 @@ UHCI::LinkDescriptors(uhci_td *first, uhci_td *second)
size_t size_t
UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer, UHCI::WriteDescriptorChain(uhci_td *topDescriptor, iovec *vector,
size_t bufferLength) size_t vectorCount)
{ {
size_t actualLength = 0;
uhci_td *current = topDescriptor; uhci_td *current = topDescriptor;
size_t actualLength = 0;
size_t vectorIndex = 0;
size_t vectorOffset = 0;
size_t bufferOffset = 0;
while (current) { while (current) {
if (!current->buffer_log) if (!current->buffer_log)
break; break;
size_t length = min_c(current->buffer_size, bufferLength); while (true) {
memcpy(current->buffer_log, buffer, length); size_t length = min_c(current->buffer_size - bufferOffset,
vector[vectorIndex].iov_len - vectorOffset);
bufferLength -= length; TRACE(("usb_uhci: copying %d bytes to bufferOffset %d from vectorOffset %d at index %d of %d\n", length, bufferOffset, vectorOffset, vectorIndex, vectorCount));
actualLength += length; memcpy((uint8 *)current->buffer_log + bufferOffset,
buffer += length; (uint8 *)vector[vectorIndex].iov_base + vectorOffset, length);
actualLength += length;
vectorOffset += length;
bufferOffset += length;
if (vectorOffset >= vector[vectorIndex].iov_len) {
if (++vectorIndex >= vectorCount) {
TRACE(("usb_uhci: wrote descriptor chain (%d bytes, no more vectors)\n", actualLength));
return actualLength;
}
vectorOffset = 0;
}
if (bufferOffset >= current->buffer_size) {
bufferOffset = 0;
break;
}
}
if (current->link_phy & TD_TERMINATE) if (current->link_phy & TD_TERMINATE)
break; break;
@@ -1215,28 +1240,53 @@ UHCI::WriteDescriptorChain(uhci_td *topDescriptor, const uint8 *buffer,
size_t size_t
UHCI::ReadDescriptorChain(uhci_td *topDescriptor, uint8 *buffer, UHCI::ReadDescriptorChain(uhci_td *topDescriptor, iovec *vector,
size_t bufferLength, uint8 *lastDataToggle) size_t vectorCount, uint8 *lastDataToggle)
{ {
size_t actualLength = 0;
uhci_td *current = topDescriptor;
uint8 dataToggle = 0; uint8 dataToggle = 0;
uhci_td *current = topDescriptor;
size_t actualLength = 0;
size_t vectorIndex = 0;
size_t vectorOffset = 0;
size_t bufferOffset = 0;
while (current && (current->status & TD_STATUS_ACTIVE) == 0) { while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
if (!current->buffer_log) if (!current->buffer_log)
break; break;
size_t length = (current->status & TD_STATUS_ACTLEN_MASK) + 1;
if (length == TD_STATUS_ACTLEN_NULL + 1)
length = 0;
length = min_c(length, bufferLength);
memcpy(buffer, current->buffer_log, length);
buffer += length;
bufferLength -= length;
actualLength += length;
dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01; dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01;
size_t bufferSize = (current->status & TD_STATUS_ACTLEN_MASK) + 1;
if (bufferSize == TD_STATUS_ACTLEN_NULL + 1)
bufferSize = 0;
while (true) {
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));
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_uhci: read descriptor chain (%d bytes, no more vectors)\n", actualLength));
if (lastDataToggle)
*lastDataToggle = dataToggle;
return actualLength;
}
vectorOffset = 0;
}
if (bufferOffset >= bufferSize) {
bufferOffset = 0;
break;
}
}
if (current->link_phy & TD_TERMINATE) if (current->link_phy & TD_TERMINATE)
break; break;
+2 -2
View File
@@ -116,9 +116,9 @@ static int32 FinishThread(void *data);
uhci_td *second); uhci_td *second);
size_t WriteDescriptorChain(uhci_td *topDescriptor, size_t WriteDescriptorChain(uhci_td *topDescriptor,
const uint8 *buffer, size_t bufferLength); iovec *vector, size_t vectorCount);
size_t ReadDescriptorChain(uhci_td *topDescriptor, size_t ReadDescriptorChain(uhci_td *topDescriptor,
uint8 *buffer, size_t bufferLength, iovec *vector, size_t vectorCount,
uint8 *lastDataToggle); uint8 *lastDataToggle);
size_t ReadActualLength(uhci_td *topDescriptor, size_t ReadActualLength(uhci_td *topDescriptor,
uint8 *lastDataToggle); uint8 *lastDataToggle);