1
/* ehci.c - EHCI Support. */
3
* GRUB -- GRand Unified Bootloader
4
* Copyright (C) 2011 Free Software Foundation, Inc.
6
* GRUB is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* GRUB is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
23
#include <grub/usbtrans.h>
24
#include <grub/misc.h>
26
#include <grub/cpu/pci.h>
27
#include <grub/cpu/io.h>
28
#include <grub/time.h>
29
#include <grub/loader.h>
30
#include <grub/cs5536.h>
32
GRUB_MOD_LICENSE ("GPLv3+");
34
/* This simple GRUB implementation of EHCI driver:
36
* - is not supporting isochronous transfers (iTD, siTD)
37
* - is not supporting interrupt transfers
40
#define GRUB_EHCI_PCI_SBRN_REG 0x60
42
/* Capability registers offsets */
45
GRUB_EHCI_EHCC_CAPLEN = 0x00, /* byte */
46
GRUB_EHCI_EHCC_VERSION = 0x02, /* word */
47
GRUB_EHCI_EHCC_SPARAMS = 0x04, /* dword */
48
GRUB_EHCI_EHCC_CPARAMS = 0x08, /* dword */
49
GRUB_EHCI_EHCC_PROUTE = 0x0c, /* 60 bits */
52
#define GRUB_EHCI_EECP_MASK (0xff << 8)
53
#define GRUB_EHCI_EECP_SHIFT 8
55
#define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
56
#define GRUB_EHCI_POINTER_MASK (~0x1f)
58
/* Capability register SPARAMS bits */
61
GRUB_EHCI_SPARAMS_N_PORTS = (0xf << 0),
62
GRUB_EHCI_SPARAMS_PPC = (1 << 4), /* Power port control */
63
GRUB_EHCI_SPARAMS_PRR = (1 << 7), /* Port routing rules */
64
GRUB_EHCI_SPARAMS_N_PCC = (0xf << 8), /* No of ports per comp. */
65
GRUB_EHCI_SPARAMS_NCC = (0xf << 12), /* No of com. controllers */
66
GRUB_EHCI_SPARAMS_P_IND = (1 << 16), /* Port indicators present */
67
GRUB_EHCI_SPARAMS_DEBUG_P = (0xf << 20) /* Debug port */
70
#define GRUB_EHCI_MAX_N_PORTS 15 /* Max. number of ports */
72
/* Capability register CPARAMS bits */
75
GRUB_EHCI_CPARAMS_64BIT = (1 << 0),
76
GRUB_EHCI_CPARAMS_PROG_FRAMELIST = (1 << 1),
77
GRUB_EHCI_CPARAMS_PARK_CAP = (1 << 2)
80
#define GRUB_EHCI_N_FRAMELIST 1024
81
#define GRUB_EHCI_N_QH 256
82
#define GRUB_EHCI_N_TD 640
84
#define GRUB_EHCI_QH_EMPTY 1
86
/* USBLEGSUP bits and related OS OWNED byte offset */
89
GRUB_EHCI_BIOS_OWNED = (1 << 16),
90
GRUB_EHCI_OS_OWNED = (1 << 24)
93
/* Operational registers offsets */
96
GRUB_EHCI_COMMAND = 0x00,
97
GRUB_EHCI_STATUS = 0x04,
98
GRUB_EHCI_INTERRUPT = 0x08,
99
GRUB_EHCI_FRAME_INDEX = 0x0c,
100
GRUB_EHCI_64BIT_SEL = 0x10,
101
GRUB_EHCI_FL_BASE = 0x14,
102
GRUB_EHCI_CUR_AL_ADDR = 0x18,
103
GRUB_EHCI_CONFIG_FLAG = 0x40,
104
GRUB_EHCI_PORT_STAT_CMD = 0x44
107
/* Operational register COMMAND bits */
110
GRUB_EHCI_CMD_RUNSTOP = (1 << 0),
111
GRUB_EHCI_CMD_HC_RESET = (1 << 1),
112
GRUB_EHCI_CMD_FL_SIZE = (3 << 2),
113
GRUB_EHCI_CMD_PS_ENABL = (1 << 4),
114
GRUB_EHCI_CMD_AS_ENABL = (1 << 5),
115
GRUB_EHCI_CMD_AS_ADV_D = (1 << 6),
116
GRUB_EHCI_CMD_L_HC_RES = (1 << 7),
117
GRUB_EHCI_CMD_AS_PARKM = (3 << 8),
118
GRUB_EHCI_CMD_AS_PARKE = (1 << 11),
119
GRUB_EHCI_CMD_INT_THRS = (0xff << 16)
122
/* Operational register STATUS bits */
125
GRUB_EHCI_ST_INTERRUPT = (1 << 0),
126
GRUB_EHCI_ST_ERROR_INT = (1 << 1),
127
GRUB_EHCI_ST_PORT_CHG = (1 << 2),
128
GRUB_EHCI_ST_FL_ROLLOVR = (1 << 3),
129
GRUB_EHCI_ST_HS_ERROR = (1 << 4),
130
GRUB_EHCI_ST_AS_ADVANCE = (1 << 5),
131
GRUB_EHCI_ST_HC_HALTED = (1 << 12),
132
GRUB_EHCI_ST_RECLAM = (1 << 13),
133
GRUB_EHCI_ST_PS_STATUS = (1 << 14),
134
GRUB_EHCI_ST_AS_STATUS = (1 << 15)
137
/* Operational register PORT_STAT_CMD bits */
140
GRUB_EHCI_PORT_CONNECT = (1 << 0),
141
GRUB_EHCI_PORT_CONNECT_CH = (1 << 1),
142
GRUB_EHCI_PORT_ENABLED = (1 << 2),
143
GRUB_EHCI_PORT_ENABLED_CH = (1 << 3),
144
GRUB_EHCI_PORT_OVERCUR = (1 << 4),
145
GRUB_EHCI_PORT_OVERCUR_CH = (1 << 5),
146
GRUB_EHCI_PORT_RESUME = (1 << 6),
147
GRUB_EHCI_PORT_SUSPEND = (1 << 7),
148
GRUB_EHCI_PORT_RESET = (1 << 8),
149
GRUB_EHCI_PORT_LINE_STAT = (3 << 10),
150
GRUB_EHCI_PORT_POWER = (1 << 12),
151
GRUB_EHCI_PORT_OWNER = (1 << 13),
152
GRUB_EHCI_PORT_INDICATOR = (3 << 14),
153
GRUB_EHCI_PORT_TEST = (0xf << 16),
154
GRUB_EHCI_PORT_WON_CONN_E = (1 << 20),
155
GRUB_EHCI_PORT_WON_DISC_E = (1 << 21),
156
GRUB_EHCI_PORT_WON_OVER_E = (1 << 22),
158
GRUB_EHCI_PORT_LINE_SE0 = (0 << 10),
159
GRUB_EHCI_PORT_LINE_K = (1 << 10),
160
GRUB_EHCI_PORT_LINE_J = (2 << 10),
161
GRUB_EHCI_PORT_LINE_UNDEF = (3 << 10),
162
GRUB_EHCI_PORT_LINE_LOWSP = GRUB_EHCI_PORT_LINE_K, /* K state means low speed */
163
GRUB_EHCI_PORT_WMASK = ~(GRUB_EHCI_PORT_CONNECT_CH
164
| GRUB_EHCI_PORT_ENABLED_CH
165
| GRUB_EHCI_PORT_OVERCUR_CH)
168
/* Operational register CONFIGFLAGS bits */
171
GRUB_EHCI_CF_EHCI_OWNER = (1 << 0)
174
/* Queue Head & Transfer Descriptor constants */
175
#define GRUB_EHCI_HPTR_OFF 5 /* Horiz. pointer bit offset */
178
GRUB_EHCI_HPTR_TYPE_MASK = (3 << 1),
179
GRUB_EHCI_HPTR_TYPE_ITD = (0 << 1),
180
GRUB_EHCI_HPTR_TYPE_QH = (1 << 1),
181
GRUB_EHCI_HPTR_TYPE_SITD = (2 << 1),
182
GRUB_EHCI_HPTR_TYPE_FSTN = (3 << 1)
187
GRUB_EHCI_C = (1 << 27),
188
GRUB_EHCI_MAXPLEN_MASK = (0x7ff << 16),
189
GRUB_EHCI_H = (1 << 15),
190
GRUB_EHCI_DTC = (1 << 14),
191
GRUB_EHCI_SPEED_MASK = (3 << 12),
192
GRUB_EHCI_SPEED_FULL = (0 << 12),
193
GRUB_EHCI_SPEED_LOW = (1 << 12),
194
GRUB_EHCI_SPEED_HIGH = (2 << 12),
195
GRUB_EHCI_SPEED_RESERVED = (3 << 12),
196
GRUB_EHCI_EP_NUM_MASK = (0xf << 8),
197
GRUB_EHCI_DEVADDR_MASK = 0x7f,
198
GRUB_EHCI_TARGET_MASK = (GRUB_EHCI_EP_NUM_MASK | GRUB_EHCI_DEVADDR_MASK)
203
GRUB_EHCI_MAXPLEN_OFF = 16,
204
GRUB_EHCI_SPEED_OFF = 12,
205
GRUB_EHCI_EP_NUM_OFF = 8
210
GRUB_EHCI_MULT_MASK = (3 << 30),
211
GRUB_EHCI_MULT_RESERVED = (0 << 30),
212
GRUB_EHCI_MULT_ONE = (1 << 30),
213
GRUB_EHCI_MULT_TWO = (2 << 30),
214
GRUB_EHCI_MULT_THREE = (3 << 30),
215
GRUB_EHCI_DEVPORT_MASK = (0x7f << 23),
216
GRUB_EHCI_HUBADDR_MASK = (0x7f << 16),
217
GRUB_EHCI_CMASK_MASK = (0xff << 8),
218
GRUB_EHCI_SMASK_MASK = (0xff << 0),
223
GRUB_EHCI_MULT_OFF = 30,
224
GRUB_EHCI_DEVPORT_OFF = 23,
225
GRUB_EHCI_HUBADDR_OFF = 16,
226
GRUB_EHCI_CMASK_OFF = 8,
227
GRUB_EHCI_SMASK_OFF = 0,
230
#define GRUB_EHCI_TERMINATE (1<<0)
232
#define GRUB_EHCI_TOGGLE (1<<31)
236
GRUB_EHCI_TOTAL_MASK = (0x7fff << 16),
237
GRUB_EHCI_CERR_MASK = (3 << 10),
238
GRUB_EHCI_CERR_0 = (0 << 10),
239
GRUB_EHCI_CERR_1 = (1 << 10),
240
GRUB_EHCI_CERR_2 = (2 << 10),
241
GRUB_EHCI_CERR_3 = (3 << 10),
242
GRUB_EHCI_PIDCODE_OUT = (0 << 8),
243
GRUB_EHCI_PIDCODE_IN = (1 << 8),
244
GRUB_EHCI_PIDCODE_SETUP = (2 << 8),
245
GRUB_EHCI_STATUS_MASK = 0xff,
246
GRUB_EHCI_STATUS_ACTIVE = (1 << 7),
247
GRUB_EHCI_STATUS_HALTED = (1 << 6),
248
GRUB_EHCI_STATUS_BUFERR = (1 << 5),
249
GRUB_EHCI_STATUS_BABBLE = (1 << 4),
250
GRUB_EHCI_STATUS_TRANERR = (1 << 3),
251
GRUB_EHCI_STATUS_MISSDMF = (1 << 2),
252
GRUB_EHCI_STATUS_SPLITST = (1 << 1),
253
GRUB_EHCI_STATUS_PINGERR = (1 << 0)
258
GRUB_EHCI_TOTAL_OFF = 16,
259
GRUB_EHCI_CERR_OFF = 10
262
#define GRUB_EHCI_BUFPTR_MASK (0xfffff<<12)
263
#define GRUB_EHCI_QHTDPTR_MASK 0xffffffe0
265
#define GRUB_EHCI_TD_BUF_PAGES 5
267
#define GRUB_EHCI_BUFPAGELEN 0x1000
268
#define GRUB_EHCI_MAXBUFLEN 0x5000
272
typedef volatile struct grub_ehci_td *grub_ehci_td_t;
273
typedef volatile struct grub_ehci_qh *grub_ehci_qh_t;
275
/* EHCI Isochronous Transfer Descriptor */
276
/* Currently not supported */
278
/* EHCI Split Transaction Isochronous Transfer Descriptor */
279
/* Currently not supported */
281
/* EHCI Queue Element Transfer Descriptor (qTD) */
282
/* Align to 32-byte boundaries */
286
grub_uint32_t next_td; /* Pointer to next qTD */
287
grub_uint32_t alt_next_td; /* Pointer to alternate next qTD */
288
grub_uint32_t token; /* Toggle, Len, Interrupt, Page, Error, PID, Status */
289
grub_uint32_t buffer_page[GRUB_EHCI_TD_BUF_PAGES]; /* Buffer pointer (+ cur. offset in page 0 */
291
grub_uint32_t buffer_page_high[GRUB_EHCI_TD_BUF_PAGES];
292
/* EHCI driver part */
293
grub_uint32_t link_td; /* pointer to next free/chained TD */
295
grub_uint32_t pad[1]; /* padding to some multiple of 32 bytes */
298
/* EHCI Queue Head */
299
/* Align to 32-byte boundaries */
300
/* QH allocation is made in the similar/same way as in OHCI driver,
301
* because unlninking QH from the Asynchronous list is not so
302
* trivial as on UHCI (at least it is time consuming) */
306
grub_uint32_t qh_hptr; /* Horiz. pointer & Terminate */
307
grub_uint32_t ep_char; /* EP characteristics */
308
grub_uint32_t ep_cap; /* EP capabilities */
309
grub_uint32_t td_current; /* current TD link pointer */
310
struct grub_ehci_td td_overlay; /* TD overlay area = 64 bytes */
311
/* EHCI driver part */
312
grub_uint32_t pad[4]; /* padding to some multiple of 32 bytes */
315
/* EHCI Periodic Frame Span Traversal Node */
316
/* Currently not supported */
320
volatile grub_uint32_t *iobase_ehcc; /* Capability registers */
321
volatile grub_uint32_t *iobase; /* Operational registers */
322
struct grub_pci_dma_chunk *framelist_chunk; /* Currently not used */
323
volatile grub_uint32_t *framelist_virt;
324
grub_uint32_t framelist_phys;
325
struct grub_pci_dma_chunk *qh_chunk; /* GRUB_EHCI_N_QH Queue Heads */
326
grub_ehci_qh_t qh_virt;
327
grub_uint32_t qh_phys;
328
struct grub_pci_dma_chunk *td_chunk; /* GRUB_EHCI_N_TD Transfer Descriptors */
329
grub_ehci_td_t td_virt;
330
grub_uint32_t td_phys;
331
grub_ehci_td_t tdfree_virt; /* Free Transfer Descriptors */
333
grub_uint32_t reset; /* bits 1-15 are flags if port was reset from connected time or not */
334
struct grub_ehci *next;
337
static struct grub_ehci *ehci;
339
/* EHCC registers access functions */
340
static inline grub_uint32_t
341
grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
344
grub_le_to_cpu32 (*((volatile grub_uint32_t *) e->iobase_ehcc +
345
(addr / sizeof (grub_uint32_t))));
348
static inline grub_uint16_t
349
grub_ehci_ehcc_read16 (struct grub_ehci *e, grub_uint32_t addr)
352
grub_le_to_cpu16 (*((volatile grub_uint16_t *) e->iobase_ehcc +
353
(addr / sizeof (grub_uint16_t))));
356
static inline grub_uint8_t
357
grub_ehci_ehcc_read8 (struct grub_ehci *e, grub_uint32_t addr)
359
return *((volatile grub_uint8_t *) e->iobase_ehcc + addr);
362
/* Operational registers access functions */
363
static inline grub_uint32_t
364
grub_ehci_oper_read32 (struct grub_ehci *e, grub_uint32_t addr)
368
((volatile grub_uint32_t *) e->iobase +
369
(addr / sizeof (grub_uint32_t))));
373
grub_ehci_oper_write32 (struct grub_ehci *e, grub_uint32_t addr,
376
*((volatile grub_uint32_t *) e->iobase + (addr / sizeof (grub_uint32_t))) =
377
grub_cpu_to_le32 (value);
380
static inline grub_uint32_t
381
grub_ehci_port_read (struct grub_ehci *e, grub_uint32_t port)
383
return grub_ehci_oper_read32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4);
387
grub_ehci_port_resbits (struct grub_ehci *e, grub_uint32_t port,
390
grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4,
391
grub_ehci_port_read (e,
392
port) & GRUB_EHCI_PORT_WMASK &
394
grub_ehci_port_read (e, port);
398
grub_ehci_port_setbits (struct grub_ehci *e, grub_uint32_t port,
401
grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4,
402
(grub_ehci_port_read (e, port) &
403
GRUB_EHCI_PORT_WMASK) | bits);
404
grub_ehci_port_read (e, port);
407
/* Halt if EHCI HC not halted */
408
static grub_usb_err_t
409
grub_ehci_halt (struct grub_ehci *e)
411
grub_uint64_t maxtime;
413
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & GRUB_EHCI_ST_HC_HALTED) == 0) /* EHCI is not halted */
416
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
417
~GRUB_EHCI_CMD_RUNSTOP
418
& grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
419
/* Ensure command is written */
420
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
421
maxtime = grub_get_time_ms () + 1000; /* Fix: Should be 2ms ! */
422
while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
423
& GRUB_EHCI_ST_HC_HALTED) == 0)
424
&& (grub_get_time_ms () < maxtime));
425
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
426
& GRUB_EHCI_ST_HC_HALTED) == 0)
427
return GRUB_USB_ERR_TIMEOUT;
430
return GRUB_USB_ERR_NONE;
434
static grub_usb_err_t
435
grub_ehci_reset (struct grub_ehci *e)
437
grub_uint64_t maxtime;
439
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
440
GRUB_EHCI_CMD_HC_RESET
441
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
442
/* Ensure command is written */
443
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
444
/* XXX: How long time could take reset of HC ? */
445
maxtime = grub_get_time_ms () + 1000;
446
while (((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)
447
& GRUB_EHCI_CMD_HC_RESET) != 0)
448
&& (grub_get_time_ms () < maxtime));
449
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)
450
& GRUB_EHCI_CMD_HC_RESET) != 0)
451
return GRUB_USB_ERR_TIMEOUT;
453
return GRUB_USB_ERR_NONE;
456
/* PCI iteration function... */
457
static int NESTED_FUNC_ATTR
458
grub_ehci_pci_iter (grub_pci_device_t dev,
459
grub_pci_id_t pciid __attribute__ ((unused)))
461
grub_uint8_t release;
462
grub_uint32_t class_code;
463
grub_uint32_t interf;
464
grub_uint32_t subclass;
466
grub_uint32_t base, base_h;
468
grub_uint32_t eecp_offset;
471
grub_uint32_t usblegsup = 0;
472
grub_uint64_t maxtime;
473
grub_uint32_t n_ports;
476
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
478
if (pciid == GRUB_CS5536_PCIID)
480
grub_uint64_t basereg;
482
basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
483
if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
485
/* Shouldn't happen. */
486
grub_dprintf ("ehci", "No EHCI address is assigned\n");
489
base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
490
basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
491
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
492
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
493
basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
494
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
498
grub_pci_address_t addr;
499
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
500
class_code = grub_pci_read (addr) >> 8;
501
interf = class_code & 0xFF;
502
subclass = (class_code >> 8) & 0xFF;
503
class = class_code >> 16;
505
/* If this is not an EHCI controller, just return. */
506
if (class != 0x0c || subclass != 0x03 || interf != 0x20)
509
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
511
/* Check Serial Bus Release Number */
512
addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
513
release = grub_pci_read_byte (addr);
516
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
520
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
522
/* Determine EHCI EHCC registers base address. */
523
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
524
base = grub_pci_read (addr);
525
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
526
base_h = grub_pci_read (addr);
527
/* Stop if registers are mapped above 4G - GRUB does not currently
528
* work with registers mapped above 4G */
529
if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
532
grub_dprintf ("ehci",
533
"EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
537
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
540
/* Allocate memory for the controller and fill basic values. */
541
e = grub_zalloc (sizeof (*e));
544
e->framelist_chunk = NULL;
547
e->iobase_ehcc = grub_pci_device_map_range (dev,
548
(base & GRUB_EHCI_ADDR_MEM_MASK),
551
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
552
(base & GRUB_EHCI_ADDR_MEM_MASK));
553
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n",
554
grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
555
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n",
556
grub_ehci_ehcc_read16 (e, GRUB_EHCI_EHCC_VERSION));
557
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: SPARAMS: %08x\n",
558
grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS));
559
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CPARAMS: %08x\n",
560
grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS));
562
/* Determine base address of EHCI operational registers */
563
caplen = grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN);
564
#ifndef GRUB_HAVE_UNALIGNED_ACCESS
565
if (caplen & (sizeof (grub_uint32_t) - 1))
567
grub_dprintf ("ehci", "Unaligned caplen\n");
570
e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
571
+ (caplen / sizeof (grub_uint32_t)));
573
e->iobase = (volatile grub_uint32_t *)
574
((grub_uint8_t *) e->iobase_ehcc + caplen);
577
grub_dprintf ("ehci",
578
"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
579
(base & GRUB_EHCI_ADDR_MEM_MASK) + caplen);
580
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
581
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
582
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
583
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
584
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n",
585
grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT));
586
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n",
587
grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX));
588
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n",
589
grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE));
590
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n",
591
grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR));
592
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
593
grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
595
/* Is there EECP ? */
596
eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
597
& GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT;
599
/* Check format of data structures requested by EHCI */
600
/* XXX: In fact it is not used at any place, it is prepared for future
601
* This implementation uses 32-bits pointers only */
602
e->flag64 = ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
603
& GRUB_EHCI_CPARAMS_64BIT) != 0);
605
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: flag64=%d\n", e->flag64);
607
/* Reserve a page for the frame list - it is accurate for max.
608
* possible size of framelist. But currently it is not used. */
609
e->framelist_chunk = grub_memalign_dma32 (4096, 4096);
610
if (!e->framelist_chunk)
612
e->framelist_virt = grub_dma_get_virt (e->framelist_chunk);
613
e->framelist_phys = grub_dma_get_phys (e->framelist_chunk);
614
grub_memset ((void *) e->framelist_virt, 0, 4096);
616
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: framelist mem=%p. OK\n",
619
/* Allocate memory for the QHs and register it in "e". */
620
e->qh_chunk = grub_memalign_dma32 (4096,
621
sizeof (struct grub_ehci_qh) *
625
e->qh_virt = (grub_ehci_qh_t) grub_dma_get_virt (e->qh_chunk);
626
e->qh_phys = grub_dma_get_phys (e->qh_chunk);
627
grub_memset ((void *) e->qh_virt, 0,
628
sizeof (struct grub_ehci_qh) * GRUB_EHCI_N_QH);
630
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH mem=%p. OK\n",
633
/* Allocate memory for the TDs and register it in "e". */
634
e->td_chunk = grub_memalign_dma32 (4096,
635
sizeof (struct grub_ehci_td) *
639
e->td_virt = (grub_ehci_td_t) grub_dma_get_virt (e->td_chunk);
640
e->td_phys = grub_dma_get_phys (e->td_chunk);
641
grub_memset ((void *) e->td_virt, 0,
642
sizeof (struct grub_ehci_td) * GRUB_EHCI_N_TD);
644
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: TD mem=%p. OK\n",
647
/* Setup all frame list pointers. Since no isochronous transfers
648
are supported, they all point to the (same!) queue
649
head with index 0. */
650
fp = grub_cpu_to_le32 ((e->qh_phys & GRUB_EHCI_POINTER_MASK)
651
| GRUB_EHCI_HPTR_TYPE_QH);
652
for (i = 0; i < GRUB_EHCI_N_FRAMELIST; i++)
653
e->framelist_virt[i] = fp;
654
/* Prepare chain of all TDs and set Terminate in all TDs */
655
for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++)
657
e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td);
658
e->td_virt[i].next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
659
e->td_virt[i].alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
661
e->td_virt[GRUB_EHCI_N_TD - 1].next_td =
662
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
663
e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td =
664
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
665
e->tdfree_virt = e->td_virt;
666
/* Set Terminate in first QH, which is used in framelist */
667
e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
668
e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
669
e->qh_virt[0].td_overlay.alt_next_td =
670
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
671
/* Also set Halted bit in token */
672
e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
673
/* Set the H bit in first QH used for AL */
674
e->qh_virt[1].ep_char = grub_cpu_to_le32 (GRUB_EHCI_H);
675
/* Set Terminate into TD in rest of QHs and set horizontal link
676
* pointer to itself - these QHs will be used for asynchronous
677
* schedule and they should have valid value in horiz. link */
678
for (i = 1; i < GRUB_EHCI_N_QH; i++)
680
e->qh_virt[i].qh_hptr =
681
grub_cpu_to_le32 ((grub_dma_virt2phys (&e->qh_virt[i],
683
GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
684
e->qh_virt[i].td_overlay.next_td =
685
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
686
e->qh_virt[i].td_overlay.alt_next_td =
687
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
688
/* Also set Halted bit in token */
689
e->qh_virt[i].td_overlay.token =
690
grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
693
/* Note: QH 0 and QH 1 are reserved and must not be used anywhere.
694
* QH 0 is used as empty QH for framelist
695
* QH 1 is used as starting empty QH for asynchronous schedule
696
* QH 1 must exist at any time because at least one QH linked to
697
* itself must exist in asynchronous schedule
698
* QH 1 has the H flag set to one */
700
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n");
702
/* Determine and change ownership. */
703
/* EECP offset valid in HCCPARAMS */
704
/* Ownership can be changed via EECP only */
705
if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
707
grub_pci_address_t pciaddr_eecp;
708
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
710
usblegsup = grub_pci_read (pciaddr_eecp);
711
if (usblegsup & GRUB_EHCI_BIOS_OWNED)
713
grub_dprintf ("ehci",
714
"EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
715
/* Ownership change - set OS_OWNED bit */
716
grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
717
/* Ensure PCI register is written */
718
grub_pci_read (pciaddr_eecp);
720
/* Wait for finish of ownership change, EHCI specification
721
* doesn't say how long it can take... */
722
maxtime = grub_get_time_ms () + 1000;
723
while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
724
&& (grub_get_time_ms () < maxtime));
725
if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
727
grub_dprintf ("ehci",
728
"EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
729
/* Change ownership in "hard way" - reset BIOS ownership */
730
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
731
/* Ensure PCI register is written */
732
grub_pci_read (pciaddr_eecp);
734
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
735
grub_pci_write (pciaddr_eecp, 0);
736
/* Ensure PCI register is written */
737
grub_pci_read (pciaddr_eecp);
740
else if (usblegsup & GRUB_EHCI_OS_OWNED)
741
/* XXX: What to do in this case - nothing ? Can it happen ? */
742
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
745
grub_dprintf ("ehci",
746
"EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
747
/* XXX: What to do in this case ? Can it happen ?
748
* Is code below correct ? */
749
/* Ownership change - set OS_OWNED bit */
750
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
751
/* Ensure PCI register is written */
752
grub_pci_read (pciaddr_eecp);
753
/* Disable SMI, just to be sure. */
754
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
755
grub_pci_write (pciaddr_eecp, 0);
756
/* Ensure PCI register is written */
757
grub_pci_read (pciaddr_eecp);
761
grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
763
/* Now we can setup EHCI (maybe...) */
765
/* Check if EHCI is halted and halt it if not */
766
if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
768
grub_error (GRUB_ERR_TIMEOUT,
769
"EHCI grub_ehci_pci_iter: EHCI halt timeout");
773
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: halted OK\n");
776
if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
778
grub_error (GRUB_ERR_TIMEOUT,
779
"EHCI grub_ehci_pci_iter: EHCI reset timeout");
783
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: reset OK\n");
785
/* Setup list address registers */
786
grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys);
787
grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR,
788
grub_dma_virt2phys (&e->qh_virt[1],
791
/* Set ownership of root hub ports to EHCI */
792
grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG, GRUB_EHCI_CF_EHCI_OWNER);
794
/* Enable asynchronous list */
795
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
796
GRUB_EHCI_CMD_AS_ENABL
797
| GRUB_EHCI_CMD_PS_ENABL
798
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
800
/* Now should be possible to power-up and enumerate ports etc. */
801
if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
802
& GRUB_EHCI_SPARAMS_PPC) != 0)
803
{ /* EHCI has port powering control */
804
/* Power on all ports */
805
n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
806
& GRUB_EHCI_SPARAMS_N_PORTS;
807
for (i = 0; i < (int) n_ports; i++)
808
grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4,
810
| grub_ehci_oper_read32 (e,
811
GRUB_EHCI_PORT_STAT_CMD
815
/* Ensure all commands are written */
816
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
819
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
820
GRUB_EHCI_CMD_RUNSTOP
821
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
823
/* Ensure command is written */
824
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
826
/* Link to ehci now that initialisation is successful. */
830
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
832
grub_dprintf ("ehci",
833
"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
834
(base & GRUB_EHCI_ADDR_MEM_MASK));
835
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
836
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
837
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
838
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
839
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n",
840
grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT));
841
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n",
842
grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX));
843
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n",
844
grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE));
845
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n",
846
grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR));
847
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
848
grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
856
grub_dma_free ((void *) e->td_chunk);
858
grub_dma_free ((void *) e->qh_chunk);
859
if (e->framelist_chunk)
860
grub_dma_free (e->framelist_chunk);
868
grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev))
871
struct grub_usb_controller dev;
873
for (e = ehci; e; e = e->next)
884
grub_ehci_setup_qh (grub_ehci_qh_t qh, grub_usb_transfer_t transfer)
886
grub_uint32_t ep_char = 0;
887
grub_uint32_t ep_cap = 0;
889
/* Note: Another part of code is responsible to this QH is
890
* Halted ! But it can be linked in AL, so we cannot erase or
891
* change qh_hptr ! */
892
/* We will not change any TD field because they should/must be
893
* in safe state from previous use. */
895
/* EP characteristic setup */
896
/* Currently not used NAK counter (RL=0),
897
* C bit set if EP is not HIGH speed and is control,
898
* Max Packet Length is taken from transfer structure,
899
* H bit = 0 (because QH[1] has this bit set),
900
* DTC bit set to 1 because we are using our own toggle bit control,
901
* SPEED is selected according to value from transfer structure,
902
* EP number is taken from transfer structure
903
* "I" bit must not be set,
904
* Device Address is taken from transfer structure
906
if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH)
907
&& (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL))
908
ep_char |= GRUB_EHCI_C;
909
ep_char |= (transfer->max << GRUB_EHCI_MAXPLEN_OFF)
910
& GRUB_EHCI_MAXPLEN_MASK;
911
ep_char |= GRUB_EHCI_DTC;
912
switch (transfer->dev->speed)
914
case GRUB_USB_SPEED_LOW:
915
ep_char |= GRUB_EHCI_SPEED_LOW;
917
case GRUB_USB_SPEED_FULL:
918
ep_char |= GRUB_EHCI_SPEED_FULL;
920
case GRUB_USB_SPEED_HIGH:
922
ep_char |= GRUB_EHCI_SPEED_HIGH;
923
/* XXX: How we will handle unknown value of speed? */
925
ep_char |= (transfer->endpoint << GRUB_EHCI_EP_NUM_OFF)
926
& GRUB_EHCI_EP_NUM_MASK;
927
ep_char |= transfer->devaddr & GRUB_EHCI_DEVADDR_MASK;
928
qh->ep_char = grub_cpu_to_le32 (ep_char);
929
/* EP capabilities setup */
930
/* MULT field - we try to use max. number
931
* PortNumber - included now in device structure referenced
932
* inside transfer structure
933
* HubAddress - included now in device structure referenced
934
* inside transfer structure
935
* SplitCompletionMask - AFAIK it is ignored in asynchronous list,
936
* InterruptScheduleMask - AFAIK it should be zero in async. list */
937
ep_cap |= GRUB_EHCI_MULT_THREE;
938
ep_cap |= (transfer->dev->port << GRUB_EHCI_DEVPORT_OFF)
939
& GRUB_EHCI_DEVPORT_MASK;
940
ep_cap |= (transfer->dev->hubaddr << GRUB_EHCI_HUBADDR_OFF)
941
& GRUB_EHCI_HUBADDR_MASK;
942
if (transfer->dev->speed == GRUB_USB_SPEED_LOW
943
&& transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL)
945
ep_cap |= (1<<0) << GRUB_EHCI_SMASK_OFF;
946
ep_cap |= (7<<2) << GRUB_EHCI_CMASK_OFF;
948
qh->ep_cap = grub_cpu_to_le32 (ep_cap);
950
grub_dprintf ("ehci", "setup_qh: qh=%p, not changed: qh_hptr=%08x\n",
951
qh, grub_le_to_cpu32 (qh->qh_hptr));
952
grub_dprintf ("ehci", "setup_qh: ep_char=%08x, ep_cap=%08x\n",
954
grub_dprintf ("ehci", "setup_qh: end\n");
955
grub_dprintf ("ehci", "setup_qh: not changed: td_current=%08x\n",
956
grub_le_to_cpu32 (qh->td_current));
957
grub_dprintf ("ehci", "setup_qh: not changed: next_td=%08x\n",
958
grub_le_to_cpu32 (qh->td_overlay.next_td));
959
grub_dprintf ("ehci", "setup_qh: not changed: alt_next_td=%08x\n",
960
grub_le_to_cpu32 (qh->td_overlay.alt_next_td));
961
grub_dprintf ("ehci", "setup_qh: not changed: token=%08x\n",
962
grub_le_to_cpu32 (qh->td_overlay.token));
965
static grub_ehci_qh_t
966
grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
968
grub_uint32_t target, mask;
970
grub_ehci_qh_t qh = e->qh_virt;
973
/* Prepare part of EP Characteristic to find existing QH */
974
target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) |
975
transfer->devaddr) & GRUB_EHCI_TARGET_MASK;
976
target = grub_cpu_to_le32 (target);
977
mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK);
979
/* First try to find existing QH with proper target */
980
for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */
983
break; /* Found first not-allocated QH, finish */
984
if (target == (qh[i].ep_char & mask))
986
/* Found proper existing (and linked) QH, do setup of QH */
987
grub_dprintf ("ehci", "find_qh: found, i=%d, QH=%p\n",
989
grub_ehci_setup_qh (&qh[i], transfer);
993
/* QH with target_addr does not exist, we have to add it */
994
/* Have we any free QH in array ? */
995
if (i >= GRUB_EHCI_N_QH) /* No. */
997
grub_dprintf ("ehci", "find_qh: end - no free QH\n");
1000
grub_dprintf ("ehci", "find_qh: new, i=%d, QH=%p\n",
1002
/* Currently we simply take next (current) QH in array, no allocation
1003
* function is used. It should be no problem until we will need to
1004
* de-allocate QHs of unplugged devices. */
1005
/* We should preset new QH and link it into AL */
1006
grub_ehci_setup_qh (&qh[i], transfer);
1008
/* low speed interrupt transfers are linked to the periodic
1009
* scheudle, everything else to the asynchronous schedule */
1010
if (transfer->dev->speed == GRUB_USB_SPEED_LOW
1011
&& transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL)
1016
/* Linking - this new (last) QH will copy the QH from the head QH */
1017
qh[i].qh_hptr = head->qh_hptr;
1018
/* Linking - the head QH will point to this new QH */
1019
head->qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_HPTR_TYPE_QH
1020
| grub_dma_virt2phys (&qh[i],
1026
static grub_ehci_td_t
1027
grub_ehci_alloc_td (struct grub_ehci *e)
1031
/* Check if there is a Transfer Descriptor available. */
1032
if (!e->tdfree_virt)
1034
grub_dprintf ("ehci", "alloc_td: end - no free TD\n");
1038
ret = e->tdfree_virt; /* Take current free TD */
1039
/* Advance to next free TD in chain */
1041
e->tdfree_virt = grub_dma_phys2virt (ret->link_td, e->td_chunk);
1043
e->tdfree_virt = NULL;
1044
ret->link_td = 0; /* Reset link_td in allocated TD */
1049
grub_ehci_free_td (struct grub_ehci *e, grub_ehci_td_t td)
1051
/* Chain new free TD & rest */
1053
td->link_td = grub_dma_virt2phys (e->tdfree_virt, e->td_chunk);
1056
e->tdfree_virt = td; /* Change address of first free TD */
1060
grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td,
1061
grub_usb_transfer_t transfer, grub_size_t * actual)
1063
int i; /* Index of TD in transfer */
1064
grub_uint32_t token, to_transfer;
1066
/* Note: Another part of code is responsible to this QH is
1070
/* Free the TDs in this queue and set last_trans. */
1071
for (i = 0; td; i++)
1073
grub_ehci_td_t tdprev;
1075
token = grub_le_to_cpu32 (td->token);
1076
to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF;
1078
/* Check state of TD - if it did not transfered
1079
* whole data then set last_trans - it should be last executed TD
1080
* in case when something went wrong. */
1081
if (transfer && (td->size != to_transfer))
1082
transfer->last_trans = i;
1084
*actual += td->size - to_transfer;
1089
td = grub_dma_phys2virt (td->link_td, e->td_chunk);
1094
grub_ehci_free_td (e, tdprev);
1097
/* Check if last_trans was set. If not and something was
1098
* transferred (it should be all data in this case), set it
1099
* to index of last TD, i.e. i-1 */
1100
if (transfer && (transfer->last_trans < 0) && (*actual != 0))
1101
transfer->last_trans = i - 1;
1103
/* XXX: Fix it: last_trans may be set to bad index.
1104
* Probably we should test more error flags to distinguish
1105
* if TD was at least partialy executed or not at all.
1106
* Generaly, we still could have problem with toggling because
1107
* EHCI can probably split transactions into smaller parts then
1108
* we defined in transaction even if we did not exceed MaxFrame
1109
* length - it probably could happen at the end of microframe (?)
1110
* and if the buffer is crossing page boundary (?). */
1113
static grub_ehci_td_t
1114
grub_ehci_transaction (struct grub_ehci *e,
1115
grub_transfer_type_t type,
1116
unsigned int toggle, grub_size_t size,
1117
grub_uint32_t data, grub_ehci_td_t td_alt)
1120
grub_uint32_t token;
1121
grub_uint32_t bufadr;
1124
/* Test of transfer size, it can be:
1125
* <= GRUB_EHCI_MAXBUFLEN if data aligned to page boundary
1126
* <= GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN if not aligned
1129
if ((((data % GRUB_EHCI_BUFPAGELEN) == 0)
1130
&& (size > GRUB_EHCI_MAXBUFLEN))
1132
(((data % GRUB_EHCI_BUFPAGELEN) != 0)
1133
&& (size > (GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN))))
1135
grub_error (GRUB_ERR_OUT_OF_MEMORY,
1136
"too long data buffer for EHCI transaction");
1140
/* Grab a free Transfer Descriptor and initialize it. */
1141
td = grub_ehci_alloc_td (e);
1144
grub_error (GRUB_ERR_OUT_OF_MEMORY,
1145
"no transfer descriptors available for EHCI transfer");
1149
grub_dprintf ("ehci",
1150
"transaction: type=%d, toggle=%d, size=%lu data=0x%x td=%p\n",
1151
type, toggle, (unsigned long) size, data, td);
1153
/* Fill whole TD by zeros */
1154
grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td));
1156
/* Don't point to any TD yet, just terminate. */
1157
td->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1158
/* Set alternate pointer. When short packet occurs, alternate TD
1159
* will not be really fetched because it is not active. But don't
1160
* forget, EHCI will try to fetch alternate TD every scan of AL
1161
* until QH is halted. */
1162
td->alt_next_td = grub_cpu_to_le32 (grub_dma_virt2phys (td_alt,
1165
* TOGGLE - according to toggle
1167
* Interrupt On Complete = FALSE, we don't need IRQ
1169
* Error Counter = max. value = 3
1170
* PID Code - according to type
1172
* ACTIVE bit should be set to one
1173
* SPLIT TRANS. STATE bit should be zero. It is ignored
1174
* in HIGH speed transaction, and should be zero for LOW/FULL
1175
* speed to indicate state Do Split Transaction */
1176
token = toggle ? GRUB_EHCI_TOGGLE : 0;
1177
token |= (size << GRUB_EHCI_TOTAL_OFF) & GRUB_EHCI_TOTAL_MASK;
1178
token |= GRUB_EHCI_CERR_3;
1181
case GRUB_USB_TRANSFER_TYPE_IN:
1182
token |= GRUB_EHCI_PIDCODE_IN;
1184
case GRUB_USB_TRANSFER_TYPE_OUT:
1185
token |= GRUB_EHCI_PIDCODE_OUT;
1187
case GRUB_USB_TRANSFER_TYPE_SETUP:
1188
token |= GRUB_EHCI_PIDCODE_SETUP;
1190
default: /* XXX: Should not happen, but what to do if it does ? */
1193
token |= GRUB_EHCI_STATUS_ACTIVE;
1194
td->token = grub_cpu_to_le32 (token);
1196
/* Fill buffer pointers according to size */
1198
td->buffer_page[0] = grub_cpu_to_le32 (bufadr);
1199
bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN;
1200
for (i = 1; ((bufadr - data) < size) && (i < GRUB_EHCI_TD_BUF_PAGES); i++)
1202
td->buffer_page[i] = grub_cpu_to_le32 (bufadr & GRUB_EHCI_BUFPTR_MASK);
1203
bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN;
1206
/* Remember data size for future use... */
1207
td->size = (grub_uint32_t) size;
1209
grub_dprintf ("ehci", "td=%p\n", td);
1210
grub_dprintf ("ehci", "HW: next_td=%08x, alt_next_td=%08x\n",
1211
grub_le_to_cpu32 (td->next_td),
1212
grub_le_to_cpu32 (td->alt_next_td));
1213
grub_dprintf ("ehci", "HW: token=%08x, buffer[0]=%08x\n",
1214
grub_le_to_cpu32 (td->token),
1215
grub_le_to_cpu32 (td->buffer_page[0]));
1216
grub_dprintf ("ehci", "HW: buffer[1]=%08x, buffer[2]=%08x\n",
1217
grub_le_to_cpu32 (td->buffer_page[1]),
1218
grub_le_to_cpu32 (td->buffer_page[2]));
1219
grub_dprintf ("ehci", "HW: buffer[3]=%08x, buffer[4]=%08x\n",
1220
grub_le_to_cpu32 (td->buffer_page[3]),
1221
grub_le_to_cpu32 (td->buffer_page[4]));
1222
grub_dprintf ("ehci", "link_td=%08x, size=%08x\n",
1223
td->link_td, td->size);
1228
struct grub_ehci_transfer_controller_data
1230
grub_ehci_qh_t qh_virt;
1231
grub_ehci_td_t td_first_virt;
1232
grub_ehci_td_t td_alt_virt;
1233
grub_ehci_td_t td_last_virt;
1234
grub_uint32_t td_last_phys;
1237
static grub_usb_err_t
1238
grub_ehci_setup_transfer (grub_usb_controller_t dev,
1239
grub_usb_transfer_t transfer)
1241
struct grub_ehci *e = (struct grub_ehci *) dev->data;
1242
grub_ehci_td_t td = NULL;
1243
grub_ehci_td_t td_prev = NULL;
1245
struct grub_ehci_transfer_controller_data *cdata;
1247
/* Check if EHCI is running and AL is enabled */
1248
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1249
& GRUB_EHCI_ST_HC_HALTED) != 0)
1250
/* XXX: Fix it: Currently we don't do anything to restart EHCI */
1251
return GRUB_USB_ERR_INTERNAL;
1252
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1253
& (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
1254
/* XXX: Fix it: Currently we don't do anything to restart EHCI */
1255
return GRUB_USB_ERR_INTERNAL;
1257
/* Check if transfer is not high speed and connected to root hub.
1258
* It should not happened but... */
1259
if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH)
1260
&& !transfer->dev->hubaddr)
1262
grub_error (GRUB_USB_ERR_BADDEVICE,
1263
"FULL/LOW speed device on EHCI port!?!");
1264
return GRUB_USB_ERR_BADDEVICE;
1267
/* Allocate memory for controller transfer data. */
1268
cdata = grub_malloc (sizeof (*cdata));
1270
return GRUB_USB_ERR_INTERNAL;
1271
cdata->td_first_virt = NULL;
1273
/* Allocate a queue head for the transfer queue. */
1274
cdata->qh_virt = grub_ehci_find_qh (e, transfer);
1275
if (!cdata->qh_virt)
1278
return GRUB_USB_ERR_INTERNAL;
1281
/* To detect short packet we need some additional "alternate" TD,
1282
* allocate it first. */
1283
cdata->td_alt_virt = grub_ehci_alloc_td (e);
1284
if (!cdata->td_alt_virt)
1287
return GRUB_USB_ERR_INTERNAL;
1289
/* Fill whole alternate TD by zeros (= inactive) and set
1290
* Terminate bits and Halt bit */
1291
grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td));
1292
cdata->td_alt_virt->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1293
cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1294
cdata->td_alt_virt->token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
1296
/* Allocate appropriate number of TDs and set */
1297
for (i = 0; i < transfer->transcnt; i++)
1299
grub_usb_transaction_t tr = &transfer->transactions[i];
1301
td = grub_ehci_transaction (e, tr->pid, tr->toggle, tr->size,
1302
tr->data, cdata->td_alt_virt);
1304
if (!td) /* de-allocate and free all */
1306
grub_size_t actual = 0;
1308
if (cdata->td_first_virt)
1309
grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual);
1312
return GRUB_USB_ERR_INTERNAL;
1315
/* Register new TD in cdata or previous TD */
1316
if (!cdata->td_first_virt)
1317
cdata->td_first_virt = td;
1320
td_prev->link_td = grub_dma_virt2phys (td, e->td_chunk);
1322
grub_cpu_to_le32 (grub_dma_virt2phys (td, e->td_chunk));
1327
/* Remember last TD */
1328
cdata->td_last_virt = td;
1329
cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk);
1330
/* Last TD should not have set alternate TD */
1331
cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1333
grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n",
1334
cdata,cdata->qh_virt);
1335
grub_dprintf ("ehci", "setup_transfer: td_first=%p, td_alt=%p\n",
1336
cdata->td_first_virt,
1337
cdata->td_alt_virt);
1338
grub_dprintf ("ehci", "setup_transfer: td_last=%p\n",
1339
cdata->td_last_virt);
1341
/* Start transfer: */
1342
/* Unlink possible alternate pointer in QH */
1343
cdata->qh_virt->td_overlay.alt_next_td =
1344
grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1345
/* Link new TDs with QH via next_td */
1346
cdata->qh_virt->td_overlay.next_td =
1347
grub_cpu_to_le32 (grub_dma_virt2phys
1348
(cdata->td_first_virt, e->td_chunk));
1349
/* Reset Active and Halted bits in QH to activate Advance Queue,
1350
* i.e. reset token */
1351
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0);
1354
transfer->controller_data = cdata;
1356
return GRUB_USB_ERR_NONE;
1359
/* This function expects QH is not active.
1360
* Function set Halt bit in QH TD overlay and possibly prints
1361
* necessary debug information. */
1363
grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer)
1365
struct grub_ehci_transfer_controller_data *cdata =
1366
transfer->controller_data;
1368
/* Collect debug data here if necessary */
1370
/* Set Halt bit in not active QH. AL will not attempt to do
1371
* Advance Queue on QH with Halt bit set, i.e., we can then
1372
* safely manipulate with QH TD part. */
1373
cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token
1376
(GRUB_EHCI_STATUS_HALTED)) &
1377
grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE);
1379
/* Print debug data here if necessary */
1383
static grub_usb_err_t
1384
grub_ehci_parse_notrun (grub_usb_controller_t dev,
1385
grub_usb_transfer_t transfer, grub_size_t * actual)
1387
struct grub_ehci *e = dev->data;
1388
struct grub_ehci_transfer_controller_data *cdata =
1389
transfer->controller_data;
1391
grub_dprintf ("ehci", "parse_notrun: info\n");
1393
/* QH can be in any state in this case. */
1394
/* But EHCI or AL is not running, so QH is surely not active
1395
* even if it has Active bit set... */
1396
grub_ehci_pre_finish_transfer (transfer);
1397
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1398
grub_ehci_free_td (e, cdata->td_alt_virt);
1401
/* Additionally, do something with EHCI to make it running (what?) */
1402
/* Try enable EHCI and AL */
1403
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1404
GRUB_EHCI_CMD_RUNSTOP | GRUB_EHCI_CMD_AS_ENABL
1405
| GRUB_EHCI_CMD_PS_ENABL
1406
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1407
/* Ensure command is written */
1408
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
1410
return GRUB_USB_ERR_UNRECOVERABLE;
1413
static grub_usb_err_t
1414
grub_ehci_parse_halt (grub_usb_controller_t dev,
1415
grub_usb_transfer_t transfer, grub_size_t * actual)
1417
struct grub_ehci *e = dev->data;
1418
struct grub_ehci_transfer_controller_data *cdata =
1419
transfer->controller_data;
1420
grub_uint32_t token;
1421
grub_usb_err_t err = GRUB_USB_ERR_NAK;
1423
/* QH should be halted and not active in this case. */
1425
grub_dprintf ("ehci", "parse_halt: info\n");
1427
/* Remember token before call pre-finish function */
1428
token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token);
1430
/* Do things like in normal finish */
1431
grub_ehci_pre_finish_transfer (transfer);
1432
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1433
grub_ehci_free_td (e, cdata->td_alt_virt);
1436
/* Evaluation of error code - currently we don't have GRUB USB error
1437
* codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
1438
* Order of evaluation is critical, specially bubble/stall. */
1439
if ((token & GRUB_EHCI_STATUS_BABBLE) != 0)
1440
err = GRUB_USB_ERR_BABBLE;
1441
else if ((token & GRUB_EHCI_CERR_MASK) != 0)
1442
err = GRUB_USB_ERR_STALL;
1443
else if ((token & GRUB_EHCI_STATUS_TRANERR) != 0)
1444
err = GRUB_USB_ERR_DATA;
1445
else if ((token & GRUB_EHCI_STATUS_BUFERR) != 0)
1446
err = GRUB_USB_ERR_DATA;
1447
else if ((token & GRUB_EHCI_STATUS_MISSDMF) != 0)
1448
err = GRUB_USB_ERR_DATA;
1453
static grub_usb_err_t
1454
grub_ehci_parse_success (grub_usb_controller_t dev,
1455
grub_usb_transfer_t transfer, grub_size_t * actual)
1457
struct grub_ehci *e = dev->data;
1458
struct grub_ehci_transfer_controller_data *cdata =
1459
transfer->controller_data;
1461
grub_dprintf ("ehci", "parse_success: info\n");
1463
/* QH should be not active in this case, but it is not halted. */
1464
grub_ehci_pre_finish_transfer (transfer);
1465
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1466
grub_ehci_free_td (e, cdata->td_alt_virt);
1469
return GRUB_USB_ERR_NONE;
1473
static grub_usb_err_t
1474
grub_ehci_check_transfer (grub_usb_controller_t dev,
1475
grub_usb_transfer_t transfer, grub_size_t * actual)
1477
struct grub_ehci *e = dev->data;
1478
struct grub_ehci_transfer_controller_data *cdata =
1479
transfer->controller_data;
1480
grub_uint32_t token;
1482
grub_dprintf ("ehci",
1483
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
1484
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
1485
cdata, cdata->qh_virt);
1486
grub_dprintf ("ehci", "check_transfer: qh_hptr=%08x, ep_char=%08x\n",
1487
grub_le_to_cpu32 (cdata->qh_virt->qh_hptr),
1488
grub_le_to_cpu32 (cdata->qh_virt->ep_char));
1489
grub_dprintf ("ehci", "check_transfer: ep_cap=%08x, td_current=%08x\n",
1490
grub_le_to_cpu32 (cdata->qh_virt->ep_cap),
1491
grub_le_to_cpu32 (cdata->qh_virt->td_current));
1492
grub_dprintf ("ehci", "check_transfer: next_td=%08x, alt_next_td=%08x\n",
1493
grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td),
1494
grub_le_to_cpu32 (cdata->qh_virt->td_overlay.alt_next_td));
1495
grub_dprintf ("ehci", "check_transfer: token=%08x, buffer[0]=%08x\n",
1496
grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token),
1497
grub_le_to_cpu32 (cdata->qh_virt->td_overlay.buffer_page[0]));
1499
/* Check if EHCI is running and AL is enabled */
1500
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1501
& GRUB_EHCI_ST_HC_HALTED) != 0)
1502
return grub_ehci_parse_notrun (dev, transfer, actual);
1503
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1504
& (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
1505
return grub_ehci_parse_notrun (dev, transfer, actual);
1507
token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token);
1509
/* Detect QH halted */
1510
if ((token & GRUB_EHCI_STATUS_HALTED) != 0)
1511
return grub_ehci_parse_halt (dev, transfer, actual);
1513
/* Detect QH not active - QH is not active and no next TD */
1514
if ((token & GRUB_EHCI_STATUS_ACTIVE) == 0)
1516
/* It could be finish at all or short packet condition */
1517
if ((grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td)
1518
& GRUB_EHCI_TERMINATE) &&
1519
((grub_le_to_cpu32 (cdata->qh_virt->td_current)
1520
& GRUB_EHCI_QHTDPTR_MASK) == cdata->td_last_phys))
1522
return grub_ehci_parse_success (dev, transfer, actual);
1523
else if ((token & GRUB_EHCI_TOTAL_MASK) != 0)
1524
/* Short packet condition */
1525
/* But currently we don't handle it - higher level will do it */
1526
return grub_ehci_parse_success (dev, transfer, actual);
1529
return GRUB_USB_ERR_WAIT;
1532
static grub_usb_err_t
1533
grub_ehci_cancel_transfer (grub_usb_controller_t dev,
1534
grub_usb_transfer_t transfer)
1536
struct grub_ehci *e = dev->data;
1537
struct grub_ehci_transfer_controller_data *cdata =
1538
transfer->controller_data;
1541
grub_uint64_t maxtime;
1542
grub_uint32_t qh_phys;
1544
/* QH can be active and should be de-activated and halted */
1546
grub_dprintf ("ehci", "cancel_transfer: begin\n");
1548
/* First check if EHCI is running and AL is enabled and if not,
1549
* there is no problem... */
1550
if (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1551
& GRUB_EHCI_ST_HC_HALTED) != 0) ||
1552
((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1553
& (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0))
1555
grub_ehci_pre_finish_transfer (transfer);
1556
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
1557
grub_ehci_free_td (e, cdata->td_alt_virt);
1559
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
1560
return GRUB_USB_ERR_NONE;
1563
/* EHCI and AL are running. What to do?
1564
* Try to Halt QH via de-scheduling QH. */
1565
/* Find index of previous QH */
1566
qh_phys = grub_dma_virt2phys(cdata->qh_virt, e->qh_chunk);
1567
for (i = 0; i < GRUB_EHCI_N_QH; i++)
1569
if ((e->qh_virt[i].qh_hptr & GRUB_EHCI_QHTDPTR_MASK) == qh_phys)
1572
if (i == GRUB_EHCI_N_QH)
1574
grub_printf ("%s: prev not found, queues are corrupt\n", __func__);
1575
return GRUB_USB_ERR_UNRECOVERABLE;
1577
/* Unlink QH from AL */
1578
e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
1580
/* If this is an interrupt transfer, we just wait for the periodic
1581
* schedule to advance a few times and then assume that the EHCI
1582
* controller has read the updated QH. */
1583
if (cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK)
1585
grub_millisleep(20);
1589
/* For the asynchronous schedule we use the advance doorbell to find
1590
* out when the EHCI controller has read the updated QH. */
1592
/* Ring the doorbell */
1593
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1594
GRUB_EHCI_CMD_AS_ADV_D
1595
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1596
/* Ensure command is written */
1597
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
1598
/* Wait answer with timeout */
1599
maxtime = grub_get_time_ms () + 2;
1600
while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1601
& GRUB_EHCI_ST_AS_ADVANCE) == 0)
1602
&& (grub_get_time_ms () < maxtime));
1604
/* We do not detect the timeout because if timeout occurs, it most
1605
* probably means something wrong with EHCI - maybe stopped etc. */
1607
/* Shut up the doorbell */
1608
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1609
~GRUB_EHCI_CMD_AS_ADV_D
1610
& grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1611
grub_ehci_oper_write32 (e, GRUB_EHCI_STATUS,
1612
GRUB_EHCI_ST_AS_ADVANCE
1613
| grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1614
/* Ensure command is written */
1615
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
1618
/* Now is QH out of AL and we can do anything with it... */
1619
grub_ehci_pre_finish_transfer (transfer);
1620
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
1621
grub_ehci_free_td (e, cdata->td_alt_virt);
1623
/* FIXME Putting the QH back on the list should work, but for some
1624
* strange reason doing that will affect other QHs on the periodic
1625
* list. So free the QH instead of putting it back on the list
1626
* which does seem to work, but I would like to know why. */
1629
/* Finaly we should return QH back to the AL... */
1630
e->qh_virt[i].qh_hptr =
1631
grub_cpu_to_le32 (grub_dma_virt2phys
1632
(cdata->qh_virt, e->qh_chunk));
1635
cdata->qh_virt->ep_char = 0;
1636
cdata->qh_virt->qh_hptr =
1637
grub_cpu_to_le32 ((grub_dma_virt2phys (cdata->qh_virt,
1639
& GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
1644
grub_dprintf ("ehci", "cancel_transfer: end\n");
1646
return GRUB_USB_ERR_NONE;
1650
grub_ehci_hubports (grub_usb_controller_t dev)
1652
struct grub_ehci *e = (struct grub_ehci *) dev->data;
1653
grub_uint32_t portinfo;
1655
portinfo = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1656
& GRUB_EHCI_SPARAMS_N_PORTS;
1657
grub_dprintf ("ehci", "root hub ports=%d\n", portinfo);
1662
grub_ehci_portstatus (grub_usb_controller_t dev,
1663
unsigned int port, unsigned int enable)
1665
struct grub_ehci *e = (struct grub_ehci *) dev->data;
1666
grub_uint64_t endtime;
1668
grub_dprintf ("ehci", "portstatus: EHCI STATUS: %08x\n",
1669
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1670
grub_dprintf ("ehci",
1671
"portstatus: begin, iobase=%p, port=%d, status=0x%02x\n",
1672
e->iobase, port, grub_ehci_port_read (e, port));
1674
/* In any case we need to disable port:
1675
* - if enable==false - we should disable port
1676
* - if enable==true we will do the reset and the specification says
1677
* PortEnable should be FALSE in such case */
1678
/* Disable the port and wait for it. */
1679
grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_ENABLED);
1680
endtime = grub_get_time_ms () + 1000;
1681
while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED)
1682
if (grub_get_time_ms () > endtime)
1683
return grub_error (GRUB_ERR_IO, "portstatus: EHCI Timed out - disable");
1685
if (!enable) /* We don't need reset port */
1687
grub_dprintf ("ehci", "portstatus: Disabled.\n");
1688
grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n",
1689
grub_ehci_port_read (e, port));
1690
return GRUB_ERR_NONE;
1693
grub_dprintf ("ehci", "portstatus: enable\n");
1695
/* Now we will do reset - if HIGH speed device connected, it will
1696
* result in Enabled state, otherwise port remains disabled. */
1697
/* Set RESET bit for 50ms */
1698
grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_RESET);
1699
grub_millisleep (50);
1701
/* Reset RESET bit and wait for the end of reset */
1702
grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_RESET);
1703
endtime = grub_get_time_ms () + 1000;
1704
while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_RESET)
1705
if (grub_get_time_ms () > endtime)
1706
return grub_error (GRUB_ERR_IO,
1707
"portstatus: EHCI Timed out - reset port");
1708
/* Remember "we did the reset" - needed by detect_dev */
1709
e->reset |= (1 << port);
1710
/* Test if port enabled, i.e. HIGH speed device connected */
1711
if ((grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED) != 0) /* yes! */
1713
grub_dprintf ("ehci", "portstatus: Enabled!\n");
1714
/* "Reset recovery time" (USB spec.) */
1715
grub_millisleep (10);
1719
/* FULL speed device connected - change port ownership.
1720
* It results in disconnected state of this EHCI port. */
1721
grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER);
1722
return GRUB_USB_ERR_BADDEVICE;
1725
/* XXX: Fix it! There is possible problem - we can say to calling
1726
* function that we lost device if it is FULL speed onlu via
1727
* return value <> GRUB_ERR_NONE. It (maybe) displays also error
1728
* message on screen - but this situation is not error, it is normal
1731
grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n",
1732
grub_ehci_port_read (e, port));
1734
return GRUB_ERR_NONE;
1737
static grub_usb_speed_t
1738
grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
1740
struct grub_ehci *e = (struct grub_ehci *) dev->data;
1741
grub_uint32_t status, line_state;
1743
status = grub_ehci_port_read (e, port);
1745
grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n",
1746
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1747
grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n",
1748
e->iobase, port, status);
1750
/* Connect Status Change bit - it detects change of connection */
1751
if (status & GRUB_EHCI_PORT_CONNECT_CH)
1754
/* Reset bit Connect Status Change */
1755
grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_CONNECT_CH);
1760
if (!(status & GRUB_EHCI_PORT_CONNECT))
1761
{ /* We should reset related "reset" flag in not connected state */
1762
e->reset &= ~(1 << port);
1763
return GRUB_USB_SPEED_NONE;
1765
/* Detected connected state, so we should return speed.
1766
* But we can detect only LOW speed device and only at connection
1767
* time when PortEnabled=FALSE. FULL / HIGH speed detection is made
1768
* later by EHCI-specific reset procedure.
1769
* Another thing - if detected speed is LOW at connection time,
1770
* we should change port ownership to companion controller.
1772
* 1. If we detect connected and enabled and EHCI-owned port,
1773
* we can say it is HIGH speed.
1774
* 2. If we detect connected and not EHCI-owned port, we can say
1775
* NONE speed, because such devices are not handled by EHCI.
1776
* 3. If we detect connected, not enabled but reset port, we can say
1777
* NONE speed, because it means FULL device connected to port and
1778
* such devices are not handled by EHCI.
1779
* 4. If we detect connected, not enabled and not reset port, which
1780
* has line state != "K", we will say HIGH - it could be FULL or HIGH
1781
* device, we will see it later after end of EHCI-specific reset
1783
* 5. If we detect connected, not enabled and not reset port, which
1784
* has line state == "K", we can say NONE speed, because LOW speed
1785
* device is connected and we should change port ownership. */
1786
if ((status & GRUB_EHCI_PORT_ENABLED) != 0) /* Port already enabled, return high speed. */
1787
return GRUB_USB_SPEED_HIGH;
1788
if ((status & GRUB_EHCI_PORT_OWNER) != 0) /* EHCI is not port owner */
1789
return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */
1790
if ((e->reset & (1 << port)) != 0) /* Port reset was done = FULL speed */
1791
return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */
1792
else /* Port connected but not enabled - test port speed. */
1794
line_state = status & GRUB_EHCI_PORT_LINE_STAT;
1795
if (line_state != GRUB_EHCI_PORT_LINE_LOWSP)
1796
return GRUB_USB_SPEED_HIGH;
1797
/* Detected LOW speed device, we should change
1799
* XXX: Fix it!: There should be test if related companion
1800
* controler is available ! And what to do if it does not exist ? */
1801
grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER);
1802
return GRUB_USB_SPEED_NONE; /* Ignore this port */
1803
/* Note: Reset of PORT_OWNER bit is done by EHCI HW when
1804
* device is really disconnected from port.
1805
* Don't do PORT_OWNER bit reset by SW when not connected signal
1806
* is detected in port register ! */
1811
grub_ehci_inithw (void)
1813
grub_pci_iterate (grub_ehci_pci_iter);
1817
grub_ehci_restore_hw (void)
1819
struct grub_ehci *e;
1820
grub_uint32_t n_ports;
1823
/* We should re-enable all EHCI HW similarly as on inithw */
1824
for (e = ehci; e; e = e->next)
1826
/* Check if EHCI is halted and halt it if not */
1827
if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
1828
grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout");
1831
if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
1832
grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout");
1834
/* Setup some EHCI registers and enable EHCI */
1835
grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys);
1836
grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR,
1837
grub_dma_virt2phys (&e->qh_virt[1],
1839
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1840
GRUB_EHCI_CMD_RUNSTOP |
1841
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1843
/* Set ownership of root hub ports to EHCI */
1844
grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG,
1845
GRUB_EHCI_CF_EHCI_OWNER);
1847
/* Enable asynchronous list */
1848
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1849
GRUB_EHCI_CMD_AS_ENABL
1850
| GRUB_EHCI_CMD_PS_ENABL
1851
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1853
/* Now should be possible to power-up and enumerate ports etc. */
1854
if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1855
& GRUB_EHCI_SPARAMS_PPC) != 0)
1856
{ /* EHCI has port powering control */
1857
/* Power on all ports */
1858
n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1859
& GRUB_EHCI_SPARAMS_N_PORTS;
1860
for (i = 0; i < (int) n_ports; i++)
1861
grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4,
1862
GRUB_EHCI_PORT_POWER
1863
| grub_ehci_oper_read32 (e,
1864
GRUB_EHCI_PORT_STAT_CMD
1869
return GRUB_USB_ERR_NONE;
1873
grub_ehci_fini_hw (int noreturn __attribute__ ((unused)))
1875
struct grub_ehci *e;
1877
/* We should disable all EHCI HW to prevent any DMA access etc. */
1878
for (e = ehci; e; e = e->next)
1880
/* Check if EHCI is halted and halt it if not */
1881
if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
1882
grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout");
1885
if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
1886
grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout");
1889
return GRUB_USB_ERR_NONE;
1892
static struct grub_usb_controller_dev usb_controller = {
1894
.iterate = grub_ehci_iterate,
1895
.setup_transfer = grub_ehci_setup_transfer,
1896
.check_transfer = grub_ehci_check_transfer,
1897
.cancel_transfer = grub_ehci_cancel_transfer,
1898
.hubports = grub_ehci_hubports,
1899
.portstatus = grub_ehci_portstatus,
1900
.detect_dev = grub_ehci_detect_dev
1903
GRUB_MOD_INIT (ehci)
1905
COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64);
1906
COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96);
1907
grub_ehci_inithw ();
1908
grub_usb_controller_dev_register (&usb_controller);
1909
grub_loader_register_preboot_hook (grub_ehci_fini_hw, grub_ehci_restore_hw,
1910
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
1913
GRUB_MOD_FINI (ehci)
1915
grub_ehci_fini_hw (0);
1916
grub_usb_controller_dev_unregister (&usb_controller);