[BACK]Return to ehci_pci.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/ehci_pci.c, Revision 1.52

1.52    ! dyoung      1: /*     $NetBSD: ehci_pci.c,v 1.51 2011/04/04 20:37:56 dyoung Exp $     */
1.1       augustss    2:
                      3: /*
1.8       augustss    4:  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
1.1       augustss    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:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
1.6       lukem      31:
                     32: #include <sys/cdefs.h>
1.52    ! dyoung     33: __KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.51 2011/04/04 20:37:56 dyoung Exp $");
1.1       augustss   34:
                     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/kernel.h>
                     38: #include <sys/device.h>
                     39: #include <sys/proc.h>
                     40: #include <sys/queue.h>
                     41:
1.31      ad         42: #include <sys/bus.h>
1.1       augustss   43:
1.22      xtraeme    44: #include <dev/pci/pcidevs.h>
1.1       augustss   45: #include <dev/pci/pcivar.h>
1.4       augustss   46: #include <dev/pci/usb_pci.h>
1.1       augustss   47:
                     48: #include <dev/usb/usb.h>
                     49: #include <dev/usb/usbdi.h>
                     50: #include <dev/usb/usbdivar.h>
                     51: #include <dev/usb/usb_mem.h>
                     52:
                     53: #include <dev/usb/ehcireg.h>
                     54: #include <dev/usb/ehcivar.h>
                     55:
1.5       augustss   56: #ifdef EHCI_DEBUG
                     57: #define DPRINTF(x)     if (ehcidebug) printf x
                     58: extern int ehcidebug;
                     59: #else
                     60: #define DPRINTF(x)
                     61: #endif
                     62:
1.45      cegger     63: enum ehci_pci_quirk_flags {
                     64:        EHCI_PCI_QUIRK_AMD_SB600 = 0x1, /* always need a quirk */
                     65:        EHCI_PCI_QUIRK_AMD_SB700 = 0x2, /* depends on the SMB revision */
                     66: };
                     67:
                     68: static const struct pci_quirkdata ehci_pci_quirks[] = {
                     69:        { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB600_USB_EHCI,
                     70:            EHCI_PCI_QUIRK_AMD_SB600 },
                     71:        { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_SB700_USB_EHCI,
                     72:            EHCI_PCI_QUIRK_AMD_SB700 },
                     73: };
                     74:
1.34      jmcneill   75: static void ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc,
                     76:                                   pcitag_t tag);
1.19      augustss   77: static void ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc,
                     78:                               pcitag_t tag);
1.47      dyoung     79: static bool ehci_pci_suspend(device_t, const pmf_qual_t *);
                     80: static bool ehci_pci_resume(device_t, const pmf_qual_t *);
1.19      augustss   81:
1.1       augustss   82: struct ehci_pci_softc {
                     83:        ehci_softc_t            sc;
                     84:        pci_chipset_tag_t       sc_pc;
                     85:        pcitag_t                sc_tag;
                     86:        void                    *sc_ih;         /* interrupt vectoring */
                     87: };
                     88:
1.51      dyoung     89: static int ehci_sb700_match(const struct pci_attach_args *pa);
1.45      cegger     90: static int ehci_apply_amd_quirks(struct ehci_pci_softc *sc);
                     91: enum ehci_pci_quirk_flags ehci_pci_lookup_quirkdata(pci_vendor_id_t,
                     92:        pci_product_id_t);
                     93:
1.19      augustss   94: #define EHCI_MAX_BIOS_WAIT             1000 /* ms */
1.45      cegger     95: #define EHCI_SBx00_WORKAROUND_REG      0x50
                     96: #define EHCI_SBx00_WORKAROUND_ENABLE   __BIT(27)
                     97:
1.19      augustss   98:
1.18      thorpej    99: static int
1.41      dyoung    100: ehci_pci_match(device_t parent, cfdata_t match, void *aux)
1.1       augustss  101: {
                    102:        struct pci_attach_args *pa = (struct pci_attach_args *) aux;
                    103:
                    104:        if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS &&
                    105:            PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_USB &&
                    106:            PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_EHCI)
1.41      dyoung    107:                return 1;
1.17      perry     108:
1.41      dyoung    109:        return 0;
1.1       augustss  110: }
                    111:
