diff --git a/drivers/usb/usbehci_new/hardware.cpp b/drivers/usb/usbehci_new/hardware.cpp index 7dea58fa8b0..82da8d7a73f 100644 --- a/drivers/usb/usbehci_new/hardware.cpp +++ b/drivers/usb/usbehci_new/hardware.cpp @@ -32,11 +32,6 @@ VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context); -VOID -NTAPI -QueueHeadCompletionRoutine(PVOID Context); - - class CUSBHardwareDevice : public IUSBHardwareDevice { public: @@ -99,7 +94,6 @@ public: friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); friend VOID NTAPI EhciDefferedRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context); - friend VOID NTAPI QueueHeadCompletionRoutine(PVOID Context); // constructor / destructor CUSBHardwareDevice(IUnknown *OuterUnknown){} virtual ~CUSBHardwareDevice(){} @@ -1312,37 +1306,6 @@ InterruptServiceRoutine( return TRUE; } -typedef struct -{ - WORK_QUEUE_ITEM QueueHeadWorkItem; - CUSBHardwareDevice * This; - -}QUEUE_HEAD_COMPLETION, *PQUEUE_HEAD_COMPLETION; - - -VOID -NTAPI -QueueHeadCompletionRoutine( - IN PVOID Ctx) -{ - // - // cast to hardware object - // - PQUEUE_HEAD_COMPLETION Context = (PQUEUE_HEAD_COMPLETION)Ctx; - - // - // now notify IUSBQueue that it can free completed requests - // - Context->This->m_UsbQueue->CompleteAsyncRequests(); - - // - // door ring bell completed - // - Context->This->m_DoorBellRingInProgress = FALSE; - - ExFreePool(Context); -} - VOID NTAPI EhciDefferedRoutine( IN PKDPC Dpc, @@ -1354,7 +1317,6 @@ EhciDefferedRoutine( ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell; NTSTATUS Status = STATUS_SUCCESS; EHCI_USBCMD_CONTENT UsbCmd; - PQUEUE_HEAD_COMPLETION Context; This = (CUSBHardwareDevice*) SystemArgument1; CStatus = (ULONG) SystemArgument2; @@ -1377,7 +1339,6 @@ EhciDefferedRoutine( // controller reported error // DPRINT1("CStatus %x\n", CStatus); - ASSERT(FALSE); } // @@ -1424,22 +1385,14 @@ EhciDefferedRoutine( PC_ASSERT(This->m_DoorBellRingInProgress == TRUE); // - // get command register + // now notify IUSBQueue that it can free completed requests // - This->GetCommandRegister(&UsbCmd); - ASSERT(UsbCmd.DoorBell == FALSE); + This->m_UsbQueue->CompleteAsyncRequests(); // - // allocate work item context + // door ring bell completed // - Context = (PQUEUE_HEAD_COMPLETION)ExAllocatePool(NonPagedPool, sizeof(QUEUE_HEAD_COMPLETION)); - if (Context) - { - ExInitializeWorkItem(&Context->QueueHeadWorkItem, QueueHeadCompletionRoutine, Context); - Context->This = This; - ExQueueWorkItem(&Context->QueueHeadWorkItem, DelayedWorkQueue); - } - + This->m_DoorBellRingInProgress = FALSE; } This->GetDeviceDetails(NULL, NULL, &PortCount, NULL); diff --git a/drivers/usb/usbehci_new/hardware.h b/drivers/usb/usbehci_new/hardware.h index b940ab2097b..12df5c8fcbd 100644 --- a/drivers/usb/usbehci_new/hardware.h +++ b/drivers/usb/usbehci_new/hardware.h @@ -148,7 +148,7 @@ typedef struct _QUEUE_TRANSFER_DESCRIPTOR //Software ULONG PhysicalAddr; - LIST_ENTRY DescriptorEntry; + LIST_ENTRY LinkedDescriptors; ULONG TotalBytesToTransfer; } QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR; @@ -216,21 +216,9 @@ typedef struct _QUEUE_HEAD //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); @@ -304,4 +292,3 @@ typedef struct ULONG PortChange; }EHCI_PORT_STATUS; - diff --git a/drivers/usb/usbehci_new/hub_controller.cpp b/drivers/usb/usbehci_new/hub_controller.cpp index 5c49c219911..8342a7d17b9 100644 --- a/drivers/usb/usbehci_new/hub_controller.cpp +++ b/drivers/usb/usbehci_new/hub_controller.cpp @@ -70,9 +70,6 @@ public: 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); @@ -1678,21 +1675,12 @@ CHubController::HandleClassEndpoint( // // initialize setup packet // - CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const. + CtrlSetup.bmRequestType.B = 0xa2; //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 // @@ -1710,185 +1698,6 @@ CHubController::HandleClassEndpoint( 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 CHubController::HandleClassInterface( @@ -1938,20 +1747,12 @@ CHubController::HandleClassInterface( // // initialize setup packet // - CtrlSetup.bmRequestType.B = 0x21; + CtrlSetup.bmRequestType.B = 0xa1; //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 // @@ -1960,13 +1761,8 @@ CHubController::HandleClassInterface( // // assert on failure // - if (!NT_SUCCESS(Status)) - { - // - // display error - // - DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status); - } + PC_ASSERT(NT_SUCCESS(Status)); + // // done @@ -2010,16 +1806,6 @@ CHubController::HandleDeviceControl( 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; diff --git a/drivers/usb/usbehci_new/interfaces.h b/drivers/usb/usbehci_new/interfaces.h index 8527948903d..242ffb16611 100644 --- a/drivers/usb/usbehci_new/interfaces.h +++ b/drivers/usb/usbehci_new/interfaces.h @@ -379,7 +379,6 @@ typedef IDMAMemoryManager *PDMAMEMORYMANAGER; // struct _QUEUE_HEAD; -struct _USB_ENDPOINT; DECLARE_INTERFACE_(IUSBRequest, IUnknown) { @@ -396,7 +395,7 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown) virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, - IN OPTIONAL struct _USB_ENDPOINT *EndpointDescriptor, + IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer) = 0; @@ -589,15 +588,6 @@ DECLARE_INTERFACE_(IUSBQueue, IUnknown) // 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; @@ -851,15 +841,6 @@ DECLARE_INTERFACE_(IUSBDevice, IUnknown) 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; diff --git a/drivers/usb/usbehci_new/usb_device.cpp b/drivers/usb/usbehci_new/usb_device.cpp index 323207737ac..04d63701f3b 100644 --- a/drivers/usb/usbehci_new/usb_device.cpp +++ b/drivers/usb/usbehci_new/usb_device.cpp @@ -11,6 +11,24 @@ #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 { public: @@ -52,12 +70,10 @@ public: 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 EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl); + virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl); virtual NTSTATUS CreateConfigurationDescriptor(ULONG ConfigurationIndex); virtual NTSTATUS CreateDeviceDescriptor(); virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); @@ -521,7 +537,7 @@ CUSBDevice::SubmitIrp( NTSTATUS CUSBDevice::CommitSetupPacket( IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, - IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, + IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl) { @@ -1257,23 +1273,6 @@ CUSBDevice::SelectInterface( 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( diff --git a/drivers/usb/usbehci_new/usb_queue.cpp b/drivers/usb/usbehci_new/usb_queue.cpp index 36a90e704da..4206d5a9020 100644 --- a/drivers/usb/usbehci_new/usb_queue.cpp +++ b/drivers/usb/usbehci_new/usb_queue.cpp @@ -41,8 +41,6 @@ public: 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){} @@ -501,6 +499,11 @@ CUSBQueue::UnlinkQueueHead( // remove software link // RemoveEntryList(&QueueHead->LinkedQueueHeads); + + // + // FIXME: clear failure + // + QueueHead->Token.Bits.Halted = FALSE; } // @@ -626,7 +629,6 @@ CUSBQueue::ProcessAsyncList( // // walk async list // - ASSERT(AsyncListQueueHead); Entry = AsyncListQueueHead->LinkedQueueHeads.Flink; while(Entry != &AsyncListQueueHead->LinkedQueueHeads) @@ -635,7 +637,6 @@ CUSBQueue::ProcessAsyncList( // get queue head structure // QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - ASSERT(QueueHead); // // sanity check @@ -657,7 +658,7 @@ CUSBQueue::ProcessAsyncList( // IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead); - DPRINT("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete); + DPRINT1("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete); // // check if queue head is complete @@ -928,16 +929,6 @@ CUSBQueue::CompleteAsyncRequests() KeReleaseSpinLock(m_Lock, OldLevel); } -NTSTATUS -CUSBQueue::AbortDevicePipe( - IN UCHAR DeviceAddress, - IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) -{ - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; -} - - NTSTATUS CreateUSBQueue( PUSBQUEUE *OutUsbQueue) @@ -971,4 +962,3 @@ CreateUSBQueue( // return STATUS_SUCCESS; } - diff --git a/drivers/usb/usbehci_new/usb_request.cpp b/drivers/usb/usbehci_new/usb_request.cpp index c1dfd171251..cc16e25661b 100644 --- a/drivers/usb/usbehci_new/usb_request.cpp +++ b/drivers/usb/usbehci_new/usb_request.cpp @@ -36,7 +36,7 @@ public: } // IUSBRequest interface functions - 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 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 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,10 +62,6 @@ public: 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){} @@ -122,13 +118,18 @@ protected: // // store end point address // - PUSB_ENDPOINT m_EndpointDescriptor; + PUSB_ENDPOINT_DESCRIPTOR 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,8 +142,6 @@ protected: NTSTATUS m_NtStatusCode; ULONG m_UrbStatusCode; - PVOID m_Base; - }; //---------------------------------------------------------------------------------------- @@ -161,7 +160,7 @@ CUSBRequest::InitializeWithSetupPacket( IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, - IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, + IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer) { @@ -322,7 +321,7 @@ CUSBRequest::InitializeWithIrp( // // get endpoint descriptor // - m_EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle; + m_EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle; } break; @@ -588,7 +587,7 @@ CUSBRequest::InternalGetTransferType() // // end point is defined in the low byte of bmAttributes // - TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK); + TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK); } else { @@ -596,7 +595,6 @@ CUSBRequest::InternalGetTransferType() // initialized with setup packet, must be a control transfer // TransferType = USB_ENDPOINT_TYPE_CONTROL; - ASSERT(m_EndpointDescriptor == FALSE); } // @@ -608,243 +606,13 @@ CUSBRequest::InternalGetTransferType() UCHAR CUSBRequest::InternalGetPidDirection() { - 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; + ASSERT(m_Irp); + ASSERT(m_EndpointDescriptor); // - // init transfer descriptor + // end point is defined in the low byte of bEndpointAddress // - 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; + return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7; } //---------------------------------------------------------------------------------------- @@ -853,9 +621,8 @@ CUSBRequest::BuildControlTransferQueueHead( PQUEUE_HEAD * OutHead) { NTSTATUS Status; - ULONG DescriptorChainLength; + ULONG NumTransferDescriptors, Index; PQUEUE_HEAD QueueHead; - PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor; // // first allocate the queue head @@ -883,34 +650,30 @@ CUSBRequest::BuildControlTransferQueueHead( // // failed to allocate setup packet // - ASSERT(FALSE); return STATUS_INSUFFICIENT_RESOURCES; } // - // create setup descriptor + // calculate num of transfer descriptors // - Status = CreateDescriptor(&SetupDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate transfer descriptor - // - ASSERT(FALSE); - return Status; - } + NumTransferDescriptors = m_TransferBufferMDL != 0 ? 3 : 2; // - // create status descriptor + // allocate transfer descriptors // - Status = CreateDescriptor(&StatusDescriptor); - if (!NT_SUCCESS(Status)) + for(Index = 0; Index < NumTransferDescriptors; Index++) { // - // failed to allocate transfer descriptor + // allocate transfer descriptor // - ASSERT(FALSE); - return Status; + Status = CreateDescriptor(&m_TransferDescriptors[Index]); + if (!NT_SUCCESS(Status)) + { + // + // failed to allocate transfer descriptor + // + return Status; + } } // @@ -923,168 +686,114 @@ CUSBRequest::BuildControlTransferQueueHead( // // set endpoint address and max packet length // - QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F; - QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; + QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F; + QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize; } // - // init setup descriptor + // setup descriptors // - 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); + 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; - - // - // init status descriptor - // - StatusDescriptor->Token.Bits.TotalBytesToTransfer = 0; - StatusDescriptor->Token.Bits.DataToggle = TRUE; - StatusDescriptor->Token.Bits.InterruptOnComplete = TRUE; - - // - // is there data - // - if (m_TransferBufferLength) + if (m_TransferBufferMDL) { - Status = BuildTransferDescriptorChain(QueueHead, - MmGetMdlVirtualAddress(m_TransferBufferMDL), - m_TransferBufferLength, - InternalGetPidDirection(), - TRUE, - &FirstDescriptor, - &LastDescriptor, - NULL, - &DescriptorChainLength); + // + // 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 handle errors + // FIXME: check if the request spawns over a page -> fill other members // - ASSERT(Status == STATUS_SUCCESS); - ASSERT(DescriptorChainLength == m_TransferBufferLength); + PC_ASSERT(m_TransferBufferLength <= PAGE_SIZE); + m_TransferDescriptors[1]->BufferPointer[0] = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart; // - // now link the descriptors + // setup out descriptor // - SetupDescriptor->NextPointer = FirstDescriptor->PhysicalAddr; - SetupDescriptor->AlternateNextPointer = FirstDescriptor->PhysicalAddr; - LastDescriptor->NextPointer = StatusDescriptor->PhysicalAddr; - LastDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr; - + m_TransferDescriptors[2]->Token.Bits.PIDCode = PID_CODE_OUT_TOKEN; + m_TransferDescriptors[2]->Token.Bits.TotalBytesToTransfer = 0; + m_TransferDescriptors[2]->Token.Bits.DataToggle = TRUE; // - // pid code is flipped for ops with data stage + // special case, setup alternative next descriptor in case of error + // HAIKU links to dead descriptor // - StatusDescriptor->Token.Bits.PIDCode = !InternalGetPidDirection(); + + // + // interrupt on completion + // + m_TransferDescriptors[2]->Token.Bits.InterruptOnComplete = TRUE; } else { // - // direct link + // no buffer, setup in descriptor // - SetupDescriptor->NextPointer = StatusDescriptor->PhysicalAddr; - SetupDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr; + m_TransferDescriptors[1]->Token.Bits.PIDCode = PID_CODE_IN_TOKEN; + m_TransferDescriptors[1]->Token.Bits.TotalBytesToTransfer = 0; + m_TransferDescriptors[1]->Token.Bits.DataToggle = TRUE; // - // retrieve result of operation + // interrupt on completion // - StatusDescriptor->Token.Bits.PIDCode = PID_CODE_IN_TOKEN; + m_TransferDescriptors[1]->Token.Bits.InterruptOnComplete = TRUE; } - // - // insert status descriptor - // - InsertTailList(&QueueHead->TransferDescriptorListHead, &StatusDescriptor->DescriptorEntry); - - // // link transfer descriptors to queue head // - QueueHead->NextPointer = SetupDescriptor->PhysicalAddr; + 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); + } + // // store result // *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 CUSBRequest::BuildBulkTransferQueueHead( @@ -1092,9 +801,11 @@ CUSBRequest::BuildBulkTransferQueueHead( { NTSTATUS Status; PQUEUE_HEAD QueueHead; + ULONG TransferDescriptorCount, Index; + ULONG BytesAvailable, BufferIndex; PVOID Base; - ULONG ChainDescriptorLength; - PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor; + ULONG PageOffset, CurrentTransferBufferLength; + UCHAR DataToggle; // // Allocate the queue head @@ -1115,82 +826,280 @@ CUSBRequest::BuildBulkTransferQueueHead( PC_ASSERT(QueueHead); PC_ASSERT(m_TransferBufferLength); - if (!m_Base) - { - // - // get virtual base of mdl - // - m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); - } + // + // Max default of 3 descriptors + // + TransferDescriptorCount = 3; + + // + // get virtual base of mdl + // + Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); // // Increase the size of last transfer, 0 in case this is the first // - Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted); + Base = (PVOID)((ULONG_PTR)Base + m_TransferBufferLengthCompleted); PC_ASSERT(m_EndpointDescriptor); PC_ASSERT(Base); // - // sanity check + // Get the offset from page size // - ASSERT(m_EndpointDescriptor); + PageOffset = BYTE_OFFSET(Base); // - // build bulk transfer descriptor chain + // PageOffset should only be > 0 if this is the first transfer for this requests // - Status = BuildTransferDescriptorChain(QueueHead, - Base, - m_TransferBufferLength - m_TransferBufferLengthCompleted, - InternalGetPidDirection(), - m_EndpointDescriptor->DataToggle, - &FirstDescriptor, - &LastDescriptor, - &m_EndpointDescriptor->DataToggle, - &ChainDescriptorLength); + if ((PageOffset != 0) && (m_TransferBufferLengthCompleted != 0)) + { + ASSERT(FALSE); + } // - // FIXME: handle errors + // Calculate the size of this transfer // - ASSERT(ChainDescriptorLength == m_TransferBufferLength); + 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); // - // move to next offset + // Add current transfer length to transfer length completed // - m_TransferBufferLengthCompleted += ChainDescriptorLength; + m_TransferBufferLengthCompleted += CurrentTransferBufferLength; + BytesAvailable = CurrentTransferBufferLength; - ASSERT(Status == STATUS_SUCCESS); + 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)); // - // init queue head + // 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 // QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress(); - 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); + if (m_EndpointDescriptor) + { + // + // Set endpoint address and max packet length + // + QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->bEndpointAddress & 0x0F; + QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->wMaxPacketSize; + } // - // interrupt on last descriptor + // store number of transactions // - LastDescriptor->Token.Bits.InterruptOnComplete = TRUE; + QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = min(Index, 1); + + // + // link descriptor with queue head + // + QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr; // // store result // *OutHead = QueueHead; - // - // dump status - // - //DumpQueueHead(QueueHead); - // // done // @@ -1267,7 +1176,6 @@ CUSBRequest::CreateQueueHead( 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 @@ -1628,50 +1536,12 @@ VOID CUSBRequest::FreeQueueHead( IN struct _QUEUE_HEAD * QueueHead) { - PLIST_ENTRY Entry; - PQUEUE_TRANSFER_DESCRIPTOR Descriptor; + LONG DescriptorCount; // - // sanity checks + // FIXME: support chained queue heads // - 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)); - } + //PC_ASSERT(QueueHead == m_QueueHead); // // release queue head @@ -1679,10 +1549,57 @@ CUSBRequest::FreeQueueHead( m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD)); // - // nullify pointers + // nullify pointer // m_QueueHead = 0; - m_DescriptorPacket = 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; + } } //----------------------------------------------------------------------------------------- @@ -1690,8 +1607,7 @@ BOOLEAN CUSBRequest::IsQueueHeadComplete( struct _QUEUE_HEAD * QueueHead) { - PLIST_ENTRY Entry; - PQUEUE_TRANSFER_DESCRIPTOR Descriptor; + ULONG Index; // // first check - is the queue head currently active @@ -1701,50 +1617,39 @@ CUSBRequest::IsQueueHeadComplete( // // queue head is active (currently processed) // - return FALSE; - } - - if (QueueHead->Token.Bits.Halted) - { - // - // error occured - // - DPRINT1("Found halted queue head %p\n", QueueHead); - DumpQueueHead(QueueHead); - ASSERT(FALSE); - return TRUE; + ASSERT(QueueHead->Token.Bits.Halted == FALSE); + //return FALSE; } // - // loop list and see if there are any active descriptors + // FIXME: support chained queue heads // - Entry = QueueHead->TransferDescriptorListHead.Flink; - while(Entry != &QueueHead->TransferDescriptorListHead) + for(Index = 0; Index < 3; Index++) { // - // obtain descriptor from entry + // check transfer descriptors for completion // - Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry); - ASSERT(Descriptor); - if (Descriptor->Token.Bits.Active) + if (m_TransferDescriptors[Index]) { // - // descriptor is still active + // check for serious error // - return FALSE; + 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); } - - // - // move to next entry - // - Entry = Entry->Flink; } + //ASSERT(FALSE); - DPRINT("QueueHead %p Addr %x is complete\n", QueueHead, QueueHead->PhysicalAddr); - - // - // no active descriptors found, queue head is finished - // return TRUE; } @@ -1777,7 +1682,8 @@ CUSBRequest::InternalCalculateTransferLength() // sanity check // ASSERT(m_EndpointDescriptor); - if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress)) + + if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress)) { // // bulk in request diff --git a/drivers/usb/usbehci_new/usbehci.h b/drivers/usb/usbehci_new/usbehci.h index 8b05ef37f19..a4d18965d38 100644 --- a/drivers/usb/usbehci_new/usbehci.h +++ b/drivers/usb/usbehci_new/usbehci.h @@ -39,28 +39,6 @@ #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 { BOOLEAN IsFDO; // is device a FDO or PDO