[BACK]Return to uhci_pci.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/uhci_pci.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uhci_pci.c,v 1.25 2007/03/22 05:53:36 pascoe Exp $    */
                      2: /*     $NetBSD: uhci_pci.c,v 1.24 2002/10/02 16:51:58 thorpej 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: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/kernel.h>
                     44: #include <sys/device.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/queue.h>
                     47:
                     48: #include <machine/bus.h>
                     49:
                     50: #include <dev/pci/pcivar.h>
                     51:
                     52: #include <dev/usb/usb.h>
                     53: #include <dev/usb/usbdi.h>
                     54: #include <dev/usb/usbdivar.h>
                     55: #include <dev/usb/usb_mem.h>
                     56:
                     57: #include <dev/usb/uhcireg.h>
                     58: #include <dev/usb/uhcivar.h>
                     59:
                     60: int    uhci_pci_match(struct device *, void *, void *);
                     61: void   uhci_pci_attach(struct device *, struct device *, void *);
                     62: void   uhci_pci_attach_deferred(struct device *);
                     63: int    uhci_pci_detach(struct device *, int);
                     64:
                     65: struct uhci_pci_softc {
                     66:        uhci_softc_t            sc;
                     67:        pci_chipset_tag_t       sc_pc;
                     68:        pcitag_t                sc_tag;
                     69:        void                    *sc_ih;         /* interrupt vectoring */
                     70: };
                     71:
                     72: struct cfattach uhci_pci_ca = {
                     73:        sizeof(struct uhci_pci_softc), uhci_pci_match, uhci_pci_attach,
                     74:        uhci_pci_detach, uhci_activate
                     75: };
                     76:
                     77: int
                     78: uhci_pci_match(struct device *parent, void *match, void *aux)
                     79: {
                     80:        struct pci_attach_args *pa = (struct pci_attach_args *) aux;
                     81:
                     82:        if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS &&
                     83:            PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB &&
                     84:            PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_UHCI)
                     85:                return (1);
                     86:
                     87:        return (0);
                     88: }
                     89:
                     90: void
                     91: uhci_pci_attach(struct device *parent, struct device *self, void *aux)
                     92: {
                     93:        struct uhci_pci_softc *sc = (struct uhci_pci_softc *)self;
                     94:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                     95:        pci_chipset_tag_t pc = pa->pa_pc;
                     96:        pcitag_t tag = pa->pa_tag;
                     97:        char const *intrstr;
                     98:        pci_intr_handle_t ih;
                     99:        const char *vendor;
                    100:        char *devname = sc->sc.sc_bus.bdev.dv_xname;
                    101:        int s;
                    102:
                    103: #if defined(__NetBSD__)
                    104:        char devinfo[256];
                    105:
                    106:        pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
                    107:        printf(": %s (rev. 0x%02x)", devinfo, PCI_REVISION(pa->pa_class));
                    108: #endif
                    109:
                    110:        /* Map I/O registers */
                    111:        if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
                    112:                    &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size, 0)) {
                    113:                printf(": can't map i/o space\n");
                    114:                return;
                    115:        }
                    116:
                    117:
                    118:        /* Disable interrupts, so we don't get any spurious ones. */
                    119:        s = splhardusb();
                    120:        bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);
                    121:
                    122:        sc->sc_pc = pc;
                    123:        sc->sc_tag = tag;
                    124:        sc->sc.sc_bus.dmatag = pa->pa_dmat;
                    125:
                    126:        /* Map and establish the interrupt. */
                    127:        if (pci_intr_map(pa, &ih)) {
                    128:                printf(": couldn't map interrupt\n");
                    129:                goto unmap_ret;
                    130:        }
                    131:        intrstr = pci_intr_string(pc, ih);
                    132:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, uhci_intr, sc,
                    133:                                       devname);
                    134:        if (sc->sc_ih == NULL) {
                    135:                printf(": couldn't establish interrupt");
                    136:                if (intrstr != NULL)
                    137:                        printf(" at %s", intrstr);
                    138:                printf("\n");
                    139:                goto unmap_ret;
                    140:        }
                    141:        printf(": %s\n", intrstr);
                    142:
                    143:        /* Set LEGSUP register to its default value. */
                    144:        pci_conf_write(pc, tag, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN);
                    145:
                    146:        switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) {
                    147:        case PCI_USBREV_PRE_1_0:
                    148:                sc->sc.sc_bus.usbrev = USBREV_PRE_1_0;
                    149:                break;
                    150:        case PCI_USBREV_1_0:
                    151:                sc->sc.sc_bus.usbrev = USBREV_1_0;
                    152:                break;
                    153:        case PCI_USBREV_1_1:
                    154:                sc->sc.sc_bus.usbrev = USBREV_1_1;
                    155:                break;
                    156:        default:
                    157:                sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
                    158:                break;
                    159:        }
                    160:
                    161:        uhci_run(&sc->sc, 0);                   /* stop the controller */
                    162:                                                /* disable interrupts */
                    163:        bus_space_barrier(sc->sc.iot, sc->sc.ioh, 0, sc->sc.sc_size,
                    164:            BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
                    165:        bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);
                    166:
                    167:        /* Figure out vendor for root hub descriptor. */
                    168:        vendor = pci_findvendor(pa->pa_id);
                    169:        sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id);
                    170:        if (vendor)
                    171:                strlcpy(sc->sc.sc_vendor, vendor, sizeof (sc->sc.sc_vendor));
                    172:        else
                    173:                snprintf(sc->sc.sc_vendor, sizeof (sc->sc.sc_vendor),
                    174:                        "vendor 0x%04x", PCI_VENDOR(pa->pa_id));
                    175:
                    176:        config_defer(self, uhci_pci_attach_deferred);
                    177:
                    178:        /* Ignore interrupts for now */
                    179:        sc->sc.sc_dying = 1;
                    180:
                    181:        splx(s);
                    182:
                    183:        return;
                    184:
                    185: unmap_ret:
                    186:        bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
                    187:        splx(s);
                    188: }
                    189:
                    190: void
                    191: uhci_pci_attach_deferred(struct device *self)
                    192: {
                    193:        struct uhci_pci_softc *sc = (struct uhci_pci_softc *)self;
                    194:        char *devname = sc->sc.sc_bus.bdev.dv_xname;
                    195:        usbd_status r;
                    196:        int s;
                    197:
                    198:        s = splhardusb();
                    199:
                    200:        sc->sc.sc_dying = 0;
                    201:        r = uhci_init(&sc->sc);
                    202:        if (r != USBD_NORMAL_COMPLETION) {
                    203:                printf("%s: init failed, error=%d\n", devname, r);
                    204:                goto unmap_ret;
                    205:        }
                    206:        splx(s);
                    207:
                    208:        /* Attach usb device. */
                    209:        sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus,
                    210:                                       usbctlprint);
                    211:
                    212:        return;
                    213:
                    214: unmap_ret:
                    215:        bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
                    216:        splx(s);
                    217: }
                    218:
                    219: int
                    220: uhci_pci_detach(struct device *self, int flags)
                    221: {
                    222:        struct uhci_pci_softc *sc = (struct uhci_pci_softc *)self;
                    223:        int rv;
                    224:
                    225:        rv = uhci_detach(&sc->sc, flags);
                    226:        if (rv)
                    227:                return (rv);
                    228:        if (sc->sc_ih != NULL) {
                    229:                pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
                    230:                sc->sc_ih = NULL;
                    231:        }
                    232:        if (sc->sc.sc_size) {
                    233:                bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
                    234:                sc->sc.sc_size = 0;
                    235:        }
                    236:
                    237:        return (0);
                    238: }

CVSweb