I set all of the static variables to 'volatile'. The reset now succeeds! Yet, device configuration still fails. Here is the code responsible for transaction:
Code: Select all
void EHCI::Private::PerformTransaction(dword AsyncAddress)
{
EHCI::Private::OpRegister->USBSTS.USBINT = 1;
EHCI::Private::USBInterrupt = false;
EHCI::Private::OpRegister->ASYNCLISTADDR = VirtualMemory::PhysicalAddress(AsyncAddress);
EHCI::Private::OpRegister->USBCMD.AsynchronousScheduleEnable = 1;
while (EHCI::Private::OpRegister->USBSTS.AsynchronousScheduleStatus == 0)
{
PIT::WaitMilliseconds(5);
}
while (!EHCI::Private::USBInterrupt)
{
PIT::WaitMilliseconds(5);
}
EHCI::Private::USBInterrupt = false;
EHCI::Private::OpRegister->USBCMD.AsynchronousScheduleEnable = 0;
while (EHCI::Private::OpRegister->USBSTS.AsynchronousScheduleStatus == 1)
{
PIT::WaitMilliseconds(5);
}
return;
}
EHCI::Private::QTD* EHCI::Private::AllocateQTD(dword next)
{
EHCI::Private::QTD* qtd = (EHCI::Private::QTD*)Heap::Malloc(sizeof(EHCI::Private::QTD), 32);
memset(qtd, 0, sizeof(EHCI::Private::QTD));
if (next == 0)
qtd->NextQTDPointer = 1;
else
qtd->NextQTDPointer = VirtualMemory::PhysicalAddress(next);
return qtd;
}
dword EHCI::Private::AllocateQTDBuffer(EHCI::Private::QTD* qtd)
{
void* data = Heap::Malloc(4096, 4096);
memset(data, 0, 4096);
qtd->BufferPointer0 = VirtualMemory::PhysicalAddress((dword)data);
qtd->BufferPointer1 = qtd->BufferPointer2 = qtd->BufferPointer3 = qtd->BufferPointer4 = 0;
return (dword)data;
}
void EHCI::Private::CreateQueueHead(void* QHAddr, dword HorizontalPointer, void* FirstQTD, byte DeviceAddr, byte EndpointNum, dword MaxPacketSize)
{
EHCI::Private::QueueHead* qh = (EHCI::Private::QueueHead*)QHAddr;
memset(QHAddr, 0, sizeof(EHCI::Private::QueueHead));
qh->HorizontalPointer = VirtualMemory::PhysicalAddress(HorizontalPointer) | 2;
qh->DeviceAddress = DeviceAddr;
qh->InactivateOnNextTransaction = 0;
qh->EndpointNumber = EndpointNum;
qh->EndpointSpeed = 2;
qh->DTC = 1;
qh->H = 1;
qh->MaximumPacketLength = MaxPacketSize;
qh->ControlEndpointFlag = 0;
qh->NakReloadFlag = 15;
qh->SMask = 0;
qh->CMask = 0;
qh->HubAddr = 0;
qh->PortNumber = 0;
qh->Mult = 1;
if (FirstQTD == 0)
{
qh->QTD.NextQTDPointer = 1;
}
else
{
qh->QTD.NextQTDPointer = VirtualMemory::PhysicalAddress((dword)FirstQTD);
}
}
void* EHCI::Private::CreateSetupQTD(dword next, bool toggle, dword tokenBytes, dword type, dword requestID, dword valueLo, dword valueHi, dword index, dword length, dword* buff)
{
byte SETUP = 2;
EHCI::Private::QTD* qtd = EHCI::Private::AllocateQTD(next);
qtd->AlternateNextQTDPointer = 1;
qtd->Token.Status = 0x80;
qtd->Token.PIDCode = 2;
qtd->Token.ErrorCounter = 3;
qtd->Token.CurrentPage = 0;
qtd->Token.InterruptOnComplete = 1;
qtd->Token.TotalBytestoTransfer = tokenBytes;
qtd->Token.DataToggle = toggle;
dword buffer = EHCI::Private::AllocateQTDBuffer(qtd);
EHCI::Private::SetupData* request = (EHCI::Private::SetupData*)buffer;
request->RequestType = type;
request->RequestID = requestID;
request->ValueHi = valueHi;
request->ValueLow = valueLo;
request->Index = index;
request->Length = length;
*buff = buffer;
return (void*)qtd;
}
void* EHCI::Private::CreateIOQTD(dword next, byte direction, bool toggle, dword tokenBytes, dword *buff)
{
byte OUT = 0;
byte IN = 1;
EHCI::Private::QTD* qtd = EHCI::Private::AllocateQTD(next);
qtd->AlternateNextQTDPointer = 1;
qtd->Token.Status = 0x80;
qtd->Token.PIDCode = direction;
qtd->Token.ErrorCounter = 3;
qtd->Token.CurrentPage = 0;
qtd->Token.InterruptOnComplete = 1;
qtd->Token.TotalBytestoTransfer = tokenBytes;
qtd->Token.DataToggle = toggle;
dword buffer = EHCI::Private::AllocateQTDBuffer(qtd);
*buff = buffer;
return (void*)qtd;
}
byte EHCI::SetupTransaction(byte DevAddr, byte EndpointNum, word BytesToTransfer, byte RequestType, byte Request, byte ValueHi, byte ValueLow, word Index, byte* Data, byte direction, byte port)
{
byte OUT = 0;
byte IN = 1;
byte SETUP = 2;
void* virtAList = Heap::Malloc(sizeof(EHCI::Private::QueueHead), 32);
EHCI::Private::OpRegister->USBCMD.AsynchronousScheduleEnable = 0;
dword SetupBuffer = 0;
dword DataBuffer = 0;
if (BytesToTransfer == 0)
{
void* HandShakeQTD = 0;
HandShakeQTD = EHCI::Private::CreateIOQTD(0, IN, 1, 0, &DataBuffer);
Heap::Free((void*)DataBuffer);
void* SetupQTD = EHCI::Private::CreateSetupQTD((dword)HandShakeQTD, 0, 8, RequestType, Request, ValueLow, ValueHi, Index, 0, &SetupBuffer);
EHCI::Private::CreateQueueHead(virtAList, (dword)virtAList, SetupQTD, DevAddr, EndpointNum, 64);
EHCI::Private::PerformTransaction((dword)virtAList);
if ((((EHCI::Private::QTD*)SetupQTD)->Token.Status) != 0)
{
Video::Print("\nQTD Status: ");
Video::PrintNumber(((EHCI::Private::QTD*)SetupQTD)->Token.Status, 10);
Video::NewLine();
}
if (((EHCI::Private::QTD*)SetupQTD)->Token.Status != 0)
{
Video::Print("\nTransaction Error!!\n");
Heap::Free((void*)SetupBuffer);
Heap::Free((void*)virtAList);
Heap::Free((void*)HandShakeQTD);
Heap::Free((void*)SetupQTD);
return 0;
}
Heap::Free((void*)SetupBuffer);
Heap::Free((void*)virtAList);
Heap::Free((void*)HandShakeQTD);
Heap::Free((void*)SetupQTD);
return 1;
}
void* HandShakeQTD = 0;
if (direction == IN)
{
HandShakeQTD = EHCI::Private::CreateIOQTD(0, OUT, 1, 0, &DataBuffer);
}
else
{
HandShakeQTD = EHCI::Private::CreateIOQTD(0, IN, 1, 0, &DataBuffer);
}
Heap::Free((void*)DataBuffer);
void* DataQTD = EHCI::Private::CreateIOQTD((dword)HandShakeQTD, direction, 1, BytesToTransfer, &DataBuffer);
if (direction == OUT)
{
memcpy((void*)DataBuffer, Data, BytesToTransfer);
}
void* SetupQTD = EHCI::Private::CreateSetupQTD((dword)DataQTD, 0, 8, RequestType, Request, ValueLow, ValueHi, Index, BytesToTransfer, &SetupBuffer);
EHCI::Private::CreateQueueHead(virtAList, (dword)virtAList, SetupQTD, DevAddr, EndpointNum, 64);
EHCI::Private::PerformTransaction((dword)virtAList);
if (direction == IN)
{
memcpy(Data, (void*)DataBuffer, BytesToTransfer);
}
if ((((EHCI::Private::QTD*)SetupQTD)->Token.Status) != 0)
{
Video::Print("\nQTD Status: ");
Video::PrintNumber(((EHCI::Private::QTD*)SetupQTD)->Token.Status, 10);
Video::NewLine();
}
if (((EHCI::Private::QTD*)SetupQTD)->Token.Status != 0)
{
Video::Print("\nTransaction Error!!\n");
Heap::Free((void*)SetupBuffer);
Heap::Free((void*)DataBuffer);
Heap::Free((void*)virtAList);
Heap::Free((void*)HandShakeQTD);
Heap::Free((void*)DataQTD);
Heap::Free((void*)SetupQTD);
return 0;
}
Heap::Free((void*)SetupBuffer);
Heap::Free((void*)DataBuffer);
Heap::Free((void*)virtAList);
Heap::Free((void*)HandShakeQTD);
Heap::Free((void*)DataQTD);
Heap::Free((void*)SetupQTD);
return 1;
}