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