Subversion Repositories Kolibri OS

Rev

Rev 1600 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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