~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/sparc/cpu/leon3/usb_uhci.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Part of this code has been derived from linux:
 
3
 * Universal Host Controller Interface driver for USB (take II).
 
4
 *
 
5
 * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar)
 
6
 *               Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
 
7
 *               Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
 
8
 *               Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter)
 
9
 * (c) 2000      Yggdrasil Computing, Inc. (port of new PCI interface support
 
10
 *               from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
 
11
 * (C) 2000      David Brownell, david-b@pacbell.net (usb-ohci.c)
 
12
 *
 
13
 * HW-initalization based on material of
 
14
 *
 
15
 * (C) Copyright 1999 Linus Torvalds
 
16
 * (C) Copyright 1999 Johannes Erdfelt
 
17
 * (C) Copyright 1999 Randy Dunlap
 
18
 * (C) Copyright 1999 Gregory P. Smith
 
19
 *
 
20
 *
 
21
 * Adapted for U-Boot:
 
22
 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
 
23
 * (C) Copyright 2008, Daniel Hellström, daniel@gaisler.com
 
24
 *     Added AMBA Plug&Play detection of GRUSB, modified interrupt handler.
 
25
 *     Added cache flushes where needed.
 
26
 *
 
27
 * SPDX-License-Identifier:     GPL-2.0+
 
28
 */
 
29
 
 
30
/**********************************************************************
 
31
 * How it works:
 
32
 * -------------
 
33
 * The framelist / Transfer descriptor / Queue Heads are similar like
 
34
 * in the linux usb_uhci.c.
 
35
 *
 
36
 * During initialization, the following skeleton is allocated in init_skel:
 
37
 *
 
38
 *         framespecific           |           common chain
 
39
 *
 
40
 * framelist[]
 
41
 * [  0 ]-----> TD ---------\
 
42
 * [  1 ]-----> TD ----------> TD ------> QH -------> QH -------> QH ---> NULL
 
43
 *   ...        TD ---------/
 
44
 * [1023]-----> TD --------/
 
45
 *
 
46
 *              ^^             ^^         ^^          ^^          ^^
 
47
 *              7 TDs for      1 TD for   Start of    Start of    End Chain
 
48
 *              INT (2-128ms)  1ms-INT    CTRL Chain  BULK Chain
 
49
 *
 
50
 *
 
51
 * Since this is a bootloader, the isochronous transfer descriptor have been removed.
 
52
 *
 
53
 * Interrupt Transfers.
 
54
 * --------------------
 
55
 * For Interrupt transfers USB_MAX_TEMP_INT_TD Transfer descriptor are available. They
 
56
 * will be inserted after the appropriate (depending the interval setting) skeleton TD.
 
57
 * If an interrupt has been detected the dev->irqhandler is called. The status and number
 
58
 * of transfered bytes is stored in dev->irq_status resp. dev->irq_act_len. If the
 
59
 * dev->irqhandler returns 0, the interrupt TD is removed and disabled. If an 1 is returned,
 
60
 * the interrupt TD will be reactivated.
 
61
 *
 
62
 * Control Transfers
 
63
 * -----------------
 
64
 * Control Transfers are issued by filling the tmp_td with the appropriate data and connect
 
65
 * them to the qh_cntrl queue header. Before other control/bulk transfers can be issued,
 
66
 * the programm has to wait for completion. This does not allows asynchronous data transfer.
 
67
 *
 
68
 * Bulk Transfers
 
69
 * --------------
 
70
 * Bulk Transfers are issued by filling the tmp_td with the appropriate data and connect
 
71
 * them to the qh_bulk queue header. Before other control/bulk transfers can be issued,
 
72
 * the programm has to wait for completion. This does not allows asynchronous data transfer.
 
73
 *
 
74
 *
 
75
 */
 
76
 
 
77
#include <common.h>
 
78
#include <ambapp.h>
 
79
#include <asm/leon.h>
 
80
#include <asm/leon3.h>
 
81
#include <asm/processor.h>
 
82
 
 
83
#ifdef CONFIG_USB_UHCI
 
84
 
 
85
#include <usb.h>
 
86
#include "usb_uhci.h"
 
87
 
 
88
#define USB_MAX_TEMP_TD      128        /* number of temporary TDs for bulk and control transfers */
 
89
#define USB_MAX_TEMP_INT_TD  32 /* number of temporary TDs for Interrupt transfers */
 
90
 
 
91
extern int leon3_snooping_avail;
 
92
/*
 
93
#define out16r(address,data) (*(unsigned short *)(address) = \
 
94
 (unsigned short)( \
 
95
 (((unsigned short)(data)&0xff)<<8) | \
 
96
 (((unsigned short)(data)&0xff00)>>8) \
 
97
 ))
 
98
 */
 
99
#define out16r(address,data) _out16r((unsigned int)(address), (unsigned short)(data))
 
100
void _out16r(unsigned int address, unsigned short data)
 
101
{
 
102
        unsigned short val = (unsigned short)((((unsigned short)(data) & 0xff)
 
103
                                               << 8) | (((unsigned short)(data)
 
104
                                                         & 0xff00) >> 8));
 
105
#ifdef UHCI_DEBUG_REGS
 
106
        printf("out16r(0x%lx,0x%04x = 0x%04x)\n", address, val, data);
 
107
#endif
 
108
        *(unsigned short *)(address) = val;
 
109
}
 
110
 
 
111
#define out32r(address,data) _out32r((unsigned int)(address), (unsigned int)(data))
 
112
void _out32r(unsigned int address, unsigned int data)
 
113
{
 
114
        unsigned int val = (unsigned int)((((unsigned int)(data) & 0x000000ff)
 
115
                                           << 24) | (((unsigned int)(data) &
 
116
                                                      0x0000ff00) << 8) |
 
117
                                          (((unsigned int)(data) & 0x00ff0000)
 
118
                                           >> 8) | (((unsigned int)(data) &
 
119
                                                     0xff000000) >> 24));
 
120
#ifdef UHCI_DEBUG_REGS
 
121
        printf("out32r(0x%lx,0x%lx = 0x%lx)\n", address, val, data);
 
122
#endif
 
123
        *(unsigned int *)address = val;
 
124
}
 
125
 
 
126
#define in16r(address) _in16r((unsigned int)(address))
 
127
unsigned short _in16r(unsigned int address)
 
128
{
 
129
        unsigned short val = sparc_load_reg_cachemiss_word(address);
 
130
        val = ((val << 8) & 0xff00) | ((val >> 8) & 0xff);
 
131
#ifdef UHCI_DEBUG_REGS
 
132
        printf("in16r(0x%lx): 0x%04x\n", address, val);
 
133
#endif
 
134
        return val;
 
135
}
 
136
 
 
137
#define in32r(address) _in32r((unsigned int)(address))
 
138
unsigned int _in32r(unsigned int address)
 
139
{
 
140
        unsigned int val = sparc_load_reg_cachemiss(address);
 
141
        val =
 
142
            ((val << 24) & 0xff000000) | ((val << 8) & 0xff0000) | ((val >> 8) &
 
143
                                                                    0xff00) |
 
144
            ((val >> 24) & 0xff);
 
145
#ifdef UHCI_DEBUG_REGS
 
146
        printf("in32r(0x%lx): 0x%08x\n", address, val);
 
147
#endif
 
148
        return val;
 
149
}
 
150
 
 
151
#define READ32(address) sparc_load_reg_cachemiss((unsigned int)(address))
 
152
 
 
153
/*#define USB_UHCI_DEBUG*/
 
154
#undef USB_UHCI_DEBUG
 
155
 
 
156
void usb_show_td(int max);
 
157
#ifdef  USB_UHCI_DEBUG
 
158
void grusb_show_regs(void);
 
159
#define USB_UHCI_PRINTF(fmt,args...)    printf (fmt ,##args)
 
160
#else
 
161
#define USB_UHCI_PRINTF(fmt,args...)
 
162
#endif
 
163
 
 
164
static int grusb_irq = -1;      /* irq vector, if -1 uhci is stopped / reseted */
 
165
unsigned int usb_base_addr;     /* base address */
 
166
 
 
167
static uhci_td_t td_int[8] __attribute__ ((aligned(16)));       /* Interrupt Transfer descriptors */
 
168
static uhci_qh_t qh_cntrl __attribute__ ((aligned(16)));        /* control Queue Head */
 
169
static uhci_qh_t qh_bulk __attribute__ ((aligned(16))); /*  bulk Queue Head */
 
170
static uhci_qh_t qh_end __attribute__ ((aligned(16)));  /* end Queue Head */
 
171
static uhci_td_t td_last __attribute__ ((aligned(16))); /* last TD (linked with end chain) */
 
172
 
 
173
/* temporary tds */
 
174
static uhci_td_t tmp_td[USB_MAX_TEMP_TD] __attribute__ ((aligned(16))); /* temporary bulk/control td's  */
 
175
static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD] __attribute__ ((aligned(16))); /* temporary interrupt td's  */
 
