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