Subversion Repositories Kolibri OS

Rev

Rev 1029 | 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_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
 
1600 serge 121
{
1029 serge 122
    int    port;
1600 serge 123
    u32_t  ifl;
124
    u16_t  dev_status;
125
    int i;
1029 serge 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 = kmalloc(sizeof(udev_t),0);
1600 serge 215
1029 serge 216
 
217
218
 
219
220
 
221
                status = in16(hc->iobase + USBPORTSC1 + (port * 2));
222
                dbgprintf("port%d status %x\n", port, status);
223
224
 
1600 serge 225
226
 
1029 serge 227
                dev->port     = port;
228
                dev->ep0_size = 8;
229
                dev->status   = status;
230
231
 
232
                if(status & 4)
233
                    dbgprintf(" enabled");
234
                else
235
                    dbgprintf(" disabled");
236
                if(status & 0x100){
237
                    dev->speed = 0x4000000;
238
                    dbgprintf(" low speed\n");
239
                } else {
240
                    dev->speed = 0;
241
                    dbgprintf(" full speed\n");
242
                };
243
244
 
245
                    list_add_tail(&dev->list, &newdev_list);
1600 serge 246
                    hc->port_map |= 1<
1029 serge 247
                }
248
                else {
249
                    free(dev);
250
                    out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
251
                }
252
                break;
253
            };
254
        };
255
    };
256
    return true;
1600 serge 257
};
1029 serge 258
259
 
260
      req_descr[4]  = {0x0680,0x0100,0x0000,8};
261
262
 
263
IN(69) OUT(E1) SETUP(2D)
264
SETUP(0) IN(1)
265
SETUP(0) OUT(1) OUT(0) OUT(1)...IN(1)
266
SETUP(0) IN(1) IN(0) IN(1)...OUT(0)
267
*/
268
269
 
270
 
1600 serge 271
{
1029 serge 272
    static  udev_id   = 0;
273
    static  udev_addr = 0;
274
    static  u16_t __attribute__((aligned(16)))
275
            req_addr[4] = {0x0500,0x0001,0x0000,0x0000};
276
277
 
278
            req_descr[4]  = {0x0680,0x0100,0x0000,8};
279
280
 
281
282
 
283
    td_t  *td0, *td1, *td2;
284
    u32_t   dev_status;
285
    count_t timeout;
286
    int address;
287
288
 
289
290
 
291
292
 
293
        return false;
1600 serge 294
1029 serge 295
 
296
    dev->id   = (++udev_id << 8) | address;
297
298
 
299
300
 
301
    data[1] = 0;
302
303
 
304
        return false;
1600 serge 305
1029 serge 306
 
307
    dev->ep0_size = descr->bMaxPacketSize0;
308
309
 
1600 serge 310
}
1029 serge 311
312
 
313
                          void *data, size_t req_size)
314
{
315
    td_t  *td, *td_prev;
316
    addr_t data_dma;
317
318
 
1600 serge 319
    size_t  size = req_size;
320
1029 serge 321
 
1600 serge 322
1029 serge 323
 
1600 serge 324
1029 serge 325
 
326
    rq->size = req_size;
327
    rq->dev  = dev;
1600 serge 328
1029 serge 329
 
330
        data_dma = DMA(data);
331
332
 
333
334
 
1600 serge 335
    {
1029 serge 336
        if ( size < packet_size)
1600 serge 337
        {
338
            packet_size = size;
339
        };
340
341
 
1029 serge 342
        td->link = 1;
1600 serge 343
1029 serge 344
 
345
            rq->td_head = td;
346
347
 
348
            td_prev->link   = td->dma | 4;
349
        td->status = 0x00800000 | dev->speed;
350
        td->token  = TOKEN(packet_size,enp->toggle,enp->address,
1600 serge 351
                           dev->addr,dir);
1029 serge 352
        td->buffer = data_dma;
353
        td->bk     = td_prev;
354
355
 
356
357
 
1600 serge 358
        size-= packet_size;
359
        enp->toggle ^= DATA1;
1029 serge 360
    }
361
    rq->td_tail = td;
362
/*
363
    dbgprintf("create request %x\n"
364
              "head           %x\n"
365
              "tail           %x\n"
366
              "data           %x\n"
367
              "size           %x\n",
368
              rq, rq->td_head, rq->td_tail,
369
              rq->data, rq->size);
370
*/
371
    return rq;
372
}
373
374
 
1600 serge 375
                  void *data, size_t req_size)
