[USBOHCI]

- Set endpoint direction indicator for control transfers
- Mask Version bits when printing out version
- Implement function for dumping endpoint descriptor
- Implement retrieving pid direction from setup packet
- Flip the pid direction for the status descriptor when data is transferred
- Return packet size 8 when using the control pipe
- OHCI control transfer hang is gone 
- OHCI control should now work and attached HID devices finish initialization

svn path=/trunk/; revision=55574
This commit is contained in:
Johannes Anderwald 2012-02-13 13:39:20 +00:00
parent 6fe02c8f47
commit 6c35ffefb5
4 changed files with 103 additions and 86 deletions

View file

@ -329,7 +329,7 @@ CUSBHardwareDevice::PnpStart(
//
Version = READ_REGISTER_ULONG((PULONG)((ULONG_PTR)ResourceBase + OHCI_REVISION_OFFSET));
DPRINT("Version %x\n", Version);
DPRINT("Version %x\n", Version & 0xFFFF);
//
// Store Resource base

View file

@ -241,7 +241,8 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
#define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc
#define OHCI_ENDPOINT_HALTED 0x00000001
#define OHCI_ENDPOINT_HALTED 0x00000001
#define OHCI_ENDPOINT_DIRECTION_DESCRIPTOR 0x00000000
//
// Maximum port count set by OHCI
//

View file

@ -285,7 +285,7 @@ CUSBQueue::AddUSBRequest(
m_Hardware->GetCurrentFrameNumber(&FrameNumber);
DPRINT("Hardware 1ms %p Iso %p\n",m_InterruptEndpoints[0], m_IsoHeadEndpointDescriptor);
ASSERT(m_InterruptEndpoints[0]->NextPhysicalEndpoint == m_IsoHeadEndpointDescriptor->PhysicalAddress.LowPart);
ASSERT(m_InterruptEndpoints[0]->NextPhysicalEndpoint == m_IsoHeadEndpointDescriptor->PhysicalAddress.LowPart);
PrintEndpointList(m_IsoHeadEndpointDescriptor);
}

View file

@ -48,7 +48,6 @@ public:
virtual VOID FreeEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
virtual UCHAR GetInterval();
// local functions
ULONG InternalGetTransferType();
UCHAR InternalGetPidDirection();
@ -65,6 +64,7 @@ public:
UCHAR GetEndpointAddress();
USHORT GetMaxPacketSize();
VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
VOID DumpEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR *Descriptor);
// constructor / destructor
@ -460,9 +460,10 @@ CUSBRequest::GetMaxPacketSize()
if (!m_EndpointDescriptor)
{
//
// control request
// FIXME: use DeviceDescriptor.bMaxPacketSize0
// control pipe request
//
return 0;
return 8;
}
ASSERT(m_Irp);
@ -541,16 +542,23 @@ CUSBRequest::InternalGetTransferType()
UCHAR
CUSBRequest::InternalGetPidDirection()
{
ASSERT(m_Irp);
ASSERT(m_EndpointDescriptor);
//
// end point is defined in the low byte of bEndpointAddress
//
return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
if (m_EndpointDescriptor)
{
//
// end point direction is highest bit in bEndpointAddress
//
return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
}
else
{
//
// request arrives on the control pipe, extract direction from setup packet
//
ASSERT(m_SetupPacket);
return (m_SetupPacket->bmRequestType.B >> 7);
}
}
//----------------------------------------------------------------------------------------
UCHAR
CUSBRequest::GetDeviceAddress()
@ -983,7 +991,13 @@ CUSBRequest::AllocateEndpointDescriptor(
//
Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_IN;
}
}
else
{
//
// get it from transfer descriptor
//
Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR;
}
//
@ -1230,6 +1244,35 @@ CUSBRequest::BuildBulkInterruptEndpoint(
return STATUS_SUCCESS;
}
VOID
CUSBRequest::DumpEndpointDescriptor(
POHCI_ENDPOINT_DESCRIPTOR Descriptor)
{
ULONG Count = 0;
POHCI_GENERAL_TD GeneralDescriptor;
DPRINT1("EndpointDescriptor %p Addr %x\n", Descriptor, Descriptor->PhysicalAddress.LowPart);
DPRINT1("EndpointDescriptor HeadPhysicalDescriptor %x HeadLogicalDescriptor %p\n", Descriptor->HeadPhysicalDescriptor, Descriptor->HeadLogicalDescriptor);
DPRINT1("EndpointDescriptor TailPhysicalDescriptor %x\n", Descriptor->TailPhysicalDescriptor);
DPRINT1("EndpointDescriptor NextDescriptor %x\n", Descriptor->NextDescriptor);
DPRINT1("EndpointDescriptor NextPhysicalEndpoint %x\n", Descriptor->NextPhysicalEndpoint);
DPRINT1("EndpointDescriptor Flags %x\n", Descriptor->Flags);
GeneralDescriptor = (POHCI_GENERAL_TD)Descriptor->HeadLogicalDescriptor;
while(GeneralDescriptor)
{
DPRINT1("Descriptor %d Address %p Addr %x\n", Count, GeneralDescriptor, GeneralDescriptor->PhysicalAddress);
DPRINT1("Descriptor %d BufferLogical %p BufferPhysical %x\n", Count, GeneralDescriptor->BufferLogical, GeneralDescriptor->BufferPhysical);
DPRINT1("Descriptor %d BufferSize %d\n", Count, GeneralDescriptor->BufferSize);
DPRINT1("Descriptor %d LastPhysicalByteAddress %x\n", Count, GeneralDescriptor->LastPhysicalByteAddress);
DPRINT1("Descriptor %d Flags %x\n", Count, GeneralDescriptor->Flags);
DPRINT1("Descriptor %d NextLogicalDescriptor %p NextPhysicalDescriptor %x\n", Count, GeneralDescriptor->NextLogicalDescriptor, GeneralDescriptor->NextPhysicalDescriptor);
Count++;
GeneralDescriptor = (POHCI_GENERAL_TD)GeneralDescriptor->NextLogicalDescriptor;
}
}
NTSTATUS
CUSBRequest::BuildControlTransferDescriptor(
@ -1293,6 +1336,31 @@ CUSBRequest::BuildControlTransferDescriptor(
return Status;
}
//
// initialize setup descriptor
//
SetupDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING | OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
//
// initialize status descriptor
//
StatusDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
if (m_SetupPacket)
{
//
// copy setup packet
//
RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
}
else
{
//
// generate setup packet from urb
//
ASSERT(FALSE);
}
if (m_TransferBufferLength)
{
//
@ -1312,7 +1380,6 @@ CUSBRequest::BuildControlTransferDescriptor(
m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR));
FreeDescriptor(SetupDescriptor);
FreeDescriptor(StatusDescriptor);
FreeDescriptor(LastDescriptor);
return Status;
}
@ -1321,30 +1388,10 @@ CUSBRequest::BuildControlTransferDescriptor(
//
DataDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY | OHCI_TD_TOGGLE_1;
if (m_EndpointDescriptor)
{
if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->bEndpointAddress))
{
//
// direction out
//
DataDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
}
else
{
//
// direction in
//
DataDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
}
}
else
{
//
// no end point address provided - assume its an in direction
//
DataDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
}
//
// setup pid direction
//
DataDescriptor->Flags |= InternalGetPidDirection() == TRUE ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT;
//
// use short packets
@ -1355,53 +1402,13 @@ CUSBRequest::BuildControlTransferDescriptor(
// store physical address of buffer
//
DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart;
DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
}
DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1;
//
// initialize setup descriptor
//
SetupDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING | OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);
//
// flip status pid direction
//
StatusDescriptor->Flags |= InternalGetPidDirection() == TRUE ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN;
if (m_SetupPacket)
{
//
// copy setup packet
//
RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
}
else
{
//
// generate setup packet from urb
//
ASSERT(FALSE);
}
//
// initialize status descriptor
//
StatusDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE);
if (m_TransferBufferLength == 0)
{
//
// input direction is flipped for the status descriptor
//
StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
}
else
{
//
// output direction is flipped for the status descriptor
//
StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_OUT;
}
//
// now link the descriptors
//
if (m_TransferBufferLength)
{
//
// link setup descriptor to data descriptor
//
@ -1423,12 +1430,16 @@ CUSBRequest::BuildControlTransferDescriptor(
}
else
{
//
// status descriptor is always in
//
StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN;
//
// link setup descriptor to status descriptor
//
SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart;
SetupDescriptor->NextLogicalDescriptor = StatusDescriptor;
//
// link status descriptor to last descriptor
//
@ -1448,6 +1459,11 @@ CUSBRequest::BuildControlTransferDescriptor(
//
*OutEndpointDescriptor = EndpointDescriptor;
//
// dump descriptor
//
//DumpEndpointDescriptor(EndpointDescriptor);
//
// done
//