Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Add root hub emulation.



details:   https://anonhg.NetBSD.org/src/rev/f68b0a7db418
branches:  trunk
changeset: 517604:f68b0a7db418
user:      augustss <augustss%NetBSD.org@localhost>
date:      Thu Nov 15 23:25:09 2001 +0000

description:
Add root hub emulation.

diffstat:

 sys/dev/usb/ehci.c    |  967 +++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/usb/ehcireg.h |    8 +-
 sys/dev/usb/ehcivar.h |   13 +-
 3 files changed, 974 insertions(+), 14 deletions(-)

diffs (truncated from 1089 to 300 lines):

diff -r e19b8800375a -r f68b0a7db418 sys/dev/usb/ehci.c
--- a/sys/dev/usb/ehci.c        Thu Nov 15 22:16:17 2001 +0000
+++ b/sys/dev/usb/ehci.c        Thu Nov 15 23:25:09 2001 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: ehci.c,v 1.4 2001/11/13 06:24:53 lukem Exp $   */
+/*     $NetBSD: ehci.c,v 1.5 2001/11/15 23:25:09 augustss Exp $        */
 
 /*
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -39,13 +39,13 @@
 /*
  * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
  *
- * EHCI 0.96 spec can be found at
+ * The EHCI 0.96 spec can be found at
  * http://developer.intel.com/technology/usb/download/ehci-r096.pdf
  *
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.4 2001/11/13 06:24:53 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.5 2001/11/15 23:25:09 augustss Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -71,13 +71,141 @@
 #ifdef EHCI_DEBUG
 #define DPRINTF(x)     if (ehcidebug) printf x
 #define DPRINTFN(n,x)  if (ehcidebug>(n)) printf x
-int ehcidebug = 1;
+int ehcidebug = 5;
 #define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
 #else
 #define DPRINTF(x)
 #define DPRINTFN(n,x)
 #endif
 
+struct ehci_pipe {
+       struct usbd_pipe pipe;
+};
+
+Static void            ehci_shutdown(void *);
+Static void            ehci_power(int, void *);
+
+Static usbd_status     ehci_open(usbd_pipe_handle);
+Static void            ehci_poll(struct usbd_bus *);
+Static void            ehci_softintr(void *);
+
+Static usbd_status     ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
+Static void            ehci_freem(struct usbd_bus *, usb_dma_t *);
+
+Static usbd_xfer_handle        ehci_allocx(struct usbd_bus *);
+Static void            ehci_freex(struct usbd_bus *, usbd_xfer_handle);
+
+Static usbd_status     ehci_root_ctrl_transfer(usbd_xfer_handle);
+Static usbd_status     ehci_root_ctrl_start(usbd_xfer_handle);
+Static void            ehci_root_ctrl_abort(usbd_xfer_handle);
+Static void            ehci_root_ctrl_close(usbd_pipe_handle);
+Static void            ehci_root_ctrl_done(usbd_xfer_handle);
+
+Static usbd_status     ehci_root_intr_transfer(usbd_xfer_handle);
+Static usbd_status     ehci_root_intr_start(usbd_xfer_handle);
+Static void            ehci_root_intr_abort(usbd_xfer_handle);
+Static void            ehci_root_intr_close(usbd_pipe_handle);
+Static void            ehci_root_intr_done(usbd_xfer_handle);
+
+Static usbd_status     ehci_device_ctrl_transfer(usbd_xfer_handle);
+Static usbd_status     ehci_device_ctrl_start(usbd_xfer_handle);
+Static void            ehci_device_ctrl_abort(usbd_xfer_handle);
+Static void            ehci_device_ctrl_close(usbd_pipe_handle);
+Static void            ehci_device_ctrl_done(usbd_xfer_handle);
+
+Static usbd_status     ehci_device_bulk_transfer(usbd_xfer_handle);
+Static usbd_status     ehci_device_bulk_start(usbd_xfer_handle);
+Static void            ehci_device_bulk_abort(usbd_xfer_handle);
+Static void            ehci_device_bulk_close(usbd_pipe_handle);
+Static void            ehci_device_bulk_done(usbd_xfer_handle);
+
+Static usbd_status     ehci_device_intr_transfer(usbd_xfer_handle);
+Static usbd_status     ehci_device_intr_start(usbd_xfer_handle);
+Static void            ehci_device_intr_abort(usbd_xfer_handle);
+Static void            ehci_device_intr_close(usbd_pipe_handle);
+Static void            ehci_device_intr_done(usbd_xfer_handle);
+
+Static usbd_status     ehci_device_isoc_transfer(usbd_xfer_handle);
+Static usbd_status     ehci_device_isoc_start(usbd_xfer_handle);
+Static void            ehci_device_isoc_abort(usbd_xfer_handle);
+Static void            ehci_device_isoc_close(usbd_pipe_handle);
+Static void            ehci_device_isoc_done(usbd_xfer_handle);
+
+Static void            ehci_device_clear_toggle(usbd_pipe_handle pipe);
+Static void            ehci_noop(usbd_pipe_handle pipe);
+
+Static int             ehci_str(usb_string_descriptor_t *, int, char *);
+
+#ifdef EHCI_DEBUG
+Static void            ehci_dumpregs(ehci_softc_t *);
+#endif
+
+#define EHCI_INTR_ENDPT 1
+
+Static struct usbd_bus_methods ehci_bus_methods = {
+       ehci_open,
+       ehci_softintr,
+       ehci_poll,
+       ehci_allocm,
+       ehci_freem,
+       ehci_allocx,
+       ehci_freex,
+};
+
+Static struct usbd_pipe_methods ehci_root_ctrl_methods = {     
+       ehci_root_ctrl_transfer,
+       ehci_root_ctrl_start,
+       ehci_root_ctrl_abort,
+       ehci_root_ctrl_close,
+       ehci_noop,
+       ehci_root_ctrl_done,
+};
+
+Static struct usbd_pipe_methods ehci_root_intr_methods = {     
+       ehci_root_intr_transfer,
+       ehci_root_intr_start,
+       ehci_root_intr_abort,
+       ehci_root_intr_close,
+       ehci_noop,
+       ehci_root_intr_done,
+};
+
+Static struct usbd_pipe_methods ehci_device_ctrl_methods = {   
+       ehci_device_ctrl_transfer,
+       ehci_device_ctrl_start,
+       ehci_device_ctrl_abort,
+       ehci_device_ctrl_close,
+       ehci_noop,
+       ehci_device_ctrl_done,
+};
+
+Static struct usbd_pipe_methods ehci_device_intr_methods = {   
+       ehci_device_intr_transfer,
+       ehci_device_intr_start,
+       ehci_device_intr_abort,
+       ehci_device_intr_close,
+       ehci_device_clear_toggle,
+       ehci_device_intr_done,
+};
+
+Static struct usbd_pipe_methods ehci_device_bulk_methods = {   
+       ehci_device_bulk_transfer,
+       ehci_device_bulk_start,
+       ehci_device_bulk_abort,
+       ehci_device_bulk_close,
+       ehci_device_clear_toggle,
+       ehci_device_bulk_done,
+};
+
+Static struct usbd_pipe_methods ehci_device_isoc_methods = {
+       ehci_device_isoc_transfer,
+       ehci_device_isoc_start,
+       ehci_device_isoc_abort,
+       ehci_device_isoc_close,
+       ehci_noop,
+       ehci_device_isoc_done,
+};
+
 usbd_status
 ehci_init(ehci_softc_t *sc)
 {
@@ -110,6 +238,7 @@
                        printf(" %s", USBDEVNAME(sc->sc_comps[i]->bdev));
                printf("\n");
        }
+       sc->sc_noport = EHCI_HCS_N_PORTS(sparams);
        cparams = EREAD4(sc, EHCI_HCCPARAMS);
        DPRINTF(("ehci_init: cparams=0x%x\n", cparams));
        
@@ -142,11 +271,16 @@
                           EHCI_FLALIGN_ALIGN, &sc->sc_fldma);
        if (err)
                return (err);
-       //sc->sc_fl = (struct ohci_hcca *)KERNADDR(&sc->sc_hccadma);
        DPRINTF(("%s: flsize=%d\n", USBDEVNAME(sc->sc_bus.bdev),sc->sc_flsize));
 
-       printf("%s: EHCI not supported yet.\n", USBDEVNAME(sc->sc_bus.bdev));
-       return (USBD_IOERROR);
+       /* Set up the bus struct. */
+       sc->sc_bus.methods = &ehci_bus_methods;
+       sc->sc_bus.pipe_size = sizeof(struct ehci_pipe);
+
+       sc->sc_powerhook = powerhook_establish(ehci_power, sc);
+       sc->sc_shutdownhook = shutdownhook_establish(ehci_shutdown, sc);
+
+       return (USBD_NORMAL_COMPLETION);
 }
 
 int
