root/dev/cardbus/ohci_cardbus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ohci_cardbus_match
  2. ohci_cardbus_attach
  3. ohci_cardbus_detach

    1 /*      $OpenBSD: ohci_cardbus.c,v 1.9 2007/03/22 05:53:36 pascoe Exp $ */
    2 /*      $NetBSD: ohci_cardbus.c,v 1.19 2004/08/02 19:14:28 mycroft Exp $        */
    3 
    4 /*
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) at
   10  * Carlstedt Research & Technology.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *        This product includes software developed by the NetBSD
   23  *        Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * USB Open Host Controller driver.
   43  *
   44  * OHCI spec: http://www.intel.com/design/usb/ohci11d.pdf
   45  * USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl
   46  */
   47 
   48 
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/kernel.h>
   52 #include <sys/device.h>
   53 #include <sys/proc.h>
   54 
   55 #include <machine/bus.h>
   56 
   57 #include <dev/cardbus/cardbusvar.h>
   58 #include <dev/pci/pcidevs.h>
   59 
   60 #include <dev/usb/usb.h>
   61 #include <dev/usb/usbdi.h>
   62 #include <dev/usb/usbdivar.h>
   63 #include <dev/usb/usb_mem.h>
   64 
   65 #include <dev/usb/ohcireg.h>
   66 #include <dev/usb/ohcivar.h>
   67 
   68 int     ohci_cardbus_match(struct device *, void *, void *);
   69 void    ohci_cardbus_attach(struct device *, struct device *, void *);
   70 int     ohci_cardbus_detach(struct device *, int);
   71 
   72 struct ohci_cardbus_softc {
   73         ohci_softc_t            sc;
   74         cardbus_chipset_tag_t   sc_cc;
   75         cardbus_function_tag_t  sc_cf;
   76         cardbus_devfunc_t       sc_ct;
   77         void                    *sc_ih;         /* interrupt vectoring */
   78 };
   79 
   80 struct cfattach ohci_cardbus_ca = {
   81         sizeof(struct ohci_cardbus_softc), ohci_cardbus_match,
   82             ohci_cardbus_attach, ohci_cardbus_detach, ohci_activate
   83 };
   84 
   85 #define CARDBUS_INTERFACE_OHCI PCI_INTERFACE_OHCI
   86 #define CARDBUS_CBMEM PCI_CBMEM
   87 #define cardbus_findvendor pci_findvendor
   88 #define cardbus_devinfo pci_devinfo
   89 
   90 int
   91 ohci_cardbus_match(struct device *parent, void *match, void *aux)
   92 {
   93         struct cardbus_attach_args *ca = (struct cardbus_attach_args *)aux;
   94 
   95         if (CARDBUS_CLASS(ca->ca_class) == CARDBUS_CLASS_SERIALBUS &&
   96             CARDBUS_SUBCLASS(ca->ca_class) == CARDBUS_SUBCLASS_SERIALBUS_USB &&
   97             CARDBUS_INTERFACE(ca->ca_class) == CARDBUS_INTERFACE_OHCI)
   98                 return (1);
   99  
  100         return (0);
  101 }
  102 
  103 void
  104 ohci_cardbus_attach(struct device *parent, struct device *self, void *aux)
  105 {
  106         struct ohci_cardbus_softc *sc = (struct ohci_cardbus_softc *)self;
  107         struct cardbus_attach_args *ca = aux;
  108         cardbus_devfunc_t ct = ca->ca_ct;
  109         cardbus_chipset_tag_t cc = ct->ct_cc;
  110         cardbus_function_tag_t cf = ct->ct_cf;
  111         cardbusreg_t csr;
  112         char devinfo[256];
  113         usbd_status r;
  114         const char *vendor;
  115         const char *devname = sc->sc.sc_bus.bdev.dv_xname;
  116 
  117         cardbus_devinfo(ca->ca_id, ca->ca_class, 0, devinfo, sizeof(devinfo));
  118         printf(" %s", devinfo);
  119 
  120         /* Map I/O registers */
  121         if (Cardbus_mapreg_map(ct, CARDBUS_CBMEM, CARDBUS_MAPREG_TYPE_MEM, 0,
  122                            &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
  123                 printf("%s: can't map mem space\n", devname);
  124                 return;
  125         }
  126 
  127         /* Disable interrupts, so we don't get any spurious ones. */
  128         bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
  129                           OHCI_MIE);
  130 
  131         sc->sc_cc = cc;
  132         sc->sc_cf = cf;
  133         sc->sc_ct = ct;
  134         sc->sc.sc_bus.dmatag = ca->ca_dmat;
  135 
  136         (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
  137         (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  138 
  139         /* Enable the device. */
  140         csr = cardbus_conf_read(cc, cf, ca->ca_tag,
  141                                 CARDBUS_COMMAND_STATUS_REG);
  142         cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG,
  143                        csr | CARDBUS_COMMAND_MASTER_ENABLE
  144                            | CARDBUS_COMMAND_MEM_ENABLE);
  145 
  146         sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline,
  147                                            IPL_USB, ohci_intr, sc, devname);
  148         if (sc->sc_ih == NULL) {
  149                 printf("%s: couldn't establish interrupt\n", devname);
  150                 return;
  151         }
  152         printf(": irq %d", ca->ca_intrline);
  153 
  154         /* Figure out vendor for root hub descriptor. */
  155         vendor = cardbus_findvendor(ca->ca_id);
  156         sc->sc.sc_id_vendor = CARDBUS_VENDOR(ca->ca_id);
  157         if (vendor)
  158                 strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor));
  159         else
  160                 snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
  161                     "vendor 0x%04x", CARDBUS_VENDOR(ca->ca_id));
  162 
  163         /* Display revision and perform legacy emulation handover. */
  164         if (ohci_checkrev(&sc->sc) != USBD_NORMAL_COMPLETION ||
  165             ohci_handover(&sc->sc) != USBD_NORMAL_COMPLETION) {
  166                 cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih);
  167                 sc->sc_ih = 0;
  168                 return;
  169         }
  170 
  171         r = ohci_init(&sc->sc);
  172         if (r != USBD_NORMAL_COMPLETION) {
  173                 printf("%s: init failed, error=%d\n", devname, r);
  174 
  175                 /* Avoid spurious interrupts. */
  176                 cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih);
  177                 sc->sc_ih = 0;
  178 
  179                 return;
  180         }
  181 
  182         sc->sc.sc_powerhook = powerhook_establish(ohci_power, &sc->sc);
  183 
  184         /* Attach usb device. */
  185         sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus,
  186                                        usbctlprint);
  187 }
  188 
  189 int
  190 ohci_cardbus_detach(struct device *self, int flags)
  191 {
  192         struct ohci_cardbus_softc *sc = (struct ohci_cardbus_softc *)self;
  193         struct cardbus_devfunc *ct = sc->sc_ct;
  194         int rv;
  195 
  196         rv = ohci_detach(&sc->sc, flags);
  197         if (rv)
  198                 return (rv);
  199 
  200         if (sc->sc.sc_powerhook != NULL)
  201                 powerhook_disestablish(sc->sc.sc_powerhook);
  202 
  203         if (sc->sc_ih != NULL) {
  204                 cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih);
  205                 sc->sc_ih = NULL;
  206         }
  207         if (sc->sc.sc_size) {
  208                 Cardbus_mapreg_unmap(ct, CARDBUS_CBMEM, sc->sc.iot,
  209                     sc->sc.ioh, sc->sc.sc_size);
  210                 sc->sc.sc_size = 0;
  211         }
  212 
  213         return (0);
  214 }

/* [<][>][^][v][top][bottom][index][help] */