1.18      thorpej   112: static void
1.41      dyoung    113: ehci_pci_attach(device_t parent, device_t self, void *aux)
1.1       augustss  114: {
1.37      drochner  115:        struct ehci_pci_softc *sc = device_private(self);
1.1       augustss  116:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    117:        pci_chipset_tag_t pc = pa->pa_pc;
                    118:        pcitag_t tag = pa->pa_tag;
                    119:        char const *intrstr;
                    120:        pci_intr_handle_t ih;
                    121:        pcireg_t csr;
1.16      mycroft   122:        const char *vendor;
1.1       augustss  123:        char devinfo[256];
                    124:        usbd_status r;
1.5       augustss  125:        int ncomp;
                    126:        struct usb_pci *up;
1.45      cegger    127:        int quirk;
1.1       augustss  128:
1.37      drochner  129:        sc->sc.sc_dev = self;
                    130:        sc->sc.sc_bus.hci_private = sc;
                    131:
1.13      thorpej   132:        aprint_naive(": USB controller\n");
                    133:
1.15      itojun    134:        pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
1.13      thorpej   135:        aprint_normal(": %s (rev. 0x%02x)\n", devinfo,
                    136:            PCI_REVISION(pa->pa_class));
1.1       augustss  137:
1.45      cegger    138:        /* Check for quirks */
                    139:        quirk = ehci_pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id),
                    140:                                           PCI_PRODUCT(pa->pa_id));
                    141:
1.1       augustss  142:        /* Map I/O registers */
                    143:        if (pci_mapreg_map(pa, PCI_CBMEM, PCI_MAPREG_TYPE_MEM, 0,
                    144:                           &sc->sc.iot, &sc->sc.ioh, NULL, &sc->sc.sc_size)) {
1.43      cegger    145:                sc->sc.sc_size = 0;
                    146:                aprint_error_dev(self, "can't map memory space\n");
1.1       augustss  147:                return;
                    148:        }
                    149:
1.43      cegger    150:        /* Disable interrupts, so we don't get any spurious ones. */
                    151:        sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
                    152:        DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs));
                    153:        EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
                    154:
1.1       augustss  155:        sc->sc_pc = pc;
                    156:        sc->sc_tag = tag;
                    157:        sc->sc.sc_bus.dmatag = pa->pa_dmat;
                    158:
1.45      cegger    159:        /* Handle quirks */
                    160:        switch (quirk) {
                    161:        case EHCI_PCI_QUIRK_AMD_SB600:
                    162:                ehci_apply_amd_quirks(sc);
                    163:                break;
                    164:        case EHCI_PCI_QUIRK_AMD_SB700:
                    165:                if (pci_find_device(NULL, ehci_sb700_match))
                    166:                        ehci_apply_amd_quirks(sc);
                    167:                break;
                    168:        }
                    169:
1.1       augustss  170:        /* Enable the device. */
                    171:        csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
                    172:        pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
                    173:                       csr | PCI_COMMAND_MASTER_ENABLE);
                    174:
                    175:        /* Map and establish the interrupt. */
1.3       sommerfe  176:        if (pci_intr_map(pa, &ih)) {
1.43      cegger    177:                aprint_error_dev(self, "couldn't map interrupt\n");
                    178:                goto fail;
1.1       augustss  179:        }
1.43      cegger    180:
                    181:        /*
                    182:         * Allocate IRQ
                    183:         */
1.1       augustss  184:        intrstr = pci_intr_string(pc, ih);
                    185:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_USB, ehci_intr, sc);
                    186:        if (sc->sc_ih == NULL) {
1.43      cegger    187:                aprint_error_dev(self, "couldn't establish interrupt");
1.1       augustss  188:                if (intrstr != NULL)
1.43      cegger    189:                        aprint_error(" at %s", intrstr);
                    190:                aprint_error("\n");
1.1       augustss  191:                return;
                    192:        }
1.43      cegger    193:        aprint_normal_dev(self, "interrupting at %s\n", intrstr);
1.1       augustss  194:
                    195:        switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) {
                    196:        case PCI_USBREV_PRE_1_0:
                    197:        case PCI_USBREV_1_0:
                    198:        case PCI_USBREV_1_1:
1.4       augustss  199:                sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
1.43      cegger    200:                aprint_verbose_dev(self, "pre-2.0 USB rev\n");
1.4       augustss  201:                return;
1.1       augustss  202:        case PCI_USBREV_2_0:
                    203:                sc->sc.sc_bus.usbrev = USBREV_2_0;
                    204:                break;
                    205:        default:
                    206:                sc->sc.sc_bus.usbrev = USBREV_UNKNOWN;
                    207:                break;
                    208:        }
                    209:
                    210:        /* Figure out vendor for root hub descriptor. */
1.49      pgoyette  211:        vendor = pci_findvendor(pa->pa_id);
1.1       augustss  212:        sc->sc.sc_id_vendor = PCI_VENDOR(pa->pa_id);
                    213:        if (vendor)
