mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
[USBOHCI]
- Fix bug in calculating offset of status register - Start implementing deferred processing routine - Signal status change when new device is arrived - Implement basic GetPortStatus - Start implementing SetPortFeature, ClearPortStatus - ResetPort not yet fully working, WIP svn path=/branches/usb-bringup/; revision=51858
This commit is contained in:
parent
89d52d98bb
commit
c5acda628c
|
@ -112,6 +112,7 @@ protected:
|
||||||
POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor; // iso endpoint descriptor
|
POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor; // iso endpoint descriptor
|
||||||
POHCI_ENDPOINT_DESCRIPTOR m_InterruptEndpoints[OHCI_STATIC_ENDPOINT_COUNT]; // endpoints for interrupt / iso transfers
|
POHCI_ENDPOINT_DESCRIPTOR m_InterruptEndpoints[OHCI_STATIC_ENDPOINT_COUNT]; // endpoints for interrupt / iso transfers
|
||||||
ULONG m_NumberOfPorts; // number of ports
|
ULONG m_NumberOfPorts; // number of ports
|
||||||
|
OHCI_PORT_STATUS m_PortStatus[OHCI_MAX_PORT_COUNT]; // port change status
|
||||||
PDMAMEMORYMANAGER m_MemoryManager; // memory manager
|
PDMAMEMORYMANAGER m_MemoryManager; // memory manager
|
||||||
HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine
|
HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine
|
||||||
PVOID m_SCEContext; // status change callback routine context
|
PVOID m_SCEContext; // status change callback routine context
|
||||||
|
@ -852,9 +853,11 @@ CUSBHardwareDevice::GetPortStatus(
|
||||||
OUT USHORT *PortStatus,
|
OUT USHORT *PortStatus,
|
||||||
OUT USHORT *PortChange)
|
OUT USHORT *PortChange)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
//
|
||||||
*PortStatus = 0;
|
// FIXME: should read status from hardware
|
||||||
*PortChange = 0;
|
//
|
||||||
|
*PortStatus = m_PortStatus[PortId].PortStatus;
|
||||||
|
*PortChange = m_PortStatus[PortId].PortChange;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,7 +866,84 @@ CUSBHardwareDevice::ClearPortStatus(
|
||||||
ULONG PortId,
|
ULONG PortId,
|
||||||
ULONG Status)
|
ULONG Status)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
ULONG Value, Index = 0;
|
||||||
|
|
||||||
|
DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status);
|
||||||
|
|
||||||
|
if (PortId > m_NumberOfPorts)
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// read port status
|
||||||
|
//
|
||||||
|
Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
|
||||||
|
KeStallExecutionProcessor(100);
|
||||||
|
|
||||||
|
if (Status == C_PORT_RESET)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// complete reset
|
||||||
|
//
|
||||||
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRSC);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// read port status
|
||||||
|
//
|
||||||
|
Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
|
||||||
|
|
||||||
|
if ((Value & OHCI_RH_PORTSTATUS_PRS) == 0)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reset is complete
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// wait a bit
|
||||||
|
//
|
||||||
|
KeStallExecutionProcessor(100);
|
||||||
|
DPRINT1("Wait...\n");
|
||||||
|
|
||||||
|
}while(Index++ < 10);
|
||||||
|
|
||||||
|
if ((Value & OHCI_RH_PORTSTATUS_PRS))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to reset\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// update port status
|
||||||
|
//
|
||||||
|
m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_RESET;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT((Value & OHCI_RH_PORTSTATUS_PES));
|
||||||
|
|
||||||
|
if (Value & OHCI_RH_PORTSTATUS_PES)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// port is enabled
|
||||||
|
//
|
||||||
|
m_PortStatus[PortId].PortStatus |= USB_PORT_STATUS_ENABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Status == C_PORT_CONNECTION)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// clear bit
|
||||||
|
//
|
||||||
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_CSC);
|
||||||
|
m_PortStatus[PortId].PortChange &= ~USB_PORT_STATUS_CONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,6 +953,16 @@ CUSBHardwareDevice::SetPortFeature(
|
||||||
ULONG PortId,
|
ULONG PortId,
|
||||||
ULONG Feature)
|
ULONG Feature)
|
||||||
{
|
{
|
||||||
|
ULONG Value;
|
||||||
|
|
||||||
|
DPRINT1("CUSBHardwareDevice::SetPortFeature PortId %x Feature %x\n", PortId, Feature);
|
||||||
|
|
||||||
|
//
|
||||||
|
// read port status
|
||||||
|
//
|
||||||
|
Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
|
||||||
|
|
||||||
|
|
||||||
if (Feature == PORT_ENABLE)
|
if (Feature == PORT_ENABLE)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -899,11 +989,27 @@ CUSBHardwareDevice::SetPortFeature(
|
||||||
}
|
}
|
||||||
else if (Feature == PORT_RESET)
|
else if (Feature == PORT_RESET)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// assert
|
||||||
|
//
|
||||||
|
ASSERT((Value & OHCI_RH_PORTSTATUS_CCS));
|
||||||
|
|
||||||
//
|
//
|
||||||
// reset port
|
// reset port
|
||||||
//
|
//
|
||||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRS);
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// wait
|
||||||
|
//
|
||||||
|
KeStallExecutionProcessor(100);
|
||||||
|
|
||||||
|
//
|
||||||
|
// update cached settings
|
||||||
|
//
|
||||||
|
m_PortStatus[PortId].PortChange |= USB_PORT_STATUS_RESET;
|
||||||
|
m_PortStatus[PortId].PortStatus &= ~USB_PORT_STATUS_ENABLE;
|
||||||
|
|
||||||
//
|
//
|
||||||
// is there a status change callback
|
// is there a status change callback
|
||||||
//
|
//
|
||||||
|
@ -1045,7 +1151,7 @@ InterruptServiceRoutine(
|
||||||
//
|
//
|
||||||
// halt controller
|
// halt controller
|
||||||
//
|
//
|
||||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)(This->m_Base + OHCI_CONTROL_OFFSET)), OHCI_HC_FUNCTIONAL_STATE_RESET);
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_CONTROL_OFFSET), OHCI_HC_FUNCTIONAL_STATE_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status & OHCI_ROOT_HUB_STATUS_CHANGE)
|
if (Status & OHCI_ROOT_HUB_STATUS_CHANGE)
|
||||||
|
@ -1053,12 +1159,11 @@ InterruptServiceRoutine(
|
||||||
//
|
//
|
||||||
// new device has arrived
|
// new device has arrived
|
||||||
//
|
//
|
||||||
DPRINT1("InterruptServiceRoutine> New Device arrival\n");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// disable interrupt as it will fire untill the port has been reset
|
// disable interrupt as it will fire untill the port has been reset
|
||||||
//
|
//
|
||||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)(This->m_Base + OHCI_INTERRUPT_DISABLE_OFFSET)), OHCI_ROOT_HUB_STATUS_CHANGE);
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_DISABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE);
|
||||||
Acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
|
Acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,7 +1175,7 @@ InterruptServiceRoutine(
|
||||||
//
|
//
|
||||||
// ack change
|
// ack change
|
||||||
//
|
//
|
||||||
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)(This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)), Acknowledge);
|
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET), Acknowledge);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1094,7 +1199,7 @@ OhciDefferedRoutine(
|
||||||
IN PVOID SystemArgument2)
|
IN PVOID SystemArgument2)
|
||||||
{
|
{
|
||||||
CUSBHardwareDevice *This;
|
CUSBHardwareDevice *This;
|
||||||
ULONG CStatus;
|
ULONG CStatus, Index, PortStatus;
|
||||||
|
|
||||||
//
|
//
|
||||||
// get parameters
|
// get parameters
|
||||||
|
@ -1102,6 +1207,69 @@ OhciDefferedRoutine(
|
||||||
This = (CUSBHardwareDevice*) SystemArgument1;
|
This = (CUSBHardwareDevice*) SystemArgument1;
|
||||||
CStatus = (ULONG) SystemArgument2;
|
CStatus = (ULONG) SystemArgument2;
|
||||||
|
|
||||||
|
if (CStatus & OHCI_ROOT_HUB_STATUS_CHANGE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// device connected, lets check which port
|
||||||
|
//
|
||||||
|
for(Index = 0; Index < This->m_NumberOfPorts; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// read port status
|
||||||
|
//
|
||||||
|
PortStatus = READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_RH_PORT_STATUS(Index)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if there is a status change
|
||||||
|
//
|
||||||
|
if (PortStatus & OHCI_RH_PORTSTATUS_CSC)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// did a device connect
|
||||||
|
//
|
||||||
|
if (PortStatus & OHCI_RH_PORTSTATUS_CCS)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// device connected
|
||||||
|
//
|
||||||
|
DPRINT1("New device arrival at Port %d LowSpeed %x\n", Index, (PortStatus & OHCI_RH_PORTSTATUS_LSDA));
|
||||||
|
|
||||||
|
//
|
||||||
|
// store change
|
||||||
|
//
|
||||||
|
This->m_PortStatus[Index].PortStatus |= USB_PORT_STATUS_CONNECT;
|
||||||
|
This->m_PortStatus[Index].PortChange |= USB_PORT_STATUS_CONNECT;
|
||||||
|
|
||||||
|
if ((PortStatus & OHCI_RH_PORTSTATUS_LSDA))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// low speed device connected
|
||||||
|
//
|
||||||
|
This->m_PortStatus[Index].PortStatus |= USB_PORT_STATUS_LOW_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// is there a status change callback
|
||||||
|
//
|
||||||
|
if (This->m_SCECallBack != NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// queue work item for processing
|
||||||
|
//
|
||||||
|
ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// device disconnected
|
||||||
|
//
|
||||||
|
DPRINT1("Device disconnected at Port %x\n", Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,4 +210,25 @@ typedef struct
|
||||||
//
|
//
|
||||||
// Maximum port count set by OHCI
|
// Maximum port count set by OHCI
|
||||||
//
|
//
|
||||||
#define OHCI_MAX_PORT_COUNT 15
|
#define OHCI_MAX_PORT_COUNT 15
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ULONG PortStatus;
|
||||||
|
ULONG PortChange;
|
||||||
|
}OHCI_PORT_STATUS;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Hardware part 16 bytes
|
||||||
|
uint32 flags; // Flags field
|
||||||
|
uint32 buffer_physical; // Physical buffer pointer
|
||||||
|
uint32 next_physical_descriptor; // Physical pointer next descriptor
|
||||||
|
uint32 last_physical_byte_address; // Physical pointer to buffer end
|
||||||
|
// Software part
|
||||||
|
addr_t physical_address; // Physical address of this descriptor
|
||||||
|
size_t buffer_size; // Size of the buffer
|
||||||
|
void *buffer_logical; // Logical pointer to the buffer
|
||||||
|
void *next_logical_descriptor; // Logical pointer next descriptor
|
||||||
|
} ohci_general_td;
|
Loading…
Reference in a new issue