~ubuntu-branches/ubuntu/precise/seabios/precise-updates

« back to all changes in this revision

Viewing changes to .pc/0052-Push-struct-pci_device-into-USB-code-instead-of-usin.patch/src/usb-ohci.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2011-11-17 12:31:22 UTC
  • Revision ID: package-import@ubuntu.com-20111117123122-xkldgqt9u3xh7ah5
Tags: 0.6.2-0ubuntu2
* Add all patches up to commit 8e301472e324b6d6496d8b4ffc66863e99d7a505
  to match what is shipped with qemu-kvm.  This includes the fix for a
  black screen when running kvm with -vga qxl.  (LP: #823494)
* debian/rules: address lintian warning:
  debian-rules-missing-recommended-target

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Code for handling OHCI USB controllers.
 
2
//
 
3
// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
 
4
//
 
5
// This file may be distributed under the terms of the GNU LGPLv3 license.
 
6
 
 
7
#include "util.h" // dprintf
 
8
#include "pci.h" // pci_bdf_to_bus
 
9
#include "config.h" // CONFIG_*
 
10
#include "usb-ohci.h" // struct ohci_hcca
 
11
#include "pci_regs.h" // PCI_BASE_ADDRESS_0
 
12
#include "usb.h" // struct usb_s
 
13
#include "farptr.h" // GET_FLATPTR
 
14
 
 
15
#define FIT                     (1 << 31)
 
16
 
 
17
struct usb_ohci_s {
 
18
    struct usb_s usb;
 
19
    struct ohci_regs *regs;
 
20
};
 
21
 
 
22
 
 
23
/****************************************************************
 
24
 * Root hub
 
25
 ****************************************************************/
 
26
 
 
27
// Check if device attached to port
 
28
static int
 
29
ohci_hub_detect(struct usbhub_s *hub, u32 port)
 
30
{
 
31
    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
 
32
    u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
 
33
    if (!(sts & RH_PS_CCS))
 
34
        // No device.
 
35
        return -1;
 
36
 
 
37
    // XXX - need to wait for USB_TIME_ATTDB if just powered up?
 
38
 
 
39
    return 0;
 
40
}
 
41
 
 
42
// Disable port
 
43
static void
 
44
ohci_hub_disconnect(struct usbhub_s *hub, u32 port)
 
45
{
 
46
    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
 
47
    writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
 
48
}
 
49
 
 
50
// Reset device on port
 
51
static int
 
52
ohci_hub_reset(struct usbhub_s *hub, u32 port)
 
53
{
 
54
    struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
 
55
    writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS);
 
56
    u32 sts;
 
57
    u64 end = calc_future_tsc(USB_TIME_DRSTR * 2);
 
58
    for (;;) {
 
59
        sts = readl(&cntl->regs->roothub_portstatus[port]);
 
60
        if (!(sts & RH_PS_PRS))
 
61
            // XXX - need to ensure USB_TIME_DRSTR time in reset?
 
62
            break;
 
63
        if (check_tsc(end)) {
 
64
            // Timeout.
 
65
            warn_timeout();
 
66
            ohci_hub_disconnect(hub, port);
 
67
            return -1;
 
68
        }
 
69
        yield();
 
70
    }
 
71
 
 
72
    if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES))
 
73
        // Device no longer present
 
74
        return -1;
 
75
 
 
76
    return !!(sts & RH_PS_LSDA);
 
77
}
 
78
 
 
79
static struct usbhub_op_s ohci_HubOp = {
 
80
    .detect = ohci_hub_detect,
 
81
    .reset = ohci_hub_reset,
 
82
    .disconnect = ohci_hub_disconnect,
 
83
};
 
84
 
 
85
// Find any devices connected to the root hub.
 
86
static int
 
87
check_ohci_ports(struct usb_ohci_s *cntl)
 
88
{
 
89
    ASSERT32FLAT();
 
90
    // Turn on power for all devices on roothub.
 
91
    u32 rha = readl(&cntl->regs->roothub_a);
 
92
    rha &= ~(RH_A_PSM | RH_A_OCPM);
 
93
    writel(&cntl->regs->roothub_status, RH_HS_LPSC);
 
94
    writel(&cntl->regs->roothub_b, RH_B_PPCM);
 
95
    msleep((rha >> 24) * 2);
 
96
    // XXX - need to sleep for USB_TIME_SIGATT if just powered up?
 
97
 
 
98
    struct usbhub_s hub;
 
99
    memset(&hub, 0, sizeof(hub));
 
100
    hub.cntl = &cntl->usb;
 
101
    hub.portcount = rha & RH_A_NDP;
 
102
    hub.op = &ohci_HubOp;
 
103
    usb_enumerate(&hub);
 
104
    return hub.devcount;
 
105
}
 
