Annotation of sys/arch/arm/xscale/pxa27x_udc.c, Revision 1.1.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