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