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

Annotation of sys/dev/usb/ohci.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ohci.c,v 1.84 2007/06/15 11:41:48 mbalmer Exp $ */
        !             2: /*     $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $       */
        !             3: /*     $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $       */
        !             4:
        !             5: /*
        !             6:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * This code is derived from software contributed to The NetBSD Foundation
        !            10:  * by Lennart Augustsson (lennart@augustsson.net) at
        !            11:  * Carlstedt Research & Technology.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. All advertising materials mentioning features or use of this software
        !            22:  *    must display the following acknowledgement:
        !            23:  *        This product includes software developed by the NetBSD
        !            24:  *        Foundation, Inc. and its contributors.
        !            25:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            26:  *    contributors may be used to endorse or promote products derived
        !            27:  *    from this software without specific prior written permission.
        !            28:  *
        !            29:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            30:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            31:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            32:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            33:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            34:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            35:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            36:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            37:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            39:  * POSSIBILITY OF SUCH DAMAGE.
        !            40:  */
        !            41:
        !            42: /*
        !            43:  * USB Open Host Controller driver.
        !            44:  *
        !            45:  * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html
        !            46:  * USB spec: http://www.usb.org/developers/docs/usbspec.zip
        !            47:  */
        !            48:
        !            49: #include <sys/param.h>
        !            50: #include <sys/systm.h>
        !            51: #include <sys/malloc.h>
        !            52: #include <sys/kernel.h>
        !            53: #include <sys/device.h>
        !            54: #include <sys/selinfo.h>
        !            55: #include <sys/proc.h>
        !            56: #include <sys/queue.h>
        !            57:
        !            58: #include <machine/bus.h>
        !            59: #include <machine/endian.h>
        !            60:
        !            61: #include <dev/usb/usb.h>
        !            62: #include <dev/usb/usbdi.h>
        !            63: #include <dev/usb/usbdivar.h>
        !            64: #include <dev/usb/usb_mem.h>
        !            65: #include <dev/usb/usb_quirks.h>
        !            66:
        !            67: #include <dev/usb/ohcireg.h>
        !            68: #include <dev/usb/ohcivar.h>
        !            69:
        !            70: struct cfdriver ohci_cd = {
        !            71:        NULL, "ohci", DV_DULL
        !            72: };
        !            73:
        !            74: #ifdef OHCI_DEBUG
        !            75: #define DPRINTF(x)     do { if (ohcidebug) printf x; } while (0)
        !            76: #define DPRINTFN(n,x)  do { if (ohcidebug>(n)) printf x; } while (0)
        !            77: int ohcidebug = 0;
        !            78: #define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
        !            79: #else
        !            80: #define DPRINTF(x)
        !            81: #define DPRINTFN(n,x)
        !            82: #endif
        !            83:
        !            84: #define mstohz(ms) ((ms) * hz / 1000)
        !            85:
        !            86: /*
        !            87:  * The OHCI controller is little endian, so on big endian machines
        !            88:  * the data stored in memory needs to be swapped.
        !            89:  */
        !            90:
        !            91: struct ohci_pipe;
        !            92:
        !            93: ohci_soft_ed_t  *ohci_alloc_sed(ohci_softc_t *);
        !            94: void           ohci_free_sed(ohci_softc_t *, ohci_soft_ed_t *);
        !            95:
        !            96: ohci_soft_td_t  *ohci_alloc_std(ohci_softc_t *);
        !            97: void           ohci_free_std(ohci_softc_t *, ohci_soft_td_t *);
        !            98:
        !            99: ohci_soft_itd_t *ohci_alloc_sitd(ohci_softc_t *);
        !           100: void           ohci_free_sitd(ohci_softc_t *,ohci_soft_itd_t *);
        !           101:
        !           102: #if 0
        !           103: void           ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *,
        !           104:                                            ohci_soft_td_t *);
        !           105: #endif
        !           106: usbd_status    ohci_alloc_std_chain(struct ohci_pipe *,
        !           107:                            ohci_softc_t *, int, int, usbd_xfer_handle,
        !           108:                            ohci_soft_td_t *, ohci_soft_td_t **);
        !           109:
        !           110: void           ohci_shutdown(void *v);
        !           111: usbd_status    ohci_open(usbd_pipe_handle);
        !           112: void           ohci_poll(struct usbd_bus *);
        !           113: void           ohci_softintr(void *);
        !           114: void           ohci_waitintr(ohci_softc_t *, usbd_xfer_handle);
        !           115: void           ohci_add_done(ohci_softc_t *, ohci_physaddr_t);
        !           116: void           ohci_rhsc(ohci_softc_t *, usbd_xfer_handle);
        !           117:
        !           118: usbd_status    ohci_device_request(usbd_xfer_handle xfer);
        !           119: void           ohci_add_ed(ohci_soft_ed_t *, ohci_soft_ed_t *);
        !           120: void           ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *);
        !           121: void           ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *);
        !           122: void           ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *);
        !           123: ohci_soft_td_t  *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t);
        !           124: void           ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *);
        !           125: void           ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *);
        !           126: ohci_soft_itd_t  *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t);
        !           127:
        !           128: usbd_status    ohci_setup_isoc(usbd_pipe_handle pipe);
        !           129: void           ohci_device_isoc_enter(usbd_xfer_handle);
        !           130:
        !           131: usbd_status    ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
        !           132: void           ohci_freem(struct usbd_bus *, usb_dma_t *);
        !           133:
        !           134: usbd_xfer_handle       ohci_allocx(struct usbd_bus *);
        !           135: void           ohci_freex(struct usbd_bus *, usbd_xfer_handle);
        !           136:
        !           137: usbd_status    ohci_root_ctrl_transfer(usbd_xfer_handle);
        !           138: usbd_status    ohci_root_ctrl_start(usbd_xfer_handle);
        !           139: void           ohci_root_ctrl_abort(usbd_xfer_handle);
        !           140: void           ohci_root_ctrl_close(usbd_pipe_handle);
        !           141: void           ohci_root_ctrl_done(usbd_xfer_handle);
        !           142:
        !           143: usbd_status    ohci_root_intr_transfer(usbd_xfer_handle);
        !           144: usbd_status    ohci_root_intr_start(usbd_xfer_handle);
        !           145: void           ohci_root_intr_abort(usbd_xfer_handle);
        !           146: void           ohci_root_intr_close(usbd_pipe_handle);
        !           147: void           ohci_root_intr_done(usbd_xfer_handle);
        !           148:
        !           149: usbd_status    ohci_device_ctrl_transfer(usbd_xfer_handle);
        !           150: usbd_status    ohci_device_ctrl_start(usbd_xfer_handle);
        !           151: void           ohci_device_ctrl_abort(usbd_xfer_handle);
        !           152: void           ohci_device_ctrl_close(usbd_pipe_handle);
        !           153: void           ohci_device_ctrl_done(usbd_xfer_handle);
        !           154:
        !           155: usbd_status    ohci_device_bulk_transfer(usbd_xfer_handle);
        !           156: usbd_status    ohci_device_bulk_start(usbd_xfer_handle);
        !           157: void           ohci_device_bulk_abort(usbd_xfer_handle);
        !           158: void           ohci_device_bulk_close(usbd_pipe_handle);
        !           159: void           ohci_device_bulk_done(usbd_xfer_handle);
        !           160:
        !           161: usbd_status    ohci_device_intr_transfer(usbd_xfer_handle);
        !           162: usbd_status    ohci_device_intr_start(usbd_xfer_handle);
        !           163: void           ohci_device_intr_abort(usbd_xfer_handle);
        !           164: void           ohci_device_intr_close(usbd_pipe_handle);
        !           165: void           ohci_device_intr_done(usbd_xfer_handle);
        !           166:
        !           167: usbd_status    ohci_device_isoc_transfer(usbd_xfer_handle);
        !           168: usbd_status    ohci_device_isoc_start(usbd_xfer_handle);
        !           169: void           ohci_device_isoc_abort(usbd_xfer_handle);
        !           170: void           ohci_device_isoc_close(usbd_pipe_handle);
        !           171: void           ohci_device_isoc_done(usbd_xfer_handle);
        !           172:
        !           173: usbd_status    ohci_device_setintr(ohci_softc_t *sc,
        !           174:                            struct ohci_pipe *pipe, int ival);
        !           175:
        !           176: int            ohci_str(usb_string_descriptor_t *, int, const char *);
        !           177:
        !           178: void           ohci_timeout(void *);
        !           179: void           ohci_timeout_task(void *);
        !           180: void           ohci_rhsc_able(ohci_softc_t *, int);
        !           181: void           ohci_rhsc_enable(void *);
        !           182:
        !           183: void           ohci_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *);
        !           184: void           ohci_abort_xfer(usbd_xfer_handle, usbd_status);
        !           185:
        !           186: void           ohci_device_clear_toggle(usbd_pipe_handle pipe);
        !           187: void           ohci_noop(usbd_pipe_handle pipe);
        !           188:
        !           189: #ifdef OHCI_DEBUG
        !           190: void           ohci_dumpregs(ohci_softc_t *);
        !           191: void           ohci_dump_tds(ohci_soft_td_t *);
        !           192: void           ohci_dump_td(ohci_soft_td_t *);
        !           193: void           ohci_dump_ed(ohci_soft_ed_t *);
        !           194: void           ohci_dump_itd(ohci_soft_itd_t *);
        !           195: void           ohci_dump_itds(ohci_soft_itd_t *);
        !           196: #endif
        !           197:
        !           198: #define OBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \
        !           199:                        BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
        !           200: #define OWRITE1(sc, r, x) \
        !           201:  do { OBARR(sc); bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)); } while (0)
        !           202: #define OWRITE2(sc, r, x) \
        !           203:  do { OBARR(sc); bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)); } while (0)
        !           204: #define OWRITE4(sc, r, x) \
        !           205:  do { OBARR(sc); bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)); } while (0)
        !           206: #define OREAD1(sc, r) (OBARR(sc), bus_space_read_1((sc)->iot, (sc)->ioh, (r)))
        !           207: #define OREAD2(sc, r) (OBARR(sc), bus_space_read_2((sc)->iot, (sc)->ioh, (r)))
        !           208: #define OREAD4(sc, r) (OBARR(sc), bus_space_read_4((sc)->iot, (sc)->ioh, (r)))
        !           209:
        !           210: /* Reverse the bits in a value 0 .. 31 */
        !           211: u_int8_t revbits[OHCI_NO_INTRS] =
        !           212:   { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
        !           213:     0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
        !           214:     0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
        !           215:     0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f };
        !           216:
        !           217: struct ohci_pipe {
        !           218:        struct usbd_pipe pipe;
        !           219:        ohci_soft_ed_t *sed;
        !           220:        union {
        !           221:                ohci_soft_td_t *td;
        !           222:                ohci_soft_itd_t *itd;
        !           223:        } tail;
        !           224:        /* Info needed for different pipe kinds. */
        !           225:        union {
        !           226:                /* Control pipe */
        !           227:                struct {
        !           228:                        usb_dma_t reqdma;
        !           229:                        u_int length;
        !           230:                        ohci_soft_td_t *setup, *data, *stat;
        !           231:                } ctl;
        !           232:                /* Interrupt pipe */
        !           233:                struct {
        !           234:                        int nslots;
        !           235:                        int pos;
        !           236:                } intr;
        !           237:                /* Bulk pipe */
        !           238:                struct {
        !           239:                        u_int length;
        !           240:                        int isread;
        !           241:                } bulk;
        !           242:                /* Iso pipe */
        !           243:                struct iso {
        !           244:                        int next, inuse;
        !           245:                } iso;
        !           246:        } u;
        !           247: };
        !           248:
        !           249: #define OHCI_INTR_ENDPT 1
        !           250:
        !           251: struct usbd_bus_methods ohci_bus_methods = {
        !           252:        ohci_open,
        !           253:        ohci_softintr,
        !           254:        ohci_poll,
        !           255:        ohci_allocm,
        !           256:        ohci_freem,
        !           257:        ohci_allocx,
        !           258:        ohci_freex,
        !           259: };
        !           260:
        !           261: struct usbd_pipe_methods ohci_root_ctrl_methods = {
        !           262:        ohci_root_ctrl_transfer,
        !           263:        ohci_root_ctrl_start,
        !           264:        ohci_root_ctrl_abort,
        !           265:        ohci_root_ctrl_close,
        !           266:        ohci_noop,
        !           267:        ohci_root_ctrl_done,
        !           268: };
        !           269:
        !           270: struct usbd_pipe_methods ohci_root_intr_methods = {
        !           271:        ohci_root_intr_transfer,
        !           272:        ohci_root_intr_start,
        !           273:        ohci_root_intr_abort,
        !           274:        ohci_root_intr_close,
        !           275:        ohci_noop,
        !           276:        ohci_root_intr_done,
        !           277: };
        !           278:
        !           279: struct usbd_pipe_methods ohci_device_ctrl_methods = {
        !           280:        ohci_device_ctrl_transfer,
        !           281:        ohci_device_ctrl_start,
        !           282:        ohci_device_ctrl_abort,
        !           283:        ohci_device_ctrl_close,
        !           284:        ohci_noop,
        !           285:        ohci_device_ctrl_done,
        !           286: };
        !           287:
        !           288: struct usbd_pipe_methods ohci_device_intr_methods = {
        !           289:        ohci_device_intr_transfer,
        !           290:        ohci_device_intr_start,
        !           291:        ohci_device_intr_abort,
        !           292:        ohci_device_intr_close,
        !           293:        ohci_device_clear_toggle,
        !           294:        ohci_device_intr_done,
        !           295: };
        !           296:
        !           297: struct usbd_pipe_methods ohci_device_bulk_methods = {
        !           298:        ohci_device_bulk_transfer,
        !           299:        ohci_device_bulk_start,
        !           300:        ohci_device_bulk_abort,
        !           301:        ohci_device_bulk_close,
        !           302:        ohci_device_clear_toggle,
        !           303:        ohci_device_bulk_done,
        !           304: };
        !           305:
        !           306: struct usbd_pipe_methods ohci_device_isoc_methods = {
        !           307:        ohci_device_isoc_transfer,
        !           308:        ohci_device_isoc_start,
        !           309:        ohci_device_isoc_abort,
        !           310:        ohci_device_isoc_close,
        !           311:        ohci_noop,
        !           312:        ohci_device_isoc_done,
        !           313: };
        !           314:
        !           315: int
        !           316: ohci_activate(struct device *self, enum devact act)
        !           317: {
        !           318:        struct ohci_softc *sc = (struct ohci_softc *)self;
        !           319:        int rv = 0;
        !           320:
        !           321:        switch (act) {
        !           322:        case DVACT_ACTIVATE:
        !           323:                break;
        !           324:
        !           325:        case DVACT_DEACTIVATE:
        !           326:                if (sc->sc_child != NULL)
        !           327:                        rv = config_deactivate(sc->sc_child);
        !           328:                sc->sc_dying = 1;
        !           329:                break;
        !           330:        }
        !           331:        return (rv);
        !           332: }
        !           333:
        !           334: int
        !           335: ohci_detach(struct ohci_softc *sc, int flags)
        !           336: {
        !           337:        int rv = 0;
        !           338:
        !           339:        if (sc->sc_child != NULL)
        !           340:                rv = config_detach(sc->sc_child, flags);
        !           341:
        !           342:        if (rv != 0)
        !           343:                return (rv);
        !           344:
        !           345:        timeout_del(&sc->sc_tmo_rhsc);
        !           346:
        !           347:        if (sc->sc_shutdownhook != NULL)
        !           348:                shutdownhook_disestablish(sc->sc_shutdownhook);
        !           349:
        !           350:        usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
        !           351:
        !           352:        /* free data structures XXX */
        !           353:
        !           354:        return (rv);
        !           355: }
        !           356:
        !           357: ohci_soft_ed_t *
        !           358: ohci_alloc_sed(ohci_softc_t *sc)
        !           359: {
        !           360:        ohci_soft_ed_t *sed;
        !           361:        usbd_status err;
        !           362:        int i, offs;
        !           363:        usb_dma_t dma;
        !           364:
        !           365:        if (sc->sc_freeeds == NULL) {
        !           366:                DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
        !           367:                err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK,
        !           368:                          OHCI_ED_ALIGN, &dma);
        !           369:                if (err)
        !           370:                        return (0);
        !           371:                for(i = 0; i < OHCI_SED_CHUNK; i++) {
        !           372:                        offs = i * OHCI_SED_SIZE;
        !           373:                        sed = KERNADDR(&dma, offs);
        !           374:                        sed->physaddr = DMAADDR(&dma, offs);
        !           375:                        sed->next = sc->sc_freeeds;
        !           376:                        sc->sc_freeeds = sed;
        !           377:                }
        !           378:        }
        !           379:        sed = sc->sc_freeeds;
        !           380:        sc->sc_freeeds = sed->next;
        !           381:        memset(&sed->ed, 0, sizeof(ohci_ed_t));
        !           382:        sed->next = 0;
        !           383:        return (sed);
        !           384: }
        !           385:
        !           386: void
        !           387: ohci_free_sed(ohci_softc_t *sc, ohci_soft_ed_t *sed)
        !           388: {
        !           389:        sed->next = sc->sc_freeeds;
        !           390:        sc->sc_freeeds = sed;
        !           391: }
        !           392:
        !           393: ohci_soft_td_t *
        !           394: ohci_alloc_std(ohci_softc_t *sc)
        !           395: {
        !           396:        ohci_soft_td_t *std;
        !           397:        usbd_status err;
        !           398:        int i, offs;
        !           399:        usb_dma_t dma;
        !           400:        int s;
        !           401:
        !           402:        if (sc->sc_freetds == NULL) {
        !           403:                DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
        !           404:                err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
        !           405:                          OHCI_TD_ALIGN, &dma);
        !           406:                if (err)
        !           407:                        return (NULL);
        !           408:                s = splusb();
        !           409:                for(i = 0; i < OHCI_STD_CHUNK; i++) {
        !           410:                        offs = i * OHCI_STD_SIZE;
        !           411:                        std = KERNADDR(&dma, offs);
        !           412:                        std->physaddr = DMAADDR(&dma, offs);
        !           413:                        std->nexttd = sc->sc_freetds;
        !           414:                        sc->sc_freetds = std;
        !           415:                }
        !           416:                splx(s);
        !           417:        }
        !           418:
        !           419:        s = splusb();
        !           420:        std = sc->sc_freetds;
        !           421:        sc->sc_freetds = std->nexttd;
        !           422:        memset(&std->td, 0, sizeof(ohci_td_t));
        !           423:        std->nexttd = NULL;
        !           424:        std->xfer = NULL;
        !           425:        ohci_hash_add_td(sc, std);
        !           426:        splx(s);
        !           427:
        !           428:        return (std);
        !           429: }
        !           430:
        !           431: void
        !           432: ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std)
        !           433: {
        !           434:        int s;
        !           435:
        !           436:        s = splusb();
        !           437:        ohci_hash_rem_td(sc, std);
        !           438:        std->nexttd = sc->sc_freetds;
        !           439:        sc->sc_freetds = std;
        !           440:        splx(s);
        !           441: }
        !           442:
        !           443: usbd_status
        !           444: ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc,
        !           445:                     int alen, int rd, usbd_xfer_handle xfer,
        !           446:                     ohci_soft_td_t *sp, ohci_soft_td_t **ep)
        !           447: {
        !           448:        ohci_soft_td_t *next, *cur;
        !           449:        ohci_physaddr_t dataphys, dataphysend;
        !           450:        u_int32_t tdflags;
        !           451:        int len, curlen;
        !           452:        usb_dma_t *dma = &xfer->dmabuf;
        !           453:        u_int16_t flags = xfer->flags;
        !           454:
        !           455:        DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
        !           456:
        !           457:        len = alen;
        !           458:        cur = sp;
        !           459:        dataphys = DMAADDR(dma, 0);
        !           460:        dataphysend = OHCI_PAGE(dataphys + len - 1);
        !           461:        tdflags = htole32(
        !           462:            (rd ? OHCI_TD_IN : OHCI_TD_OUT) |
        !           463:            (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
        !           464:            OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR);
        !           465:
        !           466:        for (;;) {
        !           467:                next = ohci_alloc_std(sc);
        !           468:                if (next == NULL)
        !           469:                        goto nomem;
        !           470:
        !           471:                /* The OHCI hardware can handle at most one page crossing. */
        !           472:                if (OHCI_PAGE(dataphys) == dataphysend ||
        !           473:                    OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == dataphysend) {
        !           474:                        /* we can handle it in this TD */
        !           475:                        curlen = len;
        !           476:                } else {
        !           477:                        /* must use multiple TDs, fill as much as possible. */
        !           478:                        curlen = 2 * OHCI_PAGE_SIZE -
        !           479:                                 (dataphys & (OHCI_PAGE_SIZE-1));
        !           480:                        /* the length must be a multiple of the max size */
        !           481:                        curlen -= curlen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize);
        !           482: #ifdef DIAGNOSTIC
        !           483:                        if (curlen == 0)
        !           484:                                panic("ohci_alloc_std: curlen == 0");
        !           485: #endif
        !           486:                }
        !           487:                DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
        !           488:                            "dataphysend=0x%08x len=%d curlen=%d\n",
        !           489:                            dataphys, dataphysend,
        !           490:                            len, curlen));
        !           491:                len -= curlen;
        !           492:
        !           493:                cur->td.td_flags = tdflags;
        !           494:                cur->td.td_cbp = htole32(dataphys);
        !           495:                cur->nexttd = next;
        !           496:                cur->td.td_nexttd = htole32(next->physaddr);
        !           497:                cur->td.td_be = htole32(dataphys + curlen - 1);
        !           498:                cur->len = curlen;
        !           499:                cur->flags = OHCI_ADD_LEN;
        !           500:                cur->xfer = xfer;
        !           501:                DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
        !           502:                            dataphys, dataphys + curlen - 1));
        !           503:                if (len == 0)
        !           504:                        break;
        !           505:                DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
        !           506:                dataphys += curlen;
        !           507:                cur = next;
        !           508:        }
        !           509:        if (!rd && (flags & USBD_FORCE_SHORT_XFER) &&
        !           510:            alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
        !           511:                /* Force a 0 length transfer at the end. */
        !           512:
        !           513:                cur = next;
        !           514:                next = ohci_alloc_std(sc);
        !           515:                if (next == NULL)
        !           516:                        goto nomem;
        !           517:
        !           518:                cur->td.td_flags = tdflags;
        !           519:                cur->td.td_cbp = 0; /* indicate 0 length packet */
        !           520:                cur->nexttd = next;
        !           521:                cur->td.td_nexttd = htole32(next->physaddr);
        !           522:                cur->td.td_be = ~0;
        !           523:                cur->len = 0;
        !           524:                cur->flags = 0;
        !           525:                cur->xfer = xfer;
        !           526:                DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
        !           527:        }
        !           528:        *ep = cur;
        !           529:
        !           530:        return (USBD_NORMAL_COMPLETION);
        !           531:
        !           532:  nomem:
        !           533:        /* XXX free chain */
        !           534:        return (USBD_NOMEM);
        !           535: }
        !           536:
        !           537: #if 0
        !           538: void
        !           539: ohci_free_std_chain(ohci_softc_t *sc, ohci_soft_td_t *std,
        !           540:                    ohci_soft_td_t *stdend)
        !           541: {
        !           542:        ohci_soft_td_t *p;
        !           543:
        !           544:        for (; std != stdend; std = p) {
        !           545:                p = std->nexttd;
        !           546:                ohci_free_std(sc, std);
        !           547:        }
        !           548: }
        !           549: #endif
        !           550:
        !           551: ohci_soft_itd_t *
        !           552: ohci_alloc_sitd(ohci_softc_t *sc)
        !           553: {
        !           554:        ohci_soft_itd_t *sitd;
        !           555:        usbd_status err;
        !           556:        int i, s, offs;
        !           557:        usb_dma_t dma;
        !           558:
        !           559:        if (sc->sc_freeitds == NULL) {
        !           560:                DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
        !           561:                err = usb_allocmem(&sc->sc_bus, OHCI_SITD_SIZE * OHCI_SITD_CHUNK,
        !           562:                          OHCI_ITD_ALIGN, &dma);
        !           563:                if (err)
        !           564:                        return (NULL);
        !           565:                s = splusb();
        !           566:                for(i = 0; i < OHCI_SITD_CHUNK; i++) {
        !           567:                        offs = i * OHCI_SITD_SIZE;
        !           568:                        sitd = KERNADDR(&dma, offs);
        !           569:                        sitd->physaddr = DMAADDR(&dma, offs);
        !           570:                        sitd->nextitd = sc->sc_freeitds;
        !           571:                        sc->sc_freeitds = sitd;
        !           572:                }
        !           573:                splx(s);
        !           574:        }
        !           575:
        !           576:        s = splusb();
        !           577:        sitd = sc->sc_freeitds;
        !           578:        sc->sc_freeitds = sitd->nextitd;
        !           579:        memset(&sitd->itd, 0, sizeof(ohci_itd_t));
        !           580:        sitd->nextitd = NULL;
        !           581:        sitd->xfer = NULL;
        !           582:        ohci_hash_add_itd(sc, sitd);
        !           583:        splx(s);
        !           584:
        !           585: #ifdef DIAGNOSTIC
        !           586:        sitd->isdone = 0;
        !           587: #endif
        !           588:
        !           589:        return (sitd);
        !           590: }
        !           591:
        !           592: void
        !           593: ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
        !           594: {
        !           595:        int s;
        !           596:
        !           597:        DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd));
        !           598:
        !           599: #ifdef DIAGNOSTIC
        !           600:        if (!sitd->isdone) {
        !           601:                panic("ohci_free_sitd: sitd=%p not done", sitd);
        !           602:                return;
        !           603:        }
        !           604:        /* Warn double free */
        !           605:        sitd->isdone = 0;
        !           606: #endif
        !           607:
        !           608:        s = splusb();
        !           609:        ohci_hash_rem_itd(sc, sitd);
        !           610:        sitd->nextitd = sc->sc_freeitds;
        !           611:        sc->sc_freeitds = sitd;
        !           612:        splx(s);
        !           613: }
        !           614:
        !           615: usbd_status
        !           616: ohci_checkrev(ohci_softc_t *sc)
        !           617: {
        !           618:        u_int32_t rev;
        !           619:
        !           620:        printf(",");
        !           621:        rev = OREAD4(sc, OHCI_REVISION);
        !           622:        printf(" version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
        !           623:               OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
        !           624:
        !           625:        if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
        !           626:                printf("%s: unsupported OHCI revision\n",
        !           627:                       sc->sc_bus.bdev.dv_xname);
        !           628:                sc->sc_bus.usbrev = USBREV_UNKNOWN;
        !           629:                return (USBD_INVAL);
        !           630:        }
        !           631:        sc->sc_bus.usbrev = USBREV_1_0;
        !           632:
        !           633:        return (USBD_NORMAL_COMPLETION);
        !           634: }
        !           635:
        !           636: usbd_status
        !           637: ohci_handover(ohci_softc_t *sc)
        !           638: {
        !           639:        u_int32_t s, ctl;
        !           640:        int i;
        !           641:
        !           642:        ctl = OREAD4(sc, OHCI_CONTROL);
        !           643:        if (ctl & OHCI_IR) {
        !           644:                /* SMM active, request change */
        !           645:                DPRINTF(("ohci_handover: SMM active, request owner change\n"));
        !           646:                if ((sc->sc_intre & (OHCI_OC | OHCI_MIE)) ==
        !           647:                    (OHCI_OC | OHCI_MIE))
        !           648:                        OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_MIE);
        !           649:                s = OREAD4(sc, OHCI_COMMAND_STATUS);
        !           650:                OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR);
        !           651:                for (i = 0; i < 100 && (ctl & OHCI_IR); i++) {
        !           652:                        usb_delay_ms(&sc->sc_bus, 1);
        !           653:                        ctl = OREAD4(sc, OHCI_CONTROL);
        !           654:                }
        !           655:                OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_MIE);
        !           656:                if (ctl & OHCI_IR) {
        !           657:                        printf("%s: SMM does not respond, will reset\n",
        !           658:                            sc->sc_bus.bdev.dv_xname);
        !           659:                }
        !           660:        }
        !           661:
        !           662:        return (USBD_NORMAL_COMPLETION);
        !           663: }
        !           664:
        !           665: usbd_status
        !           666: ohci_init(ohci_softc_t *sc)
        !           667: {
        !           668:        ohci_soft_ed_t *sed, *psed;
        !           669:        usbd_status err;
        !           670:        int i;
        !           671:        u_int32_t ctl, rwc, ival, hcr, fm, per, desca, descb;
        !           672:
        !           673:        DPRINTF(("ohci_init: start\n"));
        !           674:
        !           675:        for (i = 0; i < OHCI_HASH_SIZE; i++)
        !           676:                LIST_INIT(&sc->sc_hash_tds[i]);
        !           677:        for (i = 0; i < OHCI_HASH_SIZE; i++)
        !           678:                LIST_INIT(&sc->sc_hash_itds[i]);
        !           679:
        !           680:        SIMPLEQ_INIT(&sc->sc_free_xfers);
        !           681:
        !           682:        /* XXX determine alignment by R/W */
        !           683:        /* Allocate the HCCA area. */
        !           684:        err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE,
        !           685:                         OHCI_HCCA_ALIGN, &sc->sc_hccadma);
        !           686:        if (err)
        !           687:                return (err);
        !           688:        sc->sc_hcca = KERNADDR(&sc->sc_hccadma, 0);
        !           689:        memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE);
        !           690:
        !           691:        sc->sc_eintrs = OHCI_NORMAL_INTRS;
        !           692:
        !           693:        /* Allocate dummy ED that starts the control list. */
        !           694:        sc->sc_ctrl_head = ohci_alloc_sed(sc);
        !           695:        if (sc->sc_ctrl_head == NULL) {
        !           696:                err = USBD_NOMEM;
        !           697:                goto bad1;
        !           698:        }
        !           699:        sc->sc_ctrl_head->ed.ed_flags |= htole32(OHCI_ED_SKIP);
        !           700:
        !           701:        /* Allocate dummy ED that starts the bulk list. */
        !           702:        sc->sc_bulk_head = ohci_alloc_sed(sc);
        !           703:        if (sc->sc_bulk_head == NULL) {
        !           704:                err = USBD_NOMEM;
        !           705:                goto bad2;
        !           706:        }
        !           707:        sc->sc_bulk_head->ed.ed_flags |= htole32(OHCI_ED_SKIP);
        !           708:
        !           709:        /* Allocate dummy ED that starts the isochronous list. */
        !           710:        sc->sc_isoc_head = ohci_alloc_sed(sc);
        !           711:        if (sc->sc_isoc_head == NULL) {
        !           712:                err = USBD_NOMEM;
        !           713:                goto bad3;
        !           714:        }
        !           715:        sc->sc_isoc_head->ed.ed_flags |= htole32(OHCI_ED_SKIP);
        !           716:
        !           717:        /* Allocate all the dummy EDs that make up the interrupt tree. */
        !           718:        for (i = 0; i < OHCI_NO_EDS; i++) {
        !           719:                sed = ohci_alloc_sed(sc);
        !           720:                if (sed == NULL) {
        !           721:                        while (--i >= 0)
        !           722:                                ohci_free_sed(sc, sc->sc_eds[i]);
        !           723:                        err = USBD_NOMEM;
        !           724:                        goto bad4;
        !           725:                }
        !           726:                /* All ED fields are set to 0. */
        !           727:                sc->sc_eds[i] = sed;
        !           728:                sed->ed.ed_flags |= htole32(OHCI_ED_SKIP);
        !           729:                if (i != 0)
        !           730:                        psed = sc->sc_eds[(i-1) / 2];
        !           731:                else
        !           732:                        psed= sc->sc_isoc_head;
        !           733:                sed->next = psed;
        !           734:                sed->ed.ed_nexted = htole32(psed->physaddr);
        !           735:        }
        !           736:        /*
        !           737:         * Fill HCCA interrupt table.  The bit reversal is to get
        !           738:         * the tree set up properly to spread the interrupts.
        !           739:         */
        !           740:        for (i = 0; i < OHCI_NO_INTRS; i++)
        !           741:                sc->sc_hcca->hcca_interrupt_table[revbits[i]] =
        !           742:                    htole32(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr);
        !           743:
        !           744: #ifdef OHCI_DEBUG
        !           745:        if (ohcidebug > 15) {
        !           746:                for (i = 0; i < OHCI_NO_EDS; i++) {
        !           747:                        printf("ed#%d ", i);
        !           748:                        ohci_dump_ed(sc->sc_eds[i]);
        !           749:                }
        !           750:                printf("iso ");
        !           751:                ohci_dump_ed(sc->sc_isoc_head);
        !           752:        }
        !           753: #endif
        !           754:        /* Preserve values programmed by SMM/BIOS but lost over reset. */
        !           755:        ctl = OREAD4(sc, OHCI_CONTROL);
        !           756:        rwc = ctl & OHCI_RWC;
        !           757:        fm = OREAD4(sc, OHCI_FM_INTERVAL);
        !           758:        desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
        !           759:        descb = OREAD4(sc, OHCI_RH_DESCRIPTOR_B);
        !           760:
        !           761:        /* Determine in what context we are running. */
        !           762:        if (ctl & OHCI_IR) {
        !           763:                OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc);
        !           764:                goto reset;
        !           765: #if 0
        !           766: /* Don't bother trying to reuse the BIOS init, we'll reset it anyway. */
        !           767:        } else if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_RESET) {
        !           768:                /* BIOS started controller. */
        !           769:                DPRINTF(("ohci_init: BIOS active\n"));
        !           770:                if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) {
        !           771:                        OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL | rwc);
        !           772:                        usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
        !           773:                }
        !           774: #endif
        !           775:        } else {
        !           776:                DPRINTF(("ohci_init: cold started\n"));
        !           777:        reset:
        !           778:                /* Controller was cold started. */
        !           779:                usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
        !           780:        }
        !           781:
        !           782:        /*
        !           783:         * This reset should not be necessary according to the OHCI spec, but
        !           784:         * without it some controllers do not start.
        !           785:         */
        !           786:        DPRINTF(("%s: resetting\n", sc->sc_bus.bdev.dv_xname));
        !           787:        OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc);
        !           788:        usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
        !           789:
        !           790:        /* We now own the host controller and the bus has been reset. */
        !           791:
        !           792:        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */
        !           793:        /* Nominal time for a reset is 10 us. */
        !           794:        for (i = 0; i < 10; i++) {
        !           795:                delay(10);
        !           796:                hcr = OREAD4(sc, OHCI_COMMAND_STATUS) & OHCI_HCR;
        !           797:                if (!hcr)
        !           798:                        break;
        !           799:        }
        !           800:        if (hcr) {
        !           801:                printf("%s: reset timeout\n", sc->sc_bus.bdev.dv_xname);
        !           802:                err = USBD_IOERROR;
        !           803:                goto bad5;
        !           804:        }
        !           805: #ifdef OHCI_DEBUG
        !           806:        if (ohcidebug > 15)
        !           807:                ohci_dumpregs(sc);
        !           808: #endif
        !           809:
        !           810:        /* The controller is now in SUSPEND state, we have 2ms to finish. */
        !           811:
        !           812:        /* Set up HC registers. */
        !           813:        OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
        !           814:        OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
        !           815:        OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
        !           816:        /* disable all interrupts and then switch on all desired interrupts */
        !           817:        OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
        !           818:        /* switch on desired functional features */
        !           819:        ctl = OREAD4(sc, OHCI_CONTROL);
        !           820:        ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR);
        !           821:        ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE |
        !           822:                OHCI_RATIO_1_4 | OHCI_HCFS_OPERATIONAL | rwc;
        !           823:        /* And finally start it! */
        !           824:        OWRITE4(sc, OHCI_CONTROL, ctl);
        !           825:
        !           826:        /*
        !           827:         * The controller is now OPERATIONAL.  Set a some final
        !           828:         * registers that should be set earlier, but that the
        !           829:         * controller ignores when in the SUSPEND state.
        !           830:         */
        !           831:        ival = OHCI_GET_IVAL(fm);
        !           832:        fm = (OREAD4(sc, OHCI_FM_REMAINING) & OHCI_FIT) ^ OHCI_FIT;
        !           833:        fm |= OHCI_FSMPS(ival) | ival;
        !           834:        OWRITE4(sc, OHCI_FM_INTERVAL, fm);
        !           835:        per = OHCI_PERIODIC(ival); /* 90% periodic */
        !           836:        OWRITE4(sc, OHCI_PERIODIC_START, per);
        !           837:
        !           838:        /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */
        !           839:        OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP);
        !           840:        OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
        !           841:        usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY);
        !           842:        OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca);
        !           843:        OWRITE4(sc, OHCI_RH_DESCRIPTOR_B, descb);
        !           844:        usb_delay_ms(&sc->sc_bus, OHCI_GET_POTPGT(desca) * UHD_PWRON_FACTOR);
        !           845:
        !           846:        /*
        !           847:         * The AMD756 requires a delay before re-reading the register,
        !           848:         * otherwise it will occasionally report 0 ports.
        !           849:         */
        !           850:        sc->sc_noport = 0;
        !           851:        for (i = 0; i < 10 && sc->sc_noport == 0; i++) {
        !           852:                usb_delay_ms(&sc->sc_bus, OHCI_READ_DESC_DELAY);
        !           853:                sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
        !           854:        }
        !           855:
        !           856: #ifdef OHCI_DEBUG
        !           857:        if (ohcidebug > 5)
        !           858:                ohci_dumpregs(sc);
        !           859: #endif
        !           860:
        !           861:        /* Set up the bus struct. */
        !           862:        sc->sc_bus.methods = &ohci_bus_methods;
        !           863:        sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
        !           864:
        !           865:        sc->sc_control = sc->sc_intre = 0;
        !           866:        sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc);
        !           867:
        !           868:        timeout_set(&sc->sc_tmo_rhsc, NULL, NULL);
        !           869:
        !           870:        /* Finally, turn on interrupts. */
        !           871:        DPRINTFN(1,("ohci_init: enabling\n"));
        !           872:        OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
        !           873:
        !           874:        return (USBD_NORMAL_COMPLETION);
        !           875:
        !           876:  bad5:
        !           877:        for (i = 0; i < OHCI_NO_EDS; i++)
        !           878:                ohci_free_sed(sc, sc->sc_eds[i]);
        !           879:  bad4:
        !           880:        ohci_free_sed(sc, sc->sc_isoc_head);
        !           881:  bad3:
        !           882:        ohci_free_sed(sc, sc->sc_bulk_head);
        !           883:  bad2:
        !           884:        ohci_free_sed(sc, sc->sc_ctrl_head);
        !           885:  bad1:
        !           886:        usb_freemem(&sc->sc_bus, &sc->sc_hccadma);
        !           887:        return (err);
        !           888: }
        !           889:
        !           890: usbd_status
        !           891: ohci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
        !           892: {
        !           893:        struct ohci_softc *sc = (struct ohci_softc *)bus;
        !           894:
        !           895:        return (usb_allocmem(&sc->sc_bus, size, 0, dma));
        !           896: }
        !           897:
        !           898: void
        !           899: ohci_freem(struct usbd_bus *bus, usb_dma_t *dma)
        !           900: {
        !           901:        struct ohci_softc *sc = (struct ohci_softc *)bus;
        !           902:
        !           903:        usb_freemem(&sc->sc_bus, dma);
        !           904: }
        !           905:
        !           906: usbd_xfer_handle
        !           907: ohci_allocx(struct usbd_bus *bus)
        !           908: {
        !           909:        struct ohci_softc *sc = (struct ohci_softc *)bus;
        !           910:        usbd_xfer_handle xfer;
        !           911:
        !           912:        xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
        !           913:        if (xfer != NULL) {
        !           914:                SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
        !           915: #ifdef DIAGNOSTIC
        !           916:                if (xfer->busy_free != XFER_FREE) {
        !           917:                        printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer,
        !           918:                               xfer->busy_free);
        !           919:                }
        !           920: #endif
        !           921:        } else {
        !           922:                xfer = malloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT);
        !           923:        }
        !           924:        if (xfer != NULL) {
        !           925:                memset(xfer, 0, sizeof (struct ohci_xfer));
        !           926: #ifdef DIAGNOSTIC
        !           927:                xfer->busy_free = XFER_BUSY;
        !           928: #endif
        !           929:        }
        !           930:        return (xfer);
        !           931: }
        !           932:
        !           933: void
        !           934: ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
        !           935: {
        !           936:        struct ohci_softc *sc = (struct ohci_softc *)bus;
        !           937:
        !           938: #ifdef DIAGNOSTIC
        !           939:        if (xfer->busy_free != XFER_BUSY) {
        !           940:                printf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer,
        !           941:                       xfer->busy_free);
        !           942:                return;
        !           943:        }
        !           944:        xfer->busy_free = XFER_FREE;
        !           945: #endif
        !           946:        SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
        !           947: }
        !           948:
        !           949: /*
        !           950:  * Shut down the controller when the system is going down.
        !           951:  */
        !           952: void
        !           953: ohci_shutdown(void *v)
        !           954: {
        !           955:        ohci_softc_t *sc = v;
        !           956:
        !           957:        DPRINTF(("ohci_shutdown: stopping the HC\n"));
        !           958:        OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
        !           959: }
        !           960:
        !           961: /*
        !           962:  * Handle suspend/resume.
        !           963:  *
        !           964:  * We need to switch to polling mode here, because this routine is
        !           965:  * called from an interrupt context.  This is all right since we
        !           966:  * are almost suspended anyway.
        !           967:  */
        !           968: void
        !           969: ohci_power(int why, void *v)
        !           970: {
        !           971:        ohci_softc_t *sc = v;
        !           972:        u_int32_t reg;
        !           973:        int s;
        !           974:
        !           975: #ifdef OHCI_DEBUG
        !           976:        DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why));
        !           977:        ohci_dumpregs(sc);
        !           978: #endif
        !           979:
        !           980:        s = splhardusb();
        !           981:        switch (why) {
        !           982:        case PWR_SUSPEND:
        !           983:        case PWR_STANDBY:
        !           984:                sc->sc_bus.use_polling++;
        !           985:                reg = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK;
        !           986:                if (sc->sc_control == 0) {
        !           987:                        /*
        !           988:                         * Preserve register values, in case that APM BIOS
        !           989:                         * does not recover them.
        !           990:                         */
        !           991:                        sc->sc_control = reg;
        !           992:                        sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE);
        !           993:                        sc->sc_ival = OHCI_GET_IVAL(OREAD4(sc,
        !           994:                            OHCI_FM_INTERVAL));
        !           995:                }
        !           996:                reg |= OHCI_HCFS_SUSPEND;
        !           997:                OWRITE4(sc, OHCI_CONTROL, reg);
        !           998:                usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
        !           999:                sc->sc_bus.use_polling--;
        !          1000:                break;
        !          1001:        case PWR_RESUME:
        !          1002:                sc->sc_bus.use_polling++;
        !          1003:
        !          1004:                /* Some broken BIOSes do not recover these values */
        !          1005:                OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
        !          1006:                OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
        !          1007:                OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
        !          1008:                if (sc->sc_intre)
        !          1009:                        OWRITE4(sc, OHCI_INTERRUPT_ENABLE,
        !          1010:                            sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE));
        !          1011:                if (sc->sc_control)
        !          1012:                        reg = sc->sc_control;
        !          1013:                else
        !          1014:                        reg = OREAD4(sc, OHCI_CONTROL);
        !          1015:                reg |= OHCI_HCFS_RESUME;
        !          1016:                OWRITE4(sc, OHCI_CONTROL, reg);
        !          1017:                usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
        !          1018:                reg = (reg & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL;
        !          1019:                OWRITE4(sc, OHCI_CONTROL, reg);
        !          1020:
        !          1021:                reg = (OREAD4(sc, OHCI_FM_REMAINING) & OHCI_FIT) ^ OHCI_FIT;
        !          1022:                reg |= OHCI_FSMPS(sc->sc_ival) | sc->sc_ival;
        !          1023:                OWRITE4(sc, OHCI_FM_INTERVAL, reg);
        !          1024:                OWRITE4(sc, OHCI_PERIODIC_START, OHCI_PERIODIC(sc->sc_ival));
        !          1025:
        !          1026:                /* Fiddle the No OverCurrent Protection to avoid a chip bug */
        !          1027:                reg = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
        !          1028:                OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, reg | OHCI_NOCP);
        !          1029:                OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
        !          1030:                usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY);
        !          1031:                OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, reg);
        !          1032:
        !          1033:                usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
        !          1034:                sc->sc_control = sc->sc_intre = sc->sc_ival = 0;
        !          1035:                sc->sc_bus.use_polling--;
        !          1036:                break;
        !          1037:        }
        !          1038:        splx(s);
        !          1039: }
        !          1040:
        !          1041: #ifdef OHCI_DEBUG
        !          1042: void
        !          1043: ohci_dumpregs(ohci_softc_t *sc)
        !          1044: {
        !          1045:        DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n",
        !          1046:                 OREAD4(sc, OHCI_REVISION),
        !          1047:                 OREAD4(sc, OHCI_CONTROL),
        !          1048:                 OREAD4(sc, OHCI_COMMAND_STATUS)));
        !          1049:        DPRINTF(("               intrstat=0x%08x intre=0x%08x intrd=0x%08x\n",
        !          1050:                 OREAD4(sc, OHCI_INTERRUPT_STATUS),
        !          1051:                 OREAD4(sc, OHCI_INTERRUPT_ENABLE),
        !          1052:                 OREAD4(sc, OHCI_INTERRUPT_DISABLE)));
        !          1053:        DPRINTF(("               hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n",
        !          1054:                 OREAD4(sc, OHCI_HCCA),
        !          1055:                 OREAD4(sc, OHCI_PERIOD_CURRENT_ED),
        !          1056:                 OREAD4(sc, OHCI_CONTROL_HEAD_ED)));
        !          1057:        DPRINTF(("               ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n",
        !          1058:                 OREAD4(sc, OHCI_CONTROL_CURRENT_ED),
        !          1059:                 OREAD4(sc, OHCI_BULK_HEAD_ED),
        !          1060:                 OREAD4(sc, OHCI_BULK_CURRENT_ED)));
        !          1061:        DPRINTF(("               done=0x%08x fmival=0x%08x fmrem=0x%08x\n",
        !          1062:                 OREAD4(sc, OHCI_DONE_HEAD),
        !          1063:                 OREAD4(sc, OHCI_FM_INTERVAL),
        !          1064:                 OREAD4(sc, OHCI_FM_REMAINING)));
        !          1065:        DPRINTF(("               fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n",
        !          1066:                 OREAD4(sc, OHCI_FM_NUMBER),
        !          1067:                 OREAD4(sc, OHCI_PERIODIC_START),
        !          1068:                 OREAD4(sc, OHCI_LS_THRESHOLD)));
        !          1069:        DPRINTF(("               desca=0x%08x descb=0x%08x stat=0x%08x\n",
        !          1070:                 OREAD4(sc, OHCI_RH_DESCRIPTOR_A),
        !          1071:                 OREAD4(sc, OHCI_RH_DESCRIPTOR_B),
        !          1072:                 OREAD4(sc, OHCI_RH_STATUS)));
        !          1073:        DPRINTF(("               port1=0x%08x port2=0x%08x\n",
        !          1074:                 OREAD4(sc, OHCI_RH_PORT_STATUS(1)),
        !          1075:                 OREAD4(sc, OHCI_RH_PORT_STATUS(2))));
        !          1076:        DPRINTF(("         HCCA: frame_number=0x%04x done_head=0x%08x\n",
        !          1077:                 letoh32(sc->sc_hcca->hcca_frame_number),
        !          1078:                 letoh32(sc->sc_hcca->hcca_done_head)));
        !          1079: }
        !          1080: #endif
        !          1081:
        !          1082: int ohci_intr1(ohci_softc_t *);
        !          1083:
        !          1084: int
        !          1085: ohci_intr(void *p)
        !          1086: {
        !          1087:        ohci_softc_t *sc = p;
        !          1088:
        !          1089:        if (sc == NULL || sc->sc_dying)
        !          1090:                return (0);
        !          1091:
        !          1092:        /* If we get an interrupt while polling, then just ignore it. */
        !          1093:        if (!cold && sc->sc_bus.use_polling) {
        !          1094: #ifdef DIAGNOSTIC
        !          1095:                static struct timeval ohci_intr_tv;
        !          1096:                if ((OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs) &&
        !          1097:                    usbd_ratecheck(&ohci_intr_tv))
        !          1098:                        DPRINTFN(16,
        !          1099:                            ("ohci_intr: ignored interrupt while polling\n"));
        !          1100: #endif
        !          1101:                return (0);
        !          1102:        }
        !          1103:
        !          1104:        return (ohci_intr1(sc));
        !          1105: }
        !          1106:
        !          1107: int
        !          1108: ohci_intr1(ohci_softc_t *sc)
        !          1109: {
        !          1110:        u_int32_t intrs, eintrs;
        !          1111:        ohci_physaddr_t done;
        !          1112:
        !          1113:        DPRINTFN(14,("ohci_intr1: enter\n"));
        !          1114:
        !          1115:        /* In case the interrupt occurs before initialization has completed. */
        !          1116:        if (sc == NULL || sc->sc_hcca == NULL) {
        !          1117: #ifdef DIAGNOSTIC
        !          1118:                printf("ohci_intr: sc->sc_hcca == NULL\n");
        !          1119: #endif
        !          1120:                return (0);
        !          1121:        }
        !          1122:
        !          1123:         intrs = 0;
        !          1124:        done = letoh32(sc->sc_hcca->hcca_done_head);
        !          1125:        if (done != 0) {
        !          1126:                if (done & ~OHCI_DONE_INTRS)
        !          1127:                        intrs = OHCI_WDH;
        !          1128:                if (done & OHCI_DONE_INTRS)
        !          1129:                        intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS);
        !          1130:                sc->sc_hcca->hcca_done_head = 0;
        !          1131:        } else {
        !          1132:                intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS);
        !          1133:                /* If we've flushed out a WDH then reread */
        !          1134:                if (intrs & OHCI_WDH) {
        !          1135:                        done = letoh32(sc->sc_hcca->hcca_done_head);
        !          1136:                        sc->sc_hcca->hcca_done_head = 0;
        !          1137:                }
        !          1138:        }
        !          1139:
        !          1140:        if (!intrs)
        !          1141:                return (0);
        !          1142:
        !          1143:        intrs &= ~OHCI_MIE;
        !          1144:        OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */
        !          1145:        eintrs = intrs & sc->sc_eintrs;
        !          1146:        if (!eintrs)
        !          1147:                return (0);
        !          1148:
        !          1149:        sc->sc_bus.intr_context++;
        !          1150:        sc->sc_bus.no_intrs++;
        !          1151:        DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n",
        !          1152:                     sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS),
        !          1153:                     (u_int)eintrs));
        !          1154:
        !          1155:        if (eintrs & OHCI_SO) {
        !          1156:                sc->sc_overrun_cnt++;
        !          1157:                if (usbd_ratecheck(&sc->sc_overrun_ntc)) {
        !          1158:                        printf("%s: %u scheduling overruns\n",
        !          1159:                            sc->sc_bus.bdev.dv_xname, sc->sc_overrun_cnt);
        !          1160:                        sc->sc_overrun_cnt = 0;
        !          1161:                }
        !          1162:                /* XXX do what */
        !          1163:                eintrs &= ~OHCI_SO;
        !          1164:        }
        !          1165:        if (eintrs & OHCI_WDH) {
        !          1166:                ohci_add_done(sc, done &~ OHCI_DONE_INTRS);
        !          1167:                usb_schedsoftintr(&sc->sc_bus);
        !          1168:                eintrs &= ~OHCI_WDH;
        !          1169:        }
        !          1170:        if (eintrs & OHCI_RD) {
        !          1171:                printf("%s: resume detect\n", sc->sc_bus.bdev.dv_xname);
        !          1172:                /* XXX process resume detect */
        !          1173:        }
        !          1174:        if (eintrs & OHCI_UE) {
        !          1175:                printf("%s: unrecoverable error, controller halted\n",
        !          1176:                       sc->sc_bus.bdev.dv_xname);
        !          1177:                OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
        !          1178:                /* XXX what else */
        !          1179:        }
        !          1180:        if (eintrs & OHCI_RHSC) {
        !          1181:                ohci_rhsc(sc, sc->sc_intrxfer);
        !          1182:                /*
        !          1183:                 * Disable RHSC interrupt for now, because it will be
        !          1184:                 * on until the port has been reset.
        !          1185:                 */
        !          1186:                ohci_rhsc_able(sc, 0);
        !          1187:                DPRINTFN(2, ("%s: rhsc interrupt disabled\n",
        !          1188:                             sc->sc_bus.bdev.dv_xname));
        !          1189:
        !          1190:                /* Do not allow RHSC interrupts > 1 per second */
        !          1191:                 timeout_del(&sc->sc_tmo_rhsc);
        !          1192:                 timeout_set(&sc->sc_tmo_rhsc, ohci_rhsc_enable, sc);
        !          1193:                 timeout_add(&sc->sc_tmo_rhsc, hz);
        !          1194:                eintrs &= ~OHCI_RHSC;
        !          1195:        }
        !          1196:
        !          1197:        sc->sc_bus.intr_context--;
        !          1198:
        !          1199:        if (eintrs != 0) {
        !          1200:                /* Block unprocessed interrupts. XXX */
        !          1201:                OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs);
        !          1202:                sc->sc_eintrs &= ~eintrs;
        !          1203:                printf("%s: blocking intrs 0x%x\n",
        !          1204:                       sc->sc_bus.bdev.dv_xname, eintrs);
        !          1205:        }
        !          1206:
        !          1207:        return (1);
        !          1208: }
        !          1209:
        !          1210: void
        !          1211: ohci_rhsc_able(ohci_softc_t *sc, int on)
        !          1212: {
        !          1213:        DPRINTFN(4, ("ohci_rhsc_able: on=%d\n", on));
        !          1214:        if (on) {
        !          1215:                sc->sc_eintrs |= OHCI_RHSC;
        !          1216:                OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC);
        !          1217:        } else {
        !          1218:                sc->sc_eintrs &= ~OHCI_RHSC;
        !          1219:                OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC);
        !          1220:        }
        !          1221: }
        !          1222:
        !          1223: void
        !          1224: ohci_rhsc_enable(void *v_sc)
        !          1225: {
        !          1226:        ohci_softc_t *sc = v_sc;
        !          1227:        int s;
        !          1228:
        !          1229:        s = splhardusb();
        !          1230:        ohci_rhsc(sc, sc->sc_intrxfer);
        !          1231:        DPRINTFN(2, ("%s: rhsc interrupt enabled\n",
        !          1232:                     sc->sc_bus.bdev.dv_xname));
        !          1233:
        !          1234:        ohci_rhsc_able(sc, 1);
        !          1235:        splx(s);
        !          1236: }
        !          1237:
        !          1238: #ifdef OHCI_DEBUG
        !          1239: char *ohci_cc_strs[] = {
        !          1240:        "NO_ERROR",
        !          1241:        "CRC",
        !          1242:        "BIT_STUFFING",
        !          1243:        "DATA_TOGGLE_MISMATCH",
        !          1244:        "STALL",
        !          1245:        "DEVICE_NOT_RESPONDING",
        !          1246:        "PID_CHECK_FAILURE",
        !          1247:        "UNEXPECTED_PID",
        !          1248:        "DATA_OVERRUN",
        !          1249:        "DATA_UNDERRUN",
        !          1250:        "BUFFER_OVERRUN",
        !          1251:        "BUFFER_UNDERRUN",
        !          1252:        "reserved",
        !          1253:        "reserved",
        !          1254:        "NOT_ACCESSED",
        !          1255:        "NOT_ACCESSED",
        !          1256: };
        !          1257: #endif
        !          1258:
        !          1259: void
        !          1260: ohci_add_done(ohci_softc_t *sc, ohci_physaddr_t done)
        !          1261: {
        !          1262:        ohci_soft_itd_t *sitd, *sidone, **ip;
        !          1263:        ohci_soft_td_t  *std,  *sdone,  **p;
        !          1264:
        !          1265:        /* Reverse the done list. */
        !          1266:        for (sdone = NULL, sidone = NULL; done != 0; ) {
        !          1267:                std = ohci_hash_find_td(sc, done);
        !          1268:                if (std != NULL) {
        !          1269:                        std->dnext = sdone;
        !          1270:                        done = letoh32(std->td.td_nexttd);
        !          1271:                        sdone = std;
        !          1272:                        DPRINTFN(10,("add TD %p\n", std));
        !          1273:                        continue;
        !          1274:                }
        !          1275:                sitd = ohci_hash_find_itd(sc, done);
        !          1276:                if (sitd != NULL) {
        !          1277:                        sitd->dnext = sidone;
        !          1278:                        done = letoh32(sitd->itd.itd_nextitd);
        !          1279:                        sidone = sitd;
        !          1280:                        DPRINTFN(5,("add ITD %p\n", sitd));
        !          1281:                        continue;
        !          1282:                }
        !          1283:                panic("ohci_add_done: addr 0x%08lx not found", (u_long)done);
        !          1284:        }
        !          1285:
        !          1286:        /* sdone & sidone now hold the done lists. */
        !          1287:        /* Put them on the already processed lists. */
        !          1288:        for (p = &sc->sc_sdone; *p != NULL; p = &(*p)->dnext)
        !          1289:                ;
        !          1290:        *p = sdone;
        !          1291:        for (ip = &sc->sc_sidone; *ip != NULL; ip = &(*ip)->dnext)
        !          1292:                ;
        !          1293:        *ip = sidone;
        !          1294: }
        !          1295:
        !          1296: void
        !          1297: ohci_softintr(void *v)
        !          1298: {
        !          1299:        ohci_softc_t *sc = v;
        !          1300:        ohci_soft_itd_t *sitd, *sidone, *sitdnext;
        !          1301:        ohci_soft_td_t  *std,  *sdone,  *stdnext;
        !          1302:        usbd_xfer_handle xfer;
        !          1303:        struct ohci_pipe *opipe;
        !          1304:        int len, cc, s;
        !          1305:        int i, j, actlen, iframes, uedir;
        !          1306:
        !          1307:        DPRINTFN(10,("ohci_softintr: enter\n"));
        !          1308:
        !          1309:        sc->sc_bus.intr_context++;
        !          1310:
        !          1311:        s = splhardusb();
        !          1312:        sdone = sc->sc_sdone;
        !          1313:        sc->sc_sdone = NULL;
        !          1314:        sidone = sc->sc_sidone;
        !          1315:        sc->sc_sidone = NULL;
        !          1316:        splx(s);
        !          1317:
        !          1318:        DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone));
        !          1319:
        !          1320: #ifdef OHCI_DEBUG
        !          1321:        if (ohcidebug > 10) {
        !          1322:                DPRINTF(("ohci_process_done: TD done:\n"));
        !          1323:                ohci_dump_tds(sdone);
        !          1324:        }
        !          1325: #endif
        !          1326:
        !          1327:        for (std = sdone; std; std = stdnext) {
        !          1328:                xfer = std->xfer;
        !          1329:                stdnext = std->dnext;
        !          1330:                DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n",
        !          1331:                                std, xfer, xfer ? xfer->hcpriv : 0));
        !          1332:                if (xfer == NULL) {
        !          1333:                        /*
        !          1334:                         * xfer == NULL: There seems to be no xfer associated
        !          1335:                         * with this TD. It is tailp that happened to end up on
        !          1336:                         * the done queue.
        !          1337:                         * Shouldn't happen, but some chips are broken(?).
        !          1338:                         */
        !          1339:                        continue;
        !          1340:                }
        !          1341:                if (xfer->status == USBD_CANCELLED ||
        !          1342:                    xfer->status == USBD_TIMEOUT) {
        !          1343:                        DPRINTF(("ohci_process_done: cancel/timeout %p\n",
        !          1344:                                 xfer));
        !          1345:                        /* Handled by abort routine. */
        !          1346:                        continue;
        !          1347:                }
        !          1348:                timeout_del(&xfer->timeout_handle);
        !          1349:
        !          1350:                len = std->len;
        !          1351:                if (std->td.td_cbp != 0)
        !          1352:                        len -= letoh32(std->td.td_be) -
        !          1353:                            letoh32(std->td.td_cbp) + 1;
        !          1354:                DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", len,
        !          1355:                    std->flags));
        !          1356:                if (std->flags & OHCI_ADD_LEN)
        !          1357:                        xfer->actlen += len;
        !          1358:
        !          1359:                cc = OHCI_TD_GET_CC(letoh32(std->td.td_flags));
        !          1360:                if (cc == OHCI_CC_NO_ERROR) {
        !          1361:                        if (std->flags & OHCI_CALL_DONE) {
        !          1362:                                xfer->status = USBD_NORMAL_COMPLETION;
        !          1363:                                s = splusb();
        !          1364:                                usb_transfer_complete(xfer);
        !          1365:                                splx(s);
        !          1366:                        }
        !          1367:                        ohci_free_std(sc, std);
        !          1368:                } else {
        !          1369:                        /*
        !          1370:                         * Endpoint is halted.  First unlink all the TDs
        !          1371:                         * belonging to the failed transfer, and then restart
        !          1372:                         * the endpoint.
        !          1373:                         */
        !          1374:                        ohci_soft_td_t *p, *n;
        !          1375:                        opipe = (struct ohci_pipe *)xfer->pipe;
        !          1376:
        !          1377:                        DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n",
        !          1378:                          OHCI_TD_GET_CC(letoh32(std->td.td_flags)),
        !          1379:                          ohci_cc_strs[OHCI_TD_GET_CC(letoh32(std->td.td_flags))]));
        !          1380:
        !          1381:                        /* remove TDs */
        !          1382:                        for (p = std; p->xfer == xfer; p = n) {
        !          1383:                                n = p->nexttd;
        !          1384:                                ohci_free_std(sc, p);
        !          1385:                        }
        !          1386:
        !          1387:                        /* clear halt */
        !          1388:                        opipe->sed->ed.ed_headp = htole32(p->physaddr);
        !          1389:                        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
        !          1390:
        !          1391:                        if (cc == OHCI_CC_STALL)
        !          1392:                                xfer->status = USBD_STALLED;
        !          1393:                        else
        !          1394:                                xfer->status = USBD_IOERROR;
        !          1395:                        s = splusb();
        !          1396:                        usb_transfer_complete(xfer);
        !          1397:                        splx(s);
        !          1398:                }
        !          1399:        }
        !          1400:
        !          1401: #ifdef OHCI_DEBUG
        !          1402:        if (ohcidebug > 10) {
        !          1403:                DPRINTF(("ohci_softintr: ITD done:\n"));
        !          1404:                ohci_dump_itds(sidone);
        !          1405:        }
        !          1406: #endif
        !          1407:
        !          1408:        for (sitd = sidone; sitd != NULL; sitd = sitdnext) {
        !          1409:                xfer = sitd->xfer;
        !          1410:                sitdnext = sitd->dnext;
        !          1411:                DPRINTFN(1, ("ohci_process_done: sitd=%p xfer=%p hcpriv=%p\n",
        !          1412:                             sitd, xfer, xfer ? xfer->hcpriv : 0));
        !          1413:                if (xfer == NULL)
        !          1414:                        continue;
        !          1415:                if (xfer->status == USBD_CANCELLED ||
        !          1416:                    xfer->status == USBD_TIMEOUT) {
        !          1417:                        DPRINTF(("ohci_process_done: cancel/timeout %p\n",
        !          1418:                                 xfer));
        !          1419:                        /* Handled by abort routine. */
        !          1420:                        continue;
        !          1421:                }
        !          1422: #ifdef DIAGNOSTIC
        !          1423:                if (sitd->isdone)
        !          1424:                        printf("ohci_softintr: sitd=%p is done\n", sitd);
        !          1425:                sitd->isdone = 1;
        !          1426: #endif
        !          1427:                if (sitd->flags & OHCI_CALL_DONE) {
        !          1428:                        ohci_soft_itd_t *next;
        !          1429:
        !          1430:                        opipe = (struct ohci_pipe *)xfer->pipe;
        !          1431:                        opipe->u.iso.inuse -= xfer->nframes;
        !          1432:                        uedir = UE_GET_DIR(xfer->pipe->endpoint->edesc->
        !          1433:                            bEndpointAddress);
        !          1434:                        xfer->status = USBD_NORMAL_COMPLETION;
        !          1435:                        actlen = 0;
        !          1436:                        for (i = 0, sitd = xfer->hcpriv;;
        !          1437:                            sitd = next) {
        !          1438:                                next = sitd->nextitd;
        !          1439:                                if (OHCI_ITD_GET_CC(letoh32(sitd->
        !          1440:                                    itd.itd_flags)) != OHCI_CC_NO_ERROR)
        !          1441:                                        xfer->status = USBD_IOERROR;
        !          1442:                                /* For input, update frlengths with actual */
        !          1443:                                /* XXX anything necessary for output? */
        !          1444:                                if (uedir == UE_DIR_IN &&
        !          1445:                                    xfer->status == USBD_NORMAL_COMPLETION) {
        !          1446:                                        iframes = OHCI_ITD_GET_FC(letoh32(
        !          1447:                                            sitd->itd.itd_flags));
        !          1448:                                        for (j = 0; j < iframes; i++, j++) {
        !          1449:                                                len = letoh16(sitd->
        !          1450:                                                    itd.itd_offset[j]);
        !          1451:                                                if ((OHCI_ITD_PSW_GET_CC(len) &
        !          1452:                                                    OHCI_CC_NOT_ACCESSED_MASK)
        !          1453:                                                    == OHCI_CC_NOT_ACCESSED)
        !          1454:                                                        len = 0;
        !          1455:                                                else
        !          1456:                                                        len = OHCI_ITD_PSW_LENGTH(len);
        !          1457:                                                xfer->frlengths[i] = len;
        !          1458:                                                actlen += len;
        !          1459:                                        }
        !          1460:                                }
        !          1461:                                if (sitd->flags & OHCI_CALL_DONE)
        !          1462:                                        break;
        !          1463:                                ohci_free_sitd(sc, sitd);
        !          1464:                        }
        !          1465:                        ohci_free_sitd(sc, sitd);
        !          1466:                        if (uedir == UE_DIR_IN &&
        !          1467:                            xfer->status == USBD_NORMAL_COMPLETION)
        !          1468:                                xfer->actlen = actlen;
        !          1469:                        xfer->hcpriv = NULL;
        !          1470:
        !          1471:                        s = splusb();
        !          1472:                        usb_transfer_complete(xfer);
        !          1473:                        splx(s);
        !          1474:                }
        !          1475:        }
        !          1476:
        !          1477: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
        !          1478:        if (sc->sc_softwake) {
        !          1479:                sc->sc_softwake = 0;
        !          1480:                wakeup(&sc->sc_softwake);
        !          1481:        }
        !          1482: #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
        !          1483:
        !          1484:        sc->sc_bus.intr_context--;
        !          1485:        DPRINTFN(10,("ohci_softintr: done:\n"));
        !          1486: }
        !          1487:
        !          1488: void
        !          1489: ohci_device_ctrl_done(usbd_xfer_handle xfer)
        !          1490: {
        !          1491:        DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer));
        !          1492:
        !          1493: #ifdef DIAGNOSTIC
        !          1494:        if (!(xfer->rqflags & URQ_REQUEST)) {
        !          1495:                panic("ohci_device_ctrl_done: not a request");
        !          1496:        }
        !          1497: #endif
        !          1498: }
        !          1499:
        !          1500: void
        !          1501: ohci_device_intr_done(usbd_xfer_handle xfer)
        !          1502: {
        !          1503:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          1504:        ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
        !          1505:        ohci_soft_ed_t *sed = opipe->sed;
        !          1506:        ohci_soft_td_t *data, *tail;
        !          1507:
        !          1508:
        !          1509:        DPRINTFN(10, ("ohci_device_intr_done: xfer=%p, actlen=%d\n", xfer,
        !          1510:            xfer->actlen));
        !          1511:
        !          1512:        if (xfer->pipe->repeat) {
        !          1513:                data = opipe->tail.td;
        !          1514:                tail = ohci_alloc_std(sc); /* XXX should reuse TD */
        !          1515:                if (tail == NULL) {
        !          1516:                        xfer->status = USBD_NOMEM;
        !          1517:                        return;
        !          1518:                }
        !          1519:                tail->xfer = NULL;
        !          1520:
        !          1521:                data->td.td_flags = htole32(
        !          1522:                        OHCI_TD_IN | OHCI_TD_NOCC |
        !          1523:                        OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
        !          1524:                if (xfer->flags & USBD_SHORT_XFER_OK)
        !          1525:                        data->td.td_flags |= htole32(OHCI_TD_R);
        !          1526:                data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0));
        !          1527:                data->nexttd = tail;
        !          1528:                data->td.td_nexttd = htole32(tail->physaddr);
        !          1529:                data->td.td_be = htole32(letoh32(data->td.td_cbp) +
        !          1530:                        xfer->length - 1);
        !          1531:                data->len = xfer->length;
        !          1532:                data->xfer = xfer;
        !          1533:                data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
        !          1534:                xfer->hcpriv = data;
        !          1535:                xfer->actlen = 0;
        !          1536:
        !          1537:                sed->ed.ed_tailp = htole32(tail->physaddr);
        !          1538:                opipe->tail.td = tail;
        !          1539:        }
        !          1540: }
        !          1541:
        !          1542: void
        !          1543: ohci_device_bulk_done(usbd_xfer_handle xfer)
        !          1544: {
        !          1545:        DPRINTFN(10, ("ohci_device_bulk_done: xfer=%p, actlen=%d\n", xfer,
        !          1546:            xfer->actlen));
        !          1547: }
        !          1548:
        !          1549: void
        !          1550: ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer)
        !          1551: {
        !          1552:        usbd_pipe_handle pipe;
        !          1553:        u_char *p;
        !          1554:        int i, m;
        !          1555:        int hstatus;
        !          1556:
        !          1557:        hstatus = OREAD4(sc, OHCI_RH_STATUS);
        !          1558:        DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n",
        !          1559:                 sc, xfer, hstatus));
        !          1560:
        !          1561:        if (xfer == NULL) {
        !          1562:                /* Just ignore the change. */
        !          1563:                return;
        !          1564:        }
        !          1565:
        !          1566:        pipe = xfer->pipe;
        !          1567:
        !          1568:        p = KERNADDR(&xfer->dmabuf, 0);
        !          1569:        m = min(sc->sc_noport, xfer->length * 8 - 1);
        !          1570:        memset(p, 0, xfer->length);
        !          1571:        for (i = 1; i <= m; i++) {
        !          1572:                /* Pick out CHANGE bits from the status reg. */
        !          1573:                if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16)
        !          1574:                        p[i/8] |= 1 << (i%8);
        !          1575:        }
        !          1576:        DPRINTF(("ohci_rhsc: change=0x%02x\n", *p));
        !          1577:        xfer->actlen = xfer->length;
        !          1578:        xfer->status = USBD_NORMAL_COMPLETION;
        !          1579:
        !          1580:        usb_transfer_complete(xfer);
        !          1581: }
        !          1582:
        !          1583: void
        !          1584: ohci_root_intr_done(usbd_xfer_handle xfer)
        !          1585: {
        !          1586: }
        !          1587:
        !          1588: void
        !          1589: ohci_root_ctrl_done(usbd_xfer_handle xfer)
        !          1590: {
        !          1591: }
        !          1592:
        !          1593: /*
        !          1594:  * Wait here until controller claims to have an interrupt.
        !          1595:  * Then call ohci_intr and return.  Use timeout to avoid waiting
        !          1596:  * too long.
        !          1597:  */
        !          1598: void
        !          1599: ohci_waitintr(ohci_softc_t *sc, usbd_xfer_handle xfer)
        !          1600: {
        !          1601:        int timo;
        !          1602:        u_int32_t intrs;
        !          1603:
        !          1604:        xfer->status = USBD_IN_PROGRESS;
        !          1605:        for (timo = xfer->timeout; timo >= 0; timo--) {
        !          1606:                usb_delay_ms(&sc->sc_bus, 1);
        !          1607:                if (sc->sc_dying)
        !          1608:                        break;
        !          1609:                intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs;
        !          1610:                DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs));
        !          1611: #ifdef OHCI_DEBUG
        !          1612:                if (ohcidebug > 15)
        !          1613:                        ohci_dumpregs(sc);
        !          1614: #endif
        !          1615:                if (intrs) {
        !          1616:                        ohci_intr1(sc);
        !          1617:                        if (xfer->status != USBD_IN_PROGRESS)
        !          1618:                                return;
        !          1619:                }
        !          1620:        }
        !          1621:
        !          1622:        /* Timeout */
        !          1623:        DPRINTF(("ohci_waitintr: timeout\n"));
        !          1624:        xfer->status = USBD_TIMEOUT;
        !          1625:        usb_transfer_complete(xfer);
        !          1626:        /* XXX should free TD */
        !          1627: }
        !          1628:
        !          1629: void
        !          1630: ohci_poll(struct usbd_bus *bus)
        !          1631: {
        !          1632:        ohci_softc_t *sc = (ohci_softc_t *)bus;
        !          1633: #ifdef OHCI_DEBUG
        !          1634:        static int last;
        !          1635:        int new;
        !          1636:        new = OREAD4(sc, OHCI_INTERRUPT_STATUS);
        !          1637:        if (new != last) {
        !          1638:                DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new));
        !          1639:                last = new;
        !          1640:        }
        !          1641: #endif
        !          1642:
        !          1643:        if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs)
        !          1644:                ohci_intr1(sc);
        !          1645: }
        !          1646:
        !          1647: usbd_status
        !          1648: ohci_device_request(usbd_xfer_handle xfer)
        !          1649: {
        !          1650:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          1651:        usb_device_request_t *req = &xfer->request;
        !          1652:        usbd_device_handle dev = opipe->pipe.device;
        !          1653:        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        !          1654:        int addr = dev->address;
        !          1655:        ohci_soft_td_t *setup, *stat, *next, *tail;
        !          1656:        ohci_soft_ed_t *sed;
        !          1657:        int isread;
        !          1658:        int len;
        !          1659:        usbd_status err;
        !          1660:        int s;
        !          1661:
        !          1662:        isread = req->bmRequestType & UT_READ;
        !          1663:        len = UGETW(req->wLength);
        !          1664:
        !          1665:        DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, "
        !          1666:                    "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
        !          1667:                    req->bmRequestType, req->bRequest, UGETW(req->wValue),
        !          1668:                    UGETW(req->wIndex), len, addr,
        !          1669:                    opipe->pipe.endpoint->edesc->bEndpointAddress));
        !          1670:
        !          1671:        setup = opipe->tail.td;
        !          1672:        stat = ohci_alloc_std(sc);
        !          1673:        if (stat == NULL) {
        !          1674:                err = USBD_NOMEM;
        !          1675:                goto bad1;
        !          1676:        }
        !          1677:        tail = ohci_alloc_std(sc);
        !          1678:        if (tail == NULL) {
        !          1679:                err = USBD_NOMEM;
        !          1680:                goto bad2;
        !          1681:        }
        !          1682:        tail->xfer = NULL;
        !          1683:
        !          1684:        sed = opipe->sed;
        !          1685:        opipe->u.ctl.length = len;
        !          1686:
        !          1687:        /* Update device address and length since they may have changed
        !          1688:           during the setup of the control pipe in usbd_new_device(). */
        !          1689:        /* XXX This only needs to be done once, but it's too early in open. */
        !          1690:        /* XXXX Should not touch ED here! */
        !          1691:        sed->ed.ed_flags = htole32(
        !          1692:         (letoh32(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
        !          1693:         OHCI_ED_SET_FA(addr) |
        !          1694:         OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
        !          1695:
        !          1696:        next = stat;
        !          1697:
        !          1698:        /* Set up data transaction */
        !          1699:        if (len != 0) {
        !          1700:                ohci_soft_td_t *std = stat;
        !          1701:
        !          1702:                err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
        !          1703:                          std, &stat);
        !          1704:                stat = stat->nexttd; /* point at free TD */
        !          1705:                if (err)
        !          1706:                        goto bad3;
        !          1707:                /* Start toggle at 1 and then use the carried toggle. */
        !          1708:                std->td.td_flags &= htole32(~OHCI_TD_TOGGLE_MASK);
        !          1709:                std->td.td_flags |= htole32(OHCI_TD_TOGGLE_1);
        !          1710:        }
        !          1711:
        !          1712:        memcpy(KERNADDR(&opipe->u.ctl.reqdma, 0), req, sizeof *req);
        !          1713:
        !          1714:        setup->td.td_flags = htole32(OHCI_TD_SETUP | OHCI_TD_NOCC |
        !          1715:                                     OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
        !          1716:        setup->td.td_cbp = htole32(DMAADDR(&opipe->u.ctl.reqdma, 0));
        !          1717:        setup->nexttd = next;
        !          1718:        setup->td.td_nexttd = htole32(next->physaddr);
        !          1719:        setup->td.td_be = htole32(letoh32(setup->td.td_cbp) + sizeof *req - 1);
        !          1720:        setup->len = 0;
        !          1721:        setup->xfer = xfer;
        !          1722:        setup->flags = 0;
        !          1723:        xfer->hcpriv = setup;
        !          1724:
        !          1725:        stat->td.td_flags = htole32(
        !          1726:                (isread ? OHCI_TD_OUT : OHCI_TD_IN) |
        !          1727:                OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
        !          1728:        stat->td.td_cbp = 0;
        !          1729:        stat->nexttd = tail;
        !          1730:        stat->td.td_nexttd = htole32(tail->physaddr);
        !          1731:        stat->td.td_be = 0;
        !          1732:        stat->flags = OHCI_CALL_DONE;
        !          1733:        stat->len = 0;
        !          1734:        stat->xfer = xfer;
        !          1735:
        !          1736: #ifdef OHCI_DEBUG
        !          1737:        if (ohcidebug > 5) {
        !          1738:                DPRINTF(("ohci_device_request:\n"));
        !          1739:                ohci_dump_ed(sed);
        !          1740:                ohci_dump_tds(setup);
        !          1741:        }
        !          1742: #endif
        !          1743:
        !          1744:        /* Insert ED in schedule */
        !          1745:        s = splusb();
        !          1746:        sed->ed.ed_tailp = htole32(tail->physaddr);
        !          1747:        opipe->tail.td = tail;
        !          1748:        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
        !          1749:        if (xfer->timeout && !sc->sc_bus.use_polling) {
        !          1750:                 timeout_del(&xfer->timeout_handle);
        !          1751:                 timeout_set(&xfer->timeout_handle, ohci_timeout, xfer);
        !          1752:                 timeout_add(&xfer->timeout_handle, mstohz(xfer->timeout));
        !          1753:        }
        !          1754:        splx(s);
        !          1755:
        !          1756: #ifdef OHCI_DEBUG
        !          1757:        if (ohcidebug > 20) {
        !          1758:                delay(10000);
        !          1759:                DPRINTF(("ohci_device_request: status=%x\n",
        !          1760:                         OREAD4(sc, OHCI_COMMAND_STATUS)));
        !          1761:                ohci_dumpregs(sc);
        !          1762:                printf("ctrl head:\n");
        !          1763:                ohci_dump_ed(sc->sc_ctrl_head);
        !          1764:                printf("sed:\n");
        !          1765:                ohci_dump_ed(sed);
        !          1766:                ohci_dump_tds(setup);
        !          1767:        }
        !          1768: #endif
        !          1769:
        !          1770:        return (USBD_NORMAL_COMPLETION);
        !          1771:
        !          1772:  bad3:
        !          1773:        ohci_free_std(sc, tail);
        !          1774:  bad2:
        !          1775:        ohci_free_std(sc, stat);
        !          1776:  bad1:
        !          1777:        return (err);
        !          1778: }
        !          1779:
        !          1780: /*
        !          1781:  * Add an ED to the schedule.  Called at splusb().
        !          1782:  */
        !          1783: void
        !          1784: ohci_add_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head)
        !          1785: {
        !          1786:        DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head));
        !          1787:
        !          1788:        SPLUSBCHECK;
        !          1789:        sed->next = head->next;
        !          1790:        sed->ed.ed_nexted = head->ed.ed_nexted;
        !          1791:        head->next = sed;
        !          1792:        head->ed.ed_nexted = htole32(sed->physaddr);
        !          1793: }
        !          1794:
        !          1795: /*
        !          1796:  * Remove an ED from the schedule.  Called at splusb().
        !          1797:  */
        !          1798: void
        !          1799: ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head)
        !          1800: {
        !          1801:        ohci_soft_ed_t *p;
        !          1802:
        !          1803:        SPLUSBCHECK;
        !          1804:
        !          1805:        /* XXX */
        !          1806:        for (p = head; p != NULL && p->next != sed; p = p->next)
        !          1807:                ;
        !          1808:        if (p == NULL)
        !          1809:                panic("ohci_rem_ed: ED not found");
        !          1810:        p->next = sed->next;
        !          1811:        p->ed.ed_nexted = sed->ed.ed_nexted;
        !          1812: }
        !          1813:
        !          1814: /*
        !          1815:  * When a transfer is completed the TD is added to the done queue by
        !          1816:  * the host controller.  This queue is the processed by software.
        !          1817:  * Unfortunately the queue contains the physical address of the TD
        !          1818:  * and we have no simple way to translate this back to a kernel address.
        !          1819:  * To make the translation possible (and fast) we use a hash table of
        !          1820:  * TDs currently in the schedule.  The physical address is used as the
        !          1821:  * hash value.
        !          1822:  */
        !          1823:
        !          1824: #define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE)
        !          1825: /* Called at splusb() */
        !          1826: void
        !          1827: ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std)
        !          1828: {
        !          1829:        int h = HASH(std->physaddr);
        !          1830:
        !          1831:        SPLUSBCHECK;
        !          1832:
        !          1833:        LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext);
        !          1834: }
        !          1835:
        !          1836: /* Called at splusb() */
        !          1837: void
        !          1838: ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std)
        !          1839: {
        !          1840:        SPLUSBCHECK;
        !          1841:
        !          1842:        LIST_REMOVE(std, hnext);
        !          1843: }
        !          1844:
        !          1845: ohci_soft_td_t *
        !          1846: ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a)
        !          1847: {
        !          1848:        int h = HASH(a);
        !          1849:        ohci_soft_td_t *std;
        !          1850:
        !          1851:        for (std = LIST_FIRST(&sc->sc_hash_tds[h]);
        !          1852:             std != NULL;
        !          1853:             std = LIST_NEXT(std, hnext))
        !          1854:                if (std->physaddr == a)
        !          1855:                        return (std);
        !          1856:        return (NULL);
        !          1857: }
        !          1858:
        !          1859: /* Called at splusb() */
        !          1860: void
        !          1861: ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
        !          1862: {
        !          1863:        int h = HASH(sitd->physaddr);
        !          1864:
        !          1865:        SPLUSBCHECK;
        !          1866:
        !          1867:        DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n",
        !          1868:                    sitd, (u_long)sitd->physaddr));
        !          1869:
        !          1870:        LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext);
        !          1871: }
        !          1872:
        !          1873: /* Called at splusb() */
        !          1874: void
        !          1875: ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
        !          1876: {
        !          1877:        SPLUSBCHECK;
        !          1878:
        !          1879:        DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n",
        !          1880:                    sitd, (u_long)sitd->physaddr));
        !          1881:
        !          1882:        LIST_REMOVE(sitd, hnext);
        !          1883: }
        !          1884:
        !          1885: ohci_soft_itd_t *
        !          1886: ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a)
        !          1887: {
        !          1888:        int h = HASH(a);
        !          1889:        ohci_soft_itd_t *sitd;
        !          1890:
        !          1891:        for (sitd = LIST_FIRST(&sc->sc_hash_itds[h]);
        !          1892:             sitd != NULL;
        !          1893:             sitd = LIST_NEXT(sitd, hnext))
        !          1894:                if (sitd->physaddr == a)
        !          1895:                        return (sitd);
        !          1896:        return (NULL);
        !          1897: }
        !          1898:
        !          1899: void
        !          1900: ohci_timeout(void *addr)
        !          1901: {
        !          1902:        struct ohci_xfer *oxfer = addr;
        !          1903:        struct ohci_pipe *opipe = (struct ohci_pipe *)oxfer->xfer.pipe;
        !          1904:        ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
        !          1905:
        !          1906:        DPRINTF(("ohci_timeout: oxfer=%p\n", oxfer));
        !          1907:
        !          1908:        if (sc->sc_dying) {
        !          1909:                ohci_abort_xfer(&oxfer->xfer, USBD_TIMEOUT);
        !          1910:                return;
        !          1911:        }
        !          1912:
        !          1913:        /* Execute the abort in a process context. */
        !          1914:        usb_init_task(&oxfer->abort_task, ohci_timeout_task, addr);
        !          1915:        usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task);
        !          1916: }
        !          1917:
        !          1918: void
        !          1919: ohci_timeout_task(void *addr)
        !          1920: {
        !          1921:        usbd_xfer_handle xfer = addr;
        !          1922:        int s;
        !          1923:
        !          1924:        DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer));
        !          1925:
        !          1926:        s = splusb();
        !          1927:        ohci_abort_xfer(xfer, USBD_TIMEOUT);
        !          1928:        splx(s);
        !          1929: }
        !          1930:
        !          1931: #ifdef OHCI_DEBUG
        !          1932: void
        !          1933: ohci_dump_tds(ohci_soft_td_t *std)
        !          1934: {
        !          1935:        for (; std; std = std->nexttd)
        !          1936:                ohci_dump_td(std);
        !          1937: }
        !          1938:
        !          1939: void
        !          1940: ohci_dump_td(ohci_soft_td_t *std)
        !          1941: {
        !          1942:        char sbuf[128];
        !          1943:
        !          1944:        bitmask_snprintf((u_int32_t)letoh32(std->td.td_flags),
        !          1945:                         "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
        !          1946:                         sbuf, sizeof(sbuf));
        !          1947:
        !          1948:        printf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx "
        !          1949:               "nexttd=0x%08lx be=0x%08lx\n",
        !          1950:               std, (u_long)std->physaddr, sbuf,
        !          1951:               OHCI_TD_GET_DI(letoh32(std->td.td_flags)),
        !          1952:               OHCI_TD_GET_EC(letoh32(std->td.td_flags)),
        !          1953:               OHCI_TD_GET_CC(letoh32(std->td.td_flags)),
        !          1954:               (u_long)letoh32(std->td.td_cbp),
        !          1955:               (u_long)letoh32(std->td.td_nexttd),
        !          1956:               (u_long)letoh32(std->td.td_be));
        !          1957: }
        !          1958:
        !          1959: void
        !          1960: ohci_dump_itd(ohci_soft_itd_t *sitd)
        !          1961: {
        !          1962:        int i;
        !          1963:
        !          1964:        printf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n"
        !          1965:               "bp0=0x%08lx next=0x%08lx be=0x%08lx\n",
        !          1966:               sitd, (u_long)sitd->physaddr,
        !          1967:               OHCI_ITD_GET_SF(letoh32(sitd->itd.itd_flags)),
        !          1968:               OHCI_ITD_GET_DI(letoh32(sitd->itd.itd_flags)),
        !          1969:               OHCI_ITD_GET_FC(letoh32(sitd->itd.itd_flags)),
        !          1970:               OHCI_ITD_GET_CC(letoh32(sitd->itd.itd_flags)),
        !          1971:               (u_long)letoh32(sitd->itd.itd_bp0),
        !          1972:               (u_long)letoh32(sitd->itd.itd_nextitd),
        !          1973:               (u_long)letoh32(sitd->itd.itd_be));
        !          1974:        for (i = 0; i < OHCI_ITD_NOFFSET; i++)
        !          1975:                printf("offs[%d]=0x%04x ", i,
        !          1976:                       (u_int)letoh16(sitd->itd.itd_offset[i]));
        !          1977:        printf("\n");
        !          1978: }
        !          1979:
        !          1980: void
        !          1981: ohci_dump_itds(ohci_soft_itd_t *sitd)
        !          1982: {
        !          1983:        for (; sitd; sitd = sitd->nextitd)
        !          1984:                ohci_dump_itd(sitd);
        !          1985: }
        !          1986:
        !          1987: void
        !          1988: ohci_dump_ed(ohci_soft_ed_t *sed)
        !          1989: {
        !          1990:        char sbuf[128], sbuf2[128];
        !          1991:
        !          1992:        bitmask_snprintf((u_int32_t)letoh32(sed->ed.ed_flags),
        !          1993:                         "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO",
        !          1994:                         sbuf, sizeof(sbuf));
        !          1995:        bitmask_snprintf((u_int32_t)letoh32(sed->ed.ed_headp),
        !          1996:                         "\20\1HALT\2CARRY", sbuf2, sizeof(sbuf2));
        !          1997:
        !          1998:        printf("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d flags=%s\n"
        !          1999:               "tailp=0x%08lx headflags=%s headp=0x%08lx nexted=0x%08lx\n",
        !          2000:               sed, (u_long)sed->physaddr,
        !          2001:               OHCI_ED_GET_FA(letoh32(sed->ed.ed_flags)),
        !          2002:               OHCI_ED_GET_EN(letoh32(sed->ed.ed_flags)),
        !          2003:               OHCI_ED_GET_MAXP(letoh32(sed->ed.ed_flags)), sbuf,
        !          2004:               (u_long)letoh32(sed->ed.ed_tailp), sbuf2,
        !          2005:               (u_long)letoh32(sed->ed.ed_headp),
        !          2006:               (u_long)letoh32(sed->ed.ed_nexted));
        !          2007: }
        !          2008: #endif
        !          2009:
        !          2010: usbd_status
        !          2011: ohci_open(usbd_pipe_handle pipe)
        !          2012: {
        !          2013:        usbd_device_handle dev = pipe->device;
        !          2014:        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        !          2015:        usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
        !          2016:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          2017:        u_int8_t addr = dev->address;
        !          2018:        u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
        !          2019:        ohci_soft_ed_t *sed;
        !          2020:        ohci_soft_td_t *std;
        !          2021:        ohci_soft_itd_t *sitd;
        !          2022:        ohci_physaddr_t tdphys;
        !          2023:        u_int32_t fmt;
        !          2024:        usbd_status err;
        !          2025:        int s;
        !          2026:        int ival;
        !          2027:
        !          2028:        DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
        !          2029:                     pipe, addr, ed->bEndpointAddress, sc->sc_addr));
        !          2030:
        !          2031:        if (sc->sc_dying)
        !          2032:                return (USBD_IOERROR);
        !          2033:
        !          2034:        std = NULL;
        !          2035:        sed = NULL;
        !          2036:
        !          2037:        if (addr == sc->sc_addr) {
        !          2038:                switch (ed->bEndpointAddress) {
        !          2039:                case USB_CONTROL_ENDPOINT:
        !          2040:                        pipe->methods = &ohci_root_ctrl_methods;
        !          2041:                        break;
        !          2042:                case UE_DIR_IN | OHCI_INTR_ENDPT:
        !          2043:                        pipe->methods = &ohci_root_intr_methods;
        !          2044:                        break;
        !          2045:                default:
        !          2046:                        return (USBD_INVAL);
        !          2047:                }
        !          2048:        } else {
        !          2049:                sed = ohci_alloc_sed(sc);
        !          2050:                if (sed == NULL)
        !          2051:                        goto bad0;
        !          2052:                opipe->sed = sed;
        !          2053:                if (xfertype == UE_ISOCHRONOUS) {
        !          2054:                        sitd = ohci_alloc_sitd(sc);
        !          2055:                        if (sitd == NULL)
        !          2056:                                goto bad1;
        !          2057:                        opipe->tail.itd = sitd;
        !          2058:                        tdphys = sitd->physaddr;
        !          2059:                        fmt = OHCI_ED_FORMAT_ISO;
        !          2060:                        if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
        !          2061:                                fmt |= OHCI_ED_DIR_IN;
        !          2062:                        else
        !          2063:                                fmt |= OHCI_ED_DIR_OUT;
        !          2064:                } else {
        !          2065:                        std = ohci_alloc_std(sc);
        !          2066:                        if (std == NULL)
        !          2067:                                goto bad1;
        !          2068:                        opipe->tail.td = std;
        !          2069:                        tdphys = std->physaddr;
        !          2070:                        fmt = OHCI_ED_FORMAT_GEN | OHCI_ED_DIR_TD;
        !          2071:                }
        !          2072:                sed->ed.ed_flags = htole32(
        !          2073:                        OHCI_ED_SET_FA(addr) |
        !          2074:                        OHCI_ED_SET_EN(UE_GET_ADDR(ed->bEndpointAddress)) |
        !          2075:                        (dev->speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) |
        !          2076:                        fmt | OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)));
        !          2077:                sed->ed.ed_headp = htole32(tdphys |
        !          2078:                    (pipe->endpoint->savedtoggle ? OHCI_TOGGLECARRY : 0));
        !          2079:                sed->ed.ed_tailp = htole32(tdphys);
        !          2080:
        !          2081:                switch (xfertype) {
        !          2082:                case UE_CONTROL:
        !          2083:                        pipe->methods = &ohci_device_ctrl_methods;
        !          2084:                        err = usb_allocmem(&sc->sc_bus,
        !          2085:                                  sizeof(usb_device_request_t),
        !          2086:                                  0, &opipe->u.ctl.reqdma);
        !          2087:                        if (err)
        !          2088:                                goto bad;
        !          2089:                        s = splusb();
        !          2090:                        ohci_add_ed(sed, sc->sc_ctrl_head);
        !          2091:                        splx(s);
        !          2092:                        break;
        !          2093:                case UE_INTERRUPT:
        !          2094:                        pipe->methods = &ohci_device_intr_methods;
        !          2095:                        ival = pipe->interval;
        !          2096:                        if (ival == USBD_DEFAULT_INTERVAL)
        !          2097:                                ival = ed->bInterval;
        !          2098:                        return (ohci_device_setintr(sc, opipe, ival));
        !          2099:                case UE_ISOCHRONOUS:
        !          2100:                        pipe->methods = &ohci_device_isoc_methods;
        !          2101:                        return (ohci_setup_isoc(pipe));
        !          2102:                case UE_BULK:
        !          2103:                        pipe->methods = &ohci_device_bulk_methods;
        !          2104:                        s = splusb();
        !          2105:                        ohci_add_ed(sed, sc->sc_bulk_head);
        !          2106:                        splx(s);
        !          2107:                        break;
        !          2108:                }
        !          2109:        }
        !          2110:        return (USBD_NORMAL_COMPLETION);
        !          2111:
        !          2112:  bad:
        !          2113:        if (std != NULL)
        !          2114:                ohci_free_std(sc, std);
        !          2115:  bad1:
        !          2116:        if (sed != NULL)
        !          2117:                ohci_free_sed(sc, sed);
        !          2118:  bad0:
        !          2119:        return (USBD_NOMEM);
        !          2120:
        !          2121: }
        !          2122:
        !          2123: /*
        !          2124:  * Close a reqular pipe.
        !          2125:  * Assumes that there are no pending transactions.
        !          2126:  */
        !          2127: void
        !          2128: ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head)
        !          2129: {
        !          2130:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          2131:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          2132:        ohci_soft_ed_t *sed = opipe->sed;
        !          2133:        int s;
        !          2134:
        !          2135:        s = splusb();
        !          2136: #ifdef DIAGNOSTIC
        !          2137:        sed->ed.ed_flags |= htole32(OHCI_ED_SKIP);
        !          2138:        if ((letoh32(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
        !          2139:            (letoh32(sed->ed.ed_headp) & OHCI_HEADMASK)) {
        !          2140:                ohci_soft_td_t *std;
        !          2141:                std = ohci_hash_find_td(sc, letoh32(sed->ed.ed_headp));
        !          2142:                printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x "
        !          2143:                       "tl=0x%x pipe=%p, std=%p\n", sed,
        !          2144:                       (int)letoh32(sed->ed.ed_headp),
        !          2145:                       (int)letoh32(sed->ed.ed_tailp),
        !          2146:                       pipe, std);
        !          2147: #ifdef USB_DEBUG
        !          2148:                usbd_dump_pipe(&opipe->pipe);
        !          2149: #endif
        !          2150: #ifdef OHCI_DEBUG
        !          2151:                ohci_dump_ed(sed);
        !          2152:                if (std)
        !          2153:                        ohci_dump_td(std);
        !          2154: #endif
        !          2155:                usb_delay_ms(&sc->sc_bus, 2);
        !          2156:                if ((letoh32(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
        !          2157:                    (letoh32(sed->ed.ed_headp) & OHCI_HEADMASK))
        !          2158:                        printf("ohci_close_pipe: pipe still not empty\n");
        !          2159:        }
        !          2160: #endif
        !          2161:        ohci_rem_ed(sed, head);
        !          2162:        /* Make sure the host controller is not touching this ED */
        !          2163:        usb_delay_ms(&sc->sc_bus, 1);
        !          2164:        splx(s);
        !          2165:        pipe->endpoint->savedtoggle =
        !          2166:            (letoh32(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0;
        !          2167:        ohci_free_sed(sc, opipe->sed);
        !          2168: }
        !          2169:
        !          2170: /*
        !          2171:  * Abort a device request.
        !          2172:  * If this routine is called at splusb() it guarantees that the request
        !          2173:  * will be removed from the hardware scheduling and that the callback
        !          2174:  * for it will be called with USBD_CANCELLED status.
        !          2175:  * It's impossible to guarantee that the requested transfer will not
        !          2176:  * have happened since the hardware runs concurrently.
        !          2177:  * If the transaction has already happened we rely on the ordinary
        !          2178:  * interrupt processing to process it.
        !          2179:  */
        !          2180: void
        !          2181: ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
        !          2182: {
        !          2183:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          2184:        ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
        !          2185:        ohci_soft_ed_t *sed = opipe->sed;
        !          2186:        ohci_soft_td_t *p, *n;
        !          2187:        ohci_physaddr_t headp;
        !          2188:        int s, hit;
        !          2189:
        !          2190:        DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,
        !          2191:                 sed));
        !          2192:
        !          2193:        if (sc->sc_dying) {
        !          2194:                /* If we're dying, just do the software part. */
        !          2195:                s = splusb();
        !          2196:                xfer->status = status;  /* make software ignore it */
        !          2197:                timeout_del(&xfer->timeout_handle);
        !          2198:                usb_transfer_complete(xfer);
        !          2199:                splx(s);
        !          2200:                return;
        !          2201:        }
        !          2202:
        !          2203:        if (xfer->device->bus->intr_context || !curproc)
        !          2204:                panic("ohci_abort_xfer: not in process context");
        !          2205:
        !          2206:        /*
        !          2207:         * Step 1: Make interrupt routine and hardware ignore xfer.
        !          2208:         */
        !          2209:        s = splusb();
        !          2210:        xfer->status = status;  /* make software ignore it */
        !          2211:        timeout_del(&xfer->timeout_handle);
        !          2212:        splx(s);
        !          2213:        DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
        !          2214:        sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */
        !          2215:
        !          2216:        /*
        !          2217:         * Step 2: Wait until we know hardware has finished any possible
        !          2218:         * use of the xfer.  Also make sure the soft interrupt routine
        !          2219:         * has run.
        !          2220:         */
        !          2221:        usb_delay_ms(opipe->pipe.device->bus, 20); /* Hardware finishes in 1ms */
        !          2222:        s = splusb();
        !          2223: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
        !          2224:        sc->sc_softwake = 1;
        !          2225: #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
        !          2226:        usb_schedsoftintr(&sc->sc_bus);
        !          2227: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
        !          2228:        tsleep(&sc->sc_softwake, PZERO, "ohciab", 0);
        !          2229: #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
        !          2230:        splx(s);
        !          2231:
        !          2232:        /*
        !          2233:         * Step 3: Remove any vestiges of the xfer from the hardware.
        !          2234:         * The complication here is that the hardware may have executed
        !          2235:         * beyond the xfer we're trying to abort.  So as we're scanning
        !          2236:         * the TDs of this xfer we check if the hardware points to
        !          2237:         * any of them.
        !          2238:         */
        !          2239:        s = splusb();           /* XXX why? */
        !          2240:        p = xfer->hcpriv;
        !          2241: #ifdef DIAGNOSTIC
        !          2242:        if (p == NULL) {
        !          2243:                splx(s);
        !          2244:                printf("ohci_abort_xfer: hcpriv is NULL\n");
        !          2245:                return;
        !          2246:        }
        !          2247: #endif
        !          2248: #ifdef OHCI_DEBUG
        !          2249:        if (ohcidebug > 1) {
        !          2250:                DPRINTF(("ohci_abort_xfer: sed=\n"));
        !          2251:                ohci_dump_ed(sed);
        !          2252:                ohci_dump_tds(p);
        !          2253:        }
        !          2254: #endif
        !          2255:        headp = letoh32(sed->ed.ed_headp) & OHCI_HEADMASK;
        !          2256:        hit = 0;
        !          2257:        for (; p->xfer == xfer; p = n) {
        !          2258:                hit |= headp == p->physaddr;
        !          2259:                n = p->nexttd;
        !          2260:                if (OHCI_TD_GET_CC(letoh32(p->td.td_flags)) ==
        !          2261:                    OHCI_CC_NOT_ACCESSED)
        !          2262:                        ohci_free_std(sc, p);
        !          2263:        }
        !          2264:        /* Zap headp register if hardware pointed inside the xfer. */
        !          2265:        if (hit) {
        !          2266:                DPRINTFN(1,("ohci_abort_xfer: set hd=0x%08x, tl=0x%08x\n",
        !          2267:                            (int)p->physaddr, (int)letoh32(sed->ed.ed_tailp)));
        !          2268:                sed->ed.ed_headp = htole32(p->physaddr); /* unlink TDs */
        !          2269:        } else {
        !          2270:                DPRINTFN(1,("ohci_abort_xfer: no hit\n"));
        !          2271:        }
        !          2272:
        !          2273:        /*
        !          2274:         * Step 4: Turn on hardware again.
        !          2275:         */
        !          2276:        sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */
        !          2277:
        !          2278:        /*
        !          2279:         * Step 5: Execute callback.
        !          2280:         */
        !          2281:        usb_transfer_complete(xfer);
        !          2282:
        !          2283:        splx(s);
        !          2284: }
        !          2285:
        !          2286: /*
        !          2287:  * Data structures and routines to emulate the root hub.
        !          2288:  */
        !          2289: usb_device_descriptor_t ohci_devd = {
        !          2290:        USB_DEVICE_DESCRIPTOR_SIZE,
        !          2291:        UDESC_DEVICE,           /* type */
        !          2292:        {0x00, 0x01},           /* USB version */
        !          2293:        UDCLASS_HUB,            /* class */
        !          2294:        UDSUBCLASS_HUB,         /* subclass */
        !          2295:        UDPROTO_FSHUB,
        !          2296:        64,                     /* max packet */
        !          2297:        {0},{0},{0x00,0x01},    /* device id */
        !          2298:        1,2,0,                  /* string indices */
        !          2299:        1                       /* # of configurations */
        !          2300: };
        !          2301:
        !          2302: usb_config_descriptor_t ohci_confd = {
        !          2303:        USB_CONFIG_DESCRIPTOR_SIZE,
        !          2304:        UDESC_CONFIG,
        !          2305:        {USB_CONFIG_DESCRIPTOR_SIZE +
        !          2306:         USB_INTERFACE_DESCRIPTOR_SIZE +
        !          2307:         USB_ENDPOINT_DESCRIPTOR_SIZE},
        !          2308:        1,
        !          2309:        1,
        !          2310:        0,
        !          2311:        UC_SELF_POWERED,
        !          2312:        0                       /* max power */
        !          2313: };
        !          2314:
        !          2315: usb_interface_descriptor_t ohci_ifcd = {
        !          2316:        USB_INTERFACE_DESCRIPTOR_SIZE,
        !          2317:        UDESC_INTERFACE,
        !          2318:        0,
        !          2319:        0,
        !          2320:        1,
        !          2321:        UICLASS_HUB,
        !          2322:        UISUBCLASS_HUB,
        !          2323:        UIPROTO_FSHUB,
        !          2324:        0
        !          2325: };
        !          2326:
        !          2327: usb_endpoint_descriptor_t ohci_endpd = {
        !          2328:        USB_ENDPOINT_DESCRIPTOR_SIZE,
        !          2329:        UDESC_ENDPOINT,
        !          2330:        UE_DIR_IN | OHCI_INTR_ENDPT,
        !          2331:        UE_INTERRUPT,
        !          2332:        {8, 0},                 /* max packet */
        !          2333:        255
        !          2334: };
        !          2335:
        !          2336: usb_hub_descriptor_t ohci_hubd = {
        !          2337:        USB_HUB_DESCRIPTOR_SIZE,
        !          2338:        UDESC_HUB,
        !          2339:        0,
        !          2340:        {0,0},
        !          2341:        0,
        !          2342:        0,
        !          2343:        {0},
        !          2344: };
        !          2345:
        !          2346: int
        !          2347: ohci_str(usb_string_descriptor_t *p, int l, const char *s)
        !          2348: {
        !          2349:        int i;
        !          2350:
        !          2351:        if (l == 0)
        !          2352:                return (0);
        !          2353:        p->bLength = 2 * strlen(s) + 2;
        !          2354:        if (l == 1)
        !          2355:                return (1);
        !          2356:        p->bDescriptorType = UDESC_STRING;
        !          2357:        l -= 2;
        !          2358:        for (i = 0; s[i] && l > 1; i++, l -= 2)
        !          2359:                USETW2(p->bString[i], 0, s[i]);
        !          2360:        return (2*i+2);
        !          2361: }
        !          2362:
        !          2363: /*
        !          2364:  * Simulate a hardware hub by handling all the necessary requests.
        !          2365:  */
        !          2366: usbd_status
        !          2367: ohci_root_ctrl_transfer(usbd_xfer_handle xfer)
        !          2368: {
        !          2369:        usbd_status err;
        !          2370:
        !          2371:        /* Insert last in queue. */
        !          2372:        err = usb_insert_transfer(xfer);
        !          2373:        if (err)
        !          2374:                return (err);
        !          2375:
        !          2376:        /* Pipe isn't running, start first */
        !          2377:        return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
        !          2378: }
        !          2379:
        !          2380: usbd_status
        !          2381: ohci_root_ctrl_start(usbd_xfer_handle xfer)
        !          2382: {
        !          2383:        ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
        !          2384:        usb_device_request_t *req;
        !          2385:        void *buf = NULL;
        !          2386:        int port, i;
        !          2387:        int s, len, value, index, l, totlen = 0;
        !          2388:        usb_port_status_t ps;
        !          2389:        usb_hub_descriptor_t hubd;
        !          2390:        usbd_status err;
        !          2391:        u_int32_t v;
        !          2392:
        !          2393:        if (sc->sc_dying)
        !          2394:                return (USBD_IOERROR);
        !          2395:
        !          2396: #ifdef DIAGNOSTIC
        !          2397:        if (!(xfer->rqflags & URQ_REQUEST))
        !          2398:                /* XXX panic */
        !          2399:                return (USBD_INVAL);
        !          2400: #endif
        !          2401:        req = &xfer->request;
        !          2402:
        !          2403:        DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n",
        !          2404:                    req->bmRequestType, req->bRequest));
        !          2405:
        !          2406:        len = UGETW(req->wLength);
        !          2407:        value = UGETW(req->wValue);
        !          2408:        index = UGETW(req->wIndex);
        !          2409:
        !          2410:        if (len != 0)
        !          2411:                buf = KERNADDR(&xfer->dmabuf, 0);
        !          2412:
        !          2413: #define C(x,y) ((x) | ((y) << 8))
        !          2414:        switch(C(req->bRequest, req->bmRequestType)) {
        !          2415:        case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
        !          2416:        case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
        !          2417:        case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
        !          2418:                /*
        !          2419:                 * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
        !          2420:                 * for the integrated root hub.
        !          2421:                 */
        !          2422:                break;
        !          2423:        case C(UR_GET_CONFIG, UT_READ_DEVICE):
        !          2424:                if (len > 0) {
        !          2425:                        *(u_int8_t *)buf = sc->sc_conf;
        !          2426:                        totlen = 1;
        !          2427:                }
        !          2428:                break;
        !          2429:        case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
        !          2430:                DPRINTFN(8,("ohci_root_ctrl_control wValue=0x%04x\n", value));
        !          2431:                switch(value >> 8) {
        !          2432:                case UDESC_DEVICE:
        !          2433:                        if ((value & 0xff) != 0) {
        !          2434:                                err = USBD_IOERROR;
        !          2435:                                goto ret;
        !          2436:                        }
        !          2437:                        totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
        !          2438:                        USETW(ohci_devd.idVendor, sc->sc_id_vendor);
        !          2439:                        memcpy(buf, &ohci_devd, l);
        !          2440:                        break;
        !          2441:                case UDESC_CONFIG:
        !          2442:                        if ((value & 0xff) != 0) {
        !          2443:                                err = USBD_IOERROR;
        !          2444:                                goto ret;
        !          2445:                        }
        !          2446:                        totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
        !          2447:                        memcpy(buf, &ohci_confd, l);
        !          2448:                        buf = (char *)buf + l;
        !          2449:                        len -= l;
        !          2450:                        l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
        !          2451:                        totlen += l;
        !          2452:                        memcpy(buf, &ohci_ifcd, l);
        !          2453:                        buf = (char *)buf + l;
        !          2454:                        len -= l;
        !          2455:                        l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
        !          2456:                        totlen += l;
        !          2457:                        memcpy(buf, &ohci_endpd, l);
        !          2458:                        break;
        !          2459:                case UDESC_STRING:
        !          2460:                        if (len == 0)
        !          2461:                                break;
        !          2462:                        *(u_int8_t *)buf = 0;
        !          2463:                        totlen = 1;
        !          2464:                        switch (value & 0xff) {
        !          2465:                        case 0: /* Language table */
        !          2466:                                totlen = ohci_str(buf, len, "\001");
        !          2467:                                break;
        !          2468:                        case 1: /* Vendor */
        !          2469:                                totlen = ohci_str(buf, len, sc->sc_vendor);
        !          2470:                                break;
        !          2471:                        case 2: /* Product */
        !          2472:                                totlen = ohci_str(buf, len, "OHCI root hub");
        !          2473:                                break;
        !          2474:                        }
        !          2475:                        break;
        !          2476:                default:
        !          2477:                        err = USBD_IOERROR;
        !          2478:                        goto ret;
        !          2479:                }
        !          2480:                break;
        !          2481:        case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
        !          2482:                if (len > 0) {
        !          2483:                        *(u_int8_t *)buf = 0;
        !          2484:                        totlen = 1;
        !          2485:                }
        !          2486:                break;
        !          2487:        case C(UR_GET_STATUS, UT_READ_DEVICE):
        !          2488:                if (len > 1) {
        !          2489:                        USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED);
        !          2490:                        totlen = 2;
        !          2491:                }
        !          2492:                break;
        !          2493:        case C(UR_GET_STATUS, UT_READ_INTERFACE):
        !          2494:        case C(UR_GET_STATUS, UT_READ_ENDPOINT):
        !          2495:                if (len > 1) {
        !          2496:                        USETW(((usb_status_t *)buf)->wStatus, 0);
        !          2497:                        totlen = 2;
        !          2498:                }
        !          2499:                break;
        !          2500:        case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
        !          2501:                if (value >= USB_MAX_DEVICES) {
        !          2502:                        err = USBD_IOERROR;
        !          2503:                        goto ret;
        !          2504:                }
        !          2505:                sc->sc_addr = value;
        !          2506:                break;
        !          2507:        case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
        !          2508:                if (value != 0 && value != 1) {
        !          2509:                        err = USBD_IOERROR;
        !          2510:                        goto ret;
        !          2511:                }
        !          2512:                sc->sc_conf = value;
        !          2513:                break;
        !          2514:        case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
        !          2515:                break;
        !          2516:        case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
        !          2517:        case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
        !          2518:        case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
        !          2519:                err = USBD_IOERROR;
        !          2520:                goto ret;
        !          2521:        case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
        !          2522:                break;
        !          2523:        case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
        !          2524:                break;
        !          2525:        /* Hub requests */
        !          2526:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
        !          2527:                break;
        !          2528:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
        !          2529:                DPRINTFN(8, ("ohci_root_ctrl_control: UR_CLEAR_PORT_FEATURE "
        !          2530:                             "port=%d feature=%d\n",
        !          2531:                             index, value));
        !          2532:                if (index < 1 || index > sc->sc_noport) {
        !          2533:                        err = USBD_IOERROR;
        !          2534:                        goto ret;
        !          2535:                }
        !          2536:                port = OHCI_RH_PORT_STATUS(index);
        !          2537:                switch(value) {
        !          2538:                case UHF_PORT_ENABLE:
        !          2539:                        OWRITE4(sc, port, UPS_CURRENT_CONNECT_STATUS);
        !          2540:                        break;
        !          2541:                case UHF_PORT_SUSPEND:
        !          2542:                        OWRITE4(sc, port, UPS_OVERCURRENT_INDICATOR);
        !          2543:                        break;
        !          2544:                case UHF_PORT_POWER:
        !          2545:                        /* Yes, writing to the LOW_SPEED bit clears power. */
        !          2546:                        OWRITE4(sc, port, UPS_LOW_SPEED);
        !          2547:                        break;
        !          2548:                case UHF_C_PORT_CONNECTION:
        !          2549:                        OWRITE4(sc, port, UPS_C_CONNECT_STATUS << 16);
        !          2550:                        break;
        !          2551:                case UHF_C_PORT_ENABLE:
        !          2552:                        OWRITE4(sc, port, UPS_C_PORT_ENABLED << 16);
        !          2553:                        break;
        !          2554:                case UHF_C_PORT_SUSPEND:
        !          2555:                        OWRITE4(sc, port, UPS_C_SUSPEND << 16);
        !          2556:                        break;
        !          2557:                case UHF_C_PORT_OVER_CURRENT:
        !          2558:                        OWRITE4(sc, port, UPS_C_OVERCURRENT_INDICATOR << 16);
        !          2559:                        break;
        !          2560:                case UHF_C_PORT_RESET:
        !          2561:                        OWRITE4(sc, port, UPS_C_PORT_RESET << 16);
        !          2562:                        break;
        !          2563:                default:
        !          2564:                        err = USBD_IOERROR;
        !          2565:                        goto ret;
        !          2566:                }
        !          2567:                switch(value) {
        !          2568:                case UHF_C_PORT_CONNECTION:
        !          2569:                case UHF_C_PORT_ENABLE:
        !          2570:                case UHF_C_PORT_SUSPEND:
        !          2571:                case UHF_C_PORT_OVER_CURRENT:
        !          2572:                case UHF_C_PORT_RESET:
        !          2573:                        /* Enable RHSC interrupt if condition is cleared. */
        !          2574:                        if ((OREAD4(sc, port) >> 16) == 0)
        !          2575:                                ohci_rhsc_able(sc, 1);
        !          2576:                        break;
        !          2577:                default:
        !          2578:                        break;
        !          2579:                }
        !          2580:                break;
        !          2581:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
        !          2582:                if ((value & 0xff) != 0) {
        !          2583:                        err = USBD_IOERROR;
        !          2584:                        goto ret;
        !          2585:                }
        !          2586:                v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
        !          2587:                hubd = ohci_hubd;
        !          2588:                hubd.bNbrPorts = sc->sc_noport;
        !          2589:                USETW(hubd.wHubCharacteristics,
        !          2590:                      (v & OHCI_NPS ? UHD_PWR_NO_SWITCH :
        !          2591:                       v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL)
        !          2592:                      /* XXX overcurrent */
        !          2593:                      );
        !          2594:                hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v);
        !          2595:                v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B);
        !          2596:                for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8)
        !          2597:                        hubd.DeviceRemovable[i++] = (u_int8_t)v;
        !          2598:                hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i;
        !          2599:                l = min(len, hubd.bDescLength);
        !          2600:                totlen = l;
        !          2601:                memcpy(buf, &hubd, l);
        !          2602:                break;
        !          2603:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
        !          2604:                if (len != 4) {
        !          2605:                        err = USBD_IOERROR;
        !          2606:                        goto ret;
        !          2607:                }
        !          2608:                memset(buf, 0, len); /* ? XXX */
        !          2609:                totlen = len;
        !          2610:                break;
        !          2611:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
        !          2612:                DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n",
        !          2613:                            index));
        !          2614:                if (index < 1 || index > sc->sc_noport) {
        !          2615:                        err = USBD_IOERROR;
        !          2616:                        goto ret;
        !          2617:                }
        !          2618:                if (len != 4) {
        !          2619:                        err = USBD_IOERROR;
        !          2620:                        goto ret;
        !          2621:                }
        !          2622:                v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
        !          2623:                DPRINTFN(8,("ohci_root_ctrl_transfer: port status=0x%04x\n",
        !          2624:                            v));
        !          2625:                USETW(ps.wPortStatus, v);
        !          2626:                USETW(ps.wPortChange, v >> 16);
        !          2627:                l = min(len, sizeof ps);
        !          2628:                memcpy(buf, &ps, l);
        !          2629:                totlen = l;
        !          2630:                break;
        !          2631:        case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
        !          2632:                err = USBD_IOERROR;
        !          2633:                goto ret;
        !          2634:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
        !          2635:                break;
        !          2636:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
        !          2637:                if (index < 1 || index > sc->sc_noport) {
        !          2638:                        err = USBD_IOERROR;
        !          2639:                        goto ret;
        !          2640:                }
        !          2641:                port = OHCI_RH_PORT_STATUS(index);
        !          2642:                switch(value) {
        !          2643:                case UHF_PORT_ENABLE:
        !          2644:                        OWRITE4(sc, port, UPS_PORT_ENABLED);
        !          2645:                        break;
        !          2646:                case UHF_PORT_SUSPEND:
        !          2647:                        OWRITE4(sc, port, UPS_SUSPEND);
        !          2648:                        break;
        !          2649:                case UHF_PORT_RESET:
        !          2650:                        DPRINTFN(5,("ohci_root_ctrl_transfer: reset port %d\n",
        !          2651:                                    index));
        !          2652:                        OWRITE4(sc, port, UPS_RESET);
        !          2653:                        for (i = 0; i < 5; i++) {
        !          2654:                                usb_delay_ms(&sc->sc_bus,
        !          2655:                                             USB_PORT_ROOT_RESET_DELAY);
        !          2656:                                if (sc->sc_dying) {
        !          2657:                                        err = USBD_IOERROR;
        !          2658:                                        goto ret;
        !          2659:                                }
        !          2660:                                if ((OREAD4(sc, port) & UPS_RESET) == 0)
        !          2661:                                        break;
        !          2662:                        }
        !          2663:                        DPRINTFN(8,("ohci port %d reset, status = 0x%04x\n",
        !          2664:                                    index, OREAD4(sc, port)));
        !          2665:                        break;
        !          2666:                case UHF_PORT_POWER:
        !          2667:                        DPRINTFN(2,("ohci_root_ctrl_transfer: set port power "
        !          2668:                                    "%d\n", index));
        !          2669:                        OWRITE4(sc, port, UPS_PORT_POWER);
        !          2670:                        break;
        !          2671:                default:
        !          2672:                        err = USBD_IOERROR;
        !          2673:                        goto ret;
        !          2674:                }
        !          2675:                break;
        !          2676:        default:
        !          2677:                err = USBD_IOERROR;
        !          2678:                goto ret;
        !          2679:        }
        !          2680:        xfer->actlen = totlen;
        !          2681:        err = USBD_NORMAL_COMPLETION;
        !          2682:  ret:
        !          2683:        xfer->status = err;
        !          2684:        s = splusb();
        !          2685:        usb_transfer_complete(xfer);
        !          2686:        splx(s);
        !          2687:        return (USBD_IN_PROGRESS);
        !          2688: }
        !          2689:
        !          2690: /* Abort a root control request. */
        !          2691: void
        !          2692: ohci_root_ctrl_abort(usbd_xfer_handle xfer)
        !          2693: {
        !          2694:        /* Nothing to do, all transfers are synchronous. */
        !          2695: }
        !          2696:
        !          2697: /* Close the root pipe. */
        !          2698: void
        !          2699: ohci_root_ctrl_close(usbd_pipe_handle pipe)
        !          2700: {
        !          2701:        DPRINTF(("ohci_root_ctrl_close\n"));
        !          2702:        /* Nothing to do. */
        !          2703: }
        !          2704:
        !          2705: usbd_status
        !          2706: ohci_root_intr_transfer(usbd_xfer_handle xfer)
        !          2707: {
        !          2708:        usbd_status err;
        !          2709:
        !          2710:        /* Insert last in queue. */
        !          2711:        err = usb_insert_transfer(xfer);
        !          2712:        if (err)
        !          2713:                return (err);
        !          2714:
        !          2715:        /* Pipe isn't running, start first */
        !          2716:        return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
        !          2717: }
        !          2718:
        !          2719: usbd_status
        !          2720: ohci_root_intr_start(usbd_xfer_handle xfer)
        !          2721: {
        !          2722:        usbd_pipe_handle pipe = xfer->pipe;
        !          2723:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          2724:
        !          2725:        if (sc->sc_dying)
        !          2726:                return (USBD_IOERROR);
        !          2727:
        !          2728:        sc->sc_intrxfer = xfer;
        !          2729:
        !          2730:        return (USBD_IN_PROGRESS);
        !          2731: }
        !          2732:
        !          2733: /* Abort a root interrupt request. */
        !          2734: void
        !          2735: ohci_root_intr_abort(usbd_xfer_handle xfer)
        !          2736: {
        !          2737:        int s;
        !          2738:
        !          2739:        if (xfer->pipe->intrxfer == xfer) {
        !          2740:                DPRINTF(("ohci_root_intr_abort: remove\n"));
        !          2741:                xfer->pipe->intrxfer = NULL;
        !          2742:        }
        !          2743:        xfer->status = USBD_CANCELLED;
        !          2744:        s = splusb();
        !          2745:        usb_transfer_complete(xfer);
        !          2746:        splx(s);
        !          2747: }
        !          2748:
        !          2749: /* Close the root pipe. */
        !          2750: void
        !          2751: ohci_root_intr_close(usbd_pipe_handle pipe)
        !          2752: {
        !          2753:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          2754:
        !          2755:        DPRINTF(("ohci_root_intr_close\n"));
        !          2756:
        !          2757:        sc->sc_intrxfer = NULL;
        !          2758: }
        !          2759:
        !          2760: /************************/
        !          2761:
        !          2762: usbd_status
        !          2763: ohci_device_ctrl_transfer(usbd_xfer_handle xfer)
        !          2764: {
        !          2765:        usbd_status err;
        !          2766:
        !          2767:        /* Insert last in queue. */
        !          2768:        err = usb_insert_transfer(xfer);
        !          2769:        if (err)
        !          2770:                return (err);
        !          2771:
        !          2772:        /* Pipe isn't running, start first */
        !          2773:        return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
        !          2774: }
        !          2775:
        !          2776: usbd_status
        !          2777: ohci_device_ctrl_start(usbd_xfer_handle xfer)
        !          2778: {
        !          2779:        ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
        !          2780:        usbd_status err;
        !          2781:
        !          2782:        if (sc->sc_dying)
        !          2783:                return (USBD_IOERROR);
        !          2784:
        !          2785: #ifdef DIAGNOSTIC
        !          2786:        if (!(xfer->rqflags & URQ_REQUEST)) {
        !          2787:                /* XXX panic */
        !          2788:                printf("ohci_device_ctrl_transfer: not a request\n");
        !          2789:                return (USBD_INVAL);
        !          2790:        }
        !          2791: #endif
        !          2792:
        !          2793:        err = ohci_device_request(xfer);
        !          2794:        if (err)
        !          2795:                return (err);
        !          2796:
        !          2797:        if (sc->sc_bus.use_polling)
        !          2798:                ohci_waitintr(sc, xfer);
        !          2799:
        !          2800:        return (USBD_IN_PROGRESS);
        !          2801: }
        !          2802:
        !          2803: /* Abort a device control request. */
        !          2804: void
        !          2805: ohci_device_ctrl_abort(usbd_xfer_handle xfer)
        !          2806: {
        !          2807:        DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer));
        !          2808:        ohci_abort_xfer(xfer, USBD_CANCELLED);
        !          2809: }
        !          2810:
        !          2811: /* Close a device control pipe. */
        !          2812: void
        !          2813: ohci_device_ctrl_close(usbd_pipe_handle pipe)
        !          2814: {
        !          2815:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          2816:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          2817:
        !          2818:        DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe));
        !          2819:        ohci_close_pipe(pipe, sc->sc_ctrl_head);
        !          2820:        ohci_free_std(sc, opipe->tail.td);
        !          2821: }
        !          2822:
        !          2823: /************************/
        !          2824:
        !          2825: void
        !          2826: ohci_device_clear_toggle(usbd_pipe_handle pipe)
        !          2827: {
        !          2828:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          2829:
        !          2830:        opipe->sed->ed.ed_headp &= htole32(~OHCI_TOGGLECARRY);
        !          2831: }
        !          2832:
        !          2833: void
        !          2834: ohci_noop(usbd_pipe_handle pipe)
        !          2835: {
        !          2836: }
        !          2837:
        !          2838: usbd_status
        !          2839: ohci_device_bulk_transfer(usbd_xfer_handle xfer)
        !          2840: {
        !          2841:        usbd_status err;
        !          2842:
        !          2843:        /* Insert last in queue. */
        !          2844:        err = usb_insert_transfer(xfer);
        !          2845:        if (err)
        !          2846:                return (err);
        !          2847:
        !          2848:        /* Pipe isn't running, start first */
        !          2849:        return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
        !          2850: }
        !          2851:
        !          2852: usbd_status
        !          2853: ohci_device_bulk_start(usbd_xfer_handle xfer)
        !          2854: {
        !          2855:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          2856:        usbd_device_handle dev = opipe->pipe.device;
        !          2857:        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        !          2858:        int addr = dev->address;
        !          2859:        ohci_soft_td_t *data, *tail, *tdp;
        !          2860:        ohci_soft_ed_t *sed;
        !          2861:        int s, len, isread, endpt;
        !          2862:        usbd_status err;
        !          2863:
        !          2864:        if (sc->sc_dying)
        !          2865:                return (USBD_IOERROR);
        !          2866:
        !          2867: #ifdef DIAGNOSTIC
        !          2868:        if (xfer->rqflags & URQ_REQUEST) {
        !          2869:                /* XXX panic */
        !          2870:                printf("ohci_device_bulk_start: a request\n");
        !          2871:                return (USBD_INVAL);
        !          2872:        }
        !          2873: #endif
        !          2874:
        !          2875:        len = xfer->length;
        !          2876:        endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
        !          2877:        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
        !          2878:        sed = opipe->sed;
        !          2879:
        !          2880:        DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d "
        !          2881:                    "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags,
        !          2882:                    endpt));
        !          2883:
        !          2884:        opipe->u.bulk.isread = isread;
        !          2885:        opipe->u.bulk.length = len;
        !          2886:
        !          2887:        /* Update device address */
        !          2888:        sed->ed.ed_flags = htole32(
        !          2889:                (letoh32(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) |
        !          2890:                OHCI_ED_SET_FA(addr));
        !          2891:
        !          2892:        /* Allocate a chain of new TDs (including a new tail). */
        !          2893:        data = opipe->tail.td;
        !          2894:        err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
        !          2895:                  data, &tail);
        !          2896:        /* We want interrupt at the end of the transfer. */
        !          2897:        tail->td.td_flags &= htole32(~OHCI_TD_INTR_MASK);
        !          2898:        tail->td.td_flags |= htole32(OHCI_TD_SET_DI(1));
        !          2899:        tail->flags |= OHCI_CALL_DONE;
        !          2900:        tail = tail->nexttd;    /* point at sentinel */
        !          2901:        if (err)
        !          2902:                return (err);
        !          2903:
        !          2904:        tail->xfer = NULL;
        !          2905:        xfer->hcpriv = data;
        !          2906:
        !          2907:        DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x "
        !          2908:                    "td_cbp=0x%08x td_be=0x%08x\n",
        !          2909:                    (int)letoh32(sed->ed.ed_flags),
        !          2910:                    (int)letoh32(data->td.td_flags),
        !          2911:                    (int)letoh32(data->td.td_cbp),
        !          2912:                    (int)letoh32(data->td.td_be)));
        !          2913:
        !          2914: #ifdef OHCI_DEBUG
        !          2915:        if (ohcidebug > 5) {
        !          2916:                ohci_dump_ed(sed);
        !          2917:                ohci_dump_tds(data);
        !          2918:        }
        !          2919: #endif
        !          2920:
        !          2921:        /* Insert ED in schedule */
        !          2922:        s = splusb();
        !          2923:        for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
        !          2924:                tdp->xfer = xfer;
        !          2925:        }
        !          2926:        sed->ed.ed_tailp = htole32(tail->physaddr);
        !          2927:        opipe->tail.td = tail;
        !          2928:        sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
        !          2929:        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
        !          2930:        if (xfer->timeout && !sc->sc_bus.use_polling) {
        !          2931:                 timeout_del(&xfer->timeout_handle);
        !          2932:                 timeout_set(&xfer->timeout_handle, ohci_timeout, xfer);
        !          2933:                 timeout_add(&xfer->timeout_handle, mstohz(xfer->timeout));
        !          2934:        }
        !          2935:
        !          2936: #if 0
        !          2937: /* This goes wrong if we are too slow. */
        !          2938:        if (ohcidebug > 10) {
        !          2939:                delay(10000);
        !          2940:                DPRINTF(("ohci_device_intr_transfer: status=%x\n",
        !          2941:                         OREAD4(sc, OHCI_COMMAND_STATUS)));
        !          2942:                ohci_dump_ed(sed);
        !          2943:                ohci_dump_tds(data);
        !          2944:        }
        !          2945: #endif
        !          2946:
        !          2947:        splx(s);
        !          2948:
        !          2949:        if (sc->sc_bus.use_polling)
        !          2950:                ohci_waitintr(sc, xfer);
        !          2951:
        !          2952:        return (USBD_IN_PROGRESS);
        !          2953: }
        !          2954:
        !          2955: void
        !          2956: ohci_device_bulk_abort(usbd_xfer_handle xfer)
        !          2957: {
        !          2958:        DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer));
        !          2959:        ohci_abort_xfer(xfer, USBD_CANCELLED);
        !          2960: }
        !          2961:
        !          2962: /*
        !          2963:  * Close a device bulk pipe.
        !          2964:  */
        !          2965: void
        !          2966: ohci_device_bulk_close(usbd_pipe_handle pipe)
        !          2967: {
        !          2968:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          2969:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          2970:
        !          2971:        DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe));
        !          2972:        ohci_close_pipe(pipe, sc->sc_bulk_head);
        !          2973:        ohci_free_std(sc, opipe->tail.td);
        !          2974: }
        !          2975:
        !          2976: /************************/
        !          2977:
        !          2978: usbd_status
        !          2979: ohci_device_intr_transfer(usbd_xfer_handle xfer)
        !          2980: {
        !          2981:        usbd_status err;
        !          2982:
        !          2983:        /* Insert last in queue. */
        !          2984:        err = usb_insert_transfer(xfer);
        !          2985:        if (err)
        !          2986:                return (err);
        !          2987:
        !          2988:        /* Pipe isn't running, start first */
        !          2989:        return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
        !          2990: }
        !          2991:
        !          2992: usbd_status
        !          2993: ohci_device_intr_start(usbd_xfer_handle xfer)
        !          2994: {
        !          2995:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          2996:        usbd_device_handle dev = opipe->pipe.device;
        !          2997:        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        !          2998:        ohci_soft_ed_t *sed = opipe->sed;
        !          2999:        ohci_soft_td_t *data, *tail;
        !          3000:        int s, len, isread, endpt;
        !          3001:
        !          3002:        if (sc->sc_dying)
        !          3003:                return (USBD_IOERROR);
        !          3004:
        !          3005:        DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d "
        !          3006:                     "flags=%d priv=%p\n",
        !          3007:                     xfer, xfer->length, xfer->flags, xfer->priv));
        !          3008:
        !          3009: #ifdef DIAGNOSTIC
        !          3010:        if (xfer->rqflags & URQ_REQUEST)
        !          3011:                panic("ohci_device_intr_transfer: a request");
        !          3012: #endif
        !          3013:
        !          3014:        len = xfer->length;
        !          3015:        endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
        !          3016:        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
        !          3017:
        !          3018:        data = opipe->tail.td;
        !          3019:        tail = ohci_alloc_std(sc);
        !          3020:        if (tail == NULL)
        !          3021:                return (USBD_NOMEM);
        !          3022:        tail->xfer = NULL;
        !          3023:
        !          3024:        data->td.td_flags = htole32(
        !          3025:                isread ? OHCI_TD_IN : OHCI_TD_OUT |
        !          3026:                OHCI_TD_NOCC |
        !          3027:                OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
        !          3028:        if (xfer->flags & USBD_SHORT_XFER_OK)
        !          3029:                data->td.td_flags |= htole32(OHCI_TD_R);
        !          3030:        data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0));
        !          3031:        data->nexttd = tail;
        !          3032:        data->td.td_nexttd = htole32(tail->physaddr);
        !          3033:        data->td.td_be = htole32(letoh32(data->td.td_cbp) + len - 1);
        !          3034:        data->len = len;
        !          3035:        data->xfer = xfer;
        !          3036:        data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
        !          3037:        xfer->hcpriv = data;
        !          3038:
        !          3039: #ifdef OHCI_DEBUG
        !          3040:        if (ohcidebug > 5) {
        !          3041:                DPRINTF(("ohci_device_intr_transfer:\n"));
        !          3042:                ohci_dump_ed(sed);
        !          3043:                ohci_dump_tds(data);
        !          3044:        }
        !          3045: #endif
        !          3046:
        !          3047:        /* Insert ED in schedule */
        !          3048:        s = splusb();
        !          3049:        sed->ed.ed_tailp = htole32(tail->physaddr);
        !          3050:        opipe->tail.td = tail;
        !          3051:        sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
        !          3052:
        !          3053: #if 0
        !          3054: /*
        !          3055:  * This goes horribly wrong, printing thousands of descriptors,
        !          3056:  * because false references are followed due to the fact that the
        !          3057:  * TD is gone.
        !          3058:  */
        !          3059:        if (ohcidebug > 5) {
        !          3060:                usb_delay_ms(&sc->sc_bus, 5);
        !          3061:                DPRINTF(("ohci_device_intr_transfer: status=%x\n",
        !          3062:                         OREAD4(sc, OHCI_COMMAND_STATUS)));
        !          3063:                ohci_dump_ed(sed);
        !          3064:                ohci_dump_tds(data);
        !          3065:        }
        !          3066: #endif
        !          3067:        splx(s);
        !          3068:
        !          3069:        return (USBD_IN_PROGRESS);
        !          3070: }
        !          3071:
        !          3072: /* Abort a device control request. */
        !          3073: void
        !          3074: ohci_device_intr_abort(usbd_xfer_handle xfer)
        !          3075: {
        !          3076:        if (xfer->pipe->intrxfer == xfer) {
        !          3077:                DPRINTF(("ohci_device_intr_abort: remove\n"));
        !          3078:                xfer->pipe->intrxfer = NULL;
        !          3079:        }
        !          3080:        ohci_abort_xfer(xfer, USBD_CANCELLED);
        !          3081: }
        !          3082:
        !          3083: /* Close a device interrupt pipe. */
        !          3084: void
        !          3085: ohci_device_intr_close(usbd_pipe_handle pipe)
        !          3086: {
        !          3087:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          3088:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          3089:        int nslots = opipe->u.intr.nslots;
        !          3090:        int pos = opipe->u.intr.pos;
        !          3091:        int j;
        !          3092:        ohci_soft_ed_t *p, *sed = opipe->sed;
        !          3093:        int s;
        !          3094:
        !          3095:        DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n",
        !          3096:                    pipe, nslots, pos));
        !          3097:        s = splusb();
        !          3098:        sed->ed.ed_flags |= htole32(OHCI_ED_SKIP);
        !          3099:        if ((letoh32(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
        !          3100:            (letoh32(sed->ed.ed_headp) & OHCI_HEADMASK))
        !          3101:                usb_delay_ms(&sc->sc_bus, 2);
        !          3102:
        !          3103:        for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
        !          3104:                ;
        !          3105: #ifdef DIAGNOSTIC
        !          3106:        if (p == NULL)
        !          3107:                panic("ohci_device_intr_close: ED not found");
        !          3108: #endif
        !          3109:        p->next = sed->next;
        !          3110:        p->ed.ed_nexted = sed->ed.ed_nexted;
        !          3111:        splx(s);
        !          3112:
        !          3113:        for (j = 0; j < nslots; j++)
        !          3114:                --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS];
        !          3115:
        !          3116:        ohci_free_std(sc, opipe->tail.td);
        !          3117:        ohci_free_sed(sc, opipe->sed);
        !          3118: }
        !          3119:
        !          3120: usbd_status
        !          3121: ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival)
        !          3122: {
        !          3123:        int i, j, s, best;
        !          3124:        u_int npoll, slow, shigh, nslots;
        !          3125:        u_int bestbw, bw;
        !          3126:        ohci_soft_ed_t *hsed, *sed = opipe->sed;
        !          3127:
        !          3128:        DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe));
        !          3129:        if (ival == 0) {
        !          3130:                printf("ohci_setintr: 0 interval\n");
        !          3131:                return (USBD_INVAL);
        !          3132:        }
        !          3133:
        !          3134:        npoll = OHCI_NO_INTRS;
        !          3135:        while (npoll > ival)
        !          3136:                npoll /= 2;
        !          3137:        DPRINTFN(2, ("ohci_setintr: ival=%d npoll=%d\n", ival, npoll));
        !          3138:
        !          3139:        /*
        !          3140:         * We now know which level in the tree the ED must go into.
        !          3141:         * Figure out which slot has most bandwidth left over.
        !          3142:         * Slots to examine:
        !          3143:         * npoll
        !          3144:         * 1    0
        !          3145:         * 2    1 2
        !          3146:         * 4    3 4 5 6
        !          3147:         * 8    7 8 9 10 11 12 13 14
        !          3148:         * N    (N-1) .. (N-1+N-1)
        !          3149:         */
        !          3150:        slow = npoll-1;
        !          3151:        shigh = slow + npoll;
        !          3152:        nslots = OHCI_NO_INTRS / npoll;
        !          3153:        for (best = i = slow, bestbw = ~0; i < shigh; i++) {
        !          3154:                bw = 0;
        !          3155:                for (j = 0; j < nslots; j++)
        !          3156:                        bw += sc->sc_bws[(i * nslots + j) % OHCI_NO_INTRS];
        !          3157:                if (bw < bestbw) {
        !          3158:                        best = i;
        !          3159:                        bestbw = bw;
        !          3160:                }
        !          3161:        }
        !          3162:        DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n",
        !          3163:                     best, slow, shigh, bestbw));
        !          3164:
        !          3165:        s = splusb();
        !          3166:        hsed = sc->sc_eds[best];
        !          3167:        sed->next = hsed->next;
        !          3168:        sed->ed.ed_nexted = hsed->ed.ed_nexted;
        !          3169:        hsed->next = sed;
        !          3170:        hsed->ed.ed_nexted = htole32(sed->physaddr);
        !          3171:        splx(s);
        !          3172:
        !          3173:        for (j = 0; j < nslots; j++)
        !          3174:                ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS];
        !          3175:        opipe->u.intr.nslots = nslots;
        !          3176:        opipe->u.intr.pos = best;
        !          3177:
        !          3178:        DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe));
        !          3179:        return (USBD_NORMAL_COMPLETION);
        !          3180: }
        !          3181:
        !          3182: /***********************/
        !          3183:
        !          3184: usbd_status
        !          3185: ohci_device_isoc_transfer(usbd_xfer_handle xfer)
        !          3186: {
        !          3187:        usbd_status err;
        !          3188:
        !          3189:        DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer));
        !          3190:
        !          3191:        /* Put it on our queue, */
        !          3192:        err = usb_insert_transfer(xfer);
        !          3193:
        !          3194:        /* bail out on error, */
        !          3195:        if (err && err != USBD_IN_PROGRESS)
        !          3196:                return (err);
        !          3197:
        !          3198:        /* XXX should check inuse here */
        !          3199:
        !          3200:        /* insert into schedule, */
        !          3201:        ohci_device_isoc_enter(xfer);
        !          3202:
        !          3203:        /* and start if the pipe wasn't running */
        !          3204:        if (!err)
        !          3205:                ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
        !          3206:
        !          3207:        return (err);
        !          3208: }
        !          3209:
        !          3210: void
        !          3211: ohci_device_isoc_enter(usbd_xfer_handle xfer)
        !          3212: {
        !          3213:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          3214:        usbd_device_handle dev = opipe->pipe.device;
        !          3215:        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        !          3216:        ohci_soft_ed_t *sed = opipe->sed;
        !          3217:        struct iso *iso = &opipe->u.iso;
        !          3218:        ohci_soft_itd_t *sitd, *nsitd;
        !          3219:        ohci_physaddr_t buf, offs, noffs, bp0;
        !          3220:        int i, ncur, nframes;
        !          3221:        int s;
        !          3222:
        !          3223:        DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p "
        !          3224:                    "nframes=%d\n",
        !          3225:                    iso->inuse, iso->next, xfer, xfer->nframes));
        !          3226:
        !          3227:        if (sc->sc_dying)
        !          3228:                return;
        !          3229:
        !          3230:        if (iso->next == -1) {
        !          3231:                /* Not in use yet, schedule it a few frames ahead. */
        !          3232:                iso->next = letoh32(sc->sc_hcca->hcca_frame_number) + 5;
        !          3233:                DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n",
        !          3234:                            iso->next));
        !          3235:        }
        !          3236:
        !          3237:        sitd = opipe->tail.itd;
        !          3238:        buf = DMAADDR(&xfer->dmabuf, 0);
        !          3239:        bp0 = OHCI_PAGE(buf);
        !          3240:        offs = OHCI_PAGE_OFFSET(buf);
        !          3241:        nframes = xfer->nframes;
        !          3242:        xfer->hcpriv = sitd;
        !          3243:        for (i = ncur = 0; i < nframes; i++, ncur++) {
        !          3244:                noffs = offs + xfer->frlengths[i];
        !          3245:                if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */
        !          3246:                    OHCI_PAGE(buf + noffs) > bp0 + OHCI_PAGE_SIZE) { /* too many page crossings */
        !          3247:
        !          3248:                        /* Allocate next ITD */
        !          3249:                        nsitd = ohci_alloc_sitd(sc);
        !          3250:                        if (nsitd == NULL) {
        !          3251:                                /* XXX what now? */
        !          3252:                                printf("%s: isoc TD alloc failed\n",
        !          3253:                                       sc->sc_bus.bdev.dv_xname);
        !          3254:                                return;
        !          3255:                        }
        !          3256:
        !          3257:                        /* Fill current ITD */
        !          3258:                        sitd->itd.itd_flags = htole32(
        !          3259:                                OHCI_ITD_NOCC |
        !          3260:                                OHCI_ITD_SET_SF(iso->next) |
        !          3261:                                OHCI_ITD_SET_DI(6) | /* delay intr a little */
        !          3262:                                OHCI_ITD_SET_FC(ncur));
        !          3263:                        sitd->itd.itd_bp0 = htole32(bp0);
        !          3264:                        sitd->nextitd = nsitd;
        !          3265:                        sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
        !          3266:                        sitd->itd.itd_be = htole32(bp0 + offs - 1);
        !          3267:                        sitd->xfer = xfer;
        !          3268:                        sitd->flags = 0;
        !          3269:
        !          3270:                        sitd = nsitd;
        !          3271:                        iso->next = iso->next + ncur;
        !          3272:                        bp0 = OHCI_PAGE(buf + offs);
        !          3273:                        ncur = 0;
        !          3274:                }
        !          3275:                sitd->itd.itd_offset[ncur] = htole16(OHCI_ITD_MK_OFFS(offs));
        !          3276:                offs = noffs;
        !          3277:        }
        !          3278:        nsitd = ohci_alloc_sitd(sc);
        !          3279:        if (nsitd == NULL) {
        !          3280:                /* XXX what now? */
        !          3281:                printf("%s: isoc TD alloc failed\n",
        !          3282:                       sc->sc_bus.bdev.dv_xname);
        !          3283:                return;
        !          3284:        }
        !          3285:        /* Fixup last used ITD */
        !          3286:        sitd->itd.itd_flags = htole32(
        !          3287:                OHCI_ITD_NOCC |
        !          3288:                OHCI_ITD_SET_SF(iso->next) |
        !          3289:                OHCI_ITD_SET_DI(0) |
        !          3290:                OHCI_ITD_SET_FC(ncur));
        !          3291:        sitd->itd.itd_bp0 = htole32(bp0);
        !          3292:        sitd->nextitd = nsitd;
        !          3293:        sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
        !          3294:        sitd->itd.itd_be = htole32(bp0 + offs - 1);
        !          3295:        sitd->xfer = xfer;
        !          3296:        sitd->flags = OHCI_CALL_DONE;
        !          3297:
        !          3298:        iso->next = iso->next + ncur;
        !          3299:        iso->inuse += nframes;
        !          3300:
        !          3301:        xfer->actlen = offs;    /* XXX pretend we did it all */
        !          3302:
        !          3303:        xfer->status = USBD_IN_PROGRESS;
        !          3304:
        !          3305: #ifdef OHCI_DEBUG
        !          3306:        if (ohcidebug > 5) {
        !          3307:                DPRINTF(("ohci_device_isoc_enter: frame=%d\n",
        !          3308:                         letoh32(sc->sc_hcca->hcca_frame_number)));
        !          3309:                ohci_dump_itds(xfer->hcpriv);
        !          3310:                ohci_dump_ed(sed);
        !          3311:        }
        !          3312: #endif
        !          3313:
        !          3314:        s = splusb();
        !          3315:        sed->ed.ed_tailp = htole32(nsitd->physaddr);
        !          3316:        opipe->tail.itd = nsitd;
        !          3317:        sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
        !          3318:        splx(s);
        !          3319:
        !          3320: #ifdef OHCI_DEBUG
        !          3321:        if (ohcidebug > 5) {
        !          3322:                delay(150000);
        !          3323:                DPRINTF(("ohci_device_isoc_enter: after frame=%d\n",
        !          3324:                         letoh32(sc->sc_hcca->hcca_frame_number)));
        !          3325:                ohci_dump_itds(xfer->hcpriv);
        !          3326:                ohci_dump_ed(sed);
        !          3327:        }
        !          3328: #endif
        !          3329: }
        !          3330:
        !          3331: usbd_status
        !          3332: ohci_device_isoc_start(usbd_xfer_handle xfer)
        !          3333: {
        !          3334:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          3335:        ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
        !          3336:
        !          3337:        DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer));
        !          3338:
        !          3339:        if (sc->sc_dying)
        !          3340:                return (USBD_IOERROR);
        !          3341:
        !          3342: #ifdef DIAGNOSTIC
        !          3343:        if (xfer->status != USBD_IN_PROGRESS)
        !          3344:                printf("ohci_device_isoc_start: not in progress %p\n", xfer);
        !          3345: #endif
        !          3346:
        !          3347:        /* XXX anything to do? */
        !          3348:
        !          3349:        return (USBD_IN_PROGRESS);
        !          3350: }
        !          3351:
        !          3352: void
        !          3353: ohci_device_isoc_abort(usbd_xfer_handle xfer)
        !          3354: {
        !          3355:        struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        !          3356:        ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
        !          3357:        ohci_soft_ed_t *sed;
        !          3358:        ohci_soft_itd_t *sitd;
        !          3359:        int s;
        !          3360:
        !          3361:        s = splusb();
        !          3362:
        !          3363:        DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer));
        !          3364:
        !          3365:        /* Transfer is already done. */
        !          3366:        if (xfer->status != USBD_NOT_STARTED &&
        !          3367:            xfer->status != USBD_IN_PROGRESS) {
        !          3368:                splx(s);
        !          3369:                printf("ohci_device_isoc_abort: early return\n");
        !          3370:                return;
        !          3371:        }
        !          3372:
        !          3373:        /* Give xfer the requested abort code. */
        !          3374:        xfer->status = USBD_CANCELLED;
        !          3375:
        !          3376:        sed = opipe->sed;
        !          3377:        sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */
        !          3378:
        !          3379:        sitd = xfer->hcpriv;
        !          3380: #ifdef DIAGNOSTIC
        !          3381:        if (sitd == NULL) {
        !          3382:                splx(s);
        !          3383:                printf("ohci_device_isoc_abort: hcpriv==0\n");
        !          3384:                return;
        !          3385:        }
        !          3386: #endif
        !          3387:        for (; sitd->xfer == xfer; sitd = sitd->nextitd) {
        !          3388: #ifdef DIAGNOSTIC
        !          3389:                DPRINTFN(1,("abort sets done sitd=%p\n", sitd));
        !          3390:                sitd->isdone = 1;
        !          3391: #endif
        !          3392:        }
        !          3393:
        !          3394:        splx(s);
        !          3395:
        !          3396:        usb_delay_ms(&sc->sc_bus, OHCI_ITD_NOFFSET);
        !          3397:
        !          3398:        s = splusb();
        !          3399:
        !          3400:        /* Run callback. */
        !          3401:        usb_transfer_complete(xfer);
        !          3402:
        !          3403:        sed->ed.ed_headp = htole32(sitd->physaddr); /* unlink TDs */
        !          3404:        sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */
        !          3405:
        !          3406:        splx(s);
        !          3407: }
        !          3408:
        !          3409: void
        !          3410: ohci_device_isoc_done(usbd_xfer_handle xfer)
        !          3411: {
        !          3412:        DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer));
        !          3413: }
        !          3414:
        !          3415: usbd_status
        !          3416: ohci_setup_isoc(usbd_pipe_handle pipe)
        !          3417: {
        !          3418:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          3419:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          3420:        struct iso *iso = &opipe->u.iso;
        !          3421:        int s;
        !          3422:
        !          3423:        iso->next = -1;
        !          3424:        iso->inuse = 0;
        !          3425:
        !          3426:        s = splusb();
        !          3427:        ohci_add_ed(opipe->sed, sc->sc_isoc_head);
        !          3428:        splx(s);
        !          3429:
        !          3430:        return (USBD_NORMAL_COMPLETION);
        !          3431: }
        !          3432:
        !          3433: void
        !          3434: ohci_device_isoc_close(usbd_pipe_handle pipe)
        !          3435: {
        !          3436:        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        !          3437:        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
        !          3438:
        !          3439:        DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe));
        !          3440:        ohci_close_pipe(pipe, sc->sc_isoc_head);
        !          3441: #ifdef DIAGNOSTIC
        !          3442:        opipe->tail.itd->isdone = 1;
        !          3443: #endif
        !          3444:        ohci_free_sitd(sc, opipe->tail.itd);
        !          3445: }

CVSweb