Annotation of src/sys/dev/usb/ehci.c, Revision 1.2.4.7
1.2.4.6 nathanw 1: /* $NetBSD$ */
1.1 augustss 2:
3: /*
1.2.4.2 nathanw 4: * TODO
5: * hold off explorations by companion controllers until ehci has started.
6: */
7:
8: /*
9: * Copyright (c) 2001 The NetBSD Foundation, Inc.
1.1 augustss 10: * All rights reserved.
11: *
12: * This code is derived from software contributed to The NetBSD Foundation
13: * by Lennart Augustsson (lennart@augustsson.net).
14: *
15: * Redistribution and use in source and binary forms, with or without
16: * modification, are permitted provided that the following conditions
17: * are met:
18: * 1. Redistributions of source code must retain the above copyright
19: * notice, this list of conditions and the following disclaimer.
20: * 2. Redistributions in binary form must reproduce the above copyright
21: * notice, this list of conditions and the following disclaimer in the
22: * documentation and/or other materials provided with the distribution.
23: * 3. All advertising materials mentioning features or use of this software
24: * must display the following acknowledgement:
25: * This product includes software developed by the NetBSD
26: * Foundation, Inc. and its contributors.
27: * 4. Neither the name of The NetBSD Foundation nor the names of its
28: * contributors may be used to endorse or promote products derived
29: * from this software without specific prior written permission.
30: *
31: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
32: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
33: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
35: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41: * POSSIBILITY OF SUCH DAMAGE.
42: */
43:
44: /*
1.2.4.1 nathanw 45: * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
1.1 augustss 46: *
1.2.4.7 ! nathanw 47: * The EHCI 1.0 spec can be found at
! 48: * http://developer.intel.com/technology/usb/download/ehci-r10.pdf
1.2.4.2 nathanw 49: * and the USB 2.0 spec at
50: * http://www.usb.org/developers/data/usb_20.zip
1.1 augustss 51: *
52: */
53:
1.2.4.1 nathanw 54: #include <sys/cdefs.h>
1.2.4.6 nathanw 55: __KERNEL_RCSID(0, "$NetBSD$");
1.2.4.1 nathanw 56:
1.1 augustss 57: #include <sys/param.h>
58: #include <sys/systm.h>
59: #include <sys/kernel.h>
60: #include <sys/malloc.h>
61: #include <sys/device.h>
62: #include <sys/select.h>
63: #include <sys/proc.h>
64: #include <sys/queue.h>
65:
66: #include <machine/bus.h>
67: #include <machine/endian.h>
68:
69: #include <dev/usb/usb.h>
70: #include <dev/usb/usbdi.h>
71: #include <dev/usb/usbdivar.h>
72: #include <dev/usb/usb_mem.h>
73: #include <dev/usb/usb_quirks.h>
74:
75: #include <dev/usb/ehcireg.h>
76: #include <dev/usb/ehcivar.h>
77:
78: #ifdef EHCI_DEBUG
79: #define DPRINTF(x) if (ehcidebug) printf x
80: #define DPRINTFN(n,x) if (ehcidebug>(n)) printf x
1.2.4.2 nathanw 81: int ehcidebug = 0;
82: #ifndef __NetBSD__
1.1 augustss 83: #define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
1.2.4.2 nathanw 84: #endif
1.1 augustss 85: #else
86: #define DPRINTF(x)
87: #define DPRINTFN(n,x)
88: #endif
89:
1.2.4.2 nathanw 90: struct ehci_pipe {
91: struct usbd_pipe pipe;
92: ehci_soft_qh_t *sqh;
93: union {
94: ehci_soft_qtd_t *qtd;
95: /* ehci_soft_itd_t *itd; */
96: } tail;
97: union {
98: /* Control pipe */
99: struct {
100: usb_dma_t reqdma;
101: u_int length;
102: /*ehci_soft_qtd_t *setup, *data, *stat;*/
103: } ctl;
104: /* Interrupt pipe */
105: /* XXX */
106: /* Bulk pipe */
107: struct {
108: u_int length;
109: } bulk;
110: /* Iso pipe */
111: /* XXX */
112: } u;
113: };
114:
115: Static void ehci_shutdown(void *);
116: Static void ehci_power(int, void *);
117:
118: Static usbd_status ehci_open(usbd_pipe_handle);
119: Static void ehci_poll(struct usbd_bus *);
120: Static void ehci_softintr(void *);
121: Static int ehci_intr1(ehci_softc_t *);
122: Static void ehci_waitintr(ehci_softc_t *, usbd_xfer_handle);
123: Static void ehci_check_intr(ehci_softc_t *, struct ehci_xfer *);
124: Static void ehci_idone(struct ehci_xfer *);
125: Static void ehci_timeout(void *);
126: Static void ehci_timeout_task(void *);
127:
128: Static usbd_status ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
129: Static void ehci_freem(struct usbd_bus *, usb_dma_t *);
130:
131: Static usbd_xfer_handle ehci_allocx(struct usbd_bus *);
132: Static void ehci_freex(struct usbd_bus *, usbd_xfer_handle);
133:
134: Static usbd_status ehci_root_ctrl_transfer(usbd_xfer_handle);
135: Static usbd_status ehci_root_ctrl_start(usbd_xfer_handle);
136: Static void ehci_root_ctrl_abort(usbd_xfer_handle);
137: Static void ehci_root_ctrl_close(usbd_pipe_handle);
138: Static void ehci_root_ctrl_done(usbd_xfer_handle);
139:
140: Static usbd_status ehci_root_intr_transfer(usbd_xfer_handle);
141: Static usbd_status ehci_root_intr_start(usbd_xfer_handle);
142: Static void ehci_root_intr_abort(usbd_xfer_handle);
143: Static void ehci_root_intr_close(usbd_pipe_handle);
144: Static void ehci_root_intr_done(usbd_xfer_handle);
145:
146: Static usbd_status ehci_device_ctrl_transfer(usbd_xfer_handle);
147: Static usbd_status ehci_device_ctrl_start(usbd_xfer_handle);
148: Static void ehci_device_ctrl_abort(usbd_xfer_handle);
149: Static void ehci_device_ctrl_close(usbd_pipe_handle);
150: Static void ehci_device_ctrl_done(usbd_xfer_handle);
151:
152: Static usbd_status ehci_device_bulk_transfer(usbd_xfer_handle);
153: Static usbd_status ehci_device_bulk_start(usbd_xfer_handle);
154: Static void ehci_device_bulk_abort(usbd_xfer_handle);
155: Static void ehci_device_bulk_close(usbd_pipe_handle);
156: Static void ehci_device_bulk_done(usbd_xfer_handle);
157:
158: Static usbd_status ehci_device_intr_transfer(usbd_xfer_handle);
159: Static usbd_status ehci_device_intr_start(usbd_xfer_handle);
160: Static void ehci_device_intr_abort(usbd_xfer_handle);
161: Static void ehci_device_intr_close(usbd_pipe_handle);
162: Static void ehci_device_intr_done(usbd_xfer_handle);
163:
164: Static usbd_status ehci_device_isoc_transfer(usbd_xfer_handle);
165: Static usbd_status ehci_device_isoc_start(usbd_xfer_handle);
166: Static void ehci_device_isoc_abort(usbd_xfer_handle);
167: Static void ehci_device_isoc_close(usbd_pipe_handle);
168: Static void ehci_device_isoc_done(usbd_xfer_handle);
169:
170: Static void ehci_device_clear_toggle(usbd_pipe_handle pipe);
171: Static void ehci_noop(usbd_pipe_handle pipe);
172:
173: Static int ehci_str(usb_string_descriptor_t *, int, char *);
174: Static void ehci_pcd(ehci_softc_t *, usbd_xfer_handle);
175: Static void ehci_pcd_able(ehci_softc_t *, int);
176: Static void ehci_pcd_enable(void *);
177: Static void ehci_disown(ehci_softc_t *, int, int);
178:
179: Static ehci_soft_qh_t *ehci_alloc_sqh(ehci_softc_t *);
180: Static void ehci_free_sqh(ehci_softc_t *, ehci_soft_qh_t *);
181:
182: Static ehci_soft_qtd_t *ehci_alloc_sqtd(ehci_softc_t *);
183: Static void ehci_free_sqtd(ehci_softc_t *, ehci_soft_qtd_t *);
184: Static usbd_status ehci_alloc_sqtd_chain(struct ehci_pipe *,
185: ehci_softc_t *, int, int, usbd_xfer_handle,
186: ehci_soft_qtd_t **, ehci_soft_qtd_t **);
187: Static void ehci_free_sqtd_chain(ehci_softc_t *, ehci_soft_qtd_t *,
188: ehci_soft_qtd_t *);
189:
190: Static usbd_status ehci_device_request(usbd_xfer_handle xfer);
191:
192: Static void ehci_add_qh(ehci_soft_qh_t *, ehci_soft_qh_t *);
193: Static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *,
194: ehci_soft_qh_t *);
195: Static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *);
196: Static void ehci_sync_hc(ehci_softc_t *);
197:
198: Static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *);
199: Static void ehci_abort_xfer(usbd_xfer_handle, usbd_status);
200:
201: #ifdef EHCI_DEBUG
202: Static void ehci_dump_regs(ehci_softc_t *);
203: Static void ehci_dump(void);
204: Static ehci_softc_t *theehci;
205: Static void ehci_dump_link(ehci_link_t, int);
206: Static void ehci_dump_sqtds(ehci_soft_qtd_t *);
207: Static void ehci_dump_sqtd(ehci_soft_qtd_t *);
208: Static void ehci_dump_qtd(ehci_qtd_t *);
209: Static void ehci_dump_sqh(ehci_soft_qh_t *);
210: Static void ehci_dump_exfer(struct ehci_xfer *);
211: #endif
212:
213: #define MS_TO_TICKS(ms) ((ms) * hz / 1000)
214:
215: #define EHCI_NULL htole32(EHCI_LINK_TERMINATE)
216:
217: #define EHCI_INTR_ENDPT 1
218:
219: #define ehci_add_intr_list(sc, ex) \
220: LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ex), inext);
221: #define ehci_del_intr_list(ex) \
222: LIST_REMOVE((ex), inext)
223:
224: Static struct usbd_bus_methods ehci_bus_methods = {
225: ehci_open,
226: ehci_softintr,
227: ehci_poll,
228: ehci_allocm,
229: ehci_freem,
230: ehci_allocx,
231: ehci_freex,
232: };
233:
1.2.4.6 nathanw 234: Static struct usbd_pipe_methods ehci_root_ctrl_methods = {
1.2.4.2 nathanw 235: ehci_root_ctrl_transfer,
236: ehci_root_ctrl_start,
237: ehci_root_ctrl_abort,
238: ehci_root_ctrl_close,
239: ehci_noop,
240: ehci_root_ctrl_done,
241: };
242:
1.2.4.6 nathanw 243: Static struct usbd_pipe_methods ehci_root_intr_methods = {
1.2.4.2 nathanw 244: ehci_root_intr_transfer,
245: ehci_root_intr_start,
246: ehci_root_intr_abort,
247: ehci_root_intr_close,
248: ehci_noop,
249: ehci_root_intr_done,
250: };
251:
1.2.4.6 nathanw 252: Static struct usbd_pipe_methods ehci_device_ctrl_methods = {
1.2.4.2 nathanw 253: ehci_device_ctrl_transfer,
254: ehci_device_ctrl_start,
255: ehci_device_ctrl_abort,
256: ehci_device_ctrl_close,
257: ehci_noop,
258: ehci_device_ctrl_done,
259: };
260:
1.2.4.6 nathanw 261: Static struct usbd_pipe_methods ehci_device_intr_methods = {
1.2.4.2 nathanw 262: ehci_device_intr_transfer,
263: ehci_device_intr_start,
264: ehci_device_intr_abort,
265: ehci_device_intr_close,
266: ehci_device_clear_toggle,
267: ehci_device_intr_done,
268: };
269:
1.2.4.6 nathanw 270: Static struct usbd_pipe_methods ehci_device_bulk_methods = {
1.2.4.2 nathanw 271: ehci_device_bulk_transfer,
272: ehci_device_bulk_start,
273: ehci_device_bulk_abort,
274: ehci_device_bulk_close,
275: ehci_device_clear_toggle,
276: ehci_device_bulk_done,
277: };
278:
279: Static struct usbd_pipe_methods ehci_device_isoc_methods = {
280: ehci_device_isoc_transfer,
281: ehci_device_isoc_start,
282: ehci_device_isoc_abort,
283: ehci_device_isoc_close,
284: ehci_noop,
285: ehci_device_isoc_done,
286: };
287:
1.1 augustss 288: usbd_status
289: ehci_init(ehci_softc_t *sc)
290: {
1.2.4.1 nathanw 291: u_int32_t version, sparams, cparams, hcr;
292: u_int i;
293: usbd_status err;
1.2.4.2 nathanw 294: ehci_soft_qh_t *sqh;
1.2.4.1 nathanw 295:
296: DPRINTF(("ehci_init: start\n"));
1.2.4.2 nathanw 297: #ifdef EHCI_DEBUG
298: theehci = sc;
299: #endif
1.2.4.1 nathanw 300:
301: sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
302:
303: version = EREAD2(sc, EHCI_HCIVERSION);
304: printf("%s: EHCI version %x.%x\n", USBDEVNAME(sc->sc_bus.bdev),
305: version >> 8, version & 0xff);
306:
307: sparams = EREAD4(sc, EHCI_HCSPARAMS);
308: DPRINTF(("ehci_init: sparams=0x%x\n", sparams));
1.2.4.2 nathanw 309: sc->sc_npcomp = EHCI_HCS_N_PCC(sparams);
1.2.4.1 nathanw 310: if (EHCI_HCS_N_CC(sparams) != sc->sc_ncomp) {
311: printf("%s: wrong number of companions (%d != %d)\n",
312: USBDEVNAME(sc->sc_bus.bdev),
313: EHCI_HCS_N_CC(sparams), sc->sc_ncomp);
314: return (USBD_IOERROR);
315: }
316: if (sc->sc_ncomp > 0) {
317: printf("%s: companion controller%s, %d port%s each:",
318: USBDEVNAME(sc->sc_bus.bdev), sc->sc_ncomp!=1 ? "s" : "",
319: EHCI_HCS_N_PCC(sparams),
320: EHCI_HCS_N_PCC(sparams)!=1 ? "s" : "");
321: for (i = 0; i < sc->sc_ncomp; i++)
322: printf(" %s", USBDEVNAME(sc->sc_comps[i]->bdev));
323: printf("\n");
324: }
1.2.4.2 nathanw 325: sc->sc_noport = EHCI_HCS_N_PORTS(sparams);
1.2.4.1 nathanw 326: cparams = EREAD4(sc, EHCI_HCCPARAMS);
327: DPRINTF(("ehci_init: cparams=0x%x\n", cparams));
1.2.4.6 nathanw 328:
1.2.4.7 ! nathanw 329: if (EHCI_HCC_64BIT(cparams)) {
! 330: /* MUST clear segment register if 64 bit capable. */
! 331: EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
! 332: }
! 333:
1.2.4.1 nathanw 334: sc->sc_bus.usbrev = USBREV_2_0;
335:
336: /* Reset the controller */
337: DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev)));
338: EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
339: usb_delay_ms(&sc->sc_bus, 1);
340: EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
341: for (i = 0; i < 100; i++) {
1.2.4.7 ! nathanw 342: usb_delay_ms(&sc->sc_bus, 1);
1.2.4.1 nathanw 343: hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
344: if (!hcr)
345: break;
346: }
347: if (hcr) {
348: printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
349: return (USBD_IOERROR);
350: }
351:
352: /* frame list size at default, read back what we got and use that */
353: switch (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD))) {
354: case 0: sc->sc_flsize = 1024*4; break;
355: case 1: sc->sc_flsize = 512*4; break;
356: case 2: sc->sc_flsize = 256*4; break;
357: case 3: return (USBD_IOERROR);
358: }
359: err = usb_allocmem(&sc->sc_bus, sc->sc_flsize,
360: EHCI_FLALIGN_ALIGN, &sc->sc_fldma);
361: if (err)
362: return (err);
363: DPRINTF(("%s: flsize=%d\n", USBDEVNAME(sc->sc_bus.bdev),sc->sc_flsize));
364:
1.2.4.2 nathanw 365: /* Set up the bus struct. */
366: sc->sc_bus.methods = &ehci_bus_methods;
367: sc->sc_bus.pipe_size = sizeof(struct ehci_pipe);
368:
369: sc->sc_powerhook = powerhook_establish(ehci_power, sc);
370: sc->sc_shutdownhook = shutdownhook_establish(ehci_shutdown, sc);
371:
372: sc->sc_eintrs = EHCI_NORMAL_INTRS;
373:
374: /* Allocate dummy QH that starts the async list. */
375: sqh = ehci_alloc_sqh(sc);
376: if (sqh == NULL) {
377: err = USBD_NOMEM;
378: goto bad1;
379: }
380: /* Fill the QH */
381: sqh->qh.qh_endp =
382: htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL);
383: sqh->qh.qh_link =
384: htole32(sqh->physaddr | EHCI_LINK_QH);
385: sqh->qh.qh_curqtd = EHCI_NULL;
386: sqh->next = NULL;
387: /* Fill the overlay qTD */
388: sqh->qh.qh_qtd.qtd_next = EHCI_NULL;
389: sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
390: sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
391: sqh->sqtd = NULL;
392: #ifdef EHCI_DEBUG
393: if (ehcidebug) {
394: ehci_dump_sqh(sqh);
395: }
396: #endif
397:
398: /* Point to async list */
399: sc->sc_async_head = sqh;
400: EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH);
401:
402: usb_callout_init(sc->sc_tmo_pcd);
403:
404: lockinit(&sc->sc_doorbell_lock, PZERO, "ehcidb", 0, 0);
405:
406: /* Enable interrupts */
407: EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
408:
409: /* Turn on controller */
410: EOWRITE4(sc, EHCI_USBCMD,
411: EHCI_CMD_ITC_8 | /* 8 microframes */
412: (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) |
413: EHCI_CMD_ASE |
414: /* EHCI_CMD_PSE | */
415: EHCI_CMD_RS);
416:
417: /* Take over port ownership */
418: EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF);
419:
420: for (i = 0; i < 100; i++) {
1.2.4.7 ! nathanw 421: usb_delay_ms(&sc->sc_bus, 1);
1.2.4.2 nathanw 422: hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
423: if (!hcr)
424: break;
425: }
426: if (hcr) {
427: printf("%s: run timeout\n", USBDEVNAME(sc->sc_bus.bdev));
428: return (USBD_IOERROR);
429: }
430:
431: return (USBD_NORMAL_COMPLETION);
432:
433: #if 0
434: bad2:
435: ehci_free_sqh(sc, sc->sc_async_head);
436: #endif
437: bad1:
438: usb_freemem(&sc->sc_bus, &sc->sc_fldma);
439: return (err);
1.1 augustss 440: }
441:
442: int
443: ehci_intr(void *v)
444: {
1.2.4.2 nathanw 445: ehci_softc_t *sc = v;
446:
447: if (sc == NULL || sc->sc_dying)
448: return (0);
449:
450: /* If we get an interrupt while polling, then just ignore it. */
451: if (sc->sc_bus.use_polling) {
452: #ifdef DIAGNOSTIC
453: printf("ehci_intr: ignored interrupt while polling\n");
454: #endif
455: return (0);
456: }
457:
1.2.4.6 nathanw 458: return (ehci_intr1(sc));
1.2.4.2 nathanw 459: }
460:
461: Static int
462: ehci_intr1(ehci_softc_t *sc)
463: {
464: u_int32_t intrs, eintrs;
465:
466: DPRINTFN(20,("ehci_intr1: enter\n"));
467:
468: /* In case the interrupt occurs before initialization has completed. */
469: if (sc == NULL) {
470: #ifdef DIAGNOSTIC
471: printf("ehci_intr: sc == NULL\n");
472: #endif
473: return (0);
474: }
475:
476: intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS));
477:
478: if (!intrs)
479: return (0);
480:
481: EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */
482: eintrs = intrs & sc->sc_eintrs;
1.2.4.6 nathanw 483: DPRINTFN(7, ("ehci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n",
1.2.4.2 nathanw 484: sc, (u_int)intrs, EOREAD4(sc, EHCI_USBSTS),
485: (u_int)eintrs));
486: if (!eintrs)
487: return (0);
488:
489: sc->sc_bus.intr_context++;
490: sc->sc_bus.no_intrs++;
491: if (eintrs & EHCI_STS_IAA) {
492: DPRINTF(("ehci_intr1: door bell\n"));
493: wakeup(&sc->sc_async_head);
494: eintrs &= ~EHCI_STS_IAA;
495: }
496: if (eintrs & (EHCI_STS_INT | EHCI_STS_ERRINT)) {
1.2.4.6 nathanw 497: DPRINTF(("ehci_intr1: %s %s\n",
1.2.4.2 nathanw 498: eintrs & EHCI_STS_INT ? "INT" : "",
499: eintrs & EHCI_STS_ERRINT ? "ERRINT" : ""));
500: usb_schedsoftintr(&sc->sc_bus);
501: eintrs &= ~(EHCI_STS_INT | EHCI_STS_ERRINT);
502: }
503: if (eintrs & EHCI_STS_HSE) {
504: printf("%s: unrecoverable error, controller halted\n",
505: USBDEVNAME(sc->sc_bus.bdev));
506: /* XXX what else */
507: }
508: if (eintrs & EHCI_STS_PCD) {
509: ehci_pcd(sc, sc->sc_intrxfer);
1.2.4.6 nathanw 510: /*
1.2.4.2 nathanw 511: * Disable PCD interrupt for now, because it will be
512: * on until the port has been reset.
513: */
514: ehci_pcd_able(sc, 0);
515: /* Do not allow RHSC interrupts > 1 per second */
516: usb_callout(sc->sc_tmo_pcd, hz, ehci_pcd_enable, sc);
517: eintrs &= ~EHCI_STS_PCD;
518: }
519:
520: sc->sc_bus.intr_context--;
521:
522: if (eintrs != 0) {
523: /* Block unprocessed interrupts. */
524: sc->sc_eintrs &= ~eintrs;
525: EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
526: printf("%s: blocking intrs 0x%x\n",
527: USBDEVNAME(sc->sc_bus.bdev), eintrs);
528: }
529:
530: return (1);
531: }
532:
533: void
534: ehci_pcd_able(ehci_softc_t *sc, int on)
535: {
536: DPRINTFN(4, ("ehci_pcd_able: on=%d\n", on));
537: if (on)
538: sc->sc_eintrs |= EHCI_STS_PCD;
539: else
540: sc->sc_eintrs &= ~EHCI_STS_PCD;
541: EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
542: }
543:
544: void
545: ehci_pcd_enable(void *v_sc)
546: {
547: ehci_softc_t *sc = v_sc;
548:
549: ehci_pcd_able(sc, 1);
550: }
551:
552: void
553: ehci_pcd(ehci_softc_t *sc, usbd_xfer_handle xfer)
554: {
555: usbd_pipe_handle pipe;
556: struct ehci_pipe *epipe;
557: u_char *p;
558: int i, m;
559:
560: if (xfer == NULL) {
561: /* Just ignore the change. */
562: return;
563: }
564:
565: pipe = xfer->pipe;
566: epipe = (struct ehci_pipe *)pipe;
567:
1.2.4.3 nathanw 568: p = KERNADDR(&xfer->dmabuf, 0);
1.2.4.2 nathanw 569: m = min(sc->sc_noport, xfer->length * 8 - 1);
570: memset(p, 0, xfer->length);
571: for (i = 1; i <= m; i++) {
572: /* Pick out CHANGE bits from the status reg. */
573: if (EOREAD4(sc, EHCI_PORTSC(i)) & EHCI_PS_CLEAR)
574: p[i/8] |= 1 << (i%8);
575: }
576: DPRINTF(("ehci_pcd: change=0x%02x\n", *p));
577: xfer->actlen = xfer->length;
578: xfer->status = USBD_NORMAL_COMPLETION;
579:
580: usb_transfer_complete(xfer);
581: }
582:
583: void
584: ehci_softintr(void *v)
585: {
586: ehci_softc_t *sc = v;
587: struct ehci_xfer *ex;
588:
589: DPRINTFN(10,("%s: ehci_softintr (%d)\n", USBDEVNAME(sc->sc_bus.bdev),
590: sc->sc_bus.intr_context));
591:
592: sc->sc_bus.intr_context++;
593:
594: /*
595: * The only explanation I can think of for why EHCI is as brain dead
596: * as UHCI interrupt-wise is that Intel was involved in both.
597: * An interrupt just tells us that something is done, we have no
598: * clue what, so we need to scan through all active transfers. :-(
599: */
600: for (ex = LIST_FIRST(&sc->sc_intrhead); ex; ex = LIST_NEXT(ex, inext))
601: ehci_check_intr(sc, ex);
602:
603: if (sc->sc_softwake) {
604: sc->sc_softwake = 0;
605: wakeup(&sc->sc_softwake);
606: }
607:
608: sc->sc_bus.intr_context--;
609: }
610:
611: /* Check for an interrupt. */
612: void
613: ehci_check_intr(ehci_softc_t *sc, struct ehci_xfer *ex)
614: {
615: ehci_soft_qtd_t *sqtd, *lsqtd;
616: u_int32_t status;
617:
618: DPRINTFN(/*15*/2, ("ehci_check_intr: ex=%p\n", ex));
619:
620: if (ex->sqtdstart == NULL) {
621: printf("ehci_check_intr: sqtdstart=NULL\n");
622: return;
623: }
624: lsqtd = ex->sqtdend;
625: #ifdef DIAGNOSTIC
626: if (lsqtd == NULL) {
627: printf("ehci_check_intr: sqtd==0\n");
628: return;
629: }
630: #endif
1.2.4.6 nathanw 631: /*
1.2.4.2 nathanw 632: * If the last TD is still active we need to check whether there
633: * is a an error somewhere in the middle, or whether there was a
634: * short packet (SPD and not ACTIVE).
635: */
636: if (le32toh(lsqtd->qtd.qtd_status) & EHCI_QTD_ACTIVE) {
637: DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex));
638: for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) {
639: status = le32toh(sqtd->qtd.qtd_status);
640: /* If there's an active QTD the xfer isn't done. */
641: if (status & EHCI_QTD_ACTIVE)
642: break;
643: /* Any kind of error makes the xfer done. */
644: if (status & EHCI_QTD_HALTED)
645: goto done;
646: /* We want short packets, and it is short: it's done */
647: if (EHCI_QTD_SET_BYTES(status) != 0)
648: goto done;
649: }
650: DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n",
651: ex, ex->sqtdstart));
652: return;
653: }
654: done:
655: DPRINTFN(12, ("ehci_check_intr: ex=%p done\n", ex));
656: usb_uncallout(ex->xfer.timeout_handle, ehci_timeout, ex);
657: ehci_idone(ex);
658: }
659:
660: void
661: ehci_idone(struct ehci_xfer *ex)
662: {
663: usbd_xfer_handle xfer = &ex->xfer;
664: #ifdef EHCI_DEBUG
665: struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
666: #endif
667: ehci_soft_qtd_t *sqtd;
668: u_int32_t status = 0, nstatus;
669: int actlen;
670:
671: DPRINTFN(/*12*/2, ("ehci_idone: ex=%p\n", ex));
672: #ifdef DIAGNOSTIC
673: {
674: int s = splhigh();
675: if (ex->isdone) {
676: splx(s);
677: #ifdef EHCI_DEBUG
678: printf("ehci_idone: ex is done!\n ");
679: ehci_dump_exfer(ex);
680: #else
681: printf("ehci_idone: ex=%p is done!\n", ex);
682: #endif
683: return;
684: }
685: ex->isdone = 1;
686: splx(s);
687: }
688: #endif
689:
690: if (xfer->status == USBD_CANCELLED ||
691: xfer->status == USBD_TIMEOUT) {
692: DPRINTF(("ehci_idone: aborted xfer=%p\n", xfer));
693: return;
694: }
695:
696: #ifdef EHCI_DEBUG
697: DPRINTFN(/*10*/2, ("ehci_idone: xfer=%p, pipe=%p ready\n", xfer, epipe));
698: if (ehcidebug > 10)
699: ehci_dump_sqtds(ex->sqtdstart);
700: #endif
701:
702: /* The transfer is done, compute actual length and status. */
703: actlen = 0;
704: for (sqtd = ex->sqtdstart; sqtd != NULL; sqtd = sqtd->nextqtd) {
705: nstatus = le32toh(sqtd->qtd.qtd_status);
706: if (nstatus & EHCI_QTD_ACTIVE)
707: break;
708:
709: status = nstatus;
710: if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP)
711: actlen += sqtd->len - EHCI_QTD_GET_BYTES(status);
712: }
713:
714: /* If there are left over TDs we need to update the toggle. */
715: if (sqtd != NULL) {
716: if (!(xfer->rqflags & URQ_REQUEST))
717: printf("ehci_idone: need toggle update\n");
718: #if 0
719: epipe->nexttoggle = EHCI_TD_GET_DT(le32toh(std->td.td_token));
720: #endif
721: }
722:
723: status &= EHCI_QTD_STATERRS;
724: DPRINTFN(/*10*/2, ("ehci_idone: len=%d, actlen=%d, status=0x%x\n",
725: xfer->length, actlen, status));
726: xfer->actlen = actlen;
727: if (status != 0) {
728: #ifdef EHCI_DEBUG
729: char sbuf[128];
730:
731: bitmask_snprintf((u_int32_t)status,
732: "\20\3MISSEDMICRO\4XACT\5BABBLE\6BABBLE"
733: "\7HALTED",
734: sbuf, sizeof(sbuf));
735:
736: DPRINTFN((status == EHCI_QTD_HALTED)*/*10*/2,
737: ("ehci_idone: error, addr=%d, endpt=0x%02x, "
738: "status 0x%s\n",
739: xfer->pipe->device->address,
740: xfer->pipe->endpoint->edesc->bEndpointAddress,
741: sbuf));
742: if (ehcidebug > 2) {
743: ehci_dump_sqh(epipe->sqh);
744: ehci_dump_sqtds(ex->sqtdstart);
745: }
746: #endif
747: if (status == EHCI_QTD_HALTED)
748: xfer->status = USBD_STALLED;
749: else
750: xfer->status = USBD_IOERROR; /* more info XXX */
751: } else {
752: xfer->status = USBD_NORMAL_COMPLETION;
753: }
754:
755: usb_transfer_complete(xfer);
756: DPRINTFN(/*12*/2, ("ehci_idone: ex=%p done\n", ex));
757: }
758:
759: /*
760: * Wait here until controller claims to have an interrupt.
761: * Then call ehci_intr and return. Use timeout to avoid waiting
762: * too long.
763: */
764: void
765: ehci_waitintr(ehci_softc_t *sc, usbd_xfer_handle xfer)
766: {
767: int timo = xfer->timeout;
768: int usecs;
769: u_int32_t intrs;
770:
771: xfer->status = USBD_IN_PROGRESS;
772: for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
773: usb_delay_ms(&sc->sc_bus, 1);
774: if (sc->sc_dying)
775: break;
776: intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)) &
777: sc->sc_eintrs;
778: DPRINTFN(15,("ehci_waitintr: 0x%04x\n", intrs));
779: #ifdef OHCI_DEBUG
780: if (ehcidebug > 15)
781: ehci_dump_regs(sc);
782: #endif
783: if (intrs) {
784: ehci_intr1(sc);
785: if (xfer->status != USBD_IN_PROGRESS)
786: return;
787: }
788: }
789:
790: /* Timeout */
791: DPRINTF(("ehci_waitintr: timeout\n"));
792: xfer->status = USBD_TIMEOUT;
793: usb_transfer_complete(xfer);
794: /* XXX should free TD */
795: }
796:
797: void
798: ehci_poll(struct usbd_bus *bus)
799: {
800: ehci_softc_t *sc = (ehci_softc_t *)bus;
801: #ifdef EHCI_DEBUG
802: static int last;
803: int new;
804: new = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS));
805: if (new != last) {
806: DPRINTFN(10,("ehci_poll: intrs=0x%04x\n", new));
807: last = new;
808: }
809: #endif
810:
811: if (EOREAD4(sc, EHCI_USBSTS) & sc->sc_eintrs)
812: ehci_intr1(sc);
1.1 augustss 813: }
814:
815: int
816: ehci_detach(struct ehci_softc *sc, int flags)
817: {
818: int rv = 0;
819:
820: if (sc->sc_child != NULL)
821: rv = config_detach(sc->sc_child, flags);
1.2.4.6 nathanw 822:
1.1 augustss 823: if (rv != 0)
824: return (rv);
825:
1.2.4.2 nathanw 826: usb_uncallout(sc->sc_tmo_pcd, ehci_pcd_enable, sc);
827:
1.1 augustss 828: if (sc->sc_powerhook != NULL)
829: powerhook_disestablish(sc->sc_powerhook);
830: if (sc->sc_shutdownhook != NULL)
831: shutdownhook_disestablish(sc->sc_shutdownhook);
832:
1.2.4.2 nathanw 833: usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
834:
1.1 augustss 835: /* XXX free other data structures XXX */
836:
837: return (rv);
838: }
839:
840:
841: int
842: ehci_activate(device_ptr_t self, enum devact act)
843: {
844: struct ehci_softc *sc = (struct ehci_softc *)self;
845: int rv = 0;
846:
847: switch (act) {
848: case DVACT_ACTIVATE:
849: return (EOPNOTSUPP);
850: break;
851:
852: case DVACT_DEACTIVATE:
853: if (sc->sc_child != NULL)
854: rv = config_deactivate(sc->sc_child);
1.2.4.2 nathanw 855: sc->sc_dying = 1;
1.1 augustss 856: break;
857: }
858: return (rv);
859: }
860:
1.2.4.2 nathanw 861: /*
862: * Handle suspend/resume.
863: *
864: * We need to switch to polling mode here, because this routine is
865: * called from an intterupt context. This is all right since we
866: * are almost suspended anyway.
867: */
868: void
869: ehci_power(int why, void *v)
870: {
871: ehci_softc_t *sc = v;
872: //u_int32_t ctl;
873: int s;
874:
875: #ifdef EHCI_DEBUG
876: DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why));
877: ehci_dump_regs(sc);
878: #endif
879:
880: s = splhardusb();
881: switch (why) {
882: case PWR_SUSPEND:
883: case PWR_STANDBY:
884: sc->sc_bus.use_polling++;
885: #if 0
886: OOO
887: ctl = OREAD4(sc, EHCI_CONTROL) & ~EHCI_HCFS_MASK;
888: if (sc->sc_control == 0) {
889: /*
890: * Preserve register values, in case that APM BIOS
891: * does not recover them.
892: */
893: sc->sc_control = ctl;
894: sc->sc_intre = OREAD4(sc, EHCI_INTERRUPT_ENABLE);
895: }
896: ctl |= EHCI_HCFS_SUSPEND;
897: OWRITE4(sc, EHCI_CONTROL, ctl);
898: #endif
899: usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
900: sc->sc_bus.use_polling--;
901: break;
902: case PWR_RESUME:
903: sc->sc_bus.use_polling++;
904: #if 0
905: OOO
906: /* Some broken BIOSes do not recover these values */
1.2.4.3 nathanw 907: OWRITE4(sc, EHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
1.2.4.2 nathanw 908: OWRITE4(sc, EHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
909: OWRITE4(sc, EHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
910: if (sc->sc_intre)
911: OWRITE4(sc, EHCI_INTERRUPT_ENABLE,
912: sc->sc_intre & (EHCI_ALL_INTRS | EHCI_MIE));
913: if (sc->sc_control)
914: ctl = sc->sc_control;
915: else
916: ctl = OREAD4(sc, EHCI_CONTROL);
917: ctl |= EHCI_HCFS_RESUME;
918: OWRITE4(sc, EHCI_CONTROL, ctl);
919: usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
920: ctl = (ctl & ~EHCI_HCFS_MASK) | EHCI_HCFS_OPERATIONAL;
921: OWRITE4(sc, EHCI_CONTROL, ctl);
922: usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
923: sc->sc_control = sc->sc_intre = 0;
924: #endif
925: sc->sc_bus.use_polling--;
926: break;
927: case PWR_SOFTSUSPEND:
928: case PWR_SOFTSTANDBY:
929: case PWR_SOFTRESUME:
930: break;
931: }
932: splx(s);
933: }
934:
935: /*
936: * Shut down the controller when the system is going down.
937: */
938: void
939: ehci_shutdown(void *v)
940: {
941: ehci_softc_t *sc = v;
942:
943: DPRINTF(("ehci_shutdown: stopping the HC\n"));
944: EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
945: EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
946: }
947:
948: usbd_status
949: ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
950: {
951: struct ehci_softc *sc = (struct ehci_softc *)bus;
952: usbd_status err;
953:
954: err = usb_allocmem(&sc->sc_bus, size, 0, dma);
955: #ifdef EHCI_DEBUG
956: if (err)
957: printf("ehci_allocm: usb_allocmem()=%d\n", err);
958: #endif
959: return (err);
960: }
961:
962: void
963: ehci_freem(struct usbd_bus *bus, usb_dma_t *dma)
964: {
965: struct ehci_softc *sc = (struct ehci_softc *)bus;
966:
967: usb_freemem(&sc->sc_bus, dma);
968: }
969:
970: usbd_xfer_handle
971: ehci_allocx(struct usbd_bus *bus)
972: {
973: struct ehci_softc *sc = (struct ehci_softc *)bus;
974: usbd_xfer_handle xfer;
975:
976: xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
977: if (xfer != NULL) {
1.2.4.3 nathanw 978: SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
1.2.4.2 nathanw 979: #ifdef DIAGNOSTIC
980: if (xfer->busy_free != XFER_FREE) {
981: printf("uhci_allocx: xfer=%p not free, 0x%08x\n", xfer,
982: xfer->busy_free);
983: }
984: #endif
985: } else {
986: xfer = malloc(sizeof(struct ehci_xfer), M_USB, M_NOWAIT);
987: }
988: if (xfer != NULL) {
989: memset(xfer, 0, sizeof (struct ehci_xfer));
990: #ifdef DIAGNOSTIC
991: EXFER(xfer)->isdone = 1;
992: xfer->busy_free = XFER_BUSY;
993: #endif
994: }
995: return (xfer);
996: }
997:
998: void
999: ehci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
1000: {
1001: struct ehci_softc *sc = (struct ehci_softc *)bus;
1002:
1003: #ifdef DIAGNOSTIC
1004: if (xfer->busy_free != XFER_BUSY) {
1005: printf("ehci_freex: xfer=%p not busy, 0x%08x\n", xfer,
1006: xfer->busy_free);
1007: return;
1008: }
1009: xfer->busy_free = XFER_FREE;
1010: if (!EXFER(xfer)->isdone) {
1011: printf("ehci_freex: !isdone\n");
1012: return;
1013: }
1014: #endif
1015: SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
1016: }
1017:
1018: Static void
1019: ehci_device_clear_toggle(usbd_pipe_handle pipe)
1020: {
1021: struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
1022:
1023: DPRINTF(("ehci_device_clear_toggle: epipe=%p status=0x%x\n",
1024: epipe, epipe->sqh->qh.qh_qtd.qtd_status));
1025: #ifdef USB_DEBUG
1026: if (ehcidebug)
1027: usbd_dump_pipe(pipe);
1028: #endif
1029: epipe->sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE);
1030: }
1031:
1032: Static void
1033: ehci_noop(usbd_pipe_handle pipe)
1034: {
1035: }
1036:
1037: #ifdef EHCI_DEBUG
1038: void
1039: ehci_dump_regs(ehci_softc_t *sc)
1040: {
1041: int i;
1042: printf("cmd=0x%08x, sts=0x%08x, ien=0x%08x\n",
1043: EOREAD4(sc, EHCI_USBCMD),
1044: EOREAD4(sc, EHCI_USBSTS),
1045: EOREAD4(sc, EHCI_USBINTR));
1046: printf("frindex=0x%08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n",
1047: EOREAD4(sc, EHCI_FRINDEX),
1048: EOREAD4(sc, EHCI_CTRLDSSEGMENT),
1049: EOREAD4(sc, EHCI_PERIODICLISTBASE),
1050: EOREAD4(sc, EHCI_ASYNCLISTADDR));
1051: for (i = 1; i <= sc->sc_noport; i++)
1.2.4.6 nathanw 1052: printf("port %d status=0x%08x\n", i,
1.2.4.2 nathanw 1053: EOREAD4(sc, EHCI_PORTSC(i)));
1054: }
1055:
1056: void
1057: ehci_dump()
1058: {
1059: ehci_dump_regs(theehci);
1060: }
1061:
1062: void
1063: ehci_dump_link(ehci_link_t link, int type)
1064: {
1065: link = le32toh(link);
1066: printf("0x%08x", link);
1067: if (link & EHCI_LINK_TERMINATE)
1068: printf("<T>");
1069: else {
1070: printf("<");
1071: if (type) {
1072: switch (EHCI_LINK_TYPE(link)) {
1073: case EHCI_LINK_ITD: printf("ITD"); break;
1074: case EHCI_LINK_QH: printf("QH"); break;
1075: case EHCI_LINK_SITD: printf("SITD"); break;
1076: case EHCI_LINK_FSTN: printf("FSTN"); break;
1077: }
1078: }
1079: printf(">");
1080: }
1081: }
1082:
1083: void
1084: ehci_dump_sqtds(ehci_soft_qtd_t *sqtd)
1085: {
1086: int i;
1087: u_int32_t stop;
1088:
1089: stop = 0;
1090: for (i = 0; sqtd && i < 20 && !stop; sqtd = sqtd->nextqtd, i++) {
1091: ehci_dump_sqtd(sqtd);
1092: stop = sqtd->qtd.qtd_next & EHCI_LINK_TERMINATE;
1093: }
1094: if (sqtd)
1095: printf("dump aborted, too many TDs\n");
1096: }
1097:
1098: void
1099: ehci_dump_sqtd(ehci_soft_qtd_t *sqtd)
1100: {
1101: printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr);
1102: ehci_dump_qtd(&sqtd->qtd);
1103: }
1104:
1105: void
1106: ehci_dump_qtd(ehci_qtd_t *qtd)
1107: {
1108: u_int32_t s;
1109: char sbuf[128];
1110:
1111: printf(" next="); ehci_dump_link(qtd->qtd_next, 0);
1112: printf(" altnext="); ehci_dump_link(qtd->qtd_altnext, 0);
1113: printf("\n");
1114: s = le32toh(qtd->qtd_status);
1115: bitmask_snprintf(EHCI_QTD_GET_STATUS(s),
1116: "\20\10ACTIVE\7HALTED\6BUFERR\5BABBLE\4XACTERR"
1117: "\3MISSED\2SPLIT\1PING", sbuf, sizeof(sbuf));
1118: printf(" status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n",
1119: s, EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_BYTES(s),
1120: EHCI_QTD_GET_IOC(s), EHCI_QTD_GET_C_PAGE(s));
1121: printf(" cerr=%d pid=%d stat=0x%s\n", EHCI_QTD_GET_CERR(s),
1122: EHCI_QTD_GET_PID(s), sbuf);
1123: for (s = 0; s < 5; s++)
1124: printf(" buffer[%d]=0x%08x\n", s, le32toh(qtd->qtd_buffer[s]));
1125: }
1126:
1127: void
1128: ehci_dump_sqh(ehci_soft_qh_t *sqh)
1129: {
1130: ehci_qh_t *qh = &sqh->qh;
1131: u_int32_t endp, endphub;
1132:
1133: printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
1134: printf(" link="); ehci_dump_link(qh->qh_link, 1); printf("\n");
1135: endp = le32toh(qh->qh_endp);
1136: printf(" endp=0x%08x\n", endp);
1137: printf(" addr=0x%02x inact=%d endpt=%d eps=%d dtc=%d hrecl=%d\n",
1138: EHCI_QH_GET_ADDR(endp), EHCI_QH_GET_INACT(endp),
1139: EHCI_QH_GET_ENDPT(endp), EHCI_QH_GET_EPS(endp),
1140: EHCI_QH_GET_DTC(endp), EHCI_QH_GET_HRECL(endp));
1141: printf(" mpl=0x%x ctl=%d nrl=%d\n",
1142: EHCI_QH_GET_MPL(endp), EHCI_QH_GET_CTL(endp),
1143: EHCI_QH_GET_NRL(endp));
1144: endphub = le32toh(qh->qh_endphub);
1145: printf(" endphub=0x%08x\n", endphub);
1146: printf(" smask=0x%02x cmask=0x%02x huba=0x%02x port=%d mult=%d\n",
1147: EHCI_QH_GET_SMASK(endphub), EHCI_QH_GET_CMASK(endphub),
1148: EHCI_QH_GET_HUBA(endphub), EHCI_QH_GET_PORT(endphub),
1149: EHCI_QH_GET_MULT(endphub));
1150: printf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n");
1151: printf("Overlay qTD:\n");
1152: ehci_dump_qtd(&qh->qh_qtd);
1153: }
1154:
1155: Static void
1156: ehci_dump_exfer(struct ehci_xfer *ex)
1157: {
1158: printf("ehci_dump_exfer: ex=%p\n", ex);
1159: }
1160: #endif
1161:
1162: usbd_status
1163: ehci_open(usbd_pipe_handle pipe)
1164: {
1165: usbd_device_handle dev = pipe->device;
1166: ehci_softc_t *sc = (ehci_softc_t *)dev->bus;
1167: usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
1168: u_int8_t addr = dev->address;
1169: u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
1170: struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
1171: ehci_soft_qh_t *sqh;
1172: usbd_status err;
1173: int s;
1174: int speed, naks;
1175:
1176: DPRINTFN(1, ("ehci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
1177: pipe, addr, ed->bEndpointAddress, sc->sc_addr));
1178:
1179: if (sc->sc_dying)
1180: return (USBD_IOERROR);
1181:
1182: if (addr == sc->sc_addr) {
1183: switch (ed->bEndpointAddress) {
1184: case USB_CONTROL_ENDPOINT:
1185: pipe->methods = &ehci_root_ctrl_methods;
1186: break;
1187: case UE_DIR_IN | EHCI_INTR_ENDPT:
1188: pipe->methods = &ehci_root_intr_methods;
1189: break;
1190: default:
1191: return (USBD_INVAL);
1192: }
1193: return (USBD_NORMAL_COMPLETION);
1194: }
1195:
1196: /* XXX All this stuff is only valid for async. */
1197: switch (dev->speed) {
1198: case USB_SPEED_LOW: speed = EHCI_QH_SPEED_LOW; break;
1199: case USB_SPEED_FULL: speed = EHCI_QH_SPEED_FULL; break;
1200: case USB_SPEED_HIGH: speed = EHCI_QH_SPEED_HIGH; break;
1201: default: panic("ehci_open: bad device speed %d\n", dev->speed);
1202: }
1203: naks = 8; /* XXX */
1204: sqh = ehci_alloc_sqh(sc);
1205: if (sqh == NULL)
1206: goto bad0;
1207: /* qh_link filled when the QH is added */
1208: sqh->qh.qh_endp = htole32(
1209: EHCI_QH_SET_ADDR(addr) |
1210: EHCI_QH_SET_ENDPT(ed->bEndpointAddress) |
1211: EHCI_QH_SET_EPS(speed) | /* XXX */
1212: /* XXX EHCI_QH_DTC ? */
1213: EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) |
1214: (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ?
1215: EHCI_QH_CTL : 0) |
1216: EHCI_QH_SET_NRL(naks)
1217: );
1218: sqh->qh.qh_endphub = htole32(
1219: EHCI_QH_SET_MULT(1)
1220: /* XXX TT stuff */
1221: /* XXX interrupt mask */
1222: );
1223: sqh->qh.qh_curqtd = EHCI_NULL;
1224: /* Fill the overlay qTD */
1225: sqh->qh.qh_qtd.qtd_next = EHCI_NULL;
1226: sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
1227: sqh->qh.qh_qtd.qtd_status = htole32(0);
1228:
1229: epipe->sqh = sqh;
1230:
1231: switch (xfertype) {
1232: case UE_CONTROL:
1.2.4.6 nathanw 1233: err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t),
1.2.4.2 nathanw 1234: 0, &epipe->u.ctl.reqdma);
1235: #ifdef EHCI_DEBUG
1236: if (err)
1237: printf("ehci_open: usb_allocmem()=%d\n", err);
1238: #endif
1239: if (err)
1240: goto bad1;
1241: pipe->methods = &ehci_device_ctrl_methods;
1242: s = splusb();
1243: ehci_add_qh(sqh, sc->sc_async_head);
1244: splx(s);
1245: break;
1246: case UE_BULK:
1247: pipe->methods = &ehci_device_bulk_methods;
1248: s = splusb();
1249: ehci_add_qh(sqh, sc->sc_async_head);
1250: splx(s);
1251: break;
1252: case UE_INTERRUPT:
1253: pipe->methods = &ehci_device_intr_methods;
1254: return (USBD_INVAL);
1255: case UE_ISOCHRONOUS:
1256: pipe->methods = &ehci_device_isoc_methods;
1257: return (USBD_INVAL);
1258: default:
1259: return (USBD_INVAL);
1260: }
1261: return (USBD_NORMAL_COMPLETION);
1262:
1263: bad1:
1264: ehci_free_sqh(sc, sqh);
1265: bad0:
1266: return (USBD_NOMEM);
1267: }
1268:
1269: /*
1270: * Add an ED to the schedule. Called at splusb().
1271: */
1272: void
1273: ehci_add_qh(ehci_soft_qh_t *sqh, ehci_soft_qh_t *head)
1274: {
1275: SPLUSBCHECK;
1276:
1277: sqh->next = head->next;
1278: sqh->qh.qh_link = head->qh.qh_link;
1279: head->next = sqh;
1280: head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH);
1281:
1282: #ifdef EHCI_DEBUG
1283: if (ehcidebug > 5) {
1284: printf("ehci_add_qh:\n");
1285: ehci_dump_sqh(sqh);
1286: }
1287: #endif
1288: }
1289:
1290: /*
1291: * Remove an ED from the schedule. Called at splusb().
1292: */
1293: void
1294: ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head)
1295: {
1.2.4.6 nathanw 1296: ehci_soft_qh_t *p;
1.2.4.2 nathanw 1297:
1298: SPLUSBCHECK;
1299: /* XXX */
1300: for (p = head; p == NULL && p->next != sqh; p = p->next)
1301: ;
1302: if (p == NULL)
1303: panic("ehci_rem_qh: ED not found\n");
1304: p->next = sqh->next;
1305: p->qh.qh_link = sqh->qh.qh_link;
1306:
1307: ehci_sync_hc(sc);
1308: }
1309:
1310: void
1311: ehci_set_qh_qtd(ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd)
1312: {
1313: /* Halt while we are messing. */
1314: sqh->qh.qh_qtd.qtd_status |= htole32(EHCI_QTD_HALTED);
1315: sqh->qh.qh_curqtd = 0;
1316: sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
1317: sqh->sqtd = sqtd;
1318: /* Keep toggle, clear the rest, including length. */
1319: sqh->qh.qh_qtd.qtd_status &= htole32(EHCI_QTD_TOGGLE);
1320: }
1321:
1322: /*
1323: * Ensure that the HC has released all references to the QH. We do this
1324: * by asking for a Async Advance Doorbell interrupt and then we wait for
1325: * the interrupt.
1326: * To make this easier we first obtain exclusive use of the doorbell.
1327: */
1328: void
1329: ehci_sync_hc(ehci_softc_t *sc)
1330: {
1331: int s, error;
1332:
1333: if (sc->sc_dying) {
1334: DPRINTFN(2,("ehci_sync_hc: dying\n"));
1335: return;
1336: }
1337: DPRINTFN(2,("ehci_sync_hc: enter\n"));
1338: lockmgr(&sc->sc_doorbell_lock, LK_EXCLUSIVE, NULL); /* get doorbell */
1339: s = splhardusb();
1340: /* ask for doorbell */
1341: EOWRITE4(sc, EHCI_USBCMD, EOREAD4(sc, EHCI_USBCMD) | EHCI_CMD_IAAD);
1342: DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n",
1343: EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS)));
1344: error = tsleep(&sc->sc_async_head, PZERO, "ehcidi", hz); /* bell wait */
1345: DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n",
1346: EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS)));
1347: splx(s);
1348: lockmgr(&sc->sc_doorbell_lock, LK_RELEASE, NULL); /* release doorbell */
1349: #ifdef DIAGNOSTIC
1350: if (error)
1351: printf("ehci_sync_hc: tsleep() = %d\n", error);
1352: #endif
1353: DPRINTFN(2,("ehci_sync_hc: exit\n"));
1354: }
1355:
1356: /***********/
1357:
1358: /*
1359: * Data structures and routines to emulate the root hub.
1360: */
1361: Static usb_device_descriptor_t ehci_devd = {
1362: USB_DEVICE_DESCRIPTOR_SIZE,
1363: UDESC_DEVICE, /* type */
1364: {0x00, 0x02}, /* USB version */
1365: UDCLASS_HUB, /* class */
1366: UDSUBCLASS_HUB, /* subclass */
1367: UDPROTO_HSHUBSTT, /* protocol */
1368: 64, /* max packet */
1369: {0},{0},{0x00,0x01}, /* device id */
1370: 1,2,0, /* string indicies */
1371: 1 /* # of configurations */
1372: };
1373:
1374: Static usb_device_qualifier_t ehci_odevd = {
1375: USB_DEVICE_DESCRIPTOR_SIZE,
1376: UDESC_DEVICE_QUALIFIER, /* type */
1377: {0x00, 0x02}, /* USB version */
1378: UDCLASS_HUB, /* class */
1379: UDSUBCLASS_HUB, /* subclass */
1380: UDPROTO_FSHUB, /* protocol */
1381: 64, /* max packet */
1382: 1, /* # of configurations */
1383: 0
1384: };
1385:
1386: Static usb_config_descriptor_t ehci_confd = {
1387: USB_CONFIG_DESCRIPTOR_SIZE,
1388: UDESC_CONFIG,
1389: {USB_CONFIG_DESCRIPTOR_SIZE +
1390: USB_INTERFACE_DESCRIPTOR_SIZE +
1391: USB_ENDPOINT_DESCRIPTOR_SIZE},
1392: 1,
1393: 1,
1394: 0,
1395: UC_SELF_POWERED,
1396: 0 /* max power */
1397: };
1398:
1399: Static usb_interface_descriptor_t ehci_ifcd = {
1400: USB_INTERFACE_DESCRIPTOR_SIZE,
1401: UDESC_INTERFACE,
1402: 0,
1403: 0,
1404: 1,
1405: UICLASS_HUB,
1406: UISUBCLASS_HUB,
1407: UIPROTO_HSHUBSTT,
1408: 0
1409: };
1410:
1411: Static usb_endpoint_descriptor_t ehci_endpd = {
1412: USB_ENDPOINT_DESCRIPTOR_SIZE,
1413: UDESC_ENDPOINT,
1414: UE_DIR_IN | EHCI_INTR_ENDPT,
1415: UE_INTERRUPT,
1416: {8, 0}, /* max packet */
1417: 255
1418: };
1419:
1420: Static usb_hub_descriptor_t ehci_hubd = {
1421: USB_HUB_DESCRIPTOR_SIZE,
1422: UDESC_HUB,
1423: 0,
1424: {0,0},
1425: 0,
1426: 0,
1427: {0},
1428: };
1429:
1430: Static int
1431: ehci_str(p, l, s)
1432: usb_string_descriptor_t *p;
1433: int l;
1434: char *s;
1435: {
1436: int i;
1437:
1438: if (l == 0)
1439: return (0);
1440: p->bLength = 2 * strlen(s) + 2;
1441: if (l == 1)
1442: return (1);
1443: p->bDescriptorType = UDESC_STRING;
1444: l -= 2;
1445: for (i = 0; s[i] && l > 1; i++, l -= 2)
1446: USETW2(p->bString[i], 0, s[i]);
1447: return (2*i+2);
1448: }
1449:
1450: /*
1451: * Simulate a hardware hub by handling all the necessary requests.
1452: */
1453: Static usbd_status
1454: ehci_root_ctrl_transfer(usbd_xfer_handle xfer)
1455: {
1456: usbd_status err;
1457:
1458: /* Insert last in queue. */
1459: err = usb_insert_transfer(xfer);
1460: if (err)
1461: return (err);
1462:
1463: /* Pipe isn't running, start first */
1464: return (ehci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
1465: }
1466:
1467: Static usbd_status
1468: ehci_root_ctrl_start(usbd_xfer_handle xfer)
1469: {
1470: ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
1471: usb_device_request_t *req;
1472: void *buf = NULL;
1473: int port, i;
1474: int s, len, value, index, l, totlen = 0;
1475: usb_port_status_t ps;
1476: usb_hub_descriptor_t hubd;
1477: usbd_status err;
1478: u_int32_t v;
1479:
1480: if (sc->sc_dying)
1481: return (USBD_IOERROR);
1482:
1483: #ifdef DIAGNOSTIC
1484: if (!(xfer->rqflags & URQ_REQUEST))
1485: /* XXX panic */
1486: return (USBD_INVAL);
1487: #endif
1488: req = &xfer->request;
1489:
1.2.4.6 nathanw 1490: DPRINTFN(4,("ehci_root_ctrl_control type=0x%02x request=%02x\n",
1.2.4.2 nathanw 1491: req->bmRequestType, req->bRequest));
1492:
1493: len = UGETW(req->wLength);
1494: value = UGETW(req->wValue);
1495: index = UGETW(req->wIndex);
1496:
1497: if (len != 0)
1.2.4.3 nathanw 1498: buf = KERNADDR(&xfer->dmabuf, 0);
1.2.4.2 nathanw 1499:
1500: #define C(x,y) ((x) | ((y) << 8))
1501: switch(C(req->bRequest, req->bmRequestType)) {
1502: case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
1503: case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
1504: case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
1.2.4.6 nathanw 1505: /*
1.2.4.2 nathanw 1506: * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
1507: * for the integrated root hub.
1508: */
1509: break;
1510: case C(UR_GET_CONFIG, UT_READ_DEVICE):
1511: if (len > 0) {
1512: *(u_int8_t *)buf = sc->sc_conf;
1513: totlen = 1;
1514: }
1515: break;
1516: case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
1517: DPRINTFN(8,("ehci_root_ctrl_control wValue=0x%04x\n", value));
1518: switch(value >> 8) {
1519: case UDESC_DEVICE:
1520: if ((value & 0xff) != 0) {
1521: err = USBD_IOERROR;
1522: goto ret;
1523: }
1524: totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
1525: USETW(ehci_devd.idVendor, sc->sc_id_vendor);
1526: memcpy(buf, &ehci_devd, l);
1527: break;
1.2.4.6 nathanw 1528: /*
1.2.4.2 nathanw 1529: * We can't really operate at another speed, but the spec says
1530: * we need this descriptor.
1531: */
1532: case UDESC_DEVICE_QUALIFIER:
1533: if ((value & 0xff) != 0) {
1534: err = USBD_IOERROR;
1535: goto ret;
1536: }
1537: totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
1538: memcpy(buf, &ehci_odevd, l);
1539: break;
1.2.4.6 nathanw 1540: /*
1.2.4.2 nathanw 1541: * We can't really operate at another speed, but the spec says
1542: * we need this descriptor.
1543: */
1544: case UDESC_OTHER_SPEED_CONFIGURATION:
1545: case UDESC_CONFIG:
1546: if ((value & 0xff) != 0) {
1547: err = USBD_IOERROR;
1548: goto ret;
1549: }
1550: totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
1551: memcpy(buf, &ehci_confd, l);
1552: ((usb_config_descriptor_t *)buf)->bDescriptorType =
1553: value >> 8;
1554: buf = (char *)buf + l;
1555: len -= l;
1556: l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
1557: totlen += l;
1558: memcpy(buf, &ehci_ifcd, l);
1559: buf = (char *)buf + l;
1560: len -= l;
1561: l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
1562: totlen += l;
1563: memcpy(buf, &ehci_endpd, l);
1564: break;
1565: case UDESC_STRING:
1566: if (len == 0)
1567: break;
1568: *(u_int8_t *)buf = 0;
1569: totlen = 1;
1570: switch (value & 0xff) {
1571: case 1: /* Vendor */
1572: totlen = ehci_str(buf, len, sc->sc_vendor);
1573: break;
1574: case 2: /* Product */
1575: totlen = ehci_str(buf, len, "EHCI root hub");
1576: break;
1577: }
1578: break;
1579: default:
1580: err = USBD_IOERROR;
1581: goto ret;
1582: }
1583: break;
1584: case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
1585: if (len > 0) {
1586: *(u_int8_t *)buf = 0;
1587: totlen = 1;
1588: }
1589: break;
1590: case C(UR_GET_STATUS, UT_READ_DEVICE):
1591: if (len > 1) {
1592: USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED);
1593: totlen = 2;
1594: }
1595: break;
1596: case C(UR_GET_STATUS, UT_READ_INTERFACE):
1597: case C(UR_GET_STATUS, UT_READ_ENDPOINT):
1598: if (len > 1) {
1599: USETW(((usb_status_t *)buf)->wStatus, 0);
1600: totlen = 2;
1601: }
1602: break;
1603: case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
1604: if (value >= USB_MAX_DEVICES) {
1605: err = USBD_IOERROR;
1606: goto ret;
1607: }
1608: sc->sc_addr = value;
1609: break;
1610: case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
1611: if (value != 0 && value != 1) {
1612: err = USBD_IOERROR;
1613: goto ret;
1614: }
1615: sc->sc_conf = value;
1616: break;
1617: case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
1618: break;
1619: case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
1620: case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
1621: case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
1622: err = USBD_IOERROR;
1623: goto ret;
1624: case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
1625: break;
1626: case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
1627: break;
1628: /* Hub requests */
1629: case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
1630: break;
1631: case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
1632: DPRINTFN(8, ("ehci_root_ctrl_control: UR_CLEAR_PORT_FEATURE "
1633: "port=%d feature=%d\n",
1634: index, value));
1635: if (index < 1 || index > sc->sc_noport) {
1636: err = USBD_IOERROR;
1637: goto ret;
1638: }
1639: port = EHCI_PORTSC(index);
1640: v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR;
1641: switch(value) {
1642: case UHF_PORT_ENABLE:
1643: EOWRITE4(sc, port, v &~ EHCI_PS_PE);
1644: break;
1645: case UHF_PORT_SUSPEND:
1646: EOWRITE4(sc, port, v &~ EHCI_PS_SUSP);
1647: break;
1648: case UHF_PORT_POWER:
1649: EOWRITE4(sc, port, v &~ EHCI_PS_PP);
1650: break;
1651: case UHF_PORT_TEST:
1652: DPRINTFN(2,("ehci_root_ctrl_transfer: clear port test "
1653: "%d\n", index));
1654: break;
1655: case UHF_PORT_INDICATOR:
1656: DPRINTFN(2,("ehci_root_ctrl_transfer: clear port ind "
1657: "%d\n", index));
1658: EOWRITE4(sc, port, v &~ EHCI_PS_PIC);
1659: break;
1660: case UHF_C_PORT_CONNECTION:
1661: EOWRITE4(sc, port, v | EHCI_PS_CSC);
1662: break;
1663: case UHF_C_PORT_ENABLE:
1664: EOWRITE4(sc, port, v | EHCI_PS_PEC);
1665: break;
1666: case UHF_C_PORT_SUSPEND:
1667: /* how? */
1668: break;
1669: case UHF_C_PORT_OVER_CURRENT:
1670: EOWRITE4(sc, port, v | EHCI_PS_OCC);
1671: break;
1672: case UHF_C_PORT_RESET:
1673: sc->sc_isreset = 0;
1674: break;
1675: default:
1676: err = USBD_IOERROR;
1677: goto ret;
1678: }
1679: #if 0
1680: switch(value) {
1681: case UHF_C_PORT_CONNECTION:
1682: case UHF_C_PORT_ENABLE:
1683: case UHF_C_PORT_SUSPEND:
1684: case UHF_C_PORT_OVER_CURRENT:
1685: case UHF_C_PORT_RESET:
1686: /* Enable RHSC interrupt if condition is cleared. */
1687: if ((OREAD4(sc, port) >> 16) == 0)
1688: ehci_pcd_able(sc, 1);
1689: break;
1690: default:
1691: break;
1692: }
1693: #endif
1694: break;
1695: case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
1696: if (value != 0) {
1697: err = USBD_IOERROR;
1698: goto ret;
1699: }
1700: hubd = ehci_hubd;
1701: hubd.bNbrPorts = sc->sc_noport;
1702: v = EOREAD4(sc, EHCI_HCSPARAMS);
1703: USETW(hubd.wHubCharacteristics,
1704: EHCI_HCS_PPC(v) ? UHD_PWR_INDIVIDUAL : UHD_PWR_NO_SWITCH |
1705: EHCI_HCS_P_INCICATOR(EREAD4(sc, EHCI_HCSPARAMS))
1706: ? UHD_PORT_IND : 0);
1707: hubd.bPwrOn2PwrGood = 200; /* XXX can't find out? */
1.2.4.6 nathanw 1708: for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8)
1.2.4.2 nathanw 1709: hubd.DeviceRemovable[i++] = 0; /* XXX can't find out? */
1710: hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i;
1711: l = min(len, hubd.bDescLength);
1712: totlen = l;
1713: memcpy(buf, &hubd, l);
1714: break;
1715: case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
1716: if (len != 4) {
1717: err = USBD_IOERROR;
1718: goto ret;
1719: }
1720: memset(buf, 0, len); /* ? XXX */
1721: totlen = len;
1722: break;
1723: case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
1724: DPRINTFN(8,("ehci_root_ctrl_transfer: get port status i=%d\n",
1725: index));
1726: if (index < 1 || index > sc->sc_noport) {
1727: err = USBD_IOERROR;
1728: goto ret;
1729: }
1730: if (len != 4) {
1731: err = USBD_IOERROR;
1732: goto ret;
1733: }
1734: v = EOREAD4(sc, EHCI_PORTSC(index));
1735: DPRINTFN(8,("ehci_root_ctrl_transfer: port status=0x%04x\n",
1736: v));
1737: i = UPS_HIGH_SPEED;
1738: if (v & EHCI_PS_CS) i |= UPS_CURRENT_CONNECT_STATUS;
1739: if (v & EHCI_PS_PE) i |= UPS_PORT_ENABLED;
1740: if (v & EHCI_PS_SUSP) i |= UPS_SUSPEND;
1741: if (v & EHCI_PS_OCA) i |= UPS_OVERCURRENT_INDICATOR;
1742: if (v & EHCI_PS_PR) i |= UPS_RESET;
1743: if (v & EHCI_PS_PP) i |= UPS_PORT_POWER;
1744: USETW(ps.wPortStatus, i);
1745: i = 0;
1746: if (v & EHCI_PS_CSC) i |= UPS_C_CONNECT_STATUS;
1747: if (v & EHCI_PS_PEC) i |= UPS_C_PORT_ENABLED;
1748: if (v & EHCI_PS_OCC) i |= UPS_C_OVERCURRENT_INDICATOR;
1749: if (sc->sc_isreset) i |= UPS_C_PORT_RESET;
1750: USETW(ps.wPortChange, i);
1751: l = min(len, sizeof ps);
1752: memcpy(buf, &ps, l);
1753: totlen = l;
1754: break;
1755: case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
1756: err = USBD_IOERROR;
1757: goto ret;
1758: case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
1759: break;
1760: case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
1761: if (index < 1 || index > sc->sc_noport) {
1762: err = USBD_IOERROR;
1763: goto ret;
1764: }
1765: port = EHCI_PORTSC(index);
1766: v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR;
1767: switch(value) {
1768: case UHF_PORT_ENABLE:
1769: EOWRITE4(sc, port, v | EHCI_PS_PE);
1770: break;
1771: case UHF_PORT_SUSPEND:
1772: EOWRITE4(sc, port, v | EHCI_PS_SUSP);
1773: break;
1774: case UHF_PORT_RESET:
1775: DPRINTFN(5,("ehci_root_ctrl_transfer: reset port %d\n",
1776: index));
1777: if (EHCI_PS_IS_LOWSPEED(v)) {
1778: /* Low speed device, give up ownership. */
1779: ehci_disown(sc, index, 1);
1780: break;
1781: }
1782: /* Start reset sequence. */
1783: v &= ~ (EHCI_PS_PE | EHCI_PS_PR);
1784: EOWRITE4(sc, port, v | EHCI_PS_PR);
1785: /* Wait for reset to complete. */
1786: usb_delay_ms(&sc->sc_bus, USB_PORT_ROOT_RESET_DELAY);
1787: if (sc->sc_dying) {
1788: err = USBD_IOERROR;
1789: goto ret;
1790: }
1791: /* Terminate reset sequence. */
1792: EOWRITE4(sc, port, v);
1793: /* Wait for HC to complete reset. */
1794: usb_delay_ms(&sc->sc_bus, EHCI_PORT_RESET_COMPLETE);
1795: if (sc->sc_dying) {
1796: err = USBD_IOERROR;
1797: goto ret;
1798: }
1799: v = EOREAD4(sc, port);
1800: DPRINTF(("ehci after reset, status=0x%08x\n", v));
1801: if (v & EHCI_PS_PR) {
1802: printf("%s: port reset timeout\n",
1803: USBDEVNAME(sc->sc_bus.bdev));
1804: return (USBD_TIMEOUT);
1805: }
1806: if (!(v & EHCI_PS_PE)) {
1807: /* Not a high speed device, give up ownership.*/
1808: ehci_disown(sc, index, 0);
1809: break;
1810: }
1811: sc->sc_isreset = 1;
1812: DPRINTF(("ehci port %d reset, status = 0x%08x\n",
1813: index, v));
1814: break;
1815: case UHF_PORT_POWER:
1816: DPRINTFN(2,("ehci_root_ctrl_transfer: set port power "
1817: "%d\n", index));
1818: EOWRITE4(sc, port, v | EHCI_PS_PP);
1819: break;
1820: case UHF_PORT_TEST:
1821: DPRINTFN(2,("ehci_root_ctrl_transfer: set port test "
1822: "%d\n", index));
1823: break;
1824: case UHF_PORT_INDICATOR:
1825: DPRINTFN(2,("ehci_root_ctrl_transfer: set port ind "
1826: "%d\n", index));
1827: EOWRITE4(sc, port, v | EHCI_PS_PIC);
1828: break;
1829: default:
1830: err = USBD_IOERROR;
1831: goto ret;
1832: }
1833: break;
1834: case C(UR_CLEAR_TT_BUFFER, UT_WRITE_CLASS_OTHER):
1835: case C(UR_RESET_TT, UT_WRITE_CLASS_OTHER):
1836: case C(UR_GET_TT_STATE, UT_READ_CLASS_OTHER):
1837: case C(UR_STOP_TT, UT_WRITE_CLASS_OTHER):
1838: break;
1839: default:
1840: err = USBD_IOERROR;
1841: goto ret;
1842: }
1843: xfer->actlen = totlen;
1844: err = USBD_NORMAL_COMPLETION;
1845: ret:
1846: xfer->status = err;
1847: s = splusb();
1848: usb_transfer_complete(xfer);
1849: splx(s);
1850: return (USBD_IN_PROGRESS);
1851: }
1852:
1853: void
1854: ehci_disown(ehci_softc_t *sc, int index, int lowspeed)
1855: {
1856: int port;
1857: u_int32_t v;
1858:
1859: DPRINTF(("ehci_disown: index=%d lowspeed=%d\n", index, lowspeed));
1860: #ifdef DIAGNOSTIC
1861: if (sc->sc_npcomp != 0) {
1862: int i = (index-1) / sc->sc_npcomp;
1863: if (i >= sc->sc_ncomp)
1864: printf("%s: strange port\n",
1865: USBDEVNAME(sc->sc_bus.bdev));
1866: else
1867: printf("%s: handing over %s speed device on "
1868: "port %d to %s\n",
1869: USBDEVNAME(sc->sc_bus.bdev),
1870: lowspeed ? "low" : "full",
1871: index, USBDEVNAME(sc->sc_comps[i]->bdev));
1872: } else {
1873: printf("%s: npcomp == 0\n", USBDEVNAME(sc->sc_bus.bdev));
1874: }
1875: #endif
1876: port = EHCI_PORTSC(index);
1877: v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR;
1878: EOWRITE4(sc, port, v | EHCI_PS_PO);
1879: }
1880:
1881: /* Abort a root control request. */
1882: Static void
1883: ehci_root_ctrl_abort(usbd_xfer_handle xfer)
1884: {
1885: /* Nothing to do, all transfers are synchronous. */
1886: }
1887:
1888: /* Close the root pipe. */
1889: Static void
1890: ehci_root_ctrl_close(usbd_pipe_handle pipe)
1891: {
1892: DPRINTF(("ehci_root_ctrl_close\n"));
1893: /* Nothing to do. */
1894: }
1895:
1896: void
1897: ehci_root_intr_done(usbd_xfer_handle xfer)
1898: {
1899: xfer->hcpriv = NULL;
1900: }
1901:
1902: Static usbd_status
1903: ehci_root_intr_transfer(usbd_xfer_handle xfer)
1904: {
1905: usbd_status err;
1906:
1907: /* Insert last in queue. */
1908: err = usb_insert_transfer(xfer);
1909: if (err)
1910: return (err);
1911:
1912: /* Pipe isn't running, start first */
1913: return (ehci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
1914: }
1915:
1916: Static usbd_status
1917: ehci_root_intr_start(usbd_xfer_handle xfer)
1918: {
1919: usbd_pipe_handle pipe = xfer->pipe;
1920: ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus;
1921:
1922: if (sc->sc_dying)
1923: return (USBD_IOERROR);
1924:
1925: sc->sc_intrxfer = xfer;
1926:
1927: return (USBD_IN_PROGRESS);
1928: }
1929:
1930: /* Abort a root interrupt request. */
1931: Static void
1932: ehci_root_intr_abort(usbd_xfer_handle xfer)
1933: {
1934: int s;
1935:
1936: if (xfer->pipe->intrxfer == xfer) {
1937: DPRINTF(("ehci_root_intr_abort: remove\n"));
1938: xfer->pipe->intrxfer = NULL;
1939: }
1940: xfer->status = USBD_CANCELLED;
1941: s = splusb();
1942: usb_transfer_complete(xfer);
1943: splx(s);
1944: }
1945:
1946: /* Close the root pipe. */
1947: Static void
1948: ehci_root_intr_close(usbd_pipe_handle pipe)
1949: {
1950: ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus;
1.2.4.6 nathanw 1951:
1.2.4.2 nathanw 1952: DPRINTF(("ehci_root_intr_close\n"));
1953:
1954: sc->sc_intrxfer = NULL;
1955: }
1956:
1957: void
1958: ehci_root_ctrl_done(usbd_xfer_handle xfer)
1959: {
1960: xfer->hcpriv = NULL;
1961: }
1962:
1963: /************************/
1964:
1965: ehci_soft_qh_t *
1966: ehci_alloc_sqh(ehci_softc_t *sc)
1967: {
1968: ehci_soft_qh_t *sqh;
1969: usbd_status err;
1970: int i, offs;
1971: usb_dma_t dma;
1972:
1973: if (sc->sc_freeqhs == NULL) {
1974: DPRINTFN(2, ("ehci_alloc_sqh: allocating chunk\n"));
1975: err = usb_allocmem(&sc->sc_bus, EHCI_SQH_SIZE * EHCI_SQH_CHUNK,
1976: EHCI_PAGE_SIZE, &dma);
1977: #ifdef EHCI_DEBUG
1978: if (err)
1979: printf("ehci_alloc_sqh: usb_allocmem()=%d\n", err);
1980: #endif
1981: if (err)
1982: return (NULL);
1983: for(i = 0; i < EHCI_SQH_CHUNK; i++) {
1984: offs = i * EHCI_SQH_SIZE;
1.2.4.3 nathanw 1985: sqh = KERNADDR(&dma, offs);
1986: sqh->physaddr = DMAADDR(&dma, offs);
1.2.4.2 nathanw 1987: sqh->next = sc->sc_freeqhs;
1988: sc->sc_freeqhs = sqh;
1989: }
1990: }
1991: sqh = sc->sc_freeqhs;
1992: sc->sc_freeqhs = sqh->next;
1993: memset(&sqh->qh, 0, sizeof(ehci_qh_t));
1994: sqh->next = NULL;
1995: return (sqh);
1996: }
1997:
1998: void
1999: ehci_free_sqh(ehci_softc_t *sc, ehci_soft_qh_t *sqh)
2000: {
2001: sqh->next = sc->sc_freeqhs;
2002: sc->sc_freeqhs = sqh;
2003: }
2004:
2005: ehci_soft_qtd_t *
2006: ehci_alloc_sqtd(ehci_softc_t *sc)
2007: {
2008: ehci_soft_qtd_t *sqtd;
2009: usbd_status err;
2010: int i, offs;
2011: usb_dma_t dma;
2012: int s;
2013:
2014: if (sc->sc_freeqtds == NULL) {
2015: DPRINTFN(2, ("ehci_alloc_sqtd: allocating chunk\n"));
2016: err = usb_allocmem(&sc->sc_bus, EHCI_SQTD_SIZE*EHCI_SQTD_CHUNK,
2017: EHCI_PAGE_SIZE, &dma);
2018: #ifdef EHCI_DEBUG
2019: if (err)
2020: printf("ehci_alloc_sqtd: usb_allocmem()=%d\n", err);
2021: #endif
2022: if (err)
2023: return (NULL);
2024: s = splusb();
2025: for(i = 0; i < EHCI_SQTD_CHUNK; i++) {
2026: offs = i * EHCI_SQTD_SIZE;
1.2.4.3 nathanw 2027: sqtd = KERNADDR(&dma, offs);
2028: sqtd->physaddr = DMAADDR(&dma, offs);
1.2.4.2 nathanw 2029: sqtd->nextqtd = sc->sc_freeqtds;
2030: sc->sc_freeqtds = sqtd;
2031: }
2032: splx(s);
2033: }
2034:
2035: s = splusb();
2036: sqtd = sc->sc_freeqtds;
2037: sc->sc_freeqtds = sqtd->nextqtd;
2038: memset(&sqtd->qtd, 0, sizeof(ehci_qtd_t));
2039: sqtd->nextqtd = NULL;
2040: sqtd->xfer = NULL;
2041: splx(s);
2042:
2043: return (sqtd);
2044: }
2045:
2046: void
2047: ehci_free_sqtd(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd)
2048: {
2049: int s;
2050:
2051: s = splusb();
2052: sqtd->nextqtd = sc->sc_freeqtds;
2053: sc->sc_freeqtds = sqtd;
2054: splx(s);
2055: }
2056:
2057: usbd_status
2058: ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc,
2059: int alen, int rd, usbd_xfer_handle xfer,
2060: ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep)
2061: {
2062: ehci_soft_qtd_t *next, *cur;
2063: ehci_physaddr_t dataphys, dataphyspage, dataphyslastpage, nextphys;
2064: u_int32_t qtdstatus;
2065: int len, curlen;
2066: int i;
2067: usb_dma_t *dma = &xfer->dmabuf;
2068:
2069: DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen));
2070:
2071: len = alen;
1.2.4.3 nathanw 2072: dataphys = DMAADDR(dma, 0);
1.2.4.2 nathanw 2073: dataphyslastpage = EHCI_PAGE(dataphys + len - 1);
2074: qtdstatus = htole32(
2075: EHCI_QTD_ACTIVE |
2076: EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) |
2077: EHCI_QTD_SET_CERR(3)
2078: /* IOC set below */
2079: /* BYTES set below */
2080: /* XXX Data toggle */
2081: );
2082:
2083: cur = ehci_alloc_sqtd(sc);
2084: *sp = cur;
2085: if (cur == NULL)
2086: goto nomem;
2087: for (;;) {
2088: dataphyspage = EHCI_PAGE(dataphys);
2089: /* The EHCI hardware can handle at most 5 pages. */
1.2.4.6 nathanw 2090: if (dataphyslastpage - dataphyspage <
1.2.4.2 nathanw 2091: EHCI_QTD_NBUFFERS * EHCI_PAGE_SIZE) {
2092: /* we can handle it in this QTD */
2093: curlen = len;
2094: } else {
2095: /* must use multiple TDs, fill as much as possible. */
1.2.4.6 nathanw 2096: curlen = EHCI_QTD_NBUFFERS * EHCI_PAGE_SIZE -
1.2.4.2 nathanw 2097: EHCI_PAGE_OFFSET(dataphys);
2098: #ifdef DIAGNOSTIC
2099: if (curlen > len) {
2100: printf("ehci_alloc_sqtd_chain: curlen=0x%x "
2101: "len=0x%x offs=0x%x\n", curlen, len,
2102: EHCI_PAGE_OFFSET(dataphys));
2103: printf("lastpage=0x%x page=0x%x phys=0x%x\n",
2104: dataphyslastpage, dataphyspage,
2105: dataphys);
2106: curlen = len;
2107: }
2108: #endif
2109:
2110: /* XXX true for EHCI? */
2111: /* the length must be a multiple of the max size */
2112: curlen -= curlen % UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize);
2113: DPRINTFN(1,("ehci_alloc_sqtd_chain: multiple QTDs, "
2114: "curlen=%d\n", curlen));
2115: #ifdef DIAGNOSTIC
2116: if (curlen == 0)
2117: panic("ehci_alloc_std: curlen == 0\n");
2118: #endif
2119: }
2120: DPRINTFN(4,("ehci_alloc_sqtd_chain: dataphys=0x%08x "
2121: "dataphyslastpage=0x%08x len=%d curlen=%d\n",
2122: dataphys, dataphyslastpage,
2123: len, curlen));
2124: len -= curlen;
2125:
2126: if (len != 0) {
2127: next = ehci_alloc_sqtd(sc);
2128: if (next == NULL)
2129: goto nomem;
2130: nextphys = next->physaddr;
2131: } else {
2132: next = NULL;
2133: nextphys = EHCI_NULL;
2134: }
2135:
2136: for (i = 0; i * EHCI_PAGE_SIZE < curlen; i++) {
2137: ehci_physaddr_t a = dataphys + i * EHCI_PAGE_SIZE;
2138: if (i != 0) /* use offset only in first buffer */
2139: a = EHCI_PAGE(a);
2140: cur->qtd.qtd_buffer[i] = htole32(a);
2141: #ifdef DIAGNOSTIC
2142: if (i >= EHCI_QTD_NBUFFERS) {
2143: printf("ehci_alloc_sqtd_chain: i=%d\n", i);
2144: goto nomem;
2145: }
2146: #endif
2147: }
2148: cur->nextqtd = next;
2149: cur->qtd.qtd_next = cur->qtd.qtd_altnext = htole32(nextphys);
2150: cur->qtd.qtd_status =
2151: qtdstatus | htole32(EHCI_QTD_SET_BYTES(curlen));
2152: cur->xfer = xfer;
2153: cur->len = curlen;
2154: DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n",
2155: dataphys, dataphys + curlen));
2156: if (len == 0)
2157: break;
2158: DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n"));
2159: dataphys += curlen;
2160: cur = next;
2161: }
2162: cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC);
2163: *ep = cur;
2164:
2165: DPRINTFN(10,("ehci_alloc_sqtd_chain: return sqtd=%p sqtdend=%p\n",
2166: *sp, *ep));
2167:
2168: return (USBD_NORMAL_COMPLETION);
2169:
2170: nomem:
2171: /* XXX free chain */
2172: DPRINTFN(-1,("ehci_alloc_sqtd_chain: no memory\n"));
2173: return (USBD_NOMEM);
2174: }
2175:
2176: Static void
2177: ehci_free_sqtd_chain(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd,
2178: ehci_soft_qtd_t *sqtdend)
2179: {
2180: ehci_soft_qtd_t *p;
2181: int i;
2182:
2183: DPRINTFN(10,("ehci_free_sqtd_chain: sqtd=%p sqtdend=%p\n",
2184: sqtd, sqtdend));
2185:
2186: for (i = 0; sqtd != sqtdend; sqtd = p, i++) {
2187: p = sqtd->nextqtd;
2188: ehci_free_sqtd(sc, sqtd);
2189: }
2190: }
2191:
2192: /****************/
2193:
2194: /*
2195: * Close a reqular pipe.
2196: * Assumes that there are no pending transactions.
2197: */
2198: void
2199: ehci_close_pipe(usbd_pipe_handle pipe, ehci_soft_qh_t *head)
2200: {
2201: struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
2202: ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus;
2203: ehci_soft_qh_t *sqh = epipe->sqh;
2204: int s;
2205:
2206: s = splusb();
2207: ehci_rem_qh(sc, sqh, head);
2208: splx(s);
2209: ehci_free_sqh(sc, epipe->sqh);
2210: }
2211:
1.2.4.6 nathanw 2212: /*
1.2.4.2 nathanw 2213: * Abort a device request.
2214: * If this routine is called at splusb() it guarantees that the request
2215: * will be removed from the hardware scheduling and that the callback
2216: * for it will be called with USBD_CANCELLED status.
2217: * It's impossible to guarantee that the requested transfer will not
2218: * have happened since the hardware runs concurrently.
2219: * If the transaction has already happened we rely on the ordinary
2220: * interrupt processing to process it.
2221: * XXX This is most probably wrong.
2222: */
2223: void
2224: ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
2225: {
2226: #define exfer EXFER(xfer)
2227: struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
2228: ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus;
2229: ehci_soft_qh_t *sqh = epipe->sqh;
2230: ehci_soft_qtd_t *sqtd;
2231: ehci_physaddr_t cur;
2232: u_int32_t qhstatus;
2233: int s;
2234: int hit;
2235:
2236: DPRINTF(("ehci_abort_xfer: xfer=%p pipe=%p\n", xfer, epipe));
2237:
2238: if (sc->sc_dying) {
2239: /* If we're dying, just do the software part. */
2240: s = splusb();
2241: xfer->status = status; /* make software ignore it */
2242: usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer);
2243: usb_transfer_complete(xfer);
2244: splx(s);
2245: return;
2246: }
2247:
1.2.4.5 nathanw 2248: if (xfer->device->bus->intr_context || !curproc)
1.2.4.2 nathanw 2249: panic("ehci_abort_xfer: not in process context\n");
2250:
2251: /*
2252: * Step 1: Make interrupt routine and hardware ignore xfer.
2253: */
2254: s = splusb();
2255: xfer->status = status; /* make software ignore it */
2256: usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer);
2257: qhstatus = sqh->qh.qh_qtd.qtd_status;
2258: sqh->qh.qh_qtd.qtd_status = qhstatus | htole32(EHCI_QTD_HALTED);
2259: for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
2260: sqtd->qtd.qtd_status |= htole32(EHCI_QTD_HALTED);
2261: if (sqtd == exfer->sqtdend)
2262: break;
2263: }
2264: splx(s);
2265:
1.2.4.6 nathanw 2266: /*
1.2.4.2 nathanw 2267: * Step 2: Wait until we know hardware has finished any possible
2268: * use of the xfer. Also make sure the soft interrupt routine
2269: * has run.
2270: */
2271: ehci_sync_hc(sc);
2272: s = splusb();
2273: sc->sc_softwake = 1;
2274: usb_schedsoftintr(&sc->sc_bus);
2275: tsleep(&sc->sc_softwake, PZERO, "ehciab", 0);
2276: splx(s);
1.2.4.6 nathanw 2277:
2278: /*
1.2.4.2 nathanw 2279: * Step 3: Remove any vestiges of the xfer from the hardware.
2280: * The complication here is that the hardware may have executed
2281: * beyond the xfer we're trying to abort. So as we're scanning
2282: * the TDs of this xfer we check if the hardware points to
2283: * any of them.
2284: */
2285: s = splusb(); /* XXX why? */
2286: cur = EHCI_LINK_ADDR(le32toh(sqh->qh.qh_curqtd));
2287: hit = 0;
2288: for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
2289: hit |= cur == sqtd->physaddr;
2290: if (sqtd == exfer->sqtdend)
2291: break;
2292: }
2293: sqtd = sqtd->nextqtd;
2294: /* Zap curqtd register if hardware pointed inside the xfer. */
2295: if (hit && sqtd != NULL) {
2296: DPRINTFN(1,("ehci_abort_xfer: cur=0x%08x\n", sqtd->physaddr));
2297: sqh->qh.qh_curqtd = htole32(sqtd->physaddr); /* unlink qTDs */
2298: sqh->qh.qh_qtd.qtd_status = qhstatus;
2299: } else {
2300: DPRINTFN(1,("ehci_abort_xfer: no hit\n"));
2301: }
2302:
2303: /*
2304: * Step 4: Execute callback.
2305: */
2306: #ifdef DIAGNOSTIC
2307: exfer->isdone = 1;
2308: #endif
2309: usb_transfer_complete(xfer);
2310:
2311: splx(s);
2312: #undef exfer
2313: }
2314:
2315: void
2316: ehci_timeout(void *addr)
2317: {
2318: struct ehci_xfer *exfer = addr;
2319: struct ehci_pipe *epipe = (struct ehci_pipe *)exfer->xfer.pipe;
2320: ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus;
2321:
2322: DPRINTF(("ehci_timeout: exfer=%p\n", exfer));
2323: #ifdef USB_DEBUG
2324: if (ehcidebug > 1)
2325: usbd_dump_pipe(exfer->xfer.pipe);
2326: #endif
2327:
2328: if (sc->sc_dying) {
2329: ehci_abort_xfer(&exfer->xfer, USBD_TIMEOUT);
2330: return;
2331: }
2332:
2333: /* Execute the abort in a process context. */
2334: usb_init_task(&exfer->abort_task, ehci_timeout_task, addr);
2335: usb_add_task(exfer->xfer.pipe->device, &exfer->abort_task);
2336: }
2337:
2338: void
2339: ehci_timeout_task(void *addr)
2340: {
2341: usbd_xfer_handle xfer = addr;
2342: int s;
2343:
2344: DPRINTF(("ehci_timeout_task: xfer=%p\n", xfer));
2345:
2346: s = splusb();
2347: ehci_abort_xfer(xfer, USBD_TIMEOUT);
2348: splx(s);
2349: }
2350:
2351: /************************/
2352:
2353: Static usbd_status
2354: ehci_device_ctrl_transfer(usbd_xfer_handle xfer)
2355: {
2356: usbd_status err;
2357:
2358: /* Insert last in queue. */
2359: err = usb_insert_transfer(xfer);
2360: if (err)
2361: return (err);
2362:
2363: /* Pipe isn't running, start first */
2364: return (ehci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
2365: }
2366:
2367: Static usbd_status
2368: ehci_device_ctrl_start(usbd_xfer_handle xfer)
2369: {
2370: ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
2371: usbd_status err;
2372:
2373: if (sc->sc_dying)
2374: return (USBD_IOERROR);
2375:
2376: #ifdef DIAGNOSTIC
2377: if (!(xfer->rqflags & URQ_REQUEST)) {
2378: /* XXX panic */
2379: printf("ehci_device_ctrl_transfer: not a request\n");
2380: return (USBD_INVAL);
2381: }
2382: #endif
2383:
2384: err = ehci_device_request(xfer);
2385: if (err)
2386: return (err);
2387:
2388: if (sc->sc_bus.use_polling)
2389: ehci_waitintr(sc, xfer);
2390: return (USBD_IN_PROGRESS);
2391: }
2392:
2393: void
2394: ehci_device_ctrl_done(usbd_xfer_handle xfer)
2395: {
2396: struct ehci_xfer *ex = EXFER(xfer);
2397: ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
2398: /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
2399:
2400: DPRINTFN(10,("ehci_ctrl_done: xfer=%p\n", xfer));
2401:
2402: #ifdef DIAGNOSTIC
2403: if (!(xfer->rqflags & URQ_REQUEST)) {
2404: panic("ehci_ctrl_done: not a request\n");
2405: }
2406: #endif
2407:
2408: if (xfer->status != USBD_NOMEM) {
2409: ehci_del_intr_list(ex); /* remove from active list */
2410: ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
2411: }
2412:
2413: DPRINTFN(5, ("ehci_ctrl_done: length=%d\n", xfer->actlen));
2414: }
2415:
2416: /* Abort a device control request. */
2417: Static void
2418: ehci_device_ctrl_abort(usbd_xfer_handle xfer)
2419: {
2420: DPRINTF(("ehci_device_ctrl_abort: xfer=%p\n", xfer));
2421: ehci_abort_xfer(xfer, USBD_CANCELLED);
2422: }
2423:
2424: /* Close a device control pipe. */
2425: Static void
2426: ehci_device_ctrl_close(usbd_pipe_handle pipe)
2427: {
2428: ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus;
2429: /*struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;*/
2430:
2431: DPRINTF(("ehci_device_ctrl_close: pipe=%p\n", pipe));
2432: ehci_close_pipe(pipe, sc->sc_async_head);
2433: }
2434:
2435: usbd_status
2436: ehci_device_request(usbd_xfer_handle xfer)
2437: {
2438: #define exfer EXFER(xfer)
2439: struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
2440: usb_device_request_t *req = &xfer->request;
2441: usbd_device_handle dev = epipe->pipe.device;
2442: ehci_softc_t *sc = (ehci_softc_t *)dev->bus;
2443: int addr = dev->address;
2444: ehci_soft_qtd_t *setup, *stat, *next;
2445: ehci_soft_qh_t *sqh;
2446: int isread;
2447: int len;
2448: usbd_status err;
2449: int s;
2450:
2451: isread = req->bmRequestType & UT_READ;
2452: len = UGETW(req->wLength);
2453:
2454: DPRINTFN(3,("ehci_device_control type=0x%02x, request=0x%02x, "
2455: "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
2456: req->bmRequestType, req->bRequest, UGETW(req->wValue),
1.2.4.6 nathanw 2457: UGETW(req->wIndex), len, addr,
1.2.4.2 nathanw 2458: epipe->pipe.endpoint->edesc->bEndpointAddress));
2459:
2460: setup = ehci_alloc_sqtd(sc);
2461: if (setup == NULL) {
2462: err = USBD_NOMEM;
2463: goto bad1;
2464: }
2465: stat = ehci_alloc_sqtd(sc);
2466: if (stat == NULL) {
2467: err = USBD_NOMEM;
2468: goto bad2;
2469: }
2470:
2471: sqh = epipe->sqh;
2472: epipe->u.ctl.length = len;
2473:
1.2.4.6 nathanw 2474: /* XXX
1.2.4.2 nathanw 2475: * Since we're messing with the QH we must know the HC is in sync.
2476: * This needs to go away since it slows down control transfers.
2477: * Removing it entails:
2478: * - fill the QH only once with addr & wMaxPacketSize
2479: * - put the correct data toggles in the qtds and set DTC
2480: */
2481: /* ehci_sync_hc(sc); */
2482: /* Update device address and length since they may have changed. */
2483: /* XXX This only needs to be done once, but it's too early in open. */
2484: /* XXXX Should not touch ED here! */
1.2.4.6 nathanw 2485: sqh->qh.qh_endp =
1.2.4.2 nathanw 2486: (sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QG_MPLMASK))) |
2487: htole32(
2488: EHCI_QH_SET_ADDR(addr) |
2489: /* EHCI_QH_DTC | */
2490: EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize))
2491: );
2492: /* Clear toggle */
2493: sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE);
2494:
2495: /* Set up data transaction */
2496: if (len != 0) {
2497: ehci_soft_qtd_t *end;
2498:
2499: err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
2500: &next, &end);
2501: if (err)
2502: goto bad3;
2503: end->nextqtd = stat;
1.2.4.6 nathanw 2504: end->qtd.qtd_next =
1.2.4.2 nathanw 2505: end->qtd.qtd_altnext = htole32(stat->physaddr);
2506: /* Start toggle at 1. */
2507: /*next->qtd.td_flags |= htole32(EHCI_QTD_TOGGLE);*/
2508: } else {
2509: next = stat;
2510: }
2511:
1.2.4.3 nathanw 2512: memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req);
1.2.4.2 nathanw 2513:
2514: setup->qtd.qtd_status = htole32(
2515: EHCI_QTD_ACTIVE |
2516: EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) |
2517: EHCI_QTD_SET_CERR(3) |
2518: EHCI_QTD_SET_BYTES(sizeof *req)
2519: );
1.2.4.3 nathanw 2520: setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->u.ctl.reqdma, 0));
1.2.4.2 nathanw 2521: setup->nextqtd = next;
2522: setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr);
2523: setup->xfer = xfer;
2524: setup->len = sizeof *req;
2525:
2526: stat->qtd.qtd_status = htole32(
2527: EHCI_QTD_ACTIVE |
2528: EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) |
2529: EHCI_QTD_SET_CERR(3) |
2530: EHCI_QTD_IOC
2531: );
2532: stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */
2533: stat->nextqtd = NULL;
2534: stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL;
2535: stat->xfer = xfer;
2536: stat->len = 0;
2537:
2538: #ifdef EHCI_DEBUG
2539: if (ehcidebug > 5) {
2540: DPRINTF(("ehci_device_request:\n"));
2541: ehci_dump_sqh(sqh);
2542: ehci_dump_sqtds(setup);
2543: }
2544: #endif
2545:
2546: exfer->sqtdstart = setup;
2547: exfer->sqtdend = stat;
2548: #ifdef DIAGNOSTIC
2549: if (!exfer->isdone) {
2550: printf("ehci_device_request: not done, exfer=%p\n", exfer);
2551: }
2552: exfer->isdone = 0;
2553: #endif
2554:
2555: /* Insert qTD in QH list. */
2556: s = splusb();
2557: ehci_set_qh_qtd(sqh, setup);
2558: if (xfer->timeout && !sc->sc_bus.use_polling) {
2559: usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
2560: ehci_timeout, xfer);
2561: }
2562: ehci_add_intr_list(sc, exfer);
2563: xfer->status = USBD_IN_PROGRESS;
2564: splx(s);
2565:
2566: #ifdef EHCI_DEBUG
2567: if (ehcidebug > 10) {
2568: DPRINTF(("ehci_device_request: status=%x\n",
2569: EOREAD4(sc, EHCI_USBSTS)));
2570: delay(10000);
2571: ehci_dump_regs(sc);
2572: ehci_dump_sqh(sc->sc_async_head);
2573: ehci_dump_sqh(sqh);
2574: ehci_dump_sqtds(setup);
2575: }
2576: #endif
2577:
2578: return (USBD_NORMAL_COMPLETION);
2579:
2580: bad3:
2581: ehci_free_sqtd(sc, stat);
2582: bad2:
2583: ehci_free_sqtd(sc, setup);
2584: bad1:
2585: DPRINTFN(-1,("ehci_device_request: no memory\n"));
2586: xfer->status = err;
2587: usb_transfer_complete(xfer);
2588: return (err);
2589: #undef exfer
2590: }
2591:
2592: /************************/
2593:
2594: Static usbd_status
2595: ehci_device_bulk_transfer(usbd_xfer_handle xfer)
2596: {
2597: usbd_status err;
2598:
2599: /* Insert last in queue. */
2600: err = usb_insert_transfer(xfer);
2601: if (err)
2602: return (err);
2603:
2604: /* Pipe isn't running, start first */
2605: return (ehci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
2606: }
2607:
2608: usbd_status
2609: ehci_device_bulk_start(usbd_xfer_handle xfer)
2610: {
2611: #define exfer EXFER(xfer)
2612: struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
2613: usbd_device_handle dev = epipe->pipe.device;
2614: ehci_softc_t *sc = (ehci_softc_t *)dev->bus;
2615: ehci_soft_qtd_t *data, *dataend;
2616: ehci_soft_qh_t *sqh;
2617: usbd_status err;
2618: int len, isread, endpt;
2619: int s;
2620:
2621: DPRINTFN(2, ("ehci_device_bulk_transfer: xfer=%p len=%d flags=%d\n",
2622: xfer, xfer->length, xfer->flags));
2623:
2624: if (sc->sc_dying)
2625: return (USBD_IOERROR);
2626:
2627: #ifdef DIAGNOSTIC
2628: if (xfer->rqflags & URQ_REQUEST)
2629: panic("ehci_device_bulk_transfer: a request\n");
2630: #endif
2631:
2632: len = xfer->length;
2633: endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
2634: isread = UE_GET_DIR(endpt) == UE_DIR_IN;
2635: sqh = epipe->sqh;
2636:
2637: epipe->u.bulk.length = len;
2638:
2639: err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data,
2640: &dataend);
2641: if (err) {
2642: DPRINTFN(-1,("ehci_device_bulk_transfer: no memory\n"));
2643: xfer->status = err;
2644: usb_transfer_complete(xfer);
2645: return (err);
2646: }
2647:
2648: #ifdef EHCI_DEBUG
2649: if (ehcidebug > 5) {
2650: DPRINTF(("ehci_device_bulk_transfer: data(1)\n"));
2651: ehci_dump_sqh(sqh);
2652: ehci_dump_sqtds(data);
2653: }
2654: #endif
2655:
2656: /* Set up interrupt info. */
2657: exfer->sqtdstart = data;
2658: exfer->sqtdend = dataend;
2659: #ifdef DIAGNOSTIC
2660: if (!exfer->isdone) {
2661: printf("ehci_device_bulk_transfer: not done, ex=%p\n", exfer);
2662: }
2663: exfer->isdone = 0;
2664: #endif
2665:
2666: s = splusb();
2667: ehci_set_qh_qtd(sqh, data);
2668: if (xfer->timeout && !sc->sc_bus.use_polling) {
2669: usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
2670: ehci_timeout, xfer);
2671: }
2672: ehci_add_intr_list(sc, exfer);
2673: xfer->status = USBD_IN_PROGRESS;
2674: splx(s);
2675:
2676: #ifdef EHCI_DEBUG
2677: if (ehcidebug > 10) {
2678: DPRINTF(("ehci_device_bulk_transfer: data(2)\n"));
2679: delay(10000);
2680: DPRINTF(("ehci_device_bulk_transfer: data(3)\n"));
2681: ehci_dump_regs(sc);
2682: #if 0
2683: printf("async_head:\n");
2684: ehci_dump_sqh(sc->sc_async_head);
2685: #endif
2686: printf("sqh:\n");
2687: ehci_dump_sqh(sqh);
2688: ehci_dump_sqtds(data);
2689: }
2690: #endif
2691:
2692: if (sc->sc_bus.use_polling)
2693: ehci_waitintr(sc, xfer);
2694:
2695: return (USBD_IN_PROGRESS);
2696: #undef exfer
2697: }
2698:
2699: Static void
2700: ehci_device_bulk_abort(usbd_xfer_handle xfer)
2701: {
2702: DPRINTF(("ehci_device_bulk_abort: xfer=%p\n", xfer));
2703: ehci_abort_xfer(xfer, USBD_CANCELLED);
2704: }
2705:
1.2.4.6 nathanw 2706: /*
1.2.4.2 nathanw 2707: * Close a device bulk pipe.
2708: */
2709: Static void
2710: ehci_device_bulk_close(usbd_pipe_handle pipe)
2711: {
2712: ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus;
2713:
2714: DPRINTF(("ehci_device_bulk_close: pipe=%p\n", pipe));
2715: ehci_close_pipe(pipe, sc->sc_async_head);
2716: }
2717:
2718: void
2719: ehci_device_bulk_done(usbd_xfer_handle xfer)
2720: {
2721: struct ehci_xfer *ex = EXFER(xfer);
2722: ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
2723: /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
2724:
1.2.4.6 nathanw 2725: DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n",
1.2.4.2 nathanw 2726: xfer, xfer->actlen));
2727:
2728: if (xfer->status != USBD_NOMEM) {
2729: ehci_del_intr_list(ex); /* remove from active list */
2730: ehci_free_sqtd_chain(sc, ex->sqtdstart, 0);
2731: }
2732:
2733: DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen));
2734: }
2735:
2736: /************************/
2737:
2738: Static usbd_status ehci_device_intr_transfer(usbd_xfer_handle xfer) { return USBD_IOERROR; }
2739: Static usbd_status ehci_device_intr_start(usbd_xfer_handle xfer) { return USBD_IOERROR; }
2740: Static void ehci_device_intr_abort(usbd_xfer_handle xfer) { }
2741: Static void ehci_device_intr_close(usbd_pipe_handle pipe) { }
2742: Static void ehci_device_intr_done(usbd_xfer_handle xfer) { }
2743:
2744: /************************/
2745:
2746: Static usbd_status ehci_device_isoc_transfer(usbd_xfer_handle xfer) { return USBD_IOERROR; }
2747: Static usbd_status ehci_device_isoc_start(usbd_xfer_handle xfer) { return USBD_IOERROR; }
2748: Static void ehci_device_isoc_abort(usbd_xfer_handle xfer) { }
2749: Static void ehci_device_isoc_close(usbd_pipe_handle pipe) { }
2750: Static void ehci_device_isoc_done(usbd_xfer_handle xfer) { }
CVSweb <webmaster@jp.NetBSD.org>