Author: janderwald Date: Fri Feb 3 09:52:29 2012 New Revision: 55389
URL: http://svn.reactos.org/svn/reactos?rev=55389&view=rev Log: [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
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.h branches/usb-bringup-trunk/drivers/usb/usbohci/hub_controller.cpp branches/usb-bringup-trunk/drivers/usb/usbohci/usb_device.cpp branches/usb-bringup-trunk/drivers/usb/usbohci/usb_queue.cpp branches/usb-bringup-trunk/drivers/usb/usbohci/usb_request.cpp
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.cpp [iso-8859-1] Fri Feb 3 09:52:29 2012 @@ -1457,6 +1457,8 @@ // the interrupt was not caused by DoneHead update // 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); if (Status == 0) {
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.h [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbohci/hardware.h [iso-8859-1] Fri Feb 3 09:52:29 2012 @@ -239,7 +239,8 @@ #define OHCI_ENDPOINT_DIRECTION_IN 0x00001000 #define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000 #define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000 - +#define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc +#define OHCI_ENDPOINT_HALTED 0x00000001 // // Maximum port count set by OHCI //
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/hub_controller.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbohci/hub_controller.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbohci/hub_controller.cpp [iso-8859-1] Fri Feb 3 09:52:29 2012 @@ -1763,8 +1763,13 @@ // // 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
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/usb_device.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbohci/usb_device.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbohci/usb_device.cpp [iso-8859-1] Fri Feb 3 09:52:29 2012 @@ -598,11 +598,24 @@ USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; PMDL Mdl; NTSTATUS Status; + PVOID DeviceDescriptor; + + // + // allocate descriptor page aligned + // + DeviceDescriptor = ExAllocatePool(NonPagedPool, PAGE_SIZE); + if (!DeviceDescriptor) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + }
// // zero descriptor // - RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); + RtlZeroMemory(DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
// @@ -616,7 +629,7 @@ // // 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) { // @@ -643,10 +656,20 @@ if (NT_SUCCESS(Status)) { // + // copy back device descriptor + // + RtlCopyMemory(&m_DeviceDescriptor, DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); + + // // informal dbg print // DumpDeviceDescriptor(&m_DeviceDescriptor); } + + // + // free item + // + ExFreePool(DeviceDescriptor);
// // done
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/usb_queue.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbohci/usb_queue.cpp [iso-8859-1] Fri Feb 3 09:52:29 2012 @@ -363,7 +363,7 @@ // // 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 @@ -585,13 +585,6 @@ Request->FreeEndpointDescriptor(EndpointDescriptor);
// - // FIXME: check if complete - // - //ASSERT(Request->IsRequestComplete()); - - Request->FreeEndpointDescriptor(EndpointDescriptor); - - // // release request // Request->Release();
Modified: branches/usb-bringup-trunk/drivers/usb/usbohci/usb_request.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbohci/usb_request.cpp [iso-8859-1] Fri Feb 3 09:52:29 2012 @@ -64,6 +64,8 @@ NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount); UCHAR GetEndpointAddress(); USHORT GetMaxPacketSize(); + VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor); +
// constructor / destructor CUSBRequest(IUnknown *OuterUnknown){} @@ -968,7 +970,6 @@
}
- // // FIXME: detect type // @@ -1269,7 +1270,37 @@ // // 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 @@ -1282,7 +1313,7 @@ // // 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) { @@ -1561,6 +1592,134 @@ }
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 CUSBRequest::CompletionCallback( struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) { @@ -1570,17 +1729,16 @@ DPRINT("CUSBRequest::CompletionCallback Descriptor %p PhysicalAddress %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart);
// - // set status code - // - m_NtStatusCode = STATUS_SUCCESS; - m_UrbStatusCode = USBD_STATUS_SUCCESS; + // check for errors + // + CheckError(OutDescriptor);
if (m_Irp) { // // set irp completion status // - m_Irp->IoStatus.Status = STATUS_SUCCESS; //FIXME + m_Irp->IoStatus.Status = m_NtStatusCode;
// // get current irp stack location @@ -1595,7 +1753,7 @@ // // store urb status // - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; //FIXME + Urb->UrbHeader.Status = m_UrbStatusCode;
// // Check if the MDL was created