diff --git a/drivers/usb/usbehci_new/hardware.cpp b/drivers/usb/usbehci_new/hardware.cpp index 3dfece4c9df..6d57f0ae4cf 100644 --- a/drivers/usb/usbehci_new/hardware.cpp +++ b/drivers/usb/usbehci_new/hardware.cpp @@ -12,6 +12,8 @@ #include "usbehci.h" #include "hardware.h" +typedef VOID __stdcall HD_INIT_CALLBACK(IN PVOID CallBackContext); + BOOLEAN NTAPI InterruptServiceRoutine( @@ -66,6 +68,10 @@ public: VOID SetAsyncListRegister(ULONG PhysicalAddress); VOID SetPeriodicListRegister(ULONG PhysicalAddress); + ULONG GetAsyncListRegister(); + ULONG GetPeriodicListRegister(); + + VOID SetStatusChangeEndpointCallBack(PVOID CallBack, PVOID Context); KIRQL AcquireDeviceLock(void); VOID ReleaseDeviceLock(KIRQL OldLevel); @@ -100,7 +106,8 @@ protected: PQUEUE_HEAD AsyncQueueHead; PUSBQUEUE m_UsbQueue; PDMAMEMORYMANAGER m_MemoryManager; - + HD_INIT_CALLBACK* m_SCECallBack; + PVOID m_SCEContext; VOID SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd); VOID GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd); ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset); @@ -385,16 +392,6 @@ CUSBHardwareDevice::PnpStart( return Status; } - // - // Initialize the UsbQueue now that we have an AdapterObject. - // - Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Initialize the UsbQueue\n"); - return Status; - } - // // Create a queuehead for the Async Register // @@ -413,8 +410,20 @@ CUSBHardwareDevice::PnpStart( AsyncQueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED; AsyncQueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03; + InitializeListHead(&AsyncQueueHead->LinkedQueueHeads); + SetAsyncListRegister(AsyncQueueHead->PhysicalAddr); + // + // Initialize the UsbQueue now that we have an AdapterObject. + // + Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to Initialize the UsbQueue\n"); + return Status; + } + // // Start the controller // @@ -838,6 +847,26 @@ CUSBHardwareDevice::SetPeriodicListRegister( EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, PhysicalAddress); } +ULONG +CUSBHardwareDevice::GetAsyncListRegister() +{ + return PhysicalAddress.LowPart; +} + +ULONG CUSBHardwareDevice::GetPeriodicListRegister() +{ + UNIMPLEMENTED + return NULL; +} + +VOID CUSBHardwareDevice::SetStatusChangeEndpointCallBack( + PVOID CallBack, + PVOID Context) +{ + m_SCECallBack = (HD_INIT_CALLBACK*)CallBack; + m_SCEContext = Context; +} + KIRQL CUSBHardwareDevice::AcquireDeviceLock(void) { @@ -937,7 +966,7 @@ EhciDefferedRoutine( // // Clear the port change status // - This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus | EHCI_PRT_CONNECTSTATUSCHANGE); + //This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus | EHCI_PRT_CONNECTSTATUSCHANGE); if (PortStatus & EHCI_PRT_CONNECTED) { @@ -964,6 +993,7 @@ EhciDefferedRoutine( // FIXME: Is a port reset needed, or does hub driver request this? // } + This->m_SCECallBack(This->m_SCEContext); } else { diff --git a/drivers/usb/usbehci_new/hub_controller.cpp b/drivers/usb/usbehci_new/hub_controller.cpp index 16e7a928b5c..4dc153a9392 100644 --- a/drivers/usb/usbehci_new/hub_controller.cpp +++ b/drivers/usb/usbehci_new/hub_controller.cpp @@ -11,6 +11,9 @@ #define INITGUID #include "usbehci.h" +VOID StatusChangeEndpointCallBack( + PVOID Context); + class CHubController : public IHubController, public IDispatchIrp { @@ -62,7 +65,8 @@ public: NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb); - + + friend VOID StatusChangeEndpointCallBack(PVOID Context); // constructor / destructor CHubController(IUnknown *OuterUnknown){} @@ -91,6 +95,9 @@ protected: PULONG m_DeviceAddressBitmapBuffer; LIST_ENTRY m_UsbDeviceList; PIRP m_PendingSCEIrp; + + //Internal Functions + BOOLEAN QueryStatusChageEndpoint(PIRP Irp); }; typedef struct @@ -253,6 +260,10 @@ CHubController::Initialize( m_DeviceDescriptor.bcdUSB = 0x200; //FIXME } + // + // Set the SCE Callback that the Hardware Device will call on port status change + // + Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this); // // clear init flag // @@ -262,6 +273,62 @@ CHubController::Initialize( return STATUS_SUCCESS; } +// +// Queries the ports to see if there has been a device connected or removed. +// +BOOLEAN +CHubController::QueryStatusChageEndpoint( + PIRP Irp) +{ + ULONG PortCount, PortId; + PIO_STACK_LOCATION IoStack; + USHORT PortStatus, PortChange; + PURB Urb; + + // + // get current stack location + // + IoStack = IoGetCurrentIrpStackLocation(Irp); + ASSERT(IoStack); + + // + // Get the Urb + // + Urb = (PURB)IoStack->Parameters.Others.Argument1; + ASSERT(Urb); + + // + // Get the number of ports and check each one for device connected + // + m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL); + DPRINT1("SCE Request\n"); + ((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 0; + for (PortId = 0; PortId < PortCount; PortId++) + { + m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange); + + DPRINT1("Port %d: Status %x, Change %x\n", PortId, PortStatus, PortChange); + + // + // Loop the ports + // + if ((PortStatus & USB_PORT_STATUS_CONNECT) && (PortChange & USB_PORT_STATUS_CONNECT)) + { + DPRINT1("Device is connected on port %d\n", PortId); + // Set the value for the port number + ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((PortId + 1) & 7); + } + } + + // + // If there were changes then return TRUE + // + if (((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] != 0) + return TRUE; + + return FALSE; +} + //----------------------------------------------------------------------------------------- NTSTATUS CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject) @@ -693,9 +760,6 @@ CHubController::HandleBulkOrInterruptTransfer( IN OUT PIRP Irp, PURB Urb) { - ULONG PortCount, PortId; - USHORT PortStatus, PortChange; - // // First check if the request is for the Status Change Endpoint // @@ -703,42 +767,13 @@ CHubController::HandleBulkOrInterruptTransfer( // // Is the Request for the root hub // - if (Urb->UrbHeader.UsbdDeviceHandle==0) + if (Urb->UrbHeader.UsbdDeviceHandle == 0) { - // - // There should only be one SCE request pending at a time - // - ASSERT (m_PendingSCEIrp == NULL); - - // - // Get the number of ports and check each one for device connected - // - m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL); - DPRINT1("SCE Request\n"); - DPRINT1("PortCount %d\n", PortCount); - ((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 0; - for (PortId = 0; PortId < PortCount; PortId++) + ASSERT(m_PendingSCEIrp == NULL); + if (QueryStatusChageEndpoint(Irp)) { - m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange); - - DPRINT1("Port %d: Status %x, Change %x\n", PortId, PortStatus, PortChange); - - // - // FIXME: Verify that this is correct. - // - if ((PortStatus & USB_PORT_STATUS_CONNECT) && (PortChange & USB_PORT_STATUS_CONNECT)) - { - DPRINT1("Device is connected on port %d\n", PortId); - ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((PortId + 1) & 7); - break; - } - } - - // - // If there were changes then return SUCCESS - // - if (((PULONG)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] != 0) return STATUS_SUCCESS; + } // // Else pend the IRP, to be completed when a device connects or disconnects. @@ -747,6 +782,7 @@ CHubController::HandleBulkOrInterruptTransfer( IoMarkIrpPending(Irp); return STATUS_PENDING; } + UNIMPLEMENTED return STATUS_NOT_IMPLEMENTED; } @@ -2843,3 +2879,22 @@ CreateHubController( // return STATUS_SUCCESS; } + +VOID StatusChangeEndpointCallBack(PVOID Context) +{ + CHubController* This; + PIRP Irp; + This = (CHubController*)Context; + + ASSERT(This); + + DPRINT1("SCE Notification!\n"); + Irp = This->m_PendingSCEIrp; + This->m_PendingSCEIrp = NULL; + + This->QueryStatusChageEndpoint(Irp); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); +} diff --git a/drivers/usb/usbehci_new/interfaces.h b/drivers/usb/usbehci_new/interfaces.h index cf7027e2336..591dba24fa6 100644 --- a/drivers/usb/usbehci_new/interfaces.h +++ b/drivers/usb/usbehci_new/interfaces.h @@ -262,6 +262,30 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown) // virtual VOID SetPeriodicListRegister(ULONG PhysicalAddress) = 0; +//----------------------------------------------------------------------------------------- +// +// GetAsyncListRegister +// +// Description: Returns the memory address used in the Asynchronous Register +// + virtual ULONG GetAsyncListRegister() = 0; + +//----------------------------------------------------------------------------------------- +// +// GetPeriodicListRegister +// +// Description: Returns the the memory address used in the Periodic Register +// + virtual ULONG GetPeriodicListRegister() = 0; + +//----------------------------------------------------------------------------------------- +// +// SetStatusChangeEndpointCallBack +// +// Description: Used to callback to the hub controller when SCE detected +// + virtual VOID SetStatusChangeEndpointCallBack(PVOID CallBack,PVOID Context) = 0; + //----------------------------------------------------------------------------------------- // // AcquireDeviceLock diff --git a/drivers/usb/usbehci_new/usb_queue.cpp b/drivers/usb/usbehci_new/usb_queue.cpp index 94dc91672df..50540fc931c 100644 --- a/drivers/usb/usbehci_new/usb_queue.cpp +++ b/drivers/usb/usbehci_new/usb_queue.cpp @@ -48,8 +48,8 @@ protected: LONG m_Ref; KSPIN_LOCK m_Lock; PDMA_ADAPTER m_Adapter; - PQUEUE_HEAD AsyncQueueHead; - PQUEUE_HEAD PendingQueueHead; + PQUEUE_HEAD AsyncListQueueHead; + PQUEUE_HEAD PendingListQueueHead; VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead); @@ -93,6 +93,26 @@ CUSBQueue::Initialize( // KeInitializeSpinLock(&m_Lock); + // + // Get the AsyncQueueHead + // + AsyncListQueueHead = (PQUEUE_HEAD)Hardware->GetAsyncListRegister(); + + // + // Create the PendingListQueueHead from NONPAGEDPOOL. It will never be linked into the Asynclist Schedule + // + PendingListQueueHead = (PQUEUE_HEAD)ExAllocatePoolWithTag(NonPagedPool, sizeof(QUEUE_HEAD), TAG_USBEHCI); + if (!PendingListQueueHead) + { + DPRINT1("Pool Allocation failed!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Initialize the List Head + // + InitializeListHead(&PendingListQueueHead->LinkedQueueHeads); + return Status; } @@ -112,8 +132,17 @@ NTSTATUS CUSBQueue::AddUSBRequest( IUSBRequest * Request) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PQUEUE_HEAD QueueHead; + ASSERT(Request != NULL); + + Request->GetQueueHead(&QueueHead); + + // + // Add it to the pending list + // + LinkQueueHead(PendingListQueueHead, QueueHead); + + return STATUS_SUCCESS; } NTSTATUS @@ -135,8 +164,18 @@ NTSTATUS CUSBQueue::CreateUSBRequest( IUSBRequest **OutRequest) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PUSBREQUEST UsbRequest; + NTSTATUS Status; + + *OutRequest = NULL; + Status = InternalCreateUSBRequest(&UsbRequest); + + if (NT_SUCCESS(Status)) + { + *OutRequest = UsbRequest; + } + + return Status; } // diff --git a/drivers/usb/usbehci_new/usb_request.cpp b/drivers/usb/usbehci_new/usb_request.cpp index 8721c296f12..013ab6eb27d 100644 --- a/drivers/usb/usbehci_new/usb_request.cpp +++ b/drivers/usb/usbehci_new/usb_request.cpp @@ -934,4 +934,38 @@ CUSBRequest::ShouldReleaseRequestAfterCompletion() // return FALSE; } -} \ No newline at end of file +} + +NTSTATUS +InternalCreateUSBRequest( + PUSBREQUEST *OutRequest) +{ + PUSBREQUEST This; + + // + // allocate requests + // + This = new(NonPagedPool, TAG_USBEHCI) CUSBRequest(0); + if (!This) + { + // + // failed to allocate + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // add reference count + // + This->AddRef(); + + // + // return result + // + *OutRequest = (PUSBREQUEST)This; + + // + // done + // + return STATUS_SUCCESS; +} diff --git a/drivers/usb/usbehci_new/usbehci.h b/drivers/usb/usbehci_new/usbehci.h index 02e71cec51d..5e4f5abfaba 100644 --- a/drivers/usb/usbehci_new/usbehci.h +++ b/drivers/usb/usbehci_new/usbehci.h @@ -95,4 +95,9 @@ NTSTATUS CreateUSBDevice(PUSBDEVICE *OutDevice); // NTSTATUS CreateUSBQueue(PUSBQUEUE *OutUsbQueue); +// +// usb_request.cpp +// +NTSTATUS InternalCreateUSBRequest(PUSBREQUEST *OutRequest); + #endif