@@ -155,6 +289,32 @@
        return (0);
 }
 
+void
+ehci_softintr(void *v)
+{
+       //ehci_softc_t *sc = v;
+}
+
+void
+ehci_poll(struct usbd_bus *bus)
+{
+#if 0
+       ehci_softc_t *sc = (ehci_softc_t *)bus;
+#ifdef EHCI_DEBUG
+       static int last;
+       int new;
+       new = OREAD4(sc, EHCI_INTERRUPT_STATUS);
+       if (new != last) {
+               DPRINTFN(10,("ehci_poll: intrs=0x%04x\n", new));
+               last = new;
+       }
+#endif
+
+       if (OREAD4(sc, EHCI_INTERRUPT_STATUS) & sc->sc_eintrs)
+               ehci_intr1(sc);
+#endif
+}
+
 int
 ehci_detach(struct ehci_softc *sc, int flags)
 {
@@ -191,8 +351,799 @@
        case DVACT_DEACTIVATE:
                if (sc->sc_child != NULL)
                        rv = config_deactivate(sc->sc_child);
+               sc->sc_dying = 1;
                break;
        }
        return (rv);
 }
 
+/*
+ * Handle suspend/resume.
+ *
+ * We need to switch to polling mode here, because this routine is
+ * called from an intterupt context.  This is all right since we
+ * are almost suspended anyway.
+ */
+void
+ehci_power(int why, void *v)
+{
+       ehci_softc_t *sc = v;
+       //u_int32_t ctl;
+       int s;
+
+#ifdef EHCI_DEBUG
+       DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why));
+       ehci_dumpregs(sc);
+#endif
+
+       s = splhardusb();
+       switch (why) {
+       case PWR_SUSPEND:
+       case PWR_STANDBY:
+               sc->sc_bus.use_polling++;
+#if 0
+OOO
+               ctl = OREAD4(sc, EHCI_CONTROL) & ~EHCI_HCFS_MASK;
+               if (sc->sc_control == 0) {
+                       /*
+                        * Preserve register values, in case that APM BIOS
+                        * does not recover them.
+                        */
+                       sc->sc_control = ctl;
+                       sc->sc_intre = OREAD4(sc, EHCI_INTERRUPT_ENABLE);
+               }
+               ctl |= EHCI_HCFS_SUSPEND;
+               OWRITE4(sc, EHCI_CONTROL, ctl);
+#endif
+               usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
+               sc->sc_bus.use_polling--;
+               break;
+       case PWR_RESUME:
+               sc->sc_bus.use_polling++;
+#if 0
+OOO
+               /* Some broken BIOSes do not recover these values */
+               OWRITE4(sc, EHCI_HCCA, DMAADDR(&sc->sc_hccadma));
+               OWRITE4(sc, EHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
+               OWRITE4(sc, EHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
+               if (sc->sc_intre)
+                       OWRITE4(sc, EHCI_INTERRUPT_ENABLE,
+                               sc->sc_intre & (EHCI_ALL_INTRS | EHCI_MIE));
+               if (sc->sc_control)
+                       ctl = sc->sc_control;
+               else
+                       ctl = OREAD4(sc, EHCI_CONTROL);
+               ctl |= EHCI_HCFS_RESUME;



Home | Main Index | Thread Index | Old Index