106
 
 
107
 
 
108
/****************************************************************
 
109
 * Setup
 
110
 ****************************************************************/
 
111
 
 
112
static int
 
113
start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca)
 
114
{
 
115
    u32 oldfminterval = readl(&cntl->regs->fminterval);
 
116
    u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
 
117
 
 
118
    // XXX - check if already running?
 
119
 
 
120
    // Do reset
 
121
    writel(&cntl->regs->control, OHCI_USB_RESET | oldrwc);
 
122
    readl(&cntl->regs->control); // flush writes
 
123
    msleep(USB_TIME_DRSTR);
 
124
 
 
125
    // Do software init (min 10us, max 2ms)
 
126
    u64 end = calc_future_tsc_usec(10);
 
127
    writel(&cntl->regs->cmdstatus, OHCI_HCR);
 
128
    for (;;) {
 
129
        u32 status = readl(&cntl->regs->cmdstatus);
 
130
        if (! status & OHCI_HCR)
 
131
            break;
 
132
        if (check_tsc(end)) {
 
133
            warn_timeout();
 
134
            return -1;
 
135
        }
 
136
    }
 
137
 
 
138
    // Init memory
 
139
    writel(&cntl->regs->ed_controlhead, 0);
 
140
    writel(&cntl->regs->ed_bulkhead, 0);
 
141
    writel(&cntl->regs->hcca, (u32)hcca);
 
142
 
 
143
    // Init fminterval
 
144
    u32 fi = oldfminterval & 0x3fff;
 
145
    writel(&cntl->regs->fminterval
 
146
           , (((oldfminterval & FIT) ^ FIT)
 
147
              | fi | (((6 * (fi - 210)) / 7) << 16)));
 
148
    writel(&cntl->regs->periodicstart, ((9 * fi) / 10) & 0x3fff);
 
149
    readl(&cntl->regs->control); // flush writes
 
150
 
 
151
    // XXX - verify that fminterval was setup correctly.
 
152
 
 
153
    // Go into operational state
 
154
    writel(&cntl->regs->control
 
155
           , (OHCI_CTRL_CBSR | OHCI_CTRL_CLE | OHCI_CTRL_PLE
 
156
              | OHCI_USB_OPER | oldrwc));
 
157
    readl(&cntl->regs->control); // flush writes
 
158
 
 
159
    return 0;
 
160
}
 
161
 
 
162
static void
 
163
stop_ohci(struct usb_ohci_s *cntl)
 
164
{
 
165
    u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
 
166
    writel(&cntl->regs->control, oldrwc);
 
167
    readl(&cntl->regs->control); // flush writes
 
168
}
 
169
 
 
170
static void
 
171
configure_ohci(void *data)
 
172
{
 
173
    struct usb_ohci_s *cntl = data;
 
174
 
 
175
    // Allocate memory
 
176
    struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca));
 
177
    struct ohci_ed *intr_ed = malloc_high(sizeof(*intr_ed));
 
178
    if (!hcca || !intr_ed) {
 
179
        warn_noalloc();
 
180
        goto free;
 
181
    }
 
182
    memset(hcca, 0, sizeof(*hcca));
 
183
    memset(intr_ed, 0, sizeof(*intr_ed));
 
184
    intr_ed->hwINFO = ED_SKIP;
 
185
    int i;
 
186
    for (i=0; i<ARRAY_SIZE(hcca->int_table); i++)
 
187
        hcca->int_table[i] = (u32)intr_ed;
 
188
 
 
189
    int ret = start_ohci(cntl, hcca);
 
190
    if (ret)
 
191
        goto err;
 
192
 
 
193
    int count = check_ohci_ports(cntl);
 
194
    free_pipe(cntl->usb.defaultpipe);
 
195
    if (! count)
 
196
        goto err;
 
197
    return;
 
198
 
 
199
err:
 
200
    stop_ohci(cntl);
 
201
free:
 
202
    free(hcca);
 
203
    free(intr_ed);
 
204
}
 
205
 
 
206
void
 
207
ohci_init(u16 bdf, int busid)
 
