mirror of
https://github.com/reactos/reactos.git
synced 2025-07-25 02:34:07 +00:00
[USBOHCI]
- Check if the transfer descriptors reported errors and propagate the error in the urb status field - OHCI now reports error which the class driver are handling - Allocate device descriptor from non paged pool to prevent possible alignment problems - Fix checking of completed transfer descriptors - Fix double freeing of descriptors - Cleanup endpoints when the halted bit is set by the host controllers - Check for the endpoint direction in the data descriptor - Setup descriptor needs buffer rounding set svn path=/branches/usb-bringup-trunk/; revision=55389
This commit is contained in:
parent
b1587061be
commit
4cbccecd5c
6 changed files with 203 additions and 21 deletions
|
@ -1457,6 +1457,8 @@ InterruptServiceRoutine(
|
||||||
// the interrupt was not caused by DoneHead update
|
// the interrupt was not caused by DoneHead update
|
||||||
// check if something important happened
|
// check if something important happened
|
||||||
//
|
//
|
||||||
|
DPRINT1("InterruptStatus %x InterruptEnable %x\n", READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)),
|
||||||
|
READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET)));
|
||||||
Status = READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)) & READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET)) & (~OHCI_WRITEBACK_DONE_HEAD);
|
Status = READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)) & READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET)) & (~OHCI_WRITEBACK_DONE_HEAD);
|
||||||
if (Status == 0)
|
if (Status == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -239,7 +239,8 @@ typedef struct _OHCI_ENDPOINT_DESCRIPTOR
|
||||||
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
|
#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000
|
||||||
#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
|
#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000
|
||||||
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
|
#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000
|
||||||
|
#define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc
|
||||||
|
#define OHCI_ENDPOINT_HALTED 0x00000001
|
||||||
//
|
//
|
||||||
// Maximum port count set by OHCI
|
// Maximum port count set by OHCI
|
||||||
//
|
//
|
||||||
|
|
|
@ -1763,8 +1763,13 @@ CHubController::HandleClassInterface(
|
||||||
//
|
//
|
||||||
// assert on failure
|
// assert on failure
|
||||||
//
|
//
|
||||||
PC_ASSERT(NT_SUCCESS(Status));
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// display error
|
||||||
|
//
|
||||||
|
DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
|
|
|
@ -598,11 +598,24 @@ CUSBDevice::CreateDeviceDescriptor()
|
||||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PVOID DeviceDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate descriptor page aligned
|
||||||
|
//
|
||||||
|
DeviceDescriptor = ExAllocatePool(NonPagedPool, PAGE_SIZE);
|
||||||
|
if (!DeviceDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// zero descriptor
|
// zero descriptor
|
||||||
//
|
//
|
||||||
RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
RtlZeroMemory(DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||||
RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
|
RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -616,7 +629,7 @@ CUSBDevice::CreateDeviceDescriptor()
|
||||||
//
|
//
|
||||||
// allocate mdl describing the device descriptor
|
// allocate mdl describing the device descriptor
|
||||||
//
|
//
|
||||||
Mdl = IoAllocateMdl(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR), FALSE, FALSE, 0);
|
Mdl = IoAllocateMdl(DeviceDescriptor, PAGE_SIZE, FALSE, FALSE, 0);
|
||||||
if (!Mdl)
|
if (!Mdl)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -642,12 +655,22 @@ CUSBDevice::CreateDeviceDescriptor()
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// copy back device descriptor
|
||||||
|
//
|
||||||
|
RtlCopyMemory(&m_DeviceDescriptor, DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||||
|
|
||||||
//
|
//
|
||||||
// informal dbg print
|
// informal dbg print
|
||||||
//
|
//
|
||||||
DumpDeviceDescriptor(&m_DeviceDescriptor);
|
DumpDeviceDescriptor(&m_DeviceDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// free item
|
||||||
|
//
|
||||||
|
ExFreePool(DeviceDescriptor);
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
//
|
//
|
||||||
|
|
|
@ -363,7 +363,7 @@ CUSBQueue::FindTransferDescriptorInEndpoint(
|
||||||
//
|
//
|
||||||
// check if the transfer descriptor is inside the list
|
// check if the transfer descriptor is inside the list
|
||||||
//
|
//
|
||||||
if (IsTransferDescriptorInEndpoint(EndpointDescriptor, TransferDescriptorLogicalAddress))
|
if ((EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HEAD_MASK) == EndpointDescriptor->TailPhysicalDescriptor || (EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// found endpoint
|
// found endpoint
|
||||||
|
@ -584,13 +584,6 @@ CUSBQueue::CleanupEndpointDescriptor(
|
||||||
//
|
//
|
||||||
Request->FreeEndpointDescriptor(EndpointDescriptor);
|
Request->FreeEndpointDescriptor(EndpointDescriptor);
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME: check if complete
|
|
||||||
//
|
|
||||||
//ASSERT(Request->IsRequestComplete());
|
|
||||||
|
|
||||||
Request->FreeEndpointDescriptor(EndpointDescriptor);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// release request
|
// release request
|
||||||
//
|
//
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount);
|
NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount);
|
||||||
UCHAR GetEndpointAddress();
|
UCHAR GetEndpointAddress();
|
||||||
USHORT GetMaxPacketSize();
|
USHORT GetMaxPacketSize();
|
||||||
|
VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor);
|
||||||
|
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
CUSBRequest(IUnknown *OuterUnknown){}
|
CUSBRequest(IUnknown *OuterUnknown){}
|
||||||
|
@ -968,7 +970,6 @@ CUSBRequest::AllocateEndpointDescriptor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: detect type
|
// FIXME: detect type
|
||||||
//
|
//
|
||||||
|
@ -1269,7 +1270,37 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
//
|
//
|
||||||
// initialize data descriptor
|
// initialize data descriptor
|
||||||
//
|
//
|
||||||
DataDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING| 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_DIRECTION_PID_IN;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME verify short packets are ok
|
||||||
|
//
|
||||||
|
//DataDescriptor->Flags |= OHCI_TD_BUFFER_ROUNDING;
|
||||||
|
|
||||||
//
|
//
|
||||||
// store physical address of buffer
|
// store physical address of buffer
|
||||||
|
@ -1282,7 +1313,7 @@ CUSBRequest::BuildControlTransferDescriptor(
|
||||||
//
|
//
|
||||||
// initialize setup descriptor
|
// initialize setup descriptor
|
||||||
//
|
//
|
||||||
SetupDescriptor->Flags = 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);
|
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);
|
||||||
|
|
||||||
if (m_SetupPacket)
|
if (m_SetupPacket)
|
||||||
{
|
{
|
||||||
|
@ -1560,6 +1591,134 @@ CUSBRequest::FreeEndpointDescriptor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CUSBRequest::CheckError(
|
||||||
|
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
||||||
|
{
|
||||||
|
POHCI_GENERAL_TD TransferDescriptor;
|
||||||
|
ULONG ConditionCode;
|
||||||
|
PURB Urb;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// set status code
|
||||||
|
//
|
||||||
|
m_NtStatusCode = STATUS_SUCCESS;
|
||||||
|
m_UrbStatusCode = USBD_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
|
if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: handle isochronous support
|
||||||
|
//
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get first general transfer descriptor
|
||||||
|
//
|
||||||
|
TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor;
|
||||||
|
|
||||||
|
while(TransferDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// the descriptor must have been processed
|
||||||
|
//
|
||||||
|
ASSERT(OHCI_TD_GET_CONDITION_CODE(TransferDescriptor->Flags) != OHCI_TD_CONDITION_NOT_ACCESSED);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get condition code
|
||||||
|
//
|
||||||
|
ConditionCode = OHCI_TD_GET_CONDITION_CODE(TransferDescriptor->Flags);
|
||||||
|
if (ConditionCode != OHCI_TD_CONDITION_NO_ERROR)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME status code
|
||||||
|
//
|
||||||
|
m_NtStatusCode = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
switch(ConditionCode)
|
||||||
|
{
|
||||||
|
case OHCI_TD_CONDITION_CRC_ERROR:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_CRC_ERROR detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_CRC;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_BIT_STUFFING:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_BIT_STUFFING detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_BTSTUFF;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_TOGGLE_MISMATCH:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_TOGGLE_MISMATCH detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_DATA_TOGGLE_MISMATCH;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_STALL:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_STALL detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_STALL_PID;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_NO_RESPONSE:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_NO_RESPONSE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_DEV_NOT_RESPONDING;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_PID_CHECK_FAILURE:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_PID_CHECK_FAILURE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_PID_CHECK_FAILURE;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_UNEXPECTED_PID:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_UNEXPECTED_PID detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_UNEXPECTED_PID;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_DATA_OVERRUN:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_DATA_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_DATA_OVERRUN;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_DATA_UNDERRUN:
|
||||||
|
if (m_Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get urb
|
||||||
|
//
|
||||||
|
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
||||||
|
|
||||||
|
if(Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// short packets are ok
|
||||||
|
//
|
||||||
|
ASSERT(Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER);
|
||||||
|
m_NtStatusCode = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_DATA_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_DATA_UNDERRUN;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_BUFFER_OVERRUN:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_BUFFER_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_BUFFER_OVERRUN;
|
||||||
|
break;
|
||||||
|
case OHCI_TD_CONDITION_BUFFER_UNDERRUN:
|
||||||
|
DPRINT1("OHCI_TD_CONDITION_BUFFER_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor);
|
||||||
|
m_UrbStatusCode = USBD_STATUS_BUFFER_UNDERRUN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get next
|
||||||
|
//
|
||||||
|
TransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
CUSBRequest::CompletionCallback(
|
CUSBRequest::CompletionCallback(
|
||||||
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor)
|
||||||
|
@ -1570,17 +1729,16 @@ CUSBRequest::CompletionCallback(
|
||||||
DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
|
DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
|
||||||
|
|
||||||
//
|
//
|
||||||
// set status code
|
// check for errors
|
||||||
//
|
//
|
||||||
m_NtStatusCode = STATUS_SUCCESS;
|
CheckError(OutDescriptor);
|
||||||
m_UrbStatusCode = USBD_STATUS_SUCCESS;
|
|
||||||
|
|
||||||
if (m_Irp)
|
if (m_Irp)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// set irp completion status
|
// set irp completion status
|
||||||
//
|
//
|
||||||
m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME
|
m_Irp->IoStatus.Status = m_NtStatusCode;
|
||||||
|
|
||||||
//
|
//
|
||||||
// get current irp stack location
|
// get current irp stack location
|
||||||
|
@ -1595,7 +1753,7 @@ CUSBRequest::CompletionCallback(
|
||||||
//
|
//
|
||||||
// store urb status
|
// store urb status
|
||||||
//
|
//
|
||||||
Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME
|
Urb->UrbHeader.Status = m_UrbStatusCode;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if the MDL was created
|
// Check if the MDL was created
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue