LibXenon
Bare-metal Xbox 360 homebrew library
Loading...
Searching...
No Matches
ohci.c
Go to the documentation of this file.
1/* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * OHCI device driver File: ohci.c
5 *
6 * Open Host Controller Interface low-level routines
7 *
8 * Author: Mitch Lichtenberg
9 *
10 *********************************************************************
11 *
12 * Copyright 2000,2001,2002,2003,2005
13 * Broadcom Corporation. All rights reserved.
14 *
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
21 *
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
25 *
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
31 *
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
46
47
48#ifndef _CFE_
49#include <stdio.h>
50#include <stdlib.h>
51#include <unistd.h>
52#include <string.h>
53#include <stdint.h>
54#include "usbhack.h"
55#define CPUCFG_COHERENT_DMA 1 /* hack runs on a PC, PCs are coherent */
56#define ENDIAN_BIG 0
57#define ENDIAN_LITTLE 1 /* hack runs on PC, PCs are little endian */
58#include "lib_malloc.h"
59#include "lib_queue.h"
60#else
61#include "cfe.h"
62#endif
63
64#include "usbchap9.h"
65#include "usbd.h"
66#include "ohci.h"
67
68
69/* *********************************************************************
70 * Macros for dealing with hardware
71 *
72 * This is all yucky stuff that needs to be made more
73 * processor-independent. It's mostly here now to help us with
74 * our test harness.
75 ********************************************************************* */
76
77#if defined(_CFE_) && ENDIAN_BIG
78# if defined(BCM47XX)
79#define BSWAP32(x) (x)
80# else
81#define BSWAP32(x) __builtin_bswap32(x)
82# endif
83#else
84#define BSWAP32(x) (x)
85#endif
86
87#ifndef _CFE_
88extern uint32_t vtop(void *ptr);
89extern void *ptov(uint32_t x);
90#define OHCI_VTOP(ptr) vtop(ptr)
91#define OHCI_PTOV(ptr) ptov(ptr)
92#define OHCI_VTOD(ptr) OHCI_VTOP(ptr)
93#define OHCI_DTOV(ptr) OHCI_PTOV(ptr)
94#define OHCI_WRITECSR(softc,x,y) \
95 *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t)))) = (y)
96#define OHCI_READCSR(softc,x) \
97 *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t))))
98#else /* _CFE_ */
99
100#define OHCI_VTOP(ptr) ((uint32_t)PHYSADDR((long)(ptr)))
101
102#if CPUCFG_COHERENT_DMA
103#define OHCI_PTOV(ptr) ((void *)(KERNADDR(ptr)))
104#else
105#define OHCI_PTOV(ptr) ((void *)(UNCADDR(ptr)))
106#endif
107
108/* The following macros are for mapping between addresses of data (but
109 not control blocks) and corresponding DMA addresses that will
110 present the data in match-bytes order. */
111
112#if ENDIAN_BIG && defined(BCM47XX)
113#define PHYS_TO_DMA(a) ((a) + 0x10000000)
114#define DMA_TO_PHYS(a) ((a) - 0x10000000)
115#else
116#define PHYS_TO_DMA(a) (a)
117#define DMA_TO_PHYS(a) (a)
118#endif
119
120#define OHCI_DTOV(ptr) (OHCI_PTOV(DMA_TO_PHYS(ptr)))
121#define OHCI_VTOD(ptr) (PHYS_TO_DMA(OHCI_VTOP(ptr)))
122
123#define OHCI_WRITECSR(softc,x,y) \
124 write32(((softc)->ohci_regs + (x)),(y))
125#define OHCI_READCSR(softc,x) \
126 read32(((softc)->ohci_regs + (x)))
127#endif /* _CFE_ */
128
129#define OHCI_INVAL_RANGE(s,l) memdcbf(s,l)
130#define OHCI_FLUSH_RANGE(s,l) memdcbst(s,l)
131
132/*
133 * Debug message macro
134 */
135
136//#define _OHCI_DEBUG_
137
138#ifdef _OHCI_DEBUG_
139#define OHCIDEBUG(x) x
140#else
141#define OHCIDEBUG(x)
142#endif
143
144/* *********************************************************************
145 * Bit-reverse table - this table consists of the numbers
146 * at its index, listed in reverse. So, the reverse of 0000 0010
147 * is 0100 0000.
148 ********************************************************************* */
149
150const static int ohci_revbits[OHCI_INTTABLE_SIZE] = {
151 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
152 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
153 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
154 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f
155};
156
157
158/* *********************************************************************
159 * Macros to convert from "hardware" endpoint and transfer
160 * descriptors (ohci_ed_t, ohci_td_t) to "software"
161 * data structures (ohci_transfer_t, ohci_endpoint_t).
162 *
163 * Basically, there are two tables, indexed by the same value
164 * By subtracting the base of one pool from a pointer, we get
165 * the index into the other table.
166 *
167 * We *could* have included the ed and td in the software
168 * data structures, but placing all the hardware stuff in one
169 * pool will make it easier for hardware that does not handle
170 * coherent DMA, since we can be less careful about what we flush
171 * and what we invalidate.
172 ********************************************************************* */
173
174#define ohci_td_from_transfer(softc,transfer) \
175 ((softc)->ohci_hwtdpool + ((transfer) - (softc)->ohci_transfer_pool))
176
177#define ohci_transfer_from_td(softc,td) \
178 ((softc)->ohci_transfer_pool + ((td) - (softc)->ohci_hwtdpool))
179
180#define ohci_ed_from_endpoint(softc,endpoint) \
181 ((softc)->ohci_hwedpool + ((endpoint) - (softc)->ohci_endpoint_pool))
182
183#define ohci_endpoint_from_ed(softc,ed) \
184 ((softc)->ohci_endpoint_pool + ((ed) - (softc)->ohci_hwedpool))
185
186/* *********************************************************************
187 * Forward declarations
188 ********************************************************************* */
189
190static int ohci_roothub_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur);
191static void ohci_roothub_statchg(ohci_softc_t *softc);
193
194
195/* *********************************************************************
196 * Globals
197 ********************************************************************* */
198
199int ohcidebug = 0;
201void ohci_dumpportstat(int idx,uint32_t reg);
207
208
209/* *********************************************************************
210 * Some debug routines
211 ********************************************************************* */
212
213#ifdef _OHCI_DEBUG_
215{
216 printf("HubStatus: %08X ",reg);
217
218 if (reg & M_OHCI_RHSTATUS_LPS) printf("LocalPowerStatus ");
219 if (reg & M_OHCI_RHSTATUS_OCI) printf("OverCurrent ");
220 if (reg & M_OHCI_RHSTATUS_DRWE) printf("DeviceRemoteWakeupEnable ");
221 if (reg & M_OHCI_RHSTATUS_LPSC) printf("LocalPowerStatusChange ");
222 if (reg & M_OHCI_RHSTATUS_OCIC) printf("OverCurrentIndicatorChange ");
223 printf("\n");
224}
225
226void ohci_dumpportstat(int idx,uint32_t reg)
227{
228 printf("Port %d: %08X ",idx,reg);
229 if (reg & M_OHCI_RHPORTSTAT_CCS) printf("Connected ");
230 if (reg & M_OHCI_RHPORTSTAT_PES) printf("PortEnabled ");
231 if (reg & M_OHCI_RHPORTSTAT_PSS) printf("PortSuspended ");
232 if (reg & M_OHCI_RHPORTSTAT_POCI) printf("PortOverCurrent ");
233 if (reg & M_OHCI_RHPORTSTAT_PRS) printf("PortReset ");
234 if (reg & M_OHCI_RHPORTSTAT_PPS) printf("PortPowered ");
235 if (reg & M_OHCI_RHPORTSTAT_LSDA) printf("LowSpeed ");
236 if (reg & M_OHCI_RHPORTSTAT_CSC) printf("ConnectStatusChange ");
237 if (reg & M_OHCI_RHPORTSTAT_PESC) printf("PortEnableStatusChange ");
238 if (reg & M_OHCI_RHPORTSTAT_PSSC) printf("PortSuspendStatusChange ");
239 if (reg & M_OHCI_RHPORTSTAT_OCIC) printf("OverCurrentIndicatorChange ");
240 if (reg & M_OHCI_RHPORTSTAT_PRSC) printf("PortResetStatusChange ");
241 printf("\n");
242}
243
244void ohci_dumptd(ohci_softc_t *softc,ohci_td_t *td)
245{
246 uint32_t ctl;
247 static char *pids[4] = {"SETUP","OUT","IN","RSVD"};
248
249 ctl = BSWAP32(td->td_control);
250
251 printf("[%08X] ctl=%08X (DP=%s,DI=%d,T=%d,EC=%d,CC=%d%s) cbp=%08X be=%08X next=%08X\n",
252 OHCI_VTOP(td),
253 ctl,
254 pids[G_OHCI_TD_PID(ctl)],
255 G_OHCI_TD_DI(ctl),
256 G_OHCI_TD_DT(ctl),
257 G_OHCI_TD_EC(ctl),
258 G_OHCI_TD_CC(ctl),
259 (ctl & M_OHCI_TD_SHORTOK) ? ",R" : "",
260 BSWAP32(td->td_cbp),
261 BSWAP32(td->td_be),
262 BSWAP32(td->td_next_td));
263}
264
266{
267 ohci_transfer_t *transfer;
268 int idx = 0;
269 for (;;) {
270 printf("%d:[%08X] ctl=%08X cbp=%08X be=%08X next=%08X ",
271 idx,
272 OHCI_VTOP(td),
273 BSWAP32(td->td_control),
274 BSWAP32(td->td_cbp),
275 BSWAP32(td->td_be),
276 BSWAP32(td->td_next_td));
277
278 transfer = ohci_transfer_from_td(softc,td);
279 printf("Req=%p",transfer->t_ref);
280 printf("\n");
281 if (!td->td_next_td) break;
282 td = (ohci_td_t *) OHCI_PTOV(BSWAP32(td->td_next_td));
283 idx++;
284 }
285}
286
287void ohci_dumped(ohci_softc_t *softc,ohci_ed_t *ed)
288{
289 uint32_t ctl;
290 static char *pids[4] = {"FTD","OUT","IN","FTD"};
291
292 ctl = BSWAP32(ed->ed_control),
293
294 printf("[%08X] Ctl=%08X (MPS=%d%s%s%s,EN=%d,FA=%d,D=%s) Tailp=%08X headp=%08X next=%08X %s\n",
295 OHCI_VTOP(ed),
296 ctl,
297 G_OHCI_ED_MPS(ctl),
298 (ctl & M_OHCI_ED_LOWSPEED) ? ",LS" : "",
299 (ctl & M_OHCI_ED_SKIP) ? ",SKIP" : "",
300 (ctl & M_OHCI_ED_ISOCFMT) ? ",ISOC" : "",
301 G_OHCI_ED_EN(ctl),
302 G_OHCI_ED_FA(ctl),
303 pids[G_OHCI_ED_DIR(ctl)],
304 BSWAP32(ed->ed_tailp),
305 BSWAP32(ed->ed_headp),
306 BSWAP32(ed->ed_next_ed),
307 BSWAP32(ed->ed_headp) & M_OHCI_ED_HALT ? "HALT" : "");
308 if ((ed->ed_headp & M_OHCI_ED_PTRMASK) == 0) return;
310}
311
313{
314 int idx = 0;
315 for (;;) {
316 printf("---\nED#%d -> ",idx);
317 ohci_dumped(softc,ed);
318 if (!ed->ed_next_ed) break;
319 if (idx > 50) break;
320 ed = (ohci_ed_t *) OHCI_PTOV(BSWAP32(ed->ed_next_ed));
321 idx++;
322 }
323}
324
325void ohci_dumpdoneq(ohci_softc_t *softc)
326{
327 uint32_t donehead = softc->ohci_hcca->hcca_donehead;
328 uint32_t doneq;
329 ohci_td_t *td;
330
331 doneq = BSWAP32(donehead);
332
333 td = (ohci_td_t *) OHCI_PTOV(doneq);
334
335 printf("Done Queue:\n"); ohci_dumptdchain(softc,td);
336
337}
338
339
340static void eptstats(ohci_softc_t *softc)
341{
342 int cnt;
344 cnt = 0;
345
346 e = softc->ohci_endpoint_freelist;
347 while (e) { e = e->ep_next; cnt++; }
348 printf("%d left, %d inuse\n",cnt,OHCI_EDPOOL_SIZE-cnt);
349}
350#endif
351
352
353
354/* *********************************************************************
355 * _ohci_allocept(softc)
356 *
357 * Allocate an endpoint data structure from the pool, and
358 * make it ready for use. The endpoint is NOT attached to
359 * the hardware at this time.
360 *
361 * Input parameters:
362 * softc - our OHCI controller
363 *
364 * Return value:
365 * pointer to endpoint or NULL
366 ********************************************************************* */
367
368static ohci_endpoint_t *_ohci_allocept(ohci_softc_t *softc)
369{
371 ohci_ed_t *ed;
372
373#ifdef _OHCI_DEBUG_
374 if (ohcidebug > 2) {
375 printf("AllocEpt: ");eptstats(softc);
376 }
377#endif
378
379 e = softc->ohci_endpoint_freelist;
380
381 if (!e) {
382 OHCIDEBUG(printf("No endpoints left!\n"));
383 return NULL;
384 }
385
387
388 ed = ohci_ed_from_endpoint(softc,e);
389
391 ed->ed_tailp = BSWAP32(0);
392 ed->ed_headp = BSWAP32(0);
393 ed->ed_next_ed = BSWAP32(0);
394
395 e->ep_phys = OHCI_VTOP(ed);
396 e->ep_next = NULL;
397
398 return e;
399}
400
401
402/* *********************************************************************
403 * _ohci_allocxfer(softc)
404 *
405 * Allocate a transfer descriptor. It is prepared for use
406 * but not attached to the hardware.
407 *
408 * Input parameters:
409 * softc - our OHCI controller
410 *
411 * Return value:
412 * transfer descriptor, or NULL
413 ********************************************************************* */
414
415static ohci_transfer_t *_ohci_allocxfer(ohci_softc_t *softc)
416{
418 ohci_td_t *td;
419
420#ifdef _OHCI_DEBUG_
421 if (ohcidebug > 2) {
422 int cnt;
423 cnt = 0;
424 t = softc->ohci_transfer_freelist;
425 while (t) { t = t->t_next; cnt++; }
426 printf("AllocXfer: %d left, %d inuse\n",cnt,OHCI_TDPOOL_SIZE-cnt);
427 }
428#endif
429
430 t = softc->ohci_transfer_freelist;
431
432 if (!t) {
433 OHCIDEBUG(printf("No more transfer descriptors!\n"));
434 return NULL;
435 }
436
437 softc->ohci_transfer_freelist = t->t_next;
438
439 td = ohci_td_from_transfer(softc,t);
440
441 td->td_control = BSWAP32(0);
442 td->td_cbp = BSWAP32(0);
443 td->td_next_td = BSWAP32(0);
444 td->td_be = BSWAP32(0);
445
446 t->t_ref = NULL;
447 t->t_next = NULL;
448
449 return t;
450}
451
452
453/* *********************************************************************
454 * _ohci_freeept(softc,e)
455 *
456 * Free an endpoint, returning it to the pool.
457 *
458 * Input parameters:
459 * softc - our OHCI controller
460 * e - endpoint descriptor to return
461 *
462 * Return value:
463 * nothing
464 ********************************************************************* */
465
466static void _ohci_freeept(ohci_softc_t *softc,ohci_endpoint_t *e)
467{
468
469#ifdef _OHCI_DEBUG_
470 if (ohcidebug > 2) {
471 int cnt;
472 ohci_endpoint_t *ee;
473 cnt = 0;
474 ee = softc->ohci_endpoint_freelist;
475 while (ee) { ee = ee->ep_next; cnt++; }
476 printf("FreeEpt[%p]: %d left, %d inuse\n",e,cnt,OHCI_EDPOOL_SIZE-cnt);
477 }
478#endif
479
481 softc->ohci_endpoint_freelist = e;
482}
483
484
485/* *********************************************************************
486 * _ohci_freexfer(softc,t)
487 *
488 * Free a transfer descriptor, returning it to the pool.
489 *
490 * Input parameters:
491 * softc - our OHCI controller
492 * t - transfer descriptor to return
493 *
494 * Return value:
495 * nothing
496 ********************************************************************* */
497
498static void _ohci_freexfer(ohci_softc_t *softc,ohci_transfer_t *t)
499{
500 t->t_next = softc->ohci_transfer_freelist;
501 softc->ohci_transfer_freelist = t;
502}
503
504
505/* *********************************************************************
506 * _ohci_dma_alloc(size,align)
507 *
508 * Allocate of appropriate size. For systems with non-coherent
509 * DMA, force the allocation to an integral number of cache
510 * lines and invalidate any existing cache entries for those lines.
511 *
512 * Input parameters:
513 * size - number of bytes requested
514 * align - any protocol-required alignment
515 *
516 * Return value:
517 * base pointer, or NULL if request fails
518 ********************************************************************* */
519
520#define CACHE_ALIGN 32 /* XXX place holder, big enough to now. */
521#define ALIGN(n,align) (((n)+((align)-1)) & ~((align)-1))
522
523static void * _ohci_dma_alloc(size_t size, unsigned int align)
524{
525 void *base;
526 size_t len = ALIGN(size, CACHE_ALIGN);
527
528 base = KMALLOC(len, ALIGN(align, CACHE_ALIGN));
529#if (!CPUCFG_COHERENT_DMA)
530 if (base != NULL) {
532 }
533#endif
534 return base;
535}
536
537
538/* *********************************************************************
539 * _ohci_initpools(softc)
540 *
541 * Allocate and initialize the various pools of things that
542 * we use in the OHCI driver. We do this by allocating some
543 * big chunks from the heap and carving them up.
544 *
545 * Input parameters:
546 * softc - our OHCI controller
547 *
548 * Return value:
549 * 0 if ok
550 * else error code
551 ********************************************************************* */
552
553static int _ohci_initpools(ohci_softc_t *softc)
554{
555 int idx;
556
557 /*
558 * In the case of noncoherent DMA, make the hardware-accessed
559 * pools use uncached addresses. This way all our descriptors
560 * will be uncached. Makes life easier, as we do not need to
561 * worry about flushing descriptors, etc.
562 */
563
564 /*
565 * Do the transfer descriptor pool
566 */
567
569 softc->ohci_hwtdpool = _ohci_dma_alloc(OHCI_TDPOOL_SIZE*sizeof(ohci_td_t),OHCI_TD_ALIGN);
570
571 if (!softc->ohci_transfer_pool || !softc->ohci_hwtdpool) {
572 OHCIDEBUG(printf("Could not allocate transfer descriptors\n"));
573 return -1;
574 }
575
576#if (!CPUCFG_COHERENT_DMA)
577 softc->ohci_hwtdpool = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hwtdpool)));
578#endif
579
581
582 for (idx = 0; idx < OHCI_TDPOOL_SIZE; idx++) {
583 _ohci_freexfer(softc,softc->ohci_transfer_pool+idx);
584 }
585
586 /*
587 * Do the endpoint descriptor pool
588 */
589
591
592 softc->ohci_hwedpool = _ohci_dma_alloc(OHCI_EDPOOL_SIZE*sizeof(ohci_ed_t),OHCI_ED_ALIGN);
593
594 if (!softc->ohci_endpoint_pool || !softc->ohci_hwedpool) {
595 OHCIDEBUG(printf("Could not allocate transfer descriptors\n"));
596 return -1;
597 }
598
599#if (!CPUCFG_COHERENT_DMA)
600 softc->ohci_hwedpool = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hwedpool)));
601#endif
602
604
605 for (idx = 0; idx < OHCI_EDPOOL_SIZE; idx++) {
606 _ohci_freeept(softc,softc->ohci_endpoint_pool+idx);
607 }
608
609 /*
610 * Finally the host communications area
611 */
612
613 softc->ohci_hcca = _ohci_dma_alloc(sizeof(ohci_hcca_t),OHCI_HCCA_ALIGN);
614
615 if (!softc->ohci_hcca) {
616 OHCIDEBUG(printf("Could not allocate host communication area\n"));
617 return -1;
618 }
619
620#if (!CPUCFG_COHERENT_DMA)
621 softc->ohci_hcca = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hcca)));
622#endif
623
624 memset(softc->ohci_hcca,0,sizeof(ohci_hcca_t));
625
626 return 0;
627}
628
629
630/* *********************************************************************
631 * ohci_start(bus)
632 *
633 * Start the OHCI controller. After this routine is called,
634 * the hardware will be operational and ready to accept
635 * descriptors and interrupt calls.
636 *
637 * Input parameters:
638 * bus - bus structure, from ohci_create
639 *
640 * Return value:
641 * 0 if ok
642 * else error code
643 ********************************************************************* */
644
645static int ohci_start(usbbus_t *bus)
646{
648 uint32_t frameint;
649 uint32_t reg;
650 int idx;
651
652 /*
653 * Force a reset to the controller, followed by a short delay
654 */
655
658
659 /* Host controller state is now "RESET" */
660
661 /*
662 * We need the frame interval later, so get a copy of it now.
663 */
665
666 /*
667 * Reset the host controller. When you set the HCR bit
668 * it self-clears when the reset is complete.
669 */
670
672 for (idx = 0; idx < 10000; idx++) {
674 }
675
677 /* controller never came out of reset */
678 return -1;
679 }
680
681 /*
682 * Host controller state is now "SUSPEND". We must exit
683 * from this state within 2ms. (5.1.1.4)
684 *
685 * Set up pointers to data structures.
686 */
687
691
692 /*
693 * Our driver is polled, turn off interrupts
694 */
695
697
698 /*
699 * Set up the control register.
700 */
701
702 reg = OHCI_READCSR(softc,R_OHCI_CONTROL);
703
708
709 OHCI_WRITECSR(softc,R_OHCI_CONTROL,reg);
710
711 /*
712 * controller state is now OPERATIONAL
713 */
714
715 reg = OHCI_READCSR(softc,R_OHCI_FMINTERVAL);
718 reg |= V_OHCI_FMINTERVAL_FSMPS(OHCI_CALC_FSMPS(frameint)) |
719 V_OHCI_FMINTERVAL_FI(frameint);
721
722 reg = frameint * 9 / 10; /* calculate 90% */
724
725 usb_delay_ms(softc->ohci_bus,10);
726
727 /*
728 * Remember how many ports we have
729 */
730
731 reg = OHCI_READCSR(softc,R_OHCI_RHDSCRA);
732 softc->ohci_ndp = G_OHCI_RHDSCRA_NDP(reg);
733
734 /*
735 * Enable port power
736 */
737
739 usb_delay_ms(softc->ohci_bus,10);
740
741 return 0;
742}
743
744
745/* *********************************************************************
746 * _ohci_setupepts(softc)
747 *
748 * Set up the endpoint tree, as described in the OHCI manual.
749 * Basically the hardware knows how to scan lists of lists,
750 * so we build a tree where each level is pointed to by two
751 * parent nodes. We can choose our scanning rate by attaching
752 * endpoints anywhere within this tree.
753 *
754 * Input parameters:
755 * softc - our OHCI controller
756 *
757 * Return value:
758 * 0 if ok
759 * else error (out of descriptors)
760 ********************************************************************* */
761
762static int _ohci_setupepts(ohci_softc_t *softc)
763{
764 int idx;
766 ohci_ed_t *ed;
767 ohci_endpoint_t *child;
768
769 /*
770 * Set up the list heads for the isochronous, control,
771 * and bulk transfer lists. They don't get the same "tree"
772 * treatment that the interrupt devices get.
773 *
774 * For the purposes of CFE, it's probably not necessary
775 * to be this fancy. The only device we're planning to
776 * talk to is the keyboard and some hubs, which should
777 * have pretty minimal requirements. It's conceivable
778 * that this firmware may find a new home in other
779 * devices, so we'll meet halfway and do some things
780 * "fancy."
781 */
782
783 softc->ohci_isoc_list = _ohci_allocept(softc);
784 softc->ohci_ctl_list = _ohci_allocept(softc);
785 softc->ohci_bulk_list = _ohci_allocept(softc);
786
787 /*
788 * Set up a tree of empty endpoint descriptors. This is
789 * tree is scanned by the hardware from the leaves up to
790 * the root. Once a millisecond, the hardware picks the
791 * next leaf and starts scanning descriptors looking
792 * for something to do. It traverses all of the endpoints
793 * along the way until it gets to the root.
794 *
795 * The idea here is if you put a transfer descriptor on the
796 * root node, the hardware will see it every millisecond,
797 * since the root will be examined each time. If you
798 * put the TD on the leaf, it will be 1/32 millisecond.
799 * The tree therefore is six levels deep.
800 */
801
802 for (idx = 0; idx < OHCI_INTTREE_SIZE; idx++) {
803 e = _ohci_allocept(softc); /* allocated with sKip bit set */
804 softc->ohci_edtable[idx] = e;
805 child = (idx == 0) ? softc->ohci_isoc_list : softc->ohci_edtable[(idx-1)/2];
806 ed = ohci_ed_from_endpoint(softc,e);
807 ed->ed_next_ed = BSWAP32(child->ep_phys);
808 e->ep_next = child;
809 }
810
811 /*
812 * We maintain both physical and virtual copies of the interrupt
813 * table (leaves of the tree).
814 */
815
816 for (idx = 0; idx < OHCI_INTTABLE_SIZE; idx++) {
818 softc->ohci_inttable[ohci_revbits[idx]] = child;
819 softc->ohci_hcca->hcca_inttable[ohci_revbits[idx]] = BSWAP32(child->ep_phys);
820 }
821
822 /*
823 * Okay, at this point the tree is built.
824 */
825 return 0;
826}
827
828
829/* *********************************************************************
830 * ohci_stop(bus)
831 *
832 * Stop the OHCI hardware.
833 *
834 * Input parameters:
835 * bus - our bus structure
836 *
837 * Return value:
838 * nothing
839 ********************************************************************* */
840
841static void ohci_stop(usbbus_t *bus)
842{
844
846}
847
848
849/* *********************************************************************
850 * _ohci_queueept(softc,queue,e)
851 *
852 * Add an endpoint to a list of endpoints. This routine
853 * does things in a particular way according to the OHCI
854 * spec so we can add endpoints while the hardware is running.
855 *
856 * Input parameters:
857 * queue - endpoint descriptor for head of queue
858 * e - endpoint to add to queue
859 *
860 * Return value:
861 * nothing
862 ********************************************************************* */
863
864static void _ohci_queueept(ohci_softc_t *softc,ohci_endpoint_t *queue,ohci_endpoint_t *newept)
865{
866 ohci_ed_t *qed;
867 ohci_ed_t *newed;
868
869 qed = ohci_ed_from_endpoint(softc,queue);
870 newed = ohci_ed_from_endpoint(softc,newept);
871
872 newept->ep_next = queue->ep_next;
873 newed->ed_next_ed = qed->ed_next_ed;
874
875 queue->ep_next = newept;
876 qed->ed_next_ed = BSWAP32(newept->ep_phys);
877
878#ifdef _OHCI_DEBUG_
879 if (ohcidebug > 1) ohci_dumped(softc,newed);
880#endif
881}
882
883/* *********************************************************************
884 * _ohci_deqept(queue,e)
885 *
886 * Remove and endpoint from the list of endpoints. This
887 * routine does things in a particular way according to
888 * the OHCI specification, since we are operating on
889 * a running list.
890 *
891 * Input parameters:
892 * queue - base of queue to look for endpoint on
893 * e - endpoint to remove
894 *
895 * Return value:
896 * nothing
897 ********************************************************************* */
898
899static void _ohci_deqept(ohci_softc_t *softc,ohci_endpoint_t *queue,ohci_endpoint_t *e)
900{
901 ohci_endpoint_t *cur;
902 ohci_ed_t *cured;
903 ohci_ed_t *ed;
904
905 cur = queue;
906
907 while (cur && (cur->ep_next != e)) cur = cur->ep_next;
908
909 if (cur == NULL) {
910 OHCIDEBUG(printf("Could not remove EP %08X: not on the list!\n",(uint32_t) (intptr_t)e));
911 return;
912 }
913
914 /*
915 * Remove from our regular list
916 */
917
918 cur->ep_next = e->ep_next;
919
920 /*
921 * now remove from the hardware's list
922 */
923
924 cured = ohci_ed_from_endpoint(softc,cur);
925 ed = ohci_ed_from_endpoint(softc,e);
926
927 cured->ed_next_ed = ed->ed_next_ed;
928}
929
930
931/* *********************************************************************
932 * ohci_intr_procdoneq(softc)
933 *
934 * Process the "done" queue for this ohci controller. As
935 * descriptors are retired, the hardware links them to the
936 * "done" queue so we can examine the results.
937 *
938 * Input parameters:
939 * softc - our OHCI controller
940 *
941 * Return value:
942 * nothing
943 ********************************************************************* */
944
945static void ohci_intr_procdoneq(ohci_softc_t *softc, uint32_t donehead)
946{
947 uint32_t doneq;
948 ohci_transfer_t *transfer;
949 ohci_td_t *td;
950 int val;
951 usbreq_t *ur;
952
953 /*
954 * Get the head of the queue
955 */
956
957 doneq = BSWAP32(donehead);
958
959 td = (ohci_td_t *) OHCI_PTOV(doneq);
960 transfer = ohci_transfer_from_td(softc,td);
961
962 /*
963 * Process all elements from the queue
964 */
965
966 while (doneq) {
967
968#ifdef _OHCI_DEBUG_
969 ohci_ed_t *ed;
970 ohci_endpoint_t *ept;
971 usbreq_t *xur = transfer->t_ref;
972
973 if (ohcidebug > 1) {
974 if (xur) {
975 ept = (ohci_endpoint_t *) xur->ur_pipe->up_hwendpoint;
976 ed = ohci_ed_from_endpoint(softc,ept);
977// printf("ProcDoneQ:ED [%08X] -> ",ept->ep_phys);
978// ohci_dumped(softc,ed);
979 }
980 }
981
982 /*
983 * Get the pointer to next one before freeing this one
984 */
985
986 if (ohcidebug > 1) {
987 ur = transfer->t_ref;
988 printf("Done(%d): ",ur ? ur->ur_tdcount : -1);
989 ohci_dumptd(softc,td);
990 }
991#endif
992
993 doneq = BSWAP32(td->td_next_td);
994
996
997#ifdef _OHCI_DEBUG_
998 if (val != 0) {
999 ur = transfer->t_ref;
1000 printf("[%p Transfer error: %d %s %04X/%02X len=%d/%d (%s)]\n",ur,val,
1001 (ur->ur_flags & UR_FLAG_IN) ? "IN":"OUT",
1002 ur->ur_pipe ? ur->ur_pipe->up_flags : 0,
1003 ur->ur_pipe ? ur->ur_pipe->up_num : 0,
1004 ur->ur_xferred,ur->ur_length,
1005 ur->ur_dev->ud_drv->udrv_name);
1006 }
1007#endif
1008
1009 /*
1010 * See if it's time to call the callback.
1011 */
1012 ur = transfer->t_ref;
1013 if (ur) {
1014 ur->ur_status = val;
1015 ur->ur_tdcount--;
1016 if (BSWAP32(td->td_cbp) == 0) {
1017 ur->ur_xferred += transfer->t_length;
1018 }
1019 else {
1020 ur->ur_xferred += transfer->t_length -
1021 (BSWAP32(td->td_be) - BSWAP32(td->td_cbp) + 1);
1022 }
1023 if (ur->ur_tdcount == 0) {
1024 /* Noncoherent DMA: need to invalidate, since data is in phys mem */
1025 if ((ur->ur_flags & (UR_FLAG_OUT | UR_FLAG_STATUS_OUT)) == 0)
1027
1028 /* If device was being removed, change return code to "cancelled" */
1029 if (ur->ur_dev && (ur->ur_dev->ud_flags & UD_FLAG_REMOVING)) {
1030 OHCIDEBUG(printf("Changing status of %p to CANCELLED\n",ur));
1032 }
1033
1035 }
1036 }
1037
1038 /*
1039 * Free up the request
1040 */
1041 _ohci_freexfer(softc,transfer);
1042
1043 /*
1044 * Advance to the next request.
1045 */
1046
1047 td = (ohci_td_t *) OHCI_PTOV(doneq);
1048 transfer = ohci_transfer_from_td(softc,td);
1049 }
1050}
1051
1052
1053/* *********************************************************************
1054 * ohci_intr(bus)
1055 *
1056 * Process pending interrupts for the OHCI controller.
1057 *
1058 * Input parameters:
1059 * bus - our bus structure
1060 *
1061 * Return value:
1062 * 0 if we did nothing
1063 * nonzero if we did something.
1064 ********************************************************************* */
1065
1066static int ohci_intr(usbbus_t *bus)
1067{
1069 uint32_t reg;
1070 uint32_t donehead;
1071
1072 /*
1073 * Read the interrupt status register.
1074 */
1075
1076 reg = OHCI_READCSR(softc,R_OHCI_INTSTATUS);
1077
1078 /*
1079 * Don't bother doing anything if nothing happened.
1080 */
1081 if (reg == 0) {
1082 return 0;
1083 }
1084
1085 /*
1086 * Get the head of the queue so that we can clear the pending
1087 * interrupts. XXX Anything else needed first?
1088 */
1089
1090 donehead = softc->ohci_hcca->hcca_donehead;
1091
1092 /*
1093 * Write the value back to the interrupt
1094 * register to clear the bits that were set.
1095 */
1096
1098
1099 /* Scheduling Overruns */
1100 if (reg & M_OHCI_INT_SO) {
1101 OHCIDEBUG(printf("SchedOverrun\n"));
1102 }
1103
1104 /* Done Queue */
1105 if (reg & M_OHCI_INT_WDH) {
1106 ohci_intr_procdoneq(softc, donehead);
1107 }
1108
1109 /* Start of Frame */
1110 if (reg & M_OHCI_INT_SF) {
1111 /* don't be noisy about this */
1112 }
1113
1114 /* Resume Detect */
1115 if (reg & M_OHCI_INT_RD) {
1116 OHCIDEBUG(printf("ResumeDetect\n"));
1117 }
1118
1119 /* Unrecoverable errors */
1120 if (reg & M_OHCI_INT_UE) {
1121 OHCIDEBUG(printf("UnrecoverableError\n"));
1122 }
1123
1124 /* Frame number overflow */
1125 if (reg & M_OHCI_INT_FNO) {
1126 /* Don't be noisy about this */
1127 }
1128
1129 /* Root Hub Status Change */
1130 if ((reg & ~softc->ohci_intdisable) & M_OHCI_INT_RHSC) {
1131#ifdef _OHCI_DEBUG_
1132 uint32_t reg;
1133 if (ohcidebug > 0) {
1134 printf("RootHubStatusChange: ");
1135 reg = OHCI_READCSR(softc,R_OHCI_RHSTATUS);
1136 ohci_dumprhstat(reg);
1137 reg = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(1));
1138 ohci_dumpportstat(1,reg);
1139 reg = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(2));
1140 ohci_dumpportstat(2,reg);
1141 }
1142#endif
1143 ohci_roothub_statchg(softc);
1144 }
1145
1146 /* Ownership Change */
1147 if (reg & M_OHCI_INT_OC) {
1148 OHCIDEBUG(printf("OwnershipChange\n"));
1149 }
1150
1151 return 1;
1152}
1153
1154
1155/* *********************************************************************
1156 * ohci_delete(bus)
1157 *
1158 * Remove an OHCI bus structure and all resources allocated to
1159 * it (used when shutting down USB)
1160 *
1161 * Input parameters:
1162 * bus - our USB bus structure
1163 *
1164 * Return value:
1165 * nothing
1166 ********************************************************************* */
1167
1168static void ohci_delete(usbbus_t *bus)
1169{
1170 // xxx fill in later.
1171}
1172
1173
1174/* *********************************************************************
1175 * ohci_create(addr)
1176 *
1177 * Create a USB bus structure and associate it with our OHCI
1178 * controller device.
1179 *
1180 * Input parameters:
1181 * addr - physical address of controller
1182 *
1183 * Return value:
1184 * usbbus structure pointer
1185 ********************************************************************* */
1186
1187static usbbus_t *ohci_create(physaddr_t addr)
1188{
1189 int res;
1190 ohci_softc_t *softc;
1191 usbbus_t *bus;
1192 softc = KMALLOC(sizeof(ohci_softc_t),0);
1193 if (!softc) return NULL;
1194
1195 bus = KMALLOC(sizeof(usbbus_t),0);
1196 if (!bus) return NULL;
1197
1198 memset(softc,0,sizeof(ohci_softc_t));
1199 memset(bus,0,sizeof(usbbus_t));
1200
1201 bus->ub_hwsoftc = (usb_hc_t *) softc;
1203
1204 q_init(&(softc->ohci_rh_intrq));
1205
1206#ifdef _CFE_
1207 softc->ohci_regs = addr;
1208#else
1209 softc->ohci_regs = (volatile uint32_t *) addr;
1210#endif
1211
1212 softc->ohci_rh_newaddr = -1;
1213 softc->ohci_bus = bus;
1214
1215 if ((res = _ohci_initpools(softc)) != 0) goto error;
1216 if ((res = _ohci_setupepts(softc)) != 0) goto error;
1217
1219
1220 return bus;
1221
1222error:
1223 KFREE(softc);
1224 return NULL;
1225}
1226
1227
1228/* *********************************************************************
1229 * ohci_ept_create(bus,usbaddr,eptnum,mps,flags)
1230 *
1231 * Create a hardware endpoint structure and attach it to
1232 * the hardware's endpoint list. The hardware manages lists
1233 * of queues, and this routine adds a new queue to the appropriate
1234 * list of queues for the endpoint in question. It roughly
1235 * corresponds to the information in the OHCI specification.
1236 *
1237 * Input parameters:
1238 * bus - the USB bus we're dealing with
1239 * usbaddr - USB address (0 means default address)
1240 * eptnum - the endpoint number
1241 * mps - the packet size for this endpoint
1242 * flags - various flags to control endpoint creation
1243 *
1244 * Return value:
1245 * endpoint structure poihter, or NULL
1246 ********************************************************************* */
1247
1248static usb_ept_t *ohci_ept_create(usbbus_t *bus,
1249 int usbaddr,
1250 int eptnum,
1251 int mps,
1252 int flags)
1253{
1254 uint32_t eptflags;
1255 ohci_endpoint_t *ept;
1256 ohci_ed_t *ed;
1257 ohci_transfer_t *tailtransfer;
1258 ohci_td_t *tailtd;
1260
1261 ept = _ohci_allocept(softc);
1262 ed = ohci_ed_from_endpoint(softc,ept);
1263
1264 tailtransfer = _ohci_allocxfer(softc);
1265 tailtd = ohci_td_from_transfer(softc,tailtransfer);
1266
1267 /*
1268 * Set up functional address, endpoint number, and packet size
1269 */
1270
1271 eptflags = V_OHCI_ED_FA(usbaddr) |
1272 V_OHCI_ED_EN(eptnum) |
1273 V_OHCI_ED_MPS(mps) |
1274 0;
1275
1276 /*
1277 * Set up the endpoint type based on the flags
1278 * passed to us
1279 */
1280
1281 if (flags & UP_TYPE_IN) {
1282 eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_IN);
1283 }
1284 else if (flags & UP_TYPE_OUT) {
1285 eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_OUT);
1286 }
1287 else {
1289 }
1290
1291 /*
1292 * Don't forget about lowspeed devices.
1293 */
1294
1295 if (flags & UP_TYPE_LOWSPEED) {
1296 eptflags |= M_OHCI_ED_LOWSPEED;
1297 }
1298
1299#ifdef _OHCI_DEBUG_
1300 if (ohcidebug > 0) {
1301 printf("Create endpoint %d addr %d flags %08X mps %d\n",
1302 eptnum,usbaddr,eptflags,mps);
1303 }
1304#endif
1305
1306 /*
1307 * Transfer this info into the endpoint descriptor.
1308 * No need to flush the cache here, it'll get done when
1309 * we add to the hardware list.
1310 */
1311
1312 ed->ed_control = BSWAP32(eptflags);
1313 ed->ed_tailp = BSWAP32(OHCI_VTOP(tailtd));
1314 ed->ed_headp = BSWAP32(OHCI_VTOP(tailtd));
1315 ept->ep_flags = flags;
1316 ept->ep_mps = mps;
1317 ept->ep_num = eptnum;
1318
1319 /*
1320 * Put it on the right queue
1321 */
1322
1323 if (flags & UP_TYPE_CONTROL) {
1324 _ohci_queueept(softc,softc->ohci_ctl_list,ept);
1325 }
1326 else if (flags & UP_TYPE_BULK) {
1327 _ohci_queueept(softc,softc->ohci_bulk_list,ept);
1328 }
1329 else if (flags & UP_TYPE_INTR) {
1330 /* XXX Choose place in inttable properly. */
1331 _ohci_queueept(softc,softc->ohci_inttable[0],ept);
1332 }
1333
1334 return (usb_ept_t *) ept;
1335}
1336
1337
1338/* *********************************************************************
1339 * ohci_ept_setaddr(bus,ept,usbaddr)
1340 *
1341 * Change the functional address for a USB endpoint. We do this
1342 * when we switch the device's state from DEFAULT to ADDRESSED
1343 * and we've already got the default pipe open. This
1344 * routine mucks with the descriptor and changes its address
1345 * bits.
1346 *
1347 * Input parameters:
1348 * bus - usb bus structure
1349 * ept - an open endpoint descriptor
1350 * usbaddr - new address for this endpoint
1351 *
1352 * Return value:
1353 * nothing
1354 ********************************************************************* */
1355
1356static void ohci_ept_setaddr(usbbus_t *bus,usb_ept_t *uept,int usbaddr)
1357{
1358 uint32_t eptflags;
1359 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
1361 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
1362
1363 eptflags = BSWAP32(ed->ed_control);
1364 eptflags &= ~M_OHCI_ED_FA;
1365 eptflags |= V_OHCI_ED_FA(usbaddr);
1366 ed->ed_control = BSWAP32(eptflags);
1367}
1368
1369
1370/* *********************************************************************
1371 * ohci_ept_setmps(bus,ept,mps)
1372 *
1373 * Set the maximum packet size of this endpoint. This is
1374 * normally used during the processing of endpoint 0 (default
1375 * pipe) after we find out how big ep0's packets can be.
1376 *
1377 * Input parameters:
1378 * bus - our USB bus structure
1379 * ept - endpoint structure
1380 * mps - new packet size
1381 *
1382 * Return value:
1383 * nothing
1384 ********************************************************************* */
1385
1386static void ohci_ept_setmps(usbbus_t *bus,usb_ept_t *uept,int mps)
1387{
1388 uint32_t eptflags;
1390 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
1391 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
1392
1393 eptflags = BSWAP32(ed->ed_control);
1394 eptflags &= ~M_OHCI_ED_MPS;
1395 eptflags |= V_OHCI_ED_MPS(mps);
1396 ed->ed_control = BSWAP32(eptflags);
1397 ept->ep_mps = mps;
1398
1399}
1400
1401
1402/* *********************************************************************
1403 * ohci_ept_cleartoggle(bus,ept,mps)
1404 *
1405 * Clear the data toggle for the specified endpoint.
1406 *
1407 * Input parameters:
1408 * bus - our USB bus structure
1409 * ept - endpoint structure
1410 *
1411 * Return value:
1412 * nothing
1413 ********************************************************************* */
1414
1415static void ohci_ept_cleartoggle(usbbus_t *bus,usb_ept_t *uept)
1416{
1417 uint32_t eptflags;
1419 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
1420 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
1421
1422 eptflags = BSWAP32(ed->ed_headp);
1423 eptflags &= ~(M_OHCI_ED_HALT | M_OHCI_ED_TOGGLECARRY);
1424 ed->ed_headp = BSWAP32(eptflags);
1425
1427}
1428
1429
1430/* *********************************************************************
1431 * ohci_ept_delete(bus,ept)
1432 *
1433 * Deletes an endpoint from the OHCI controller. This
1434 * routine also completes pending transfers for the
1435 * endpoint and gets rid of the hardware ept (queue base).
1436 *
1437 * Input parameters:
1438 * bus - ohci bus structure
1439 * ept - endpoint to remove
1440 *
1441 * Return value:
1442 * nothing
1443 ********************************************************************* */
1444
1445static void ohci_ept_delete(usbbus_t *bus,usb_ept_t *uept)
1446{
1447 ohci_endpoint_t *queue;
1449 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
1450 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
1451 uint32_t framenum;
1452 uint32_t tdphys;
1453 usbreq_t *ur;
1454 ohci_td_t *td;
1455 ohci_transfer_t *transfer;
1456
1457 if (ept->ep_flags & UP_TYPE_CONTROL) {
1458 queue = softc->ohci_ctl_list;
1459 }
1460 else if (ept->ep_flags & UP_TYPE_BULK) {
1461 queue = softc->ohci_bulk_list;
1462 }
1463 else if (ept->ep_flags & UP_TYPE_INTR) {
1464 queue = softc->ohci_inttable[0];
1465 }
1466 else {
1467 OHCIDEBUG(printf("Invalid endpoint\n"));
1468 return;
1469 }
1470
1471 /*
1472 * Set the SKIP bit on the endpoint and
1473 * wait for two SOFs to guarantee that we're
1474 * not processing this ED anymore.
1475 */
1476
1477 ed->ed_control = (volatile uint32_t) ed->ed_control | BSWAP32(M_OHCI_ED_SKIP);
1478
1479 framenum = OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF;
1480 while ((OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF) == framenum) ; /* NULL LOOP */
1481
1482 framenum = OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF;
1483 while ((OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF) == framenum) ; /* NULL LOOP */
1484
1485 /*
1486 * Remove endpoint from queue
1487 */
1488
1489 _ohci_deqept(softc,queue,ept);
1490
1491 /*
1492 * Free/complete the TDs on the queue
1493 */
1494
1495 tdphys = BSWAP32(ed->ed_headp) & M_OHCI_ED_PTRMASK;
1496
1497 while (tdphys != BSWAP32(ed->ed_tailp)) {
1498 td = (ohci_td_t *) OHCI_PTOV(tdphys);
1499 tdphys = BSWAP32(td->td_next_td);
1500 transfer = ohci_transfer_from_td(softc,td);
1501 ur = transfer->t_ref;
1502 if (ur) {
1504 ur->ur_tdcount--;
1505 if (ur->ur_tdcount == 0) {
1506#ifdef _OHCI_DEBUG_
1507 if (ohcidebug > 0) printf("dev %p Completing request due to closed pipe: %p (%s,%04X/%02X,%s)\n",
1508 ur->ur_dev,
1509 ur,
1510 (ur->ur_flags & UR_FLAG_IN) ? "IN":"OUT",
1511 ept->ep_flags,ept->ep_num,
1512 ur->ur_dev->ud_drv->udrv_name);
1513#endif
1515 /* it is expected that the callee will free the usbreq. */
1516 }
1517 }
1518
1519 _ohci_freexfer(softc,transfer);
1520 }
1521
1522 /*
1523 * tdphys now points at the tail TD. Just free it.
1524 */
1525
1526 td = (ohci_td_t *) OHCI_PTOV(tdphys);
1527 _ohci_freexfer(softc,ohci_transfer_from_td(softc,td));
1528
1529 /*
1530 * Return endpoint to free pool
1531 */
1532
1533 _ohci_freeept(softc,ept);
1534}
1535
1536
1537/* *********************************************************************
1538 * ohci_xfer(bus,ept,ur)
1539 *
1540 * Queue a transfer for the specified endpoint. Depending on
1541 * the transfer type, the transfer may go on one of many queues.
1542 * When the transfer completes, a callback will be called.
1543 *
1544 * Input parameters:
1545 * bus - bus structure
1546 * ept - endpoint descriptor
1547 * ur - request (includes pointer to user buffer)
1548 *
1549 * Return value:
1550 * 0 if ok
1551 * else error
1552 ********************************************************************* */
1553
1554static int ohci_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur)
1555{
1557 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
1558 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
1559 ohci_transfer_t *newtailtransfer = 0;
1560 ohci_td_t *newtailtd = NULL;
1561 ohci_transfer_t *curtransfer;
1562 ohci_td_t *curtd;
1563 uint8_t *ptr;
1564 int len;
1565 int amtcopy;
1566 int pktlen;
1567 uint32_t tdcontrol = 0;
1568
1569 /*
1570 * If the destination USB address matches
1571 * the address of the root hub, shunt the request
1572 * over to our root hub emulation.
1573 */
1574
1575 if (ur->ur_dev->ud_address == softc->ohci_rh_addr) {
1576 return ohci_roothub_xfer(bus,uept,ur);
1577 }
1578
1579 /*
1580 * Set up the TD flags based on the
1581 * request type.
1582 */
1583
1584
1585// pktlen = ept->ep_mps;
1586 pktlen = OHCI_TD_MAX_DATA - 16;
1587
1588 if (ur->ur_flags & UR_FLAG_SETUP) {
1589 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_SETUP) |
1592 V_OHCI_TD_DI(1);
1593 }
1594 else if (ur->ur_flags & UR_FLAG_IN) {
1595 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_IN) |
1598 V_OHCI_TD_DI(1);
1599 }
1600 else if (ur->ur_flags & UR_FLAG_OUT) {
1601 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_OUT) |
1604 V_OHCI_TD_DI(1);
1605 }
1606 else if (ur->ur_flags & UR_FLAG_STATUS_OUT) {
1607 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_OUT) |
1610 V_OHCI_TD_DI(1);
1611 }
1612 else if (ur->ur_flags & UR_FLAG_STATUS_IN) {
1613 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_IN) |
1616 V_OHCI_TD_DI(1);
1617 }
1618 else {
1619 OHCIDEBUG(printf("Shouldn't happen!\n"));
1620 }
1621
1622 if (ur->ur_flags & UR_FLAG_SHORTOK) {
1623 tdcontrol |= M_OHCI_TD_SHORTOK;
1624 }
1625
1626
1627 ptr = ur->ur_buffer;
1628 len = ur->ur_length;
1629 ur->ur_tdcount = 0;
1630
1631#ifdef _OHCI_DEBUG_
1632 if (ohcidebug > 1) {
1633 printf(">> Queueing xfer addr %d pipe %d ED %08X ptr %016X length %d\n",
1634 ur->ur_dev->ud_address,
1635 ur->ur_pipe->up_num,
1636 ept->ep_phys,
1637 ptr,
1638 len);
1639// ohci_dumped(softc,ed);
1640 }
1641#endif
1642
1643 curtd = OHCI_PTOV(BSWAP32(ed->ed_tailp));
1644 curtransfer = ohci_transfer_from_td(softc,curtd);
1645
1646 if (len == 0) {
1647 newtailtransfer = _ohci_allocxfer(softc);
1648 newtailtd = ohci_td_from_transfer(softc,newtailtransfer);
1649 curtd->td_cbp = 0;
1650 curtd->td_be = 0;
1651 curtd->td_next_td = BSWAP32(OHCI_VTOP(newtailtd));
1652 curtd->td_control = BSWAP32(tdcontrol);
1653 curtransfer->t_next = newtailtransfer;
1654 curtransfer->t_ref = ur;
1655 curtransfer->t_length = 0;
1656#ifdef _OHCI_DEBUG_
1657 if (ohcidebug > 1) { printf("QueueTD: "); ohci_dumptd(softc,curtd); }
1658#endif
1659 ur->ur_tdcount++;
1660 }
1661 else {
1662 /* Noncoherent DMA: need to flush user buffer to real memory first */
1663 OHCI_FLUSH_RANGE(ptr,len);
1664 while (len > 0) {
1665 amtcopy = len;
1666 if (amtcopy > pktlen) amtcopy = pktlen;
1667 newtailtransfer = _ohci_allocxfer(softc);
1668 newtailtd = ohci_td_from_transfer(softc,newtailtransfer);
1669 curtd->td_cbp = BSWAP32(OHCI_VTOD(ptr));
1670 curtd->td_be = BSWAP32(OHCI_VTOD(ptr+amtcopy)-1);
1671 curtd->td_next_td = BSWAP32(OHCI_VTOP(newtailtd));
1672 curtd->td_control = BSWAP32(tdcontrol);
1673 curtransfer->t_next = newtailtransfer;
1674 curtransfer->t_ref = ur;
1675 curtransfer->t_length = amtcopy;
1676#ifdef _OHCI_DEBUG_
1677 if (ohcidebug > 1) { printf("QueueTD: "); ohci_dumptd(softc,curtd); }
1678#endif
1679 curtd = newtailtd;
1680 curtransfer = ohci_transfer_from_td(softc,curtd);
1681 ptr += amtcopy;
1682 len -= amtcopy;
1683 ur->ur_tdcount++;
1684 }
1685 }
1686
1688 ed->ed_tailp = BSWAP32(OHCI_VTOP(newtailtd));
1689
1690 /*
1691 * Clear halted state
1692 */
1693
1695
1696 /*
1697 * Prod the controller depending on what type of list we put
1698 * a TD on.
1699 */
1700
1701 if (ept->ep_flags & UP_TYPE_BULK) {
1703 }
1704 else {
1705 /* XXX should probably make sure we're UP_TYPE_CONTROL here */
1707 }
1708
1709 return 0;
1710}
1711
1712
1713/* *********************************************************************
1714 * Driver structure
1715 ********************************************************************* */
1716
1718 ohci_create,
1719 ohci_delete,
1720 ohci_start,
1721 ohci_stop,
1722 ohci_intr,
1723 ohci_ept_create,
1724 ohci_ept_delete,
1725 ohci_ept_setmps,
1726 ohci_ept_setaddr,
1727 ohci_ept_cleartoggle,
1728 ohci_xfer
1729};
1730
1731
1732/* *********************************************************************
1733 * Root Hub
1734 *
1735 * Data structures and functions
1736 ********************************************************************* */
1737
1738/*
1739 * Data structures and routines to emulate the root hub.
1740 */
1741static usb_device_descr_t ohci_root_devdsc = {
1742 sizeof(usb_device_descr_t), /* bLength */
1743 USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
1744 USBWORD(0x0100), /* bcdUSB */
1745 USB_DEVICE_CLASS_HUB, /* bDeviceClass */
1746 0, /* bDeviceSubClass */
1747 0, /* bDeviceProtocol */
1748 64, /* bMaxPacketSize0 */
1749 USBWORD(0), /* idVendor */
1750 USBWORD(0), /* idProduct */
1751 USBWORD(0x0100), /* bcdDevice */
1752 1, /* iManufacturer */
1753 2, /* iProduct */
1754 0, /* iSerialNumber */
1755 1 /* bNumConfigurations */
1756};
1757
1758static usb_config_descr_t ohci_root_cfgdsc = {
1759 sizeof(usb_config_descr_t), /* bLength */
1760 USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
1761 USBWORD(
1762 sizeof(usb_config_descr_t) +
1763 sizeof(usb_interface_descr_t) +
1764 sizeof(usb_endpoint_descr_t)), /* wTotalLength */
1765 1, /* bNumInterfaces */
1766 1, /* bConfigurationValue */
1767 0, /* iConfiguration */
1768 USB_CONFIG_SELF_POWERED, /* bmAttributes */
1769 0 /* MaxPower */
1770};
1771
1772static usb_interface_descr_t ohci_root_ifdsc = {
1773 sizeof(usb_interface_descr_t), /* bLength */
1774 USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
1775 0, /* bInterfaceNumber */
1776 0, /* bAlternateSetting */
1777 1, /* bNumEndpoints */
1778 USB_INTERFACE_CLASS_HUB, /* bInterfaceClass */
1779 0, /* bInterfaceSubClass */
1780 0, /* bInterfaceProtocol */
1781 0 /* iInterface */
1782};
1783
1784static usb_endpoint_descr_t ohci_root_epdsc = {
1785 sizeof(usb_endpoint_descr_t), /* bLength */
1786 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
1787 (USB_ENDPOINT_DIRECTION_IN | 1), /* bEndpointAddress */
1788 USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
1789 USBWORD(8), /* wMaxPacketSize */
1790 255 /* bInterval */
1791};
1792
1793static usb_hub_descr_t ohci_root_hubdsc = {
1794 USB_HUB_DESCR_SIZE, /* bLength */
1795 USB_HUB_DESCRIPTOR_TYPE, /* bDescriptorType */
1796 0, /* bNumberOfPorts */
1797 USBWORD(0), /* wHubCharacteristics */
1798 0, /* bPowreOnToPowerGood */
1799 0, /* bHubControl Current */
1800 {0} /* bRemoveAndPowerMask */
1801};
1802
1803/* *********************************************************************
1804 * ohci_roothb_strdscr(ptr,str)
1805 *
1806 * Construct a string descriptor for root hub requests
1807 *
1808 * Input parameters:
1809 * ptr - pointer to where to put descriptor
1810 * str - regular string to put into descriptor
1811 *
1812 * Return value:
1813 * number of bytes written to descriptor
1814 ********************************************************************* */
1815
1816static int ohci_roothub_strdscr(uint8_t *ptr,char *str)
1817{
1818 uint8_t *p = ptr;
1819
1820 *p++ = strlen(str)*2 + 2; /* Unicode strings */
1822 while (*str) {
1823 *p++ = *str++;
1824 *p++ = 0;
1825 }
1826 return (p - ptr);
1827}
1828
1829/* *********************************************************************
1830 * ohci_roothub_req(softc,req)
1831 *
1832 * Handle a descriptor request on the control pipe for the
1833 * root hub. We pretend to be a real root hub here and
1834 * return all the standard descriptors.
1835 *
1836 * Input parameters:
1837 * softc - our OHCI controller
1838 * req - a usb request (completed immediately)
1839 *
1840 * Return value:
1841 * 0 if ok
1842 * else error code
1843 ********************************************************************* */
1844
1845static int ohci_roothub_req(ohci_softc_t *softc,usb_device_request_t *req)
1846{
1847 uint8_t *ptr;
1848// uint16_t wLength;
1849 uint16_t wValue;
1850 uint16_t wIndex;
1852 usb_hub_descr_t hdsc;
1854 uint32_t statport;
1855 uint32_t tmpval;
1856 int res = 0;
1857
1858 ptr = softc->ohci_rh_buf;
1859
1860// wLength = GETUSBFIELD(req,wLength);
1861 wValue = GETUSBFIELD(req,wValue);
1862 wIndex = GETUSBFIELD(req,wIndex);
1863
1864 switch (REQSW(req->bRequest,req->bmRequestType)) {
1865
1867 *ptr++ = (USB_GETSTATUS_SELF_POWERED & 0xFF);
1868 *ptr++ = (USB_GETSTATUS_SELF_POWERED >> 8);
1869 break;
1870
1873 *ptr++ = 0;
1874 *ptr++ = 0;
1875 break;
1876
1878 status = OHCI_READCSR(softc,(R_OHCI_RHPORTSTATUS(wIndex)));
1879#ifdef _OHCI_DEBUG_
1880 if (ohcidebug > 0) { printf("RHGetStatus: "); ohci_dumpportstat(wIndex,status);}
1881#endif
1882 PUTUSBFIELD((&ups),wPortStatus,(status & 0xFFFF));
1883 PUTUSBFIELD((&ups),wPortChange,(status >> 16));
1884 memcpy(ptr,&ups,sizeof(ups));
1885 ptr += sizeof(ups);
1886 break;
1887
1889 *ptr++ = 0;
1890 *ptr++ = 0;
1891 *ptr++ = 0;
1892 *ptr++ = 0;
1893 break;
1894
1898 /* do nothing, not supported */
1899 break;
1900
1902 statport = R_OHCI_RHPORTSTATUS(wIndex);
1903#ifdef _OHCI_DEBUG_
1904 if (ohcidebug> 0) {
1905 printf("RHClearFeature(%d): ",wValue); ohci_dumpportstat(wIndex,OHCI_READCSR(softc,statport));
1906 }
1907#endif
1908 switch (wValue) {
1910 break;
1912 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_CCS);
1913 break;
1915 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_POCI);
1916 break;
1918 break;
1920 break;
1922 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_LSDA);
1923 break;
1925 break;
1927 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_CSC);
1928 break;
1930 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PESC);
1931 break;
1933 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PSSC);
1934 break;
1936 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_OCIC);
1937 break;
1939 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PRSC);
1940 break;
1941
1942 }
1943
1944 /*
1945 * If we've cleared all of the conditions that
1946 * want our attention on the port status,
1947 * then we can accept port status interrupts again.
1948 */
1949
1950 if ((wValue >= USB_PORT_FEATURE_C_PORT_CONNECTION) &&
1951 (wValue <= USB_PORT_FEATURE_C_PORT_RESET)) {
1952 status = OHCI_READCSR(softc,statport);
1953 if ((status & M_OHCI_RHPORTSTAT_ALLC) == 0) {
1954 softc->ohci_intdisable &= ~M_OHCI_INT_RHSC;
1955 }
1956 }
1957 break;
1958
1962 res = -1;
1963 break;
1964
1966 /* nothing */
1967 break;
1968
1970 statport = R_OHCI_RHPORTSTATUS(wIndex);
1971 switch (wValue) {
1973 break;
1975 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PES);
1976 break;
1978 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PSS);
1979 break;
1981 break;
1983 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PRS);
1984 for (;;) { /* XXX timer */
1985 usb_delay_ms(softc->ohci_bus,100);
1986 if (!(OHCI_READCSR(softc,statport) & M_OHCI_RHPORTSTAT_PRS)) break;
1987 }
1988 break;
1990 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PPS);
1991 break;
1993 break;
1995 break;
1997 break;
1999 break;
2001 break;
2003 break;
2004
2005 }
2006
2007 break;
2008
2010 softc->ohci_rh_newaddr = wValue;
2011 break;
2012
2014 switch (wValue >> 8) {
2016 memcpy(ptr,&ohci_root_devdsc,sizeof(ohci_root_devdsc));
2017 ptr += sizeof(ohci_root_devdsc);
2018 break;
2020 memcpy(ptr,&ohci_root_cfgdsc,sizeof(ohci_root_cfgdsc));
2021 ptr += sizeof(ohci_root_cfgdsc);
2022 memcpy(ptr,&ohci_root_ifdsc,sizeof(ohci_root_ifdsc));
2023 ptr += sizeof(ohci_root_ifdsc);
2024 memcpy(ptr,&ohci_root_epdsc,sizeof(ohci_root_epdsc));
2025 ptr += sizeof(ohci_root_epdsc);
2026 break;
2028 switch (wValue & 0xFF) {
2029 case 1:
2030 ptr += ohci_roothub_strdscr(ptr,"Generic");
2031 break;
2032 case 2:
2033 ptr += ohci_roothub_strdscr(ptr,"Root Hub");
2034 break;
2035 default:
2036 *ptr++ = 0;
2037 break;
2038 }
2039 break;
2040 default:
2041 res = -1;
2042 break;
2043 }
2044 break;
2045
2047 memcpy(&hdsc,&ohci_root_hubdsc,sizeof(hdsc));
2048 hdsc.bNumberOfPorts = softc->ohci_ndp;
2050 tmpval = 0;
2053 else tmpval |= USB_HUBCHAR_PWR_IND;
2054 PUTUSBFIELD((&hdsc),wHubCharacteristics,tmpval);
2055 tmpval = G_OHCI_RHDSCRA_POTPGT(status);
2056 hdsc.bPowerOnToPowerGood = tmpval;
2060 memcpy(ptr,&hdsc,sizeof(hdsc));
2061 ptr += sizeof(hdsc);
2062 break;
2063
2065 /* nothing */
2066 break;
2067
2069 *ptr++ = softc->ohci_rh_conf;
2070 break;
2071
2073 softc->ohci_rh_conf = wValue;
2074 break;
2075
2077 *ptr++ = 0;
2078 break;
2079
2081 /* nothing */
2082 break;
2083
2085 /* nothing */
2086 break;
2087 }
2088
2089 softc->ohci_rh_ptr = softc->ohci_rh_buf;
2090 softc->ohci_rh_len = ptr - softc->ohci_rh_buf;
2091
2092 return res;
2093}
2094
2095/* *********************************************************************
2096 * ohci_roothub_statchg(softc)
2097 *
2098 * This routine is called from the interrupt service routine
2099 * (well, polling routine) for the ohci controller. If the
2100 * controller notices a root hub status change, it dequeues an
2101 * interrupt transfer from the root hub's queue and completes
2102 * it here.
2103 *
2104 * Input parameters:
2105 * softc - our OHCI controller
2106 *
2107 * Return value:
2108 * nothing
2109 ********************************************************************* */
2110
2111static void ohci_roothub_statchg(ohci_softc_t *softc)
2112{
2113 usbreq_t *ur;
2115 uint8_t portstat = 0;
2116 int idx;
2117
2118 /* Note: this only works up to 8 ports */
2119 for (idx = 1; idx <= softc->ohci_ndp; idx++) {
2122 portstat = (1<<idx);
2123 }
2124 }
2125
2126 /* Complete the root hub's interrupt usbreq if there's a change */
2127 if (portstat != 0) {
2129
2130 ur = (usbreq_t *) q_deqnext(&(softc->ohci_rh_intrq));
2131 if (!ur) return; /* no requests pending, ignore it */
2132
2133 memset(ur->ur_buffer,0,ur->ur_length);
2134 ur->ur_buffer[0] = portstat;
2135 ur->ur_xferred = ur->ur_length;
2136
2138 }
2139}
2140
2141/* *********************************************************************
2142 * ohci_roothub_xfer(softc,req)
2143 *
2144 * Handle a root hub xfer - ohci_xfer transfers control here
2145 * if we detect the address of the root hub - no actual transfers
2146 * go out on the wire, we just handle the requests directly to
2147 * make it look like a hub is attached.
2148 *
2149 * This seems to be common practice in the USB world, so we do
2150 * it here too.
2151 *
2152 * Input parameters:
2153 * softc - our OHCI controller structure
2154 * req - usb request destined for host controller
2155 *
2156 * Return value:
2157 * 0 if ok
2158 * else error
2159 ********************************************************************* */
2160
2161static int ohci_roothub_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur)
2162{
2164 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
2165// int res;
2166
2167 switch (ept->ep_num) {
2168
2169 /*
2170 * CONTROL ENDPOINT
2171 */
2172 case 0:
2173
2174 /*
2175 * Three types of transfers: OUT (SETUP), IN (data), or STATUS.
2176 * figure out which is which.
2177 */
2178
2179 if (ur->ur_flags & UR_FLAG_SETUP) {
2180 /*
2181 * SETUP packet - this is an OUT request to the control
2182 * pipe. We emulate the hub request here.
2183 */
2185
2186 req = (usb_device_request_t *) ur->ur_buffer;
2187
2188 /*res =*/ ohci_roothub_req(softc,req);
2189#ifdef _OHCI_DEBUG_
2190 if (res != 0) printf("Root hub request returned an error\n");
2191#endif
2192
2193 ur->ur_xferred = ur->ur_length;
2194 ur->ur_status = 0;
2196 }
2197
2198 else if (ur->ur_flags & UR_FLAG_STATUS_IN) {
2199 /*
2200 * STATUS IN : it's sort of like a dummy IN request
2201 * to acknowledge a SETUP packet that otherwise has no
2202 * status. Just complete the usbreq.
2203 */
2204
2205 if (softc->ohci_rh_newaddr != -1) {
2206 softc->ohci_rh_addr = softc->ohci_rh_newaddr;
2207 softc->ohci_rh_newaddr = -1;
2208 }
2209
2210 ur->ur_status = 0;
2211 ur->ur_xferred = 0;
2213 }
2214
2215 else if (ur->ur_flags & UR_FLAG_STATUS_OUT) {
2216 /*
2217 * STATUS OUT : it's sort of like a dummy OUT request
2218 */
2219 ur->ur_status = 0;
2220 ur->ur_xferred = 0;
2222 }
2223
2224 else if (ur->ur_flags & UR_FLAG_IN) {
2225 /*
2226 * IN : return data from the root hub
2227 */
2228 int amtcopy;
2229
2230 amtcopy = softc->ohci_rh_len;
2231 if (amtcopy > ur->ur_length) amtcopy = ur->ur_length;
2232
2233 memcpy(ur->ur_buffer,softc->ohci_rh_ptr,amtcopy);
2234
2235 softc->ohci_rh_ptr += amtcopy;
2236 softc->ohci_rh_len -= amtcopy;
2237
2238 ur->ur_status = 0;
2239 ur->ur_xferred = amtcopy;
2241 }
2242
2243 else {
2244 OHCIDEBUG(printf("Unknown root hub transfer type\n"));
2245 return -1;
2246 }
2247 break;
2248
2249 /*
2250 * INTERRUPT ENDPOINT
2251 */
2252
2253 case 1: /* interrupt pipe */
2254 if (ur->ur_flags & UR_FLAG_IN) {
2255 q_enqueue(&(softc->ohci_rh_intrq),(queue_t *) ur);
2256 }
2257 break;
2258
2259 }
2260
2261 return 0;
2262}
#define PHYSADDR(x)
Definition: cfe.h:14
unsigned int physaddr_t
Definition: cfe.h:12
#define UNCADDR(x)
Definition: cfe.h:16
#define base
#define NULL
Definition: def.h:47
u32 status
Definition: ehci_defs.h:15
u32 pids
Definition: ehci_defs.h:12
int cnt
Definition: enet.c:409
static uint32_t val
Definition: io.h:17
u32 ptr
Definition: iso9660.c:536
u32 size
Definition: iso9660.c:537
#define KMALLOC(size, align)
Definition: lib_malloc.h:92
#define KFREE(ptr)
Definition: lib_malloc.h:93
void q_enqueue(queue_t *qb, queue_t *item)
Definition: lib_queue.c:65
queue_t * q_deqnext(queue_t *qb)
Definition: lib_queue.c:105
#define q_init(q)
Definition: lib_queue.h:56
__SIZE_TYPE__ intptr_t
Definition: lib_types.h:62
u32 uint32_t
Definition: libfdt_env.h:11
u16 uint16_t
Definition: libfdt_env.h:10
u8 uint8_t
Definition: libfdt_env.h:9
void ohci_dumptdchain(ohci_softc_t *, ohci_td_t *td)
#define OHCI_FLUSH_RANGE(s, l)
Definition: ohci.c:130
#define BSWAP32(x)
Definition: ohci.c:84
#define OHCI_PTOV(ptr)
Definition: ohci.c:91
usb_hcdrv_t ohci_driver
Definition: ohci.c:1717
void ohci_dumprhstat(uint32_t reg)
int ohcidebug
Definition: ohci.c:199
#define OHCI_VTOD(ptr)
Definition: ohci.c:92
void ohci_dumpdoneq(ohci_softc_t *softc)
void ohci_dumpportstat(int idx, uint32_t reg)
#define CACHE_ALIGN
Definition: ohci.c:520
void * ptov(uint32_t x)
Definition: usbhack.c:197
#define ALIGN(n, align)
Definition: ohci.c:521
#define ohci_td_from_transfer(softc, transfer)
Definition: ohci.c:174
#define OHCI_INVAL_RANGE(s, l)
Definition: ohci.c:129
#define ohci_ed_from_endpoint(softc, endpoint)
Definition: ohci.c:180
#define OHCI_READCSR(softc, x)
Definition: ohci.c:96
void ohci_dumptd(ohci_softc_t *, ohci_td_t *td)
#define OHCI_WRITECSR(softc, x, y)
Definition: ohci.c:94
void ohci_dumped(ohci_softc_t *, ohci_ed_t *ed)
uint32_t vtop(void *ptr)
Definition: usbhack.c:171
void ohci_dumpedchain(ohci_softc_t *, ohci_ed_t *ed)
#define OHCIDEBUG(x)
Definition: ohci.c:141
#define OHCI_VTOP(ptr)
Definition: ohci.c:90
#define ohci_transfer_from_td(softc, td)
Definition: ohci.c:177
#define M_OHCI_CMDSTATUS_HCR
Definition: ohci.h:297
#define M_OHCI_ED_LOWSPEED
Definition: ohci.h:107
#define M_OHCI_RHSTATUS_OCIC
Definition: ohci.h:401
#define M_OHCI_RHPORTSTAT_PESC
Definition: ohci.h:416
#define G_OHCI_FMINTERVAL_FI(x)
Definition: ohci.h:334
#define M_OHCI_RHPORTSTAT_POCI
Definition: ohci.h:411
#define OHCI_INTTABLE_SIZE
Definition: ohci.h:208
#define V_OHCI_TD_DI(x)
Definition: ohci.h:152
#define R_OHCI_RHPORTSTATUS(x)
Definition: ohci.h:247
#define V_OHCI_TD_DT(x)
Definition: ohci.h:160
#define R_OHCI_FMINTERVAL
Definition: ohci.h:239
#define M_OHCI_ED_SKIP
Definition: ohci.h:108
#define M_OHCI_INT_WDH
Definition: ohci.h:313
#define M_OHCI_RHPORTSTAT_ALLC
Definition: ohci.h:421
#define K_OHCI_TD_DT_TCARRY
Definition: ohci.h:165
#define V_OHCI_ED_DIR(x)
Definition: ohci.h:100
#define K_OHCI_TD_DT_DATA1
Definition: ohci.h:164
#define G_OHCI_ED_DIR(x)
Definition: ohci.h:101
#define K_OHCI_TD_OUT
Definition: ohci.h:141
#define R_OHCI_CONTROL
Definition: ohci.h:227
#define V_OHCI_TD_CC(x)
Definition: ohci.h:174
#define G_OHCI_ED_MPS(x)
Definition: ohci.h:114
#define K_OHCI_CC_NOTACCESSED
Definition: ohci.h:189
#define M_OHCI_CONTROL_CLE
Definition: ohci.h:276
#define K_OHCI_ED_DIR_IN
Definition: ohci.h:105
#define M_OHCI_CONTROL_PLE
Definition: ohci.h:274
#define G_OHCI_RHDSCRA_POTPGT(x)
Definition: ohci.h:377
#define OHCI_EDPOOL_SIZE
Definition: ohci.h:434
#define K_OHCI_TD_DT_DATA0
Definition: ohci.h:163
#define OHCI_CALC_FSMPS(x)
Definition: ohci.h:341
#define V_OHCI_ED_MPS(x)
Definition: ohci.h:113
#define M_OHCI_ED_PTRMASK
Definition: ohci.h:116
#define K_OHCI_TD_IN
Definition: ohci.h:142
#define M_OHCI_INT_SO
Definition: ohci.h:312
#define M_OHCI_RHPORTSTAT_OCIC
Definition: ohci.h:418
#define V_OHCI_CONTROL_HCFS(x)
Definition: ohci.h:281
#define R_OHCI_HCCA
Definition: ohci.h:232
#define M_OHCI_RHDSCRA_PSM
Definition: ohci.h:368
#define OHCI_RESET_DELAY
Definition: ohci.h:488
#define G_OHCI_TD_CC(x)
Definition: ohci.h:175
#define M_OHCI_CONTROL_BLE
Definition: ohci.h:277
#define V_OHCI_TD_PID(x)
Definition: ohci.h:137
#define K_OHCI_TD_SETUP
Definition: ohci.h:140
#define K_OHCI_ED_DIR_OUT
Definition: ohci.h:104
#define M_OHCI_RHSTATUS_OCI
Definition: ohci.h:398
#define K_OHCI_HCFS_RESET
Definition: ohci.h:284
#define G_OHCI_ED_FA(x)
Definition: ohci.h:91
#define R_OHCI_FMNUMBER
Definition: ohci.h:241
#define V_OHCI_CONTROL_CBSR(x)
Definition: ohci.h:266
#define OHCI_TDPOOL_SIZE
Definition: ohci.h:435
#define V_OHCI_ED_EN(x)
Definition: ohci.h:95
#define G_OHCI_TD_EC(x)
Definition: ohci.h:170
#define V_OHCI_FMINTERVAL_FI(x)
Definition: ohci.h:333
#define OHCI_ED_ALIGN
Definition: ohci.h:79
#define G_OHCI_RHDSCRA_NDP(x)
Definition: ohci.h:366
#define K_OHCI_ED_DIR_FROMTD
Definition: ohci.h:103
#define M_OHCI_RHSTATUS_LPS
Definition: ohci.h:397
#define M_OHCI_RHPORTSTAT_PRS
Definition: ohci.h:412
#define M_OHCI_CMDSTATUS_CLF
Definition: ohci.h:298
#define M_OHCI_ED_ISOCFMT
Definition: ohci.h:109
#define G_OHCI_ED_EN(x)
Definition: ohci.h:96
#define M_OHCI_ED_HALT
Definition: ohci.h:117
#define M_OHCI_RHSTATUS_LPSC
Definition: ohci.h:400
#define M_OHCI_RHPORTSTAT_PSS
Definition: ohci.h:410
#define R_OHCI_PERIODICSTART
Definition: ohci.h:242
#define OHCI_INTTREE_SIZE
Definition: ohci.h:432
#define M_OHCI_RHPORTSTAT_CCS
Definition: ohci.h:408
#define M_OHCI_CONTROL_IE
Definition: ohci.h:275
#define M_OHCI_INT_OC
Definition: ohci.h:319
#define R_OHCI_INTDISABLE
Definition: ohci.h:231
#define G_OHCI_TD_PID(x)
Definition: ohci.h:138
#define M_OHCI_RHPORTSTAT_LSDA
Definition: ohci.h:414
#define M_OHCI_FMINTERVAL_FIT
Definition: ohci.h:344
#define G_OHCI_TD_DT(x)
Definition: ohci.h:161
#define M_OHCI_INT_FNO
Definition: ohci.h:317
#define V_OHCI_FMINTERVAL_FSMPS(x)
Definition: ohci.h:338
#define M_OHCI_RHPORTSTAT_CSC
Definition: ohci.h:415
#define R_OHCI_RHDSCRB
Definition: ohci.h:245
#define R_OHCI_CMDSTATUS
Definition: ohci.h:228
#define M_OHCI_RHPORTSTAT_PPS
Definition: ohci.h:413
#define K_OHCI_CBSR_41
Definition: ohci.h:272
#define R_OHCI_RHDSCRA
Definition: ohci.h:244
#define R_OHCI_INTSTATUS
Definition: ohci.h:229
#define M_OHCI_INT_SF
Definition: ohci.h:314
#define K_OHCI_HCFS_OPERATIONAL
Definition: ohci.h:286
#define R_OHCI_RHSTATUS
Definition: ohci.h:246
#define M_OHCI_INT_ALL
Definition: ohci.h:322
#define M_OHCI_INT_RHSC
Definition: ohci.h:318
#define M_OHCI_INT_RD
Definition: ohci.h:315
#define M_OHCI_RHDSCRA_NPS
Definition: ohci.h:369
#define V_OHCI_ED_FA(x)
Definition: ohci.h:90
#define G_OHCI_TD_DI(x)
Definition: ohci.h:153
#define R_OHCI_BULKHEADED
Definition: ohci.h:236
#define R_OHCI_CONTROLHEADED
Definition: ohci.h:234
#define OHCI_TD_ALIGN
Definition: ohci.h:124
#define M_OHCI_RHPORTSTAT_PES
Definition: ohci.h:409
#define M_OHCI_INT_UE
Definition: ohci.h:316
#define M_OHCI_CMDSTATUS_BLF
Definition: ohci.h:299
#define OHCI_HCCA_ALIGN
Definition: ohci.h:210
#define K_OHCI_CC_CANCELLED
Definition: ohci.h:191
#define M_OHCI_ED_TOGGLECARRY
Definition: ohci.h:118
#define M_OHCI_RHSTATUS_DRWE
Definition: ohci.h:399
#define M_OHCI_RHPORTSTAT_PRSC
Definition: ohci.h:419
#define OHCI_TD_MAX_DATA
Definition: ohci.h:193
#define M_OHCI_TD_SHORTOK
Definition: ohci.h:133
#define M_OHCI_RHPORTSTAT_PSSC
Definition: ohci.h:417
Definition: ohci.h:81
uint32_t ed_next_ed
Definition: ohci.h:85
uint32_t ed_tailp
Definition: ohci.h:83
uint32_t ed_headp
Definition: ohci.h:84
uint32_t ed_control
Definition: ohci.h:82
struct ohci_endpoint_s * ep_next
Definition: ohci.h:438
int ep_flags
Definition: ohci.h:440
int ep_num
Definition: ohci.h:442
uint32_t ep_phys
Definition: ohci.h:439
int ep_mps
Definition: ohci.h:441
uint32_t hcca_inttable[OHCI_INTTABLE_SIZE]
Definition: ohci.h:213
uint32_t hcca_donehead
Definition: ohci.h:215
uint8_t ohci_rh_buf[128]
Definition: ohci.h:476
ohci_endpoint_t * ohci_endpoint_pool
Definition: ohci.h:458
ohci_td_t * ohci_hwtdpool
Definition: ohci.h:461
ohci_endpoint_t * ohci_inttable[OHCI_INTTABLE_SIZE]
Definition: ohci.h:453
ohci_transfer_t * ohci_transfer_pool
Definition: ohci.h:459
ohci_hcca_t * ohci_hcca
Definition: ohci.h:457
usbbus_t * ohci_bus
Definition: ohci.h:480
ohci_ed_t * ohci_hwedpool
Definition: ohci.h:460
int ohci_rh_addr
Definition: ohci.h:474
volatile uint32_t * ohci_regs
Definition: ohci.h:467
ohci_endpoint_t * ohci_ctl_list
Definition: ohci.h:455
ohci_endpoint_t * ohci_isoc_list
Definition: ohci.h:454
int ohci_ndp
Definition: ohci.h:469
ohci_transfer_t * ohci_transfer_freelist
Definition: ohci.h:463
ohci_endpoint_t * ohci_edtable[OHCI_INTTREE_SIZE]
Definition: ohci.h:452
int ohci_rh_len
Definition: ohci.h:478
uint8_t * ohci_rh_ptr
Definition: ohci.h:477
uint32_t ohci_intdisable
Definition: ohci.h:471
queue_t ohci_rh_intrq
Definition: ohci.h:479
int ohci_rh_newaddr
Definition: ohci.h:473
ohci_endpoint_t * ohci_bulk_list
Definition: ohci.h:456
ohci_endpoint_t * ohci_endpoint_freelist
Definition: ohci.h:462
uint32_t td_control
Definition: ohci.h:127
uint32_t td_be
Definition: ohci.h:130
uint32_t td_next_td
Definition: ohci.h:129
uint32_t td_cbp
Definition: ohci.h:128
struct ohci_transfer_s * t_next
Definition: ohci.h:448
int t_length
Definition: ohci.h:447
void * t_ref
Definition: ohci.h:446
uint8_t bmRequestType
Definition: usbchap9.h:352
char * udrv_name
Definition: usbd.h:291
uint8_t bNumberOfPorts
Definition: usbchap9.h:291
uint8_t bDescriptorLength
Definition: usbchap9.h:289
uint8_t bRemoveAndPowerMask[64]
Definition: usbchap9.h:297
uint8_t bPowerOnToPowerGood
Definition: usbchap9.h:294
Definition: usbd.h:92
usb_hcdrv_t * ub_hwdisp
Definition: usbd.h:95
usb_hc_t * ub_hwsoftc
Definition: usbd.h:94
int ud_flags
Definition: usbd.h:147
int ud_address
Definition: usbd.h:144
usb_driver_t * ud_drv
Definition: usbd.h:142
int up_flags
Definition: usbd.h:124
usb_ept_t * up_hwendpoint
Definition: usbd.h:120
int up_num
Definition: usbd.h:122
Definition: usbd.h:171
int ur_status
Definition: usbd.h:188
uint8_t * ur_buffer
Definition: usbd.h:185
int ur_xferred
Definition: usbd.h:187
int ur_flags
Definition: usbd.h:189
int ur_tdcount
Definition: usbd.h:202
usbdev_t * ur_dev
Definition: usbd.h:178
int ur_length
Definition: usbd.h:186
usbpipe_t * ur_pipe
Definition: usbd.h:179
struct usb_config_descr_s usb_config_descr_t
#define GETUSBFIELD(s, f)
Definition: usbchap9.h:347
#define USB_REQUEST_GET_STATUS
Definition: usbchap9.h:123
#define REQSW(req, attr)
Definition: usbchap9.h:374
#define USB_GETSTATUS_SELF_POWERED
Definition: usbchap9.h:58
#define USB_REQUEST_GET_INTERFACE
Definition: usbchap9.h:133
#define USB_PORT_FEATURE_C_PORT_OVER_CURRENT
Definition: usbchap9.h:343
#define USB_ENDPOINT_TYPE_INTERRUPT
Definition: usbchap9.h:83
#define USB_PORT_FEATURE_C_PORT_CONNECTION
Definition: usbchap9.h:340
#define PUTUSBFIELD(s, f, v)
Definition: usbchap9.h:348
#define USB_REQUEST_GET_CONFIGURATION
Definition: usbchap9.h:131
#define USB_REQUEST_GET_DESCRIPTOR
Definition: usbchap9.h:129
#define USB_REQUEST_SET_DESCRIPTOR
Definition: usbchap9.h:130
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
Definition: usbchap9.h:63
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usbchap9.h:66
#define REQCODE(req, dir, type, rec)
Definition: usbchap9.h:373
#define USB_HUB_DESCR_SIZE
Definition: usbchap9.h:287
#define USB_PORT_FEATURE_CONNECTION
Definition: usbchap9.h:333
#define USB_PORT_FEATURE_SUSPEND
Definition: usbchap9.h:335
struct usb_device_descr_s usb_device_descr_t
#define USB_DEVICE_DESCRIPTOR_TYPE
Definition: usbchap9.h:62
#define USBREQ_REC_ENDPOINT
Definition: usbchap9.h:370
#define USBREQ_REC_OTHER
Definition: usbchap9.h:371
#define USB_PORT_FEATURE_OVER_CURRENT
Definition: usbchap9.h:336
#define USB_PORT_FEATURE_C_PORT_RESET
Definition: usbchap9.h:344
#define USB_PORT_FEATURE_C_PORT_SUSPEND
Definition: usbchap9.h:342
#define USB_PORT_FEATURE_ENABLE
Definition: usbchap9.h:334
#define USB_PORT_FEATURE_LOW_SPEED
Definition: usbchap9.h:339
#define USB_PORT_FEATURE_RESET
Definition: usbchap9.h:337
#define USB_CONFIG_SELF_POWERED
Definition: usbchap9.h:93
#define USB_REQUEST_SYNC_FRAME
Definition: usbchap9.h:135
#define USB_ENDPOINT_DIRECTION_IN
Definition: usbchap9.h:101
#define USBWORD(x)
Definition: usbchap9.h:172
#define USB_HUBCHAR_PWR_NONE
Definition: usbchap9.h:302
struct usb_endpoint_descr_s usb_endpoint_descr_t
#define USB_REQUEST_SET_FEATURE
Definition: usbchap9.h:126
#define USBREQ_TYPE_CLASS
Definition: usbchap9.h:365
#define USB_PORT_FEATURE_POWER
Definition: usbchap9.h:338
#define USBREQ_REC_DEVICE
Definition: usbchap9.h:368
#define USB_REQUEST_SET_CONFIGURATION
Definition: usbchap9.h:132
#define USB_HUB_DESCRIPTOR_TYPE
Definition: usbchap9.h:69
#define USB_STRING_DESCRIPTOR_TYPE
Definition: usbchap9.h:64
#define USB_DEVICE_CLASS_HUB
Definition: usbchap9.h:152
#define USB_REQUEST_CLEAR_FEATURE
Definition: usbchap9.h:124
#define USBREQ_DIR_OUT
Definition: usbchap9.h:363
struct usb_interface_descr_s usb_interface_descr_t
#define USB_REQUEST_SET_ADDRESS
Definition: usbchap9.h:128
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usbchap9.h:65
#define USB_PORT_FEATURE_C_PORT_ENABLE
Definition: usbchap9.h:341
#define USBREQ_DIR_IN
Definition: usbchap9.h:362
#define USB_HUBCHAR_PWR_GANGED
Definition: usbchap9.h:300
#define USB_INTERFACE_CLASS_HUB
Definition: usbchap9.h:222
#define USBREQ_REC_INTERFACE
Definition: usbchap9.h:369
#define USB_HUBCHAR_PWR_IND
Definition: usbchap9.h:301
#define USBREQ_TYPE_STD
Definition: usbchap9.h:364
#define USB_REQUEST_SET_INTERFACE
Definition: usbchap9.h:134
void usb_complete_request(usbreq_t *ur, int status)
Definition: usbd.c:1105
void usb_delay_ms(usbbus_t *bus, int ms)
Definition: usbd.c:482
struct usb_hc_s usb_hc_t
Definition: usbd.h:57
#define UP_TYPE_OUT
Definition: usbd.h:115
#define UP_TYPE_IN
Definition: usbd.h:114
#define UR_FLAG_SETUP
Definition: usbd.h:163
#define UP_TYPE_INTR
Definition: usbd.h:111
#define UR_FLAG_OUT
Definition: usbd.h:165
#define UR_FLAG_STATUS_IN
Definition: usbd.h:166
#define UP_TYPE_LOWSPEED
Definition: usbd.h:117
struct usb_ept_s usb_ept_t
Definition: usbd.h:58
#define UR_FLAG_IN
Definition: usbd.h:164
#define UP_TYPE_BULK
Definition: usbd.h:110
#define UR_FLAG_SHORTOK
Definition: usbd.h:168
#define UD_FLAG_REMOVING
Definition: usbd.h:136
#define UR_FLAG_STATUS_OUT
Definition: usbd.h:167
#define UP_TYPE_CONTROL
Definition: usbd.h:109
usbbus_t * bus
Definition: usbhack.c:153
u8 str[13]
Definition: xenos_edid.h:0