176
 
 
177
static unsigned long framelist[1024] __attribute__ ((aligned(0x1000))); /* frame list */
 
178
 
 
179
static struct virt_root_hub rh; /* struct for root hub */
 
180
 
 
181
/**********************************************************************
 
182
 * some forward decleration
 
183
 */
 
184
int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
 
185
                       void *buffer, int transfer_len,
 
186
                       struct devrequest *setup);
 
187
 
 
188
/* fill a td with the approproiate data. Link, status, info and buffer
 
189
 * are used by the USB controller itselfes, dev is used to identify the
 
190
 * "connected" device
 
191
 */
 
192
void usb_fill_td(uhci_td_t * td, unsigned long link, unsigned long status,
 
193
                 unsigned long info, unsigned long buffer, unsigned long dev)
 
194
{
 
195
        td->link = swap_32(link);
 
196
        td->status = swap_32(status);
 
197
        if ((info & UHCI_PID) == 0)
 
198
                info |= USB_PID_OUT;
 
199
        td->info = swap_32(info);
 
200
        td->buffer = swap_32(buffer);
 
201
        td->dev_ptr = dev;
 
202
}
 
203
 
 
204
/* fill a qh with the approproiate data. Head and element are used by the USB controller
 
205
 * itselfes. As soon as a valid dev_ptr is filled, a td chain is connected to the qh.
 
206
 * Please note, that after completion of the td chain, the entry element is removed /
 
207
 * marked invalid by the USB controller.
 
208
 */
 
209
void usb_fill_qh(uhci_qh_t * qh, unsigned long head, unsigned long element)
 
210
{
 
211
        qh->head = swap_32(head);
 
212
        qh->element = swap_32(element);
 
213
        qh->dev_ptr = 0L;
 
214
}
 
215
 
 
216
/* get the status of a td->status
 
217
 */
 
218
unsigned long usb_uhci_td_stat(unsigned long status)
 
219
{
 
220
        unsigned long result = 0;
 
221
        result |= (status & TD_CTRL_NAK) ? USB_ST_NAK_REC : 0;
 
222
        result |= (status & TD_CTRL_STALLED) ? USB_ST_STALLED : 0;
 
223
        result |= (status & TD_CTRL_DBUFERR) ? USB_ST_BUF_ERR : 0;
 
224
        result |= (status & TD_CTRL_BABBLE) ? USB_ST_BABBLE_DET : 0;
 
225
        result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0;
 
226
        result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0;
 
227
        result |= (status & TD_CTRL_ACTIVE) ? USB_ST_NOT_PROC : 0;
 
228
        return result;
 
229
}
 
230
 
 
231
/* get the status and the transfered len of a td chain.
 
232
 * called from the completion handler
 
233
 */
 
234
int usb_get_td_status(uhci_td_t * td, struct usb_device *dev)
 
235
{
 
236
        unsigned long temp, info;
 
237
        unsigned long stat;
 
238
        uhci_td_t *mytd = td;
 
239
 
 
240
        if (dev->devnum == rh.devnum)
 
241
                return 0;
 
242
        dev->act_len = 0;
 
243
        stat = 0;
 
244
        do {
 
245
                temp = swap_32((unsigned long)READ32(&mytd->status));
 
246
                stat = usb_uhci_td_stat(temp);
 
247
                info = swap_32((unsigned long)READ32(&mytd->info));
 
248
                if (((info & 0xff) != USB_PID_SETUP) && (((info >> 21) & 0x7ff) != 0x7ff) && (temp & 0x7FF) != 0x7ff) { /* if not setup and not null data pack */
 
249
                        dev->act_len += (temp & 0x7FF) + 1;     /* the transfered len is act_len + 1 */
 
250
                }
 
251
                if (stat) {     /* status no ok */
 
252
                        dev->status = stat;
 
253
                        return -1;
 
254
                }
 
255
                temp = swap_32((unsigned long)READ32(&mytd->link));
 
256
                mytd = (uhci_td_t *) (temp & 0xfffffff0);
 
257
        } while ((temp & 0x1) == 0);    /* process all TDs */
 
258
        dev->status = stat;
 
259
        return 0;               /* Ok */
 
260
}
 
261
 
 
262
/*-------------------------------------------------------------------
 
263
 *                         LOW LEVEL STUFF
 
264
 *          assembles QHs und TDs for control, bulk and iso
 
265
 *-------------------------------------------------------------------*/
 
266
int dummy(void)
 
267
{
 
268
        USB_UHCI_PRINTF("DUMMY\n");
 
269
        return 0;
 
270
}
 
271
 
 
272
/* Submits a control message. That is a Setup, Data and Status transfer.
 
273
 * Routine does not wait for completion.
 
274
 */
 
275
int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 
276
                       int transfer_len, struct devrequest *setup)
 
