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/u…
==============================================================================
--- 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/u…
==============================================================================
--- 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/u…
==============================================================================
--- 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/u…
==============================================================================
--- 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/u…
==============================================================================
--- 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/u…
==============================================================================
--- 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/u…
==============================================================================
--- 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/u…
==============================================================================
--- 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
{