The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/ehci_pci.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ehci_pci.c,v 1.13 2003/01/31 00:07:41 thorpej Exp $    */
    2 
    3 /*
    4  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Lennart Augustsson (lennart@augustsson.net).
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.13 2003/01/31 00:07:41 thorpej Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/device.h>
   46 #include <sys/proc.h>
   47 #include <sys/queue.h>
   48 
   49 #include <machine/bus.h>
   50 
   51 #include <dev/pci/pcivar.h>
   52 #include <dev/pci/usb_pci.h>
   53 
   54 #include <dev/usb/usb.h>
   55 #include <dev/usb/usbdi.h>
   56 #include <dev/usb/usbdivar.h>
   57 #include <dev/usb/usb_mem.h>
   58 
   59 #include <dev/usb/ehcireg.h>
   60 #include <dev/usb/ehcivar.h>
   61 
   62 #ifdef EHCI_DEBUG
   63 #define DPRINTF(x)      if (ehcidebug) printf x
   64 extern int ehcidebug;
   65 #else
   66 #define DPRINTF(x)
   67 #endif
   68 
   69 int     ehci_pci_match(struct device *, struct cfdata *, void *);
   70 void    ehci_pci_attach(struct device *, struct device *, void *);
   71 int     ehci_pci_detach(device_ptr_t, int);
   72 
   73 struct ehci_pci_softc {
   74         ehci_softc_t            sc;
   75         pci_chipset_tag_t       sc_pc;
   76         pcitag_t                sc_tag;
   77         void                    *sc_ih;         /* interrupt vectoring */
   78 };
   79 
   80 CFATTACH_DECL(ehci_pci, sizeof(struct ehci_pci_softc),
   81     ehci_pci_match, ehci_pci_attach, ehci_pci_detach, ehci_activate);
   82 
   83 int
   84 ehci_pci_match(struct device *parent, struct cfdata *match, void *aux)
   85 {
   86         struct pci_attach_args *pa = (struct pci_attach_args *) aux;
   87 
   88         if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS &&
   89             PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB &&
   90             PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_EHCI)
   91                 return (1);
   92  
   93         return (0);
   94 }
   95 
   96 void
   97 ehci_pci_attach(struct device *parent, struct device *self, void *aux)
   98 {
   99         struct ehci_pci_softc *sc = (struct ehci_pci_softc *)self;
  100         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  101         pci_chipset_tag_t pc = pa->pa_pc;
  102         pcitag_t tag = pa->pa_tag;
  103         char const *intrstr;
  104         pci_intr_handle_t ih;
  105         pcireg_t csr;
  106         char *vendor;
  107         char *devname = sc->sc.sc_bus.bdev.dv_xname;
  108         char devinfo[256];
  109         usbd_status r;
  110         int ncomp;
  111         struct usb_pci *up;
  112 
  113         aprint_naive(": USB controller\n");
  114 
  115         pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
  116         aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
  117             PCI_REVISION(pa->pa_class));
  118 
  119         /* Map I/O registers */
  120         if (pci_mapreg_map(pa, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0,
  121                            &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
  122                 aprint_error("%s: can't map memory space\n", devname);
  123                 return;
  124         }
  125 
  126         sc->sc_pc = pc;
  127         sc->sc_tag = tag;
  128         sc->sc.sc_bus.dmatag = pa->pa_dmat;
  129 
  130         /* Enable the device. */
  131         csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
  132         pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
  133                        csr | PCI_COMMAND_MASTER_ENABLE);
  134 
  135         /* Disable interrupts, so we don't get any spurious ones. */
  136         sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
  137         DPRINTF(("%s: offs=%d\n", devname, sc->sc.sc_offs));
  138         EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
  139 
  140         /* Map and establish the interrupt. */
  141         if (pci_intr_map(pa, &ih)) {
  142                 aprint_error("%s: couldn't map interrupt\n", devname);
  143                 return;
  144         }
  145         intrstr = pci_intr_string(pc, ih);
  146         sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, ehci_intr, sc);
  147         if (sc->sc_ih == NULL) {
  148                 aprint_error("%s: couldn't establish interrupt", devname);
  149                 if (intrstr != NULL)
  150                         aprint_normal(" at %s", intrstr);
  151                 aprint_normal("\n");
  152                 return;
  153         }
  154         aprint_normal("%s: interrupting at %s\n", devname, intrstr);
  155 
  156         switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) {
  157         case PCI_USBREV_PRE_1_0:
  158         case PCI_USBREV_1_0:
  159         case PCI_USBREV_1_1:
  160                 sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
  161                 aprint_normal("%s: pre-2.0 USB rev\n", devname);
  162                 return;
  163         case PCI_USBREV_2_0:
  164                 sc->sc.sc_bus.usbrev = USBREV_2_0;
  165                 break;
  166         default:
  167                 sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
  168                 break;
  169         }
  170 
  171         /* Figure out vendor for root hub descriptor. */
  172         vendor = pci_findvendor(pa->pa_id);
  173         sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id);
  174         if (vendor)
  175                 strncpy(sc->sc.sc_vendor, vendor,
  176                         sizeof(sc->sc.sc_vendor) - 1);
  177         else
  178                 sprintf(sc->sc.sc_vendor, "vendor 0x%04x",
  179                         PCI_VENDOR(pa->pa_id));
  180         
  181         /*
  182          * Find companion controllers.  According to the spec they always
  183          * have lower function numbers so they should be enumerated already.
  184          */
  185         ncomp = 0;
  186         TAILQ_FOREACH(up, &ehci_pci_alldevs, next) {
  187                 if (up->bus == pa->pa_bus && up->device == pa->pa_device) {
  188                         DPRINTF(("ehci_pci_attach: companion %s\n",
  189                                  USBDEVNAME(up->usb->bdev)));
  190                         sc->sc.sc_comps[ncomp++] = up->usb;
  191                         if (ncomp >= EHCI_COMPANION_MAX)
  192                                 break;
  193                 }
  194         }
  195         sc->sc.sc_ncomp = ncomp;
  196 
  197         r = ehci_init(&sc->sc);
  198         if (r != USBD_NORMAL_COMPLETION) {
  199                 aprint_error("%s: init failed, error=%d\n", devname, r);
  200                 return;
  201         }
  202 
  203         /* Attach usb device. */
  204         sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus,
  205                                        usbctlprint);
  206 }
  207 
  208 int
  209 ehci_pci_detach(device_ptr_t self, int flags)
  210 {
  211         struct ehci_pci_softc *sc = (struct ehci_pci_softc *)self;
  212         int rv;
  213 
  214         rv = ehci_detach(&sc->sc, flags);
  215         if (rv)
  216                 return (rv);
  217         if (sc->sc_ih != NULL) {
  218                 pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
  219                 sc->sc_ih = NULL;
  220         }
  221         if (sc->sc.sc_size) {
  222                 bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
  223                 sc->sc.sc_size = 0;
  224         }
  225         return (0);
  226 }

Cache object: 2a56552de556826166ab2df8f3c16946


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.