277
{
 
278
        unsigned long destination, status;
 
279
        int maxsze = usb_maxpacket(dev, pipe);
 
280
        unsigned long dataptr;
 
281
        int len;
 
282
        int pktsze;
 
283
        int i = 0;
 
284
 
 
285
        if (!maxsze) {
 
286
                USB_UHCI_PRINTF
 
287
                    ("uhci_submit_control_urb: pipesize for pipe %lx is zero\n",
 
288
                     pipe);
 
289
                return -1;
 
290
        }
 
291
        if (((pipe >> 8) & 0x7f) == rh.devnum) {
 
292
                /* this is the root hub -> redirect it */
 
293
                return uhci_submit_rh_msg(dev, pipe, buffer, transfer_len,
 
294
                                          setup);
 
295
        }
 
296
        USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n",
 
297
                        transfer_len, maxsze);
 
298
        /* The "pipe" thing contains the destination in bits 8--18 */
 
299
        destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; /* Setup stage */
 
300
        /* 3 errors */
 
301
        status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
 
302
        /* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD); */
 
303
        /*  Build the TD for the control request, try forever, 8 bytes of data */
 
304
        usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, destination | (7 << 21),
 
305
                    (unsigned long)setup, (unsigned long)dev);
 
306
#ifdef DEBUG_EXTRA
 
307
        {
 
308
                char *sp = (char *)setup;
 
309
                printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe,
 
310
                       sp[0], sp[1], sp[2], sp[3], sp[4], sp[5], sp[6], sp[7]);
 
311
        }
 
312
#endif
 
313
        dataptr = (unsigned long)buffer;
 
314
        len = transfer_len;
 
315
 
 
316
        /* If direction is "send", change the frame from SETUP (0x2D)
 
317
           to OUT (0xE1). Else change it from SETUP to IN (0x69). */
 
318
        destination =
 
319
            (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN) ==
 
320
                                        0 ? USB_PID_OUT : USB_PID_IN);
 
321
        while (len > 0) {
 
322
                /* data stage */
 
323
                pktsze = len;
 
324
                i++;
 
325
                if (pktsze > maxsze)
 
326
                        pktsze = maxsze;
 
327
                destination ^= 1 << TD_TOKEN_TOGGLE;    /* toggle DATA0/1 */
 
328
                usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21), dataptr, (unsigned long)dev);        /* Status, pktsze bytes of data */
 
329
                tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]);
 
330
 
 
331
                dataptr += pktsze;
 
332
                len -= pktsze;
 
333
        }
 
334
 
 
335
        /*  Build the final TD for control status */
 
336
        /* It's only IN if the pipe is out AND we aren't expecting data */
 
337
 
 
338
        destination &= ~UHCI_PID;
 
339
        if (((pipe & USB_DIR_IN) == 0) || (transfer_len == 0))
 
340
                destination |= USB_PID_IN;
 
341
        else
 
342
                destination |= USB_PID_OUT;
 
343
        destination |= 1 << TD_TOKEN_TOGGLE;    /* End in Data1 */
 
344
        i++;
 
345
        status &= ~TD_CTRL_SPD;
 
346
        /* no limit on errors on final packet , 0 bytes of data */
 
347
        usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status | TD_CTRL_IOC,
 
348
                    destination | (UHCI_NULL_DATA_SIZE << 21), 0,
 
349
                    (unsigned long)dev);
 
350
        tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]);        /* queue status td */
 
351
        /* usb_show_td(i+1); */
 
352
        USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n", i);
 
353
        /* first mark the control QH element terminated */
 
354
        qh_cntrl.element = 0xffffffffL;
 
355
        /* set qh active */
 
356
        qh_cntrl.dev_ptr = (unsigned long)dev;
 
357
        /* fill in tmp_td_chain */
 
358
        dummy();
 
359
        qh_cntrl.element = swap_32((unsigned long)&tmp_td[0]);
 
360
        return 0;
 
361
}
 
362
 
 
363
/*-------------------------------------------------------------------
 
364
 * Prepare TDs for bulk transfers.
 
365
 */
 
366
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 
367
                    int transfer_len)
 
368
{
 
369
        unsigned long destination, status, info;
 
370
        unsigned long dataptr;
 
371
        int maxsze = usb_maxpacket(dev, pipe);
 
372
        int len;
 
373
        int i = 0;
 
374
 
 
375
        if (transfer_len < 0) {
 
376
                printf("Negative transfer length in submit_bulk\n");
 
377
                return -1;
 
378
        }
 
379
        if (!maxsze)
 
380
                return -1;
 
381
        /* The "pipe" thing contains the destination in bits 8--18. */
 
382
        destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe);
 
383
        /* 3 errors */
 
384
        status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
 
385
        /*      ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); */
 
386
        /* Build the TDs for the bulk request */
 
387
        len = transfer_len;
 
388
        dataptr = (unsigned long)buffer;
 
389
        do {
 
390
                int pktsze = len;
 
391
                if (pktsze > maxsze)
 
392
                        pktsze = maxsze;
 
393
                /* pktsze bytes of data  */
 
394
                info =
 
395
                    destination | (((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) |
 
396
                    (usb_gettoggle
 
397
                     (dev, usb_pipeendpoint(pipe),
 
398
                      usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
 
399
 
 
400
                if ((len - pktsze) == 0)
 
401
                        status |= TD_CTRL_IOC;  /* last one generates INT */
 
402
 
 
403
                usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, info, dataptr, (unsigned long)dev);      /* Status, pktsze bytes of data */
 
404
                if (i > 0)
 
405
                        tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]);
 
406
                i++;
 
407
                dataptr += pktsze;
 
408
                len -= pktsze;
 
409
                usb_dotoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
 
410
        } while (len > 0);
 
411
        /* first mark the bulk QH element terminated */
 
412
        qh_bulk.element = 0xffffffffL;
 
413
        /* set qh active */
 
414
        qh_bulk.dev_ptr = (unsigned long)dev;
 
415
        /* fill in tmp_td_chain */
 
416
        qh_bulk.element = swap_32((unsigned long)&tmp_td[0]);
 
417
        return 0;
 
418
}
 
419
 
 
420
/* search a free interrupt td
 
421
 */
 
422
uhci_td_t *uhci_alloc_int_td(void)
 
423
{
 
424
        int i;
 
425
        for (i = 0; i < USB_MAX_TEMP_INT_TD; i++) {
 
426
                if (tmp_int_td[i].dev_ptr == 0) /* no device assigned -> free TD */
 
427
                        return &tmp_int_td[i];
 
428
        }
 
429
        return NULL;
 
430
}
 
431
 
 
432
/*-------------------------------------------------------------------
 
433
 * submits USB interrupt (ie. polling ;-)
 
434
 */
 
435
int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 
436
                   int transfer_len, int interval)
 
