mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 06:02:59 +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;
|
ULONG PortStatus;
|
||||||
|
|
||||||
|
if (PortIndex > m_Capabilities.HCSParams.PortCount)
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
|
PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
|
||||||
if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
|
if (PortStatus & EHCI_PRT_SLOWSPEEDLINE)
|
||||||
{
|
{
|
||||||
|
@ -640,7 +643,8 @@ CUSBHardwareDevice::ResetPort(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CUSBHardwareDevice::GetPortStatus(
|
NTSTATUS
|
||||||
|
CUSBHardwareDevice::GetPortStatus(
|
||||||
ULONG PortId,
|
ULONG PortId,
|
||||||
OUT USHORT *PortStatus,
|
OUT USHORT *PortStatus,
|
||||||
OUT USHORT *PortChange)
|
OUT USHORT *PortChange)
|
||||||
|
@ -648,6 +652,11 @@ NTSTATUS CUSBHardwareDevice::GetPortStatus(
|
||||||
ULONG Value;
|
ULONG Value;
|
||||||
USHORT Status = 0, Change = 0;
|
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
|
// Get the value of the Port Status and Control Register
|
||||||
//
|
//
|
||||||
|
@ -703,16 +712,28 @@ NTSTATUS CUSBHardwareDevice::GetPortStatus(
|
||||||
if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE)
|
if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE)
|
||||||
Change |= USB_PORT_STATUS_ENABLE;
|
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CUSBHardwareDevice::ClearPortStatus(
|
NTSTATUS
|
||||||
|
CUSBHardwareDevice::ClearPortStatus(
|
||||||
ULONG PortId,
|
ULONG PortId,
|
||||||
ULONG Status)
|
ULONG Status)
|
||||||
{
|
{
|
||||||
ULONG Value;
|
ULONG Value;
|
||||||
|
|
||||||
|
DPRINT1("CUSBHardwareDevice::ClearPortStatus\n");
|
||||||
|
|
||||||
|
if (PortId > m_Capabilities.HCSParams.PortCount)
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
|
Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
|
||||||
|
|
||||||
if (Status == C_PORT_RESET)
|
if (Status == C_PORT_RESET)
|
||||||
|
@ -737,18 +758,26 @@ NTSTATUS CUSBHardwareDevice::ClearPortStatus(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS CUSBHardwareDevice::SetPortFeature(
|
NTSTATUS
|
||||||
|
CUSBHardwareDevice::SetPortFeature(
|
||||||
ULONG PortId,
|
ULONG PortId,
|
||||||
ULONG Feature)
|
ULONG Feature)
|
||||||
{
|
{
|
||||||
ULONG Value;
|
ULONG Value;
|
||||||
|
|
||||||
|
DPRINT1("CUSBHardwareDevice::SetPortFeature\n");
|
||||||
|
|
||||||
|
if (PortId > m_Capabilities.HCSParams.PortCount)
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
|
Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
|
||||||
|
|
||||||
if (Feature == PORT_ENABLE)
|
if (Feature == PORT_ENABLE)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// FIXME: EHCI Ports can only be disabled via reset
|
// FIXME: EHCI Ports can only be disabled via reset
|
||||||
//
|
//
|
||||||
|
DPRINT1("PORT_ENABLE not supported for EHCI\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Feature == PORT_RESET)
|
if (Feature == PORT_RESET)
|
||||||
|
@ -757,7 +786,6 @@ NTSTATUS CUSBHardwareDevice::SetPortFeature(
|
||||||
{
|
{
|
||||||
DPRINT1("Non HighSpeed device. Releasing Ownership\n");
|
DPRINT1("Non HighSpeed device. Releasing Ownership\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reset and clean enable
|
// Reset and clean enable
|
||||||
//
|
//
|
||||||
|
@ -769,17 +797,21 @@ NTSTATUS CUSBHardwareDevice::SetPortFeature(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Feature == PORT_POWER)
|
if (Feature == PORT_POWER)
|
||||||
DPRINT1("Not implemented\n");
|
DPRINT1("PORT_POWER Not implemented\n");
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID CUSBHardwareDevice::SetAsyncListRegister(ULONG PhysicalAddress)
|
VOID
|
||||||
|
CUSBHardwareDevice::SetAsyncListRegister(
|
||||||
|
ULONG PhysicalAddress)
|
||||||
{
|
{
|
||||||
EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, 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);
|
EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, PhysicalAddress);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ protected:
|
||||||
RTL_BITMAP m_DeviceAddressBitmap;
|
RTL_BITMAP m_DeviceAddressBitmap;
|
||||||
PULONG m_DeviceAddressBitmapBuffer;
|
PULONG m_DeviceAddressBitmapBuffer;
|
||||||
LIST_ENTRY m_UsbDeviceList;
|
LIST_ENTRY m_UsbDeviceList;
|
||||||
|
PIRP m_PendingSCEIrp;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -692,6 +693,60 @@ CHubController::HandleBulkOrInterruptTransfer(
|
||||||
IN OUT PIRP Irp,
|
IN OUT PIRP Irp,
|
||||||
PURB Urb)
|
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
|
UNIMPLEMENTED
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
@ -743,9 +798,8 @@ CHubController::HandleClassOther(
|
||||||
//
|
//
|
||||||
// get port status
|
// get port status
|
||||||
//
|
//
|
||||||
//Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
|
Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -771,10 +825,10 @@ CHubController::HandleClassOther(
|
||||||
switch (Urb->UrbControlVendorClassRequest.Value)
|
switch (Urb->UrbControlVendorClassRequest.Value)
|
||||||
{
|
{
|
||||||
case C_PORT_CONNECTION:
|
case C_PORT_CONNECTION:
|
||||||
//Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
|
Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
|
||||||
break;
|
break;
|
||||||
case C_PORT_RESET:
|
case C_PORT_RESET:
|
||||||
//Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
|
Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
|
DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
|
||||||
|
@ -806,7 +860,7 @@ CHubController::HandleClassOther(
|
||||||
//
|
//
|
||||||
// set suspend port feature
|
// set suspend port feature
|
||||||
//
|
//
|
||||||
Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
|
Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PORT_POWER:
|
case PORT_POWER:
|
||||||
|
@ -814,7 +868,7 @@ CHubController::HandleClassOther(
|
||||||
//
|
//
|
||||||
// set power feature on port
|
// set power feature on port
|
||||||
//
|
//
|
||||||
Status = STATUS_SUCCESS; //m_Hardware->SetPortFeature(PortId, PORT_POWER);
|
Status = m_Hardware->SetPortFeature(PortId, PORT_POWER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1232,9 +1286,12 @@ CHubController::HandleDeviceControl(
|
||||||
break;
|
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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ protected:
|
||||||
PQUEUE_HEAD m_QueueHead;
|
PQUEUE_HEAD m_QueueHead;
|
||||||
PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3];
|
PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3];
|
||||||
PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket;
|
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
|
// link transfer descriptors to queue head
|
||||||
|
@ -791,6 +793,7 @@ CUSBRequest::BuildSetupPacket()
|
||||||
// copy setup packet
|
// copy setup packet
|
||||||
//
|
//
|
||||||
RtlCopyMemory(m_DescriptorPacket, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_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