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
This commit is contained in:
parent
75c92c56f6
commit
abe8e8a2c2
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user