Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1029 serge 1
 
2
#define UHCI_USBCMD                  0  /* command register */
3
#define UHCI_USBINTR                 4  /* interrupt register */
4
#define UHCI_USBLEGSUP_RWC      0x8f00  /* the R/WC bits */
5
#define UHCI_USBLEGSUP_RO       0x5040  /* R/O and reserved bits */
6
#define UHCI_USBCMD_RUN         0x0001  /* RUN/STOP bit */
7
#define UHCI_USBCMD_HCRESET     0x0002  /* Host Controller reset */
8
#define UHCI_USBCMD_EGSM        0x0008  /* Global Suspend Mode */
9
#define UHCI_USBCMD_CONFIGURE   0x0040  /* Config Flag */
10
#define UHCI_USBINTR_RESUME     0x0002  /* Resume interrupt enable */
11
12
 
13
 
14
#define  USBCMD_RS              0x0001  /* Run/Stop */
15
#define  USBCMD_HCRESET         0x0002  /* Host reset */
16
#define  USBCMD_GRESET          0x0004  /* Global reset */
17
#define  USBCMD_EGSM            0x0008  /* Global Suspend Mode */
18
#define  USBCMD_FGR             0x0010  /* Force Global Resume */
19
#define  USBCMD_SWDBG           0x0020  /* SW Debug mode */
20
#define  USBCMD_CF              0x0040  /* Config Flag (sw only) */
21
#define  USBCMD_MAXP            0x0080  /* Max Packet (0 = 32, 1 = 64) */
22
23
 
24
#define   USBSTS_USBINT         0x0001  /* Interrupt due to IOC */
25
#define   USBSTS_ERROR          0x0002  /* Interrupt due to error */
26
#define   USBSTS_RD             0x0004  /* Resume Detect */
27
#define   USBSTS_HSE            0x0008  /* Host System Error: PCI problems */
28
#define   USBSTS_HCPE           0x0010  /* Host Controller Process Error:
29
                                         * the schedule is buggy */
30
#define   USBSTS_HCH            0x0020  /* HC Halted */
31
32
 
33
 
34
#define  USBFLBASEADD                8
35
#define  USBSOF                     12
36
#define  USBSOF_DEFAULT             64  /* Frame length is exactly 1 ms */
37
38
 
39
#define  USBPORTSC2                 18
40
41
 
42
43
 
44
 
45
 * Make sure the controller is completely inactive, unable to
46
 * generate interrupts or do DMA.
47
 */
48
void uhci_reset_hc(hc_t *hc)
49
{
50
	/* Turn off PIRQ enable and SMI enable.  (This also turns off the
51
	 * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
52
	 */
53
    pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
54
55
 
56
	 * new notification of any already connected
57
	 * ports due to the virtual disconnect that it
58
	 * implies.
59
	 */
60
    out16(hc->iobase + UHCI_USBCMD, UHCI_USBCMD_HCRESET);
61
    __asm__ __volatile__ ("":::"memory");
62
63
 
64
65
 
66
        dbgprintf("HCRESET not completed yet!\n");
67
68
 
69
	 * make sure the controller is stopped.
70
	 */
71
    out16(hc->iobase + UHCI_USBINTR, 0);
72
    out16(hc->iobase + UHCI_USBCMD, 0);
73
};
74
75
 
76
{
77
    u16_t legsup;
78
	unsigned int cmd, intr;
79
80
 
81
	 * When restarting a suspended controller, we expect all the
82
	 * settings to be the same as we left them:
83
	 *
84
	 *	PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
85
	 *	Controller is stopped and configured with EGSM set;
86
	 *	No interrupts enabled except possibly Resume Detect.
87
	 *
88
	 * If any of these conditions are violated we do a complete reset.
89
	 */
90
    legsup = pciReadWord(hc->PciTag, UHCI_USBLEGSUP);
91
	if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
92
        dbgprintf("%s: legsup = 0x%04x\n",__FUNCTION__, legsup);
93
		goto reset_needed;
94
	}
95
96
 
97
    if ( (cmd & UHCI_USBCMD_RUN) ||
98
        !(cmd & UHCI_USBCMD_CONFIGURE) ||
99
        !(cmd & UHCI_USBCMD_EGSM))
100
    {
101
        dbgprintf("%s: cmd = 0x%04x\n", __FUNCTION__, cmd);
102
		goto reset_needed;
103
	}