437
{
 
438
        int nint, n;
 
439
        unsigned long status, destination;
 
440
        unsigned long info, tmp;
 
441
        uhci_td_t *mytd;
 
442
        if (interval < 0 || interval >= 256)
 
443
                return -1;
 
444
 
 
445
        if (interval == 0)
 
446
                nint = 0;
 
447
        else {
 
448
                for (nint = 0, n = 1; nint <= 8; nint++, n += n) {      /* round interval down to 2^n */
 
449
                        if (interval < n) {
 
450
                                interval = n / 2;
 
451
                                break;
 
452
                        }
 
453
                }
 
454
                nint--;
 
455
        }
 
456
 
 
457
        USB_UHCI_PRINTF("Rounded interval to %i, chain  %i\n", interval, nint);
 
458
        mytd = uhci_alloc_int_td();
 
459
        if (mytd == NULL) {
 
460
                printf("No free INT TDs found\n");
 
461
                return -1;
 
462
        }
 
463
        status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27);
 
464
/*              (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
 
465
*/
 
466
 
 
467
        destination =
 
468
            (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe) |
 
469
            (((transfer_len - 1) & 0x7ff) << 21);
 
470
 
 
471
        info =
 
472
            destination |
 
473
            (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) <<
 
474
             TD_TOKEN_TOGGLE);
 
475
        tmp = swap_32(td_int[nint].link);
 
476
        usb_fill_td(mytd, tmp, status, info, (unsigned long)buffer,
 
477
                    (unsigned long)dev);
 
478
        /* Link it */
 
479
        tmp = swap_32((unsigned long)mytd);
 
480
        td_int[nint].link = tmp;
 
481
 
 
482
        usb_dotoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
 
483
 
 
484
        return 0;
 
485
}
 
486
 
 
487
/**********************************************************************
 
488
 * Low Level functions
 
489
 */
 
490
 
 
491
void reset_hc(void)
 
492
{
 
493
 
 
494
        /* Global reset for 100ms */
 
495
        out16r(usb_base_addr + USBPORTSC1, 0x0204);
 
496
        out16r(usb_base_addr + USBPORTSC2, 0x0204);
 
497
        out16r(usb_base_addr + USBCMD, USBCMD_GRESET | USBCMD_RS);
 
498
        /* Turn off all interrupts */
 
499
        out16r(usb_base_addr + USBINTR, 0);
 
500
        mdelay(50);
 
501
        out16r(usb_base_addr + USBCMD, 0);
 
502
        mdelay(10);
 
503
}
 
504
 
 
505
void start_hc(void)
 
506
{
 
507
        int timeout = 1000;
 
508
 
 
509
        while (in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) {
 
510
                if (!--timeout) {
 
511
                        printf("USBCMD_HCRESET timed out!\n");
 
512
                        break;
 
513
                }
 
514
        }
 
515
        /* Turn on all interrupts */
 
516
        out16r(usb_base_addr + USBINTR,
 
517
               USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP);
 
518
        /* Start at frame 0 */
 
519
        out16r(usb_base_addr + USBFRNUM, 0);
 
520
        /* set Framebuffer base address */
 
521
        out32r(usb_base_addr + USBFLBASEADD, (unsigned long)&framelist);
 
522
        /* Run and mark it configured with a 64-byte max packet */
 
523
        out16r(usb_base_addr + USBCMD, USBCMD_RS | USBCMD_CF | USBCMD_MAXP);
 
524
}
 
525
 
 
526
/* Initialize the skeleton
 
527
 */
 
528
void usb_init_skel(void)
 
529
{
 
530
        unsigned long temp;
 
531
        int n;
 
532
 
 
533
        for (n = 0; n < USB_MAX_TEMP_INT_TD; n++)
 
534
                tmp_int_td[n].dev_ptr = 0L;     /* no devices connected */
 
535
        /* last td */
 
536
        usb_fill_td(&td_last, UHCI_PTR_TERM, TD_CTRL_IOC, USB_PID_OUT, 0, 0L);
 
537
        /* usb_fill_td(&td_last,UHCI_PTR_TERM,0,0,0); */
 
538
        /* End Queue Header */
 
539
        usb_fill_qh(&qh_end, UHCI_PTR_TERM, (unsigned long)&td_last);
 
540
        /* Bulk Queue Header */
 
541
        temp = (unsigned long)&qh_end;
 
542
        usb_fill_qh(&qh_bulk, temp | UHCI_PTR_QH, UHCI_PTR_TERM);
 
543
        /* Control Queue Header */
 
544
        temp = (unsigned long)&qh_bulk;
 
545
        usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH, UHCI_PTR_TERM);
 
546
        /* 1ms Interrupt td */
 
547
        temp = (unsigned long)&qh_cntrl;
 
548
        usb_fill_td(&td_int[0], temp | UHCI_PTR_QH, 0, USB_PID_OUT, 0, 0L);
 
549
        temp = (unsigned long)&td_int[0];
 
550
        for (n = 1; n < 8; n++)
 
551
                usb_fill_td(&td_int[n], temp, 0, USB_PID_OUT, 0, 0L);
 
552
        for (n = 0; n < 1024; n++) {
 
553
                /* link all framelist pointers to one of the interrupts */
 
554
                int m, o;
 
555
                if ((n & 127) == 127)
 
556
                        framelist[n] = swap_32((unsigned long)&td_int[0]);
 
557
                else
 
558
                        for (o = 1, m = 2; m <= 128; o++, m += m)
 
559
                                if ((n & (m - 1)) == ((m - 1) / 2))
 
560
                                        framelist[n] =
 
561
                                            swap_32((unsigned long)&td_int[o]);
 
562
 
 
563
        }
 
564
}
 
565
 
 
566
/* check the common skeleton for completed transfers, and update the status
 
567
 * of the "connected" device. Called from the IRQ routine.
 
568
 */
 
569
void usb_check_skel(void)
 
570
{
 
571
        struct usb_device *dev;
 
572
        /* start with the control qh */
 
573
        if (qh_cntrl.dev_ptr != 0) {    /* it's a device assigned check if this caused IRQ */
 
574
                dev = (struct usb_device *)qh_cntrl.dev_ptr;
 
575
                /* Flush cache now that hardware updated DATA and TDs/QHs */
 
576
                if (!leon3_snooping_avail)
 
577
                        sparc_dcache_flush_all();
 
578
                usb_get_td_status(&tmp_td[0], dev);     /* update status */
 
579
                if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
 
580
                        qh_cntrl.dev_ptr = 0;
 
581
                }
 
582
        }
 
583
        /* now process the bulk */
 
584
        if (qh_bulk.dev_ptr != 0) {     /* it's a device assigned check if this caused IRQ */
 
585
                dev = (struct usb_device *)qh_bulk.dev_ptr;
 
586
                /* Flush cache now that hardware updated DATA and TDs/QHs */
 
587
                if (!leon3_snooping_avail)
 
588
                        sparc_dcache_flush_all();
 
589
                usb_get_td_status(&tmp_td[0], dev);     /* update status */
 
590
                if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
 
591
                        qh_bulk.dev_ptr = 0;
 
592
                }
 
593
        }
 
594
}
 
