Author: janderwald Date: Fri Feb 10 20:15:39 2012 New Revision: 55530
URL: http://svn.reactos.org/svn/reactos?rev=55530&view=rev Log: [USBEHCI] - Partly revert 55516, as the memory bug got fixed
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -1339,6 +1339,7 @@ // controller reported error // DPRINT1("CStatus %x\n", CStatus); + ASSERT(FALSE); }
//
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/hardware.h [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -148,7 +148,7 @@
//Software ULONG PhysicalAddr; - LIST_ENTRY LinkedDescriptors; + LIST_ENTRY DescriptorEntry; ULONG TotalBytesToTransfer; } QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
@@ -216,9 +216,21 @@ //Software ULONG PhysicalAddr; LIST_ENTRY LinkedQueueHeads; + LIST_ENTRY TransferDescriptorListHead; PVOID Request; } QUEUE_HEAD, *PQUEUE_HEAD;
+C_ASSERT(sizeof(END_POINT_CHARACTERISTICS) == 4); +C_ASSERT(sizeof(END_POINT_CAPABILITIES) == 4); + +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, HorizontalLinkPointer) == 0x00); +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCharacteristics) == 0x04); +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCapabilities) == 0x08); +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, CurrentLinkPointer) == 0xC); +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, NextPointer) == 0x10); +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, AlternateNextPointer) == 0x14); +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, Token) == 0x18); +C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, BufferPointer) == 0x1C); C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, PhysicalAddr) == 0x30);
@@ -292,3 +304,4 @@ ULONG PortChange; }EHCI_PORT_STATUS;
+
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/hub_controller.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -70,6 +70,9 @@ NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb); + NTSTATUS HandleClearStall(IN OUT PIRP Irp, PURB Urb); + NTSTATUS HandleSyncResetAndClearStall(IN OUT PIRP Irp, PURB Urb); + NTSTATUS HandleAbortPipe(IN OUT PIRP Irp, PURB Urb);
friend VOID StatusChangeEndpointCallBack(PVOID Context);
@@ -1675,12 +1678,21 @@ // // initialize setup packet // - CtrlSetup.bmRequestType.B = 0xa2; //FIXME: Const. + CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const. CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
+ if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN) + { + // + // data direction is device to host + // + CtrlSetup.bmRequestType.B |= 0x80; + } + + // // issue request // @@ -1697,6 +1709,185 @@ // return Status; } + +NTSTATUS +CHubController::HandleSyncResetAndClearStall( + IN OUT PIRP Irp, + IN OUT PURB Urb) +{ + NTSTATUS Status = STATUS_SUCCESS; + PUSB_ENDPOINT EndpointDescriptor; + ULONG Type; + + // + // sanity check + // + PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); + PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST)); + PC_ASSERT(Urb->UrbPipeRequest.PipeHandle); + + // + // check if this is a valid usb device handle + // + if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) + { + DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle); + + // + // invalid device handle + // + return STATUS_DEVICE_NOT_CONNECTED; + } + + // + // get endpoint descriptor + // + EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbPipeRequest.PipeHandle; + + // + // get type + // + Type = (EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK); + if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS) + { + // + // clear stall + // + Status = HandleClearStall(Irp, Urb); + } + DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status); + + // + // reset data toggle + // + ASSERT(NT_SUCCESS(Status)); + EndpointDescriptor->DataToggle = 0x0; + + // + // done + // + return Status; +} + +NTSTATUS +CHubController::HandleAbortPipe( + IN OUT PIRP Irp, + IN OUT PURB Urb) +{ + NTSTATUS Status; + PUSBDEVICE UsbDevice; + PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + + // + // sanity check + // + PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); + PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST)); + PC_ASSERT(Urb->UrbPipeRequest.PipeHandle); + + // + // check if this is a valid usb device handle + // + if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) + { + DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle); + + // + // invalid device handle + // + return STATUS_DEVICE_NOT_CONNECTED; + } + + // + // get endpoint descriptor + // + EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle; + + // + // get device + // + UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); + + + // + // issue request + // + Status = UsbDevice->AbortPipe(EndpointDescriptor); + DPRINT1("URB_FUNCTION_ABORT_PIPE Status %x\n", Status); + + // + // done + // + return Status; +} + + +//----------------------------------------------------------------------------------------- +NTSTATUS +CHubController::HandleClearStall( + IN OUT PIRP Irp, + IN OUT PURB Urb) +{ + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + NTSTATUS Status; + PUSBDEVICE UsbDevice; + PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + + + // + // sanity check + // + PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); + PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST)); + PC_ASSERT(Urb->UrbPipeRequest.PipeHandle); + + // + // check if this is a valid usb device handle + // + if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) + { + DPRINT1("HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle); + + // + // invalid device handle + // + return STATUS_DEVICE_NOT_CONNECTED; + } + + // + // get endpoint descriptor + // + EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle; + + // + // get device + // + UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); + DPRINT1("URB_FUNCTION_SYNC_CLEAR_STALL\n"); + + // + // initialize setup packet + // + CtrlSetup.bmRequestType.B = 0x02; + CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE; + CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL; + CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress; + CtrlSetup.wLength = 0; + CtrlSetup.wValue.W = 0; + + // + // issue request + // + Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0); + + DPRINT1("URB_FUNCTION_CLEAR_STALL Status %x\n", Status); + + // + // done + // + return Status; +} +
//----------------------------------------------------------------------------------------- NTSTATUS @@ -1747,12 +1938,20 @@ // // initialize setup packet // - CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const. + CtrlSetup.bmRequestType.B = 0x21; CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
+ if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN) + { + // + // data direction is device to host + // + CtrlSetup.bmRequestType.B |= 0x80; + } + // // issue request // @@ -1761,8 +1960,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 @@ -1806,6 +2010,16 @@
switch (Urb->UrbHeader.Function) { + case URB_FUNCTION_SYNC_RESET_PIPE: + case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: + Status = HandleSyncResetAndClearStall(Irp, Urb); + break; + case URB_FUNCTION_ABORT_PIPE: + Status = HandleAbortPipe(Irp, Urb); + break; + case URB_FUNCTION_SYNC_CLEAR_STALL: + Status = HandleClearStall(Irp, Urb); + break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: Status = HandleGetDescriptorFromInterface(Irp, Urb); break;
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/interfaces.h [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -379,6 +379,7 @@ //
struct _QUEUE_HEAD; +struct _USB_ENDPOINT;
DECLARE_INTERFACE_(IUSBRequest, IUnknown) { @@ -395,7 +396,7 @@ virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, - IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, + IN OPTIONAL struct _USB_ENDPOINT *EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer) = 0;
@@ -588,6 +589,15 @@ // This function gets called by IUSBHardware after it the Interrupt on Async Advance bit has been set
virtual VOID CompleteAsyncRequests() = 0; + +//----------------------------------------------------------------------------------------- +// +// AbortDevicePipe +// +// Description: aborts all pending requsts of an device + + virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) = 0; + };
typedef IUSBQueue *PUSBQUEUE; @@ -841,6 +851,15 @@
virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface) = 0; + +//----------------------------------------------------------------------------------------- +// +// AbortPipe +// +// Description: aborts all pending requsts + + virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) = 0; + };
typedef IUSBDevice *PUSBDEVICE;
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/usb_device.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -10,24 +10,6 @@
#define INITGUID #include "usbehci.h" - -typedef struct _USB_ENDPOINT -{ - USB_ENDPOINT_DESCRIPTOR EndPointDescriptor; -} USB_ENDPOINT, *PUSB_ENDPOINT; - -typedef struct _USB_INTERFACE -{ - USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - USB_ENDPOINT *EndPoints; -} USB_INTERFACE, *PUSB_INTERFACE; - -typedef struct _USB_CONFIGURATION -{ - USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; - USB_INTERFACE *Interfaces; -} USB_CONFIGURATION, *PUSB_CONFIGURATION; -
class CUSBDevice : public IUSBDevice { @@ -70,10 +52,12 @@ virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, OUT ULONG BufferLength, OUT PVOID Buffer); virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, IN PUSBD_INTERFACE_INFORMATION Interface, OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle); virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface); + virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor); +
// local function virtual NTSTATUS CommitIrp(PIRP Irp); - virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl); + virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl); virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex); virtual NTSTATUS CreateDeviceDescriptor(); virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); @@ -537,7 +521,7 @@ NTSTATUS CUSBDevice::CommitSetupPacket( IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, - IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, + IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl) { @@ -1273,6 +1257,23 @@ return Status; }
+NTSTATUS +CUSBDevice::AbortPipe( + IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) +{ + // + // let it handle usb queue + // + ASSERT(m_Queue); + ASSERT(m_DeviceAddress); + + // + // done + // + return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor); +} + + //---------------------------------------------------------------------------------------- NTSTATUS CreateUSBDevice(
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/usb_queue.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -41,6 +41,8 @@ virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest); virtual VOID InterruptCallback(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell); virtual VOID CompleteAsyncRequests(); + virtual NTSTATUS AbortDevicePipe(UCHAR DeviceAddress, IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor); +
// constructor / destructor CUSBQueue(IUnknown *OuterUnknown){} @@ -499,11 +501,6 @@ // remove software link // RemoveEntryList(&QueueHead->LinkedQueueHeads); - - // - // FIXME: clear failure - // - QueueHead->Token.Bits.Halted = FALSE; }
// @@ -629,6 +626,7 @@ // // walk async list // + ASSERT(AsyncListQueueHead); Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
while(Entry != &AsyncListQueueHead->LinkedQueueHeads) @@ -637,6 +635,7 @@ // get queue head structure // QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); + ASSERT(QueueHead);
// // sanity check @@ -658,7 +657,7 @@ // IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
- DPRINT1("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete); + DPRINT("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete);
// // check if queue head is complete @@ -930,6 +929,16 @@ }
NTSTATUS +CUSBQueue::AbortDevicePipe( + IN UCHAR DeviceAddress, + IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) +{ + UNIMPLEMENTED + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS CreateUSBQueue( PUSBQUEUE *OutUsbQueue) { @@ -962,3 +971,4 @@ // return STATUS_SUCCESS; } +
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/usb_request.cpp [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -36,7 +36,7 @@ }
// IUSBRequest interface functions - virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer); + virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer); virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp); virtual VOID CompletionCallback(IN NTSTATUS NtStatusCode, IN ULONG UrbStatusCode, IN struct _QUEUE_HEAD *QueueHead); virtual VOID CancelCallback(IN NTSTATUS NtStatusCode, IN struct _QUEUE_HEAD *QueueHead); @@ -62,6 +62,10 @@ NTSTATUS BuildSetupPacket(); NTSTATUS BuildSetupPacketFromURB(); ULONG InternalCalculateTransferLength(); + NTSTATUS BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG OutTransferBufferOffset); + VOID InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR DataToggle, OUT PULONG OutDescriptorLength); + VOID DumpQueueHead(IN PQUEUE_HEAD QueueHead); +
// constructor / destructor CUSBRequest(IUnknown *OuterUnknown){} @@ -118,17 +122,12 @@ // // store end point address // - PUSB_ENDPOINT_DESCRIPTOR m_EndpointDescriptor; + PUSB_ENDPOINT m_EndpointDescriptor;
// // DMA queue head // PQUEUE_HEAD m_QueueHead; - - // - // DMA transfer descriptors linked to the queue head - // - PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[4];
// // allocated setup packet from the DMA pool @@ -141,6 +140,8 @@ // NTSTATUS m_NtStatusCode; ULONG m_UrbStatusCode; + + PVOID m_Base;
};
@@ -160,7 +161,7 @@ IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, - IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, + IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer) { @@ -321,7 +322,7 @@ // // get endpoint descriptor // - m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle; + m_EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
} break; @@ -587,7 +588,7 @@ // // end point is defined in the low byte of bmAttributes // - TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK); + TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK); } else { @@ -595,6 +596,7 @@ // initialized with setup packet, must be a control transfer // TransferType = USB_ENDPOINT_TYPE_CONTROL; + ASSERT(m_EndpointDescriptor == FALSE); }
// @@ -606,13 +608,243 @@ 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->EndPointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7; + } + else + { + // + // request arrives on the control pipe, extract direction from setup packet + // + ASSERT(m_DescriptorPacket); + return (m_DescriptorPacket->bmRequestType.B >> 7); + } +} + +VOID +CUSBRequest::InitDescriptor( + IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, + IN PVOID TransferBuffer, + IN ULONG TransferBufferLength, + IN UCHAR PidCode, + IN UCHAR DataToggle, + OUT PULONG OutDescriptorLength) +{ + ULONG Index, Length = 0, PageOffset, BufferLength; + + // + // init transfer descriptor + // + CurrentDescriptor->Token.Bits.PIDCode = PidCode; + CurrentDescriptor->Token.Bits.TotalBytesToTransfer = 0; + CurrentDescriptor->Token.Bits.DataToggle = DataToggle; + + // + // sanity check + // + ASSERT(TransferBufferLength); + + // + // store buffers + // + Index = 0; + do + { + // + // use physical address + // + CurrentDescriptor->BufferPointer[Index] = MmGetPhysicalAddress(TransferBuffer).LowPart; + + // + // Get the offset from page size + // + PageOffset = BYTE_OFFSET(CurrentDescriptor->BufferPointer[Index]); + if (PageOffset != 0) + { + // + // move to next page + // + TransferBuffer = (PVOID)ROUND_TO_PAGES(TransferBuffer); + } + else + { + // + // move to next page + // + TransferBuffer = (PVOID)((ULONG_PTR)TransferBuffer + PAGE_SIZE); + } + + // + // calculate buffer length + // + BufferLength = min(TransferBufferLength, PAGE_SIZE - PageOffset); + + // + // increment transfer bytes + // + CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength; + CurrentDescriptor->TotalBytesToTransfer += BufferLength; + Length += BufferLength; + DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index, TransferBufferLength, PageOffset, BufferLength, CurrentDescriptor->BufferPointer[Index], TransferBuffer); + + // + // decrement available byte count + // + TransferBufferLength -= BufferLength; + if (TransferBufferLength == 0) + { + // + // end reached + // + break; + } + + // + // sanity check + // + if (Index > 1) + { + // + // no equal buffers + // + ASSERT(CurrentDescriptor->BufferPointer[Index] != CurrentDescriptor->BufferPointer[Index-1]); + } + + // + // next descriptor index + // + Index++; + }while(Index < 5); + + // + // store result + // + *OutDescriptorLength = Length; +} + + +NTSTATUS +CUSBRequest::BuildTransferDescriptorChain( + IN PQUEUE_HEAD QueueHead, + IN PVOID TransferBuffer, + IN ULONG TransferBufferLength, + IN UCHAR PidCode, + IN UCHAR InitialDataToggle, + OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, + OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, + OUT PUCHAR OutDataToggle, + OUT PULONG OutTransferBufferOffset) +{ + PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL; + NTSTATUS Status; + ULONG DescriptorLength, TransferBufferOffset = 0; + + do + { + // + // allocate transfer descriptor + // + Status = CreateDescriptor(&CurrentDescriptor); + if (!NT_SUCCESS(Status)) + { + // + // failed to allocate transfer descriptor + // + ASSERT(FALSE); + return Status; + } + + // + // now init the descriptor + // + InitDescriptor(CurrentDescriptor, + (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset), + TransferBufferLength - TransferBufferOffset, + PidCode, + InitialDataToggle, + &DescriptorLength); + + // + // insert into queue head + // + InsertTailList(&QueueHead->TransferDescriptorListHead, &CurrentDescriptor->DescriptorEntry); + + // + // adjust offset + // + TransferBufferOffset += DescriptorLength; + + if (LastDescriptor) + { + // + // link to current descriptor + // + LastDescriptor->AlternateNextPointer = CurrentDescriptor->PhysicalAddr; + LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr; + LastDescriptor = CurrentDescriptor; + } + else + { + // + // first descriptor in chain + // + LastDescriptor = FirstDescriptor = CurrentDescriptor; + } + + if(TransferBufferLength == TransferBufferOffset) + { + // + // end reached + // + break; + } + }while(TRUE); + + if (OutFirstDescriptor) + { + // + // store first descriptor + // + *OutFirstDescriptor = FirstDescriptor; + } + + if (OutLastDescriptor) + { + // + // store last descriptor + // + *OutLastDescriptor = CurrentDescriptor; + } + + if (OutDataToggle) + { + // + // flip data toggle + // + InitialDataToggle = !InitialDataToggle; + + // + // store result data toggle + // + *OutDataToggle = InitialDataToggle; + } + + if (OutTransferBufferOffset) + { + // + // store offset + // + *OutTransferBufferOffset = TransferBufferOffset; + } + + // + // done + // + return STATUS_SUCCESS; }
//---------------------------------------------------------------------------------------- @@ -621,8 +853,9 @@ PQUEUE_HEAD * OutHead) { NTSTATUS Status; - ULONG NumTransferDescriptors, Index; + ULONG DescriptorChainLength; PQUEUE_HEAD QueueHead; + PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor;
// // first allocate the queue head @@ -650,30 +883,34 @@ // // failed to allocate setup packet // + ASSERT(FALSE); return STATUS_INSUFFICIENT_RESOURCES; }
// - // calculate num of transfer descriptors - // - NumTransferDescriptors = m_TransferBufferMDL != 0 ? 3 : 2; - - // - // allocate transfer descriptors - // - for(Index = 0; Index < NumTransferDescriptors; Index++) - { - // - // allocate transfer descriptor - // - Status = CreateDescriptor(&m_TransferDescriptors[Index]); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate transfer descriptor - // - return Status; - } + // create setup descriptor + // + Status = CreateDescriptor(&SetupDescriptor); + if (!NT_SUCCESS(Status)) + { + // + // failed to allocate transfer descriptor + // + ASSERT(FALSE); + return Status; + } + + // + // create status descriptor + // + Status = CreateDescriptor(&StatusDescriptor); + if (!NT_SUCCESS(Status)) + { + // + // failed to allocate transfer descriptor + // + ASSERT(FALSE); + return Status; }
// @@ -686,102 +923,86 @@ // // set endpoint address and max packet length // - QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F; - QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize; - } - - // - // setup descriptors - // - m_TransferDescriptors[0]->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN; - m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET); - m_TransferDescriptors[0]->Token.Bits.DataToggle = FALSE; - m_TransferDescriptors[0]->BufferPointer[0] = (ULONG)PtrToUlong(m_DescriptorSetupPacket.LowPart); - m_TransferDescriptors[0]->NextPointer = m_TransferDescriptors[1]->PhysicalAddr; - m_TransferDescriptors[0]->AlternateNextPointer = m_TransferDescriptors[1]->PhysicalAddr; - - if (m_TransferBufferMDL) - { - // - // setup in descriptor - // - m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN; - m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = m_TransferBufferLength; - m_TransferDescriptors[1]->NextPointer = m_TransferDescriptors[2]->PhysicalAddr; - m_TransferDescriptors[1]->Token.Bits.DataToggle = TRUE; - m_TransferDescriptors[1]->AlternateNextPointer = m_TransferDescriptors[2]->PhysicalAddr; - - // - // FIXME: check if the request spawns over a page -> fill other members - // - PC_ASSERT(m_TransferBufferLength <= PAGE_SIZE); - m_TransferDescriptors[1]->BufferPointer[0] = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart; - - // - // setup out descriptor - // - m_TransferDescriptors[2]->Token.Bits.PIDCode = PID_CODE_OUT_TOKEN; - m_TransferDescriptors[2]->Token.Bits.TotalBytesToTransfer = 0; - m_TransferDescriptors[2]->Token.Bits.DataToggle = TRUE; - - // - // special case, setup alternative next descriptor in case of error - // HAIKU links to dead descriptor - // - - // - // interrupt on completion - // - m_TransferDescriptors[2]->Token.Bits.InterruptOnComplete = TRUE; + QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F; + QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; + } + + // + // init setup descriptor + // + SetupDescriptor->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN; + SetupDescriptor->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET); + SetupDescriptor->Token.Bits.DataToggle = FALSE; + SetupDescriptor->BufferPointer[0] = (ULONG)PtrToUlong(m_DescriptorSetupPacket.LowPart); + InsertTailList(&QueueHead->TransferDescriptorListHead, &SetupDescriptor->DescriptorEntry); + + + // + // init status descriptor + // + StatusDescriptor->Token.Bits.TotalBytesToTransfer = 0; + StatusDescriptor->Token.Bits.DataToggle = TRUE; + StatusDescriptor->Token.Bits.InterruptOnComplete = TRUE; + + // + // is there data + // + if (m_TransferBufferLength) + { + Status = BuildTransferDescriptorChain(QueueHead, + MmGetMdlVirtualAddress(m_TransferBufferMDL), + m_TransferBufferLength, + InternalGetPidDirection(), + TRUE, + &FirstDescriptor, + &LastDescriptor, + NULL, + &DescriptorChainLength); + + // + // FIXME handle errors + // + ASSERT(Status == STATUS_SUCCESS); + ASSERT(DescriptorChainLength == m_TransferBufferLength); + + // + // now link the descriptors + // + SetupDescriptor->NextPointer = FirstDescriptor->PhysicalAddr; + SetupDescriptor->AlternateNextPointer = FirstDescriptor->PhysicalAddr; + LastDescriptor->NextPointer = StatusDescriptor->PhysicalAddr; + LastDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr; + + + // + // pid code is flipped for ops with data stage + // + StatusDescriptor->Token.Bits.PIDCode = !InternalGetPidDirection(); } else { // - // no buffer, setup in descriptor - // - m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN; - m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = 0; - m_TransferDescriptors[1]->Token.Bits.DataToggle = TRUE; - - // - // interrupt on completion - // - m_TransferDescriptors[1]->Token.Bits.InterruptOnComplete = TRUE; - } + // direct link + // + SetupDescriptor->NextPointer = StatusDescriptor->PhysicalAddr; + SetupDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr; + + // + // retrieve result of operation + // + StatusDescriptor->Token.Bits.PIDCode = PID_CODE_IN_TOKEN; + } + + // + // insert status descriptor + // + InsertTailList(&QueueHead->TransferDescriptorListHead, &StatusDescriptor->DescriptorEntry); +
// // link transfer descriptors to queue head // - QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr; - - DPRINT("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr); - DPRINT("NumDescriptors %lu\n", NumTransferDescriptors); - DPRINT("QueueHead AlternateNextPointer %x\n", QueueHead->AlternateNextPointer); - DPRINT("QueueHead NextPointer %x\n", QueueHead->NextPointer); - DPRINT("m_DescriptorSetupPacket HiPart %x LoPart %x\n", m_DescriptorSetupPacket.HighPart, m_DescriptorSetupPacket.LowPart); - - - DPRINT("TransferDescriptor 0 Addr %x\n", m_TransferDescriptors[0]->PhysicalAddr); - DPRINT("TransferDescriptor 0 Next %x\n", m_TransferDescriptors[0]->NextPointer); - DPRINT("TransferDescriptor 0 AlternativeNext %x\n", m_TransferDescriptors[0]->AlternateNextPointer); - DPRINT("TransferDescriptor 0 Buffer Pointer %x\n", m_TransferDescriptors[0]->BufferPointer[0]); - DPRINT("TransferDescriptor 0 TotalBytesToTransfer 0x%x\n", m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer); - - DPRINT("TransferDescriptor 1 Addr %x\n", m_TransferDescriptors[1]->PhysicalAddr); - DPRINT("TransferDescriptor 1 Next %x\n", m_TransferDescriptors[1]->NextPointer); - DPRINT("TransferDescriptor 1 AlternativeNext %x\n", m_TransferDescriptors[1]->AlternateNextPointer); - DPRINT("TransferDescriptor 1 Buffer Pointer %x\n", m_TransferDescriptors[1]->BufferPointer[0]); - DPRINT("TransferDescriptor 1 TotalBytesToTransfer 0x%x\n", m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer); - - if (NumTransferDescriptors == 3) - { - DPRINT("TransferDescriptor 2 Addr %x\n", m_TransferDescriptors[2]->PhysicalAddr); - DPRINT("TransferDescriptor 2 Next %x\n", m_TransferDescriptors[2]->NextPointer); - DPRINT("TransferDescriptor 2 AlternativeNext %x\n", m_TransferDescriptors[2]->AlternateNextPointer); - DPRINT("TransferDescriptor 2 Buffer Pointer %x\n", m_TransferDescriptors[2]->BufferPointer[0]); - DPRINT("TransferDescriptor 2 TotalBytesToTransfer 0x%x\n", m_TransferDescriptors[2]->Token.Bits.TotalBytesToTransfer); - } - + QueueHead->NextPointer = SetupDescriptor->PhysicalAddr;
// // store result @@ -789,10 +1010,80 @@ *OutHead = QueueHead;
// + // displays the current request + // + //DumpQueueHead(QueueHead); + + DPRINT1("BuildControlTransferQueueHead done\n"); + // // done // return STATUS_SUCCESS; } + +VOID +CUSBRequest::DumpQueueHead( + IN PQUEUE_HEAD QueueHead) +{ + PLIST_ENTRY Entry; + PQUEUE_TRANSFER_DESCRIPTOR Descriptor; + ULONG Index = 0; + + DPRINT1("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr); + DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead->AlternateNextPointer); + DPRINT1("QueueHead NextPointer %x\n", QueueHead->NextPointer); + + DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCharacteristics.ControlEndPointFlag); + DPRINT1("QueueHead DeviceAddress %x\n", QueueHead->EndPointCharacteristics.DeviceAddress); + DPRINT1("QueueHead EndPointNumber %x\n", QueueHead->EndPointCharacteristics.EndPointNumber); + DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead->EndPointCharacteristics.EndPointSpeed); + DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead->EndPointCharacteristics.HeadOfReclamation); + DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead->EndPointCharacteristics.InactiveOnNextTransaction); + DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead->EndPointCharacteristics.MaximumPacketLength); + DPRINT1("QueueHead NakCountReload %x\n", QueueHead->EndPointCharacteristics.NakCountReload); + DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead->EndPointCharacteristics.QEDTDataToggleControl); + DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCapabilities.HubAddr); + DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead->EndPointCapabilities.InterruptScheduleMask); + DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame); + DPRINT1("QueueHead PortNumber %x\n", QueueHead->EndPointCapabilities.PortNumber); + DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead->EndPointCapabilities.SplitCompletionMask); + + Entry = QueueHead->TransferDescriptorListHead.Flink; + while(Entry != &QueueHead->TransferDescriptorListHead) + { + // + // get transfer descriptor + // + Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry); + + DPRINT1("TransferDescriptor %lu Addr %x\n", Index, Descriptor->PhysicalAddr); + DPRINT1("TransferDescriptor %lu Next %x\n", Index, Descriptor->NextPointer); + DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index, Descriptor->AlternateNextPointer); + DPRINT1("TransferDescriptor %lu Active %lu\n", Index, Descriptor->Token.Bits.Active); + DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index, Descriptor->Token.Bits.BabbleDetected); + DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index, Descriptor->Token.Bits.CurrentPage); + DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index, Descriptor->Token.Bits.DataBufferError); + DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index, Descriptor->Token.Bits.DataToggle); + DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index, Descriptor->Token.Bits.ErrorCounter); + DPRINT1("TransferDescriptor %lu Halted %lu\n", Index, Descriptor->Token.Bits.Halted); + DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index, Descriptor->Token.Bits.InterruptOnComplete); + DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index, Descriptor->Token.Bits.MissedMicroFrame); + DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index, Descriptor->Token.Bits.PIDCode); + DPRINT1("TransferDescriptor %lu PingState %lu\n", Index, Descriptor->Token.Bits.PingState); + DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index, Descriptor->Token.Bits.SplitTransactionState); + DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index, Descriptor->Token.Bits.TotalBytesToTransfer); + DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index, Descriptor->Token.Bits.TransactionError); + + DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index, Descriptor->BufferPointer[0]); + DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index, Descriptor->BufferPointer[1]); + DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index, Descriptor->BufferPointer[2]); + DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index, Descriptor->BufferPointer[3]); + DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index, Descriptor->BufferPointer[4]); + Entry = Entry->Flink; + Index++; + } +} +
//---------------------------------------------------------------------------------------- NTSTATUS @@ -801,11 +1092,9 @@ { NTSTATUS Status; PQUEUE_HEAD QueueHead; - ULONG TransferDescriptorCount, Index; - ULONG BytesAvailable, BufferIndex; PVOID Base; - ULONG PageOffset, CurrentTransferBufferLength; - UCHAR DataToggle; + ULONG ChainDescriptorLength; + PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor;
// // Allocate the queue head @@ -826,279 +1115,81 @@ PC_ASSERT(QueueHead); PC_ASSERT(m_TransferBufferLength);
- // - // Max default of 3 descriptors - // - TransferDescriptorCount = 3; - - // - // get virtual base of mdl - // - Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); + if (!m_Base) + { + // + // get virtual base of mdl + // + m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); + }
// // Increase the size of last transfer, 0 in case this is the first // - Base = (PVOID)((ULONG_PTR)Base + m_TransferBufferLengthCompleted); + Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
PC_ASSERT(m_EndpointDescriptor); PC_ASSERT(Base);
// - // Get the offset from page size - // - PageOffset = BYTE_OFFSET(Base); - - // - // PageOffset should only be > 0 if this is the first transfer for this requests - // - if ((PageOffset != 0) && (m_TransferBufferLengthCompleted != 0)) - { - ASSERT(FALSE); - } - - // - // Calculate the size of this transfer - // - if ((PageOffset != 0) && ((m_TransferBufferLength - m_TransferBufferLengthCompleted) >= (PAGE_SIZE * 4) + PageOffset)) - { - CurrentTransferBufferLength = (PAGE_SIZE * 4) + PageOffset; - } - else if ((m_TransferBufferLength - m_TransferBufferLengthCompleted) >= PAGE_SIZE * 5) - { - CurrentTransferBufferLength = PAGE_SIZE * 5; - } - else - CurrentTransferBufferLength = (m_TransferBufferLength - m_TransferBufferLengthCompleted); - - // - // Add current transfer length to transfer length completed - // - m_TransferBufferLengthCompleted += CurrentTransferBufferLength; - BytesAvailable = CurrentTransferBufferLength; - - DPRINT1("BuildBulkTransferQueueHead\n"); - DPRINT("CurrentTransferBufferLength %x, m_TransferBufferLengthCompleted %x\n", CurrentTransferBufferLength, m_TransferBufferLengthCompleted); - - DPRINT("EndPointAddress %x\n", m_EndpointDescriptor->bEndpointAddress); - DPRINT("EndPointDirection %x\n", USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress)); - - DPRINT("Request %p Base Address %p TransferBytesLength %lu MDL %p\n", this, Base, BytesAvailable, m_TransferBufferMDL); - DPRINT("InternalGetPidDirection() %d EndPointAddress %x\n", InternalGetPidDirection(), m_EndpointDescriptor->bEndpointAddress & 0x0F); - DPRINT("Irp %p QueueHead %p\n", m_Irp, QueueHead); - - //PC_ASSERT(InternalGetPidDirection() == USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress)); - - // - // DataToggle - // - DataToggle = FALSE; - - // - // Allocated transfer descriptors - // - for (Index = 0; Index < TransferDescriptorCount; Index++) - { - Status = CreateDescriptor(&m_TransferDescriptors[Index]); - if (!NT_SUCCESS(Status)) - { - // - // Failed to allocate transfer descriptors - // - - // - // Free QueueHead - // - FreeQueueHead(QueueHead); - - // - // Free Descriptors - // FIXME: Implement FreeDescriptors - // - return Status; - } - - // - // sanity check - // - PC_ASSERT(BytesAvailable); - - // - // now setup transfer buffers - // - for(BufferIndex = 0; BufferIndex < 5; BufferIndex++) - { - // - // If this is the first buffer of the first descriptor and there is a PageOffset - // - if ((BufferIndex == 0) && (PageOffset != 0) && (Index == 0)) - { - // - // use physical address - // - m_TransferDescriptors[Index]->BufferPointer[0] = MmGetPhysicalAddress(Base).LowPart; - - // - // move to next page - // - Base = (PVOID)ROUND_TO_PAGES(Base); - - // - // increment transfer bytes - // - if (CurrentTransferBufferLength > PAGE_SIZE - PageOffset) - m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = PAGE_SIZE - PageOffset; - else - m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = CurrentTransferBufferLength; - - // - // decrement available byte count - // - BytesAvailable -= m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer; - - DPRINT1("TransferDescriptor %p Index %lu BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], Index, m_TransferDescriptors[Index]->BufferPointer[BufferIndex], - BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable); - } - else - { - // - // the following pages always start on byte zero of each page - // - PC_ASSERT(((ULONG_PTR)Base & (PAGE_SIZE-1)) == 0); - - if (BytesAvailable >= PAGE_SIZE) - { - // - // store address - // - m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart; - - // - // move to next page - // - Base = (PVOID)((ULONG_PTR)Base + PAGE_SIZE); - - // - // increment transfer descriptor bytes - // - m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += PAGE_SIZE; - - // - // decrement available byte count - // - BytesAvailable -= PAGE_SIZE; - - DPRINT1("TransferDescriptor %p Index %lu BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], Index, m_TransferDescriptors[Index]->BufferPointer[BufferIndex], - BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable); - } - else - { - PC_ASSERT(BytesAvailable); - - if (BytesAvailable) - { - // - // store address - // - m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart; - - // - // increment transfer descriptor bytes - // - m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += BytesAvailable; - - // - // decrement available byte count - // - BytesAvailable -= BytesAvailable; - - // - // done as this is the last partial or full page - // - } - DPRINT1("TransferDescriptor %p Index %lu BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], Index, m_TransferDescriptors[Index]->BufferPointer[BufferIndex], - BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable); - - break; - } - } - - // - // Check if all bytes have been consumed - // - if (BytesAvailable == 0) - break; - } - - // - // Go ahead and link descriptors - // - if (Index > 0) - { - m_TransferDescriptors[Index - 1]->NextPointer = m_TransferDescriptors[Index]->PhysicalAddr; - } - - - // - // status descriptor - // - m_TransferDescriptors[Index]->Token.Bits.InterruptOnComplete = TRUE; - - // - // FIXME: need status descriptor? - // - - // - // setup direction - // - m_TransferDescriptors[Index]->Token.Bits.PIDCode = InternalGetPidDirection(); - - // - // set data toggle - // - m_TransferDescriptors[Index]->Token.Bits.DataToggle = DataToggle; - DataToggle = !DataToggle; - - // - // Check if all bytes have been consumed - // - if (BytesAvailable == 0) - break; - } - - // - // all bytes should have been consumed - // - PC_ASSERT(BytesAvailable == 0); - - // - // Initialize the QueueHead + // sanity check + // + ASSERT(m_EndpointDescriptor); + + // + // build bulk transfer descriptor chain + // + Status = BuildTransferDescriptorChain(QueueHead, + Base, + m_TransferBufferLength - m_TransferBufferLengthCompleted, + InternalGetPidDirection(), + m_EndpointDescriptor->DataToggle, + &FirstDescriptor, + &LastDescriptor, + &m_EndpointDescriptor->DataToggle, + &ChainDescriptorLength); + + // + // FIXME: handle errors + // + ASSERT(ChainDescriptorLength == m_TransferBufferLength); + + // + // move to next offset + // + m_TransferBufferLengthCompleted += ChainDescriptorLength; + + ASSERT(Status == STATUS_SUCCESS); + + // + // init queue head // QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress(); - - if (m_EndpointDescriptor) - { - // - // Set endpoint address and max packet length - // - QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F; - QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize; - } - - // - // store number of transactions - // - QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = min(Index, 1); - - // - // link descriptor with queue head - // - QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr; + QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F; + QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; + QueueHead->NextPointer = FirstDescriptor->PhysicalAddr; + QueueHead->CurrentLinkPointer = FirstDescriptor->PhysicalAddr; + QueueHead->AlternateNextPointer = TERMINATE_POINTER; + + ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress); + ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber); + ASSERT(QueueHead->EndPointCharacteristics.MaximumPacketLength); + ASSERT(QueueHead->NextPointer); + + // + // interrupt on last descriptor + // + LastDescriptor->Token.Bits.InterruptOnComplete = TRUE;
// // store result // *OutHead = QueueHead; + + // + // dump status + // + //DumpQueueHead(QueueHead);
// // done @@ -1176,6 +1267,7 @@ QueueHead->HorizontalLinkPointer = TERMINATE_POINTER; QueueHead->AlternateNextPointer = TERMINATE_POINTER; QueueHead->NextPointer = TERMINATE_POINTER; + InitializeListHead(&QueueHead->TransferDescriptorListHead);
// // 1 for non high speed, 0 for high speed device @@ -1536,12 +1628,50 @@ CUSBRequest::FreeQueueHead( IN struct _QUEUE_HEAD * QueueHead) { - LONG DescriptorCount; - - // - // FIXME: support chained queue heads - // - //PC_ASSERT(QueueHead == m_QueueHead); + PLIST_ENTRY Entry; + PQUEUE_TRANSFER_DESCRIPTOR Descriptor; + + // + // sanity checks + // + ASSERT(m_DmaManager); + ASSERT(QueueHead); + ASSERT(!IsListEmpty(&QueueHead->TransferDescriptorListHead)); + + do + { + // + // get transfer descriptors + // + Entry = RemoveHeadList(&QueueHead->TransferDescriptorListHead); + ASSERT(Entry); + + // + // obtain descriptor from entry + // + Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry); + ASSERT(Descriptor); + + // + // add transfer count + // + m_TotalBytesTransferred += (Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer); + DPRINT("TotalBytes Transferred in Descriptor %p Phys Addr %x TotalBytesSoftware %lu Length %lu\n", Descriptor, Descriptor->PhysicalAddr, Descriptor->TotalBytesToTransfer, Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer); + + // + // release transfer descriptors + // + m_DmaManager->Release(Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR)); + + }while(!IsListEmpty(&QueueHead->TransferDescriptorListHead)); + + if (m_DescriptorPacket) + { + // + // release packet descriptor + // + m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); + }
// // release queue head @@ -1549,57 +1679,10 @@ m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD));
// - // nullify pointer + // nullify pointers // m_QueueHead = 0; - - // - // release transfer descriptors - // - for (DescriptorCount = 0; DescriptorCount < 3; DescriptorCount++) - { - if (m_TransferDescriptors[DescriptorCount]) - { - // - // Calculate Total Bytes Transferred - // FIXME: Is this the correct method of determine bytes transferred? - // - if (USB_ENDPOINT_TYPE_BULK == GetTransferType()) - { - // - // sanity check - // - ASSERT(m_EndpointDescriptor); - - if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress)) - { - DPRINT("m_TotalBytesTransferred %x, %x - %x\n", - m_TotalBytesTransferred, - m_TransferDescriptors[DescriptorCount]->TotalBytesToTransfer, - m_TransferDescriptors[DescriptorCount]->Token.Bits.TotalBytesToTransfer); - - m_TotalBytesTransferred += - m_TransferDescriptors[DescriptorCount]->TotalBytesToTransfer - - m_TransferDescriptors[DescriptorCount]->Token.Bits.TotalBytesToTransfer; - } - } - - // - // release transfer descriptors - // - m_DmaManager->Release(m_TransferDescriptors[DescriptorCount], sizeof(QUEUE_TRANSFER_DESCRIPTOR)); - m_TransferDescriptors[DescriptorCount] = 0; - } - } - - if (m_DescriptorPacket) - { - // - // release packet descriptor - // - m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - m_DescriptorPacket = 0; - } + m_DescriptorPacket = 0; }
//----------------------------------------------------------------------------------------- @@ -1607,7 +1690,8 @@ CUSBRequest::IsQueueHeadComplete( struct _QUEUE_HEAD * QueueHead) { - ULONG Index; + PLIST_ENTRY Entry; + PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
// // first check - is the queue head currently active @@ -1617,39 +1701,50 @@ // // queue head is active (currently processed) // - ASSERT(QueueHead->Token.Bits.Halted == FALSE); - //return FALSE; - } - - // - // FIXME: support chained queue heads - // - for(Index = 0; Index < 3; Index++) - { - // - // check transfer descriptors for completion - // - if (m_TransferDescriptors[Index]) + return FALSE; + } + + if (QueueHead->Token.Bits.Halted) + { + // + // error occured + // + DPRINT1("Found halted queue head %p\n", QueueHead); + DumpQueueHead(QueueHead); + ASSERT(FALSE); + return TRUE; + } + + // + // loop list and see if there are any active descriptors + // + Entry = QueueHead->TransferDescriptorListHead.Flink; + while(Entry != &QueueHead->TransferDescriptorListHead) + { + // + // obtain descriptor from entry + // + Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry); + ASSERT(Descriptor); + if (Descriptor->Token.Bits.Active) { // - // check for serious error - // - DPRINT("Descriptor Addr %x\n", m_TransferDescriptors[Index]->PhysicalAddr); - DPRINT("Descriptor BabbleDetected %x\n", m_TransferDescriptors[Index]->Token.Bits.BabbleDetected); - DPRINT("Descriptor DataBufferError %x\n", m_TransferDescriptors[Index]->Token.Bits.DataBufferError); - DPRINT("Descriptor DataToggle %x\n", m_TransferDescriptors[Index]->Token.Bits.DataToggle); - DPRINT("Descriptor ErrorCounter %x\n", m_TransferDescriptors[Index]->Token.Bits.ErrorCounter); - DPRINT("Descriptor TransactionError %x\n", m_TransferDescriptors[Index]->Token.Bits.TransactionError); - - - // - // the transfer descriptor should be in the same state as the queue head - // - //PC_ASSERT(m_TransferDescriptors[Index]->Token.Bits.Active == 0); + // descriptor is still active + // + return FALSE; } - } - //ASSERT(FALSE); - + + // + // move to next entry + // + Entry = Entry->Flink; + } + + DPRINT("QueueHead %p Addr %x is complete\n", QueueHead, QueueHead->PhysicalAddr); + + // + // no active descriptors found, queue head is finished + // return TRUE; }
@@ -1682,8 +1777,7 @@ // sanity check // ASSERT(m_EndpointDescriptor); - - if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress)) + if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress)) { // // bulk in request
Modified: branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup-trunk/drivers/usb/us... ============================================================================== --- branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h [iso-8859-1] (original) +++ branches/usb-bringup-trunk/drivers/usb/usbehci/usbehci.h [iso-8859-1] Fri Feb 10 20:15:39 2012 @@ -38,6 +38,28 @@ #define C_PORT_SUSPEND 18 #define C_PORT_OVER_CURRENT 19 #define C_PORT_RESET 20 + +typedef struct _USB_ENDPOINT +{ + USB_ENDPOINT_DESCRIPTOR EndPointDescriptor; + UCHAR HubAddress; + UCHAR HubPort; + UCHAR DataToggle; +} USB_ENDPOINT, *PUSB_ENDPOINT; + +typedef struct _USB_INTERFACE +{ + USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + USB_ENDPOINT *EndPoints; +} USB_INTERFACE, *PUSB_INTERFACE; + +typedef struct _USB_CONFIGURATION +{ + USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; + USB_INTERFACE *Interfaces; +} USB_CONFIGURATION, *PUSB_CONFIGURATION; + +
typedef struct {