uhci.c revision 1.83 1 /* $NetBSD: uhci.c,v 1.83 2000/01/28 00:15:54 augustss Exp $ */
2 /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */
3
4 /*
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (augustss (at) carlstedt.se) at
10 * Carlstedt Research & Technology.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 /*
42 * USB Universal Host Controller driver.
43 * Handles e.g. PIIX3 and PIIX4.
44 *
45 * UHCI spec: http://www.intel.com/design/usb/uhci11d.pdf
46 * USB spec: http://www.usb.org/developers/data/usb11.pdf
47 * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
48 * ftp://download.intel.com/design/intarch/datashts/29056201.pdf
49 */
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
54 #include <sys/malloc.h>
55 #if defined(__NetBSD__) || defined(__OpenBSD__)
56 #include <sys/device.h>
57 #include <sys/select.h>
58 #elif defined(__FreeBSD__)
59 #include <sys/module.h>
60 #include <sys/bus.h>
61 #include <machine/bus_pio.h>
62 #if defined(DIAGNOSTIC) && defined(__i386__)
63 #include <machine/cpu.h>
64 #endif
65 #endif
66 #include <sys/proc.h>
67 #include <sys/queue.h>
68
69 #include <machine/bus.h>
70 #include <machine/endian.h>
71
72 #include <dev/usb/usb.h>
73 #include <dev/usb/usbdi.h>
74 #include <dev/usb/usbdivar.h>
75 #include <dev/usb/usb_mem.h>
76 #include <dev/usb/usb_quirks.h>
77
78 #include <dev/usb/uhcireg.h>
79 #include <dev/usb/uhcivar.h>
80
81 #if defined(__FreeBSD__)
82 #include <machine/clock.h>
83
84 #define delay(d) DELAY(d)
85 #endif
86
87 #define MS_TO_TICKS(ms) ((ms) * hz / 1000)
88
89 #if defined(__OpenBSD__)
90 struct cfdriver uhci_cd = {
91 NULL, "uhci", DV_DULL
92 };
93 #endif
94
95 #ifdef UHCI_DEBUG
96 #define DPRINTF(x) if (uhcidebug) printf x
97 #define DPRINTFN(n,x) if (uhcidebug>(n)) printf x
98 int uhcidebug = 0;
99 #else
100 #define DPRINTF(x)
101 #define DPRINTFN(n,x)
102 #endif
103
104 /*
105 * The UHCI controller is little endian, so on big endian machines
106 * the data strored in memory needs to be swapped.
107 */
108 #if BYTE_ORDER == BIG_ENDIAN
109 #define LE(x) (bswap32(x))
110 #else
111 #define LE(x) (x)
112 #endif
113
114 struct uhci_pipe {
115 struct usbd_pipe pipe;
116 uhci_intr_info_t *iinfo;
117 int nexttoggle;
118 /* Info needed for different pipe kinds. */
119 union {
120 /* Control pipe */
121 struct {
122 uhci_soft_qh_t *sqh;
123 usb_dma_t reqdma;
124 uhci_soft_td_t *setup, *stat;
125 u_int length;
126 } ctl;
127 /* Interrupt pipe */
128 struct {
129 int npoll;
130 uhci_soft_qh_t **qhs;
131 } intr;
132 /* Bulk pipe */
133 struct {
134 uhci_soft_qh_t *sqh;
135 u_int length;
136 int isread;
137 } bulk;
138 /* Iso pipe */
139 struct iso {
140 uhci_soft_td_t **stds;
141 int next, inuse;
142 } iso;
143 } u;
144 };
145
146 /*
147 * The uhci_intr_info free list can be global since they contain
148 * no dma specific data. The other free lists do.
149 */
150 LIST_HEAD(, uhci_intr_info) uhci_ii_free;
151
152 static void uhci_busreset __P((uhci_softc_t *));
153 static void uhci_shutdown __P((void *v));
154 static void uhci_power __P((int, void *));
155 static usbd_status uhci_run __P((uhci_softc_t *, int run));
156 static uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *));
157 static void uhci_free_std __P((uhci_softc_t *, uhci_soft_td_t *));
158 static uhci_soft_qh_t *uhci_alloc_sqh __P((uhci_softc_t *));
159 static void uhci_free_sqh __P((uhci_softc_t *, uhci_soft_qh_t *));
160 static uhci_intr_info_t *uhci_alloc_intr_info __P((uhci_softc_t *));
161 static void uhci_free_intr_info __P((uhci_intr_info_t *ii));
162 #if 0
163 static void uhci_enter_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *,
164 uhci_intr_info_t *));
165 static void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *));
166 #endif
167
168 static void uhci_free_std_chain __P((uhci_softc_t *,
169 uhci_soft_td_t *, uhci_soft_td_t *));
170 static usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *,
171 uhci_softc_t *, int, int, u_int16_t, usb_dma_t *,
172 uhci_soft_td_t **, uhci_soft_td_t **));
173 static void uhci_timo __P((void *));
174 static void uhci_waitintr __P((uhci_softc_t *,
175 usbd_xfer_handle));
176 static void uhci_check_intr __P((uhci_softc_t *,
177 uhci_intr_info_t *));
178 static void uhci_idone __P((uhci_intr_info_t *));
179 static void uhci_abort_xfer __P((usbd_xfer_handle,
180 usbd_status status));
181 static void uhci_abort_xfer_end __P((void *v));
182 static void uhci_timeout __P((void *));
183 static void uhci_lock_frames __P((uhci_softc_t *));
184 static void uhci_unlock_frames __P((uhci_softc_t *));
185 static void uhci_add_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *));
186 static void uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *));
187 static void uhci_remove_ctrl __P((uhci_softc_t *,uhci_soft_qh_t *));
188 static void uhci_remove_bulk __P((uhci_softc_t *,uhci_soft_qh_t *));
189 static int uhci_str __P((usb_string_descriptor_t *, int, char *));
190
191 static usbd_status uhci_setup_isoc __P((usbd_pipe_handle pipe));
192 static void uhci_device_isoc_enter __P((usbd_xfer_handle));
193
194 static usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *,
195 u_int32_t));
196 static void uhci_freem __P((struct usbd_bus *, usb_dma_t *));
197
198 static usbd_xfer_handle uhci_allocx __P((struct usbd_bus *));
199 static void uhci_freex __P((struct usbd_bus *, usbd_xfer_handle));
200
201 static usbd_status uhci_device_ctrl_transfer __P((usbd_xfer_handle));
202 static usbd_status uhci_device_ctrl_start __P((usbd_xfer_handle));
203 static void uhci_device_ctrl_abort __P((usbd_xfer_handle));
204 static void uhci_device_ctrl_close __P((usbd_pipe_handle));
205 static void uhci_device_ctrl_done __P((usbd_xfer_handle));
206
207 static usbd_status uhci_device_intr_transfer __P((usbd_xfer_handle));
208 static usbd_status uhci_device_intr_start __P((usbd_xfer_handle));
209 static void uhci_device_intr_abort __P((usbd_xfer_handle));
210 static void uhci_device_intr_close __P((usbd_pipe_handle));
211 static void uhci_device_intr_done __P((usbd_xfer_handle));
212
213 static usbd_status uhci_device_bulk_transfer __P((usbd_xfer_handle));
214 static usbd_status uhci_device_bulk_start __P((usbd_xfer_handle));
215 static void uhci_device_bulk_abort __P((usbd_xfer_handle));
216 static void uhci_device_bulk_close __P((usbd_pipe_handle));
217 static void uhci_device_bulk_done __P((usbd_xfer_handle));
218
219 static usbd_status uhci_device_isoc_transfer __P((usbd_xfer_handle));
220 static usbd_status uhci_device_isoc_start __P((usbd_xfer_handle));
221 static void uhci_device_isoc_abort __P((usbd_xfer_handle));
222 static void uhci_device_isoc_close __P((usbd_pipe_handle));
223 static void uhci_device_isoc_done __P((usbd_xfer_handle));
224
225 static usbd_status uhci_root_ctrl_transfer __P((usbd_xfer_handle));
226 static usbd_status uhci_root_ctrl_start __P((usbd_xfer_handle));
227 static void uhci_root_ctrl_abort __P((usbd_xfer_handle));
228 static void uhci_root_ctrl_close __P((usbd_pipe_handle));
229
230 static usbd_status uhci_root_intr_transfer __P((usbd_xfer_handle));
231 static usbd_status uhci_root_intr_start __P((usbd_xfer_handle));
232 static void uhci_root_intr_abort __P((usbd_xfer_handle));
233 static void uhci_root_intr_close __P((usbd_pipe_handle));
234 static void uhci_root_intr_done __P((usbd_xfer_handle));
235
236 static usbd_status uhci_open __P((usbd_pipe_handle));
237 static void uhci_poll __P((struct usbd_bus *));
238
239 static usbd_status uhci_device_request __P((usbd_xfer_handle xfer));
240
241 static void uhci_add_intr __P((uhci_softc_t *, int,
242 uhci_soft_qh_t *));
243 static void uhci_remove_intr __P((uhci_softc_t *, int,
244 uhci_soft_qh_t *));
245 static usbd_status uhci_device_setintr __P((uhci_softc_t *sc,
246 struct uhci_pipe *pipe, int ival));
247
248 static void uhci_device_clear_toggle __P((usbd_pipe_handle pipe));
249 static void uhci_noop __P((usbd_pipe_handle pipe));
250
251 #ifdef UHCI_DEBUG
252 static void uhci_dumpregs __P((uhci_softc_t *));
253 static void uhci_dump_qhs __P((uhci_soft_qh_t *));
254 static void uhci_dump_qh __P((uhci_soft_qh_t *));
255 static void uhci_dump_tds __P((uhci_soft_td_t *));
256 static void uhci_dump_td __P((uhci_soft_td_t *));
257 #endif
258
259 #define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
260 #define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))
261 #define UREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r))
262 #define UREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r))
263 #define UREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r))
264
265 #define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd)
266 #define UHCISTS(sc) UREAD2(sc, UHCI_STS)
267
268 #define UHCI_RESET_TIMEOUT 100 /* reset timeout */
269
270 #define UHCI_CURFRAME(sc) (UREAD2(sc, UHCI_FRNUM) & UHCI_FRNUM_MASK)
271
272 #define UHCI_INTR_ENDPT 1
273
274 struct usbd_bus_methods uhci_bus_methods = {
275 uhci_open,
276 uhci_poll,
277 uhci_allocm,
278 uhci_freem,
279 uhci_allocx,
280 uhci_freex,
281 };
282
283 struct usbd_pipe_methods uhci_root_ctrl_methods = {
284 uhci_root_ctrl_transfer,
285 uhci_root_ctrl_start,
286 uhci_root_ctrl_abort,
287 uhci_root_ctrl_close,
288 uhci_noop,
289 0,
290 };
291
292 struct usbd_pipe_methods uhci_root_intr_methods = {
293 uhci_root_intr_transfer,
294 uhci_root_intr_start,
295 uhci_root_intr_abort,
296 uhci_root_intr_close,
297 uhci_noop,
298 uhci_root_intr_done,
299 };
300
301 struct usbd_pipe_methods uhci_device_ctrl_methods = {
302 uhci_device_ctrl_transfer,
303 uhci_device_ctrl_start,
304 uhci_device_ctrl_abort,
305 uhci_device_ctrl_close,
306 uhci_noop,
307 uhci_device_ctrl_done,
308 };
309
310 struct usbd_pipe_methods uhci_device_intr_methods = {
311 uhci_device_intr_transfer,
312 uhci_device_intr_start,
313 uhci_device_intr_abort,
314 uhci_device_intr_close,
315 uhci_device_clear_toggle,
316 uhci_device_intr_done,
317 };
318
319 struct usbd_pipe_methods uhci_device_bulk_methods = {
320 uhci_device_bulk_transfer,
321 uhci_device_bulk_start,
322 uhci_device_bulk_abort,
323 uhci_device_bulk_close,
324 uhci_device_clear_toggle,
325 uhci_device_bulk_done,
326 };
327
328 struct usbd_pipe_methods uhci_device_isoc_methods = {
329 uhci_device_isoc_transfer,
330 uhci_device_isoc_start,
331 uhci_device_isoc_abort,
332 uhci_device_isoc_close,
333 uhci_noop,
334 uhci_device_isoc_done,
335 };
336
337 void
338 uhci_busreset(sc)
339 uhci_softc_t *sc;
340 {
341 UHCICMD(sc, UHCI_CMD_GRESET); /* global reset */
342 usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); /* wait a little */
343 UHCICMD(sc, 0); /* do nothing */
344 }
345
346 usbd_status
347 uhci_init(sc)
348 uhci_softc_t *sc;
349 {
350 usbd_status err;
351 int i, j;
352 uhci_soft_qh_t *csqh, *bsqh, *sqh;
353 uhci_soft_td_t *std;
354
355 DPRINTFN(1,("uhci_init: start\n"));
356
357 #ifdef UHCI_DEBUG
358 if (uhcidebug > 2)
359 uhci_dumpregs(sc);
360 #endif
361
362 uhci_run(sc, 0); /* stop the controller */
363 UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */
364
365 uhci_busreset(sc);
366
367 /* Allocate and initialize real frame array. */
368 err = usb_allocmem(&sc->sc_bus,
369 UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t),
370 UHCI_FRAMELIST_ALIGN, &sc->sc_dma);
371 if (err)
372 return (err);
373 sc->sc_pframes = KERNADDR(&sc->sc_dma);
374 UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */
375 UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/
376
377 /* Allocate the dummy QH where bulk traffic will be queued. */
378 bsqh = uhci_alloc_sqh(sc);
379 if (bsqh == NULL)
380 return (USBD_NOMEM);
381 bsqh->qh.qh_hlink = LE(UHCI_PTR_T); /* end of QH chain */
382 bsqh->qh.qh_elink = LE(UHCI_PTR_T);
383 sc->sc_bulk_start = sc->sc_bulk_end = bsqh;
384
385 /* Allocate the dummy QH where control traffic will be queued. */
386 csqh = uhci_alloc_sqh(sc);
387 if (csqh == NULL)
388 return (USBD_NOMEM);
389 csqh->hlink = bsqh;
390 csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q);
391 csqh->qh.qh_elink = LE(UHCI_PTR_T);
392 sc->sc_ctl_start = sc->sc_ctl_end = csqh;
393
394 /*
395 * Make all (virtual) frame list pointers point to the interrupt
396 * queue heads and the interrupt queue heads at the control
397 * queue head and point the physical frame list to the virtual.
398 */
399 for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
400 std = uhci_alloc_std(sc);
401 sqh = uhci_alloc_sqh(sc);
402 if (std == NULL || sqh == NULL)
403 return (USBD_NOMEM);
404 std->link.sqh = sqh;
405 std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q);
406 std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */
407 std->td.td_token = LE(0);
408 std->td.td_buffer = LE(0);
409 sqh->hlink = csqh;
410 sqh->qh.qh_hlink = LE(csqh->physaddr | UHCI_PTR_Q);
411 sqh->elink = 0;
412 sqh->qh.qh_elink = LE(UHCI_PTR_T);
413 sc->sc_vframes[i].htd = std;
414 sc->sc_vframes[i].etd = std;
415 sc->sc_vframes[i].hqh = sqh;
416 sc->sc_vframes[i].eqh = sqh;
417 for (j = i;
418 j < UHCI_FRAMELIST_COUNT;
419 j += UHCI_VFRAMELIST_COUNT)
420 sc->sc_pframes[j] = LE(std->physaddr);
421 }
422
423 LIST_INIT(&sc->sc_intrhead);
424
425 SIMPLEQ_INIT(&sc->sc_free_xfers);
426
427 /* Set up the bus struct. */
428 sc->sc_bus.methods = &uhci_bus_methods;
429 sc->sc_bus.pipe_size = sizeof(struct uhci_pipe);
430
431 sc->sc_suspend = PWR_RESUME;
432 sc->sc_powerhook = powerhook_establish(uhci_power, sc);
433
434 sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc);
435
436 DPRINTFN(1,("uhci_init: enabling\n"));
437 UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
438 UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */
439
440 UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */
441
442 return (uhci_run(sc, 1)); /* and here we go... */
443 }
444
445 #if defined(__NetBSD__) || defined(__OpenBSD__)
446 int
447 uhci_activate(self, act)
448 device_ptr_t self;
449 enum devact act;
450 {
451 struct uhci_softc *sc = (struct uhci_softc *)self;
452 int rv = 0;
453
454 switch (act) {
455 case DVACT_ACTIVATE:
456 return (EOPNOTSUPP);
457 break;
458
459 case DVACT_DEACTIVATE:
460 if (sc->sc_child != NULL)
461 rv = config_deactivate(sc->sc_child);
462 break;
463 }
464 return (rv);
465 }
466
467 int
468 uhci_detach(sc, flags)
469 struct uhci_softc *sc;
470 int flags;
471 {
472 usbd_xfer_handle xfer;
473 int rv = 0;
474
475 if (sc->sc_child != NULL)
476 rv = config_detach(sc->sc_child, flags);
477
478 if (rv != 0)
479 return (rv);
480
481 powerhook_disestablish(sc->sc_powerhook);
482 shutdownhook_disestablish(sc->sc_shutdownhook);
483
484 /* Free all xfers associated with this HC. */
485 for (;;) {
486 xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
487 if (xfer == NULL)
488 break;
489 SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
490 free(xfer, M_USB);
491 }
492
493 /* XXX free other data structures XXX */
494
495 return (rv);
496 }
497 #endif
498
499 usbd_status
500 uhci_allocm(bus, dma, size)
501 struct usbd_bus *bus;
502 usb_dma_t *dma;
503 u_int32_t size;
504 {
505 return (usb_allocmem(&((struct uhci_softc *)bus)->sc_bus, size, 0,
506 dma));
507 }
508
509 void
510 uhci_freem(bus, dma)
511 struct usbd_bus *bus;
512 usb_dma_t *dma;
513 {
514 usb_freemem(&((struct uhci_softc *)bus)->sc_bus, dma);
515 }
516
517 usbd_xfer_handle
518 uhci_allocx(bus)
519 struct usbd_bus *bus;
520 {
521 struct uhci_softc *sc = (struct uhci_softc *)bus;
522 usbd_xfer_handle xfer;
523
524 xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
525 if (xfer != NULL)
526 SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
527 else
528 xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
529 if (xfer != NULL)
530 memset(xfer, 0, sizeof *xfer);
531 return (xfer);
532 }
533
534 void
535 uhci_freex(bus, xfer)
536 struct usbd_bus *bus;
537 usbd_xfer_handle xfer;
538 {
539 struct uhci_softc *sc = (struct uhci_softc *)bus;
540
541 SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
542 }
543
544 /*
545 * Shut down the controller when the system is going down.
546 */
547 void
548 uhci_shutdown(v)
549 void *v;
550 {
551 uhci_softc_t *sc = v;
552
553 DPRINTF(("uhci_shutdown: stopping the HC\n"));
554 uhci_run(sc, 0); /* stop the controller */
555 }
556
557 /*
558 * Handle suspend/resume.
559 *
560 * We need to switch to polling mode here, because this routine is
561 * called from an intterupt context. This is all right since we
562 * are almost suspended anyway.
563 */
564 void
565 uhci_power(why, v)
566 int why;
567 void *v;
568 {
569 uhci_softc_t *sc = v;
570 int cmd;
571 int s;
572
573 s = splusb();
574 cmd = UREAD2(sc, UHCI_CMD);
575
576 DPRINTF(("uhci_power: sc=%p, why=%d (was %d), cmd=0x%x\n",
577 sc, why, sc->sc_suspend, cmd));
578
579 if (why != PWR_RESUME) {
580 #ifdef UHCI_DEBUG
581 if (uhcidebug > 2)
582 uhci_dumpregs(sc);
583 #endif
584 if (sc->sc_has_timo != NULL)
585 usb_untimeout(uhci_timo, sc->sc_has_timo,
586 sc->sc_has_timo->timo_handle);
587 sc->sc_bus.use_polling++;
588 uhci_run(sc, 0); /* stop the controller */
589 UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
590 usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
591 sc->sc_suspend = why;
592 sc->sc_bus.use_polling--;
593 DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
594 } else {
595 /*
596 * XXX We should really do much more here in case the
597 * controller registers have been lost and BIOS has
598 * not restored them.
599 */
600 #ifdef DIAGNOSTIC
601 if (sc->sc_suspend == PWR_RESUME)
602 printf("uhci_power: weird, resume without suspend.\n");
603 #endif
604 sc->sc_bus.use_polling++;
605 sc->sc_suspend = why;
606 if (cmd & UHCI_CMD_RS)
607 uhci_run(sc, 0); /* in case BIOS has started it */
608 UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */
609 usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
610 UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */
611 UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
612 UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */
613 uhci_run(sc, 1); /* and start traffic again */
614 usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
615 sc->sc_bus.use_polling--;
616 if (sc->sc_has_timo != NULL)
617 usb_timeout(uhci_timo, sc->sc_has_timo,
618 sc->sc_ival, sc->sc_has_timo->timo_handle);
619 #ifdef UHCI_DEBUG
620 if (uhcidebug > 2)
621 uhci_dumpregs(sc);
622 #endif
623 }
624 splx(s);
625 }
626
627 #ifdef UHCI_DEBUG
628 static void
629 uhci_dumpregs(sc)
630 uhci_softc_t *sc;
631 {
632 DPRINTFN(-1,("%s regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, "
633 "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
634 USBDEVNAME(sc->sc_bus.bdev),
635 UREAD2(sc, UHCI_CMD),
636 UREAD2(sc, UHCI_STS),
637 UREAD2(sc, UHCI_INTR),
638 UREAD2(sc, UHCI_FRNUM),
639 UREAD4(sc, UHCI_FLBASEADDR),
640 UREAD1(sc, UHCI_SOF),
641 UREAD2(sc, UHCI_PORTSC1),
642 UREAD2(sc, UHCI_PORTSC2)));
643 }
644
645 void
646 uhci_dump_td(p)
647 uhci_soft_td_t *p;
648 {
649 DPRINTFN(-1,("TD(%p) at %08lx = link=0x%08lx status=0x%08lx "
650 "token=0x%08lx buffer=0x%08lx\n",
651 p, (long)p->physaddr,
652 (long)LE(p->td.td_link),
653 (long)LE(p->td.td_status),
654 (long)LE(p->td.td_token),
655 (long)LE(p->td.td_buffer)));
656 DPRINTFN(-1,(" %b %b,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d,"
657 "D=%d,maxlen=%d\n",
658 (int)LE(p->td.td_link),
659 "\20\1T\2Q\3VF",
660 (int)LE(p->td.td_status),
661 "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
662 "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD",
663 UHCI_TD_GET_ERRCNT(LE(p->td.td_status)),
664 UHCI_TD_GET_ACTLEN(LE(p->td.td_status)),
665 UHCI_TD_GET_PID(LE(p->td.td_token)),
666 UHCI_TD_GET_DEVADDR(LE(p->td.td_token)),
667 UHCI_TD_GET_ENDPT(LE(p->td.td_token)),
668 UHCI_TD_GET_DT(LE(p->td.td_token)),
669 UHCI_TD_GET_MAXLEN(LE(p->td.td_token))));
670 }
671
672 void
673 uhci_dump_qh(sqh)
674 uhci_soft_qh_t *sqh;
675 {
676 DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh,
677 (int)sqh->physaddr, LE(sqh->qh.qh_hlink), LE(sqh->qh.qh_elink)));
678 }
679
680
681 #if 0
682 void
683 uhci_dump()
684 {
685 uhci_softc_t *sc = uhci;
686
687 uhci_dumpregs(sc);
688 printf("intrs=%d\n", sc->sc_bus.no_intrs);
689 printf("framelist[i].link = %08x\n", sc->sc_framelist[0].link);
690 uhci_dump_qh(sc->sc_ctl_start->qh.hlink);
691 }
692 #endif
693
694
695 void
696 uhci_dump_qhs(sqh)
697 uhci_soft_qh_t *sqh;
698 {
699 uhci_dump_qh(sqh);
700
701 /* uhci_dump_qhs displays all the QHs and TDs from the given QH onwards
702 * Traverses sideways first, then down.
703 *
704 * QH1
705 * QH2
706 * No QH
707 * TD2.1
708 * TD2.2
709 * TD1.1
710 * etc.
711 *
712 * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1.
713 */
714
715
716 if (sqh->hlink != NULL && !(sqh->qh.qh_hlink & UHCI_PTR_T))
717 uhci_dump_qhs(sqh->hlink);
718 else
719 DPRINTF(("No QH\n"));
720
721 if (sqh->elink != NULL && !(sqh->qh.qh_elink & UHCI_PTR_T))
722 uhci_dump_tds(sqh->elink);
723 else
724 DPRINTF(("No TD\n"));
725 }
726
727 void
728 uhci_dump_tds(std)
729 uhci_soft_td_t *std;
730 {
731 uhci_soft_td_t *td;
732
733 for(td = std; td != NULL; td = td->link.std) {
734 uhci_dump_td(td);
735
736 /* Check whether the link pointer in this TD marks
737 * the link pointer as end of queue. This avoids
738 * printing the free list in case the queue/TD has
739 * already been moved there (seatbelt).
740 */
741 if (td->td.td_link & UHCI_PTR_T ||
742 td->td.td_link == 0)
743 break;
744 }
745 }
746 #endif
747
748 /*
749 * This routine is executed periodically and simulates interrupts
750 * from the root controller interrupt pipe for port status change.
751 */
752 void
753 uhci_timo(addr)
754 void *addr;
755 {
756 usbd_xfer_handle xfer = addr;
757 usbd_pipe_handle pipe = xfer->pipe;
758 uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
759 int s;
760 u_char *p;
761
762 DPRINTFN(20, ("uhci_timo\n"));
763
764 usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
765
766 p = KERNADDR(&xfer->dmabuf);
767 p[0] = 0;
768 if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
769 p[0] |= 1<<1;
770 if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
771 p[0] |= 1<<2;
772 if (p[0] == 0)
773 /* No change, try again in a while */
774 return;
775
776 xfer->actlen = 1;
777 xfer->status = USBD_NORMAL_COMPLETION;
778 s = splusb();
779 xfer->hcpriv = 0;
780 xfer->device->bus->intr_context++;
781 usb_transfer_complete(xfer);
782 xfer->device->bus->intr_context--;
783 splx(s);
784 }
785
786 void
787 uhci_root_intr_done(xfer)
788 usbd_xfer_handle xfer;
789 {
790 }
791
792 void
793 uhci_lock_frames(sc)
794 uhci_softc_t *sc;
795 {
796 int s = splusb();
797
798 while (sc->sc_vflock & UHCI_HAS_LOCK) {
799 sc->sc_vflock |= UHCI_WANT_LOCK;
800 tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0);
801 }
802 sc->sc_vflock = UHCI_HAS_LOCK;
803 splx(s);
804 }
805
806 void
807 uhci_unlock_frames(sc)
808 uhci_softc_t *sc;
809 {
810 int s = splusb();
811
812 sc->sc_vflock &= ~UHCI_HAS_LOCK;
813 if (sc->sc_vflock & UHCI_WANT_LOCK)
814 wakeup(&sc->sc_vflock);
815 splx(s);
816 }
817
818 /*
819 * Allocate an interrupt information struct. A free list is kept
820 * for fast allocation.
821 */
822 uhci_intr_info_t *
823 uhci_alloc_intr_info(sc)
824 uhci_softc_t *sc;
825 {
826 uhci_intr_info_t *ii;
827
828 ii = LIST_FIRST(&uhci_ii_free);
829 if (ii)
830 LIST_REMOVE(ii, list);
831 else {
832 ii = malloc(sizeof(uhci_intr_info_t), M_USBHC, M_NOWAIT);
833 }
834 ii->sc = sc;
835 #if defined(__FreeBSD__)
836 callout_handle_init(&ii->timeout_handle);
837 #endif
838
839 return ii;
840 }
841
842 void
843 uhci_free_intr_info(ii)
844 uhci_intr_info_t *ii;
845 {
846 LIST_INSERT_HEAD(&uhci_ii_free, ii, list); /* and put on free list */
847 }
848
849 /* Add control QH, called at splusb(). */
850 void
851 uhci_add_ctrl(sc, sqh)
852 uhci_softc_t *sc;
853 uhci_soft_qh_t *sqh;
854 {
855 uhci_soft_qh_t *eqh;
856
857 SPLUSBCHECK;
858
859 DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh));
860 eqh = sc->sc_ctl_end;
861 sqh->hlink = eqh->hlink;
862 sqh->qh.qh_hlink = eqh->qh.qh_hlink;
863 eqh->hlink = sqh;
864 eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q);
865 sc->sc_ctl_end = sqh;
866 }
867
868 /* Remove control QH, called at splusb(). */
869 void
870 uhci_remove_ctrl(sc, sqh)
871 uhci_softc_t *sc;
872 uhci_soft_qh_t *sqh;
873 {
874 uhci_soft_qh_t *pqh;
875
876 SPLUSBCHECK;
877
878 DPRINTFN(10, ("uhci_remove_ctrl: sqh=%p\n", sqh));
879 for (pqh = sc->sc_ctl_start; pqh->hlink != sqh; pqh=pqh->hlink)
880 #if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)
881 if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) {
882 printf("uhci_remove_ctrl: QH not found\n");
883 return;
884 }
885 #else
886 ;
887 #endif
888 pqh->hlink = sqh->hlink;
889 pqh->qh.qh_hlink = sqh->qh.qh_hlink;
890 if (sc->sc_ctl_end == sqh)
891 sc->sc_ctl_end = pqh;
892 }
893
894 /* Add bulk QH, called at splusb(). */
895 void
896 uhci_add_bulk(sc, sqh)
897 uhci_softc_t *sc;
898 uhci_soft_qh_t *sqh;
899 {
900 uhci_soft_qh_t *eqh;
901
902 SPLUSBCHECK;
903
904 DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh));
905 eqh = sc->sc_bulk_end;
906 sqh->hlink = eqh->hlink;
907 sqh->qh.qh_hlink = eqh->qh.qh_hlink;
908 eqh->hlink = sqh;
909 eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q);
910 sc->sc_bulk_end = sqh;
911 }
912
913 /* Remove bulk QH, called at splusb(). */
914 void
915 uhci_remove_bulk(sc, sqh)
916 uhci_softc_t *sc;
917 uhci_soft_qh_t *sqh;
918 {
919 uhci_soft_qh_t *pqh;
920
921 SPLUSBCHECK;
922
923 DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
924 for (pqh = sc->sc_bulk_start; pqh->hlink != sqh; pqh = pqh->hlink)
925 #if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)
926 if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) {
927 printf("uhci_remove_bulk: QH not found\n");
928 return;
929 }
930 #else
931 ;
932 #endif
933 pqh->hlink = sqh->hlink;
934 pqh->qh.qh_hlink = sqh->qh.qh_hlink;
935 if (sc->sc_bulk_end == sqh)
936 sc->sc_bulk_end = pqh;
937 }
938
939 int
940 uhci_intr(arg)
941 void *arg;
942 {
943 uhci_softc_t *sc = arg;
944 int status;
945 int ack;
946 uhci_intr_info_t *ii;
947
948 #ifdef UHCI_DEBUG
949 if (uhcidebug > 15) {
950 DPRINTF(("%s: uhci_intr\n", USBDEVNAME(sc->sc_bus.bdev)));
951 uhci_dumpregs(sc);
952 }
953 #endif
954
955 status = UREAD2(sc, UHCI_STS);
956 if (status == 0) /* The interrupt was not for us. */
957 return (0);
958
959 #if defined(DIAGNOSTIC) && defined(__NetBSD__)
960 if (sc->sc_suspend != PWR_RESUME)
961 printf("uhci_intr: suspended sts=0x%x\n", status);
962 #endif
963
964 ack = 0;
965 if (status & UHCI_STS_USBINT)
966 ack |= UHCI_STS_USBINT;
967 if (status & UHCI_STS_USBEI)
968 ack |= UHCI_STS_USBEI;
969 if (status & UHCI_STS_RD) {
970 ack |= UHCI_STS_RD;
971 printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev));
972 }
973 if (status & UHCI_STS_HSE) {
974 ack |= UHCI_STS_HSE;
975 printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev));
976 }
977 if (status & UHCI_STS_HCPE) {
978 ack |= UHCI_STS_HCPE;
979 printf("%s: host controller process error\n",
980 USBDEVNAME(sc->sc_bus.bdev));
981 }
982 if (status & UHCI_STS_HCH) {
983 /* no acknowledge needed */
984 printf("%s: host controller halted\n",
985 USBDEVNAME(sc->sc_bus.bdev));
986 sc->sc_dying = 1;
987 }
988
989 if (ack) /* acknowledge the ints */
990 UWRITE2(sc, UHCI_STS, ack);
991 else /* nothing to acknowledge */
992 return (0);
993
994 sc->sc_bus.intr_context++;
995 sc->sc_bus.no_intrs++;
996
997 /*
998 * Interrupts on UHCI really suck. When the host controller
999 * interrupts because a transfer is completed there is no
1000 * way of knowing which transfer it was. You can scan down
1001 * the TDs and QHs of the previous frame to limit the search,
1002 * but that assumes that the interrupt was not delayed by more
1003 * than 1 ms, which may not always be true (e.g. after debug
1004 * output on a slow console).
1005 * We scan all interrupt descriptors to see if any have
1006 * completed.
1007 */
1008 for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list))
1009 uhci_check_intr(sc, ii);
1010
1011 DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev)));
1012
1013 sc->sc_bus.intr_context--;
1014
1015 return (1);
1016 }
1017
1018 /* Check for an interrupt. */
1019 void
1020 uhci_check_intr(sc, ii)
1021 uhci_softc_t *sc;
1022 uhci_intr_info_t *ii;
1023 {
1024 uhci_soft_td_t *std, *lstd;
1025 u_int32_t status;
1026
1027 DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii));
1028 #ifdef DIAGNOSTIC
1029 if (ii == NULL) {
1030 printf("uhci_check_intr: no ii? %p\n", ii);
1031 return;
1032 }
1033 #endif
1034 if (ii->stdstart == NULL)
1035 return;
1036 lstd = ii->stdend;
1037 #ifdef DIAGNOSTIC
1038 if (lstd == NULL) {
1039 printf("uhci_check_intr: std==0\n");
1040 return;
1041 }
1042 #endif
1043 /*
1044 * If the last TD is still active we need to check whether there
1045 * is a an error somewhere in the middle, or whether there was a
1046 * short packet (SPD and not ACTIVE).
1047 */
1048 if (LE(lstd->td.td_status) & UHCI_TD_ACTIVE) {
1049 DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
1050 for (std = ii->stdstart; std != lstd; std = std->link.std) {
1051 status = LE(std->td.td_status);
1052 /* If there's an active TD the xfer isn't done. */
1053 if (status & UHCI_TD_ACTIVE)
1054 break;
1055 /* Any kind of error makes the xfer done. */
1056 if (status & UHCI_TD_STALLED)
1057 goto done;
1058 /* We want short packets, and it is short: it's done */
1059 if ((status & UHCI_TD_SPD) &&
1060 UHCI_TD_GET_ACTLEN(status) <
1061 UHCI_TD_GET_MAXLEN(LE(std->td.td_token)))
1062 goto done;
1063 }
1064 DPRINTFN(15, ("uhci_check_intr: ii=%p std=%p still active\n",
1065 ii, ii->stdstart));
1066 return;
1067 }
1068 done:
1069 DPRINTFN(15, ("uhci_check_intr: ii=%p done\n", ii));
1070 usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
1071 uhci_idone(ii);
1072 }
1073
1074 /* Called at splusb() */
1075 void
1076 uhci_idone(ii)
1077 uhci_intr_info_t *ii;
1078 {
1079 usbd_xfer_handle xfer = ii->xfer;
1080 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
1081 uhci_soft_td_t *std;
1082 u_int32_t status = 0, nstatus;
1083 int actlen;
1084
1085 #ifdef DIAGNOSTIC
1086 {
1087 int s = splhigh();
1088 if (ii->isdone) {
1089 splx(s);
1090 printf("uhci_idone: ii=%p is done!\n", ii);
1091 return;
1092 }
1093 ii->isdone = 1;
1094 splx(s);
1095 }
1096 #endif
1097
1098 if (xfer->status == USBD_CANCELLED ||
1099 xfer->status == USBD_TIMEOUT) {
1100 DPRINTF(("uhci_idone: aborted xfer=%p\n", xfer));
1101 return;
1102 }
1103
1104 if (xfer->nframes != 0) {
1105 /* Isoc transfer, do things differently. */
1106 uhci_soft_td_t **stds = upipe->u.iso.stds;
1107 int i, n, nframes;
1108
1109 DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii));
1110
1111 nframes = xfer->nframes;
1112 actlen = 0;
1113 n = xfer->hcprivint;
1114 for (i = 0; i < nframes; i++) {
1115 std = stds[n];
1116 #ifdef UHCI_DEBUG
1117 if (uhcidebug > 5) {
1118 DPRINTFN(-1,("uhci_idone: isoc TD %d\n", i));
1119 uhci_dump_td(std);
1120 }
1121 #endif
1122 if (++n >= UHCI_VFRAMELIST_COUNT)
1123 n = 0;
1124 status = LE(std->td.td_status);
1125 actlen += UHCI_TD_GET_ACTLEN(status);
1126 }
1127 upipe->u.iso.inuse -= nframes;
1128 xfer->actlen = actlen;
1129 xfer->status = USBD_NORMAL_COMPLETION;
1130 xfer->hcpriv = ii;
1131 usb_transfer_complete(xfer);
1132 return;
1133 }
1134
1135 #ifdef UHCI_DEBUG
1136 DPRINTFN(10, ("uhci_idone: ii=%p, xfer=%p, pipe=%p ready\n",
1137 ii, xfer, upipe));
1138 if (uhcidebug > 10)
1139 uhci_dump_tds(ii->stdstart);
1140 #endif
1141
1142 /* The transfer is done, compute actual length and status. */
1143 actlen = 0;
1144 for (std = ii->stdstart; std != NULL; std = std->link.std) {
1145 nstatus = LE(std->td.td_status);
1146 if (nstatus & UHCI_TD_ACTIVE)
1147 break;
1148
1149 status = nstatus;
1150 if (UHCI_TD_GET_PID(LE(std->td.td_token)) != UHCI_TD_PID_SETUP)
1151 actlen += UHCI_TD_GET_ACTLEN(status);
1152 }
1153 /* If there are left over TDs we need to update the toggle. */
1154 if (std != NULL)
1155 upipe->nexttoggle = UHCI_TD_GET_DT(LE(std->td.td_token));
1156
1157 status &= UHCI_TD_ERROR;
1158 DPRINTFN(10, ("uhci_check_intr: actlen=%d, status=0x%x\n",
1159 actlen, status));
1160 xfer->actlen = actlen;
1161 if (status != 0) {
1162 DPRINTFN((status == UHCI_TD_STALLED)*10,
1163 ("uhci_idone: error, addr=%d, endpt=0x%02x, "
1164 "status 0x%b\n",
1165 xfer->pipe->device->address,
1166 xfer->pipe->endpoint->edesc->bEndpointAddress,
1167 (int)status,
1168 "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
1169 "STALLED\30ACTIVE"));
1170 if (status == UHCI_TD_STALLED)
1171 xfer->status = USBD_STALLED;
1172 else
1173 xfer->status = USBD_IOERROR; /* more info XXX */
1174 } else {
1175 xfer->status = USBD_NORMAL_COMPLETION;
1176 }
1177 xfer->hcpriv = ii;
1178 usb_transfer_complete(xfer);
1179 }
1180
1181 /*
1182 * Called when a request does not complete.
1183 */
1184 void
1185 uhci_timeout(addr)
1186 void *addr;
1187 {
1188 uhci_intr_info_t *ii = addr;
1189
1190 DPRINTF(("uhci_timeout: ii=%p\n", ii));
1191
1192 #ifdef UHCI_DEBUG
1193 if (uhcidebug > 10)
1194 uhci_dump_tds(ii->stdstart);
1195 #endif
1196
1197 ii->xfer->device->bus->intr_context++;
1198 uhci_abort_xfer(ii->xfer, USBD_TIMEOUT);
1199 ii->xfer->device->bus->intr_context--;
1200 }
1201
1202 /*
1203 * Wait here until controller claims to have an interrupt.
1204 * Then call uhci_intr and return. Use timeout to avoid waiting
1205 * too long.
1206 * Only used during boot when interrupts are not enabled yet.
1207 */
1208 void
1209 uhci_waitintr(sc, xfer)
1210 uhci_softc_t *sc;
1211 usbd_xfer_handle xfer;
1212 {
1213 int timo = xfer->timeout;
1214 uhci_intr_info_t *ii;
1215
1216 DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo));
1217
1218 xfer->status = USBD_IN_PROGRESS;
1219 for (; timo >= 0; timo--) {
1220 usb_delay_ms(&sc->sc_bus, 1);
1221 DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS)));
1222 if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) {
1223 uhci_intr(sc);
1224 if (xfer->status != USBD_IN_PROGRESS)
1225 return;
1226 }
1227 }
1228
1229 /* Timeout */
1230 DPRINTF(("uhci_waitintr: timeout\n"));
1231 for (ii = LIST_FIRST(&sc->sc_intrhead);
1232 ii != NULL && ii->xfer != xfer;
1233 ii = LIST_NEXT(ii, list))
1234 ;
1235 #ifdef DIAGNOSTIC
1236 if (ii == NULL)
1237 panic("uhci_waitintr: lost intr_info\n");
1238 #endif
1239 uhci_idone(ii);
1240 }
1241
1242 void
1243 uhci_poll(bus)
1244 struct usbd_bus *bus;
1245 {
1246 uhci_softc_t *sc = (uhci_softc_t *)bus;
1247
1248 if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT)
1249 uhci_intr(sc);
1250 }
1251
1252 #if 0
1253 void
1254 uhci_reset(p)
1255 void *p;
1256 {
1257 uhci_softc_t *sc = p;
1258 int n;
1259
1260 UHCICMD(sc, UHCI_CMD_HCRESET);
1261 /* The reset bit goes low when the controller is done. */
1262 for (n = 0; n < UHCI_RESET_TIMEOUT &&
1263 (UREAD2(sc, UHCI_CMD) & UHCI_CMD_HCRESET); n++)
1264 delay(100);
1265 if (n >= UHCI_RESET_TIMEOUT)
1266 printf("%s: controller did not reset\n",
1267 USBDEVNAME(sc->sc_bus.bdev));
1268 }
1269 #endif
1270
1271 usbd_status
1272 uhci_run(sc, run)
1273 uhci_softc_t *sc;
1274 int run;
1275 {
1276 int s, n, running;
1277 u_int16_t cmd;
1278
1279 run = run != 0;
1280 s = splusb();
1281 DPRINTF(("uhci_run: setting run=%d\n", run));
1282 cmd = UREAD2(sc, UHCI_CMD);
1283 if (run)
1284 cmd |= UHCI_CMD_RS;
1285 else
1286 cmd &= ~UHCI_CMD_RS;
1287 UHCICMD(sc, cmd);
1288 for(n = 0; n < 10; n++) {
1289 running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH);
1290 /* return when we've entered the state we want */
1291 if (run == running) {
1292 splx(s);
1293 DPRINTF(("uhci_run: done cmd=0x%x sts=0x%x\n",
1294 UREAD2(sc, UHCI_CMD), UREAD2(sc, UHCI_STS)));
1295 return (USBD_NORMAL_COMPLETION);
1296 }
1297 usb_delay_ms(&sc->sc_bus, 1);
1298 }
1299 splx(s);
1300 printf("%s: cannot %s\n", USBDEVNAME(sc->sc_bus.bdev),
1301 run ? "start" : "stop");
1302 return (USBD_IOERROR);
1303 }
1304
1305 /*
1306 * Memory management routines.
1307 * uhci_alloc_std allocates TDs
1308 * uhci_alloc_sqh allocates QHs
1309 * These two routines do their own free list management,
1310 * partly for speed, partly because allocating DMAable memory
1311 * has page size granularaity so much memory would be wasted if
1312 * only one TD/QH (32 bytes) was placed in each allocated chunk.
1313 */
1314
1315 uhci_soft_td_t *
1316 uhci_alloc_std(sc)
1317 uhci_softc_t *sc;
1318 {
1319 uhci_soft_td_t *std;
1320 usbd_status err;
1321 int i, offs;
1322 usb_dma_t dma;
1323
1324 if (sc->sc_freetds == NULL) {
1325 DPRINTFN(2,("uhci_alloc_std: allocating chunk\n"));
1326 err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK,
1327 UHCI_TD_ALIGN, &dma);
1328 if (err)
1329 return (0);
1330 for(i = 0; i < UHCI_STD_CHUNK; i++) {
1331 offs = i * UHCI_STD_SIZE;
1332 std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) +offs);
1333 std->physaddr = DMAADDR(&dma) + offs;
1334 std->link.std = sc->sc_freetds;
1335 sc->sc_freetds = std;
1336 }
1337 }
1338 std = sc->sc_freetds;
1339 sc->sc_freetds = std->link.std;
1340 memset(&std->td, 0, sizeof(uhci_td_t));
1341 return std;
1342 }
1343
1344 void
1345 uhci_free_std(sc, std)
1346 uhci_softc_t *sc;
1347 uhci_soft_td_t *std;
1348 {
1349 #ifdef DIAGNOSTIC
1350 #define TD_IS_FREE 0x12345678
1351 if (std->td.td_token == LE(TD_IS_FREE)) {
1352 printf("uhci_free_std: freeing free TD %p\n", std);
1353 return;
1354 }
1355 std->td.td_token = LE(TD_IS_FREE);
1356 #endif
1357 std->link.std = sc->sc_freetds;
1358 sc->sc_freetds = std;
1359 }
1360
1361 uhci_soft_qh_t *
1362 uhci_alloc_sqh(sc)
1363 uhci_softc_t *sc;
1364 {
1365 uhci_soft_qh_t *sqh;
1366 usbd_status err;
1367 int i, offs;
1368 usb_dma_t dma;
1369
1370 if (sc->sc_freeqhs == NULL) {
1371 DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n"));
1372 err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
1373 UHCI_QH_ALIGN, &dma);
1374 if (err)
1375 return (0);
1376 for(i = 0; i < UHCI_SQH_CHUNK; i++) {
1377 offs = i * UHCI_SQH_SIZE;
1378 sqh = (uhci_soft_qh_t *)((char *)KERNADDR(&dma) +offs);
1379 sqh->physaddr = DMAADDR(&dma) + offs;
1380 sqh->hlink = sc->sc_freeqhs;
1381 sc->sc_freeqhs = sqh;
1382 }
1383 }
1384 sqh = sc->sc_freeqhs;
1385 sc->sc_freeqhs = sqh->hlink;
1386 memset(&sqh->qh, 0, sizeof(uhci_qh_t));
1387 return (sqh);
1388 }
1389
1390 void
1391 uhci_free_sqh(sc, sqh)
1392 uhci_softc_t *sc;
1393 uhci_soft_qh_t *sqh;
1394 {
1395 sqh->hlink = sc->sc_freeqhs;
1396 sc->sc_freeqhs = sqh;
1397 }
1398
1399 #if 0
1400 /*
1401 * Enter a list of transfers onto a control queue.
1402 * Called at splusb()
1403 */
1404 void
1405 uhci_enter_ctl_q(sc, sqh, ii)
1406 uhci_softc_t *sc;
1407 uhci_soft_qh_t *sqh;
1408 uhci_intr_info_t *ii;
1409 {
1410 DPRINTFN(5, ("uhci_enter_ctl_q: sqh=%p\n", sqh));
1411
1412 }
1413 #endif
1414
1415 void
1416 uhci_free_std_chain(sc, std, stdend)
1417 uhci_softc_t *sc;
1418 uhci_soft_td_t *std;
1419 uhci_soft_td_t *stdend;
1420 {
1421 uhci_soft_td_t *p;
1422
1423 for (; std != stdend; std = p) {
1424 p = std->link.std;
1425 uhci_free_std(sc, std);
1426 }
1427 }
1428
1429 usbd_status
1430 uhci_alloc_std_chain(upipe, sc, len, rd, flags, dma, sp, ep)
1431 struct uhci_pipe *upipe;
1432 uhci_softc_t *sc;
1433 int len, rd;
1434 u_int16_t flags;
1435 usb_dma_t *dma;
1436 uhci_soft_td_t **sp, **ep;
1437 {
1438 uhci_soft_td_t *p, *lastp;
1439 uhci_physaddr_t lastlink;
1440 int i, ntd, l, tog, maxp;
1441 u_int32_t status;
1442 int addr = upipe->pipe.device->address;
1443 int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
1444
1445 DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d "
1446 "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len,
1447 upipe->pipe.device->lowspeed, flags));
1448 maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize);
1449 if (maxp == 0) {
1450 printf("uhci_alloc_std_chain: maxp=0\n");
1451 return (USBD_INVAL);
1452 }
1453 ntd = (len + maxp - 1) / maxp;
1454 if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0)
1455 ntd++;
1456 DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd));
1457 if (ntd == 0) {
1458 *sp = *ep = 0;
1459 DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n"));
1460 return (USBD_NORMAL_COMPLETION);
1461 }
1462 tog = upipe->nexttoggle;
1463 if (ntd % 2 == 0)
1464 tog ^= 1;
1465 upipe->nexttoggle = tog ^ 1;
1466 lastp = 0;
1467 lastlink = UHCI_PTR_T;
1468 ntd--;
1469 status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE);
1470 if (upipe->pipe.device->lowspeed)
1471 status |= UHCI_TD_LS;
1472 if (flags & USBD_SHORT_XFER_OK)
1473 status |= UHCI_TD_SPD;
1474 for (i = ntd; i >= 0; i--) {
1475 p = uhci_alloc_std(sc);
1476 if (p == NULL) {
1477 uhci_free_std_chain(sc, lastp, 0);
1478 return (USBD_NOMEM);
1479 }
1480 p->link.std = lastp;
1481 if (lastlink == UHCI_PTR_T)
1482 p->td.td_link = LE(lastlink);
1483 else
1484 p->td.td_link = LE(lastlink|UHCI_PTR_VF);
1485 lastp = p;
1486 lastlink = p->physaddr;
1487 p->td.td_status = LE(status);
1488 if (i == ntd) {
1489 /* last TD */
1490 l = len % maxp;
1491 if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER))
1492 l = maxp;
1493 *ep = p;
1494 } else
1495 l = maxp;
1496 p->td.td_token =
1497 LE(rd ? UHCI_TD_IN (l, endpt, addr, tog) :
1498 UHCI_TD_OUT(l, endpt, addr, tog));
1499 p->td.td_buffer = LE(DMAADDR(dma) + i * maxp);
1500 tog ^= 1;
1501 }
1502 *sp = lastp;
1503 DPRINTFN(10, ("uhci_alloc_std_chain: nexttog=%d\n",
1504 upipe->nexttoggle));
1505 return (USBD_NORMAL_COMPLETION);
1506 }
1507
1508 void
1509 uhci_device_clear_toggle(pipe)
1510 usbd_pipe_handle pipe;
1511 {
1512 struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
1513 upipe->nexttoggle = 0;
1514 }
1515
1516 void
1517 uhci_noop(pipe)
1518 usbd_pipe_handle pipe;
1519 {
1520 }
1521
1522 usbd_status
1523 uhci_device_bulk_transfer(xfer)
1524 usbd_xfer_handle xfer;
1525 {
1526 usbd_status err;
1527
1528 /* Insert last in queue. */
1529 err = usb_insert_transfer(xfer);
1530 if (err)
1531 return (err);
1532
1533 /* Pipe isn't running (otherwise err would be USBD_INPROG),
1534 * start first
1535 */
1536 return (uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
1537 }
1538
1539 usbd_status
1540 uhci_device_bulk_start(xfer)
1541 usbd_xfer_handle xfer;
1542 {
1543 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
1544 usbd_device_handle dev = upipe->pipe.device;
1545 uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
1546 uhci_intr_info_t *ii = upipe->iinfo;
1547 uhci_soft_td_t *data, *dataend;
1548 uhci_soft_qh_t *sqh;
1549 usbd_status err;
1550 int len, isread, endpt;
1551 int s;
1552
1553 DPRINTFN(3, ("uhci_device_bulk_transfer: xfer=%p len=%d flags=%d\n",
1554 xfer, xfer->length, xfer->flags));
1555
1556 if (sc->sc_dying)
1557 return (USBD_IOERROR);
1558
1559 #ifdef DIAGNOSTIC
1560 if (xfer->rqflags & URQ_REQUEST)
1561 panic("uhci_device_bulk_transfer: a request\n");
1562 #endif
1563
1564 len = xfer->length;
1565 endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
1566 isread = UE_GET_DIR(endpt) == UE_DIR_IN;
1567 sqh = upipe->u.bulk.sqh;
1568
1569 upipe->u.bulk.isread = isread;
1570 upipe->u.bulk.length = len;
1571
1572 err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
1573 &xfer->dmabuf, &data, &dataend);
1574 if (err)
1575 return (err);
1576 dataend->td.td_status |= LE(UHCI_TD_IOC);
1577
1578 #ifdef UHCI_DEBUG
1579 if (uhcidebug > 8) {
1580 DPRINTF(("uhci_device_bulk_transfer: data(1)\n"));
1581 uhci_dump_tds(data);
1582 }
1583 #endif
1584
1585 /* Set up interrupt info. */
1586 ii->xfer = xfer;
1587 ii->stdstart = data;
1588 ii->stdend = dataend;
1589 #if defined(__FreeBSD__)
1590 callout_handle_init(&ii->timeout_handle);
1591 #endif
1592 #ifdef DIAGNOSTIC
1593 if (!ii->isdone) {
1594 printf("uhci_device_bulk_transfer: not done, ii=%p\n", ii);
1595 }
1596 ii->isdone = 0;
1597 #endif
1598
1599 sqh->elink = data;
1600 sqh->qh.qh_elink = LE(data->physaddr);
1601 sqh->intr_info = ii;
1602
1603 s = splusb();
1604 uhci_add_bulk(sc, sqh);
1605 LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
1606
1607 if (xfer->timeout && !sc->sc_bus.use_polling) {
1608 usb_timeout(uhci_timeout, ii, MS_TO_TICKS(xfer->timeout),
1609 ii->timeout_handle);
1610 }
1611 splx(s);
1612
1613 #ifdef UHCI_DEBUG
1614 if (uhcidebug > 10) {
1615 DPRINTF(("uhci_device_bulk_transfer: data(2)\n"));
1616 uhci_dump_tds(data);
1617 }
1618 #endif
1619
1620 if (sc->sc_bus.use_polling)
1621 uhci_waitintr(sc, xfer);
1622
1623 return (USBD_IN_PROGRESS);
1624 }
1625
1626 /* Abort a device bulk request. */
1627 void
1628 uhci_device_bulk_abort(xfer)
1629 usbd_xfer_handle xfer;
1630 {
1631 DPRINTF(("uhci_device_bulk_abort:\n"));
1632 uhci_abort_xfer(xfer, USBD_CANCELLED);
1633 }
1634
1635 void
1636 uhci_abort_xfer(xfer, status)
1637 usbd_xfer_handle xfer;
1638 usbd_status status;
1639 {
1640 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
1641 uhci_intr_info_t *ii = upipe->iinfo;
1642 uhci_soft_td_t *std;
1643
1644 DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status));
1645
1646 /* Make interrupt routine ignore it, */
1647 xfer->status = status;
1648
1649 /* don't timeout, */
1650 usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
1651
1652 /* make hardware ignore it, */
1653 for (std = ii->stdstart; std != 0; std = std->link.std)
1654 std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
1655
1656 xfer->hcpriv = ii;
1657
1658 #if 1
1659 /* Make sure hardware has completed. */
1660 if (xfer->device->bus->intr_context) {
1661 /* We have no process context, so we can't use tsleep(). */
1662 timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
1663 } else {
1664 #if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
1665 KASSERT(intr_nesting_level == 0,
1666 ("ohci_abort_req in interrupt context"));
1667 #endif
1668 usb_delay_ms(xfer->pipe->device->bus, 1);
1669 /* and call final part of interrupt handler. */
1670 uhci_abort_xfer_end(xfer);
1671 }
1672 #else
1673 delay(1000);
1674 uhci_abort_xfer_end(xfer);
1675 #endif
1676 }
1677
1678 void
1679 uhci_abort_xfer_end(v)
1680 void *v;
1681 {
1682 usbd_xfer_handle xfer = v;
1683 int s;
1684
1685 s = splusb();
1686 usb_transfer_complete(xfer);
1687 splx(s);
1688 }
1689
1690 /* Close a device bulk pipe. */
1691 void
1692 uhci_device_bulk_close(pipe)
1693 usbd_pipe_handle pipe;
1694 {
1695 struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
1696 usbd_device_handle dev = upipe->pipe.device;
1697 uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
1698
1699 uhci_free_sqh(sc, upipe->u.bulk.sqh);
1700 uhci_free_intr_info(upipe->iinfo);
1701 /* XXX free other resources */
1702 }
1703
1704 usbd_status
1705 uhci_device_ctrl_transfer(xfer)
1706 usbd_xfer_handle xfer;
1707 {
1708 usbd_status err;
1709
1710 /* Insert last in queue. */
1711 err = usb_insert_transfer(xfer);
1712 if (err)
1713 return (err);
1714
1715 /* Pipe isn't running (otherwise err would be USBD_INPROG),
1716 * start first
1717 */
1718 return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
1719 }
1720
1721 usbd_status
1722 uhci_device_ctrl_start(xfer)
1723 usbd_xfer_handle xfer;
1724 {
1725 uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
1726 usbd_status err;
1727
1728 if (sc->sc_dying)
1729 return (USBD_IOERROR);
1730
1731 #ifdef DIAGNOSTIC
1732 if (!(xfer->rqflags & URQ_REQUEST))
1733 panic("uhci_device_ctrl_transfer: not a request\n");
1734 #endif
1735
1736 err = uhci_device_request(xfer);
1737 if (err)
1738 return (err);
1739
1740 if (sc->sc_bus.use_polling)
1741 uhci_waitintr(sc, xfer);
1742 return (USBD_IN_PROGRESS);
1743 }
1744
1745 usbd_status
1746 uhci_device_intr_transfer(xfer)
1747 usbd_xfer_handle xfer;
1748 {
1749 usbd_status err;
1750
1751 /* Insert last in queue. */
1752 err = usb_insert_transfer(xfer);
1753 if (err)
1754 return (err);
1755
1756 /* Pipe isn't running (otherwise err would be USBD_INPROG),
1757 * start first
1758 */
1759 return (uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
1760 }
1761
1762 usbd_status
1763 uhci_device_intr_start(xfer)
1764 usbd_xfer_handle xfer;
1765 {
1766 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
1767 usbd_device_handle dev = upipe->pipe.device;
1768 uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
1769 uhci_intr_info_t *ii = upipe->iinfo;
1770 uhci_soft_td_t *data, *dataend;
1771 uhci_soft_qh_t *sqh;
1772 usbd_status err;
1773 int i, s;
1774
1775 if (sc->sc_dying)
1776 return (USBD_IOERROR);
1777
1778 DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n",
1779 xfer, xfer->length, xfer->flags));
1780
1781 #ifdef DIAGNOSTIC
1782 if (xfer->rqflags & URQ_REQUEST)
1783 panic("uhci_device_intr_transfer: a request\n");
1784 #endif
1785
1786 err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
1787 &xfer->dmabuf, &data, &dataend);
1788 if (err)
1789 return (err);
1790 dataend->td.td_status |= LE(UHCI_TD_IOC);
1791
1792 #ifdef UHCI_DEBUG
1793 if (uhcidebug > 10) {
1794 DPRINTF(("uhci_device_intr_transfer: data(1)\n"));
1795 uhci_dump_tds(data);
1796 uhci_dump_qh(upipe->u.intr.qhs[0]);
1797 }
1798 #endif
1799
1800 s = splusb();
1801 /* Set up interrupt info. */
1802 ii->xfer = xfer;
1803 ii->stdstart = data;
1804 ii->stdend = dataend;
1805 #if defined(__FreeBSD__)
1806 callout_handle_init(&ii->timeout_handle);
1807 #endif
1808 #ifdef DIAGNOSTIC
1809 if (!ii->isdone) {
1810 printf("uhci_device_intr_transfer: not done, ii=%p\n", ii);
1811 }
1812 ii->isdone = 0;
1813 #endif
1814
1815 DPRINTFN(10,("uhci_device_intr_transfer: qhs[0]=%p\n",
1816 upipe->u.intr.qhs[0]));
1817 for (i = 0; i < upipe->u.intr.npoll; i++) {
1818 sqh = upipe->u.intr.qhs[i];
1819 sqh->elink = data;
1820 sqh->qh.qh_elink = LE(data->physaddr);
1821 }
1822 splx(s);
1823
1824 #ifdef UHCI_DEBUG
1825 if (uhcidebug > 10) {
1826 DPRINTF(("uhci_device_intr_transfer: data(2)\n"));
1827 uhci_dump_tds(data);
1828 uhci_dump_qh(upipe->u.intr.qhs[0]);
1829 }
1830 #endif
1831
1832 return (USBD_IN_PROGRESS);
1833 }
1834
1835 /* Abort a device control request. */
1836 void
1837 uhci_device_ctrl_abort(xfer)
1838 usbd_xfer_handle xfer;
1839 {
1840 DPRINTF(("uhci_device_ctrl_abort:\n"));
1841 uhci_abort_xfer(xfer, USBD_CANCELLED);
1842 }
1843
1844 /* Close a device control pipe. */
1845 void
1846 uhci_device_ctrl_close(pipe)
1847 usbd_pipe_handle pipe;
1848 {
1849 struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
1850
1851 uhci_free_intr_info(upipe->iinfo);
1852 /* XXX free other resources? */
1853 }
1854
1855 /* Abort a device interrupt request. */
1856 void
1857 uhci_device_intr_abort(xfer)
1858 usbd_xfer_handle xfer;
1859 {
1860 DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer));
1861 if (xfer->pipe->intrxfer == xfer) {
1862 DPRINTFN(1,("uhci_device_intr_abort: remove\n"));
1863 xfer->pipe->intrxfer = 0;
1864 }
1865 uhci_abort_xfer(xfer, USBD_CANCELLED);
1866 }
1867
1868 /* Close a device interrupt pipe. */
1869 void
1870 uhci_device_intr_close(pipe)
1871 usbd_pipe_handle pipe;
1872 {
1873 struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
1874 uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
1875 int i, s, npoll;
1876
1877 upipe->iinfo->stdstart = 0; /* inactive */
1878
1879 /* Unlink descriptors from controller data structures. */
1880 npoll = upipe->u.intr.npoll;
1881 uhci_lock_frames(sc);
1882 for (i = 0; i < npoll; i++)
1883 uhci_remove_intr(sc, upipe->u.intr.qhs[i]->pos,
1884 upipe->u.intr.qhs[i]);
1885 uhci_unlock_frames(sc);
1886
1887 /*
1888 * We now have to wait for any activity on the physical
1889 * descriptors to stop.
1890 */
1891 usb_delay_ms(&sc->sc_bus, 2);
1892
1893 for(i = 0; i < npoll; i++)
1894 uhci_free_sqh(sc, upipe->u.intr.qhs[i]);
1895 free(upipe->u.intr.qhs, M_USBHC);
1896
1897 s = splusb();
1898 LIST_REMOVE(upipe->iinfo, list); /* remove from active list */
1899 splx(s);
1900 uhci_free_intr_info(upipe->iinfo);
1901
1902 /* XXX free other resources */
1903 }
1904
1905 usbd_status
1906 uhci_device_request(xfer)
1907 usbd_xfer_handle xfer;
1908 {
1909 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
1910 usb_device_request_t *req = &xfer->request;
1911 usbd_device_handle dev = upipe->pipe.device;
1912 uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
1913 int addr = dev->address;
1914 int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
1915 uhci_intr_info_t *ii = upipe->iinfo;
1916 uhci_soft_td_t *setup, *data, *stat, *next, *dataend;
1917 uhci_soft_qh_t *sqh;
1918 int len;
1919 u_int32_t ls;
1920 usbd_status err;
1921 int isread;
1922 int s;
1923
1924 DPRINTFN(3,("uhci_device_control type=0x%02x, request=0x%02x, "
1925 "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
1926 req->bmRequestType, req->bRequest, UGETW(req->wValue),
1927 UGETW(req->wIndex), UGETW(req->wLength),
1928 addr, endpt));
1929
1930 ls = dev->lowspeed ? UHCI_TD_LS : 0;
1931 isread = req->bmRequestType & UT_READ;
1932 len = UGETW(req->wLength);
1933
1934 setup = upipe->u.ctl.setup;
1935 stat = upipe->u.ctl.stat;
1936 sqh = upipe->u.ctl.sqh;
1937
1938 /* Set up data transaction */
1939 if (len != 0) {
1940 upipe->nexttoggle = 1;
1941 err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
1942 &xfer->dmabuf, &data, &dataend);
1943 if (err)
1944 return (err);
1945 next = data;
1946 dataend->link.std = stat;
1947 dataend->td.td_link = LE(stat->physaddr | UHCI_PTR_VF);
1948 } else {
1949 next = stat;
1950 }
1951 upipe->u.ctl.length = len;
1952
1953 memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
1954
1955 setup->link.std = next;
1956 setup->td.td_link = LE(next->physaddr | UHCI_PTR_VF);
1957 setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE);
1958 setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr));
1959 setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma));
1960
1961 stat->link.std = 0;
1962 stat->td.td_link = LE(UHCI_PTR_T);
1963 stat->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls |
1964 UHCI_TD_ACTIVE | UHCI_TD_IOC);
1965 stat->td.td_token =
1966 LE(isread ? UHCI_TD_OUT(0, endpt, addr, 1) :
1967 UHCI_TD_IN (0, endpt, addr, 1));
1968 stat->td.td_buffer = LE(0);
1969
1970 #ifdef UHCI_DEBUG
1971 if (uhcidebug > 10) {
1972 DPRINTF(("uhci_device_request: before transfer\n"));
1973 uhci_dump_tds(setup);
1974 }
1975 #endif
1976
1977 /* Set up interrupt info. */
1978 ii->xfer = xfer;
1979 ii->stdstart = setup;
1980 ii->stdend = stat;
1981 #if defined(__FreeBSD__)
1982 callout_handle_init(&ii->timeout_handle);
1983 #endif
1984 #ifdef DIAGNOSTIC
1985 if (!ii->isdone) {
1986 printf("uhci_device_request: not done, ii=%p\n", ii);
1987 }
1988 ii->isdone = 0;
1989 #endif
1990
1991 sqh->elink = setup;
1992 sqh->qh.qh_elink = LE(setup->physaddr);
1993 sqh->intr_info = ii;
1994
1995 s = splusb();
1996 uhci_add_ctrl(sc, sqh);
1997 LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
1998 #ifdef UHCI_DEBUG
1999 if (uhcidebug > 12) {
2000 uhci_soft_td_t *std;
2001 uhci_soft_qh_t *xqh;
2002 uhci_soft_qh_t *sxqh;
2003 int maxqh = 0;
2004 uhci_physaddr_t link;
2005 DPRINTF(("uhci_enter_ctl_q: follow from [0]\n"));
2006 for (std = sc->sc_vframes[0].htd, link = 0;
2007 (link & UHCI_PTR_Q) == 0;
2008 std = std->link.std) {
2009 link = LE(std->td.td_link);
2010 uhci_dump_td(std);
2011 }
2012 sxqh = (uhci_soft_qh_t *)std;
2013 uhci_dump_qh(sxqh);
2014 for (xqh = sxqh;
2015 xqh != NULL;
2016 xqh = (maxqh++ == 5 || xqh->hlink==sxqh ||
2017 xqh->hlink==xqh ? NULL : xqh->hlink)) {
2018 uhci_dump_qh(xqh);
2019 }
2020 DPRINTF(("Enqueued QH:\n"));
2021 uhci_dump_qh(sqh);
2022 uhci_dump_tds(sqh->elink);
2023 }
2024 #endif
2025 if (xfer->timeout && !sc->sc_bus.use_polling) {
2026 usb_timeout(uhci_timeout, ii,
2027 MS_TO_TICKS(xfer->timeout), ii->timeout_handle);
2028 }
2029 splx(s);
2030
2031 return (USBD_NORMAL_COMPLETION);
2032 }
2033
2034 usbd_status
2035 uhci_device_isoc_transfer(xfer)
2036 usbd_xfer_handle xfer;
2037 {
2038 usbd_status err;
2039
2040 DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer));
2041
2042 /* Put it on our queue, */
2043 err = usb_insert_transfer(xfer);
2044
2045 /* bail out on error, */
2046 if (err && err != USBD_IN_PROGRESS)
2047 return (err);
2048
2049 /* XXX should check inuse here */
2050
2051 /* insert into schedule, */
2052 uhci_device_isoc_enter(xfer);
2053
2054 /* and put on interrupt list if the pipe wasn't running */
2055 if (!err)
2056 uhci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
2057
2058 return (err);
2059 }
2060
2061 void
2062 uhci_device_isoc_enter(xfer)
2063 usbd_xfer_handle xfer;
2064 {
2065 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
2066 usbd_device_handle dev = upipe->pipe.device;
2067 uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
2068 struct iso *iso = &upipe->u.iso;
2069 uhci_soft_td_t *std;
2070 u_int32_t buf, len, status;
2071 int s, i, next, nframes;
2072
2073 DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p "
2074 "nframes=%d\n",
2075 iso->inuse, iso->next, xfer, xfer->nframes));
2076
2077 if (sc->sc_dying)
2078 return;
2079
2080 if (xfer->status == USBD_IN_PROGRESS) {
2081 /* This request has already been entered into the frame list */
2082 /* XXX */
2083 }
2084
2085 #ifdef DIAGNOSTIC
2086 if (iso->inuse >= UHCI_VFRAMELIST_COUNT)
2087 printf("uhci_device_isoc_enter: overflow!\n");
2088 #endif
2089
2090 next = iso->next;
2091 if (next == -1) {
2092 /* Not in use yet, schedule it a few frames ahead. */
2093 next = (UREAD2(sc, UHCI_FRNUM) + 3) % UHCI_VFRAMELIST_COUNT;
2094 DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next));
2095 }
2096
2097 xfer->status = USBD_IN_PROGRESS;
2098 xfer->hcprivint = next;
2099
2100 buf = DMAADDR(&xfer->dmabuf);
2101 status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
2102 UHCI_TD_ACTIVE |
2103 UHCI_TD_IOS));
2104 nframes = xfer->nframes;
2105 s = splusb();
2106 for (i = 0; i < nframes; i++) {
2107 std = iso->stds[next];
2108 if (++next >= UHCI_VFRAMELIST_COUNT)
2109 next = 0;
2110 len = xfer->frlengths[i];
2111 std->td.td_buffer = LE(buf);
2112 if (i == nframes - 1)
2113 status |= LE(UHCI_TD_IOC);
2114 std->td.td_status = status;
2115 std->td.td_token &= LE(~UHCI_TD_MAXLEN_MASK);
2116 std->td.td_token |= LE(UHCI_TD_SET_MAXLEN(len));
2117 #ifdef UHCI_DEBUG
2118 if (uhcidebug > 5) {
2119 DPRINTFN(5,("uhci_device_isoc_enter: TD %d\n", i));
2120 uhci_dump_td(std);
2121 }
2122 #endif
2123 buf += len;
2124 }
2125 iso->next = next;
2126 iso->inuse += xfer->nframes;
2127
2128 splx(s);
2129 }
2130
2131 usbd_status
2132 uhci_device_isoc_start(xfer)
2133 usbd_xfer_handle xfer;
2134 {
2135 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
2136 uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus;
2137 uhci_intr_info_t *ii = upipe->iinfo;
2138 uhci_soft_td_t *end;
2139 int s, i;
2140
2141 if (sc->sc_dying)
2142 return (USBD_IOERROR);
2143
2144 #ifdef DIAGNOSTIC
2145 if (xfer->status != USBD_IN_PROGRESS)
2146 printf("uhci_device_isoc_start: not in progress %p\n", xfer);
2147 #endif
2148
2149 /* Find the last TD */
2150 i = xfer->hcprivint + xfer->nframes;
2151 if (i >= UHCI_VFRAMELIST_COUNT)
2152 i -= UHCI_VFRAMELIST_COUNT;
2153 end = upipe->u.iso.stds[i];
2154
2155 s = splusb();
2156
2157 /* Set up interrupt info. */
2158 ii->xfer = xfer;
2159 ii->stdstart = end;
2160 ii->stdend = end;
2161 #if defined(__FreeBSD__)
2162 callout_handle_init(&ii->timeout_handle);
2163 #endif
2164 #ifdef DIAGNOSTIC
2165 if (!ii->isdone) {
2166 printf("uhci_device_isoc_start: not done, ii=%p\n", ii);
2167 }
2168 ii->isdone = 0;
2169 #endif
2170 LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
2171
2172 splx(s);
2173
2174 return (USBD_IN_PROGRESS);
2175 }
2176
2177 void
2178 uhci_device_isoc_abort(xfer)
2179 usbd_xfer_handle xfer;
2180 {
2181 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
2182 uhci_intr_info_t *ii = upipe->iinfo;
2183 uhci_soft_td_t **stds = upipe->u.iso.stds;
2184 uhci_soft_td_t *std;
2185 int i, n, nframes;
2186
2187 /* Make interrupt routine ignore it, */
2188 xfer->status = USBD_CANCELLED;
2189
2190 /* make hardware ignore it, */
2191 nframes = xfer->nframes;
2192 n = xfer->hcprivint;
2193 for (i = 0; i < nframes; i++) {
2194 std = stds[n];
2195 std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
2196 if (++n >= UHCI_VFRAMELIST_COUNT)
2197 n = 0;
2198 }
2199
2200 xfer->hcpriv = ii;
2201
2202 /* make sure hardware has completed, */
2203 if (xfer->device->bus->intr_context) {
2204 /* We have no process context, so we can't use tsleep(). */
2205 timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
2206 } else {
2207 usb_delay_ms(xfer->pipe->device->bus, 1);
2208 /* and call final part of interrupt handler. */
2209 uhci_abort_xfer_end(xfer);
2210 }
2211 }
2212
2213 void
2214 uhci_device_isoc_close(pipe)
2215 usbd_pipe_handle pipe;
2216 {
2217 struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
2218 usbd_device_handle dev = upipe->pipe.device;
2219 uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
2220 uhci_soft_td_t *std, *vstd;
2221 struct iso *iso;
2222 int i;
2223
2224 /*
2225 * Make sure all TDs are marked as inactive.
2226 * Wait for completion.
2227 * Unschedule.
2228 * Deallocate.
2229 */
2230 iso = &upipe->u.iso;
2231
2232 for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++)
2233 iso->stds[i]->td.td_status &= LE(~UHCI_TD_ACTIVE);
2234 usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */
2235
2236 uhci_lock_frames(sc);
2237 for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
2238 std = iso->stds[i];
2239 for (vstd = sc->sc_vframes[i].htd;
2240 vstd != NULL && vstd->link.std != std;
2241 vstd = vstd->link.std)
2242 ;
2243 if (vstd == NULL) {
2244 /*panic*/
2245 printf("uhci_device_isoc_close: %p not found\n", std);
2246 uhci_unlock_frames(sc);
2247 return;
2248 }
2249 vstd->link = std->link;
2250 vstd->td.td_link = std->td.td_link;
2251 uhci_free_std(sc, std);
2252 }
2253 uhci_unlock_frames(sc);
2254
2255 free(iso->stds, M_USBHC);
2256 }
2257
2258 usbd_status
2259 uhci_setup_isoc(pipe)
2260 usbd_pipe_handle pipe;
2261 {
2262 struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
2263 usbd_device_handle dev = upipe->pipe.device;
2264 uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
2265 int addr = upipe->pipe.device->address;
2266 int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
2267 int rd = UE_GET_DIR(endpt) == UE_DIR_IN;
2268 uhci_soft_td_t *std, *vstd;
2269 u_int32_t token;
2270 struct iso *iso;
2271 int i;
2272
2273 iso = &upipe->u.iso;
2274 iso->stds = malloc(UHCI_VFRAMELIST_COUNT * sizeof (uhci_soft_td_t *),
2275 M_USBHC, M_WAITOK);
2276
2277 token = LE(rd ? UHCI_TD_IN (0, endpt, addr, 0) :
2278 UHCI_TD_OUT(0, endpt, addr, 0));
2279
2280 /* Allocate the TDs and mark as inactive; */
2281 for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
2282 std = uhci_alloc_std(sc);
2283 if (std == 0)
2284 goto bad;
2285 std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */
2286 std->td.td_token = token;
2287 iso->stds[i] = std;
2288 }
2289
2290 /* Insert TDs into schedule. */
2291 uhci_lock_frames(sc);
2292 for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
2293 std = iso->stds[i];
2294 vstd = sc->sc_vframes[i].htd;
2295 std->link = vstd->link;
2296 std->td.td_link = vstd->td.td_link;
2297 vstd->link.std = std;
2298 vstd->td.td_link = LE(std->physaddr);
2299 }
2300 uhci_unlock_frames(sc);
2301
2302 iso->next = -1;
2303 iso->inuse = 0;
2304
2305 return (USBD_NORMAL_COMPLETION);
2306
2307 bad:
2308 while (--i >= 0)
2309 uhci_free_std(sc, iso->stds[i]);
2310 free(iso->stds, M_USBHC);
2311 return (USBD_NOMEM);
2312 }
2313
2314 void
2315 uhci_device_isoc_done(xfer)
2316 usbd_xfer_handle xfer;
2317 {
2318 uhci_intr_info_t *ii = xfer->hcpriv;
2319
2320 DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen));
2321
2322 /* Turn off the interrupt since it is active even if the TD is not. */
2323 ii->stdend->td.td_status &= LE(~UHCI_TD_IOC);
2324
2325 LIST_REMOVE(ii, list); /* remove from active list */
2326 }
2327
2328 void
2329 uhci_device_intr_done(xfer)
2330 usbd_xfer_handle xfer;
2331 {
2332 uhci_intr_info_t *ii = xfer->hcpriv;
2333 uhci_softc_t *sc = ii->sc;
2334 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
2335 uhci_soft_qh_t *sqh;
2336 int i, npoll;
2337
2338 DPRINTFN(5, ("uhci_intr_done: length=%d\n", xfer->actlen));
2339
2340 npoll = upipe->u.intr.npoll;
2341 for(i = 0; i < npoll; i++) {
2342 sqh = upipe->u.intr.qhs[i];
2343 sqh->elink = 0;
2344 sqh->qh.qh_elink = LE(UHCI_PTR_T);
2345 }
2346 uhci_free_std_chain(sc, ii->stdstart, 0);
2347
2348 /* XXX Wasteful. */
2349 if (xfer->pipe->repeat) {
2350 uhci_soft_td_t *data, *dataend;
2351
2352 /* This alloc cannot fail since we freed the chain above. */
2353 uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
2354 &xfer->dmabuf, &data, &dataend);
2355 dataend->td.td_status |= LE(UHCI_TD_IOC);
2356
2357 #ifdef UHCI_DEBUG
2358 if (uhcidebug > 10) {
2359 DPRINTF(("uhci_device_intr_done: data(1)\n"));
2360 uhci_dump_tds(data);
2361 uhci_dump_qh(upipe->u.intr.qhs[0]);
2362 }
2363 #endif
2364
2365 ii->stdstart = data;
2366 ii->stdend = dataend;
2367 #if defined(__FreeBSD__)
2368 callout_handle_init(&ii->timeout_handle);
2369 #endif
2370 #ifdef DIAGNOSTIC
2371 if (!ii->isdone) {
2372 printf("uhci_device_intr_done: not done, ii=%p\n", ii);
2373 }
2374 ii->isdone = 0;
2375 #endif
2376 for (i = 0; i < npoll; i++) {
2377 sqh = upipe->u.intr.qhs[i];
2378 sqh->elink = data;
2379 sqh->qh.qh_elink = LE(data->physaddr);
2380 }
2381 } else {
2382 ii->stdstart = 0; /* mark as inactive */
2383 }
2384 }
2385
2386 /* Deallocate request data structures */
2387 void
2388 uhci_device_ctrl_done(xfer)
2389 usbd_xfer_handle xfer;
2390 {
2391 uhci_intr_info_t *ii = xfer->hcpriv;
2392 uhci_softc_t *sc = ii->sc;
2393 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
2394
2395 #ifdef DIAGNOSTIC
2396 if (!(xfer->rqflags & URQ_REQUEST))
2397 panic("uhci_ctrl_done: not a request\n");
2398 #endif
2399
2400 LIST_REMOVE(ii, list); /* remove from active list */
2401
2402 uhci_remove_ctrl(sc, upipe->u.ctl.sqh);
2403
2404 if (upipe->u.ctl.length != 0)
2405 uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
2406
2407 DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", xfer->actlen));
2408 }
2409
2410 /* Deallocate request data structures */
2411 void
2412 uhci_device_bulk_done(xfer)
2413 usbd_xfer_handle xfer;
2414 {
2415 uhci_intr_info_t *ii = xfer->hcpriv;
2416 uhci_softc_t *sc = ii->sc;
2417 struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
2418
2419 LIST_REMOVE(ii, list); /* remove from active list */
2420
2421 uhci_remove_bulk(sc, upipe->u.bulk.sqh);
2422
2423 uhci_free_std_chain(sc, ii->stdstart, 0);
2424
2425 DPRINTFN(5, ("uhci_bulk_done: length=%d\n", xfer->actlen));
2426 }
2427
2428 /* Add interrupt QH, called with vflock. */
2429 void
2430 uhci_add_intr(sc, n, sqh)
2431 uhci_softc_t *sc;
2432 int n;
2433 uhci_soft_qh_t *sqh;
2434 {
2435 struct uhci_vframe *vf = &sc->sc_vframes[n];
2436 uhci_soft_qh_t *eqh;
2437
2438 DPRINTFN(4, ("uhci_add_intr: n=%d sqh=%p\n", n, sqh));
2439 eqh = vf->eqh;
2440 sqh->hlink = eqh->hlink;
2441 sqh->qh.qh_hlink = eqh->qh.qh_hlink;
2442 eqh->hlink = sqh;
2443 eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q);
2444 vf->eqh = sqh;
2445 vf->bandwidth++;
2446 }
2447
2448 /* Remove interrupt QH, called with vflock. */
2449 void
2450 uhci_remove_intr(sc, n, sqh)
2451 uhci_softc_t *sc;
2452 int n;
2453 uhci_soft_qh_t *sqh;
2454 {
2455 struct uhci_vframe *vf = &sc->sc_vframes[n];
2456 uhci_soft_qh_t *pqh;
2457
2458 DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", n, sqh));
2459
2460 for (pqh = vf->hqh; pqh->hlink != sqh; pqh = pqh->hlink)
2461 #if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)
2462 if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) {
2463 DPRINTF(("uhci_remove_intr: QH not found\n"));
2464 return;
2465 }
2466 #else
2467 ;
2468 #endif
2469 pqh->hlink = sqh->hlink;
2470 pqh->qh.qh_hlink = sqh->qh.qh_hlink;
2471 if (vf->eqh == sqh)
2472 vf->eqh = pqh;
2473 vf->bandwidth--;
2474 }
2475
2476 usbd_status
2477 uhci_device_setintr(sc, upipe, ival)
2478 uhci_softc_t *sc;
2479 struct uhci_pipe *upipe;
2480 int ival;
2481 {
2482 uhci_soft_qh_t *sqh;
2483 int i, npoll, s;
2484 u_int bestbw, bw, bestoffs, offs;
2485
2486 DPRINTFN(2, ("uhci_setintr: pipe=%p\n", upipe));
2487 if (ival == 0) {
2488 printf("uhci_setintr: 0 interval\n");
2489 return (USBD_INVAL);
2490 }
2491
2492 if (ival > UHCI_VFRAMELIST_COUNT)
2493 ival = UHCI_VFRAMELIST_COUNT;
2494 npoll = (UHCI_VFRAMELIST_COUNT + ival - 1) / ival;
2495 DPRINTFN(2, ("uhci_setintr: ival=%d npoll=%d\n", ival, npoll));
2496
2497 upipe->u.intr.npoll = npoll;
2498 upipe->u.intr.qhs =
2499 malloc(npoll * sizeof(uhci_soft_qh_t *), M_USBHC, M_WAITOK);
2500
2501 /*
2502 * Figure out which offset in the schedule that has most
2503 * bandwidth left over.
2504 */
2505 #define MOD(i) ((i) & (UHCI_VFRAMELIST_COUNT-1))
2506 for (bestoffs = offs = 0, bestbw = ~0; offs < ival; offs++) {
2507 for (bw = i = 0; i < npoll; i++)
2508 bw += sc->sc_vframes[MOD(i * ival + offs)].bandwidth;
2509 if (bw < bestbw) {
2510 bestbw = bw;
2511 bestoffs = offs;
2512 }
2513 }
2514 DPRINTFN(1, ("uhci_setintr: bw=%d offs=%d\n", bestbw, bestoffs));
2515
2516 upipe->iinfo->stdstart = 0;
2517 for(i = 0; i < npoll; i++) {
2518 upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc);
2519 sqh->elink = 0;
2520 sqh->qh.qh_elink = LE(UHCI_PTR_T);
2521 sqh->pos = MOD(i * ival + bestoffs);
2522 sqh->intr_info = upipe->iinfo;
2523 }
2524 #undef MOD
2525
2526 s = splusb();
2527 LIST_INSERT_HEAD(&sc->sc_intrhead, upipe->iinfo, list);
2528 splx(s);
2529
2530 uhci_lock_frames(sc);
2531 /* Enter QHs into the controller data structures. */
2532 for(i = 0; i < npoll; i++)
2533 uhci_add_intr(sc, upipe->u.intr.qhs[i]->pos,
2534 upipe->u.intr.qhs[i]);
2535 uhci_unlock_frames(sc);
2536
2537 DPRINTFN(5, ("uhci_setintr: returns %p\n", upipe));
2538 return (USBD_NORMAL_COMPLETION);
2539 }
2540
2541 /* Open a new pipe. */
2542 usbd_status
2543 uhci_open(pipe)
2544 usbd_pipe_handle pipe;
2545 {
2546 uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
2547 struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
2548 usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
2549 usbd_status err;
2550 int ival;
2551
2552 DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
2553 pipe, pipe->device->address,
2554 ed->bEndpointAddress, sc->sc_addr));
2555 if (pipe->device->address == sc->sc_addr) {
2556 switch (ed->bEndpointAddress) {
2557 case USB_CONTROL_ENDPOINT:
2558 pipe->methods = &uhci_root_ctrl_methods;
2559 break;
2560 case UE_DIR_IN | UHCI_INTR_ENDPT:
2561 pipe->methods = &uhci_root_intr_methods;
2562 break;
2563 default:
2564 return (USBD_INVAL);
2565 }
2566 } else {
2567 upipe->iinfo = uhci_alloc_intr_info(sc);
2568 if (upipe->iinfo == 0)
2569 return (USBD_NOMEM);
2570 switch (ed->bmAttributes & UE_XFERTYPE) {
2571 case UE_CONTROL:
2572 pipe->methods = &uhci_device_ctrl_methods;
2573 upipe->u.ctl.sqh = uhci_alloc_sqh(sc);
2574 if (upipe->u.ctl.sqh == NULL)
2575 goto bad;
2576 upipe->u.ctl.setup = uhci_alloc_std(sc);
2577 if (upipe->u.ctl.setup == NULL) {
2578 uhci_free_sqh(sc, upipe->u.ctl.sqh);
2579 goto bad;
2580 }
2581 upipe->u.ctl.stat = uhci_alloc_std(sc);
2582 if (upipe->u.ctl.stat == NULL) {
2583 uhci_free_sqh(sc, upipe->u.ctl.sqh);
2584 uhci_free_std(sc, upipe->u.ctl.setup);
2585 goto bad;
2586 }
2587 err = usb_allocmem(&sc->sc_bus,
2588 sizeof(usb_device_request_t),
2589 0, &upipe->u.ctl.reqdma);
2590 if (err) {
2591 uhci_free_sqh(sc, upipe->u.ctl.sqh);
2592 uhci_free_std(sc, upipe->u.ctl.setup);
2593 uhci_free_std(sc, upipe->u.ctl.stat);
2594 goto bad;
2595 }
2596 break;
2597 case UE_INTERRUPT:
2598 pipe->methods = &uhci_device_intr_methods;
2599 ival = pipe->interval;
2600 if (ival == USBD_DEFAULT_INTERVAL)
2601 ival = ed->bInterval;
2602 return (uhci_device_setintr(sc, upipe, ival));
2603 case UE_ISOCHRONOUS:
2604 pipe->methods = &uhci_device_isoc_methods;
2605 return (uhci_setup_isoc(pipe));
2606 case UE_BULK:
2607 pipe->methods = &uhci_device_bulk_methods;
2608 upipe->u.bulk.sqh = uhci_alloc_sqh(sc);
2609 if (upipe->u.bulk.sqh == NULL)
2610 goto bad;
2611 break;
2612 }
2613 }
2614 return (USBD_NORMAL_COMPLETION);
2615
2616 bad:
2617 uhci_free_intr_info(upipe->iinfo);
2618 return (USBD_NOMEM);
2619 }
2620
2621 /*
2622 * Data structures and routines to emulate the root hub.
2623 */
2624 usb_device_descriptor_t uhci_devd = {
2625 USB_DEVICE_DESCRIPTOR_SIZE,
2626 UDESC_DEVICE, /* type */
2627 {0x00, 0x01}, /* USB version */
2628 UCLASS_HUB, /* class */
2629 USUBCLASS_HUB, /* subclass */
2630 0, /* protocol */
2631 64, /* max packet */
2632 {0},{0},{0x00,0x01}, /* device id */
2633 1,2,0, /* string indicies */
2634 1 /* # of configurations */
2635 };
2636
2637 usb_config_descriptor_t uhci_confd = {
2638 USB_CONFIG_DESCRIPTOR_SIZE,
2639 UDESC_CONFIG,
2640 {USB_CONFIG_DESCRIPTOR_SIZE +
2641 USB_INTERFACE_DESCRIPTOR_SIZE +
2642 USB_ENDPOINT_DESCRIPTOR_SIZE},
2643 1,
2644 1,
2645 0,
2646 UC_SELF_POWERED,
2647 0 /* max power */
2648 };
2649
2650 usb_interface_descriptor_t uhci_ifcd = {
2651 USB_INTERFACE_DESCRIPTOR_SIZE,
2652 UDESC_INTERFACE,
2653 0,
2654 0,
2655 1,
2656 UCLASS_HUB,
2657 USUBCLASS_HUB,
2658 0,
2659 0
2660 };
2661
2662 usb_endpoint_descriptor_t uhci_endpd = {
2663 USB_ENDPOINT_DESCRIPTOR_SIZE,
2664 UDESC_ENDPOINT,
2665 UE_DIR_IN | UHCI_INTR_ENDPT,
2666 UE_INTERRUPT,
2667 {8},
2668 255
2669 };
2670
2671 usb_hub_descriptor_t uhci_hubd_piix = {
2672 USB_HUB_DESCRIPTOR_SIZE,
2673 UDESC_HUB,
2674 2,
2675 { UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL, 0 },
2676 50, /* power on to power good */
2677 0,
2678 { 0x00 }, /* both ports are removable */
2679 };
2680
2681 int
2682 uhci_str(p, l, s)
2683 usb_string_descriptor_t *p;
2684 int l;
2685 char *s;
2686 {
2687 int i;
2688
2689 if (l == 0)
2690 return (0);
2691 p->bLength = 2 * strlen(s) + 2;
2692 if (l == 1)
2693 return (1);
2694 p->bDescriptorType = UDESC_STRING;
2695 l -= 2;
2696 for (i = 0; s[i] && l > 1; i++, l -= 2)
2697 USETW2(p->bString[i], 0, s[i]);
2698 return (2*i+2);
2699 }
2700
2701 /*
2702 * Simulate a hardware hub by handling all the necessary requests.
2703 */
2704 usbd_status
2705 uhci_root_ctrl_transfer(xfer)
2706 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 (otherwise err would be USBD_INPROG),
2716 * start first
2717 */
2718 return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
2719 }
2720
2721 usbd_status
2722 uhci_root_ctrl_start(xfer)
2723 usbd_xfer_handle xfer;
2724 {
2725 uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
2726 usb_device_request_t *req;
2727 void *buf = NULL;
2728 int port, x;
2729 int s, len, value, index, status, change, l, totlen = 0;
2730 usb_port_status_t ps;
2731 usbd_status err;
2732
2733 if (sc->sc_dying)
2734 return (USBD_IOERROR);
2735
2736 #ifdef DIAGNOSTIC
2737 if (!(xfer->rqflags & URQ_REQUEST))
2738 panic("uhci_root_ctrl_transfer: not a request\n");
2739 #endif
2740 req = &xfer->request;
2741
2742 DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n",
2743 req->bmRequestType, req->bRequest));
2744
2745 len = UGETW(req->wLength);
2746 value = UGETW(req->wValue);
2747 index = UGETW(req->wIndex);
2748
2749 if (len != 0)
2750 buf = KERNADDR(&xfer->dmabuf);
2751
2752 #define C(x,y) ((x) | ((y) << 8))
2753 switch(C(req->bRequest, req->bmRequestType)) {
2754 case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
2755 case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
2756 case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
2757 /*
2758 * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
2759 * for the integrated root hub.
2760 */
2761 break;
2762 case C(UR_GET_CONFIG, UT_READ_DEVICE):
2763 if (len > 0) {
2764 *(u_int8_t *)buf = sc->sc_conf;
2765 totlen = 1;
2766 }
2767 break;
2768 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
2769 DPRINTFN(2,("uhci_root_ctrl_control wValue=0x%04x\n", value));
2770 switch(value >> 8) {
2771 case UDESC_DEVICE:
2772 if ((value & 0xff) != 0) {
2773 err = USBD_IOERROR;
2774 goto ret;
2775 }
2776 totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
2777 USETW(uhci_devd.idVendor, sc->sc_id_vendor);
2778 memcpy(buf, &uhci_devd, l);
2779 break;
2780 case UDESC_CONFIG:
2781 if ((value & 0xff) != 0) {
2782 err = USBD_IOERROR;
2783 goto ret;
2784 }
2785 totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
2786 memcpy(buf, &uhci_confd, l);
2787 buf = (char *)buf + l;
2788 len -= l;
2789 l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
2790 totlen += l;
2791 memcpy(buf, &uhci_ifcd, l);
2792 buf = (char *)buf + l;
2793 len -= l;
2794 l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
2795 totlen += l;
2796 memcpy(buf, &uhci_endpd, l);
2797 break;
2798 case UDESC_STRING:
2799 if (len == 0)
2800 break;
2801 *(u_int8_t *)buf = 0;
2802 totlen = 1;
2803 switch (value & 0xff) {
2804 case 1: /* Vendor */
2805 totlen = uhci_str(buf, len, sc->sc_vendor);
2806 break;
2807 case 2: /* Product */
2808 totlen = uhci_str(buf, len, "UHCI root hub");
2809 break;
2810 }
2811 break;
2812 default:
2813 err = USBD_IOERROR;
2814 goto ret;
2815 }
2816 break;
2817 case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
2818 if (len > 0) {
2819 *(u_int8_t *)buf = 0;
2820 totlen = 1;
2821 }
2822 break;
2823 case C(UR_GET_STATUS, UT_READ_DEVICE):
2824 if (len > 1) {
2825 USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED);
2826 totlen = 2;
2827 }
2828 break;
2829 case C(UR_GET_STATUS, UT_READ_INTERFACE):
2830 case C(UR_GET_STATUS, UT_READ_ENDPOINT):
2831 if (len > 1) {
2832 USETW(((usb_status_t *)buf)->wStatus, 0);
2833 totlen = 2;
2834 }
2835 break;
2836 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
2837 if (value >= USB_MAX_DEVICES) {
2838 err = USBD_IOERROR;
2839 goto ret;
2840 }
2841 sc->sc_addr = value;
2842 break;
2843 case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
2844 if (value != 0 && value != 1) {
2845 err = USBD_IOERROR;
2846 goto ret;
2847 }
2848 sc->sc_conf = value;
2849 break;
2850 case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
2851 break;
2852 case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
2853 case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
2854 case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
2855 err = USBD_IOERROR;
2856 goto ret;
2857 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
2858 break;
2859 case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
2860 break;
2861 /* Hub requests */
2862 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
2863 break;
2864 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
2865 DPRINTFN(3, ("uhci_root_ctrl_control: UR_CLEAR_PORT_FEATURE "
2866 "port=%d feature=%d\n",
2867 index, value));
2868 if (index == 1)
2869 port = UHCI_PORTSC1;
2870 else if (index == 2)
2871 port = UHCI_PORTSC2;
2872 else {
2873 err = USBD_IOERROR;
2874 goto ret;
2875 }
2876 switch(value) {
2877 case UHF_PORT_ENABLE:
2878 x = UREAD2(sc, port);
2879 UWRITE2(sc, port, x & ~UHCI_PORTSC_PE);
2880 break;
2881 case UHF_PORT_SUSPEND:
2882 x = UREAD2(sc, port);
2883 UWRITE2(sc, port, x & ~UHCI_PORTSC_SUSP);
2884 break;
2885 case UHF_PORT_RESET:
2886 x = UREAD2(sc, port);
2887 UWRITE2(sc, port, x & ~UHCI_PORTSC_PR);
2888 break;
2889 case UHF_C_PORT_CONNECTION:
2890 x = UREAD2(sc, port);
2891 UWRITE2(sc, port, x | UHCI_PORTSC_CSC);
2892 break;
2893 case UHF_C_PORT_ENABLE:
2894 x = UREAD2(sc, port);
2895 UWRITE2(sc, port, x | UHCI_PORTSC_POEDC);
2896 break;
2897 case UHF_C_PORT_OVER_CURRENT:
2898 x = UREAD2(sc, port);
2899 UWRITE2(sc, port, x | UHCI_PORTSC_OCIC);
2900 break;
2901 case UHF_C_PORT_RESET:
2902 sc->sc_isreset = 0;
2903 err = USBD_NORMAL_COMPLETION;
2904 goto ret;
2905 case UHF_PORT_CONNECTION:
2906 case UHF_PORT_OVER_CURRENT:
2907 case UHF_PORT_POWER:
2908 case UHF_PORT_LOW_SPEED:
2909 case UHF_C_PORT_SUSPEND:
2910 default:
2911 err = USBD_IOERROR;
2912 goto ret;
2913 }
2914 break;
2915 case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
2916 if (index == 1)
2917 port = UHCI_PORTSC1;
2918 else if (index == 2)
2919 port = UHCI_PORTSC2;
2920 else {
2921 err = USBD_IOERROR;
2922 goto ret;
2923 }
2924 if (len > 0) {
2925 *(u_int8_t *)buf =
2926 (UREAD2(sc, port) & UHCI_PORTSC_LS) >>
2927 UHCI_PORTSC_LS_SHIFT;
2928 totlen = 1;
2929 }
2930 break;
2931 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
2932 if (value != 0) {
2933 err = USBD_IOERROR;
2934 goto ret;
2935 }
2936 l = min(len, USB_HUB_DESCRIPTOR_SIZE);
2937 totlen = l;
2938 memcpy(buf, &uhci_hubd_piix, l);
2939 break;
2940 case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
2941 if (len != 4) {
2942 err = USBD_IOERROR;
2943 goto ret;
2944 }
2945 memset(buf, 0, len);
2946 totlen = len;
2947 break;
2948 case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
2949 if (index == 1)
2950 port = UHCI_PORTSC1;
2951 else if (index == 2)
2952 port = UHCI_PORTSC2;
2953 else {
2954 err = USBD_IOERROR;
2955 goto ret;
2956 }
2957 if (len != 4) {
2958 err = USBD_IOERROR;
2959 goto ret;
2960 }
2961 x = UREAD2(sc, port);
2962 status = change = 0;
2963 if (x & UHCI_PORTSC_CCS )
2964 status |= UPS_CURRENT_CONNECT_STATUS;
2965 if (x & UHCI_PORTSC_CSC )
2966 change |= UPS_C_CONNECT_STATUS;
2967 if (x & UHCI_PORTSC_PE )
2968 status |= UPS_PORT_ENABLED;
2969 if (x & UHCI_PORTSC_POEDC)
2970 change |= UPS_C_PORT_ENABLED;
2971 if (x & UHCI_PORTSC_OCI )
2972 status |= UPS_OVERCURRENT_INDICATOR;
2973 if (x & UHCI_PORTSC_OCIC )
2974 change |= UPS_C_OVERCURRENT_INDICATOR;
2975 if (x & UHCI_PORTSC_SUSP )
2976 status |= UPS_SUSPEND;
2977 if (x & UHCI_PORTSC_LSDA )
2978 status |= UPS_LOW_SPEED;
2979 status |= UPS_PORT_POWER;
2980 if (sc->sc_isreset)
2981 change |= UPS_C_PORT_RESET;
2982 USETW(ps.wPortStatus, status);
2983 USETW(ps.wPortChange, change);
2984 l = min(len, sizeof ps);
2985 memcpy(buf, &ps, l);
2986 totlen = l;
2987 break;
2988 case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
2989 err = USBD_IOERROR;
2990 goto ret;
2991 case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
2992 break;
2993 case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
2994 if (index == 1)
2995 port = UHCI_PORTSC1;
2996 else if (index == 2)
2997 port = UHCI_PORTSC2;
2998 else {
2999 err = USBD_IOERROR;
3000 goto ret;
3001 }
3002 switch(value) {
3003 case UHF_PORT_ENABLE:
3004 x = UREAD2(sc, port);
3005 UWRITE2(sc, port, x | UHCI_PORTSC_PE);
3006 break;
3007 case UHF_PORT_SUSPEND:
3008 x = UREAD2(sc, port);
3009 UWRITE2(sc, port, x | UHCI_PORTSC_SUSP);
3010 break;
3011 case UHF_PORT_RESET:
3012 x = UREAD2(sc, port);
3013 UWRITE2(sc, port, x | UHCI_PORTSC_PR);
3014 usb_delay_ms(&sc->sc_bus, 10);
3015 UWRITE2(sc, port, x & ~UHCI_PORTSC_PR);
3016 delay(100);
3017 x = UREAD2(sc, port);
3018 UWRITE2(sc, port, x | UHCI_PORTSC_PE);
3019 delay(100);
3020 DPRINTFN(3,("uhci port %d reset, status = 0x%04x\n",
3021 index, UREAD2(sc, port)));
3022 sc->sc_isreset = 1;
3023 break;
3024 case UHF_C_PORT_CONNECTION:
3025 case UHF_C_PORT_ENABLE:
3026 case UHF_C_PORT_OVER_CURRENT:
3027 case UHF_PORT_CONNECTION:
3028 case UHF_PORT_OVER_CURRENT:
3029 case UHF_PORT_POWER:
3030 case UHF_PORT_LOW_SPEED:
3031 case UHF_C_PORT_SUSPEND:
3032 case UHF_C_PORT_RESET:
3033 default:
3034 err = USBD_IOERROR;
3035 goto ret;
3036 }
3037 break;
3038 default:
3039 err = USBD_IOERROR;
3040 goto ret;
3041 }
3042 xfer->actlen = totlen;
3043 err = USBD_NORMAL_COMPLETION;
3044 ret:
3045 xfer->status = err;
3046 xfer->hcpriv = 0;
3047 s = splusb();
3048 usb_transfer_complete(xfer);
3049 splx(s);
3050 return (USBD_IN_PROGRESS);
3051 }
3052
3053 /* Abort a root control request. */
3054 void
3055 uhci_root_ctrl_abort(xfer)
3056 usbd_xfer_handle xfer;
3057 {
3058 /* Nothing to do, all transfers are synchronous. */
3059 }
3060
3061 /* Close the root pipe. */
3062 void
3063 uhci_root_ctrl_close(pipe)
3064 usbd_pipe_handle pipe;
3065 {
3066 DPRINTF(("uhci_root_ctrl_close\n"));
3067 }
3068
3069 /* Abort a root interrupt request. */
3070 void
3071 uhci_root_intr_abort(xfer)
3072 usbd_xfer_handle xfer;
3073 {
3074 uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
3075
3076 usb_untimeout(uhci_timo, xfer, xfer->timo_handle);
3077 sc->sc_has_timo = NULL;
3078
3079 if (xfer->pipe->intrxfer == xfer) {
3080 DPRINTF(("uhci_root_intr_abort: remove\n"));
3081 xfer->pipe->intrxfer = 0;
3082 }
3083 xfer->status = USBD_CANCELLED;
3084 usb_transfer_complete(xfer);
3085 }
3086
3087 usbd_status
3088 uhci_root_intr_transfer(xfer)
3089 usbd_xfer_handle xfer;
3090 {
3091 usbd_status err;
3092
3093 /* Insert last in queue. */
3094 err = usb_insert_transfer(xfer);
3095 if (err)
3096 return (err);
3097
3098 /* Pipe isn't running (otherwise err would be USBD_INPROG),
3099 * start first
3100 */
3101 return (uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
3102 }
3103
3104 /* Start a transfer on the root interrupt pipe */
3105 usbd_status
3106 uhci_root_intr_start(xfer)
3107 usbd_xfer_handle xfer;
3108 {
3109 usbd_pipe_handle pipe = xfer->pipe;
3110 uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
3111
3112 DPRINTFN(3, ("uhci_root_intr_transfer: xfer=%p len=%d flags=%d\n",
3113 xfer, xfer->length, xfer->flags));
3114
3115 if (sc->sc_dying)
3116 return (USBD_IOERROR);
3117
3118 sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval);
3119 usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
3120 sc->sc_has_timo = xfer;
3121 return (USBD_IN_PROGRESS);
3122 }
3123
3124 /* Close the root interrupt pipe. */
3125 void
3126 uhci_root_intr_close(pipe)
3127 usbd_pipe_handle pipe;
3128 {
3129 uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
3130
3131 usb_untimeout(uhci_timo, pipe->intrxfer, pipe->intrxfer->timo_handle);
3132 sc->sc_has_timo = NULL;
3133 DPRINTF(("uhci_root_intr_close\n"));
3134 }
3135