595
 
 
596
/* check the interrupt chain, ubdate the status of the appropriate device,
 
597
 * call the appropriate irqhandler and reactivate the TD if the irqhandler
 
598
 * returns with 1
 
599
 */
 
600
void usb_check_int_chain(void)
 
601
{
 
602
        int i, res;
 
603
        unsigned long link, status;
 
604
        struct usb_device *dev;
 
605
        uhci_td_t *td, *prevtd;
 
606
 
 
607
        for (i = 0; i < 8; i++) {
 
608
                prevtd = &td_int[i];    /* the first previous td is the skeleton td */
 
609
                link = swap_32(READ32(&td_int[i].link)) & 0xfffffff0;   /* next in chain */
 
610
                td = (uhci_td_t *) link;        /* assign it */
 
611
                /* all interrupt TDs are finally linked to the td_int[0].
 
612
                 * so we process all until we find the td_int[0].
 
613
                 * if int0 chain points to a QH, we're also done
 
614
                 */
 
615
                while (((i > 0) && (link != (unsigned long)&td_int[0])) ||
 
616
                       ((i == 0)
 
617
                        && !(swap_32(READ32(&td->link)) & UHCI_PTR_QH))) {
 
618
                        /* check if a device is assigned with this td */
 
619
                        status = swap_32(READ32(&td->status));
 
620
                        if ((td->dev_ptr != 0L) && !(status & TD_CTRL_ACTIVE)) {
 
621
                                /* td is not active and a device is assigned -> call irqhandler */
 
622
                                dev = (struct usb_device *)td->dev_ptr;
 
623
                                dev->irq_act_len = ((status & 0x7FF) == 0x7FF) ? 0 : (status & 0x7FF) + 1;      /* transfered length */
 
624
                                dev->irq_status = usb_uhci_td_stat(status);     /* get status */
 
625
                                res = dev->irq_handle(dev);     /* call irqhandler */
 
626
                                if (res == 1) {
 
627
                                        /* reactivate */
 
628
                                        status |= TD_CTRL_ACTIVE;
 
629
                                        td->status = swap_32(status);
 
630
                                        prevtd = td;    /* previous td = this td */
 
631
                                } else {
 
632
                                        prevtd->link = READ32(&td->link);       /* link previous td directly to the nex td -> unlinked */
 
633
                                        /* remove device pointer */
 
634
                                        td->dev_ptr = 0L;
 
635
                                }
 
636
                        }       /* if we call the irq handler */
 
637
                        link = swap_32(READ32(&td->link)) & 0xfffffff0; /* next in chain */
 
638
                        td = (uhci_td_t *) link;        /* assign it */
 
639
                }               /* process all td in this int chain */
 
640
        }                       /* next interrupt chain */
 
641
}
 
642
 
 
643
/* usb interrupt service routine.
 
644
 */
 
645
void handle_usb_interrupt(void)
 
646
{
 
647
        unsigned short status;
 
648
        static int error = 0;
 
649
 
 
650
        /*
 
651
         * Read the interrupt status, and write it back to clear the
 
652
         * interrupt cause
 
653
         */
 
654
 
 
655
        status = in16r(usb_base_addr + USBSTS);
 
656
 
 
657
        if (!status)            /* shared interrupt, not mine */
 
658
                return;
 
659
        if (status != 1) {
 
660
                /* remove host controller halted state */
 
661
                if ((status & (USBSTS_HCPE | USBSTS_HCH)) ==
 
662
                    (USBSTS_HCPE | USBSTS_HCH)) {
 
663
                        /* Stop due to bug in driver, or hardware */
 
664
                        out16r(usb_base_addr + USBSTS, status);
 
665
                        out16r(usb_base_addr + USBCMD,
 
666
                               USBCMD_HCRESET | USBCMD_GRESET);
 
667
                        printf
 
668
                            ("GRUSB: HW detected error(s) in USB Descriptors (STS: 0x%x)\n",
 
669
                             status);
 
670
                        usb_show_td(8);
 
671
                        return;
 
672
                } else if ((status & 0x20)
 
673
                           && ((in16r(usb_base_addr + USBCMD) & USBCMD_RS) ==
 
674
                               0)) {
 
675
                        if (error < 10) {
 
676
                                out16r(usb_base_addr + USBCMD,
 
677
                                       USBCMD_RS | in16r(usb_base_addr +
 
678
                                                         USBCMD));
 
679
                                error++;
 
680
                        }
 
681
                } else
 
682
                        error = 0;
 
683
        }
 
684
        usb_check_int_chain();  /* call interrupt handlers for int tds */
 
685
        usb_check_skel();       /* call completion handler for common transfer routines */
 
686
        out16r(usb_base_addr + USBSTS, status);
 
687
}
 
688
 
 
689
/* init uhci
 
690
 */
 
691
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 
692
{
 
693
        unsigned char temp;
 
694
        ambapp_ahbdev ahbdev;
 
695
 
 
696
        /* Find GRUSB core using AMBA Plug&Play information */
 
697
        if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_UHCI, &ahbdev) != 1) {
 
698
                printf("USB UHCI: Failed to find GRUSB controller\n");
 
699
                return -1;
 
700
        }
 
701
        usb_base_addr = ahbdev.address[0];
 
702
        grusb_irq = ahbdev.irq;
 
703
        /*
 
704
           usb_base_addr = 0xfffa0000;
 
705
           grusb_irq = 10;
 
706
         */
 
707
#ifdef USB_UHCI_DEBUG
 
708
        grusb_show_regs();
 
709
#endif
 
710
        memset(td_int, 0, sizeof(td_int));
 
711
        memset(tmp_td, 0, sizeof(tmp_td));
 
712
        memset(tmp_int_td, 0, sizeof(tmp_int_td));
 
713
        memset(&qh_cntrl, 0, sizeof(qh_cntrl));
 
714
        memset(&qh_end, 0, sizeof(qh_end));
 
715
        memset(&td_last, 0, sizeof(td_last));
 
716
 
 
717
        irq_free_handler(grusb_irq);
 
718
        USB_UHCI_PRINTF("GRUSB: at 0x%lx irq %d\n", usb_base_addr, grusb_irq);
 
719
        rh.devnum = 0;
 
720
        usb_init_skel();
 
721
        reset_hc();
 
722
        start_hc();
 
723
        irq_install_handler(grusb_irq,
 
724
                            (interrupt_handler_t *) handle_usb_interrupt, NULL);
 
725
        return 0;
 
726
}
 
727
 
 
728
/* stop uhci
 
729
 */
 
730
int usb_lowlevel_stop(int index)
 
731
{
 
732
        if (grusb_irq == -1)
 
733
                return 1;
 
734
        irq_free_handler(grusb_irq);
 
735
        reset_hc();
 
736
        grusb_irq = -1;
 
737
        return 0;
 
738
}
 
739
 
 
740
/*******************************************************************************************
 
741
 * Virtual Root Hub
 
742
 * Since the uhci does not have a real HUB, we simulate one ;-)
 
743
 */
 
