]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/mips/cavium/usb/octusb.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / mips / cavium / usb / octusb.c
1 #include <sys/cdefs.h>
2 __FBSDID("$FreeBSD$");
3
4 /*-
5  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * This file contains the driver for Octeon Executive Library USB
31  * Controller driver API.
32  */
33
34 /* TODO: The root HUB port callback is not yet implemented. */
35
36 #include <sys/stdint.h>
37 #include <sys/stddef.h>
38 #include <sys/param.h>
39 #include <sys/queue.h>
40 #include <sys/types.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/bus.h>
44 #include <sys/module.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/condvar.h>
48 #include <sys/sysctl.h>
49 #include <sys/sx.h>
50 #include <sys/unistd.h>
51 #include <sys/callout.h>
52 #include <sys/malloc.h>
53 #include <sys/priv.h>
54
55 #include <dev/usb/usb.h>
56 #include <dev/usb/usbdi.h>
57
58 #define USB_DEBUG_VAR octusbdebug
59
60 #include <dev/usb/usb_core.h>
61 #include <dev/usb/usb_debug.h>
62 #include <dev/usb/usb_busdma.h>
63 #include <dev/usb/usb_process.h>
64 #include <dev/usb/usb_transfer.h>
65 #include <dev/usb/usb_device.h>
66 #include <dev/usb/usb_hub.h>
67 #include <dev/usb/usb_util.h>
68
69 #include <dev/usb/usb_controller.h>
70 #include <dev/usb/usb_bus.h>
71
72 #include <contrib/octeon-sdk/cvmx.h>
73 #include <contrib/octeon-sdk/cvmx-usb.h>
74
75 #include <mips/cavium/usb/octusb.h>
76
77 #define OCTUSB_BUS2SC(bus) \
78    ((struct octusb_softc *)(((uint8_t *)(bus)) - \
79     ((uint8_t *)&(((struct octusb_softc *)0)->sc_bus))))
80
81 #ifdef USB_DEBUG
82 static int octusbdebug = 0;
83
84 static SYSCTL_NODE(_hw_usb, OID_AUTO, octusb, CTLFLAG_RW, 0, "OCTUSB");
85 SYSCTL_INT(_hw_usb_octusb, OID_AUTO, debug, CTLFLAG_RW,
86     &octusbdebug, 0, "OCTUSB debug level");
87
88 TUNABLE_INT("hw.usb.octusb.debug", &octusbdebug);
89
90 #endif
91
92 struct octusb_std_temp {
93         octusb_cmd_t *func;
94         struct octusb_td *td;
95         struct octusb_td *td_next;
96         struct usb_page_cache *pc;
97         uint32_t offset;
98         uint32_t len;
99         uint8_t short_pkt;
100         uint8_t setup_alt_next;
101 };
102
103 extern struct usb_bus_methods octusb_bus_methods;
104 extern struct usb_pipe_methods octusb_device_bulk_methods;
105 extern struct usb_pipe_methods octusb_device_ctrl_methods;
106 extern struct usb_pipe_methods octusb_device_intr_methods;
107 extern struct usb_pipe_methods octusb_device_isoc_methods;
108
109 static void octusb_standard_done(struct usb_xfer *);
110 static void octusb_device_done(struct usb_xfer *, usb_error_t);
111 static void octusb_timeout(void *);
112 static void octusb_do_poll(struct usb_bus *);
113
114 static cvmx_usb_speed_t
115 octusb_convert_speed(enum usb_dev_speed speed)
116 {
117         ;                               /* indent fix */
118         switch (speed) {
119         case USB_SPEED_HIGH:
120                 return (CVMX_USB_SPEED_HIGH);
121         case USB_SPEED_FULL:
122                 return (CVMX_USB_SPEED_FULL);
123         default:
124                 return (CVMX_USB_SPEED_LOW);
125         }
126 }
127
128 static cvmx_usb_transfer_t
129 octusb_convert_ep_type(uint8_t ep_type)
130 {
131         ;                               /* indent fix */
132         switch (ep_type & UE_XFERTYPE) {
133         case UE_CONTROL:
134                 return (CVMX_USB_TRANSFER_CONTROL);
135         case UE_INTERRUPT:
136                 return (CVMX_USB_TRANSFER_INTERRUPT);
137         case UE_ISOCHRONOUS:
138                 return (CVMX_USB_TRANSFER_ISOCHRONOUS);
139         case UE_BULK:
140                 return (CVMX_USB_TRANSFER_BULK);
141         default:
142                 return (0);             /* should not happen */
143         }
144 }
145
146 static uint8_t
147 octusb_host_alloc_endpoint(struct octusb_td *td)
148 {
149         struct octusb_softc *sc;
150         int ep_handle;
151
152         if (td->qh->fixup_pending)
153                 return (1);             /* busy */
154
155         if (td->qh->ep_allocated)
156                 return (0);             /* success */
157
158         /* get softc */
159         sc = td->qh->sc;
160
161         ep_handle = cvmx_usb_open_pipe(
162             &sc->sc_port[td->qh->port_index].state,
163             0,
164             td->qh->dev_addr,
165             td->qh->ep_num,
166             octusb_convert_speed(td->qh->dev_speed),
167             td->qh->max_packet_size,
168             octusb_convert_ep_type(td->qh->ep_type),
169             (td->qh->ep_num & UE_DIR_IN) ? CVMX_USB_DIRECTION_IN :
170             CVMX_USB_DIRECTION_OUT,
171             td->qh->ep_interval,
172             td->qh->ep_mult,
173             td->qh->hs_hub_addr,
174             td->qh->hs_hub_port);
175
176         if (ep_handle < 0)
177                 return (1);             /* busy */
178
179         cvmx_usb_set_toggle(
180             &sc->sc_port[td->qh->port_index].state,
181             ep_handle, td->qh->ep_toggle_next);
182
183         td->qh->fixup_handle = -1;
184         td->qh->fixup_complete = 0;
185         td->qh->fixup_len = 0;
186         td->qh->fixup_off = 0;
187         td->qh->fixup_pending = 0;
188         td->qh->fixup_actlen = 0;
189
190         td->qh->ep_handle = ep_handle;
191         td->qh->ep_allocated = 1;
192
193         return (0);                     /* success */
194 }
195
196 static void
197 octusb_host_free_endpoint(struct octusb_td *td)
198 {
199         struct octusb_softc *sc;
200
201         if (td->qh->ep_allocated == 0)
202                 return;
203
204         /* get softc */
205         sc = td->qh->sc;
206
207         if (td->qh->fixup_handle >= 0) {
208                 /* cancel, if any */
209                 cvmx_usb_cancel(&sc->sc_port[td->qh->port_index].state,
210                     td->qh->ep_handle, td->qh->fixup_handle);
211         }
212         cvmx_usb_close_pipe(&sc->sc_port[td->qh->port_index].state, td->qh->ep_handle);
213
214         td->qh->ep_allocated = 0;
215 }
216
217 static void
218 octusb_complete_cb(cvmx_usb_state_t *state,
219     cvmx_usb_callback_t reason,
220     cvmx_usb_complete_t status,
221     int pipe_handle, int submit_handle,
222     int bytes_transferred, void *user_data)
223 {
224         struct octusb_td *td;
225
226         if (reason != CVMX_USB_CALLBACK_TRANSFER_COMPLETE)
227                 return;
228
229         td = user_data;
230
231         td->qh->fixup_complete = 1;
232         td->qh->fixup_pending = 0;
233         td->qh->fixup_actlen = bytes_transferred;
234         td->qh->fixup_handle = -1;
235
236         switch (status) {
237         case CVMX_USB_COMPLETE_SUCCESS:
238         case CVMX_USB_COMPLETE_SHORT:
239                 td->error_any = 0;
240                 td->error_stall = 0;
241                 break;
242         case CVMX_USB_COMPLETE_STALL:
243                 td->error_stall = 1;
244                 td->error_any = 1;
245                 break;
246         default:
247                 td->error_any = 1;
248                 break;
249         }
250 }
251
252 static uint8_t
253 octusb_host_control_header_tx(struct octusb_td *td)
254 {
255         int status;
256
257         /* allocate endpoint and check pending */
258         if (octusb_host_alloc_endpoint(td))
259                 return (1);             /* busy */
260
261         /* check error */
262         if (td->error_any)
263                 return (0);             /* done */
264
265         if (td->qh->fixup_complete != 0) {
266                 /* clear complete flag */
267                 td->qh->fixup_complete = 0;
268
269                 /* flush data */
270                 usb_pc_cpu_invalidate(td->qh->fixup_pc);
271                 return (0);             /* done */
272         }
273         /* verify length */
274         if (td->remainder != 8) {
275                 td->error_any = 1;
276                 return (0);             /* done */
277         }
278         usbd_copy_out(td->pc, td->offset, td->qh->fixup_buf, 8);
279
280         /* update offset and remainder */
281         td->offset += 8;
282         td->remainder -= 8;
283
284         /* setup data length and offset */
285         td->qh->fixup_len = UGETW(td->qh->fixup_buf + 6);
286         td->qh->fixup_off = 0;
287
288         if (td->qh->fixup_len > (OCTUSB_MAX_FIXUP - 8)) {
289                 td->error_any = 1;
290                 return (0);             /* done */
291         }
292         /* do control IN request */
293         if (td->qh->fixup_buf[0] & UE_DIR_IN) {
294
295                 struct octusb_softc *sc;
296
297                 /* get softc */
298                 sc = td->qh->sc;
299
300                 /* flush data */
301                 usb_pc_cpu_flush(td->qh->fixup_pc);
302
303                 status = cvmx_usb_submit_control(
304                     &sc->sc_port[td->qh->port_index].state,
305                     td->qh->ep_handle, td->qh->fixup_phys,
306                     td->qh->fixup_phys + 8, td->qh->fixup_len,
307                     &octusb_complete_cb, td);
308                 /* check status */
309                 if (status < 0) {
310                         td->error_any = 1;
311                         return (0);     /* done */
312                 }
313                 td->qh->fixup_handle = status;
314                 td->qh->fixup_pending = 1;
315                 td->qh->fixup_complete = 0;
316
317                 return (1);             /* busy */
318         }
319         return (0);                     /* done */
320 }
321
322 static uint8_t
323 octusb_host_control_data_tx(struct octusb_td *td)
324 {
325         uint32_t rem;
326
327         /* allocate endpoint and check pending */
328         if (octusb_host_alloc_endpoint(td))
329                 return (1);             /* busy */
330
331         /* check error */
332         if (td->error_any)
333                 return (0);             /* done */
334
335         rem = td->qh->fixup_len - td->qh->fixup_off;
336
337         if (td->remainder > rem) {
338                 td->error_any = 1;
339                 DPRINTFN(1, "Excess setup transmit data\n");
340                 return (0);             /* done */
341         }
342         usbd_copy_out(td->pc, td->offset, td->qh->fixup_buf +
343             td->qh->fixup_off + 8, td->remainder);
344
345         td->offset += td->remainder;
346         td->qh->fixup_off += td->remainder;
347         td->remainder = 0;
348
349         return (0);                     /* done */
350 }
351
352 static uint8_t
353 octusb_host_control_data_rx(struct octusb_td *td)
354 {
355         uint32_t rem;
356
357         /* allocate endpoint and check pending */
358         if (octusb_host_alloc_endpoint(td))
359                 return (1);             /* busy */
360
361         /* check error */
362         if (td->error_any)
363                 return (0);             /* done */
364
365         /* copy data from buffer */
366         rem = td->qh->fixup_actlen - td->qh->fixup_off;
367
368         if (rem > td->remainder)
369                 rem = td->remainder;
370
371         usbd_copy_in(td->pc, td->offset, td->qh->fixup_buf +
372             td->qh->fixup_off + 8, rem);
373
374         td->offset += rem;
375         td->remainder -= rem;
376         td->qh->fixup_off += rem;
377
378         return (0);                     /* done */
379 }
380
381 static uint8_t
382 octusb_host_control_status_tx(struct octusb_td *td)
383 {
384         int status;
385
386         /* allocate endpoint and check pending */
387         if (octusb_host_alloc_endpoint(td))
388                 return (1);             /* busy */
389
390         /* check error */
391         if (td->error_any)
392                 return (0);             /* done */
393
394         if (td->qh->fixup_complete != 0) {
395                 /* clear complete flag */
396                 td->qh->fixup_complete = 0;
397                 /* done */
398                 return (0);
399         }
400         /* do control IN request */
401         if (!(td->qh->fixup_buf[0] & UE_DIR_IN)) {
402
403                 struct octusb_softc *sc;
404
405                 /* get softc */
406                 sc = td->qh->sc;
407
408                 /* flush data */
409                 usb_pc_cpu_flush(td->qh->fixup_pc);
410
411                 /* start USB transfer */
412                 status = cvmx_usb_submit_control(
413                     &sc->sc_port[td->qh->port_index].state,
414                     td->qh->ep_handle, td->qh->fixup_phys,
415                     td->qh->fixup_phys + 8, td->qh->fixup_len,
416                     &octusb_complete_cb, td);
417
418                 /* check status */
419                 if (status < 0) {
420                         td->error_any = 1;
421                         return (0);     /* done */
422                 }
423                 td->qh->fixup_handle = status;
424                 td->qh->fixup_pending = 1;
425                 td->qh->fixup_complete = 0;
426
427                 return (1);             /* busy */
428         }
429         return (0);                     /* done */
430 }
431
432 static uint8_t
433 octusb_non_control_data_tx(struct octusb_td *td)
434 {
435         struct octusb_softc *sc;
436         uint32_t rem;
437         int status;
438
439         /* allocate endpoint and check pending */
440         if (octusb_host_alloc_endpoint(td))
441                 return (1);             /* busy */
442
443         /* check error */
444         if (td->error_any)
445                 return (0);             /* done */
446
447         if ((td->qh->fixup_complete != 0) &&
448             ((td->qh->ep_type & UE_XFERTYPE) == UE_ISOCHRONOUS)) {
449                 td->qh->fixup_complete = 0;
450                 return (0);             /* done */
451         }
452         /* check complete */
453         if (td->remainder == 0) {
454                 if (td->short_pkt)
455                         return (0);     /* complete */
456                 /* else need to send a zero length packet */
457                 rem = 0;
458                 td->short_pkt = 1;
459         } else {
460                 /* get maximum length */
461                 rem = OCTUSB_MAX_FIXUP % td->qh->max_frame_size;
462                 rem = OCTUSB_MAX_FIXUP - rem;
463
464                 if (rem == 0) {
465                         /* should not happen */
466                         DPRINTFN(1, "Fixup buffer is too small\n");
467                         td->error_any = 1;
468                         return (0);     /* done */
469                 }
470                 /* get minimum length */
471                 if (rem > td->remainder) {
472                         rem = td->remainder;
473                         if ((rem == 0) || (rem % td->qh->max_frame_size))
474                                 td->short_pkt = 1;
475                 }
476                 /* copy data into fixup buffer */
477                 usbd_copy_out(td->pc, td->offset, td->qh->fixup_buf, rem);
478
479                 /* flush data */
480                 usb_pc_cpu_flush(td->qh->fixup_pc);
481
482                 /* pre-increment TX buffer offset */
483                 td->offset += rem;
484                 td->remainder -= rem;
485         }
486
487         /* get softc */
488         sc = td->qh->sc;
489
490         switch (td->qh->ep_type & UE_XFERTYPE) {
491         case UE_ISOCHRONOUS:
492                 td->qh->iso_pkt.offset = 0;
493                 td->qh->iso_pkt.length = rem;
494                 td->qh->iso_pkt.status = 0;
495                 /* start USB transfer */
496                 status = cvmx_usb_submit_isochronous(&sc->sc_port[td->qh->port_index].state,
497                     td->qh->ep_handle, 1, CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT |
498                     CVMX_USB_ISOCHRONOUS_FLAGS_ASAP, 1, &td->qh->iso_pkt,
499                     td->qh->fixup_phys, rem, &octusb_complete_cb, td);
500                 break;
501         case UE_BULK:
502                 /* start USB transfer */
503                 status = cvmx_usb_submit_bulk(&sc->sc_port[td->qh->port_index].state,
504                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
505                 break;
506         case UE_INTERRUPT:
507                 /* start USB transfer (interrupt or interrupt) */
508                 status = cvmx_usb_submit_interrupt(&sc->sc_port[td->qh->port_index].state,
509                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
510                 break;
511         default:
512                 status = -1;
513                 break;
514         }
515
516         /* check status */
517         if (status < 0) {
518                 td->error_any = 1;
519                 return (0);             /* done */
520         }
521         td->qh->fixup_handle = status;
522         td->qh->fixup_len = rem;
523         td->qh->fixup_pending = 1;
524         td->qh->fixup_complete = 0;
525
526         return (1);                     /* busy */
527 }
528
529 static uint8_t
530 octusb_non_control_data_rx(struct octusb_td *td)
531 {
532         struct octusb_softc *sc;
533         uint32_t rem;
534         int status;
535         uint8_t got_short;
536
537         /* allocate endpoint and check pending */
538         if (octusb_host_alloc_endpoint(td))
539                 return (1);             /* busy */
540
541         /* check error */
542         if (td->error_any)
543                 return (0);             /* done */
544
545         got_short = 0;
546
547         if (td->qh->fixup_complete != 0) {
548
549                 /* invalidate data */
550                 usb_pc_cpu_invalidate(td->qh->fixup_pc);
551
552                 rem = td->qh->fixup_actlen;
553
554                 /* verify transfer length */
555                 if (rem != td->qh->fixup_len) {
556                         if (rem < td->qh->fixup_len) {
557                                 /* we have a short packet */
558                                 td->short_pkt = 1;
559                                 got_short = 1;
560                         } else {
561                                 /* invalid USB packet */
562                                 td->error_any = 1;
563                                 return (0);     /* we are complete */
564                         }
565                 }
566                 /* copy data into fixup buffer */
567                 usbd_copy_in(td->pc, td->offset, td->qh->fixup_buf, rem);
568
569                 /* post-increment RX buffer offset */
570                 td->offset += rem;
571                 td->remainder -= rem;
572
573                 td->qh->fixup_complete = 0;
574
575                 if ((td->qh->ep_type & UE_XFERTYPE) == UE_ISOCHRONOUS)
576                         return (0);     /* done */
577         }
578         /* check if we are complete */
579         if ((td->remainder == 0) || got_short) {
580                 if (td->short_pkt) {
581                         /* we are complete */
582                         return (0);
583                 }
584                 /* else need to receive a zero length packet */
585                 rem = 0;
586                 td->short_pkt = 1;
587         } else {
588                 /* get maximum length */
589                 rem = OCTUSB_MAX_FIXUP % td->qh->max_frame_size;
590                 rem = OCTUSB_MAX_FIXUP - rem;
591
592                 if (rem == 0) {
593                         /* should not happen */
594                         DPRINTFN(1, "Fixup buffer is too small\n");
595                         td->error_any = 1;
596                         return (0);     /* done */
597                 }
598                 /* get minimum length */
599                 if (rem > td->remainder)
600                         rem = td->remainder;
601         }
602
603         /* invalidate data */
604         usb_pc_cpu_invalidate(td->qh->fixup_pc);
605
606         /* get softc */
607         sc = td->qh->sc;
608
609         switch (td->qh->ep_type & UE_XFERTYPE) {
610         case UE_ISOCHRONOUS:
611                 td->qh->iso_pkt.offset = 0;
612                 td->qh->iso_pkt.length = rem;
613                 td->qh->iso_pkt.status = 0;
614                 /* start USB transfer */
615                 status = cvmx_usb_submit_isochronous(&sc->sc_port[td->qh->port_index].state,
616                     td->qh->ep_handle, 1, CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT |
617                     CVMX_USB_ISOCHRONOUS_FLAGS_ASAP, 1, &td->qh->iso_pkt,
618                     td->qh->fixup_phys, rem, &octusb_complete_cb, td);
619                 break;
620         case UE_BULK:
621                 /* start USB transfer */
622                 status = cvmx_usb_submit_bulk(&sc->sc_port[td->qh->port_index].state,
623                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
624                 break;
625         case UE_INTERRUPT:
626                 /* start USB transfer */
627                 status = cvmx_usb_submit_interrupt(&sc->sc_port[td->qh->port_index].state,
628                     td->qh->ep_handle, td->qh->fixup_phys, rem, &octusb_complete_cb, td);
629                 break;
630         default:
631                 status = -1;
632                 break;
633         }
634
635         /* check status */
636         if (status < 0) {
637                 td->error_any = 1;
638                 return (0);             /* done */
639         }
640         td->qh->fixup_handle = status;
641         td->qh->fixup_len = rem;
642         td->qh->fixup_pending = 1;
643         td->qh->fixup_complete = 0;
644
645         return (1);                     /* busy */
646 }
647
648 static uint8_t
649 octusb_xfer_do_fifo(struct usb_xfer *xfer)
650 {
651         struct octusb_td *td;
652
653         DPRINTFN(8, "\n");
654
655         td = xfer->td_transfer_cache;
656
657         while (1) {
658                 if ((td->func) (td)) {
659                         /* operation in progress */
660                         break;
661                 }
662                 if (((void *)td) == xfer->td_transfer_last) {
663                         goto done;
664                 }
665                 if (td->error_any) {
666                         goto done;
667                 } else if (td->remainder > 0) {
668                         /*
669                          * We had a short transfer. If there is no
670                          * alternate next, stop processing !
671                          */
672                         if (td->alt_next == 0)
673                                 goto done;
674                 }
675                 /*
676                  * Fetch the next transfer descriptor and transfer
677                  * some flags to the next transfer descriptor
678                  */
679                 td = td->obj_next;
680                 xfer->td_transfer_cache = td;
681         }
682         return (1);                     /* not complete */
683
684 done:
685         /* compute all actual lengths */
686
687         octusb_standard_done(xfer);
688
689         return (0);                     /* complete */
690 }
691
692 static usb_error_t
693 octusb_standard_done_sub(struct usb_xfer *xfer)
694 {
695         struct octusb_td *td;
696         uint32_t len;
697         usb_error_t error;
698
699         DPRINTFN(8, "\n");
700
701         td = xfer->td_transfer_cache;
702
703         do {
704                 len = td->remainder;
705
706                 if (xfer->aframes != xfer->nframes) {
707                         /*
708                          * Verify the length and subtract
709                          * the remainder from "frlengths[]":
710                          */
711                         if (len > xfer->frlengths[xfer->aframes]) {
712                                 td->error_any = 1;
713                         } else {
714                                 xfer->frlengths[xfer->aframes] -= len;
715                         }
716                 }
717                 /* Check for transfer error */
718                 if (td->error_any) {
719                         /* the transfer is finished */
720                         error = td->error_stall ? USB_ERR_STALLED : USB_ERR_IOERROR;
721                         td = NULL;
722                         break;
723                 }
724                 /* Check for short transfer */
725                 if (len > 0) {
726                         if (xfer->flags_int.short_frames_ok) {
727                                 /* follow alt next */
728                                 if (td->alt_next) {
729                                         td = td->obj_next;
730                                 } else {
731                                         td = NULL;
732                                 }
733                         } else {
734                                 /* the transfer is finished */
735                                 td = NULL;
736                         }
737                         error = 0;
738                         break;
739                 }
740                 td = td->obj_next;
741
742                 /* this USB frame is complete */
743                 error = 0;
744                 break;
745
746         } while (0);
747
748         /* update transfer cache */
749
750         xfer->td_transfer_cache = td;
751
752         return (error);
753 }
754
755 static void
756 octusb_standard_done(struct usb_xfer *xfer)
757 {
758         struct octusb_softc *sc;
759         struct octusb_qh *qh;
760         usb_error_t error = 0;
761
762         DPRINTFN(12, "xfer=%p endpoint=%p transfer done\n",
763             xfer, xfer->endpoint);
764
765         /* reset scanner */
766
767         xfer->td_transfer_cache = xfer->td_transfer_first;
768
769         if (xfer->flags_int.control_xfr) {
770
771                 if (xfer->flags_int.control_hdr)
772                         error = octusb_standard_done_sub(xfer);
773
774                 xfer->aframes = 1;
775
776                 if (xfer->td_transfer_cache == NULL)
777                         goto done;
778         }
779         while (xfer->aframes != xfer->nframes) {
780
781                 error = octusb_standard_done_sub(xfer);
782
783                 xfer->aframes++;
784
785                 if (xfer->td_transfer_cache == NULL)
786                         goto done;
787         }
788
789         if (xfer->flags_int.control_xfr &&
790             !xfer->flags_int.control_act)
791                 error = octusb_standard_done_sub(xfer);
792
793 done:
794         /* update data toggle */
795
796         qh = xfer->qh_start[0];
797         sc = qh->sc;
798
799         xfer->endpoint->toggle_next =
800             cvmx_usb_get_toggle(
801             &sc->sc_port[qh->port_index].state,
802             qh->ep_handle) ? 1 : 0;
803
804         octusb_device_done(xfer, error);
805 }
806
807 static void
808 octusb_interrupt_poll(struct octusb_softc *sc)
809 {
810         struct usb_xfer *xfer;
811         uint8_t x;
812
813         /* poll all ports */
814         for (x = 0; x != sc->sc_noport; x++)
815                 cvmx_usb_poll(&sc->sc_port[x].state);
816
817 repeat:
818         TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
819                 if (!octusb_xfer_do_fifo(xfer)) {
820                         /* queue has been modified */
821                         goto repeat;
822                 }
823         }
824 }
825
826 static void
827 octusb_start_standard_chain(struct usb_xfer *xfer)
828 {
829         DPRINTFN(8, "\n");
830
831         /* poll one time */
832         if (octusb_xfer_do_fifo(xfer)) {
833
834                 /* put transfer on interrupt queue */
835                 usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
836
837                 /* start timeout, if any */
838                 if (xfer->timeout != 0) {
839                         usbd_transfer_timeout_ms(xfer,
840                             &octusb_timeout, xfer->timeout);
841                 }
842         }
843 }
844
845 void
846 octusb_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
847 {
848
849 }
850
851 usb_error_t
852 octusb_init(struct octusb_softc *sc)
853 {
854         cvmx_usb_initialize_flags_t flags;
855         int status;
856         uint8_t x;
857
858         /* flush all cache into memory */
859
860         usb_bus_mem_flush_all(&sc->sc_bus, &octusb_iterate_hw_softc);
861
862         /* set up the bus struct */
863         sc->sc_bus.methods = &octusb_bus_methods;
864
865         /* get number of ports */
866         sc->sc_noport = cvmx_usb_get_num_ports();
867
868         /* check number of ports */
869         if (sc->sc_noport > OCTUSB_MAX_PORTS)
870                 sc->sc_noport = OCTUSB_MAX_PORTS;
871
872         /* set USB revision */
873         sc->sc_bus.usbrev = USB_REV_2_0;
874
875         /* flags for port initialization */
876         flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO;
877 #ifdef USB_DEBUG
878         if (octusbdebug > 100)
879                 flags |= CVMX_USB_INITIALIZE_FLAGS_DEBUG_ALL;
880 #endif
881
882         USB_BUS_LOCK(&sc->sc_bus);
883
884         /* setup all ports */
885         for (x = 0; x != sc->sc_noport; x++) {
886                 status = cvmx_usb_initialize(&sc->sc_port[x].state, x, flags);
887                 if (status < 0)
888                         sc->sc_port[x].disabled = 1;
889         }
890
891         USB_BUS_UNLOCK(&sc->sc_bus);
892
893         /* catch lost interrupts */
894         octusb_do_poll(&sc->sc_bus);
895
896         return (0);
897 }
898
899 usb_error_t
900 octusb_uninit(struct octusb_softc *sc)
901 {
902         uint8_t x;
903
904         USB_BUS_LOCK(&sc->sc_bus);
905
906         for (x = 0; x != sc->sc_noport; x++) {
907                 if (sc->sc_port[x].disabled == 0)
908                         cvmx_usb_shutdown(&sc->sc_port[x].state);
909         }
910         USB_BUS_UNLOCK(&sc->sc_bus);
911
912         return (0);
913
914 }
915
916 static void
917 octusb_suspend(struct octusb_softc *sc)
918 {
919         /* TODO */
920 }
921
922 static void
923 octusb_resume(struct octusb_softc *sc)
924 {
925         /* TODO */
926 }
927
928 /*------------------------------------------------------------------------*
929  *      octusb_interrupt - OCTUSB interrupt handler
930  *------------------------------------------------------------------------*/
931 void
932 octusb_interrupt(struct octusb_softc *sc)
933 {
934         USB_BUS_LOCK(&sc->sc_bus);
935
936         DPRINTFN(16, "real interrupt\n");
937
938         /* poll all the USB transfers */
939         octusb_interrupt_poll(sc);
940
941         USB_BUS_UNLOCK(&sc->sc_bus);
942 }
943
944 /*------------------------------------------------------------------------*
945  *      octusb_timeout - OCTUSB transfer timeout handler
946  *------------------------------------------------------------------------*/
947 static void
948 octusb_timeout(void *arg)
949 {
950         struct usb_xfer *xfer = arg;
951
952         DPRINTF("xfer=%p\n", xfer);
953
954         USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
955
956         /* transfer is transferred */
957         octusb_device_done(xfer, USB_ERR_TIMEOUT);
958 }
959
960 /*------------------------------------------------------------------------*
961  *      octusb_do_poll - OCTUSB poll transfers
962  *------------------------------------------------------------------------*/
963 static void
964 octusb_do_poll(struct usb_bus *bus)
965 {
966         struct octusb_softc *sc = OCTUSB_BUS2SC(bus);
967
968         USB_BUS_LOCK(&sc->sc_bus);
969         octusb_interrupt_poll(sc);
970         USB_BUS_UNLOCK(&sc->sc_bus);
971 }
972
973 static void
974 octusb_setup_standard_chain_sub(struct octusb_std_temp *temp)
975 {
976         struct octusb_td *td;
977
978         /* get current Transfer Descriptor */
979         td = temp->td_next;
980         temp->td = td;
981
982         /* prepare for next TD */
983         temp->td_next = td->obj_next;
984
985         /* fill out the Transfer Descriptor */
986         td->func = temp->func;
987         td->pc = temp->pc;
988         td->offset = temp->offset;
989         td->remainder = temp->len;
990         td->error_any = 0;
991         td->error_stall = 0;
992         td->short_pkt = temp->short_pkt;
993         td->alt_next = temp->setup_alt_next;
994 }
995
996 static void
997 octusb_setup_standard_chain(struct usb_xfer *xfer)
998 {
999         struct octusb_std_temp temp;
1000         struct octusb_td *td;
1001         uint32_t x;
1002
1003         DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
1004             xfer->address, UE_GET_ADDR(xfer->endpointno),
1005             xfer->sumlen, usbd_get_speed(xfer->xroot->udev));
1006
1007         /* setup starting point */
1008         td = xfer->td_start[0];
1009         xfer->td_transfer_first = td;
1010         xfer->td_transfer_cache = td;
1011
1012         temp.td = NULL;
1013         temp.td_next = td;
1014         temp.setup_alt_next = xfer->flags_int.short_frames_ok;
1015         temp.offset = 0;
1016
1017         /* check if we should prepend a setup message */
1018
1019         if (xfer->flags_int.control_xfr) {
1020
1021                 if (xfer->flags_int.control_hdr) {
1022
1023                         temp.func = &octusb_host_control_header_tx;
1024                         temp.len = xfer->frlengths[0];
1025                         temp.pc = xfer->frbuffers + 0;
1026                         temp.short_pkt = temp.len ? 1 : 0;
1027
1028                         /* check for last frame */
1029                         if (xfer->nframes == 1) {
1030                                 /*
1031                                  * no STATUS stage yet, SETUP is
1032                                  * last
1033                                  */
1034                                 if (xfer->flags_int.control_act)
1035                                         temp.setup_alt_next = 0;
1036                         }
1037                         octusb_setup_standard_chain_sub(&temp);
1038                 }
1039                 x = 1;
1040         } else {
1041                 x = 0;
1042         }
1043
1044         if (x != xfer->nframes) {
1045                 if (xfer->endpointno & UE_DIR_IN) {
1046                         if (xfer->flags_int.control_xfr)
1047                                 temp.func = &octusb_host_control_data_rx;
1048                         else
1049                                 temp.func = &octusb_non_control_data_rx;
1050                 } else {
1051                         if (xfer->flags_int.control_xfr)
1052                                 temp.func = &octusb_host_control_data_tx;
1053                         else
1054                                 temp.func = &octusb_non_control_data_tx;
1055                 }
1056
1057                 /* setup "pc" pointer */
1058                 temp.pc = xfer->frbuffers + x;
1059         }
1060         while (x != xfer->nframes) {
1061
1062                 /* DATA0 or DATA1 message */
1063
1064                 temp.len = xfer->frlengths[x];
1065
1066                 x++;
1067
1068                 if (x == xfer->nframes) {
1069                         if (xfer->flags_int.control_xfr) {
1070                                 /* no STATUS stage yet, DATA is last */
1071                                 if (xfer->flags_int.control_act)
1072                                         temp.setup_alt_next = 0;
1073                         } else {
1074                                 temp.setup_alt_next = 0;
1075                         }
1076                 }
1077                 if (temp.len == 0) {
1078
1079                         /* make sure that we send an USB packet */
1080
1081                         temp.short_pkt = 0;
1082
1083                 } else {
1084
1085                         /* regular data transfer */
1086
1087                         temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
1088                 }
1089
1090                 octusb_setup_standard_chain_sub(&temp);
1091
1092                 if (xfer->flags_int.isochronous_xfr) {
1093                         /* get next data offset */
1094                         temp.offset += temp.len;
1095                 } else {
1096                         /* get next Page Cache pointer */
1097                         temp.pc = xfer->frbuffers + x;
1098                 }
1099         }
1100
1101         /* check if we should append a status stage */
1102
1103         if (xfer->flags_int.control_xfr &&
1104             !xfer->flags_int.control_act) {
1105
1106                 temp.func = &octusb_host_control_status_tx;
1107                 temp.len = 0;
1108                 temp.pc = NULL;
1109                 temp.short_pkt = 0;
1110                 temp.setup_alt_next = 0;
1111
1112                 octusb_setup_standard_chain_sub(&temp);
1113         }
1114         /* must have at least one frame! */
1115         td = temp.td;
1116         xfer->td_transfer_last = td;
1117
1118         /* properly setup QH */
1119
1120         td->qh->ep_allocated = 0;
1121         td->qh->ep_toggle_next = xfer->endpoint->toggle_next ? 1 : 0;
1122 }
1123
1124 /*------------------------------------------------------------------------*
1125  *      octusb_device_done - OCTUSB transfers done code
1126  *
1127  * NOTE: This function can be called more than one time in a row.
1128  *------------------------------------------------------------------------*/
1129 static void
1130 octusb_device_done(struct usb_xfer *xfer, usb_error_t error)
1131 {
1132         USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
1133
1134         DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n",
1135             xfer, xfer->endpoint, error);
1136
1137         /*
1138          * 1) Free any endpoints.
1139          * 2) Control transfers can be split and we should not re-open
1140          *    the data pipe between transactions unless there is an error.
1141          */
1142         if ((xfer->flags_int.control_act == 0) || (error != 0)) {
1143                 struct octusb_td *td;
1144
1145                 td = xfer->td_start[0];
1146
1147                 octusb_host_free_endpoint(td);
1148         }
1149         /* dequeue transfer and start next transfer */
1150         usbd_transfer_done(xfer, error);
1151 }
1152
1153 /*------------------------------------------------------------------------*
1154  * octusb bulk support
1155  *------------------------------------------------------------------------*/
1156 static void
1157 octusb_device_bulk_open(struct usb_xfer *xfer)
1158 {
1159         return;
1160 }
1161
1162 static void
1163 octusb_device_bulk_close(struct usb_xfer *xfer)
1164 {
1165         octusb_device_done(xfer, USB_ERR_CANCELLED);
1166 }
1167
1168 static void
1169 octusb_device_bulk_enter(struct usb_xfer *xfer)
1170 {
1171         return;
1172 }
1173
1174 static void
1175 octusb_device_bulk_start(struct usb_xfer *xfer)
1176 {
1177         /* setup TDs */
1178         octusb_setup_standard_chain(xfer);
1179         octusb_start_standard_chain(xfer);
1180 }
1181
1182 struct usb_pipe_methods octusb_device_bulk_methods =
1183 {
1184         .open = octusb_device_bulk_open,
1185         .close = octusb_device_bulk_close,
1186         .enter = octusb_device_bulk_enter,
1187         .start = octusb_device_bulk_start,
1188 };
1189
1190 /*------------------------------------------------------------------------*
1191  * octusb control support
1192  *------------------------------------------------------------------------*/
1193 static void
1194 octusb_device_ctrl_open(struct usb_xfer *xfer)
1195 {
1196         return;
1197 }
1198
1199 static void
1200 octusb_device_ctrl_close(struct usb_xfer *xfer)
1201 {
1202         octusb_device_done(xfer, USB_ERR_CANCELLED);
1203 }
1204
1205 static void
1206 octusb_device_ctrl_enter(struct usb_xfer *xfer)
1207 {
1208         return;
1209 }
1210
1211 static void
1212 octusb_device_ctrl_start(struct usb_xfer *xfer)
1213 {
1214         /* setup TDs */
1215         octusb_setup_standard_chain(xfer);
1216         octusb_start_standard_chain(xfer);
1217 }
1218
1219 struct usb_pipe_methods octusb_device_ctrl_methods =
1220 {
1221         .open = octusb_device_ctrl_open,
1222         .close = octusb_device_ctrl_close,
1223         .enter = octusb_device_ctrl_enter,
1224         .start = octusb_device_ctrl_start,
1225 };
1226
1227 /*------------------------------------------------------------------------*
1228  * octusb interrupt support
1229  *------------------------------------------------------------------------*/
1230 static void
1231 octusb_device_intr_open(struct usb_xfer *xfer)
1232 {
1233         return;
1234 }
1235
1236 static void
1237 octusb_device_intr_close(struct usb_xfer *xfer)
1238 {
1239         octusb_device_done(xfer, USB_ERR_CANCELLED);
1240 }
1241
1242 static void
1243 octusb_device_intr_enter(struct usb_xfer *xfer)
1244 {
1245         return;
1246 }
1247
1248 static void
1249 octusb_device_intr_start(struct usb_xfer *xfer)
1250 {
1251         /* setup TDs */
1252         octusb_setup_standard_chain(xfer);
1253         octusb_start_standard_chain(xfer);
1254 }
1255
1256 struct usb_pipe_methods octusb_device_intr_methods =
1257 {
1258         .open = octusb_device_intr_open,
1259         .close = octusb_device_intr_close,
1260         .enter = octusb_device_intr_enter,
1261         .start = octusb_device_intr_start,
1262 };
1263
1264 /*------------------------------------------------------------------------*
1265  * octusb isochronous support
1266  *------------------------------------------------------------------------*/
1267 static void
1268 octusb_device_isoc_open(struct usb_xfer *xfer)
1269 {
1270         return;
1271 }
1272
1273 static void
1274 octusb_device_isoc_close(struct usb_xfer *xfer)
1275 {
1276         octusb_device_done(xfer, USB_ERR_CANCELLED);
1277 }
1278
1279 static void
1280 octusb_device_isoc_enter(struct usb_xfer *xfer)
1281 {
1282         struct octusb_softc *sc = OCTUSB_BUS2SC(xfer->xroot->bus);
1283         uint32_t temp;
1284         uint32_t frame_count;
1285         uint32_t fs_frames;
1286
1287         DPRINTFN(5, "xfer=%p next=%d nframes=%d\n",
1288             xfer, xfer->endpoint->isoc_next, xfer->nframes);
1289
1290         /* get the current frame index */
1291
1292         frame_count = cvmx_usb_get_frame_number(
1293             &sc->sc_port[xfer->xroot->udev->port_index].state);
1294
1295         /*
1296          * check if the frame index is within the window where the frames
1297          * will be inserted
1298          */
1299         temp = (frame_count - xfer->endpoint->isoc_next) & 0x7FF;
1300
1301         if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
1302                 fs_frames = (xfer->nframes + 7) / 8;
1303         } else {
1304                 fs_frames = xfer->nframes;
1305         }
1306
1307         if ((xfer->endpoint->is_synced == 0) || (temp < fs_frames)) {
1308                 /*
1309                  * If there is data underflow or the pipe queue is
1310                  * empty we schedule the transfer a few frames ahead
1311                  * of the current frame position. Else two isochronous
1312                  * transfers might overlap.
1313                  */
1314                 xfer->endpoint->isoc_next = (frame_count + 3) & 0x7FF;
1315                 xfer->endpoint->is_synced = 1;
1316                 DPRINTFN(2, "start next=%d\n", xfer->endpoint->isoc_next);
1317         }
1318         /*
1319          * compute how many milliseconds the insertion is ahead of the
1320          * current frame position:
1321          */
1322         temp = (xfer->endpoint->isoc_next - frame_count) & 0x7FF;
1323
1324         /*
1325          * pre-compute when the isochronous transfer will be finished:
1326          */
1327         xfer->isoc_time_complete =
1328             usb_isoc_time_expand(&sc->sc_bus, frame_count) + temp +
1329             fs_frames;
1330
1331         /* compute frame number for next insertion */
1332         xfer->endpoint->isoc_next += fs_frames;
1333 }
1334
1335 static void
1336 octusb_device_isoc_start(struct usb_xfer *xfer)
1337 {
1338         /* setup TDs */
1339         octusb_setup_standard_chain(xfer);
1340         octusb_start_standard_chain(xfer);
1341 }
1342
1343 struct usb_pipe_methods octusb_device_isoc_methods =
1344 {
1345         .open = octusb_device_isoc_open,
1346         .close = octusb_device_isoc_close,
1347         .enter = octusb_device_isoc_enter,
1348         .start = octusb_device_isoc_start,
1349 };
1350
1351 /*------------------------------------------------------------------------*
1352  * OCTUSB root HUB support
1353  *------------------------------------------------------------------------*
1354  * Simulate a hardware HUB by handling all the necessary requests.
1355  *------------------------------------------------------------------------*/
1356 static const
1357 struct usb_device_descriptor octusb_devd = {
1358         .bLength = sizeof(octusb_devd),
1359         .bDescriptorType = UDESC_DEVICE,
1360         .bcdUSB = {0x00, 0x02},
1361         .bDeviceClass = UDCLASS_HUB,
1362         .bDeviceSubClass = UDSUBCLASS_HUB,
1363         .bDeviceProtocol = UDPROTO_FSHUB,
1364         .bMaxPacketSize = 64,
1365         .idVendor = {0},
1366         .idProduct = {0},
1367         .bcdDevice = {0x00, 0x01},
1368         .iManufacturer = 1,
1369         .iProduct = 2,
1370         .iSerialNumber = 0,
1371         .bNumConfigurations = 1,
1372 };
1373
1374 static const
1375 struct usb_device_qualifier octusb_odevd = {
1376         .bLength = sizeof(octusb_odevd),
1377         .bDescriptorType = UDESC_DEVICE_QUALIFIER,
1378         .bcdUSB = {0x00, 0x02},
1379         .bDeviceClass = UDCLASS_HUB,
1380         .bDeviceSubClass = UDSUBCLASS_HUB,
1381         .bDeviceProtocol = UDPROTO_FSHUB,
1382         .bMaxPacketSize0 = 0,
1383         .bNumConfigurations = 0,
1384         .bReserved = 0,
1385 };
1386
1387 static const
1388 struct octusb_config_desc octusb_confd = {
1389         .confd = {
1390                 .bLength = sizeof(struct usb_config_descriptor),
1391                 .bDescriptorType = UDESC_CONFIG,
1392                 .wTotalLength[0] = sizeof(octusb_confd),
1393                 .bNumInterface = 1,
1394                 .bConfigurationValue = 1,
1395                 .iConfiguration = 0,
1396                 .bmAttributes = UC_SELF_POWERED,
1397                 .bMaxPower = 0          /* max power */
1398         },
1399         .ifcd = {
1400                 .bLength = sizeof(struct usb_interface_descriptor),
1401                 .bDescriptorType = UDESC_INTERFACE,
1402                 .bNumEndpoints = 1,
1403                 .bInterfaceClass = UICLASS_HUB,
1404                 .bInterfaceSubClass = UISUBCLASS_HUB,
1405                 .bInterfaceProtocol = UIPROTO_FSHUB,
1406         },
1407         .endpd = {
1408                 .bLength = sizeof(struct usb_endpoint_descriptor),
1409                 .bDescriptorType = UDESC_ENDPOINT,
1410                 .bEndpointAddress = UE_DIR_IN | OCTUSB_INTR_ENDPT,
1411                 .bmAttributes = UE_INTERRUPT,
1412                 .wMaxPacketSize[0] = 8, /* max packet (63 ports) */
1413                 .bInterval = 255,
1414         },
1415 };
1416
1417 static const
1418 struct usb_hub_descriptor_min octusb_hubd =
1419 {
1420         .bDescLength = sizeof(octusb_hubd),
1421         .bDescriptorType = UDESC_HUB,
1422         .bNbrPorts = 2,
1423         .wHubCharacteristics = {UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL, 0},
1424         .bPwrOn2PwrGood = 50,
1425         .bHubContrCurrent = 0,
1426         .DeviceRemovable = {0x00},      /* all ports are removable */
1427 };
1428
1429 static usb_error_t
1430 octusb_roothub_exec(struct usb_device *udev,
1431     struct usb_device_request *req, const void **pptr, uint16_t *plength)
1432 {
1433         struct octusb_softc *sc = OCTUSB_BUS2SC(udev->bus);
1434         const void *ptr;
1435         const char *str_ptr;
1436         uint16_t value;
1437         uint16_t index;
1438         uint16_t status;
1439         uint16_t change;
1440         uint16_t len;
1441         usb_error_t err;
1442         cvmx_usb_port_status_t usb_port_status;
1443
1444         USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
1445
1446         /* XXX disable power save mode, hence it is not supported */
1447         udev->power_mode = USB_POWER_MODE_ON;
1448
1449         /* buffer reset */
1450         ptr = (const void *)&sc->sc_hub_desc.temp;
1451         len = 0;
1452         err = 0;
1453
1454         value = UGETW(req->wValue);
1455         index = UGETW(req->wIndex);
1456
1457         DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
1458             "wValue=0x%04x wIndex=0x%04x\n",
1459             req->bmRequestType, req->bRequest,
1460             UGETW(req->wLength), value, index);
1461
1462 #define C(x,y) ((x) | ((y) << 8))
1463         switch (C(req->bRequest, req->bmRequestType)) {
1464         case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
1465         case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
1466         case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
1467                 break;
1468         case C(UR_GET_CONFIG, UT_READ_DEVICE):
1469                 len = 1;
1470                 sc->sc_hub_desc.temp[0] = sc->sc_conf;
1471                 break;
1472         case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
1473                 switch (value >> 8) {
1474                 case UDESC_DEVICE:
1475                         if ((value & 0xff) != 0) {
1476                                 err = USB_ERR_IOERROR;
1477                                 goto done;
1478                         }
1479                         len = sizeof(octusb_devd);
1480
1481                         ptr = (const void *)&octusb_devd;
1482                         break;
1483
1484                 case UDESC_DEVICE_QUALIFIER:
1485                         if ((value & 0xff) != 0) {
1486                                 err = USB_ERR_IOERROR;
1487                                 goto done;
1488                         }
1489                         len = sizeof(octusb_odevd);
1490                         ptr = (const void *)&octusb_odevd;
1491                         break;
1492
1493                 case UDESC_CONFIG:
1494                         if ((value & 0xff) != 0) {
1495                                 err = USB_ERR_IOERROR;
1496                                 goto done;
1497                         }
1498                         len = sizeof(octusb_confd);
1499                         ptr = (const void *)&octusb_confd;
1500                         break;
1501
1502                 case UDESC_STRING:
1503                         switch (value & 0xff) {
1504                         case 0: /* Language table */
1505                                 str_ptr = "\001";
1506                                 break;
1507
1508                         case 1: /* Vendor */
1509                                 str_ptr = "Cavium Networks";
1510                                 break;
1511
1512                         case 2: /* Product */
1513                                 str_ptr = "OCTUSB Root HUB";
1514                                 break;
1515
1516                         default:
1517                                 str_ptr = "";
1518                                 break;
1519                         }
1520
1521                         len = usb_make_str_desc(sc->sc_hub_desc.temp,
1522                             sizeof(sc->sc_hub_desc.temp), str_ptr);
1523                         break;
1524
1525                 default:
1526                         err = USB_ERR_IOERROR;
1527                         goto done;
1528                 }
1529                 break;
1530         case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
1531                 len = 1;
1532                 sc->sc_hub_desc.temp[0] = 0;
1533                 break;
1534         case C(UR_GET_STATUS, UT_READ_DEVICE):
1535                 len = 2;
1536                 USETW(sc->sc_hub_desc.stat.wStatus, UDS_SELF_POWERED);
1537                 break;
1538         case C(UR_GET_STATUS, UT_READ_INTERFACE):
1539         case C(UR_GET_STATUS, UT_READ_ENDPOINT):
1540                 len = 2;
1541                 USETW(sc->sc_hub_desc.stat.wStatus, 0);
1542                 break;
1543         case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
1544                 if (value >= OCTUSB_MAX_DEVICES) {
1545                         err = USB_ERR_IOERROR;
1546                         goto done;
1547                 }
1548                 sc->sc_addr = value;
1549                 break;
1550         case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
1551                 if ((value != 0) && (value != 1)) {
1552                         err = USB_ERR_IOERROR;
1553                         goto done;
1554                 }
1555                 sc->sc_conf = value;
1556                 break;
1557         case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
1558                 break;
1559         case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
1560         case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
1561         case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
1562                 err = USB_ERR_IOERROR;
1563                 goto done;
1564         case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
1565                 break;
1566         case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
1567                 break;
1568                 /* Hub requests */
1569         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
1570                 break;
1571         case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
1572                 DPRINTFN(4, "UR_CLEAR_PORT_FEATURE "
1573                     "port=%d feature=%d\n",
1574                     index, value);
1575                 if ((index < 1) ||
1576                     (index > sc->sc_noport) ||
1577                     sc->sc_port[index - 1].disabled) {
1578                         err = USB_ERR_IOERROR;
1579                         goto done;
1580                 }
1581                 index--;
1582
1583                 switch (value) {
1584                 case UHF_PORT_ENABLE:
1585                         cvmx_usb_disable(&sc->sc_port[index].state);
1586                         break;
1587                 case UHF_PORT_SUSPEND:
1588                 case UHF_PORT_RESET:
1589                         break;
1590                 case UHF_C_PORT_CONNECTION:
1591                         cvmx_usb_set_status(&sc->sc_port[index].state,
1592                             cvmx_usb_get_status(&sc->sc_port[index].state));
1593                         break;
1594                 case UHF_C_PORT_ENABLE:
1595                         cvmx_usb_set_status(&sc->sc_port[index].state,
1596                             cvmx_usb_get_status(&sc->sc_port[index].state));
1597                         break;
1598                 case UHF_C_PORT_OVER_CURRENT:
1599                         cvmx_usb_set_status(&sc->sc_port[index].state,
1600                             cvmx_usb_get_status(&sc->sc_port[index].state));
1601                         break;
1602                 case UHF_C_PORT_RESET:
1603                         sc->sc_isreset = 0;
1604                         goto done;
1605                 case UHF_C_PORT_SUSPEND:
1606                         break;
1607                 case UHF_PORT_CONNECTION:
1608                 case UHF_PORT_OVER_CURRENT:
1609                 case UHF_PORT_POWER:
1610                 case UHF_PORT_LOW_SPEED:
1611                 default:
1612                         err = USB_ERR_IOERROR;
1613                         goto done;
1614                 }
1615                 break;
1616         case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
1617                 if ((value & 0xff) != 0) {
1618                         err = USB_ERR_IOERROR;
1619                         goto done;
1620                 }
1621                 sc->sc_hubd = octusb_hubd;
1622                 sc->sc_hubd.bNbrPorts = sc->sc_noport;
1623                 len = sizeof(sc->sc_hubd);
1624                 ptr = (const void *)&sc->sc_hubd;
1625                 break;
1626         case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
1627                 len = 16;
1628                 memset(sc->sc_hub_desc.temp, 0, 16);
1629                 break;
1630         case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
1631                 if ((index < 1) ||
1632                     (index > sc->sc_noport) ||
1633                     sc->sc_port[index - 1].disabled) {
1634                         err = USB_ERR_IOERROR;
1635                         goto done;
1636                 }
1637                 index--;
1638
1639                 usb_port_status = cvmx_usb_get_status(&sc->sc_port[index].state);
1640
1641                 status = change = 0;
1642                 if (usb_port_status.connected)
1643                         status |= UPS_CURRENT_CONNECT_STATUS;
1644                 if (usb_port_status.port_enabled)
1645                         status |= UPS_PORT_ENABLED;
1646                 if (usb_port_status.port_over_current)
1647                         status |= UPS_OVERCURRENT_INDICATOR;
1648                 if (usb_port_status.port_powered)
1649                         status |= UPS_PORT_POWER;
1650
1651                 switch (usb_port_status.port_speed) {
1652                 case CVMX_USB_SPEED_HIGH:
1653                         status |= UPS_HIGH_SPEED;
1654                         break;
1655                 case CVMX_USB_SPEED_FULL:
1656                         break;
1657                 default:
1658                         status |= UPS_LOW_SPEED;
1659                         break;
1660                 }
1661
1662                 if (usb_port_status.connect_change)
1663                         change |= UPS_C_CONNECT_STATUS;
1664                 if (sc->sc_isreset)
1665                         change |= UPS_C_PORT_RESET;
1666
1667                 USETW(sc->sc_hub_desc.ps.wPortStatus, status);
1668                 USETW(sc->sc_hub_desc.ps.wPortChange, change);
1669
1670                 len = sizeof(sc->sc_hub_desc.ps);
1671                 break;
1672         case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
1673                 err = USB_ERR_IOERROR;
1674                 goto done;
1675         case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
1676                 break;
1677         case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
1678                 if ((index < 1) ||
1679                     (index > sc->sc_noport) ||
1680                     sc->sc_port[index - 1].disabled) {
1681                         err = USB_ERR_IOERROR;
1682                         goto done;
1683                 }
1684                 index--;
1685
1686                 switch (value) {
1687                 case UHF_PORT_ENABLE:
1688                         break;
1689                 case UHF_PORT_RESET:
1690                         cvmx_usb_disable(&sc->sc_port[index].state);
1691                         if (cvmx_usb_enable(&sc->sc_port[index].state)) {
1692                                 err = USB_ERR_IOERROR;
1693                                 goto done;
1694                         }
1695                         sc->sc_isreset = 1;
1696                         goto done;
1697                 case UHF_PORT_POWER:
1698                         /* pretend we turned on power */
1699                         goto done;
1700                 case UHF_PORT_SUSPEND:
1701                 case UHF_C_PORT_CONNECTION:
1702                 case UHF_C_PORT_ENABLE:
1703                 case UHF_C_PORT_OVER_CURRENT:
1704                 case UHF_PORT_CONNECTION:
1705                 case UHF_PORT_OVER_CURRENT:
1706                 case UHF_PORT_LOW_SPEED:
1707                 case UHF_C_PORT_SUSPEND:
1708                 case UHF_C_PORT_RESET:
1709                 default:
1710                         err = USB_ERR_IOERROR;
1711                         goto done;
1712                 }
1713                 break;
1714         default:
1715                 err = USB_ERR_IOERROR;
1716                 goto done;
1717         }
1718 done:
1719         *plength = len;
1720         *pptr = ptr;
1721         return (err);
1722 }
1723
1724 static void
1725 octusb_xfer_setup(struct usb_setup_params *parm)
1726 {
1727         struct usb_page_search page_info;
1728         struct usb_page_cache *pc;
1729         struct octusb_softc *sc;
1730         struct octusb_qh *qh;
1731         struct usb_xfer *xfer;
1732         void *last_obj;
1733         uint32_t n;
1734         uint32_t ntd;
1735
1736         sc = OCTUSB_BUS2SC(parm->udev->bus);
1737         xfer = parm->curr_xfer;
1738         qh = NULL;
1739
1740         /*
1741          * NOTE: This driver does not use any of the parameters that
1742          * are computed from the following values. Just set some
1743          * reasonable dummies:
1744          */
1745
1746         parm->hc_max_packet_size = 0x400;
1747         parm->hc_max_packet_count = 3;
1748         parm->hc_max_frame_size = 0xC00;
1749
1750         usbd_transfer_setup_sub(parm);
1751
1752         if (parm->err)
1753                 return;
1754
1755         /* Allocate a queue head */
1756
1757         if (usbd_transfer_setup_sub_malloc(
1758             parm, &pc, sizeof(struct octusb_qh),
1759             USB_HOST_ALIGN, 1)) {
1760                 parm->err = USB_ERR_NOMEM;
1761                 return;
1762         }
1763         if (parm->buf) {
1764                 usbd_get_page(pc, 0, &page_info);
1765
1766                 qh = page_info.buffer;
1767
1768                 /* fill out QH */
1769
1770                 qh->sc = OCTUSB_BUS2SC(xfer->xroot->bus);
1771                 qh->max_frame_size = xfer->max_frame_size;
1772                 qh->max_packet_size = xfer->max_packet_size;
1773                 qh->ep_num = xfer->endpointno;
1774                 qh->ep_type = xfer->endpoint->edesc->bmAttributes;
1775                 qh->dev_addr = xfer->address;
1776                 qh->dev_speed = usbd_get_speed(xfer->xroot->udev);
1777                 qh->port_index = xfer->xroot->udev->port_index;
1778
1779                 switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
1780                 case UE_INTERRUPT:
1781                         if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH)
1782                                 qh->ep_interval = xfer->interval * 8;
1783                         else
1784                                 qh->ep_interval = xfer->interval * 1;
1785                         break;
1786                 case UE_ISOCHRONOUS:
1787                         qh->ep_interval = 1 << xfer->fps_shift;
1788                         break;
1789                 default:
1790                         qh->ep_interval = 0;
1791                         break;
1792                 }
1793
1794                 qh->ep_mult = xfer->max_packet_count & 3;
1795                 qh->hs_hub_addr = xfer->xroot->udev->hs_hub_addr;
1796                 qh->hs_hub_port = xfer->xroot->udev->hs_port_no;
1797         }
1798         xfer->qh_start[0] = qh;
1799
1800         /* Allocate a fixup buffer */
1801
1802         if (usbd_transfer_setup_sub_malloc(
1803             parm, &pc, OCTUSB_MAX_FIXUP,
1804             OCTUSB_MAX_FIXUP, 1)) {
1805                 parm->err = USB_ERR_NOMEM;
1806                 return;
1807         }
1808         if (parm->buf) {
1809                 usbd_get_page(pc, 0, &page_info);
1810
1811                 qh->fixup_phys = page_info.physaddr;
1812                 qh->fixup_pc = pc;
1813                 qh->fixup_buf = page_info.buffer;
1814         }
1815         /* Allocate transfer descriptors */
1816
1817         last_obj = NULL;
1818
1819         ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ;
1820
1821         if (usbd_transfer_setup_sub_malloc(
1822             parm, &pc, sizeof(struct octusb_td),
1823             USB_HOST_ALIGN, ntd)) {
1824                 parm->err = USB_ERR_NOMEM;
1825                 return;
1826         }
1827         if (parm->buf) {
1828                 for (n = 0; n != ntd; n++) {
1829                         struct octusb_td *td;
1830
1831                         usbd_get_page(pc + n, 0, &page_info);
1832
1833                         td = page_info.buffer;
1834
1835                         td->qh = qh;
1836                         td->obj_next = last_obj;
1837
1838                         last_obj = td;
1839                 }
1840         }
1841         xfer->td_start[0] = last_obj;
1842 }
1843
1844 static void
1845 octusb_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
1846     struct usb_endpoint *ep)
1847 {
1848         struct octusb_softc *sc = OCTUSB_BUS2SC(udev->bus);
1849
1850         DPRINTFN(2, "endpoint=%p, addr=%d, endpt=%d, mode=%d (%d)\n",
1851             ep, udev->address, edesc->bEndpointAddress,
1852             udev->flags.usb_mode, sc->sc_addr);
1853
1854         if (udev->flags.usb_mode != USB_MODE_HOST) {
1855                 /* not supported */
1856                 return;
1857         }
1858         if (udev->device_index != sc->sc_addr) {
1859                 switch (edesc->bmAttributes & UE_XFERTYPE) {
1860                 case UE_CONTROL:
1861                         ep->methods = &octusb_device_ctrl_methods;
1862                         break;
1863                 case UE_INTERRUPT:
1864                         ep->methods = &octusb_device_intr_methods;
1865                         break;
1866                 case UE_ISOCHRONOUS:
1867                         if (udev->speed != USB_SPEED_LOW)
1868                                 ep->methods = &octusb_device_isoc_methods;
1869                         break;
1870                 case UE_BULK:
1871                         ep->methods = &octusb_device_bulk_methods;
1872                         break;
1873                 default:
1874                         /* do nothing */
1875                         break;
1876                 }
1877         }
1878 }
1879
1880 static void
1881 octusb_xfer_unsetup(struct usb_xfer *xfer)
1882 {
1883         DPRINTF("Nothing to do.\n");
1884 }
1885
1886 static void
1887 octusb_get_dma_delay(struct usb_device *udev, uint32_t *pus)
1888 {
1889         /* DMA delay - wait until any use of memory is finished */
1890         *pus = (2125);                  /* microseconds */
1891 }
1892
1893 static void
1894 octusb_device_resume(struct usb_device *udev)
1895 {
1896         DPRINTF("Nothing to do.\n");
1897 }
1898
1899 static void
1900 octusb_device_suspend(struct usb_device *udev)
1901 {
1902         DPRINTF("Nothing to do.\n");
1903 }
1904
1905 static void
1906 octusb_set_hw_power(struct usb_bus *bus)
1907 {
1908         DPRINTF("Nothing to do.\n");
1909 }
1910
1911 static void
1912 octusb_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
1913 {
1914         struct octusb_softc *sc = OCTUSB_BUS2SC(bus);
1915
1916         switch (state) {
1917         case USB_HW_POWER_SUSPEND:
1918                 octusb_suspend(sc);
1919                 break;
1920         case USB_HW_POWER_SHUTDOWN:
1921                 octusb_uninit(sc);
1922                 break;
1923         case USB_HW_POWER_RESUME:
1924                 octusb_resume(sc);
1925                 break;
1926         default:
1927                 break;
1928         }
1929 }
1930
1931 struct usb_bus_methods octusb_bus_methods = {
1932         .endpoint_init = octusb_ep_init,
1933         .xfer_setup = octusb_xfer_setup,
1934         .xfer_unsetup = octusb_xfer_unsetup,
1935         .get_dma_delay = octusb_get_dma_delay,
1936         .device_resume = octusb_device_resume,
1937         .device_suspend = octusb_device_suspend,
1938         .set_hw_power = octusb_set_hw_power,
1939         .set_hw_power_sleep = octusb_set_hw_power_sleep,
1940         .roothub_exec = octusb_roothub_exec,
1941         .xfer_poll = octusb_do_poll,
1942 };