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