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