1.14      itojun    214:                strlcpy(sc->sc.sc_vendor, vendor, sizeof(sc->sc.sc_vendor));
1.1       augustss  215:        else
1.14      itojun    216:                snprintf(sc->sc.sc_vendor, sizeof(sc->sc.sc_vendor),
                    217:                    "vendor 0x%04x", PCI_VENDOR(pa->pa_id));
1.17      perry     218:
1.22      xtraeme   219:        /* Enable workaround for dropped interrupts as required */
1.30      tsutsui   220:        switch (sc->sc.sc_id_vendor) {
                    221:        case PCI_VENDOR_ATI:
                    222:        case PCI_VENDOR_VIATECH:
1.22      xtraeme   223:                sc->sc.sc_flags |= EHCIF_DROPPED_INTR_WORKAROUND;
1.43      cegger    224:                aprint_normal_dev(self, "dropped intr workaround enabled\n");
1.30      tsutsui   225:                break;
                    226:        default:
                    227:                break;
                    228:        }
1.22      xtraeme   229:
1.5       augustss  230:        /*
                    231:         * Find companion controllers.  According to the spec they always
                    232:         * have lower function numbers so they should be enumerated already.
                    233:         */
1.50      matt      234:        const u_int maxncomp = EHCI_HCS_N_CC(EREAD4(&sc->sc, EHCI_HCSPARAMS));
                    235:        KASSERT(maxncomp <= EHCI_COMPANION_MAX);
1.5       augustss  236:        ncomp = 0;
                    237:        TAILQ_FOREACH(up, &ehci_pci_alldevs, next) {
1.50      matt      238:                if (up->bus == pa->pa_bus && up->device == pa->pa_device
                    239:                    && !up->claimed) {
1.5       augustss  240:                        DPRINTF(("ehci_pci_attach: companion %s\n",
1.37      drochner  241:                                 device_xname(up->usb)));
1.5       augustss  242:                        sc->sc.sc_comps[ncomp++] = up->usb;
1.50      matt      243:                        up->claimed = true;
                    244:                        if (ncomp == maxncomp)
1.5       augustss  245:                                break;
                    246:                }
                    247:        }
                    248:        sc->sc.sc_ncomp = ncomp;
                    249:
1.19      augustss  250:        ehci_get_ownership(&sc->sc, pc, tag);
                    251:
1.1       augustss  252:        r = ehci_init(&sc->sc);
                    253:        if (r != USBD_NORMAL_COMPLETION) {
1.43      cegger    254:                aprint_error_dev(self, "init failed, error=%d\n", r);
                    255:                goto fail;
1.1       augustss  256:        }
                    257:
1.36      dyoung    258:        if (!pmf_device_register1(self, ehci_pci_suspend, ehci_pci_resume,
                    259:                                  ehci_shutdown))
1.32      jmcneill  260:                aprint_error_dev(self, "couldn't establish power handler\n");
                    261:
1.1       augustss  262:        /* Attach usb device. */
1.37      drochner  263:        sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint);
1.43      cegger    264:        return;
                    265:
                    266: fail:
                    267:        if (sc->sc_ih) {
                    268:                pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
                    269:                sc->sc_ih = NULL;
                    270:        }
                    271:        if (sc->sc.sc_size) {
                    272:                ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
                    273:                bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
                    274:                sc->sc.sc_size = 0;
                    275:        }
                    276:        return;
1.1       augustss  277: }
                    278:
