Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Sep 2003 03:18:50 -0400
From:      Anish Mistry <mistry.7@osu.edu>
To:        freebsd-current@freebsd.org
Cc:        Mark Sergeant <msergeant@snsonline.net>
Subject:   [patch] usb ohci suspend/resume v2
Message-ID:  <200309090318.50846.mistry.7@osu.edu>

next in thread | raw e-mail | index | archive | help

--Boundary-03=_a7XX/yXtniDRQ/N
Content-Type: multipart/mixed;
  boundary="Boundary-01=_a7XX/U1scR9TTaL"
Content-Transfer-Encoding: 7bit
Content-Description: signed data
Content-Disposition: inline

--Boundary-01=_a7XX/U1scR9TTaL
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Description: body text
Content-Disposition: inline

On Monday 08 September 2003 02:39 am, you wrote:
> I've tried this patch but was unable to compile my kernel against it
> with any of the sources from the past couple of weeks, it does apply
> cleanly though.
>
> Cheers,
>
> Mark
>
Updated patch at (same as attached):
http://am-productions.biz/docs/usb-3.patch

This still causes the same problem as setting hw.acpi.sleep_delay on my laptop
which cause a reset.  I can't seem to figure out what in this patch that is
causing that same behavior, but I've yet to see anyone with that same
problem, so I'm going to assume that this should work for everyone else :(.
Please if you are a usb guru, I could use some help, I've looked at the spec
and some of the usb code, but am stuck for now.
If you try it, let me know your outcome so I can then clean up the patch so
that someone can commit it.

Anish Mistry

--Boundary-01=_a7XX/U1scR9TTaL
Content-Type: text/x-diff;
  charset="us-ascii";
  name="usb-3.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="usb-3.patch"

diff -u usb.orig/ohci.c usb/ohci.c
=2D-- usb.orig/ohci.c	Tue Sep  9 02:56:49 2003
+++ usb/ohci.c	Tue Sep  9 03:05:42 2003
@@ -1020,7 +1020,7 @@
 	DPRINTF(("ohci_shutdown: stopping the HC\n"));
 	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
 }
=2D
+#endif
 /*
  * Handle suspend/resume.
  *
@@ -1028,6 +1028,141 @@
  * called from an intterupt context.  This is all right since we
  * are almost suspended anyway.
  */
+usbd_status
+ohci_resume(struct ohci_softc *sc)
+{
+	int s;
+	u_int32_t ctl, ival, hcr, fm, per, rev, desca;
+	=09
+	DPRINTF(("ohci_resume: start\n"));
+#if defined(__OpenBSD__)
+	printf(",");
+#else
+	printf("%s:", USBDEVNAME(sc->sc_bus.bdev));
+#endif
+	rev =3D OREAD4(sc, OHCI_REVISION);
+	printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
+	       OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
+	printf("ohci_resume: controller state: ");
+	switch(OREAD4(sc, OHCI_CONTROL) & OHCI_HCFS_MASK) {
+		case OHCI_HCFS_SUSPEND:
+			printf("SUSPEND");
+			break;
+		case OHCI_HCFS_RESUME:
+                        printf("RESUME");
+                        break;
+		case OHCI_HCFS_RESET:
+                        printf("RESET");
+                        break;
+		case OHCI_HCFS_OPERATIONAL:
+                        printf("OPERATIONAL");
+                        break;
+	}
+	printf("\n");
+	s =3D splhardusb();
+	/* The controller only responds to resume or reset writes at this point, =
so lets resume */
+	/* We are only supposed to enter resume state from a suspend state.  Shou=
ld we check? */
+	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESUME);
+	usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);=09
+	/* check if the controller has resumed */
+        ctl =3D OREAD4(sc, OHCI_CONTROL);
+        if((ctl & OHCI_HCFS_RESUME) =3D=3D OHCI_HCFS_RESUME) {
+                printf("ohci_resume: Controller resumed.\n");
+        } else {
+                /* panic or abort? */
+                printf("ohci_resume: ??? Controller not resumeded!\n");
+                printf("ohci_resume: OHCI_CONTROL: 0x%x\n",ctl);
+        }
+
+#ifdef USB_DEBUG
+        ohci_dumpregs(sc);
+#endif
+
+	/* reset or controller may not start */
+	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
+	usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
+
+        /* spec says save frame interrupt value, reset, then restore */
+        ival =3D OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL));
+        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */
+        usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
+/*	OWRITE4(sc, OHCI_FM_INTERVAL, ival);*/
+
+ 	/* Some broken BIOSes do not recover these values */
+	OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
+	OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
+	OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
+	/* disable all interrupts and then switch on all desired interrupts */
+	OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
+	OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_intre | OHCI_MIE );
+
+	fm =3D (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT;
+	fm |=3D OHCI_FSMPS(ival) | ival;
+	OWRITE4(sc, OHCI_FM_INTERVAL, fm);
+	per =3D OHCI_PERIODIC(ival);
+	OWRITE4(sc, OHCI_PERIODIC_START, per);
+	printf("ohci_resume: fm=3D0x%x per=3D0x%x\n",fm,per);
+
+	/* start controller */
+        ctl =3D sc->sc_control;
+        OWRITE4(sc, OHCI_CONTROL, ctl);
+        usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
+
+	/* power up ports */
+	OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC);
+	usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY);
+	splx(s);
+#ifdef USB_DEBUG
+        ohci_dumpregs(sc);
+#endif
+=09
+	return (USBD_NORMAL_COMPLETION);
+}
+
+usbd_status
+ohci_suspend(struct ohci_softc *sc)
+{
+	u_int32_t ctl,i;
+	int s;
+
+#ifdef USB_DEBUG
+        ohci_dumpregs(sc);
+#endif
+	/*
+         * Preserve register values, in case that APM BIOS
+         * does not recover them.
+         */
+        sc->sc_control =3D OREAD4(sc, OHCI_CONTROL);
+        sc->sc_intre =3D OREAD4(sc, OHCI_INTERRUPT_ENABLE);
+/*	sc->sc_port1 =3D OREAD4(sc, OHCI_RH_PORT_STATUS(1));
+	sc->sc_port2 =3D OREAD4(sc, OHCI_RH_PORT_STATUS(2));*/
+	s =3D splhardusb();
+	/* disable interrupts */
+	OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
+	splx(s);
+	/*  */
+/*	sc->sc_fmrem =3D OREAD4(sc, OHCI_FM_REMAINING);
+        sc->sc_fmnum =3D OREAD4(sc, OHCI_FM_NUMBER);*/
+	/* Reset to stop processing frames or the controller might not suspend */
+	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
+	usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
+	/* now suspend */
+	ctl =3D OHCI_HCFS_SUSPEND;
+	OWRITE4(sc, OHCI_CONTROL, ctl);
+	usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
+	/* check if the controller is suspended */
+	ctl =3D OREAD4(sc, OHCI_CONTROL);
+	if((ctl & OHCI_HCFS_SUSPEND) =3D=3D OHCI_HCFS_SUSPEND) {
+		printf("ohci_suspend: Controller suspended.\n");
+	} else {
+		/* panic or abort? */
+		printf("ohci_suspend: ??? Controller not suspended!\n");
+		printf("ohci_suspend: OHCI_CONTROL: 0x%x\n",ctl);
+	}
+	return (USBD_NORMAL_COMPLETION);
+}
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
 void
 ohci_power(int why, void *v)
 {
diff -u usb.orig/ohci_pci.c usb/ohci_pci.c
=2D-- usb.orig/ohci_pci.c	Tue Sep  9 02:56:49 2003
+++ usb/ohci_pci.c	Tue Sep  9 03:03:33 2003
@@ -304,11 +304,42 @@
 	return 0;
 }
