[USBEHCI_NEW]

- hub_controller: Implement Status Change Endpoint for RootHub. 
Handling the URB can return STATUS_PENDING, as in the new SCE code. Check for this before completing the Irp.
Uncomment calls to PortStatus, SetPortFeature, and ClearPortStatus now that they are implemented.
- For function receiving a port number check that its not larger than the actual number of ports on the controller.

svn path=/branches/usb-bringup/; revision=51401
This commit is contained in:
Michael Martin 2011-04-19 13:57:32 +00:00
parent 40e499c2d4
commit 775c4ce80d
3 changed files with 111 additions and 19 deletions

View file

@ -602,6 +602,9 @@ CUSBHardwareDevice::ResetPort(
{
ULONG PortStatus;
if (PortIndex > m_Capabilities.HCSParams.PortCount)
return STATUS_UNSUCCESSFUL;
PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
{
@ -640,7 +643,8 @@ CUSBHardwareDevice::ResetPort(
return STATUS_SUCCESS;
}
NTSTATUS CUSBHardwareDevice::GetPortStatus(
NTSTATUS
CUSBHardwareDevice::GetPortStatus(
ULONG PortId,
OUT USHORT *PortStatus,
OUT USHORT *PortChange)
@ -648,6 +652,11 @@ NTSTATUS CUSBHardwareDevice::GetPortStatus(
ULONG Value;
USHORT Status = 0, Change = 0;
DPRINT1("CUSBHardwareDevice::GetPortStatus\n");
if (PortId > m_Capabilities.HCSParams.PortCount)
return STATUS_UNSUCCESSFUL;
//
// Get the value of the Port Status and Control Register
//
@ -703,16 +712,28 @@ NTSTATUS CUSBHardwareDevice::GetPortStatus(
if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE)
Change |= USB_PORT_STATUS_ENABLE;
*PortStatus = Status;
*PortChange = Change;
//HACK: Maybe
if (Status == (USB_PORT_STATUS_HIGH_SPEED | USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_POWER))
*PortChange = USB_PORT_STATUS_CONNECT;
return STATUS_SUCCESS;
}
NTSTATUS CUSBHardwareDevice::ClearPortStatus(
NTSTATUS
CUSBHardwareDevice::ClearPortStatus(
ULONG PortId,
ULONG Status)
{
ULONG Value;
DPRINT1("CUSBHardwareDevice::ClearPortStatus\n");
if (PortId > m_Capabilities.HCSParams.PortCount)
return STATUS_UNSUCCESSFUL;
Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
if (Status == C_PORT_RESET)
@ -737,18 +758,26 @@ NTSTATUS CUSBHardwareDevice::ClearPortStatus(
}
NTSTATUS CUSBHardwareDevice::SetPortFeature(
NTSTATUS
CUSBHardwareDevice::SetPortFeature(
ULONG PortId,
ULONG Feature)
{
ULONG Value;
DPRINT1("CUSBHardwareDevice::SetPortFeature\n");
if (PortId > m_Capabilities.HCSParams.PortCount)
return STATUS_UNSUCCESSFUL;
Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
if (Feature == PORT_ENABLE)
{
//
// FIXME: EHCI Ports can only be disabled via reset
//
DPRINT1("PORT_ENABLE not supported for EHCI\n");
}
if (Feature == PORT_RESET)
@ -757,7 +786,6 @@ NTSTATUS CUSBHardwareDevice::SetPortFeature(
{
DPRINT1("Non HighSpeed device. Releasing Ownership\n");
}
//
// Reset and clean enable
//
@ -769,17 +797,21 @@ NTSTATUS CUSBHardwareDevice::SetPortFeature(
}
if (Feature == PORT_POWER)
DPRINT1("Not implemented\n");
DPRINT1("PORT_POWER Not implemented\n");
return STATUS_SUCCESS;
}
VOID CUSBHardwareDevice::SetAsyncListRegister(ULONG PhysicalAddress)
VOID
CUSBHardwareDevice::SetAsyncListRegister(
ULONG PhysicalAddress)
{
EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, PhysicalAddress);
}
VOID CUSBHardwareDevice::SetPeriodicListRegister(ULONG PhysicalAddress)
VOID
CUSBHardwareDevice::SetPeriodicListRegister(
ULONG PhysicalAddress)
{
EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, PhysicalAddress);
}

View file

@ -90,6 +90,7 @@ protected:
RTL_BITMAP m_DeviceAddressBitmap;
PULONG m_DeviceAddressBitmapBuffer;
LIST_ENTRY m_UsbDeviceList;
PIRP m_PendingSCEIrp;
};
typedef struct
@ -692,6 +693,60 @@ 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
//
//
// Is the Request for the root hub
//
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++)
{
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.
//
m_PendingSCEIrp = Irp;
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
}
@ -743,9 +798,8 @@ CHubController::HandleClassOther(
//
// get port status
//
//Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
Status = STATUS_SUCCESS;
if (NT_SUCCESS(Status))
{
//
@ -771,10 +825,10 @@ CHubController::HandleClassOther(
switch (Urb->UrbControlVendorClassRequest.Value)
{
case C_PORT_CONNECTION:
//Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
break;
case C_PORT_RESET:
//Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
break;
default:
DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
@ -806,7 +860,7 @@ CHubController::HandleClassOther(
//
// set suspend port feature
//
Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
break;
}
case PORT_POWER:
@ -814,7 +868,7 @@ CHubController::HandleClassOther(
//
// set power feature on port
//
Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId, PORT_POWER);
Status = m_Hardware->SetPortFeature(PortId, PORT_POWER);
break;
}
@ -1232,9 +1286,12 @@ CHubController::HandleDeviceControl(
break;
}
}
if (Status != STATUS_PENDING)
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

View file

@ -70,6 +70,7 @@ protected:
PQUEUE_HEAD m_QueueHead;
PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3];
PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
PHYSICAL_ADDRESS m_DescriptorSetupPacket;
};
//----------------------------------------------------------------------------------------
@ -570,14 +571,15 @@ CUSBRequest::BuildControlTransferQueueHead(
}
//
// FIXME: where put MDL virtual address?
// Control Transfers have only one in or out buffer if one at all. Put in the QueueHead the
// same as BulkTransfers. USBQueue will use the Mdl to fill in the BufferPointers
//
QueueHead->Mdl = m_TransferBufferMDL;
//
// link setup packet into buffer - VIRTUAL Address!!!
// link setup packet into buffer - Physical Address!!!
//
m_TransferDescriptors[0]->BufferPointer[0] = (ULONG)PtrToUlong(m_DescriptorPacket);
m_TransferDescriptors[0]->BufferPointer[0] = (ULONG)PtrToUlong(m_DescriptorSetupPacket.LowPart);
//
// link transfer descriptors to queue head
@ -791,6 +793,7 @@ CUSBRequest::BuildSetupPacket()
// copy setup packet
//
RtlCopyMemory(m_DescriptorPacket, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
m_DescriptorSetupPacket = PhysicalAddress;
}
//