1.18      thorpej   279: static int
1.41      dyoung    280: ehci_pci_detach(device_t self, int flags)
1.1       augustss  281: {
1.37      drochner  282:        struct ehci_pci_softc *sc = device_private(self);
1.1       augustss  283:        int rv;
                    284:
                    285:        rv = ehci_detach(&sc->sc, flags);
                    286:        if (rv)
1.41      dyoung    287:                return rv;
1.40      dyoung    288:
1.52    ! dyoung    289:        pmf_device_deregister(self);
        !           290:        ehci_shutdown(self, flags);
        !           291:
1.40      dyoung    292:        /* disable interrupts */
                    293:        EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
                    294:        /* XXX grotty hack to flush the write */
1.42      christos  295:        (void)EOREAD2(&sc->sc, EHCI_USBINTR);
1.40      dyoung    296:
1.1       augustss  297:        if (sc->sc_ih != NULL) {
                    298:                pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
                    299:                sc->sc_ih = NULL;
                    300:        }
                    301:        if (sc->sc.sc_size) {
1.34      jmcneill  302:                ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
1.1       augustss  303:                bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
                    304:                sc->sc.sc_size = 0;
                    305:        }
1.34      jmcneill  306:
1.41      dyoung    307:        return 0;
1.1       augustss  308: }
1.18      thorpej   309:
1.39      dyoung    310: CFATTACH_DECL3_NEW(ehci_pci, sizeof(struct ehci_pci_softc),
1.35      dyoung    311:     ehci_pci_match, ehci_pci_attach, ehci_pci_detach, ehci_activate, NULL,
1.39      dyoung    312:     ehci_childdet, DVF_DETACH_SHUTDOWN);
1.19      augustss  313:
                    314: #ifdef EHCI_DEBUG
                    315: static void
                    316: ehci_dump_caps(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag)
                    317: {
1.44      cegger    318:        uint32_t cparams, legctlsts, addr, cap, id;
1.19      augustss  319:        int maxdump = 10;
                    320:
                    321:        cparams = EREAD4(sc, EHCI_HCCPARAMS);
                    322:        addr = EHCI_HCC_EECP(cparams);
                    323:        while (addr != 0) {
                    324:                cap = pci_conf_read(pc, tag, addr);
                    325:                id = EHCI_CAP_GET_ID(cap);
                    326:                switch (id) {
                    327:                case EHCI_CAP_ID_LEGACY:
                    328:                        legctlsts = pci_conf_read(pc, tag,
                    329:                                                  addr + PCI_EHCI_USBLEGCTLSTS);
1.20      augustss  330:                        printf("ehci_dump_caps: legsup=0x%08x "
                    331:                               "legctlsts=0x%08x\n", cap, legctlsts);
1.19      augustss  332:                        break;
                    333:                default:
1.20      augustss  334:                        printf("ehci_dump_caps: cap=0x%08x\n", cap);
1.19      augustss  335:                        break;
                    336:                }
                    337:                if (--maxdump < 0)
                    338:                        break;
                    339:                addr = EHCI_CAP_GET_NEXT(cap);
                    340:        }
                    341: }
                    342: #endif
                    343:
                    344: static void
1.34      jmcneill  345: ehci_release_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag)
                    346: {
1.37      drochner  347:        const char *devname = device_xname(sc->sc_dev);
1.44      cegger    348:        uint32_t cparams, addr, cap;
1.34      jmcneill  349:        pcireg_t legsup;
                    350:        int maxcap = 10;
                    351:
                    352:        cparams = EREAD4(sc, EHCI_HCCPARAMS);
                    353:        addr = EHCI_HCC_EECP(cparams);
                    354:        while (addr != 0) {
                    355:                cap = pci_conf_read(pc, tag, addr);
                    356:                if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY)
                    357:                        goto next;
                    358:                legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP);
                    359:                pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP,
                    360:                    legsup & ~EHCI_LEG_HC_OS_OWNED);
                    361:
                    362: next:
                    363:                if (--maxcap < 0) {
                    364:                        aprint_normal("%s: broken extended capabilities "
                    365:                                      "ignored\n", devname);
                    366:                        return;
                    367:                }
                    368:                addr = EHCI_CAP_GET_NEXT(cap);
                    369:        }
                    370: }
                    371:
                    372: static void
