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/hardware.cpp?rev=51858&r1=51857&r2=51858&view=diff
==============================================================================
--- 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/hardware.h?rev=51858&r1=51857&r2=51858&view=diff
==============================================================================
--- 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;


Reply via email to