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