104
105
 
106
    if (intr & (~UHCI_USBINTR_RESUME))
107
    {
108
        dbgprintf("%s: intr = 0x%04x\n", __FUNCTION__, intr);
109
		goto reset_needed;
110
	}
111
	return 0;
112
113
 
114
    dbgprintf("Performing full reset\n");
115
    uhci_reset_hc(hc);
116
	return 1;
117
}
118
119
 
120
 
121
{
122
	int port;
123
    u32_t ifl;
124
    u16_t dev_status;
125
    int i;
126
127
 
128
129
 
130
    {
131
        if(hc->ioBase[i]){
132
           hc->iobase = hc->ioBase[i];
133
       //    dbgprintf("Io base_%d 0x%x\n", i,hc->ioBase[i]);
134
           break;
135
        };
136
    };
137
138
 
139
	 * they may have more but gives no way to determine how many there
140
	 * are.  However according to the UHCI spec, Bit 7 of the port
141
	 * status and control register is always set to 1.  So we try to
142
	 * use this to our advantage.  Another common failure mode when
143
	 * a nonexistent register is addressed is to return all ones, so
144
	 * we test for that also.
145
	 */
146
    for (port = 0; port < 2; port++)
147
    {
148
        u32_t status;
149
150
 
151
        dbgprintf("port%d status %x\n", port, status);
152
        if (!(status & 0x0080) || status == 0xffff)
153
			break;
154
	}
155
    dbgprintf("detected %d ports\n\n", port);
156
157
 
158
159
 
160
	 * isn't already safely quiescent.
161
	 */
162
    uhci_check_and_reset_hc(hc);
163
164
 
165
    hc->frame_dma    = GetPgAddr(hc->frame_base);
166
    hc->frame_number = 0;
167
168
 
169
170
 
171
    qh->qelem = 1;
172
173
 
174
175
 
176
177
 
178
        hc->frame_base[i] = qh->dma | 2;
179
180
 
181
 
182
    out8(hc->iobase + USBSOF, USBSOF_DEFAULT);
183
184
 
185
    out32(hc->iobase + USBFLBASEADD, hc->frame_dma);
186
187
 
188
    out16(hc->iobase + USBFRNUM, 0);
189
190
 
191
    out16(hc->iobase + USBCMD, USBCMD_RS | USBCMD_CF |
192
                               USBCMD_MAXP);
193
194
 
195
        out16(hc->iobase + USBPORTSC1 + (port * 2), 0x200);
196
    delay(100/10);
197
198
 
199
    {
200
        time_t timeout;
201
202
 
203
        dbgprintf("port%d status %x\n", port, status);
204
205
 
206
207
 
208
        while(timeout--)
209
        {
210
            delay(10/10);
211
            status = in16(hc->iobase + USBPORTSC1 + (port * 2));
212
            if(status & 1)
213
            {
214
                udev_t *dev = malloc(sizeof(udev_t));
215
216
 
217
218
 
219
220
 
221
                status = in16(hc->iobase + USBPORTSC1 + (port * 2));
222
                dbgprintf("port%d status %x\n", port, status);
223
224
 
225
                dev->id       = 0;
226
                dev->host     = hc;
227
                dev->addr     = 0;
228
                dev->port     = port;
229
                dev->ep0_size = 8;
230
                dev->status   = status;
231
232
 
233
                if(status & 4)
234
                    dbgprintf(" enabled");
235
                else
236
                    dbgprintf(" disabled");
237
                if(status & 0x100){
238
                    dev->speed = 0x4000000;
239
                    dbgprintf(" low speed\n");
240
                } else {
241
                    dev->speed = 0;
242
                    dbgprintf(" full speed\n");
243
                };
244
245
 
246
                    list_prepend(&dev->link, &newdev_list);
247
                    hc->port_map |= 1<
248
                }
249
                else {
250
                    free(dev);
251
                    out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
252
                }
253
                break;
254
            };
255
        };
256
    };
257
    return TRUE;
258
};
259
260
 
261
      req_descr[4]  = {0x0680,0x0100,0x0000,8};
262
263
 
264
IN(69) OUT(E1) SETUP(2D)
265
SETUP(0) IN(1)
266
SETUP(0) OUT(1) OUT(0) OUT(1)...IN(1)
267
SETUP(0) IN(1) IN(0) IN(1)...OUT(0)
268
*/
269
270
 
