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