mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 15:51:49 +00:00
[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:
parent
40e499c2d4
commit
775c4ce80d
3 changed files with 111 additions and 19 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue