Author: janderwald
Date: Mon May 23 11:29:55 2011
New Revision: 51858
URL:
http://svn.reactos.org/svn/reactos?rev=51858&view=rev
Log:
[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
Modified:
branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
branches/usb-bringup/drivers/usb/usbohci/hardware.h
Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.cpp [iso-8859-1] Mon May 23 11:29:55
2011
@@ -112,6 +112,7 @@
POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor; //
iso endpoint descriptor
POHCI_ENDPOINT_DESCRIPTOR m_InterruptEndpoints[OHCI_STATIC_ENDPOINT_COUNT]; //
endpoints for interrupt / iso transfers
ULONG m_NumberOfPorts; //
number of ports
+ OHCI_PORT_STATUS m_PortStatus[OHCI_MAX_PORT_COUNT]; //
port change status
PDMAMEMORYMANAGER m_MemoryManager; //
memory manager
HD_INIT_CALLBACK* m_SCECallBack; //
status change callback routine
PVOID m_SCEContext; //
status change callback routine context
@@ -852,9 +853,11 @@
OUT USHORT *PortStatus,
OUT USHORT *PortChange)
{
- UNIMPLEMENTED
- *PortStatus = 0;
- *PortChange = 0;
+ //
+ // FIXME: should read status from hardware
+ //
+ *PortStatus = m_PortStatus[PortId].PortStatus;
+ *PortChange = m_PortStatus[PortId].PortChange;
return STATUS_SUCCESS;
}
@@ -863,7 +866,84 @@
ULONG PortId,
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;
}
@@ -873,6 +953,16 @@
ULONG PortId,
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)
{
//
@@ -900,9 +990,25 @@
else if (Feature == PORT_RESET)
{
//
+ // assert
+ //
+ ASSERT((Value & OHCI_RH_PORTSTATUS_CCS));
+
+ //
// reset port
//
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
@@ -1045,7 +1151,7 @@
//
// 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)
@@ -1053,12 +1159,11 @@
//
// new device has arrived
//
- DPRINT1("InterruptServiceRoutine> New Device arrival\n");
//
// 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;
}
@@ -1070,7 +1175,7 @@
//
// 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,13 +1199,76 @@
IN PVOID SystemArgument2)
{
CUSBHardwareDevice *This;
- ULONG CStatus;
+ ULONG CStatus, Index, PortStatus;
//
// get parameters
//
This = (CUSBHardwareDevice*) SystemArgument1;
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);
+ }
+ }
+ }
+ }
}
Modified: branches/usb-bringup/drivers/usb/usbohci/hardware.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbohci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbohci/hardware.h [iso-8859-1] Mon May 23 11:29:55
2011
@@ -210,4 +210,25 @@
//
// 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;