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