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