744
#undef  USB_RH_DEBUG
 
745
 
 
746
#ifdef  USB_RH_DEBUG
 
747
#define USB_RH_PRINTF(fmt,args...)      printf (fmt ,##args)
 
748
static void usb_display_wValue(unsigned short wValue, unsigned short wIndex);
 
749
static void usb_display_Req(unsigned short req);
 
750
#else
 
751
#define USB_RH_PRINTF(fmt,args...)
 
752
static void usb_display_wValue(unsigned short wValue, unsigned short wIndex)
 
753
{
 
754
}
 
755
static void usb_display_Req(unsigned short req)
 
756
{
 
757
}
 
758
#endif
 
759
 
 
760
#define WANT_USB_ROOT_HUB_HUB_DES
 
761
#include <usbroothubdes.h>
 
762
#undef WANT_USB_ROOT_HUB_HUB_DES
 
763
 
 
764
/*
 
765
 * Root Hub Control Pipe (interrupt Pipes are not supported)
 
766
 */
 
767
 
 
768
int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 
769
                       int transfer_len, struct devrequest *cmd)
 
770
{
 
771
        void *data = buffer;
 
772
        int leni = transfer_len;
 
773
        int len = 0;
 
774
        int status = 0;
 
775
        int stat = 0;
 
776
        int i;
 
777
 
 
778
        unsigned short cstatus;
 
779
 
 
780
        unsigned short bmRType_bReq;
 
781
        unsigned short wValue;
 
782
        unsigned short wIndex;
 
783
        unsigned short wLength;
 
784
 
 
785
        if (usb_pipeint(pipe)) {
 
786
                printf("Root-Hub submit IRQ: NOT implemented\n");
 
787
                return 0;
 
788
        }
 
789
        bmRType_bReq = cmd->requesttype | cmd->request << 8;
 
790
        wValue = swap_16(cmd->value);
 
791
        wIndex = swap_16(cmd->index);
 
792
        wLength = swap_16(cmd->length);
 
793
        usb_display_Req(bmRType_bReq);
 
794
        for (i = 0; i < 8; i++)
 
795
                rh.c_p_r[i] = 0;
 
796
        USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n",
 
797
                      dev->devnum, 8, cmd->requesttype, cmd->request, wValue,
 
798
                      wIndex, wLength);
 
799
 
 
800
        switch (bmRType_bReq) {
 
801
                /* Request Destination:
 
802
                   without flags: Device,
 
803
                   RH_INTERFACE: interface,
 
804
                   RH_ENDPOINT: endpoint,
 
805
                   RH_CLASS means HUB here,
 
806
                   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
 
807
                 */
 
808
 
 
809
        case RH_GET_STATUS:
 
810
                *(unsigned short *)data = swap_16(1);
 
811
                len = 2;
 
812
                break;
 
813
        case RH_GET_STATUS | RH_INTERFACE:
 
814
                *(unsigned short *)data = swap_16(0);
 
815
                len = 2;
 
816
                break;
 
817
        case RH_GET_STATUS | RH_ENDPOINT:
 
818
                *(unsigned short *)data = swap_16(0);
 
819
                len = 2;
 
820
                break;
 
821
        case RH_GET_STATUS | RH_CLASS:
 
822
                *(unsigned long *)data = swap_32(0);
 
823
                len = 4;
 
824
                break;          /* hub power ** */
 
825
        case RH_GET_STATUS | RH_OTHER | RH_CLASS:
 
826
 
 
827
                status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1));
 
828
                cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
 
829
                    ((status & USBPORTSC_PEC) >> (3 - 1)) |
 
830
                    (rh.c_p_r[wIndex - 1] << (0 + 4));
 
831
                status = (status & USBPORTSC_CCS) | ((status & USBPORTSC_PE) >> (2 - 1)) | ((status & USBPORTSC_SUSP) >> (12 - 2)) | ((status & USBPORTSC_PR) >> (9 - 4)) | (1 << 8) |  /* power on ** */
 
832
                    ((status & USBPORTSC_LSDA) << (-8 + 9));
 
833
 
 
834
                *(unsigned short *)data = swap_16(status);
 
835
                *(unsigned short *)(data + 2) = swap_16(cstatus);
 
836
                len = 4;
 
837
                break;
 
838
        case RH_CLEAR_FEATURE | RH_ENDPOINT:
 
839
                switch (wValue) {
 
840
                case (RH_ENDPOINT_STALL):
 
841
                        len = 0;
 
842
                        break;
 
843
                }
 
844
                break;
 
845
 
 
846
        case RH_CLEAR_FEATURE | RH_CLASS:
 
847
                switch (wValue) {
 
848
                case (RH_C_HUB_OVER_CURRENT):
 
849
                        len = 0;        /* hub power over current ** */
 
850
                        break;
 
851
                }
 
852
                break;
 
853
 
 
854
        case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
 
855
                usb_display_wValue(wValue, wIndex);
 
856
                switch (wValue) {
 
857
                case (RH_PORT_ENABLE):
 
858
                        status =
 
859
                            in16r(usb_base_addr + USBPORTSC1 +
 
860
                                  2 * (wIndex - 1));
 
861
                        status = (status & 0xfff5) & ~USBPORTSC_PE;
 
862
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
863
                               status);
 
864
                        len = 0;
 
865
                        break;
 
866
                case (RH_PORT_SUSPEND):
 
867
                        status =
 
868
                            in16r(usb_base_addr + USBPORTSC1 +
 
869
                                  2 * (wIndex - 1));
 
870
                        status = (status & 0xfff5) & ~USBPORTSC_SUSP;
 
871
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
872
                               status);
 
873
                        len = 0;
 
874
                        break;
 
875
                case (RH_PORT_POWER):
 
876
                        len = 0;        /* port power ** */
 
877
                        break;
 
878
                case (RH_C_PORT_CONNECTION):
 
879
                        status =
 
880
                            in16r(usb_base_addr + USBPORTSC1 +
 
881
                                  2 * (wIndex - 1));
 
882
                        status = (status & 0xfff5) | USBPORTSC_CSC;
 
883
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
884
                               status);
 
885
                        len = 0;
 
886
                        break;
 
887
                case (RH_C_PORT_ENABLE):
 
888
                        status =
 
889
                            in16r(usb_base_addr + USBPORTSC1 +
 
890
                                  2 * (wIndex - 1));
 
891
                        status = (status & 0xfff5) | USBPORTSC_PEC;
 
892
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
893
                               status);
 
894
                        len = 0;
 
895
                        break;
 
896
                case (RH_C_PORT_SUSPEND):
 
897
/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
 
898
                        len = 0;
 
899
                        break;
 
900
                case (RH_C_PORT_OVER_CURRENT):
 
901
                        len = 0;
 
902
                        break;
 
903
                case (RH_C_PORT_RESET):
 
904
                        rh.c_p_r[wIndex - 1] = 0;
 