=20
+/* implement suspend and resume */
+static int
+ohci_pci_suspend(device_t self)
+{
+	int err;
+	ohci_softc_t *sc =3D device_get_softc(self);
+	err =3D bus_generic_suspend(self);
+	if (err)
+		return err;
+	ohci_suspend(sc);
+	return 0;
+}
+
+static int
+ohci_pci_resume(device_t self)
+{
+	ohci_softc_t *sc =3D device_get_softc(self);
+	device_printf(self, "ohci_pci_resume: power_state =3D 0x%08x\n",
+					pci_get_powerstate(self));
+	pci_set_powerstate(self, PCI_POWERSTATE_D0);
+	if(ohci_resume(sc) !=3D USBD_NORMAL_COMPLETION) {
+		return ENXIO;
+	}
+	bus_generic_resume(self);
+
+	return 0;
+}
+
 static device_method_t ohci_methods[] =3D {
 	/* Device interface */
 	DEVMETHOD(device_probe, ohci_pci_probe),
 	DEVMETHOD(device_attach, ohci_pci_attach),
=2D	DEVMETHOD(device_shutdown, bus_generic_shutdown),
+	DEVMETHOD(device_detach, bus_generic_detach),
+	DEVMETHOD(device_suspend, ohci_pci_suspend),
+	DEVMETHOD(device_resume, ohci_pci_resume),
+ 	DEVMETHOD(device_shutdown, bus_generic_shutdown),
=20
 	/* Bus interface */
 	DEVMETHOD(bus_print_child, bus_generic_print_child),
diff -u usb.orig/ohcivar.h usb/ohcivar.h
=2D-- usb.orig/ohcivar.h	Tue Sep  9 02:56:49 2003
+++ usb/ohcivar.h	Tue Sep  9 03:03:33 2003
@@ -158,6 +158,8 @@
 #define OXFER(xfer) ((struct ohci_xfer *)(xfer))
=20
 usbd_status	ohci_init(ohci_softc_t *);
+usbd_status	ohci_suspend(ohci_softc_t *);
+usbd_status	ohci_resume(ohci_softc_t *);
 int		ohci_intr(void *);
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 int		ohci_detach(ohci_softc_t *, int);

--Boundary-01=_a7XX/U1scR9TTaL--

--Boundary-03=_a7XX/yXtniDRQ/N
Content-Type: application/pgp-signature
Content-Description: signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (FreeBSD)

iD8DBQA/XX7axqA5ziudZT0RArerAJ9DxkiYhVBC/hEvj3hVal8D4N3thACeMNQT
De+UzX0NruQ6WDmDTvfmS0A=
=M8pK
-----END PGP SIGNATURE-----

--Boundary-03=_a7XX/yXtniDRQ/N--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309090318.50846.mistry.7>