208
{
 
209
    if (! CONFIG_USB_OHCI)
 
210
        return;
 
211
    struct usb_ohci_s *cntl = malloc_tmphigh(sizeof(*cntl));
 
212
    memset(cntl, 0, sizeof(*cntl));
 
213
    cntl->usb.busid = busid;
 
214
    cntl->usb.bdf = bdf;
 
215
    cntl->usb.type = USB_TYPE_OHCI;
 
216
 
 
217
    u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
 
218
    cntl->regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK);
 
219
 
 
220
    dprintf(1, "OHCI init on dev %02x:%02x.%x (regs=%p)\n"
 
221
            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)
 
222
            , pci_bdf_to_fn(bdf), cntl->regs);
 
223
 
 
224
    // Enable bus mastering and memory access.
 
225
    pci_config_maskw(bdf, PCI_COMMAND
 
226
                     , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY);
 
227
 
 
228
    // XXX - check for and disable SMM control?
 
229
 
 
230
    // Disable interrupts
 
231
    writel(&cntl->regs->intrdisable, ~0);
 
232
    writel(&cntl->regs->intrstatus, ~0);
 
233
 
 
234
    run_thread(configure_ohci, cntl);
 
235
}
 
236
 
 
237
 
 
238
/****************************************************************
 
239
 * End point communication
 
240
 ****************************************************************/
 
241
 
 
242
static int
 
243
wait_ed(struct ohci_ed *ed)
 
244
{
 
245
    // XXX - 500ms just a guess
 
246
    u64 end = calc_future_tsc(500);
 
247
    for (;;) {
 
248
        if (ed->hwHeadP == ed->hwTailP)
 
249
            return 0;
 
250
        if (check_tsc(end)) {
 
251
            warn_timeout();
 
252
            return -1;
 
253
        }
 
254
        yield();
 
255
    }
 
256
}
 
257
 
 
258
// Wait for next USB frame to start - for ensuring safe memory release.
 
259
static void
 
260
ohci_waittick(struct usb_ohci_s *cntl)
 
261
{
 
262
    barrier();
 
263
    struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
 
264
    u32 startframe = hcca->frame_no;
 
265
    u64 end = calc_future_tsc(1000 * 5);
 
266
    for (;;) {
 
267
        if (hcca->frame_no != startframe)
 
268
            break;
 
269
        if (check_tsc(end)) {
 
270
            warn_timeout();
 
271
            return;
 
272
        }
 
273
        yield();
 
274
    }
 
275
}
 
276
 
 
277
static void
 
278
signal_freelist(struct usb_ohci_s *cntl)
 
279
{
 
280
    u32 v = readl(&cntl->regs->control);
 
281
    if (v & OHCI_CTRL_CLE) {
 
282
        writel(&cntl->regs->control, v & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE));
 
283
        ohci_waittick(cntl);
 
284
        writel(&cntl->regs->ed_controlcurrent, 0);
 
285
        writel(&cntl->regs->ed_bulkcurrent, 0);
 
286
        writel(&cntl->regs->control, v);
 
287
    } else {
 
288
        ohci_waittick(cntl);
 
289
    }
 
290
}
 
291
 
 
292
struct ohci_pipe {
 
293
    struct ohci_ed ed;
 
294
    struct usb_pipe pipe;
 
295
    void *data;
 
296
    int count;
 
297
    struct ohci_td *tds;
 
298
};
 
299
 
 
300
void
 
301
ohci_free_pipe(struct usb_pipe *p)
 
302
{
 
303
    if (! CONFIG_USB_OHCI)
 
304
        return;
 
305
    dprintf(7, "ohci_free_pipe %p\n", p);
 
306
    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
 
307
    struct usb_ohci_s *cntl = container_of(
 
308
        pipe->pipe.cntl, struct usb_ohci_s, usb);
 
309
 
 
310
    u32 *pos = &cntl->regs->ed_controlhead;
 
311
    for (;;) {
 
312
        struct ohci_ed *next = (void*)*pos;
 
313
        if (!next) {
 
314
            // Not found?!  Exit without freeing.
 
315
            warn_internalerror();
 
316
            return;
 
317
        }
 
318
        if (next == &pipe->ed) {
 
319
            *pos = next->hwNextED;
 
320
            signal_freelist(cntl);
 
321
            free(pipe);
 
322
            return;
 
323
        }
 
324
        pos = &next->hwNextED;
 
325
    }
 
326
}
 