905
                        len = 0;
 
906
                        break;
 
907
                }
 
908
                break;
 
909
        case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
 
910
                usb_display_wValue(wValue, wIndex);
 
911
                switch (wValue) {
 
912
                case (RH_PORT_SUSPEND):
 
913
                        status =
 
914
                            in16r(usb_base_addr + USBPORTSC1 +
 
915
                                  2 * (wIndex - 1));
 
916
                        status = (status & 0xfff5) | USBPORTSC_SUSP;
 
917
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
918
                               status);
 
919
                        len = 0;
 
920
                        break;
 
921
                case (RH_PORT_RESET):
 
922
                        status =
 
923
                            in16r(usb_base_addr + USBPORTSC1 +
 
924
                                  2 * (wIndex - 1));
 
925
                        status = (status & 0xfff5) | USBPORTSC_PR;
 
926
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
927
                               status);
 
928
                        mdelay(10);
 
929
                        status = (status & 0xfff5) & ~USBPORTSC_PR;
 
930
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
931
                               status);
 
932
                        udelay(10);
 
933
                        status = (status & 0xfff5) | USBPORTSC_PE;
 
934
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
935
                               status);
 
936
                        mdelay(10);
 
937
                        status = (status & 0xfff5) | 0xa;
 
938
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
939
                               status);
 
940
                        len = 0;
 
941
                        break;
 
942
                case (RH_PORT_POWER):
 
943
                        len = 0;        /* port power ** */
 
944
                        break;
 
945
                case (RH_PORT_ENABLE):
 
946
                        status =
 
947
                            in16r(usb_base_addr + USBPORTSC1 +
 
948
                                  2 * (wIndex - 1));
 
949
                        status = (status & 0xfff5) | USBPORTSC_PE;
 
950
                        out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
 
951
                               status);
 
952
                        len = 0;
 
953
                        break;
 
954
                }
 
955
                break;
 
956
 
 
957
        case RH_SET_ADDRESS:
 
958
                rh.devnum = wValue;
 
959
                len = 0;
 
960
                break;
 
961
        case RH_GET_DESCRIPTOR:
 
962
                switch ((wValue & 0xff00) >> 8) {
 
963
                case (0x01):    /* device descriptor */
 
964
                        i = sizeof(root_hub_config_des);
 
965
                        status = i > wLength ? wLength : i;
 
966
                        len = leni > status ? status : leni;
 
967
                        memcpy(data, root_hub_dev_des, len);
 
968
                        break;
 
969
                case (0x02):    /* configuration descriptor */
 
970
                        i = sizeof(root_hub_config_des);
 
971
                        status = i > wLength ? wLength : i;
 
972
                        len = leni > status ? status : leni;
 
973
                        memcpy(data, root_hub_config_des, len);
 
974
                        break;
 
975
                case (0x03):    /*string descriptors */
 
976
                        if (wValue == 0x0300) {
 
977
                                i = sizeof(root_hub_str_index0);
 
978
                                status = i > wLength ? wLength : i;
 
979
                                len = leni > status ? status : leni;
 
980
                                memcpy(data, root_hub_str_index0, len);
 
981
                                break;
 
982
                        }
 
983
                        if (wValue == 0x0301) {
 
984
                                i = sizeof(root_hub_str_index1);
 
985
                                status = i > wLength ? wLength : i;
 
986
                                len = leni > status ? status : leni;
 
987
                                memcpy(data, root_hub_str_index1, len);
 
988
                                break;
 
989
                        }
 
990
                        stat = USB_ST_STALLED;
 
991
                }
 
992
                break;
 
993
 
 
994
        case RH_GET_DESCRIPTOR | RH_CLASS:
 
995
                root_hub_hub_des[2] = 2;
 
996
                i = sizeof(root_hub_hub_des);
 
997
                status = i > wLength ? wLength : i;
 
998
                len = leni > status ? status : leni;
 
999
                memcpy(data, root_hub_hub_des, len);
 
1000
                break;
 
1001
        case RH_GET_CONFIGURATION:
 
1002
                *(unsigned char *)data = 0x01;
 
1003
                len = 1;
 
1004
                break;
 
1005
        case RH_SET_CONFIGURATION:
 
1006
                len = 0;
 
1007
                break;
 
1008
        default:
 
1009
                stat = USB_ST_STALLED;
 
1010
        }
 
1011
        USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n", stat,
 
1012
                      in16r(usb_base_addr + USBPORTSC1),
 
1013
                      in16r(usb_base_addr + USBPORTSC2));
 
1014
        dev->act_len = len;
 
1015
        dev->status = stat;
 
1016
        return stat;
 
1017
 
 
1018
}
 
1019
 
 
1020
/********************************************************************************
 
1021
 * Some Debug Routines
 
1022
 */
 
1023
 
 
1024
#ifdef  USB_RH_DEBUG
 
1025
 
 
1026
static void usb_display_Req(unsigned short req)
 
1027
{
 
1028
        USB_RH_PRINTF("- Root-Hub Request: ");
 
1029
        switch (req) {
 
1030
        case RH_GET_STATUS:
 
1031
                USB_RH_PRINTF("Get Status ");
 
1032
                break;
 
1033
        case RH_GET_STATUS | RH_INTERFACE:
 
1034
                USB_RH_PRINTF("Get Status Interface ");
 
1035
                break;
 
1036
        case RH_GET_STATUS | RH_ENDPOINT:
 
1037
                USB_RH_PRINTF("Get Status Endpoint ");
 
1038
                break;
 
1039
        case RH_GET_STATUS | RH_CLASS:
 
1040
                USB_RH_PRINTF("Get Status Class");
 
1041
                break;          /* hub power ** */
 
1042
        case RH_GET_STATUS | RH_OTHER | RH_CLASS:
 
1043
                USB_RH_PRINTF("Get Status Class Others");
 
1044
                break;
 
1045
        case RH_CLEAR_FEATURE | RH_ENDPOINT:
 
1046
                USB_RH_PRINTF("Clear Feature Endpoint ");
 
1047
                break;
 
1048
        case RH_CLEAR_FEATURE | RH_CLASS:
 
1049
                USB_RH_PRINTF("Clear Feature Class ");
 
1050
                break;
 
1051
        case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
 
1052
                USB_RH_PRINTF("Clear Feature Other Class ");
 
1053
                break;
 
1054
        case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
 
1055
                USB_RH_PRINTF("Set Feature Other Class ");
 
1056
                break;
 
1057
        case RH_SET_ADDRESS:
 
1058
                USB_RH_PRINTF("Set Address ");
 
1059
                break;
 
1060
        case RH_GET_DESCRIPTOR:
 
1061
                USB_RH_PRINTF("Get Descriptor ");
 
1062
                break;
 
1063
        case RH_GET_DESCRIPTOR | RH_CLASS:
 
1064
                USB_RH_PRINTF("Get Descriptor Class ");
 
1065
                break;
 
1066
        case RH_GET_CONFIGURATION:
 
1067
                USB_RH_PRINTF("Get Configuration ");
 
1068
                break;
 
1069
        case RH_SET_CONFIGURATION:
 
1070
                USB_RH_PRINTF("Get Configuration ");
 
1071
                break;
 
1072
        default:
 
1073
                USB_RH_PRINTF("****UNKNOWN**** 0x%04X ", req);
 
1074
        }
 
1075
        USB_RH_PRINTF("\n");
 
1076
 
 
1077
}
 