271
 
272
{
273
    static  udev_id   = 0;
274
    static  udev_addr = 0;
275
    static  u16_t __attribute__((aligned(16)))
276
            req_addr[4] = {0x0500,0x0001,0x0000,0x0000};
277
278
 
279
            req_descr[4]  = {0x0680,0x0100,0x0000,8};
280
281
 
282
283
 
284
    td_t  *td0, *td1, *td2;
285
    u32_t   dev_status;
286
    count_t timeout;
287
    int address;
288
289
 
290
291
 
292
293
 
294
        return FALSE;
295
296
 
297
    dev->id   = (++udev_id << 8) | address;
298
299
 
300
301
 
302
    data[1] = 0;
303
304
 
305
        return FALSE;
306
307
 
308
    dev->ep0_size = descr->bMaxPacketSize0;
309
310
 
311
}
312
313
 
314
                          void *data, size_t req_size)
315
{
316
    td_t  *td, *td_prev;
317
    addr_t data_dma;
318
319
 
320
321
 
322
323
 
324
    rq->td_tail = 0;
325
326
 
327
    rq->size = req_size;
328
    rq->dev = dev;
329
330
 
331
        data_dma = DMA(data);
332
333
 
334
335
 
336
    {
337
        td = alloc_td();
338
        td->link   = 1;
339
340
 
341
            rq->td_head = td;
342
343
 
344
            td_prev->link   = td->dma | 4;
345
        td->status = 0x00800000 | dev->speed;
346
        td->token  = TOKEN(enp->size,enp->toggle,enp->address,
347
                           dev->addr,dir);
348
        td->buffer = data_dma;
349
        td->bk     = td_prev;
350
351
 
352
353
 
354
        req_size-= enp->size;
355
        enp->toggle ^= DATA1;
356
    }
357
    if(req_size)
358
    {
359
        td = alloc_td();
360
        td->link   = 1;
361
362
 
363
            rq->td_head = td;
364
365
 
366
            td_prev->link   = td->dma | 4;
367
368
 
369
        td->token  = TOKEN( req_size, enp->toggle, enp->address,
370
                            dev->addr, dir);
371
        td->buffer = data_dma;
372
        td->bk     = td_prev;
373
374
 
375
    }
376
    rq->td_tail = td;
377
/*
378
    dbgprintf("create request %x\n"
379
              "head           %x\n"
380
              "tail           %x\n"
381
              "data           %x\n"
382
              "size           %x\n",
383
              rq, rq->td_head, rq->td_tail,
384
              rq->data, rq->size);
385
*/
386
    return rq;
387
}
388
389
 
390
                  void *data, size_t req_size)
391
{
392
    size_t  packet_size = dev->ep0_size;
393
    size_t  size = req_size;
394
    u32_t   toggle = DATA1;
395
396
 
397
    qh_t   *qh;
398
    addr_t  data_dma = 0;
399
    Bool    retval;
400
401
 
402
403
 
404
    td0->token  = TOKEN( 8, DATA0, 0, dev->addr, 0x2D);
405
    td0->buffer = DMA(req);
406
    td0->bk     = NULL;
407
408
 
409
        data_dma = DMA(data);
410
411
 
412
413
 
414
    {
415
        td = alloc_td();
416
        td_prev->link   = td->dma | 4;
417
        td->status = 0x00800000 | dev->speed;
418
        td->token  = TOKEN(packet_size, toggle, 0,dev->addr, pid);
419
        td->buffer = data_dma;
420
        td->bk     = td_prev;
421
422
 
423
424
 
425
        size-= packet_size;
426
        toggle ^= DATA1;
427
    }
428
    if(size)
429
    {
430
        td = alloc_td();
431
        td_prev->link   = td->dma | 4;
432
        td->status = 0x00800000 | dev->speed;
433
        td->token  = ((size-1)<<21)|toggle|(dev->addr<<8)|pid;
434
        td->buffer = data_dma;
435
        td->bk     = td_prev;
436
437
 
438
439
 
440
        size-= packet_size;
441
        toggle ^= DATA1;
442
    }
443
444
 
445
    td_prev->link   = td->dma | 4;
446
447
 
448
449
 
450
    td->status = 0x00800000 | dev->speed;
451
    td->token  = (0x7FF<<21)|DATA1|(dev->addr<<8)|pid;
452
    td->buffer = 0;
453
    td->bk     = td_prev;
454
455
 
456
457
 
458
    __asm__ __volatile__ ("":::"memory");
459
460
 
461
    while(timeout--){
462
        delay(10/10);
463
        if( !(td->status & TD_CTRL_ACTIVE))
464
            break;
465
    }
466
467
 
468
        (td_prev->status & TD_ANY_ERROR) ||
469
        (td->status & TD_ANY_ERROR))