1.19      augustss  373: ehci_get_ownership(ehci_softc_t *sc, pci_chipset_tag_t pc, pcitag_t tag)
                    374: {
1.37      drochner  375:        const char *devname = device_xname(sc->sc_dev);
1.44      cegger    376:        uint32_t cparams, addr, cap;
1.33      jmcneill  377:        pcireg_t legsup;
1.19      augustss  378:        int maxcap = 10;
                    379:        int ms;
                    380:
                    381: #ifdef EHCI_DEBUG
1.20      augustss  382:        if (ehcidebug)
                    383:                ehci_dump_caps(sc, pc, tag);
1.19      augustss  384: #endif
                    385:        cparams = EREAD4(sc, EHCI_HCCPARAMS);
                    386:        addr = EHCI_HCC_EECP(cparams);
                    387:        while (addr != 0) {
                    388:                cap = pci_conf_read(pc, tag, addr);
1.34      jmcneill  389:                if (EHCI_CAP_GET_ID(cap) != EHCI_CAP_ID_LEGACY)
                    390:                        goto next;
                    391:                legsup = pci_conf_read(pc, tag, addr + PCI_EHCI_USBLEGSUP);
                    392:                /* Ask BIOS to give up ownership */
                    393:                pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGSUP,
                    394:                    legsup | EHCI_LEG_HC_OS_OWNED);
                    395:                if (legsup & EHCI_LEG_HC_BIOS_OWNED) {
                    396:                        for (ms = 0; ms < EHCI_MAX_BIOS_WAIT; ms++) {
                    397:                                legsup = pci_conf_read(pc, tag,
                    398:                                    addr + PCI_EHCI_USBLEGSUP);
                    399:                                if (!(legsup & EHCI_LEG_HC_BIOS_OWNED))
                    400:                                        break;
                    401:                                delay(1000);
                    402:                        }
                    403:                        if (ms == EHCI_MAX_BIOS_WAIT) {
                    404:                                aprint_normal("%s: BIOS refuses to give up "
                    405:                                    "ownership, using force\n", devname);
                    406:                                pci_conf_write(pc, tag,
                    407:                                    addr + PCI_EHCI_USBLEGSUP, 0);
                    408:                        } else
                    409:                                aprint_verbose("%s: BIOS has given up "
                    410:                                    "ownership\n", devname);
                    411:                }
                    412:
                    413:                /* Disable SMIs */
                    414:                pci_conf_write(pc, tag, addr + PCI_EHCI_USBLEGCTLSTS,
                    415:                    EHCI_LEG_EXT_SMI_BAR | EHCI_LEG_EXT_SMI_PCICMD |
                    416:                    EHCI_LEG_EXT_SMI_OS_CHANGE);
                    417:
                    418: next:
1.21      augustss  419:                if (--maxcap < 0) {
                    420:                        aprint_normal("%s: broken extended capabilities "
                    421:                                      "ignored\n", devname);
1.19      augustss  422:                        return;
1.21      augustss  423:                }
1.19      augustss  424:                addr = EHCI_CAP_GET_NEXT(cap);
                    425:        }
                    426:
1.34      jmcneill  427: }
                    428:
                    429: static bool
1.47      dyoung    430: ehci_pci_suspend(device_t dv, const pmf_qual_t *qual)
1.34      jmcneill  431: {
                    432:        struct ehci_pci_softc *sc = device_private(dv);
1.28      jmcneill  433:
1.46      dyoung    434:        ehci_suspend(dv, qual);
1.34      jmcneill  435:        ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
1.33      jmcneill  436:
1.34      jmcneill  437:        return true;
1.19      augustss  438: }
1.23      jmcneill  439:
1.32      jmcneill  440: static bool
1.47      dyoung    441: ehci_pci_resume(device_t dv, const pmf_qual_t *qual)
1.23      jmcneill  442: {
1.32      jmcneill  443:        struct ehci_pci_softc *sc = device_private(dv);
1.23      jmcneill  444:
1.32      jmcneill  445:        ehci_get_ownership(&sc->sc, sc->sc_pc, sc->sc_tag);
1.46      dyoung    446:        return ehci_resume(dv, qual);
1.23      jmcneill  447: }
1.45      cegger    448:
                    449: static int
1.51      dyoung    450: ehci_sb700_match(const struct pci_attach_args *pa)
1.45      cegger    451: {
                    452:        if (!(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
                    453:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_SMB))
                    454:                return 0;
                    455:
                    456:        switch (PCI_REVISION(pa->pa_class)) {
                    457:        case 0x3a:
                    458:        case 0x3b:
                    459:                return 1;
                    460:        }
                    461:
                    462:        return 0;
                    463: }
                    464:
                    465: static int
                    466: ehci_apply_amd_quirks(struct ehci_pci_softc *sc)
                    467: {
                    468:        pcireg_t value;
                    469:
                    470:        aprint_normal_dev(sc->sc.sc_dev,
                    471:            "applying AMD SB600/SB700 USB freeze workaround\n");
                    472:        value = pci_conf_read(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG);
                    473:        pci_conf_write(sc->sc_pc, sc->sc_tag, EHCI_SBx00_WORKAROUND_REG,
                    474:            value | EHCI_SBx00_WORKAROUND_ENABLE);
                    475:
                    476:        return 0;
                    477: }
                    478:
                    479: enum ehci_pci_quirk_flags
                    480: ehci_pci_lookup_quirkdata(pci_vendor_id_t vendor, pci_product_id_t product)
                    481: {
                    482:        int i;
                    483:
                    484:        for (i = 0; i < __arraycount(ehci_pci_quirks); i++) {
                    485:                if (vendor == ehci_pci_quirks[i].vendor &&
                    486:                    product == ehci_pci_quirks[i].product)
                    487:                        return ehci_pci_quirks[i].quirks;
                    488:        }
                    489:        return 0;
                    490: }
                    491:

CVSweb <webmaster@jp.NetBSD.org>