From abe8e8a2c2ebef2a46252a5f1bf904b4cc18ce3c Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 19 Aug 2009 04:45:02 +0000 Subject: [PATCH] A try at actual data toggle handling. Since we do not properly ensure that the toggle carry stays valid, we better make sure we set it correctly. Additionally even if the toggle carry wasn't clobbered, there are conditions the toggle is reset without the controller being able to notice (as in clearing a halt state). Since I don't have any OHCI hardware this is untested, but should fix bug #4067 if correct. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32510 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/busses/usb/ohci.cpp | 23 ++++++++++++++++------- src/add-ons/kernel/busses/usb/ohci.h | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp b/src/add-ons/kernel/busses/usb/ohci.cpp index c67e3f5a62..ceb708fcde 100644 --- a/src/add-ons/kernel/busses/usb/ohci.cpp +++ b/src/add-ons/kernel/busses/usb/ohci.cpp @@ -1033,6 +1033,11 @@ OHCI::_FinishTransfers() transfer->data_descriptor); } + // get the last data toggle and store it for next time + transfer->transfer->TransferPipe()->SetDataToggle( + (transfer->endpoint->head_physical_descriptor + & OHCI_ENDPOINT_TOGGLE_CARRY) == 0); + if (transfer->transfer->IsFragmented()) { // this transfer may still have data left TRACE("advancing fragmented transfer\n"); @@ -1109,8 +1114,9 @@ OHCI::_SubmitRequest(Transfer *transfer) ohci_general_td *dataDescriptor = NULL; if (transfer->VectorCount() > 0) { ohci_general_td *lastDescriptor = NULL; - result = _CreateDescriptorChain(&dataDescriptor, &lastDescriptor, - directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT, + result = _CreateDescriptorChain(transfer->TransferPipe(), + &dataDescriptor, &lastDescriptor, directionIn + ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT, transfer->VectorLength()); if (result < B_OK) { _FreeGeneralDescriptor(setupDescriptor); @@ -1158,8 +1164,9 @@ OHCI::_SubmitTransfer(Transfer *transfer) ohci_general_td *firstDescriptor = NULL; ohci_general_td *lastDescriptor = NULL; - status_t result = _CreateDescriptorChain(&firstDescriptor, &lastDescriptor, - directionIn ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT, + status_t result = _CreateDescriptorChain(pipe, &firstDescriptor, + &lastDescriptor, directionIn + ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT, transfer->VectorLength()); if (result < B_OK) @@ -1514,7 +1521,7 @@ OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor) status_t -OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor, +OHCI::_CreateDescriptorChain(Pipe *pipe, ohci_general_td **_firstDescriptor, ohci_general_td **_lastDescriptor, uint32 direction, size_t bufferSize) { size_t blockSize = 8192; @@ -1522,6 +1529,7 @@ OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor, if (descriptorCount == 0) descriptorCount = 1; + bool dataToggle = pipe->DataToggle(); ohci_general_td *firstDescriptor = NULL; ohci_general_td *lastDescriptor = *_firstDescriptor; for (int32 i = 0; i < descriptorCount; i++) { @@ -1536,13 +1544,14 @@ OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor, descriptor->flags = direction | OHCI_TD_BUFFER_ROUNDING | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) - | OHCI_TD_TOGGLE_CARRY - | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE); + | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) + | (dataToggle ? OHCI_TD_TOGGLE_1 : OHCI_TD_TOGGLE_0); // link to previous if (lastDescriptor) _LinkDescriptors(lastDescriptor, descriptor); + dataToggle = !dataToggle; bufferSize -= blockSize; lastDescriptor = descriptor; if (!firstDescriptor) diff --git a/src/add-ons/kernel/busses/usb/ohci.h b/src/add-ons/kernel/busses/usb/ohci.h index b23ce6f46e..97a31ff973 100644 --- a/src/add-ons/kernel/busses/usb/ohci.h +++ b/src/add-ons/kernel/busses/usb/ohci.h @@ -101,7 +101,7 @@ static int32 _FinishThread(void *data); void _FreeGeneralDescriptor( ohci_general_td *descriptor); - status_t _CreateDescriptorChain( + status_t _CreateDescriptorChain(Pipe *pipe, ohci_general_td **firstDescriptor, ohci_general_td **lastDescriptor, uint32 direction,