* Move the actual and maximum length calculation into two inline functions.

* Use those to make sure the size is retrieved correctly in all cases (which
  it wasn't in the short packet tests).
* Don't detect short packets for control transfers as we need the status packet
  to finish the transfer and cannot quit earlier.
* Only check for short packets when we also have the short packet flag set.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30710 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2009-05-11 22:35:50 +00:00
parent b8bc570a12
commit aa3ca9ed30
2 changed files with 30 additions and 17 deletions
+10 -17
View File
@@ -684,8 +684,8 @@ UHCI::ProcessDebugTransfer(Transfer *transfer)
} }
if ((descriptor->link_phy & TD_TERMINATE) if ((descriptor->link_phy & TD_TERMINATE)
|| (descriptor->status & TD_STATUS_ACTLEN_MASK) || uhci_td_actual_length(descriptor)
< (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT)) { < uhci_td_maximum_length(descriptor)) {
transferOK = true; transferOK = true;
break; break;
} }
@@ -1295,8 +1295,9 @@ UHCI::FinishTransfers()
} }
if ((descriptor->link_phy & TD_TERMINATE) if ((descriptor->link_phy & TD_TERMINATE)
|| (descriptor->status & TD_STATUS_ACTLEN_MASK) || ((descriptor->status & TD_CONTROL_SPD) != 0
< (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT)) { && uhci_td_actual_length(descriptor)
< uhci_td_maximum_length(descriptor))) {
// all descriptors are done, or we have a short packet // all descriptors are done, or we have a short packet
TRACE("td (0x%08lx) ok\n", descriptor->this_phy); TRACE("td (0x%08lx) ok\n", descriptor->this_phy);
callbackStatus = B_OK; callbackStatus = B_OK;
@@ -1903,7 +1904,8 @@ UHCI::CreateDescriptor(Pipe *pipe, uint8 direction, size_t bufferSize)
result->status |= TD_CONTROL_ISOCHRONOUS; result->status |= TD_CONTROL_ISOCHRONOUS;
else { else {
result->status |= TD_CONTROL_3_ERRORS; result->status |= TD_CONTROL_3_ERRORS;
if (direction == TD_TOKEN_IN) if (direction == TD_TOKEN_IN
&& (pipe->Type() & USB_OBJECT_CONTROL_PIPE) == 0)
result->status |= TD_CONTROL_SPD; result->status |= TD_CONTROL_SPD;
} }
if (pipe->Speed() == USB_SPEED_LOWSPEED) if (pipe->Speed() == USB_SPEED_LOWSPEED)
@@ -2086,9 +2088,7 @@ UHCI::ReadDescriptorChain(uhci_td *topDescriptor, iovec *vector,
break; break;
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; size_t bufferSize = uhci_td_actual_length(current);
if (bufferSize == TD_STATUS_ACTLEN_NULL + 1)
bufferSize = 0;
while (true) { while (true) {
size_t length = min_c(bufferSize - bufferOffset, size_t length = min_c(bufferSize - bufferOffset,
@@ -2144,11 +2144,7 @@ UHCI::ReadActualLength(uhci_td *topDescriptor, uint8 *lastDataToggle)
uint8 dataToggle = 0; uint8 dataToggle = 0;
while (current && (current->status & TD_STATUS_ACTIVE) == 0) { while (current && (current->status & TD_STATUS_ACTIVE) == 0) {
size_t length = (current->status & TD_STATUS_ACTLEN_MASK) + 1; actualLength += uhci_td_actual_length(current);
if (length == TD_STATUS_ACTLEN_NULL + 1)
length = 0;
actualLength += length;
dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01; dataToggle = (current->token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01;
if (current->link_phy & TD_TERMINATE) if (current->link_phy & TD_TERMINATE)
@@ -2191,10 +2187,7 @@ UHCI::ReadIsochronousDescriptorChain(isochronous_transfer_data *transfer,
uhci_td *current = transfer->descriptors[i]; uhci_td *current = transfer->descriptors[i];
size_t bufferSize = current->buffer_size; size_t bufferSize = current->buffer_size;
size_t actualLength = (current->status & TD_STATUS_ACTLEN_MASK) + 1; size_t actualLength = uhci_td_actual_length(current);
if (actualLength == TD_STATUS_ACTLEN_NULL + 1)
actualLength = 0;
isochronousData->packet_descriptors[i].actual_length = actualLength; isochronousData->packet_descriptors[i].actual_length = actualLength;
@@ -140,6 +140,26 @@ typedef struct
#define TD_LINK_MASK 0xfffffff0 #define TD_LINK_MASK 0xfffffff0
static inline size_t
uhci_td_maximum_length(uhci_td *descriptor)
{
size_t length = (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT) + 1;
if (length == TD_STATUS_ACTLEN_NULL + 1)
return 0;
return length;
}
static inline size_t
uhci_td_actual_length(uhci_td *descriptor)
{
size_t length = (descriptor->status & TD_STATUS_ACTLEN_MASK) + 1;
if (length == TD_STATUS_ACTLEN_NULL + 1)
return 0;
return length;
}
// Represents a Queue Head (QH) // Represents a Queue Head (QH)
typedef struct typedef struct
{ {