1078
 
 
1079
static void usb_display_wValue(unsigned short wValue, unsigned short wIndex)
 
1080
{
 
1081
        switch (wValue) {
 
1082
        case (RH_PORT_ENABLE):
 
1083
                USB_RH_PRINTF("Root-Hub: Enable Port %d\n", wIndex);
 
1084
                break;
 
1085
        case (RH_PORT_SUSPEND):
 
1086
                USB_RH_PRINTF("Root-Hub: Suspend Port %d\n", wIndex);
 
1087
                break;
 
1088
        case (RH_PORT_POWER):
 
1089
                USB_RH_PRINTF("Root-Hub: Port Power %d\n", wIndex);
 
1090
                break;
 
1091
        case (RH_C_PORT_CONNECTION):
 
1092
                USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n", wIndex);
 
1093
                break;
 
1094
        case (RH_C_PORT_ENABLE):
 
1095
                USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n", wIndex);
 
1096
                break;
 
1097
        case (RH_C_PORT_SUSPEND):
 
1098
                USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n", wIndex);
 
1099
                break;
 
1100
        case (RH_C_PORT_OVER_CURRENT):
 
1101
                USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n",
 
1102
                              wIndex);
 
1103
                break;
 
1104
        case (RH_C_PORT_RESET):
 
1105
                USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n", wIndex);
 
1106
                break;
 
1107
        default:
 
1108
                USB_RH_PRINTF("Root-Hub: unknown %x %x\n", wValue, wIndex);
 
1109
                break;
 
1110
        }
 
1111
}
 
1112
 
 
1113
#endif
 
1114
 
 
1115
/*#ifdef        USB_UHCI_DEBUG*/
 
1116
 
 
1117
static int usb_display_td(uhci_td_t * td)
 
1118
{
 
1119
        unsigned long tmp;
 
1120
        int valid;
 
1121
 
 
1122
        printf("TD at %p:\n", td);
 
1123
 
 
1124
        tmp = swap_32(READ32(&td->link));
 
1125
        printf("Link points to 0x%08lX, %s first, %s, %s\n", tmp & 0xfffffff0,
 
1126
               ((tmp & 0x4) == 0x4) ? "Depth" : "Breath",
 
1127
               ((tmp & 0x2) == 0x2) ? "QH" : "TD",
 
1128
               ((tmp & 0x1) == 0x1) ? "invalid" : "valid");
 
1129
        valid = ((tmp & 0x1) == 0x0);
 
1130
        tmp = swap_32(READ32(&td->status));
 
1131
        printf
 
1132
            ("     %s %ld Errors %s %s %s \n     %s %s %s %s %s %s\n     Len 0x%lX\n",
 
1133
             (((tmp >> 29) & 0x1) == 0x1) ? "SPD Enable" : "SPD Disable",
 
1134
             ((tmp >> 28) & 0x3),
 
1135
             (((tmp >> 26) & 0x1) == 0x1) ? "Low Speed" : "Full Speed",
 
1136
             (((tmp >> 25) & 0x1) == 0x1) ? "ISO " : "",
 
1137
             (((tmp >> 24) & 0x1) == 0x1) ? "IOC " : "",
 
1138
             (((tmp >> 23) & 0x1) == 0x1) ? "Active " : "Inactive ",
 
1139
             (((tmp >> 22) & 0x1) == 0x1) ? "Stalled" : "",
 
1140
             (((tmp >> 21) & 0x1) == 0x1) ? "Data Buffer Error" : "",
 
1141
             (((tmp >> 20) & 0x1) == 0x1) ? "Babble" : "",
 
1142
             (((tmp >> 19) & 0x1) == 0x1) ? "NAK" : "",
 
1143
             (((tmp >> 18) & 0x1) == 0x1) ? "Bitstuff Error" : "",
 
1144
             (tmp & 0x7ff));
 
1145
        tmp = swap_32(READ32(&td->info));
 
1146
        printf("     MaxLen 0x%lX\n", ((tmp >> 21) & 0x7FF));
 
1147
        printf("     %sEndpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n",
 
1148
               ((tmp >> 19) & 0x1) == 0x1 ? "TOGGLE " : "", ((tmp >> 15) & 0xF),
 
1149
               ((tmp >> 8) & 0x7F), tmp & 0xFF);
 
1150
        tmp = swap_32(READ32(&td->buffer));
 
1151
        printf("     Buffer 0x%08lX\n", tmp);
 
1152
        printf("     DEV %08lX\n", td->dev_ptr);
 
1153
        return valid;
 
1154
}
 
1155
 
 
1156
void usb_show_td(int max)
 
1157
{
 
1158
        int i;
 
1159
        if (max > 0) {
 
1160
                for (i = 0; i < max; i++) {
 
1161
                        usb_display_td(&tmp_td[i]);
 
1162
                }
 
1163
        } else {
 
1164
                i = 0;
 
1165
                do {
 
1166
                        printf("tmp_td[%d]\n", i);
 
1167
                } while (usb_display_td(&tmp_td[i++]));
 
1168
        }
 
1169
}
 
1170
 
 
1171
void grusb_show_regs(void)
 
1172
{
 
1173
        unsigned int tmp;
 
1174
 
 
1175
        tmp = in16r(usb_base_addr + USBCMD);
 
1176
        printf(" USBCMD:   0x%04x\n", tmp);
 
1177
        tmp = in16r(usb_base_addr + USBSTS);
 
1178
        printf(" USBSTS:   0x%04x\n", tmp);
 
1179
        tmp = in16r(usb_base_addr + USBINTR);
 
1180
        printf(" USBINTR:   0x%04x\n", tmp);
 
1181
        tmp = in16r(usb_base_addr + USBFRNUM);
 
1182
        printf(" FRNUM:   0x%04x\n", tmp);
 
1183
        tmp = in32r(usb_base_addr + USBFLBASEADD);
 
1184
        printf(" FLBASEADD:   0x%08x\n", tmp);
 
1185
        tmp = in16r(usb_base_addr + USBSOF);
 
1186
        printf(" SOFMOD:   0x%04x\n", tmp);
 
1187
        tmp = in16r(usb_base_addr + USBPORTSC1);
 
1188
        printf(" PORTSC1:   0x%04x\n", tmp);
 
1189
}
 
1190
 
 
1191
/*#endif*/
 
1192
#endif                          /* CONFIG_USB_UHCI */
 
1193
 
 
1194
/* EOF */