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