327
 
 
328
struct usb_pipe *
 
329
ohci_alloc_control_pipe(struct usb_pipe *dummy)
 
330
{
 
331
    if (! CONFIG_USB_OHCI)
 
332
        return NULL;
 
333
    struct usb_ohci_s *cntl = container_of(
 
334
        dummy->cntl, struct usb_ohci_s, usb);
 
335
    dprintf(7, "ohci_alloc_control_pipe %p\n", &cntl->usb);
 
336
 
 
337
    // Allocate a queue head.
 
338
    struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
 
339
    if (!pipe) {
 
340
        warn_noalloc();
 
341
        return NULL;
 
342
    }
 
343
    memset(pipe, 0, sizeof(*pipe));
 
344
    memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
 
345
    pipe->ed.hwINFO = ED_SKIP;
 
346
 
 
347
    // Add queue head to controller list.
 
348
    pipe->ed.hwNextED = cntl->regs->ed_controlhead;
 
349
    barrier();
 
350
    cntl->regs->ed_controlhead = (u32)&pipe->ed;
 
351
    return &pipe->pipe;
 
352
}
 
353
 
 
354
int
 
355
ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
 
356
             , void *data, int datasize)
 
357
{
 
358
    if (! CONFIG_USB_OHCI)
 
359
        return -1;
 
360
    dprintf(5, "ohci_control %p\n", p);
 
361
    if (datasize > 4096) {
 
362
        // XXX - should support larger sizes.
 
363
        warn_noalloc();
 
364
        return -1;
 
365
    }
 
366
    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
 
367
    struct usb_ohci_s *cntl = container_of(
 
368
        pipe->pipe.cntl, struct usb_ohci_s, usb);
 
369
    int maxpacket = pipe->pipe.maxpacket;
 
370
    int lowspeed = pipe->pipe.speed;
 
371
    int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
 
372
 
 
373
    // Setup transfer descriptors
 
374
    struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3);
 
375
    if (!tds) {
 
376
        warn_noalloc();
 
377
        return -1;
 
378
    }
 
379
    struct ohci_td *td = tds;
 
380
    td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC;
 
381
    td->hwCBP = (u32)cmd;
 
382
    td->hwNextTD = (u32)&td[1];
 
383
    td->hwBE = (u32)cmd + cmdsize - 1;
 
384
    td++;
 
385
    if (datasize) {
 
386
        td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC;
 
387
        td->hwCBP = (u32)data;
 
388
        td->hwNextTD = (u32)&td[1];
 
389
        td->hwBE = (u32)data + datasize - 1;
 
390
        td++;
 
391
    }
 
392
    td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC;
 
393
    td->hwCBP = 0;
 
394
    td->hwNextTD = (u32)&td[1];
 
395
    td->hwBE = 0;
 
396
    td++;
 
397
 
 
398
    // Transfer data
 
399
    pipe->ed.hwINFO = ED_SKIP;
 
400
    barrier();
 
401
    pipe->ed.hwHeadP = (u32)tds;
 
402
    pipe->ed.hwTailP = (u32)td;
 
403
    barrier();
 
404
    pipe->ed.hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0);
 
405
    writel(&cntl->regs->cmdstatus, OHCI_CLF);
 
406
 
 
407
    int ret = wait_ed(&pipe->ed);
 
408
    pipe->ed.hwINFO = ED_SKIP;
 
409
    if (ret)
 
410
        ohci_waittick(cntl);
 
411
    free(tds);
 
412
    return ret;
 
413
}
 
414
 
 
415
struct usb_pipe *
 
416
ohci_alloc_bulk_pipe(struct usb_pipe *dummy)
 
417
{
 
418
    if (! CONFIG_USB_OHCI)
 
419
        return NULL;
 
420
    dprintf(1, "OHCI Bulk transfers not supported.\n");
 
421
    return NULL;
 
422
}
 
423
 
 
424
int
 
425
ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
 
426
{
 
427
    return -1;
 
428
}
 
429
 
 
430
struct usb_pipe *
 
431
ohci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp)
 
