[BACK]Return to pxa27x_udc.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / xscale

Annotation of sys/arch/arm/xscale/pxa27x_udc.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pxa27x_udc.c,v 1.22 2007/06/14 06:55:10 mbalmer Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2007 Dale Rahn <drahn@openbsd.org>
        !             5:  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
        !             6:  * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
        !             7:  *
        !             8:  * Permission to use, copy, modify, and distribute this software for any
        !             9:  * purpose with or without fee is hereby granted, provided that the above
        !            10:  * copyright notice and this permission notice appear in all copies.
        !            11:  *
        !            12:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            13:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            14:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            15:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            16:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            17:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            18:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            19:  */
        !            20:
        !            21: #include <sys/param.h>
        !            22: #include <sys/systm.h>
        !            23: #include <sys/device.h>
        !            24: #include <sys/kernel.h>
        !            25: #include <sys/malloc.h>
        !            26: #include <sys/timeout.h>
        !            27:
        !            28: #include <machine/intr.h>
        !            29: #include <machine/bus.h>
        !            30:
        !            31: #include <dev/usb/usb.h>
        !            32: #include <dev/usb/usbdi.h>
        !            33: #include <dev/usb/usbdivar.h>
        !            34: #include <dev/usb/usbf.h>
        !            35: #include <dev/usb/usbfvar.h>
        !            36:
        !            37: #include <arm/xscale/pxa2x0reg.h>
        !            38: #include <arm/xscale/pxa2x0var.h>
        !            39: #include <arm/xscale/pxa2x0_gpio.h>
        !            40:
        !            41: #include <arm/xscale/pxa27x_udcreg.h>
        !            42: #define PXAUDC_EP0MAXP 16      /* XXX */
        !            43: #define PXAUDC_NEP     24      /* total number of endpoints */
        !            44:
        !            45: #include <machine/zaurus_reg.h>        /* XXX */
        !            46:
        !            47: #include "usbf.h"
        !            48:
        !            49: struct pxaudc_xfer {
        !            50:        struct usbf_xfer         xfer;
        !            51:        u_int16_t                frmlen;
        !            52: };
        !            53:
        !            54: struct pxaudc_pipe {
        !            55:        struct usbf_pipe         pipe;
        !            56: //     LIST_ENTRY(pxaudc_pipe)  list;
        !            57: };
        !            58:
        !            59: struct pxaudc_softc {
        !            60:        struct usbf_bus          sc_bus;
        !            61:        bus_space_tag_t          sc_iot;
        !            62:        bus_space_handle_t       sc_ioh;
        !            63:        bus_size_t               sc_size;
        !            64:        void                    *sc_ih;
        !            65:        void                    *sc_conn_ih;
        !            66:        void                    *sc_powerhook;
        !            67:        SIMPLEQ_HEAD(,usbf_xfer) sc_free_xfers; /* recycled xfers */
        !            68:        u_int32_t                sc_icr0;       /* enabled EP interrupts */
        !            69:        u_int32_t                sc_icr1;       /* enabled EP interrupts */
        !            70:        enum {
        !            71:                EP0_SETUP,
        !            72:                EP0_IN
        !            73:        }                        sc_ep0state;
        !            74:        u_int32_t                sc_isr0;       /* XXX deferred interrupts */
        !            75:        u_int32_t                sc_isr1;       /* XXX deferred interrupts */
        !            76:        u_int32_t                sc_otgisr;     /* XXX deferred interrupts */
        !            77:        struct pxaudc_pipe      *sc_pipe[PXAUDC_NEP];
        !            78:        int                      sc_npipe;
        !            79:
        !            80:        int                      sc_cn;
        !            81:        int                      sc_in;
        !            82:        int                      sc_isn;
        !            83:        int8_t                   sc_ep_map[16];
        !            84: };
        !            85:
        !            86: int             pxaudc_match(struct device *, void *, void *);
        !            87: void            pxaudc_attach(struct device *, struct device *, void *);
        !            88: int             pxaudc_detach(struct device *, int);
        !            89: void            pxaudc_power(int, void *);
        !            90:
        !            91: int             pxaudc_is_host(void);
        !            92: int             pxaudc_is_device(void);
        !            93: void            pxaudc_setup(struct pxaudc_softc *);
        !            94: void            pxaudc_hide(struct pxaudc_softc *);
        !            95: void            pxaudc_show(struct pxaudc_softc *);
        !            96:
        !            97: void            pxaudc_enable(struct pxaudc_softc *);
        !            98: void            pxaudc_disable(struct pxaudc_softc *);
        !            99: void            pxaudc_read_ep0(struct pxaudc_softc *, usbf_xfer_handle);
        !           100: void            pxaudc_read_epN(struct pxaudc_softc *sc, int ep);
        !           101: void            pxaudc_write_ep0(struct pxaudc_softc *, usbf_xfer_handle);
        !           102: void            pxaudc_write(struct pxaudc_softc *, usbf_xfer_handle);
        !           103: void            pxaudc_write_epN(struct pxaudc_softc *sc, int ep);
        !           104:
        !           105: int             pxaudc_connect_intr(void *);
        !           106: int             pxaudc_intr(void *);
        !           107: void            pxaudc_intr1(struct pxaudc_softc *);
        !           108: void            pxaudc_ep0_intr(struct pxaudc_softc *);
        !           109: void            pxaudc_epN_intr(struct pxaudc_softc *sc, int ep, int isr);
        !           110:
        !           111: usbf_status     pxaudc_open(struct usbf_pipe *);
        !           112: void            pxaudc_softintr(void *);
        !           113: usbf_status     pxaudc_allocm(struct usbf_bus *, usb_dma_t *, u_int32_t);
        !           114: void            pxaudc_freem(struct usbf_bus *, usb_dma_t *);
        !           115: usbf_xfer_handle pxaudc_allocx(struct usbf_bus *);
        !           116: void            pxaudc_freex(struct usbf_bus *, usbf_xfer_handle);
        !           117:
        !           118: usbf_status     pxaudc_ctrl_transfer(usbf_xfer_handle);
        !           119: usbf_status     pxaudc_ctrl_start(usbf_xfer_handle);
        !           120: void            pxaudc_ctrl_abort(usbf_xfer_handle);
        !           121: void            pxaudc_ctrl_done(usbf_xfer_handle);
        !           122: void            pxaudc_ctrl_close(usbf_pipe_handle);
        !           123:
        !           124: usbf_status     pxaudc_bulk_transfer(usbf_xfer_handle);
        !           125: usbf_status     pxaudc_bulk_start(usbf_xfer_handle);
        !           126: void            pxaudc_bulk_abort(usbf_xfer_handle);
        !           127: void            pxaudc_bulk_done(usbf_xfer_handle);
        !           128: void            pxaudc_bulk_close(usbf_pipe_handle);
        !           129:
        !           130: struct cfattach pxaudc_ca = {
        !           131:        sizeof(struct pxaudc_softc), pxaudc_match, pxaudc_attach,
        !           132:        pxaudc_detach
        !           133: };
        !           134:
        !           135: struct cfdriver pxaudc_cd = {
        !           136:        NULL, "pxaudc", DV_DULL
        !           137: };
        !           138:
        !           139: #if NUSBF > 0
        !           140:
        !           141: struct usbf_bus_methods pxaudc_bus_methods = {
        !           142:        pxaudc_open,
        !           143:        pxaudc_softintr,
        !           144:        pxaudc_allocm,
        !           145:        pxaudc_freem,
        !           146:        pxaudc_allocx,
        !           147:        pxaudc_freex
        !           148: };
        !           149:
        !           150: struct usbf_pipe_methods pxaudc_ctrl_methods = {
        !           151:        pxaudc_ctrl_transfer,
        !           152:        pxaudc_ctrl_start,
        !           153:        pxaudc_ctrl_abort,
        !           154:        pxaudc_ctrl_done,
        !           155:        pxaudc_ctrl_close
        !           156: };
        !           157:
        !           158: struct usbf_pipe_methods pxaudc_bulk_methods = {
        !           159:        pxaudc_bulk_transfer,
        !           160:        pxaudc_bulk_start,
        !           161:        pxaudc_bulk_abort,
        !           162:        pxaudc_bulk_done,
        !           163:        pxaudc_bulk_close
        !           164: };
        !           165:
        !           166: #endif /* NUSBF > 0 */
        !           167:
        !           168: #define DEVNAME(sc)    ((sc)->sc_bus.bdev.dv_xname)
        !           169:
        !           170: #define CSR_READ_4(sc, reg) \
        !           171:        bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
        !           172: #define CSR_WRITE_4(sc, reg, val) \
        !           173:        bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
        !           174: #define CSR_WRITE_1(sc, reg, val) \
        !           175:        bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
        !           176: #define CSR_SET_4(sc, reg, val) \
        !           177:        CSR_WRITE_4((sc), (reg), CSR_READ_4((sc), (reg)) | (val))
        !           178: #define CSR_CLR_4(sc, reg, val) \
        !           179:        CSR_WRITE_4((sc), (reg), CSR_READ_4((sc), (reg)) & ~(val))
        !           180:
        !           181: #ifndef PXAUDC_DEBUG
        !           182: #define DPRINTF(l, x)  do {} while (0)
        !           183: #else
        !           184: int pxaudcdebug = 0;
        !           185: #define DPRINTF(l, x)  if ((l) <= pxaudcdebug) printf x; else {}
        !           186: #endif
        !           187:
        !           188: int
        !           189: pxaudc_match(struct device *parent, void *match, void *aux)
        !           190: {
        !           191:        if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) != CPU_ID_PXA27X)
        !           192:                return (0);
        !           193:
        !           194:        return (1);
        !           195: }
        !           196:
        !           197: void
        !           198: pxaudc_attach(struct device *parent, struct device *self, void *aux)
        !           199: {
        !           200:        struct pxaudc_softc             *sc = (struct pxaudc_softc *)self;
        !           201:        struct pxaip_attach_args        *pxa = aux;
        !           202:        int i;
        !           203:
        !           204:        sc->sc_iot = pxa->pxa_iot;
        !           205:        if (bus_space_map(sc->sc_iot, PXA2X0_USBDC_BASE, PXA2X0_USBDC_SIZE, 0,
        !           206:            &sc->sc_ioh)) {
        !           207:                printf(": cannot map mem space\n");
        !           208:                return;
        !           209:        }
        !           210:        sc->sc_size = PXA2X0_USBDC_SIZE;
        !           211:
        !           212:        printf(": USB Device Controller\n");
        !           213:
        !           214:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, sc->sc_size,
        !           215:            BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
        !           216:
        !           217:        /* Set up GPIO pins and disable the controller. */
        !           218:        pxaudc_setup(sc);
        !           219:        pxaudc_disable(sc);
        !           220:
        !           221: #if NUSBF > 0
        !           222:        /* Establish USB device interrupt. */
        !           223:        sc->sc_ih = pxa2x0_intr_establish(PXA2X0_INT_USB, IPL_USB,
        !           224:            pxaudc_intr, sc, DEVNAME(sc));
        !           225:        if (sc->sc_ih == NULL) {
        !           226:                printf(": unable to establish interrupt\n");
        !           227:                bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
        !           228:                sc->sc_size = 0;
        !           229:                return;
        !           230:        }
        !           231:
        !           232:        /* Establish device connect interrupt. */
        !           233: #if 0
        !           234:        sc->sc_conn_ih = pxa2x0_gpio_intr_establish(C3000_USB_DEVICE_PIN, /* XXX */
        !           235:            IST_EDGE_BOTH, IPL_USB, pxaudc_connect_intr, sc, "usbc");
        !           236: #endif
        !           237:        sc->sc_conn_ih = pxa2x0_gpio_intr_establish(C3000_USB_CONNECT_PIN,
        !           238:            IST_EDGE_BOTH, IPL_USB, pxaudc_connect_intr, sc, "usbc");
        !           239:        if (sc->sc_conn_ih == NULL) {
        !           240:                printf(": unable to establish connect interrupt\n");
        !           241:                pxa2x0_intr_disestablish(sc->sc_ih);
        !           242:                bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
        !           243:                sc->sc_ioh = NULL;
        !           244:                sc->sc_size = 0;
        !           245:                return;
        !           246:        }
        !           247:
        !           248:        sc->sc_powerhook = powerhook_establish(pxaudc_power, sc);
        !           249:
        !           250:        /* Set up the bus struct. */
        !           251:        sc->sc_bus.methods = &pxaudc_bus_methods;
        !           252:        sc->sc_bus.pipe_size = sizeof(struct pxaudc_pipe);
        !           253:        sc->sc_bus.ep0_maxp = PXAUDC_EP0MAXP;
        !           254:        sc->sc_bus.usbrev = USBREV_1_1;
        !           255:        sc->sc_bus.dmatag = pxa->pxa_dmat;
        !           256:        sc->sc_npipe = 0;       /* ep0 is always there. */
        !           257:
        !           258:        sc->sc_ep_map[0] = 0;
        !           259:        /* 16 == max logical endpoints */
        !           260:        for (i = 1; i < 16; i++) {
        !           261:                sc->sc_ep_map[i] = -1;
        !           262:        }
        !           263:
        !           264:        /* Attach logical device and function. */
        !           265:        (void)config_found(self, &sc->sc_bus, NULL);
        !           266:
        !           267:        /* Enable the controller unless we're now acting as a host. */
        !           268:        if (!pxaudc_is_host())
        !           269:                pxaudc_enable(sc);
        !           270: #endif
        !           271: }
        !           272:
        !           273: int
        !           274: pxaudc_detach(struct device *self, int flags)
        !           275: {
        !           276:        struct pxaudc_softc             *sc = (struct pxaudc_softc *)self;
        !           277:
        !           278:        if (sc->sc_powerhook != NULL)
        !           279:                powerhook_disestablish(sc->sc_powerhook);
        !           280:
        !           281:        if (sc->sc_conn_ih != NULL)
        !           282:                pxa2x0_gpio_intr_disestablish(sc->sc_conn_ih);
        !           283:
        !           284:        if (sc->sc_ih != NULL)
        !           285:                pxa2x0_intr_disestablish(sc->sc_ih);
        !           286:
        !           287:        if (sc->sc_size) {
        !           288:                bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
        !           289:                sc->sc_size = 0;
        !           290:        }
        !           291:
        !           292:        return (0);
        !           293: }
        !           294:
        !           295: void
        !           296: pxaudc_power(int why, void *arg)
        !           297: {
        !           298:        struct pxaudc_softc             *sc = (struct pxaudc_softc *)arg;
        !           299:
        !           300:        switch (why) {
        !           301:        case PWR_SUSPEND:
        !           302:        case PWR_STANDBY:
        !           303:                pxaudc_disable(sc);
        !           304:                break;
        !           305:
        !           306:        case PWR_RESUME:
        !           307:                pxaudc_enable(sc);
        !           308:                break;
        !           309:        }
        !           310: }
        !           311:
        !           312: /*
        !           313:  * Machine-specific functions
        !           314:  */
        !           315:
        !           316: /* XXX move to machine-specific file */
        !           317:
        !           318: int
        !           319: pxaudc_is_host(void)
        !           320: {
        !           321:        return (!pxa2x0_gpio_get_bit(C3000_USB_CONNECT_PIN) &&
        !           322:                !pxa2x0_gpio_get_bit(C3000_USB_DEVICE_PIN));
        !           323: }
        !           324:
        !           325: int
        !           326: pxaudc_is_device(void)
        !           327: {
        !           328:        return (pxa2x0_gpio_get_bit(C3000_USB_CONNECT_PIN) &&
        !           329:                pxa2x0_gpio_get_bit(C3000_USB_DEVICE_PIN));
        !           330: }
        !           331:
        !           332: void
        !           333: pxaudc_setup(struct pxaudc_softc *sc)
        !           334: {
        !           335:        pxa2x0_gpio_set_function(45, GPIO_OUT);
        !           336:        pxa2x0_gpio_set_function(C3000_USB_CONNECT_PIN, GPIO_IN); /* 41 */
        !           337:        pxa2x0_gpio_set_function(40, GPIO_OUT);
        !           338:        pxa2x0_gpio_set_function(39, GPIO_IN);
        !           339:        pxa2x0_gpio_set_function(38, GPIO_IN);
        !           340:        pxa2x0_gpio_set_function(37, GPIO_OUT);
        !           341:        pxa2x0_gpio_set_function(36, GPIO_IN);
        !           342:        pxa2x0_gpio_set_function(C3000_USB_DEVICE_PIN, GPIO_IN); /* 35 */
        !           343:        pxa2x0_gpio_set_function(34, GPIO_IN);
        !           344:        pxa2x0_gpio_set_function(89, GPIO_OUT);
        !           345:        pxa2x0_gpio_set_function(120, GPIO_OUT);
        !           346: }
        !           347:
        !           348: /* Hide us from the host. */
        !           349: void
        !           350: pxaudc_hide(struct pxaudc_softc *sc)
        !           351: {
        !           352:        pxa2x0_gpio_clear_bit(C3000_USB_PULLUP_PIN);
        !           353: }
        !           354:
        !           355: /* Show us to the host. */
        !           356: void
        !           357: pxaudc_show(struct pxaudc_softc *sc)
        !           358: {
        !           359:        pxa2x0_gpio_set_bit(C3000_USB_PULLUP_PIN);
        !           360: }
        !           361:
        !           362: /*
        !           363:  * Register manipulation
        !           364:  */
        !           365:
        !           366: #if 0
        !           367: static void
        !           368: pxaudc_dump_regs(struct pxaudc_softc *sc)
        !           369: {
        !           370:        printf("UDCCR\t%b\n", CSR_READ_4(sc, USBDC_UDCCR),
        !           371:            USBDC_UDCCR_BITS);
        !           372:        printf("UDCICR0\t%b\n", CSR_READ_4(sc, USBDC_UDCICR0),
        !           373:            USBDC_UDCISR0_BITS);
        !           374:        printf("UDCICR1\t%b\n", CSR_READ_4(sc, USBDC_UDCICR1),
        !           375:            USBDC_UDCISR1_BITS);
        !           376:        printf("OTGICR\t%b\n", CSR_READ_4(sc, USBDC_UDCOTGICR),
        !           377:            USBDC_UDCOTGISR_BITS);
        !           378: }
        !           379: #endif
        !           380:
        !           381: void
        !           382: pxaudc_enable(struct pxaudc_softc *sc)
        !           383: {
        !           384:        int i;
        !           385:
        !           386:        DPRINTF(10,("pxaudc_enable\n"));
        !           387:
        !           388:        /* Start the clocks. */
        !           389:        pxa2x0_clkman_config(CKEN_USBDC, 1);
        !           390:
        !           391: #if 0
        !           392:        /* Configure Port 2 for USB device. */
        !           393:        CSR_WRITE_4(sc, USBDC_UP2OCR, USBDC_UP2OCR_DMPUE |
        !           394:            USBDC_UP2OCR_DPPUE | USBDC_UP2OCR_HXOE);
        !           395: #else
        !           396:        /* Configure Port 2 for USB device. */
        !           397:        CSR_WRITE_4(sc, USBDC_UP2OCR, USBDC_UP2OCR_DPPUE | USBDC_UP2OCR_HXOE);
        !           398: #endif
        !           399:
        !           400:        CSR_SET_4(sc, USBDC_UDCCR, 0);
        !           401:        sc->sc_icr0 = 0;
        !           402:        sc->sc_icr1 = 0;
        !           403:
        !           404:        for (i = 1; i < PXAUDC_NEP; i++)
        !           405:                CSR_WRITE_4(sc, USBDC_UDCECR(i), 0); /* disable endpoints */
        !           406:
        !           407:        for (i = 1; i < sc->sc_npipe; i++) {
        !           408:                if (sc->sc_pipe[i] != NULL)  {
        !           409:                        struct usbf_endpoint *ep =
        !           410:                            sc->sc_pipe[i]->pipe.endpoint;
        !           411:                        u_int32_t cr;
        !           412:                        int dir = usbf_endpoint_dir(ep);
        !           413:                        usb_endpoint_descriptor_t *ed = ep->edesc;
        !           414:
        !           415:                        if (i < 16)
        !           416:                                sc->sc_icr0 |= USBDC_UDCICR0_IE(i);
        !           417:                        else
        !           418:                                sc->sc_icr1 |= USBDC_UDCICR1_IE(i-16);
        !           419:
        !           420:                        cr = USBDC_UDCECR_EE | USBDC_UDCECR_DE;
        !           421:                        cr |= USBDC_UDCECR_ENs(
        !           422:                            UE_GET_ADDR(ed->bEndpointAddress));
        !           423:                        cr |= USBDC_UDCECR_MPSs(UGETW(ed->wMaxPacketSize));
        !           424:                        cr |= USBDC_UDCECR_ETs(ed->bmAttributes & UE_XFERTYPE);
        !           425:                        if (dir == UE_DIR_IN)
        !           426:                                cr |= USBDC_UDCECR_ED;
        !           427:
        !           428:                        /* XXX - until pipe has cn/in/ain */
        !           429:                        cr |=   USBDC_UDCECR_AISNs(0) | USBDC_UDCECR_INs(0) |
        !           430:                            USBDC_UDCECR_CNs(1);
        !           431:
        !           432:                        CSR_WRITE_4(sc, USBDC_UDCECR(i), cr);
        !           433:
        !           434:                        /* clear old status */
        !           435:                        CSR_WRITE_4(sc, USBDC_UDCCSR(1),
        !           436:                            USBDC_UDCCSR_PC | USBDC_UDCCSR_TRN |
        !           437:                            USBDC_UDCCSR_SST | USBDC_UDCCSR_FEF);
        !           438:                }
        !           439:        }
        !           440:
        !           441:        CSR_WRITE_4(sc, USBDC_UDCISR0, 0xffffffff); /* clear all */
        !           442:        CSR_WRITE_4(sc, USBDC_UDCISR1, 0xffffffff); /* clear all */
        !           443:        CSR_SET_4(sc, USBDC_UDCCSR0, USBDC_UDCCSR0_ACM);
        !           444:
        !           445:
        !           446:        /* Enable interrupts for configured endpoints. */
        !           447:        CSR_WRITE_4(sc, USBDC_UDCICR0, USBDC_UDCICR0_IE(0) |
        !           448:            sc->sc_icr0);
        !           449:
        !           450:        CSR_WRITE_4(sc, USBDC_UDCICR1, USBDC_UDCICR1_IERS |
        !           451:            USBDC_UDCICR1_IESU | USBDC_UDCICR1_IERU |
        !           452:            USBDC_UDCICR1_IECC | sc->sc_icr1);
        !           453:
        !           454:        /* Enable the controller. */
        !           455:        CSR_CLR_4(sc, USBDC_UDCCR, USBDC_UDCCR_EMCE);
        !           456:        CSR_SET_4(sc, USBDC_UDCCR, USBDC_UDCCR_UDE);
        !           457:
        !           458:        /* Enable USB client on port 2. */
        !           459:        pxa2x0_gpio_clear_bit(37); /* USB_P2_8 */
        !           460: }
        !           461:
        !           462: void
        !           463: pxaudc_disable(struct pxaudc_softc *sc)
        !           464: {
        !           465:        DPRINTF(10,("pxaudc_disable\n"));
        !           466:
        !           467:        /* Disable the controller. */
        !           468:        CSR_CLR_4(sc, USBDC_UDCCR, USBDC_UDCCR_UDE);
        !           469:
        !           470:        /* Disable all interrupts. */
        !           471:        CSR_WRITE_4(sc, USBDC_UDCICR0, 0);
        !           472:        CSR_WRITE_4(sc, USBDC_UDCICR1, 0);
        !           473:        CSR_WRITE_4(sc, USBDC_UDCOTGICR, 0);
        !           474:
        !           475:        /* Set Port 2 output to "Non-OTG Host with Differential Port". */
        !           476:        CSR_WRITE_4(sc, USBDC_UP2OCR, USBDC_UP2OCR_HXS | USBDC_UP2OCR_HXOE);
        !           477:
        !           478:        /* Set "Host Port 2 Transceiver D­ Pull Down Enable". */
        !           479:        CSR_SET_4(sc, USBDC_UP2OCR, USBDC_UP2OCR_DMPDE);
        !           480:
        !           481:        /* Stop the clocks. */
        !           482:        pxa2x0_clkman_config(CKEN_USBDC, 0);
        !           483:
        !           484:        /* Enable USB host on port 2. */
        !           485:        pxa2x0_gpio_set_bit(37); /* USB_P2_8 */
        !           486: }
        !           487:
        !           488: #if NUSBF > 0
        !           489:
        !           490: /*
        !           491:  * Endpoint FIFO handling
        !           492:  */
        !           493:
        !           494: void
        !           495: pxaudc_read_ep0(struct pxaudc_softc *sc, usbf_xfer_handle xfer)
        !           496: {
        !           497:        size_t len;
        !           498:        u_int8_t *p;
        !           499:
        !           500:        xfer->actlen = CSR_READ_4(sc, USBDC_UDCBCR(0));
        !           501:        len = MIN(xfer->actlen, xfer->length);
        !           502:        p = xfer->buffer;
        !           503:
        !           504:        while (CSR_READ_4(sc, USBDC_UDCCSR0) & USBDC_UDCCSR0_RNE) {
        !           505:                u_int32_t v = CSR_READ_4(sc, USBDC_UDCDR(0));
        !           506:
        !           507:                if (len > 0) {
        !           508:                        if (((unsigned)p & 0x3) == 0)
        !           509:                                *(u_int32_t *)p = v;
        !           510:                        else {
        !           511:                                *(p+0) = v & 0xff;
        !           512:                                *(p+1) = (v >> 8) & 0xff;
        !           513:                                *(p+2) = (v >> 16) & 0xff;
        !           514:                                *(p+3) = (v >> 24) & 0xff;
        !           515:                        }
        !           516:                        p += 4;
        !           517:                        len -= 4;
        !           518:                }
        !           519:        }
        !           520:
        !           521:        CSR_WRITE_4(sc, USBDC_UDCCSR0, USBDC_UDCCSR0_SA | USBDC_UDCCSR0_OPC);
        !           522:
        !           523:        xfer->status = USBF_NORMAL_COMPLETION;
        !           524:        usbf_transfer_complete(xfer);
        !           525: }
        !           526:
        !           527: void
        !           528: pxaudc_read_epN(struct pxaudc_softc *sc, int ep)
        !           529: {
        !           530:        size_t len, tlen;
        !           531:        u_int8_t *p;
        !           532:        struct pxaudc_pipe *ppipe;
        !           533:        usbf_pipe_handle pipe = NULL;
        !           534:        usbf_xfer_handle xfer = NULL;
        !           535:        int count;
        !           536:        u_int32_t csr;
        !           537:
        !           538:        ppipe = sc->sc_pipe[ep];
        !           539:
        !           540:        if (ppipe == NULL) {
        !           541:                return;
        !           542:        }
        !           543:        pipe = &ppipe->pipe;
        !           544: again:
        !           545:        xfer = SIMPLEQ_FIRST(&pipe->queue);
        !           546:
        !           547:        if (xfer == NULL) {
        !           548:                printf("pxaudc_read_epN: ep %d, no xfer\n", ep);
        !           549:                return;
        !           550:        }
        !           551:
        !           552:        count = CSR_READ_4(sc, USBDC_UDCBCR(ep));
        !           553:        tlen = len = MIN(count, xfer->length - xfer->actlen);
        !           554:        p = xfer->buffer + xfer->actlen;
        !           555:        csr = CSR_READ_4(sc, USBDC_UDCCSR(ep));
        !           556:
        !           557:        if ((csr & USBDC_UDCCSR_PC) && count == 0)
        !           558:        {
        !           559: #ifdef DEBUG_RX
        !           560:                printf("trans1 complete\n");
        !           561: #endif
        !           562:                xfer->status = USBF_NORMAL_COMPLETION;
        !           563:                usbf_transfer_complete(xfer);
        !           564:                CSR_SET_4(sc, USBDC_UDCCSR(ep), USBDC_UDCCSR_PC);
        !           565:                return;
        !           566:        }
        !           567:
        !           568: #ifdef DEBUG_RX
        !           569:        printf("reading data from endpoint %x, len %x csr %x",
        !           570:                ep, count, csr);
        !           571: #endif
        !           572:
        !           573:        while (CSR_READ_4(sc, USBDC_UDCCSR(ep)) & USBDC_UDCCSR_BNE) {
        !           574:                u_int32_t v = CSR_READ_4(sc, USBDC_UDCDR(ep));
        !           575:
        !           576:                /* double buffering? */
        !           577:                if (len > 0) {
        !           578:                        if (((unsigned)p & 0x3) == 0)
        !           579:                                *(u_int32_t *)p = v;
        !           580:                        else {
        !           581:                                *(p+0) = v & 0xff;
        !           582:                                *(p+1) = (v >> 8) & 0xff;
        !           583:                                *(p+2) = (v >> 16) & 0xff;
        !           584:                                *(p+3) = (v >> 24) & 0xff;
        !           585:                        }
        !           586:                        p += 4;
        !           587:                        len -= 4;
        !           588:                        xfer->actlen += 4;
        !           589:                }
        !           590:                count -= 4;
        !           591:        }
        !           592:        CSR_SET_4(sc, USBDC_UDCCSR(ep), USBDC_UDCCSR_PC);
        !           593:
        !           594:
        !           595:        if (xfer->length == xfer->actlen || (tlen == 0 && xfer->actlen != 0) ||
        !           596:            csr & USBDC_UDCCSR_SP) {
        !           597: #ifdef DEBUG_RX
        !           598:                printf("trans2 complete\n");
        !           599: #endif
        !           600:                xfer->status = USBF_NORMAL_COMPLETION;
        !           601:                usbf_transfer_complete(xfer);
        !           602:        }
        !           603:        csr = CSR_READ_4(sc, USBDC_UDCCSR(ep));
        !           604: #ifdef DEBUG_RX
        !           605:        printf("csr now %x len %x\n",
        !           606:            csr, CSR_READ_4(sc, USBDC_UDCBCR(ep)));
        !           607: #endif
        !           608:        if (csr & USBDC_UDCCSR_PC)
        !           609:                goto again;
        !           610: }
        !           611:
        !           612: void
        !           613: pxaudc_write_ep0(struct pxaudc_softc *sc, usbf_xfer_handle xfer)
        !           614: {
        !           615:        struct pxaudc_xfer *lxfer = (struct pxaudc_xfer *)xfer;
        !           616:        u_int32_t len;
        !           617:        u_int8_t *p;
        !           618:
        !           619:        if (lxfer->frmlen > 0) {
        !           620:                xfer->actlen += lxfer->frmlen;
        !           621:                lxfer->frmlen = 0;
        !           622:        }
        !           623:
        !           624:        DPRINTF(11,("%s: ep0 ctrl-in, xfer=%p, len=%u, actlen=%u\n",
        !           625:            DEVNAME(sc), xfer, xfer->length, xfer->actlen));
        !           626:
        !           627:        if (xfer->actlen >= xfer->length) {
        !           628:                sc->sc_ep0state = EP0_SETUP;
        !           629:                usbf_transfer_complete(xfer);
        !           630:                return;
        !           631:        }
        !           632:
        !           633:        sc->sc_ep0state = EP0_IN;
        !           634:
        !           635:        p = (u_char *)xfer->buffer + xfer->actlen;
        !           636:        len = xfer->length - xfer->actlen;
        !           637:        len = MIN(len, PXAUDC_EP0MAXP);
        !           638:        lxfer->frmlen = len;
        !           639:
        !           640:        while (len >= 4) {
        !           641:                u_int32_t v;
        !           642:
        !           643:                if (((unsigned)p & 0x3) == 0)
        !           644:                        v = *(u_int32_t *)p;
        !           645:                else {
        !           646:                        v = *(p+0);
        !           647:                        v |= *(p+1) << 8;
        !           648:                        v |= *(p+2) << 16;
        !           649:                        v |= *(p+3) << 24;
        !           650:                }
        !           651:
        !           652:                CSR_WRITE_4(sc, USBDC_UDCDR(0), v);
        !           653:                len -= 4;
        !           654:                p += 4;
        !           655:        }
        !           656:
        !           657:        while (len > 0) {
        !           658:                CSR_WRITE_1(sc, USBDC_UDCDR(0), *p);
        !           659:                len--;
        !           660:                p++;
        !           661:        }
        !           662:
        !           663:        /* (12.6.7) Set IPR only for short packets. */
        !           664:        if (lxfer->frmlen < PXAUDC_EP0MAXP)
        !           665:                CSR_SET_4(sc, USBDC_UDCCSR0, USBDC_UDCCSR0_IPR);
        !           666: }
        !           667:
        !           668: void
        !           669: pxaudc_write(struct pxaudc_softc *sc, usbf_xfer_handle xfer)
        !           670: {
        !           671:        u_int8_t *p;
        !           672:        int ep = sc->sc_ep_map[usbf_endpoint_index(xfer->pipe->endpoint)];
        !           673:        int tlen = 0;
        !           674:        int maxp = UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize);
        !           675:        u_int32_t csr, csr_o;
        !           676:
        !           677: #ifdef DEBUG_TX_PKT
        !           678:        if (xfer->actlen == 0)
        !           679:                printf("new packet len %x\n", xfer->length);
        !           680: #endif
        !           681:
        !           682: #ifdef DEBUG_TX
        !           683:        printf("writing data to endpoint %x, xlen %x xact %x\n",
        !           684:                ep, xfer->length, xfer->actlen);
        !           685: #endif
        !           686:
        !           687:
        !           688:        if (xfer->actlen == xfer->length) {
        !           689:                /*
        !           690:                 * If the packet size is wMaxPacketSize byte multiple
        !           691:                 * send a zero packet to indicate termiation.
        !           692:                 */
        !           693:                if ((xfer->actlen % maxp) == 0 &&
        !           694:                    xfer->status != USBF_NORMAL_COMPLETION &&
        !           695:                    xfer->flags & USBD_FORCE_SHORT_XFER) {
        !           696:                        if (CSR_READ_4(sc, USBDC_UDCCSR(ep))
        !           697:                            & USBDC_UDCCSR_BNF) {
        !           698:                                CSR_SET_4(sc, USBDC_UDCCSR(ep),
        !           699:                                    USBDC_UDCCSR_SP);
        !           700:                                /*
        !           701:                                 * if we send a zero packet, we are 'done', but
        !           702:                                 * dont to usbf_transfer_complete() just yet
        !           703:                                 * because the short packet will cause another
        !           704:                                 * interrupt.
        !           705:                                 */
        !           706:                                xfer->status = USBF_NORMAL_COMPLETION;
        !           707:                                return;
        !           708:                        } else  {
        !           709:                                printf("fifo full when trying to set short packet\n");
        !           710:                        }
        !           711:                }
        !           712:                xfer->status = USBF_NORMAL_COMPLETION;
        !           713: #ifdef DEBUG_TX_PKT
        !           714:                printf("packet complete %x\n", xfer->actlen);
        !           715: #endif
        !           716:                usbf_transfer_complete(xfer);
        !           717:                return;
        !           718:        }
        !           719:
        !           720:        p = xfer->buffer + xfer->actlen;
        !           721:
        !           722:
        !           723:
        !           724:        csr_o = 0;
        !           725:        csr = CSR_READ_4(sc, USBDC_UDCCSR(ep));
        !           726:        if (csr & USBDC_UDCCSR_PC)
        !           727:                csr_o |= USBDC_UDCCSR_PC;
        !           728:        if (csr & USBDC_UDCCSR_TRN)
        !           729:                csr_o |= USBDC_UDCCSR_TRN;
        !           730:        if (csr & USBDC_UDCCSR_SST)
        !           731:                csr_o |= USBDC_UDCCSR_SST;
        !           732:        if (csr_o != 0)
        !           733:        CSR_WRITE_4(sc, USBDC_UDCCSR(ep), csr_o);
        !           734:
        !           735:
        !           736:        while (CSR_READ_4(sc, USBDC_UDCCSR(ep)) & USBDC_UDCCSR_BNF) {
        !           737:                u_int32_t v;
        !           738:
        !           739:                if (xfer->length - xfer->actlen < 4) {
        !           740:                        while (xfer->actlen < xfer->length) {
        !           741:                                CSR_WRITE_1(sc, USBDC_UDCDR(ep), *p);
        !           742:                                p++;
        !           743:                                xfer->actlen++;
        !           744:                                tlen++;
        !           745:                        }
        !           746:                        break;
        !           747:                }
        !           748:                if (((unsigned)p & 0x3) == 0)
        !           749:                        v = *(u_int32_t *)p;
        !           750:                else {
        !           751:                        v = *(p+0);
        !           752:                        v |= *(p+1) << 8;
        !           753:                        v |= *(p+2) << 16;
        !           754:                        v |= *(p+3) << 24;
        !           755:                }
        !           756:                CSR_WRITE_4(sc, USBDC_UDCDR(ep), v);
        !           757:
        !           758:                p += 4;
        !           759:                xfer->actlen += 4;
        !           760:
        !           761:                tlen += 4;
        !           762:        }
        !           763: #ifdef DEBUG_TX
        !           764:        printf(" wrote tlen %x %x\n", tlen, xfer->actlen);
        !           765:        if (xfer->actlen == 0) {
        !           766:                printf("whoa, write_ep called, but no free space\n");
        !           767:        }
        !           768: #endif
        !           769:        if (xfer->actlen == xfer->length) {
        !           770:                if ((xfer->actlen % maxp) != 0) {
        !           771:                        if (xfer->flags & USBD_FORCE_SHORT_XFER) {
        !           772:                                CSR_SET_4(sc, USBDC_UDCCSR(ep), USBDC_UDCCSR_SP);
        !           773: #ifdef DEBUG_TX
        !           774:                                printf("setting short packet on %x csr\n", ep,
        !           775:                                    CSR_READ_4(sc, USBDC_UDCCSR(ep)));
        !           776: #endif
        !           777:                        } else {
        !           778:                                /* fill buffer to maxpacket size??? */
        !           779:                        }
        !           780:                }
        !           781:        }
        !           782: }
        !           783:
        !           784: /*
        !           785:  * Interrupt handling
        !           786:  */
        !           787:
        !           788: int
        !           789: pxaudc_connect_intr(void *v)
        !           790: {
        !           791:        struct pxaudc_softc *sc = v;
        !           792:
        !           793:        DPRINTF(10,("pxaudc_connect_intr: connect=%d device=%d\n",
        !           794:            pxa2x0_gpio_get_bit(C3000_USB_CONNECT_PIN),
        !           795:            pxa2x0_gpio_get_bit(C3000_USB_DEVICE_PIN)));
        !           796:
        !           797:        /* XXX only set a flag here */
        !           798:        if (pxaudc_is_host()) {
        !           799: #if 0
        !           800:                printf("%s:switching to host\n", sc->sc_bus.bdev.dv_xname);
        !           801: #endif
        !           802:                pxaudc_disable(sc);
        !           803:        } else {
        !           804: #if 0
        !           805:                printf("%s:switching to client\n", sc->sc_bus.bdev.dv_xname);
        !           806: #endif
        !           807:                pxaudc_enable(sc);
        !           808:        }
        !           809:
        !           810:        /* Claim this interrupt. */
        !           811:        return 1;
        !           812: }
        !           813:
        !           814: int
        !           815: pxaudc_intr(void *v)
        !           816: {
        !           817:        struct pxaudc_softc *sc = v;
        !           818:        u_int32_t isr0, isr1, otgisr;
        !           819:
        !           820:        isr0 = CSR_READ_4(sc, USBDC_UDCISR0);
        !           821:        isr1 = CSR_READ_4(sc, USBDC_UDCISR1);
        !           822:        otgisr = CSR_READ_4(sc, USBDC_UDCOTGISR);
        !           823:
        !           824:        DPRINTF(10,("pxaudc_intr: isr0=%b, isr1=%b, otgisr=%b\n",
        !           825:            isr0, USBDC_UDCISR0_BITS, isr1, USBDC_UDCISR1_BITS,
        !           826:            otgisr, USBDC_UDCOTGISR_BITS));
        !           827:
        !           828:        if (isr0 || isr1 || otgisr) {
        !           829:                sc->sc_isr0 |= isr0;
        !           830:                sc->sc_isr1 |= isr1;
        !           831:                sc->sc_otgisr |= otgisr;
        !           832:
        !           833:                //usbf_schedsoftintr(&sc->sc_bus);
        !           834:                pxaudc_intr1(sc); /* XXX */
        !           835:        }
        !           836:
        !           837:        CSR_WRITE_4(sc, USBDC_UDCISR0, isr0);
        !           838:        CSR_WRITE_4(sc, USBDC_UDCISR1, isr1);
        !           839:        CSR_WRITE_4(sc, USBDC_UDCOTGISR, otgisr);
        !           840:
        !           841:        /* Claim this interrupt. */
        !           842:        return 1;
        !           843: }
        !           844: u_int32_t csr1, csr2;
        !           845:
        !           846: void
        !           847: pxaudc_intr1(struct pxaudc_softc *sc)
        !           848: {
        !           849:        u_int32_t isr0, isr1, otgisr;
        !           850:        int i;
        !           851:        //int s;
        !           852:
        !           853:        //s = splhardusb();
        !           854:        isr0 = sc->sc_isr0;
        !           855:        isr1 = sc->sc_isr1;
        !           856:        otgisr = sc->sc_otgisr;
        !           857:        sc->sc_isr0 = 0;
        !           858:        sc->sc_isr1 = 0;
        !           859:        sc->sc_otgisr = 0;
        !           860:        //splx(s);
        !           861:
        !           862:        sc->sc_bus.intr_context++;
        !           863:
        !           864:        if (isr1 & USBDC_UDCISR1_IRCC) {
        !           865:                u_int32_t ccr;
        !           866:                 CSR_SET_4(sc, USBDC_UDCCR, USBDC_UDCCR_SMAC);
        !           867:
        !           868:                /* wait for reconfig to finish (SMAC auto clears) */
        !           869:                while (CSR_READ_4(sc, USBDC_UDCCR)  & USBDC_UDCCR_SMAC)
        !           870:                        delay(10);
        !           871:
        !           872:                ccr = CSR_READ_4(sc, USBDC_UDCCR);
        !           873:                sc->sc_cn = USBDC_UDCCR_ACNr(ccr);
        !           874:                sc->sc_in = USBDC_UDCCR_AINr(ccr);
        !           875:                sc->sc_isn = USBDC_UDCCR_AAISNr(ccr);
        !           876:                goto ret;
        !           877:        }
        !           878: #if 0
        !           879:        printf("pxaudc_intr: isr0=%b, isr1=%b, otgisr=%b\n",
        !           880:            isr0, USBDC_UDCISR0_BITS, isr1, USBDC_UDCISR1_BITS,
        !           881:            otgisr, USBDC_UDCOTGISR_BITS);
        !           882: #endif
        !           883:
        !           884:        /* Handle USB RESET condition. */
        !           885:        if (isr1 & USBDC_UDCISR1_IRRS) {
        !           886:                sc->sc_ep0state = EP0_SETUP;
        !           887:                usbf_host_reset(&sc->sc_bus);
        !           888:                /* Discard all other interrupts. */
        !           889:                goto ret;
        !           890:        }
        !           891:
        !           892:        /* Service control pipe interrupts. */
        !           893:        if (isr0 & USBDC_UDCISR0_IR(0))
        !           894:                pxaudc_ep0_intr(sc);
        !           895:
        !           896:        for (i = 1; i < 24; i++) {
        !           897:                if (i < 16) {
        !           898:                        if (USBDC_UDCISR0_IRs(isr0,i))
        !           899:                                pxaudc_epN_intr(sc, i,
        !           900:                                    USBDC_UDCISR0_IRs(isr0,i));
        !           901:                } else {
        !           902:                        if (USBDC_UDCISR1_IRs(isr1,i))
        !           903:                                pxaudc_epN_intr(sc, i,
        !           904:                                    USBDC_UDCISR1_IRs(isr1,i));
        !           905:                }
        !           906:        }
        !           907:
        !           908:        if (isr1 & USBDC_UDCISR1_IRSU) {
        !           909:                /* suspend ?? */
        !           910:        }
        !           911:        if (isr1 & USBDC_UDCISR1_IRRU) {
        !           912:                /* resume ?? */
        !           913:        }
        !           914:
        !           915: ret:
        !           916:        sc->sc_bus.intr_context--;
        !           917: }
        !           918:
        !           919: void
        !           920: pxaudc_epN_intr(struct pxaudc_softc *sc, int ep, int isr)
        !           921: {
        !           922:        struct pxaudc_pipe *ppipe;
        !           923:        usbf_pipe_handle pipe;
        !           924:        int dir;
        !           925:
        !           926:        /* should not occur before device is configured */
        !           927:        if (sc->sc_cn == 0)
        !           928:                return;
        !           929:        if (isr &  2)
        !           930:                printf("ep%d: fifo error\n", ep); /* XXX */
        !           931:
        !           932:        /* faster method of determining direction? */
        !           933:        ppipe = sc->sc_pipe[ep];
        !           934:
        !           935:        if (ppipe == NULL)
        !           936:                return;
        !           937:        pipe = &ppipe->pipe;
        !           938:        dir = usbf_endpoint_dir(pipe->endpoint);
        !           939:
        !           940:        if (dir == UE_DIR_IN) {
        !           941:                pxaudc_write_epN(sc, ep);
        !           942:        } else {
        !           943:                pxaudc_read_epN(sc, ep);
        !           944:        }
        !           945:
        !           946: }
        !           947:
        !           948: void
        !           949: pxaudc_write_epN(struct pxaudc_softc *sc, int ep)
        !           950: {
        !           951:        struct pxaudc_pipe *ppipe;
        !           952:        usbf_pipe_handle pipe = NULL;
        !           953:        usbf_xfer_handle xfer = NULL;
        !           954:
        !           955:        ppipe = sc->sc_pipe[ep];
        !           956:
        !           957:        if (ppipe == NULL) {
        !           958:                return;
        !           959:        }
        !           960:        pipe = &ppipe->pipe;
        !           961:        xfer = SIMPLEQ_FIRST(&pipe->queue);
        !           962:        if (xfer != NULL)
        !           963:                pxaudc_write(sc, xfer);
        !           964: }
        !           965: void
        !           966: pxaudc_ep0_intr(struct pxaudc_softc *sc)
        !           967: {
        !           968:        struct pxaudc_pipe *ppipe;
        !           969:        usbf_pipe_handle pipe = NULL;
        !           970:        usbf_xfer_handle xfer = NULL;
        !           971:        u_int32_t csr0;
        !           972:
        !           973:        csr0 = CSR_READ_4(sc, USBDC_UDCCSR0);
        !           974:        DPRINTF(10,("pxaudc_ep0_intr: csr0=%b\n", csr0, USBDC_UDCCSR0_BITS));
        !           975:        delay (25);
        !           976:
        !           977:        ppipe = sc->sc_pipe[0];
        !           978:        if (ppipe != NULL) {
        !           979:                pipe = &ppipe->pipe;
        !           980:                xfer = SIMPLEQ_FIRST(&pipe->queue);
        !           981:        }
        !           982:
        !           983:        if (sc->sc_ep0state == EP0_SETUP && (csr0 & USBDC_UDCCSR0_OPC)) {
        !           984:                if (pipe == NULL) {
        !           985:                        DPRINTF(10,("pxaudc_ep0_intr: no control pipe\n"));
        !           986:                        return;
        !           987:                }
        !           988:
        !           989:                if (xfer == NULL) {
        !           990:                        DPRINTF(10,("pxaudc_ep0_intr: no xfer\n"));
        !           991:                        return;
        !           992:                }
        !           993:
        !           994:                pxaudc_read_ep0(sc, xfer);
        !           995:        } else if (sc->sc_ep0state == EP0_IN &&
        !           996:            (csr0 & USBDC_UDCCSR0_IPR) == 0 && xfer) {
        !           997:                pxaudc_write_ep0(sc, xfer);
        !           998:        }
        !           999: }
        !          1000:
        !          1001: /*
        !          1002:  * Bus methods
        !          1003:  */
        !          1004:
        !          1005: usbf_status
        !          1006: pxaudc_open(struct usbf_pipe *pipe)
        !          1007: {
        !          1008:        struct pxaudc_softc *sc = (struct pxaudc_softc *)pipe->device->bus;
        !          1009:        struct pxaudc_pipe *ppipe = (struct pxaudc_pipe *)pipe;
        !          1010:        int ep_idx;
        !          1011:        int s;
        !          1012:
        !          1013:        ep_idx = usbf_endpoint_index(pipe->endpoint);
        !          1014:        if (ep_idx >= PXAUDC_NEP)
        !          1015:                return USBF_BAD_ADDRESS;
        !          1016:
        !          1017:        DPRINTF(10,("pxaudc_open\n"));
        !          1018:        s = splhardusb();
        !          1019:
        !          1020:        switch (usbf_endpoint_type(pipe->endpoint)) {
        !          1021:        case UE_CONTROL:
        !          1022:                pipe->methods = &pxaudc_ctrl_methods;
        !          1023:                break;
        !          1024:
        !          1025:        case UE_BULK:
        !          1026:                pipe->methods = &pxaudc_bulk_methods;
        !          1027:                break;
        !          1028:
        !          1029:        case UE_ISOCHRONOUS:
        !          1030:        case UE_INTERRUPT:
        !          1031:        default:
        !          1032:                /* XXX */
        !          1033:                splx(s);
        !          1034:                return USBF_BAD_ADDRESS;
        !          1035:        }
        !          1036:
        !          1037:        if (ep_idx != 0 && sc->sc_ep_map[ep_idx] != -1) {
        !          1038:                printf("endpoint %d already used by %c",
        !          1039:                    ep_idx, '@'+ sc->sc_ep_map[0]);
        !          1040:                return USBF_BAD_ADDRESS;
        !          1041:        }
        !          1042:        sc->sc_ep_map[ep_idx] = sc->sc_npipe;
        !          1043:
        !          1044:        sc->sc_pipe[sc->sc_npipe] = ppipe;
        !          1045:        sc->sc_npipe++;
        !          1046:
        !          1047:        splx(s);
        !          1048:        return USBF_NORMAL_COMPLETION;
        !          1049: }
        !          1050:
        !          1051: void
        !          1052: pxaudc_softintr(void *v)
        !          1053: {
        !          1054:        struct pxaudc_softc *sc = v;
        !          1055:
        !          1056:        pxaudc_intr1(sc);
        !          1057: }
        !          1058:
        !          1059: usbf_status
        !          1060: pxaudc_allocm(struct usbf_bus *bus, usb_dma_t *dmap, u_int32_t size)
        !          1061: {
        !          1062:        return usbf_allocmem(bus, size, 0, dmap);
        !          1063: }
        !          1064:
        !          1065: void
        !          1066: pxaudc_freem(struct usbf_bus *bus, usb_dma_t *dmap)
        !          1067: {
        !          1068:        usbf_freemem(bus, dmap);
        !          1069: }
        !          1070:
        !          1071: usbf_xfer_handle
        !          1072: pxaudc_allocx(struct usbf_bus *bus)
        !          1073: {
        !          1074:        struct pxaudc_softc *sc = (struct pxaudc_softc *)bus;
        !          1075:        usbf_xfer_handle xfer;
        !          1076:
        !          1077:        xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
        !          1078:        if (xfer != NULL)
        !          1079:                SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
        !          1080:        else
        !          1081:                xfer = malloc(sizeof(struct pxaudc_xfer), M_USB, M_NOWAIT);
        !          1082:        if (xfer != NULL)
        !          1083:                bzero(xfer, sizeof(struct pxaudc_xfer));
        !          1084:        return xfer;
        !          1085: }
        !          1086:
        !          1087: void
        !          1088: pxaudc_freex(struct usbf_bus *bus, usbf_xfer_handle xfer)
        !          1089: {
        !          1090:        struct pxaudc_softc *sc = (struct pxaudc_softc *)bus;
        !          1091:
        !          1092:        SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
        !          1093: }
        !          1094:
        !          1095: /*
        !          1096:  * Control pipe methods
        !          1097:  */
        !          1098:
        !          1099: usbf_status
        !          1100: pxaudc_ctrl_transfer(usbf_xfer_handle xfer)
        !          1101: {
        !          1102:        usbf_status err;
        !          1103:
        !          1104:        /* Insert last in queue. */
        !          1105:        err = usbf_insert_transfer(xfer);
        !          1106:        if (err)
        !          1107:                return err;
        !          1108:
        !          1109:        /*
        !          1110:         * Pipe isn't running (otherwise err would be USBF_IN_PROGRESS),
        !          1111:         * so start first.
        !          1112:         */
        !          1113:        return pxaudc_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
        !          1114: }
        !          1115:
        !          1116: usbf_status
        !          1117: pxaudc_ctrl_start(usbf_xfer_handle xfer)
        !          1118: {
        !          1119:        struct usbf_pipe *pipe = xfer->pipe;
        !          1120:        struct pxaudc_softc *sc = (struct pxaudc_softc *)pipe->device->bus;
        !          1121:        int iswrite = !(xfer->rqflags & URQ_REQUEST);
        !          1122:        int s;
        !          1123:
        !          1124:        s = splusb();
        !          1125:        xfer->status = USBF_IN_PROGRESS;
        !          1126:        if (iswrite)
        !          1127:                pxaudc_write_ep0(sc, xfer);
        !          1128:        else {
        !          1129:                /* XXX boring message, this case is normally reached if
        !          1130:                 * XXX the xfer for a device request is being queued. */
        !          1131:                DPRINTF(10,("%s: ep[%x] ctrl-out, xfer=%p, len=%u, "
        !          1132:                    "actlen=%u\n", DEVNAME(sc),
        !          1133:                    usbf_endpoint_address(xfer->pipe->endpoint),
        !          1134:                    xfer, xfer->length,
        !          1135:                    xfer->actlen));
        !          1136:        }
        !          1137:        splx(s);
        !          1138:        return USBF_IN_PROGRESS;
        !          1139: }
        !          1140:
        !          1141: /* (also used by bulk pipes) */
        !          1142: void
        !          1143: pxaudc_ctrl_abort(usbf_xfer_handle xfer)
        !          1144: {
        !          1145:        int s;
        !          1146: #ifdef PXAUDC_DEBUG
        !          1147:        struct usbf_pipe *pipe = xfer->pipe;
        !          1148:        struct pxaudc_softc *sc = (struct pxaudc_softc *)pipe->device->bus;
        !          1149:        int index = usbf_endpoint_index(pipe->endpoint);
        !          1150:        int dir = usbf_endpoint_dir(pipe->endpoint);
        !          1151:        int type = usbf_endpoint_type(pipe->endpoint);
        !          1152: #endif
        !          1153:
        !          1154:        DPRINTF(10,("%s: ep%d %s-%s abort, xfer=%p\n", DEVNAME(sc), index,
        !          1155:            type == UE_CONTROL ? "ctrl" : "bulk", dir == UE_DIR_IN ?
        !          1156:            "in" : "out", xfer));
        !          1157:
        !          1158:        /*
        !          1159:         * Step 1: Make soft interrupt routine and hardware ignore the xfer.
        !          1160:         */
        !          1161:        s = splusb();
        !          1162:        xfer->status = USBF_CANCELLED;
        !          1163:        timeout_del(&xfer->timeout_handle);
        !          1164:        splx(s);
        !          1165:
        !          1166:        /*
        !          1167:         * Step 2: Make sure hardware has finished any possible use of the
        !          1168:         * xfer and the soft interrupt routine has run.
        !          1169:         */
        !          1170:        s = splusb();
        !          1171:        /* XXX this does not seem right, what if there
        !          1172:         * XXX are two xfers in the FIFO and we only want to
        !          1173:         * XXX ignore one? */
        !          1174: #ifdef notyet
        !          1175:        pxaudc_flush(sc, usbf_endpoint_address(pipe->endpoint));
        !          1176: #endif
        !          1177:        /* XXX we're not doing DMA and the soft interrupt routine does not
        !          1178:           XXX need to clean up anything. */
        !          1179:        splx(s);
        !          1180:
        !          1181:        /*
        !          1182:         * Step 3: Execute callback.
        !          1183:         */
        !          1184:        s = splusb();
        !          1185:        usbf_transfer_complete(xfer);
        !          1186:        splx(s);
        !          1187: }
        !          1188:
        !          1189: void
        !          1190: pxaudc_ctrl_done(usbf_xfer_handle xfer)
        !          1191: {
        !          1192: }
        !          1193:
        !          1194: void
        !          1195: pxaudc_ctrl_close(usbf_pipe_handle pipe)
        !          1196: {
        !          1197:        /* XXX */
        !          1198: }
        !          1199:
        !          1200: /*
        !          1201:  * Bulk pipe methods
        !          1202:  */
        !          1203:
        !          1204: usbf_status
        !          1205: pxaudc_bulk_transfer(usbf_xfer_handle xfer)
        !          1206: {
        !          1207:        usbf_status err;
        !          1208:
        !          1209:        /* Insert last in queue. */
        !          1210:        err = usbf_insert_transfer(xfer);
        !          1211:        if (err)
        !          1212:                return err;
        !          1213:
        !          1214:        /*
        !          1215:         * Pipe isn't running (otherwise err would be USBF_IN_PROGRESS),
        !          1216:         * so start first.
        !          1217:         */
        !          1218:        return pxaudc_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
        !          1219: }
        !          1220:
        !          1221: usbf_status
        !          1222: pxaudc_bulk_start(usbf_xfer_handle xfer)
        !          1223: {
        !          1224:        struct usbf_pipe *pipe = xfer->pipe;
        !          1225:        struct pxaudc_softc *sc = (struct pxaudc_softc *)pipe->device->bus;
        !          1226:        int iswrite = (usbf_endpoint_dir(pipe->endpoint) == UE_DIR_IN);
        !          1227:        int s;
        !          1228:
        !          1229:        DPRINTF(0,("%s: ep%d bulk-%s start, xfer=%p, len=%u\n", DEVNAME(sc),
        !          1230:            usbf_endpoint_index(pipe->endpoint), iswrite ? "in" : "out",
        !          1231:            xfer, xfer->length));
        !          1232:
        !          1233:        s = splusb();
        !          1234:        xfer->status = USBF_IN_PROGRESS;
        !          1235:        if (iswrite)
        !          1236:                pxaudc_write(sc, xfer);
        !          1237:        else {
        !          1238:                /* enable interrupt */
        !          1239:        }
        !          1240:        splx(s);
        !          1241:        return USBF_IN_PROGRESS;
        !          1242: }
        !          1243:
        !          1244: void
        !          1245: pxaudc_bulk_abort(usbf_xfer_handle xfer)
        !          1246: {
        !          1247:        pxaudc_ctrl_abort(xfer);
        !          1248: }
        !          1249:
        !          1250: void
        !          1251: pxaudc_bulk_done(usbf_xfer_handle xfer)
        !          1252: {
        !          1253: #if 0
        !          1254:        int ep = usbf_endpoint_address(xfer->pipe->endpoint);
        !          1255:        struct usbf_pipe *pipe = xfer->pipe;
        !          1256:        struct pxaudc_softc *sc = (struct pxaudc_softc *)pipe->device->bus;
        !          1257:
        !          1258: #endif
        !          1259: }
        !          1260:
        !          1261: void
        !          1262: pxaudc_bulk_close(usbf_pipe_handle pipe)
        !          1263: {
        !          1264:        /* XXX */
        !          1265: }
        !          1266:
        !          1267: #endif /* NUSBF > 0 */

CVSweb