1029 serge 376
{
377
    size_t  packet_size = dev->ep0_size;
378
    size_t  size = req_size;
379
    u32_t   toggle = DATA1;
380
381
 
382
    qh_t   *qh;
383
    addr_t  data_dma = 0;
384
    bool    retval;
1600 serge 385
1029 serge 386
 
387
388
 
389
    td0->token  = TOKEN( 8, DATA0, 0, dev->addr, 0x2D);
390
    td0->buffer = DMA(req);
391
    td0->bk     = NULL;
392
393
 
394
        data_dma = DMA(data);
395
396
 
397
398
 
1600 serge 399
    {
1029 serge 400
        if ( size < packet_size)
1600 serge 401
        {
402
            packet_size = size;
403
        };
404
405
 
1029 serge 406
        td_prev->link   = td->dma | 4;
407
        td->status = 0x00800000 | dev->speed;
408
        td->token  = TOKEN(packet_size, toggle, 0,dev->addr, pid);
409
        td->buffer = data_dma;
410
        td->bk     = td_prev;
411
412
 
413
414
 
415
        size-= packet_size;
416
        toggle ^= DATA1;
417
    }
418
419
 
420
    td_prev->link   = td->dma | 4;
421
422
 
423
424
 
425
    td->status = 0x00800000 | dev->speed;
426
    td->token  = (0x7FF<<21)|DATA1|(dev->addr<<8)|pid;
427
    td->buffer = 0;
428
    td->bk     = td_prev;
429
430
 
431
432
 
433
    __asm__ __volatile__ ("":::"memory");
434
435
 
436
    while(timeout--){
437
        delay(10/10);
438
        if( !(td->status & TD_CTRL_ACTIVE))
439
            break;
440
    }
441
442
 
443
        (td_prev->status & TD_ANY_ERROR) ||
444
        (td->status & TD_ANY_ERROR))
445
    {
446
        u32_t dev_status = in16(dev->host->iobase + USBSTS);
447
448
 
449
                   in16(dev->host->iobase + USBFRNUM),
450
                   in16(dev->host->iobase + USBCMD),
451
                    dev_status);
452
        dbgprintf("td0 status %x\n",td0->status);
453
        dbgprintf("td_prev status %x\n",td_prev->status);
454
        dbgprintf("td status %x\n",td->status);
455
        dbgprintf("qh %x \n", qh->qelem);
456
457
 
1600 serge 458
    } else retval = true;
459
1029 serge 460
 
461
    {
462
        td_prev = td->bk;
463
        free_td(td);
464
        td = td_prev;
465
    }while( td != NULL);
466
467
 
468
};
469
470
 
471
 
1600 serge 472
{
1029 serge 473
    static  u16_t __attribute__((aligned(16)))
474
            req_descr[4]  = {0x0680,0x0100,0x0000,18};
475
476
 
477
            req_conf[4]  = {0x0680,0x0200,0x0000,9};
478
479
 
480
481
 
482
483
 
484
485
 
486
    conf_descr_t      *conf;
487
488
 
489
               dev->id, dev->host->pciId, dev->port);
490
491
 
492
        return;
493
494
 
495
496
 
497
              "bLength             %d\n"
498
              "bDescriptorType     %d\n"
499
              "bcdUSB              %x\n"
500
              "bDeviceClass        %x\n"
501
              "bDeviceSubClass     %x\n"
502
              "bDeviceProtocol     %x\n"
503
              "bMaxPacketSize0     %d\n"
504
              "idVendor            %x\n"
505
              "idProduct           %x\n"
506
              "bcdDevice           %x\n"
507
              "iManufacturer       %x\n"
508
              "iProduct            %x\n"
509
              "iSerialNumber       %x\n"
510
              "bNumConfigurations  %d\n\n",
511
              descr.bLength, descr.bDescriptorType,
512
              descr.bcdUSB,  descr.bDeviceClass,
513
              descr.bDeviceSubClass, descr.bDeviceProtocol,
514
              descr.bMaxPacketSize0, descr.idVendor,
515
              descr.idProduct, descr.bcdDevice,
516
              descr.iManufacturer, descr.iProduct,
517
              descr.iSerialNumber, descr.bNumConfigurations);
518
519
 
520
    if( !ctrl_request(dev, req_conf, DIN, &data, 8))
521
        return;
522
523
 
524
525
 
526
527
 
528
    conf = malloc(conf_size);
529
530
 
531
        return;
532
533
 
534
    dptr+= conf->bLength;
535
536
 
537
              "bLength             %d\n"
538
              "bDescriptorType     %d\n"
539
              "wTotalLength        %d\n"
540
              "bNumInterfaces      %d\n"
541
              "bConfigurationValue %x\n"
542
              "iConfiguration      %d\n"
543
              "bmAttributes        %x\n"
544
              "bMaxPower           %dmA\n\n",
545
              conf->bLength,
546
              conf->bDescriptorType,
547
              conf->wTotalLength,
548
              conf->bNumInterfaces,
549
              conf->bConfigurationValue,
550
              conf->iConfiguration,
551
              conf->bmAttributes,
552
              conf->bMaxPower*2);
553
554
 
555
556
 
557
        {
558
            case USB_CLASS_AUDIO:
559
                dbgprintf( "audio device\n");
560
                break;
561
            case USB_CLASS_HID:
562
                dev->conf = conf;
563
                list_del(&dev->list);
1600 serge 564
                return init_hid(dev);
1029 serge 565
566
 
567
                dbgprintf("printer\n");
568
                break;
569
            case USB_CLASS_MASS_STORAGE:
570
                dbgprintf("mass storage device\n");
571
                break;
572
            case USB_CLASS_HUB:
573
                dbgprintf("hub device\n");
574
                break;
575
            default:
576
                dbgprintf("unknown device\n");
577
        };
578
};
579
>