470
    {
471
        u32_t dev_status = in16(dev->host->iobase + USBSTS);
472
473
 
474
                   in16(dev->host->iobase + USBFRNUM),
475
                   in16(dev->host->iobase + USBCMD),
476
                    dev_status);
477
        dbgprintf("td0 status %x\n",td0->status);
478
        dbgprintf("td_prev status %x\n",td_prev->status);
479
        dbgprintf("td status %x\n",td->status);
480
        dbgprintf("qh %x \n", qh->qelem);
481
482
 
483
    } else retval = TRUE;
484
485
 
486
    {
487
        td_prev = td->bk;
488
        free_td(td);
489
        td = td_prev;
490
    }while( td != NULL);
491
492
 
493
};
494
495
 
496
 
497
{
498
    static  u16_t __attribute__((aligned(16)))
499
            req_descr[4]  = {0x0680,0x0100,0x0000,18};
500
501
 
502
            req_conf[4]  = {0x0680,0x0200,0x0000,9};
503
504
 
505
506
 
507
508
 
509
510
 
511
    conf_descr_t      *conf;
512
513
 
514
               dev->id, dev->host->pciId, dev->port);
515
516
 
517
        return;
518
519
 
520
521
 
522
              "bLength             %d\n"
523
              "bDescriptorType     %d\n"
524
              "bcdUSB              %x\n"
525
              "bDeviceClass        %x\n"
526
              "bDeviceSubClass     %x\n"
527
              "bDeviceProtocol     %x\n"
528
              "bMaxPacketSize0     %d\n"
529
              "idVendor            %x\n"
530
              "idProduct           %x\n"
531
              "bcdDevice           %x\n"
532
              "iManufacturer       %x\n"
533
              "iProduct            %x\n"
534
              "iSerialNumber       %x\n"
535
              "bNumConfigurations  %d\n\n",
536
              descr.bLength, descr.bDescriptorType,
537
              descr.bcdUSB,  descr.bDeviceClass,
538
              descr.bDeviceSubClass, descr.bDeviceProtocol,
539
              descr.bMaxPacketSize0, descr.idVendor,
540
              descr.idProduct, descr.bcdDevice,
541
              descr.iManufacturer, descr.iProduct,
542
              descr.iSerialNumber, descr.bNumConfigurations);
543
544
 
545
    if( !ctrl_request(dev, req_conf, DIN, &data, 8))
546
        return;
547
548
 
549
550
 
551
552
 
553
    conf = malloc(conf_size);
554
555
 
556
        return;
557
558
 
559
    dptr+= conf->bLength;
560
561
 
562
              "bLength             %d\n"
563
              "bDescriptorType     %d\n"
564
              "wTotalLength        %d\n"
565
              "bNumInterfaces      %d\n"
566
              "bConfigurationValue %x\n"
567
              "iConfiguration      %d\n"
568
              "bmAttributes        %x\n"
569
              "bMaxPower           %dmA\n\n",
570
              conf->bLength,
571
              conf->bDescriptorType,
572
              conf->wTotalLength,
573
              conf->bNumInterfaces,
574
              conf->bConfigurationValue,
575
              conf->iConfiguration,
576
              conf->bmAttributes,
577
              conf->bMaxPower*2);
578
579
 
580
581
 
582
        {
583
            case USB_CLASS_AUDIO:
584
                dbgprintf( "audio device\n");
585
                break;
586
            case USB_CLASS_HID:
587
                dev->conf = conf;
588
                list_remove(&dev->link);
589
                return init_hid(dev);
590
591
 
592
                dbgprintf("printer\n");
593
                break;
594
            case USB_CLASS_MASS_STORAGE:
595
                dbgprintf("mass storage device\n");
596
                break;
597
            case USB_CLASS_HUB:
598
                dbgprintf("hub device\n");
599
                break;
600
            default:
601
                dbgprintf("unknown device\n");
602
        };
603
};
604
>