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