[ros-diffs] [fireball] 30608: - Implement a port reset function. - Fix a bug in get_dev_change function.

fireball at svn.reactos.org fireball at svn.reactos.org
Tue Nov 20 23:45:48 CET 2007


Author: fireball
Date: Wed Nov 21 01:45:48 2007
New Revision: 30608

URL: http://svn.reactos.org/svn/reactos?rev=30608&view=rev
Log:
- Implement a port reset function.
- Fix a bug in get_dev_change function.

Modified:
    trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c

Modified: trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c?rev=30608&r1=30607&r2=30608&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c (original)
+++ trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c Wed Nov 21 01:45:48 2007
@@ -36,6 +36,7 @@
 //BOOLEAN NTAPI ohci_isr(PKINTERRUPT interrupt, PVOID context);
 //BOOLEAN ohci_start(PHCD hcd);
 VOID ohci_init_hcd_interface(POHCI_DEV ohci);
+BOOLEAN ohci_rh_reset_port(PHCD hcd, UCHAR port_idx);
 
 // shared with EHCI
 NTSTATUS ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp);
@@ -50,6 +51,8 @@
 
 extern USB_DEV_MANAGER g_dev_mgr;
 
+/* wrap-aware logic morphed from <linux/jiffies.h> */
+#define tick_before(t1,t2) ((SHORT)(((SHORT)(t1))-((SHORT)(t2))) < 0)
 
 #define OHCI_READ_PORT_ULONG( pul ) ( *pul )
 #define OHCI_WRITE_PORT_ULONG( pul, src ) \
@@ -92,6 +95,20 @@
 #define	OHCI_INTR_INIT \
 	(OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
 
+/* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
+ * not necessarily continuous ... to guard against resume signaling.
+ * The short timeout is safe for non-root hubs, and is backward-compatible
+ * with earlier Linux hosts.
+ */
+#ifdef	CONFIG_USB_SUSPEND
+#define	PORT_RESET_MSEC		50
+#else
+#define	PORT_RESET_MSEC		10
+#endif
+
+/* this timer value might be vendor-specific ... */
+#define	PORT_RESET_HW_MSEC	10
+
 
 VOID
 ohci_wait_ms(POHCI_DEV ohci, LONG ms)
@@ -517,7 +534,7 @@
 	 * (for OHCI integrated on mainboard, it normally is)
 	 */
 	hc_control = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control);
-	DbgPrint("resetting from state %x, control = 0x%x\n",
+    DbgPrint("OHCI: resetting from state %x, control = 0x%x\n",
 			(hc_control & OHCI_CTRL_HCFS),
 			hc_control);
 
@@ -632,6 +649,14 @@
 	//ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
 
 
+    // Debug code follows!
+    /*(VOID)ohci_rh_reset_port(hcd, 1);
+    (VOID)ohci_rh_reset_port(hcd, 2);
+    (VOID)ohci_rh_reset_port(hcd, 3);
+    (VOID)ohci_rh_reset_port(hcd, 4);*/
+    // Debug code ends!
+
+
     return TRUE;
 }
 
@@ -645,6 +670,7 @@
 NTSTATUS
 ohci_submit_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb)
 {
+    DbgPrint("ohci_submit_urb2 caled, but not implemented!\n");
     return STATUS_UNSUCCESSFUL;
 }
 
@@ -695,30 +721,67 @@
         return STATUS_INVALID_PARAMETER;
 
     ohci = ohci_from_hcd(hcd);
+    DbgPrint("ohci_cancel_urb2 called, but not implemented!\n");
     return STATUS_UNSUCCESSFUL;//ehci_cancel_urb(ehci, pdev, pendp, purb);
 }
 
 VOID
 ohci_generic_urb_completion(PURB purb, PVOID context)
 {
+    DbgPrint("ohci_generic_urb_completion called, but not implemented!\n");
 }
 
 BOOLEAN
 ohci_rh_reset_port(PHCD hcd, UCHAR port_idx)
 {
-    //ULONG i;
     POHCI_DEV ohci;
-    //ULONG status;
+    ULONG status, temp;
+    PULONG PortStatus;
+    USHORT Now, ResetDone;
 
     if (hcd == NULL)
         return FALSE;
 
     ohci = ohci_from_hcd(hcd);
 
-    //if (port_idx < 1 || port_idx > ohci->num_ports)
-      //  return FALSE;
-
-    //usb_dbg_print(DBGLVL_MAXIMUM, ("ohci_rh_reset_port(): status after written=0x%x\n", status));
+    if (port_idx < 1 || port_idx > ohci->num_ports)
+        return FALSE;
+
+    port_idx--;
+
+    PortStatus = &ohci->regs->roothub.portstatus[port_idx];
+
+    Now = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->fmnumber);
+	ResetDone = Now + PORT_RESET_MSEC;
+
+	/* build a "continuous enough" reset signal, with up to
+	 * 3msec gap between pulses.  scheduler HZ==100 must work;
+	 * this might need to be deadline-scheduled.
+	 */
+	do {
+		/* spin until any current reset finishes */
+		for (;;) {
+            temp = OHCI_READ_PORT_ULONG(PortStatus);
+			if (!(temp & RH_PS_PRS))
+				break;
+            usb_wait_us_dpc(500);
+		} 
+
+		if (!(temp & RH_PS_CCS))
+			break;
+		if (temp & RH_PS_PRSC)
+        {
+            OHCI_WRITE_PORT_ULONG(PortStatus, RH_PS_PRSC);
+        }
+
+		/* start the next reset, sleep till it's probably done */
+        OHCI_WRITE_PORT_ULONG(PortStatus, RH_PS_PRS);
+        usb_wait_ms_dpc(PORT_RESET_HW_MSEC);
+        Now = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->fmnumber);
+	} while (tick_before(Now, ResetDone));
+
+    status = OHCI_READ_PORT_ULONG((PULONG)(&ohci->regs->roothub.portstatus[port_idx]));
+    usb_dbg_print(DBGLVL_MAXIMUM, ("ohci_rh_reset_port(): status after written=0x%x\n", status));
     return TRUE;
 }
 
@@ -736,7 +799,7 @@
 
     for(i = 0; i < ohci->num_ports; i++)
     {
-        status = OHCI_READ_PORT_ULONG((PULONG)(ohci->regs->roothub.portstatus[i]));
+        status = OHCI_READ_PORT_ULONG((PULONG)(&ohci->regs->roothub.portstatus[i]));
 
         if (status != 0)
         {




More information about the Ros-diffs mailing list