432
{
 
433
    if (! CONFIG_USB_OHCI)
 
434
        return NULL;
 
435
    struct usb_ohci_s *cntl = container_of(
 
436
        dummy->cntl, struct usb_ohci_s, usb);
 
437
    dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
 
438
 
 
439
    if (frameexp > 5)
 
440
        frameexp = 5;
 
441
    int maxpacket = dummy->maxpacket;
 
442
    int lowspeed = dummy->speed;
 
443
    int devaddr = dummy->devaddr | (dummy->ep << 7);
 
444
    // Determine number of entries needed for 2 timer ticks.
 
445
    int ms = 1<<frameexp;
 
446
    int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms)+1;
 
447
    struct ohci_pipe *pipe = malloc_low(sizeof(*pipe));
 
448
    struct ohci_td *tds = malloc_low(sizeof(*tds) * count);
 
449
    void *data = malloc_low(maxpacket * count);
 
450
    if (!pipe || !tds || !data)
 
451
        goto err;
 
452
    memset(pipe, 0, sizeof(*pipe));
 
453
    memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
 
454
    pipe->data = data;
 
455
    pipe->count = count;
 
456
    pipe->tds = tds;
 
457
 
 
458
    struct ohci_ed *ed = &pipe->ed;
 
459
    ed->hwHeadP = (u32)&tds[0];
 
460
    ed->hwTailP = (u32)&tds[count-1];
 
461
    ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0);
 
462
 
 
463
    int i;
 
464
    for (i=0; i<count-1; i++) {
 
465
        tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC;
 
466
        tds[i].hwCBP = (u32)data + maxpacket * i;
 
467
        tds[i].hwNextTD = (u32)&tds[i+1];
 
468
        tds[i].hwBE = tds[i].hwCBP + maxpacket - 1;
 
469
    }
 
470
 
 
471
    // Add to interrupt schedule.
 
472
    barrier();
 
473
    struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
 
474
    if (frameexp == 0) {
 
475
        // Add to existing interrupt entry.
 
476
        struct ohci_ed *intr_ed = (void*)hcca->int_table[0];
 
477
        ed->hwNextED = intr_ed->hwNextED;
 
478
        intr_ed->hwNextED = (u32)ed;
 
479
    } else {
 
480
        int startpos = 1<<(frameexp-1);
 
481
        ed->hwNextED = hcca->int_table[startpos];
 
482
        for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms)
 
483
            hcca->int_table[i] = (u32)ed;
 
484
    }
 
485
 
 
486
    return &pipe->pipe;
 
487
 
 
488
err:
 
489
    free(pipe);
 
490
    free(tds);
 
491
    free(data);
 
492
    return NULL;
 
493
}
 
494
 
 
495
int
 
496
ohci_poll_intr(struct usb_pipe *p, void *data)
 
497
{
 
498
    ASSERT16();
 
499
    if (! CONFIG_USB_OHCI)
 
500
        return -1;
 
501
 
 
502
    struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
 
503
    struct ohci_td *tds = GET_FLATPTR(pipe->tds);
 
504
    struct ohci_td *head = (void*)(GET_FLATPTR(pipe->ed.hwHeadP) & ~(ED_C|ED_H));
 
505
    struct ohci_td *tail = (void*)GET_FLATPTR(pipe->ed.hwTailP);
 
506
    int count = GET_FLATPTR(pipe->count);
 
507
    int pos = (tail - tds + 1) % count;
 
508
    struct ohci_td *next = &tds[pos];
 
509
    if (head == next)
 
510
        // No intrs found.
 
511
        return -1;
 
512
    // XXX - check for errors.
 
513
 
 
514
    // Copy data.
 
515
    int maxpacket = GET_FLATPTR(pipe->pipe.maxpacket);
 
516
    void *pipedata = GET_FLATPTR(pipe->data);
 
517
    void *intrdata = pipedata + maxpacket * pos;
 
518
    memcpy_far(GET_SEG(SS), data
 
519
               , FLATPTR_TO_SEG(intrdata), (void*)FLATPTR_TO_OFFSET(intrdata)
 
520
               , maxpacket);
 
521
 
 
522
    // Reenable this td.
 
523
    SET_FLATPTR(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC);
 
524
    intrdata = pipedata + maxpacket * (tail-tds);
 
525
    SET_FLATPTR(tail->hwCBP, (u32)intrdata);
 
526
    SET_FLATPTR(tail->hwNextTD, (u32)next);
 
527
    SET_FLATPTR(tail->hwBE, (u32)intrdata + maxpacket - 1);
 
528
    barrier();
 
529
    SET_FLATPTR(pipe->ed.hwTailP, (u32)next);
 
530
 
 
531
    return 0;
 
532
}