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