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