]> git.proxmox.com Git - grub2.git/blob - grub-core/bus/usb/ehci.c
EHCI and OHCI PCI bus master
[grub2.git] / grub-core / bus / usb / ehci.c
1 /* ehci.c - EHCI Support. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2011 Free Software Foundation, Inc.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20 #include <grub/dl.h>
21 #include <grub/mm.h>
22 #include <grub/usb.h>
23 #include <grub/usbtrans.h>
24 #include <grub/misc.h>
25 #include <grub/pci.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>
31
32 GRUB_MOD_LICENSE ("GPLv3+");
33
34 /* This simple GRUB implementation of EHCI driver:
35 * - assumes no IRQ
36 * - is not supporting isochronous transfers (iTD, siTD)
37 * - is not supporting interrupt transfers
38 */
39
40 #define GRUB_EHCI_PCI_SBRN_REG 0x60
41
42 /* Capability registers offsets */
43 enum
44 {
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 */
50 };
51
52 #define GRUB_EHCI_EECP_MASK (0xff << 8)
53 #define GRUB_EHCI_EECP_SHIFT 8
54
55 #define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
56 #define GRUB_EHCI_POINTER_MASK (~0x1f)
57
58 /* Capability register SPARAMS bits */
59 enum
60 {
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 */
68 };
69
70 #define GRUB_EHCI_MAX_N_PORTS 15 /* Max. number of ports */
71
72 /* Capability register CPARAMS bits */
73 enum
74 {
75 GRUB_EHCI_CPARAMS_64BIT = (1 << 0),
76 GRUB_EHCI_CPARAMS_PROG_FRAMELIST = (1 << 1),
77 GRUB_EHCI_CPARAMS_PARK_CAP = (1 << 2)
78 };
79
80 #define GRUB_EHCI_N_FRAMELIST 1024
81 #define GRUB_EHCI_N_QH 256
82 #define GRUB_EHCI_N_TD 640
83
84 #define GRUB_EHCI_QH_EMPTY 1
85
86 /* USBLEGSUP bits and related OS OWNED byte offset */
87 enum
88 {
89 GRUB_EHCI_BIOS_OWNED = (1 << 16),
90 GRUB_EHCI_OS_OWNED = (1 << 24)
91 };
92
93 /* Operational registers offsets */
94 enum
95 {
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
105 };
106
107 /* Operational register COMMAND bits */
108 enum
109 {
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)
120 };
121
122 /* Operational register STATUS bits */
123 enum
124 {
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)
135 };
136
137 /* Operational register PORT_STAT_CMD bits */
138 enum
139 {
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),
157
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)
166 };
167
168 /* Operational register CONFIGFLAGS bits */
169 enum
170 {
171 GRUB_EHCI_CF_EHCI_OWNER = (1 << 0)
172 };
173
174 /* Queue Head & Transfer Descriptor constants */
175 #define GRUB_EHCI_HPTR_OFF 5 /* Horiz. pointer bit offset */
176 enum
177 {
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)
183 };
184
185 enum
186 {
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)
199 };
200
201 enum
202 {
203 GRUB_EHCI_MAXPLEN_OFF = 16,
204 GRUB_EHCI_SPEED_OFF = 12,
205 GRUB_EHCI_EP_NUM_OFF = 8
206 };
207
208 enum
209 {
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),
219 };
220
221 enum
222 {
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,
228 };
229
230 #define GRUB_EHCI_TERMINATE (1<<0)
231
232 #define GRUB_EHCI_TOGGLE (1<<31)
233
234 enum
235 {
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)
254 };
255
256 enum
257 {
258 GRUB_EHCI_TOTAL_OFF = 16,
259 GRUB_EHCI_CERR_OFF = 10
260 };
261
262 #define GRUB_EHCI_BUFPTR_MASK (0xfffff<<12)
263 #define GRUB_EHCI_QHTDPTR_MASK 0xffffffe0
264
265 #define GRUB_EHCI_TD_BUF_PAGES 5
266
267 #define GRUB_EHCI_BUFPAGELEN 0x1000
268 #define GRUB_EHCI_MAXBUFLEN 0x5000
269
270 struct grub_ehci_td;
271 struct grub_ehci_qh;
272 typedef volatile struct grub_ehci_td *grub_ehci_td_t;
273 typedef volatile struct grub_ehci_qh *grub_ehci_qh_t;
274
275 /* EHCI Isochronous Transfer Descriptor */
276 /* Currently not supported */
277
278 /* EHCI Split Transaction Isochronous Transfer Descriptor */
279 /* Currently not supported */
280
281 /* EHCI Queue Element Transfer Descriptor (qTD) */
282 /* Align to 32-byte boundaries */
283 struct grub_ehci_td
284 {
285 /* EHCI HW part */
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 */
290 /* 64-bits part */
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 */
294 grub_uint32_t size;
295 grub_uint32_t pad[1]; /* padding to some multiple of 32 bytes */
296 };
297
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) */
303 struct grub_ehci_qh
304 {
305 /* EHCI HW part */
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 */
313 };
314
315 /* EHCI Periodic Frame Span Traversal Node */
316 /* Currently not supported */
317
318 struct grub_ehci
319 {
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 */
332 int flag64;
333 grub_uint32_t reset; /* bits 1-15 are flags if port was reset from connected time or not */
334 struct grub_ehci *next;
335 };
336
337 static struct grub_ehci *ehci;
338
339 /* EHCC registers access functions */
340 static inline grub_uint32_t
341 grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
342 {
343 return
344 grub_le_to_cpu32 (*((volatile grub_uint32_t *) e->iobase_ehcc +
345 (addr / sizeof (grub_uint32_t))));
346 }
347
348 static inline grub_uint16_t
349 grub_ehci_ehcc_read16 (struct grub_ehci *e, grub_uint32_t addr)
350 {
351 return
352 grub_le_to_cpu16 (*((volatile grub_uint16_t *) e->iobase_ehcc +
353 (addr / sizeof (grub_uint16_t))));
354 }
355
356 static inline grub_uint8_t
357 grub_ehci_ehcc_read8 (struct grub_ehci *e, grub_uint32_t addr)
358 {
359 return *((volatile grub_uint8_t *) e->iobase_ehcc + addr);
360 }
361
362 /* Operational registers access functions */
363 static inline grub_uint32_t
364 grub_ehci_oper_read32 (struct grub_ehci *e, grub_uint32_t addr)
365 {
366 return
367 grub_le_to_cpu32 (*
368 ((volatile grub_uint32_t *) e->iobase +
369 (addr / sizeof (grub_uint32_t))));
370 }
371
372 static inline void
373 grub_ehci_oper_write32 (struct grub_ehci *e, grub_uint32_t addr,
374 grub_uint32_t value)
375 {
376 *((volatile grub_uint32_t *) e->iobase + (addr / sizeof (grub_uint32_t))) =
377 grub_cpu_to_le32 (value);
378 }
379
380 static inline grub_uint32_t
381 grub_ehci_port_read (struct grub_ehci *e, grub_uint32_t port)
382 {
383 return grub_ehci_oper_read32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4);
384 }
385
386 static inline void
387 grub_ehci_port_resbits (struct grub_ehci *e, grub_uint32_t port,
388 grub_uint32_t bits)
389 {
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 &
393 ~(bits));
394 grub_ehci_port_read (e, port);
395 }
396
397 static inline void
398 grub_ehci_port_setbits (struct grub_ehci *e, grub_uint32_t port,
399 grub_uint32_t bits)
400 {
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);
405 }
406
407 /* Halt if EHCI HC not halted */
408 static grub_usb_err_t
409 grub_ehci_halt (struct grub_ehci *e)
410 {
411 grub_uint64_t maxtime;
412
413 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & GRUB_EHCI_ST_HC_HALTED) == 0) /* EHCI is not halted */
414 {
415 /* Halt EHCI */
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;
428 }
429
430 return GRUB_USB_ERR_NONE;
431 }
432
433 /* EHCI HC reset */
434 static grub_usb_err_t
435 grub_ehci_reset (struct grub_ehci *e)
436 {
437 grub_uint64_t maxtime;
438
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;
452
453 return GRUB_USB_ERR_NONE;
454 }
455
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)))
460 {
461 grub_uint8_t release;
462 grub_uint32_t class_code;
463 grub_uint32_t interf;
464 grub_uint32_t subclass;
465 grub_uint32_t class;
466 grub_uint32_t base, base_h;
467 struct grub_ehci *e;
468 grub_uint32_t eecp_offset;
469 grub_uint32_t fp;
470 int i;
471 grub_uint32_t usblegsup = 0;
472 grub_uint64_t maxtime;
473 grub_uint32_t n_ports;
474 grub_uint8_t caplen;
475
476 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
477
478 if (pciid == GRUB_CS5536_PCIID)
479 {
480 grub_uint64_t basereg;
481
482 basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
483 if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
484 {
485 /* Shouldn't happen. */
486 grub_dprintf ("ehci", "No EHCI address is assigned\n");
487 return 0;
488 }
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);
495 }
496 else
497 {
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;
504
505 /* If this is not an EHCI controller, just return. */
506 if (class != 0x0c || subclass != 0x03 || interf != 0x20)
507 return 0;
508
509 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
510
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);
514 if (release != 0x20)
515 {
516 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
517 release);
518 return 0;
519 }
520 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
521
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)
530 && (base_h != 0))
531 {
532 grub_dprintf ("ehci",
533 "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
534 return 0;
535 }
536
537 /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
538 addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
539 grub_pci_write_word(addr,
540 GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr));
541
542 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
543 }
544
545 /* Allocate memory for the controller and fill basic values. */
546 e = grub_zalloc (sizeof (*e));
547 if (!e)
548 return 1;
549 e->framelist_chunk = NULL;
550 e->td_chunk = NULL;
551 e->qh_chunk = NULL;
552 e->iobase_ehcc = grub_pci_device_map_range (dev,
553 (base & GRUB_EHCI_ADDR_MEM_MASK),
554 0x100);
555
556 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
557 (base & GRUB_EHCI_ADDR_MEM_MASK));
558 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n",
559 grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
560 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n",
561 grub_ehci_ehcc_read16 (e, GRUB_EHCI_EHCC_VERSION));
562 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: SPARAMS: %08x\n",
563 grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS));
564 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CPARAMS: %08x\n",
565 grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS));
566
567 /* Determine base address of EHCI operational registers */
568 caplen = grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN);
569 #ifndef GRUB_HAVE_UNALIGNED_ACCESS
570 if (caplen & (sizeof (grub_uint32_t) - 1))
571 {
572 grub_dprintf ("ehci", "Unaligned caplen\n");
573 return 0;
574 }
575 e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
576 + (caplen / sizeof (grub_uint32_t)));
577 #else
578 e->iobase = (volatile grub_uint32_t *)
579 ((grub_uint8_t *) e->iobase_ehcc + caplen);
580 #endif
581
582 grub_dprintf ("ehci",
583 "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
584 (base & GRUB_EHCI_ADDR_MEM_MASK) + caplen);
585 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
586 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
587 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
588 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
589 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n",
590 grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT));
591 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n",
592 grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX));
593 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n",
594 grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE));
595 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n",
596 grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR));
597 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
598 grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
599
600 /* Is there EECP ? */
601 eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
602 & GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT;
603
604 /* Check format of data structures requested by EHCI */
605 /* XXX: In fact it is not used at any place, it is prepared for future
606 * This implementation uses 32-bits pointers only */
607 e->flag64 = ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
608 & GRUB_EHCI_CPARAMS_64BIT) != 0);
609
610 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: flag64=%d\n", e->flag64);
611
612 /* Reserve a page for the frame list - it is accurate for max.
613 * possible size of framelist. But currently it is not used. */
614 e->framelist_chunk = grub_memalign_dma32 (4096, 4096);
615 if (!e->framelist_chunk)
616 goto fail;
617 e->framelist_virt = grub_dma_get_virt (e->framelist_chunk);
618 e->framelist_phys = grub_dma_get_phys (e->framelist_chunk);
619 grub_memset ((void *) e->framelist_virt, 0, 4096);
620
621 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: framelist mem=%p. OK\n",
622 e->framelist_virt);
623
624 /* Allocate memory for the QHs and register it in "e". */
625 e->qh_chunk = grub_memalign_dma32 (4096,
626 sizeof (struct grub_ehci_qh) *
627 GRUB_EHCI_N_QH);
628 if (!e->qh_chunk)
629 goto fail;
630 e->qh_virt = (grub_ehci_qh_t) grub_dma_get_virt (e->qh_chunk);
631 e->qh_phys = grub_dma_get_phys (e->qh_chunk);
632 grub_memset ((void *) e->qh_virt, 0,
633 sizeof (struct grub_ehci_qh) * GRUB_EHCI_N_QH);
634
635 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH mem=%p. OK\n",
636 e->qh_virt);
637
638 /* Allocate memory for the TDs and register it in "e". */
639 e->td_chunk = grub_memalign_dma32 (4096,
640 sizeof (struct grub_ehci_td) *
641 GRUB_EHCI_N_TD);
642 if (!e->td_chunk)
643 goto fail;
644 e->td_virt = (grub_ehci_td_t) grub_dma_get_virt (e->td_chunk);
645 e->td_phys = grub_dma_get_phys (e->td_chunk);
646 grub_memset ((void *) e->td_virt, 0,
647 sizeof (struct grub_ehci_td) * GRUB_EHCI_N_TD);
648
649 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: TD mem=%p. OK\n",
650 e->td_virt);
651
652 /* Setup all frame list pointers. Since no isochronous transfers
653 are supported, they all point to the (same!) queue
654 head with index 0. */
655 fp = grub_cpu_to_le32 ((e->qh_phys & GRUB_EHCI_POINTER_MASK)
656 | GRUB_EHCI_HPTR_TYPE_QH);
657 for (i = 0; i < GRUB_EHCI_N_FRAMELIST; i++)
658 e->framelist_virt[i] = fp;
659 /* Prepare chain of all TDs and set Terminate in all TDs */
660 for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++)
661 {
662 e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td);
663 e->td_virt[i].next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
664 e->td_virt[i].alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
665 }
666 e->td_virt[GRUB_EHCI_N_TD - 1].next_td =
667 grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
668 e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td =
669 grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
670 e->tdfree_virt = e->td_virt;
671 /* Set Terminate in first QH, which is used in framelist */
672 e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
673 e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
674 e->qh_virt[0].td_overlay.alt_next_td =
675 grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
676 /* Also set Halted bit in token */
677 e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
678 /* Set the H bit in first QH used for AL */
679 e->qh_virt[1].ep_char = grub_cpu_to_le32 (GRUB_EHCI_H);
680 /* Set Terminate into TD in rest of QHs and set horizontal link
681 * pointer to itself - these QHs will be used for asynchronous
682 * schedule and they should have valid value in horiz. link */
683 for (i = 1; i < GRUB_EHCI_N_QH; i++)
684 {
685 e->qh_virt[i].qh_hptr =
686 grub_cpu_to_le32 ((grub_dma_virt2phys (&e->qh_virt[i],
687 e->qh_chunk) &
688 GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
689 e->qh_virt[i].td_overlay.next_td =
690 grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
691 e->qh_virt[i].td_overlay.alt_next_td =
692 grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
693 /* Also set Halted bit in token */
694 e->qh_virt[i].td_overlay.token =
695 grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
696 }
697
698 /* Note: QH 0 and QH 1 are reserved and must not be used anywhere.
699 * QH 0 is used as empty QH for framelist
700 * QH 1 is used as starting empty QH for asynchronous schedule
701 * QH 1 must exist at any time because at least one QH linked to
702 * itself must exist in asynchronous schedule
703 * QH 1 has the H flag set to one */
704
705 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n");
706
707 /* Determine and change ownership. */
708 /* EECP offset valid in HCCPARAMS */
709 /* Ownership can be changed via EECP only */
710 if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
711 {
712 grub_pci_address_t pciaddr_eecp;
713 pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
714
715 usblegsup = grub_pci_read (pciaddr_eecp);
716 if (usblegsup & GRUB_EHCI_BIOS_OWNED)
717 {
718 grub_dprintf ("ehci",
719 "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
720 /* Ownership change - set OS_OWNED bit */
721 grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
722 /* Ensure PCI register is written */
723 grub_pci_read (pciaddr_eecp);
724
725 /* Wait for finish of ownership change, EHCI specification
726 * doesn't say how long it can take... */
727 maxtime = grub_get_time_ms () + 1000;
728 while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
729 && (grub_get_time_ms () < maxtime));
730 if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
731 {
732 grub_dprintf ("ehci",
733 "EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
734 /* Change ownership in "hard way" - reset BIOS ownership */
735 grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
736 /* Ensure PCI register is written */
737 grub_pci_read (pciaddr_eecp);
738 /* Disable SMI. */
739 pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
740 grub_pci_write (pciaddr_eecp, 0);
741 /* Ensure PCI register is written */
742 grub_pci_read (pciaddr_eecp);
743 }
744 }
745 else if (usblegsup & GRUB_EHCI_OS_OWNED)
746 /* XXX: What to do in this case - nothing ? Can it happen ? */
747 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
748 else
749 {
750 grub_dprintf ("ehci",
751 "EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
752 /* XXX: What to do in this case ? Can it happen ?
753 * Is code below correct ? */
754 /* Ownership change - set OS_OWNED bit */
755 grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
756 /* Ensure PCI register is written */
757 grub_pci_read (pciaddr_eecp);
758 /* Disable SMI, just to be sure. */
759 pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
760 grub_pci_write (pciaddr_eecp, 0);
761 /* Ensure PCI register is written */
762 grub_pci_read (pciaddr_eecp);
763 }
764 }
765
766 grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
767
768 /* Now we can setup EHCI (maybe...) */
769
770 /* Check if EHCI is halted and halt it if not */
771 if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
772 {
773 grub_error (GRUB_ERR_TIMEOUT,
774 "EHCI grub_ehci_pci_iter: EHCI halt timeout");
775 goto fail;
776 }
777
778 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: halted OK\n");
779
780 /* Reset EHCI */
781 if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
782 {
783 grub_error (GRUB_ERR_TIMEOUT,
784 "EHCI grub_ehci_pci_iter: EHCI reset timeout");
785 goto fail;
786 }
787
788 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: reset OK\n");
789
790 /* Setup list address registers */
791 grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys);
792 grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR,
793 grub_dma_virt2phys (&e->qh_virt[1],
794 e->qh_chunk));
795
796 /* Set ownership of root hub ports to EHCI */
797 grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG, GRUB_EHCI_CF_EHCI_OWNER);
798
799 /* Enable asynchronous list */
800 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
801 GRUB_EHCI_CMD_AS_ENABL
802 | GRUB_EHCI_CMD_PS_ENABL
803 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
804
805 /* Now should be possible to power-up and enumerate ports etc. */
806 if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
807 & GRUB_EHCI_SPARAMS_PPC) != 0)
808 { /* EHCI has port powering control */
809 /* Power on all ports */
810 n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
811 & GRUB_EHCI_SPARAMS_N_PORTS;
812 for (i = 0; i < (int) n_ports; i++)
813 grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4,
814 GRUB_EHCI_PORT_POWER
815 | grub_ehci_oper_read32 (e,
816 GRUB_EHCI_PORT_STAT_CMD
817 + i * 4));
818 }
819
820 /* Ensure all commands are written */
821 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
822
823 /* Enable EHCI */
824 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
825 GRUB_EHCI_CMD_RUNSTOP
826 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
827
828 /* Ensure command is written */
829 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
830
831 /* Link to ehci now that initialisation is successful. */
832 e->next = ehci;
833 ehci = e;
834
835 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
836
837 grub_dprintf ("ehci",
838 "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
839 (base & GRUB_EHCI_ADDR_MEM_MASK));
840 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
841 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
842 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
843 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
844 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n",
845 grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT));
846 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n",
847 grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX));
848 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n",
849 grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE));
850 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n",
851 grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR));
852 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
853 grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
854
855 return 0;
856
857 fail:
858 if (e)
859 {
860 if (e->td_chunk)
861 grub_dma_free ((void *) e->td_chunk);
862 if (e->qh_chunk)
863 grub_dma_free ((void *) e->qh_chunk);
864 if (e->framelist_chunk)
865 grub_dma_free (e->framelist_chunk);
866 }
867 grub_free (e);
868
869 return 0;
870 }
871
872 static int
873 grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev))
874 {
875 struct grub_ehci *e;
876 struct grub_usb_controller dev;
877
878 for (e = ehci; e; e = e->next)
879 {
880 dev.data = e;
881 if (hook (&dev))
882 return 1;
883 }
884
885 return 0;
886 }
887
888 static void
889 grub_ehci_setup_qh (grub_ehci_qh_t qh, grub_usb_transfer_t transfer)
890 {
891 grub_uint32_t ep_char = 0;
892 grub_uint32_t ep_cap = 0;
893
894 /* Note: Another part of code is responsible to this QH is
895 * Halted ! But it can be linked in AL, so we cannot erase or
896 * change qh_hptr ! */
897 /* We will not change any TD field because they should/must be
898 * in safe state from previous use. */
899
900 /* EP characteristic setup */
901 /* Currently not used NAK counter (RL=0),
902 * C bit set if EP is not HIGH speed and is control,
903 * Max Packet Length is taken from transfer structure,
904 * H bit = 0 (because QH[1] has this bit set),
905 * DTC bit set to 1 because we are using our own toggle bit control,
906 * SPEED is selected according to value from transfer structure,
907 * EP number is taken from transfer structure
908 * "I" bit must not be set,
909 * Device Address is taken from transfer structure
910 * */
911 if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH)
912 && (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL))
913 ep_char |= GRUB_EHCI_C;
914 ep_char |= (transfer->max << GRUB_EHCI_MAXPLEN_OFF)
915 & GRUB_EHCI_MAXPLEN_MASK;
916 ep_char |= GRUB_EHCI_DTC;
917 switch (transfer->dev->speed)
918 {
919 case GRUB_USB_SPEED_LOW:
920 ep_char |= GRUB_EHCI_SPEED_LOW;
921 break;
922 case GRUB_USB_SPEED_FULL:
923 ep_char |= GRUB_EHCI_SPEED_FULL;
924 break;
925 case GRUB_USB_SPEED_HIGH:
926 default:
927 ep_char |= GRUB_EHCI_SPEED_HIGH;
928 /* XXX: How we will handle unknown value of speed? */
929 }
930 ep_char |= (transfer->endpoint << GRUB_EHCI_EP_NUM_OFF)
931 & GRUB_EHCI_EP_NUM_MASK;
932 ep_char |= transfer->devaddr & GRUB_EHCI_DEVADDR_MASK;
933 qh->ep_char = grub_cpu_to_le32 (ep_char);
934 /* EP capabilities setup */
935 /* MULT field - we try to use max. number
936 * PortNumber - included now in device structure referenced
937 * inside transfer structure
938 * HubAddress - included now in device structure referenced
939 * inside transfer structure
940 * SplitCompletionMask - AFAIK it is ignored in asynchronous list,
941 * InterruptScheduleMask - AFAIK it should be zero in async. list */
942 ep_cap |= GRUB_EHCI_MULT_THREE;
943 ep_cap |= (transfer->dev->port << GRUB_EHCI_DEVPORT_OFF)
944 & GRUB_EHCI_DEVPORT_MASK;
945 ep_cap |= (transfer->dev->hubaddr << GRUB_EHCI_HUBADDR_OFF)
946 & GRUB_EHCI_HUBADDR_MASK;
947 if (transfer->dev->speed == GRUB_USB_SPEED_LOW
948 && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL)
949 {
950 ep_cap |= (1<<0) << GRUB_EHCI_SMASK_OFF;
951 ep_cap |= (7<<2) << GRUB_EHCI_CMASK_OFF;
952 }
953 qh->ep_cap = grub_cpu_to_le32 (ep_cap);
954
955 grub_dprintf ("ehci", "setup_qh: qh=%p, not changed: qh_hptr=%08x\n",
956 qh, grub_le_to_cpu32 (qh->qh_hptr));
957 grub_dprintf ("ehci", "setup_qh: ep_char=%08x, ep_cap=%08x\n",
958 ep_char, ep_cap);
959 grub_dprintf ("ehci", "setup_qh: end\n");
960 grub_dprintf ("ehci", "setup_qh: not changed: td_current=%08x\n",
961 grub_le_to_cpu32 (qh->td_current));
962 grub_dprintf ("ehci", "setup_qh: not changed: next_td=%08x\n",
963 grub_le_to_cpu32 (qh->td_overlay.next_td));
964 grub_dprintf ("ehci", "setup_qh: not changed: alt_next_td=%08x\n",
965 grub_le_to_cpu32 (qh->td_overlay.alt_next_td));
966 grub_dprintf ("ehci", "setup_qh: not changed: token=%08x\n",
967 grub_le_to_cpu32 (qh->td_overlay.token));
968 }
969
970 static grub_ehci_qh_t
971 grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
972 {
973 grub_uint32_t target, mask;
974 int i;
975 grub_ehci_qh_t qh = e->qh_virt;
976 grub_ehci_qh_t head;
977
978 /* Prepare part of EP Characteristic to find existing QH */
979 target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) |
980 transfer->devaddr) & GRUB_EHCI_TARGET_MASK;
981 target = grub_cpu_to_le32 (target);
982 mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK);
983
984 /* First try to find existing QH with proper target */
985 for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */
986 {
987 if (!qh[i].ep_char)
988 break; /* Found first not-allocated QH, finish */
989 if (target == (qh[i].ep_char & mask))
990 {
991 /* Found proper existing (and linked) QH, do setup of QH */
992 grub_dprintf ("ehci", "find_qh: found, i=%d, QH=%p\n",
993 i, &qh[i]);
994 grub_ehci_setup_qh (&qh[i], transfer);
995 return &qh[i];
996 }
997 }
998 /* QH with target_addr does not exist, we have to add it */
999 /* Have we any free QH in array ? */
1000 if (i >= GRUB_EHCI_N_QH) /* No. */
1001 {
1002 grub_dprintf ("ehci", "find_qh: end - no free QH\n");
1003 return NULL;
1004 }
1005 grub_dprintf ("ehci", "find_qh: new, i=%d, QH=%p\n",
1006 i, &qh[i]);
1007 /* Currently we simply take next (current) QH in array, no allocation
1008 * function is used. It should be no problem until we will need to
1009 * de-allocate QHs of unplugged devices. */
1010 /* We should preset new QH and link it into AL */
1011 grub_ehci_setup_qh (&qh[i], transfer);
1012
1013 /* low speed interrupt transfers are linked to the periodic
1014 * scheudle, everything else to the asynchronous schedule */
1015 if (transfer->dev->speed == GRUB_USB_SPEED_LOW
1016 && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL)
1017 head = &qh[0];
1018 else
1019 head = &qh[1];
1020
1021 /* Linking - this new (last) QH will copy the QH from the head QH */
1022 qh[i].qh_hptr = head->qh_hptr;
1023 /* Linking - the head QH will point to this new QH */
1024 head->qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_HPTR_TYPE_QH
1025 | grub_dma_virt2phys (&qh[i],
1026 e->qh_chunk));
1027
1028 return &qh[i];
1029 }
1030
1031 static grub_ehci_td_t
1032 grub_ehci_alloc_td (struct grub_ehci *e)
1033 {
1034 grub_ehci_td_t ret;
1035
1036 /* Check if there is a Transfer Descriptor available. */
1037 if (!e->tdfree_virt)
1038 {
1039 grub_dprintf ("ehci", "alloc_td: end - no free TD\n");
1040 return NULL;
1041 }
1042
1043 ret = e->tdfree_virt; /* Take current free TD */
1044 /* Advance to next free TD in chain */
1045 if (ret->link_td)
1046 e->tdfree_virt = grub_dma_phys2virt (ret->link_td, e->td_chunk);
1047 else
1048 e->tdfree_virt = NULL;
1049 ret->link_td = 0; /* Reset link_td in allocated TD */
1050 return ret;
1051 }
1052
1053 static void
1054 grub_ehci_free_td (struct grub_ehci *e, grub_ehci_td_t td)
1055 {
1056 /* Chain new free TD & rest */
1057 if (e->tdfree_virt)
1058 td->link_td = grub_dma_virt2phys (e->tdfree_virt, e->td_chunk);
1059 else
1060 td->link_td = 0;
1061 e->tdfree_virt = td; /* Change address of first free TD */
1062 }
1063
1064 static void
1065 grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td,
1066 grub_usb_transfer_t transfer, grub_size_t * actual)
1067 {
1068 int i; /* Index of TD in transfer */
1069 grub_uint32_t token, to_transfer;
1070
1071 /* Note: Another part of code is responsible to this QH is
1072 * INACTIVE ! */
1073 *actual = 0;
1074
1075 /* Free the TDs in this queue and set last_trans. */
1076 for (i = 0; td; i++)
1077 {
1078 grub_ehci_td_t tdprev;
1079
1080 token = grub_le_to_cpu32 (td->token);
1081 to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF;
1082
1083 /* Check state of TD - if it did not transfered
1084 * whole data then set last_trans - it should be last executed TD
1085 * in case when something went wrong. */
1086 if (transfer && (td->size != to_transfer))
1087 transfer->last_trans = i;
1088
1089 *actual += td->size - to_transfer;
1090
1091 /* Unlink the TD */
1092 tdprev = td;
1093 if (td->link_td)
1094 td = grub_dma_phys2virt (td->link_td, e->td_chunk);
1095 else
1096 td = NULL;
1097
1098 /* Free the TD. */
1099 grub_ehci_free_td (e, tdprev);
1100 }
1101
1102 /* Check if last_trans was set. If not and something was
1103 * transferred (it should be all data in this case), set it
1104 * to index of last TD, i.e. i-1 */
1105 if (transfer && (transfer->last_trans < 0) && (*actual != 0))
1106 transfer->last_trans = i - 1;
1107
1108 /* XXX: Fix it: last_trans may be set to bad index.
1109 * Probably we should test more error flags to distinguish
1110 * if TD was at least partialy executed or not at all.
1111 * Generaly, we still could have problem with toggling because
1112 * EHCI can probably split transactions into smaller parts then
1113 * we defined in transaction even if we did not exceed MaxFrame
1114 * length - it probably could happen at the end of microframe (?)
1115 * and if the buffer is crossing page boundary (?). */
1116 }
1117
1118 static grub_ehci_td_t
1119 grub_ehci_transaction (struct grub_ehci *e,
1120 grub_transfer_type_t type,
1121 unsigned int toggle, grub_size_t size,
1122 grub_uint32_t data, grub_ehci_td_t td_alt)
1123 {
1124 grub_ehci_td_t td;
1125 grub_uint32_t token;
1126 grub_uint32_t bufadr;
1127 int i;
1128
1129 /* Test of transfer size, it can be:
1130 * <= GRUB_EHCI_MAXBUFLEN if data aligned to page boundary
1131 * <= GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN if not aligned
1132 * (worst case)
1133 */
1134 if ((((data % GRUB_EHCI_BUFPAGELEN) == 0)
1135 && (size > GRUB_EHCI_MAXBUFLEN))
1136 ||
1137 (((data % GRUB_EHCI_BUFPAGELEN) != 0)
1138 && (size > (GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN))))
1139 {
1140 grub_error (GRUB_ERR_OUT_OF_MEMORY,
1141 "too long data buffer for EHCI transaction");
1142 return 0;
1143 }
1144
1145 /* Grab a free Transfer Descriptor and initialize it. */
1146 td = grub_ehci_alloc_td (e);
1147 if (!td)
1148 {
1149 grub_error (GRUB_ERR_OUT_OF_MEMORY,
1150 "no transfer descriptors available for EHCI transfer");
1151 return 0;
1152 }
1153
1154 grub_dprintf ("ehci",
1155 "transaction: type=%d, toggle=%d, size=%lu data=0x%x td=%p\n",
1156 type, toggle, (unsigned long) size, data, td);
1157
1158 /* Fill whole TD by zeros */
1159 grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td));
1160
1161 /* Don't point to any TD yet, just terminate. */
1162 td->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1163 /* Set alternate pointer. When short packet occurs, alternate TD
1164 * will not be really fetched because it is not active. But don't
1165 * forget, EHCI will try to fetch alternate TD every scan of AL
1166 * until QH is halted. */
1167 td->alt_next_td = grub_cpu_to_le32 (grub_dma_virt2phys (td_alt,
1168 e->td_chunk));
1169 /* token:
1170 * TOGGLE - according to toggle
1171 * TOTAL SIZE = size
1172 * Interrupt On Complete = FALSE, we don't need IRQ
1173 * Current Page = 0
1174 * Error Counter = max. value = 3
1175 * PID Code - according to type
1176 * STATUS:
1177 * ACTIVE bit should be set to one
1178 * SPLIT TRANS. STATE bit should be zero. It is ignored
1179 * in HIGH speed transaction, and should be zero for LOW/FULL
1180 * speed to indicate state Do Split Transaction */
1181 token = toggle ? GRUB_EHCI_TOGGLE : 0;
1182 token |= (size << GRUB_EHCI_TOTAL_OFF) & GRUB_EHCI_TOTAL_MASK;
1183 token |= GRUB_EHCI_CERR_3;
1184 switch (type)
1185 {
1186 case GRUB_USB_TRANSFER_TYPE_IN:
1187 token |= GRUB_EHCI_PIDCODE_IN;
1188 break;
1189 case GRUB_USB_TRANSFER_TYPE_OUT:
1190 token |= GRUB_EHCI_PIDCODE_OUT;
1191 break;
1192 case GRUB_USB_TRANSFER_TYPE_SETUP:
1193 token |= GRUB_EHCI_PIDCODE_SETUP;
1194 break;
1195 default: /* XXX: Should not happen, but what to do if it does ? */
1196 break;
1197 }
1198 token |= GRUB_EHCI_STATUS_ACTIVE;
1199 td->token = grub_cpu_to_le32 (token);
1200
1201 /* Fill buffer pointers according to size */
1202 bufadr = data;
1203 td->buffer_page[0] = grub_cpu_to_le32 (bufadr);
1204 bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN;
1205 for (i = 1; ((bufadr - data) < size) && (i < GRUB_EHCI_TD_BUF_PAGES); i++)
1206 {
1207 td->buffer_page[i] = grub_cpu_to_le32 (bufadr & GRUB_EHCI_BUFPTR_MASK);
1208 bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN;
1209 }
1210
1211 /* Remember data size for future use... */
1212 td->size = (grub_uint32_t) size;
1213
1214 grub_dprintf ("ehci", "td=%p\n", td);
1215 grub_dprintf ("ehci", "HW: next_td=%08x, alt_next_td=%08x\n",
1216 grub_le_to_cpu32 (td->next_td),
1217 grub_le_to_cpu32 (td->alt_next_td));
1218 grub_dprintf ("ehci", "HW: token=%08x, buffer[0]=%08x\n",
1219 grub_le_to_cpu32 (td->token),
1220 grub_le_to_cpu32 (td->buffer_page[0]));
1221 grub_dprintf ("ehci", "HW: buffer[1]=%08x, buffer[2]=%08x\n",
1222 grub_le_to_cpu32 (td->buffer_page[1]),
1223 grub_le_to_cpu32 (td->buffer_page[2]));
1224 grub_dprintf ("ehci", "HW: buffer[3]=%08x, buffer[4]=%08x\n",
1225 grub_le_to_cpu32 (td->buffer_page[3]),
1226 grub_le_to_cpu32 (td->buffer_page[4]));
1227 grub_dprintf ("ehci", "link_td=%08x, size=%08x\n",
1228 td->link_td, td->size);
1229
1230 return td;
1231 }
1232
1233 struct grub_ehci_transfer_controller_data
1234 {
1235 grub_ehci_qh_t qh_virt;
1236 grub_ehci_td_t td_first_virt;
1237 grub_ehci_td_t td_alt_virt;
1238 grub_ehci_td_t td_last_virt;
1239 grub_uint32_t td_last_phys;
1240 };
1241
1242 static grub_usb_err_t
1243 grub_ehci_setup_transfer (grub_usb_controller_t dev,
1244 grub_usb_transfer_t transfer)
1245 {
1246 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1247 grub_ehci_td_t td = NULL;
1248 grub_ehci_td_t td_prev = NULL;
1249 int i;
1250 struct grub_ehci_transfer_controller_data *cdata;
1251
1252 /* Check if EHCI is running and AL is enabled */
1253 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1254 & GRUB_EHCI_ST_HC_HALTED) != 0)
1255 /* XXX: Fix it: Currently we don't do anything to restart EHCI */
1256 return GRUB_USB_ERR_INTERNAL;
1257 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1258 & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
1259 /* XXX: Fix it: Currently we don't do anything to restart EHCI */
1260 return GRUB_USB_ERR_INTERNAL;
1261
1262 /* Check if transfer is not high speed and connected to root hub.
1263 * It should not happened but... */
1264 if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH)
1265 && !transfer->dev->hubaddr)
1266 {
1267 grub_error (GRUB_USB_ERR_BADDEVICE,
1268 "FULL/LOW speed device on EHCI port!?!");
1269 return GRUB_USB_ERR_BADDEVICE;
1270 }
1271
1272 /* Allocate memory for controller transfer data. */
1273 cdata = grub_malloc (sizeof (*cdata));
1274 if (!cdata)
1275 return GRUB_USB_ERR_INTERNAL;
1276 cdata->td_first_virt = NULL;
1277
1278 /* Allocate a queue head for the transfer queue. */
1279 cdata->qh_virt = grub_ehci_find_qh (e, transfer);
1280 if (!cdata->qh_virt)
1281 {
1282 grub_free (cdata);
1283 return GRUB_USB_ERR_INTERNAL;
1284 }
1285
1286 /* To detect short packet we need some additional "alternate" TD,
1287 * allocate it first. */
1288 cdata->td_alt_virt = grub_ehci_alloc_td (e);
1289 if (!cdata->td_alt_virt)
1290 {
1291 grub_free (cdata);
1292 return GRUB_USB_ERR_INTERNAL;
1293 }
1294 /* Fill whole alternate TD by zeros (= inactive) and set
1295 * Terminate bits and Halt bit */
1296 grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td));
1297 cdata->td_alt_virt->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1298 cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1299 cdata->td_alt_virt->token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
1300
1301 /* Allocate appropriate number of TDs and set */
1302 for (i = 0; i < transfer->transcnt; i++)
1303 {
1304 grub_usb_transaction_t tr = &transfer->transactions[i];
1305
1306 td = grub_ehci_transaction (e, tr->pid, tr->toggle, tr->size,
1307 tr->data, cdata->td_alt_virt);
1308
1309 if (!td) /* de-allocate and free all */
1310 {
1311 grub_size_t actual = 0;
1312
1313 if (cdata->td_first_virt)
1314 grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual);
1315
1316 grub_free (cdata);
1317 return GRUB_USB_ERR_INTERNAL;
1318 }
1319
1320 /* Register new TD in cdata or previous TD */
1321 if (!cdata->td_first_virt)
1322 cdata->td_first_virt = td;
1323 else
1324 {
1325 td_prev->link_td = grub_dma_virt2phys (td, e->td_chunk);
1326 td_prev->next_td =
1327 grub_cpu_to_le32 (grub_dma_virt2phys (td, e->td_chunk));
1328 }
1329 td_prev = td;
1330 }
1331
1332 /* Remember last TD */
1333 cdata->td_last_virt = td;
1334 cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk);
1335 /* Last TD should not have set alternate TD */
1336 cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1337
1338 grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n",
1339 cdata,cdata->qh_virt);
1340 grub_dprintf ("ehci", "setup_transfer: td_first=%p, td_alt=%p\n",
1341 cdata->td_first_virt,
1342 cdata->td_alt_virt);
1343 grub_dprintf ("ehci", "setup_transfer: td_last=%p\n",
1344 cdata->td_last_virt);
1345
1346 /* Start transfer: */
1347 /* Unlink possible alternate pointer in QH */
1348 cdata->qh_virt->td_overlay.alt_next_td =
1349 grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
1350 /* Link new TDs with QH via next_td */
1351 cdata->qh_virt->td_overlay.next_td =
1352 grub_cpu_to_le32 (grub_dma_virt2phys
1353 (cdata->td_first_virt, e->td_chunk));
1354 /* Reset Active and Halted bits in QH to activate Advance Queue,
1355 * i.e. reset token */
1356 cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0);
1357
1358 /* Finito */
1359 transfer->controller_data = cdata;
1360
1361 return GRUB_USB_ERR_NONE;
1362 }
1363
1364 /* This function expects QH is not active.
1365 * Function set Halt bit in QH TD overlay and possibly prints
1366 * necessary debug information. */
1367 static void
1368 grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer)
1369 {
1370 struct grub_ehci_transfer_controller_data *cdata =
1371 transfer->controller_data;
1372
1373 /* Collect debug data here if necessary */
1374
1375 /* Set Halt bit in not active QH. AL will not attempt to do
1376 * Advance Queue on QH with Halt bit set, i.e., we can then
1377 * safely manipulate with QH TD part. */
1378 cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token
1379 |
1380 grub_cpu_to_le32
1381 (GRUB_EHCI_STATUS_HALTED)) &
1382 grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE);
1383
1384 /* Print debug data here if necessary */
1385
1386 }
1387
1388 static grub_usb_err_t
1389 grub_ehci_parse_notrun (grub_usb_controller_t dev,
1390 grub_usb_transfer_t transfer, grub_size_t * actual)
1391 {
1392 struct grub_ehci *e = dev->data;
1393 struct grub_ehci_transfer_controller_data *cdata =
1394 transfer->controller_data;
1395
1396 grub_dprintf ("ehci", "parse_notrun: info\n");
1397
1398 /* QH can be in any state in this case. */
1399 /* But EHCI or AL is not running, so QH is surely not active
1400 * even if it has Active bit set... */
1401 grub_ehci_pre_finish_transfer (transfer);
1402 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1403 grub_ehci_free_td (e, cdata->td_alt_virt);
1404 grub_free (cdata);
1405
1406 /* Additionally, do something with EHCI to make it running (what?) */
1407 /* Try enable EHCI and AL */
1408 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1409 GRUB_EHCI_CMD_RUNSTOP | GRUB_EHCI_CMD_AS_ENABL
1410 | GRUB_EHCI_CMD_PS_ENABL
1411 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1412 /* Ensure command is written */
1413 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
1414
1415 return GRUB_USB_ERR_UNRECOVERABLE;
1416 }
1417
1418 static grub_usb_err_t
1419 grub_ehci_parse_halt (grub_usb_controller_t dev,
1420 grub_usb_transfer_t transfer, grub_size_t * actual)
1421 {
1422 struct grub_ehci *e = dev->data;
1423 struct grub_ehci_transfer_controller_data *cdata =
1424 transfer->controller_data;
1425 grub_uint32_t token;
1426 grub_usb_err_t err = GRUB_USB_ERR_NAK;
1427
1428 /* QH should be halted and not active in this case. */
1429
1430 grub_dprintf ("ehci", "parse_halt: info\n");
1431
1432 /* Remember token before call pre-finish function */
1433 token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token);
1434
1435 /* Do things like in normal finish */
1436 grub_ehci_pre_finish_transfer (transfer);
1437 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1438 grub_ehci_free_td (e, cdata->td_alt_virt);
1439 grub_free (cdata);
1440
1441 /* Evaluation of error code - currently we don't have GRUB USB error
1442 * codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
1443 * Order of evaluation is critical, specially bubble/stall. */
1444 if ((token & GRUB_EHCI_STATUS_BABBLE) != 0)
1445 err = GRUB_USB_ERR_BABBLE;
1446 else if ((token & GRUB_EHCI_CERR_MASK) != 0)
1447 err = GRUB_USB_ERR_STALL;
1448 else if ((token & GRUB_EHCI_STATUS_TRANERR) != 0)
1449 err = GRUB_USB_ERR_DATA;
1450 else if ((token & GRUB_EHCI_STATUS_BUFERR) != 0)
1451 err = GRUB_USB_ERR_DATA;
1452 else if ((token & GRUB_EHCI_STATUS_MISSDMF) != 0)
1453 err = GRUB_USB_ERR_DATA;
1454
1455 return err;
1456 }
1457
1458 static grub_usb_err_t
1459 grub_ehci_parse_success (grub_usb_controller_t dev,
1460 grub_usb_transfer_t transfer, grub_size_t * actual)
1461 {
1462 struct grub_ehci *e = dev->data;
1463 struct grub_ehci_transfer_controller_data *cdata =
1464 transfer->controller_data;
1465
1466 grub_dprintf ("ehci", "parse_success: info\n");
1467
1468 /* QH should be not active in this case, but it is not halted. */
1469 grub_ehci_pre_finish_transfer (transfer);
1470 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1471 grub_ehci_free_td (e, cdata->td_alt_virt);
1472 grub_free (cdata);
1473
1474 return GRUB_USB_ERR_NONE;
1475 }
1476
1477
1478 static grub_usb_err_t
1479 grub_ehci_check_transfer (grub_usb_controller_t dev,
1480 grub_usb_transfer_t transfer, grub_size_t * actual)
1481 {
1482 struct grub_ehci *e = dev->data;
1483 struct grub_ehci_transfer_controller_data *cdata =
1484 transfer->controller_data;
1485 grub_uint32_t token;
1486
1487 grub_dprintf ("ehci",
1488 "check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
1489 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
1490 cdata, cdata->qh_virt);
1491 grub_dprintf ("ehci", "check_transfer: qh_hptr=%08x, ep_char=%08x\n",
1492 grub_le_to_cpu32 (cdata->qh_virt->qh_hptr),
1493 grub_le_to_cpu32 (cdata->qh_virt->ep_char));
1494 grub_dprintf ("ehci", "check_transfer: ep_cap=%08x, td_current=%08x\n",
1495 grub_le_to_cpu32 (cdata->qh_virt->ep_cap),
1496 grub_le_to_cpu32 (cdata->qh_virt->td_current));
1497 grub_dprintf ("ehci", "check_transfer: next_td=%08x, alt_next_td=%08x\n",
1498 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td),
1499 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.alt_next_td));
1500 grub_dprintf ("ehci", "check_transfer: token=%08x, buffer[0]=%08x\n",
1501 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token),
1502 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.buffer_page[0]));
1503
1504 /* Check if EHCI is running and AL is enabled */
1505 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1506 & GRUB_EHCI_ST_HC_HALTED) != 0)
1507 return grub_ehci_parse_notrun (dev, transfer, actual);
1508 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1509 & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
1510 return grub_ehci_parse_notrun (dev, transfer, actual);
1511
1512 token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token);
1513
1514 /* Detect QH halted */
1515 if ((token & GRUB_EHCI_STATUS_HALTED) != 0)
1516 return grub_ehci_parse_halt (dev, transfer, actual);
1517
1518 /* Detect QH not active - QH is not active and no next TD */
1519 if ((token & GRUB_EHCI_STATUS_ACTIVE) == 0)
1520 {
1521 /* It could be finish at all or short packet condition */
1522 if ((grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td)
1523 & GRUB_EHCI_TERMINATE) &&
1524 ((grub_le_to_cpu32 (cdata->qh_virt->td_current)
1525 & GRUB_EHCI_QHTDPTR_MASK) == cdata->td_last_phys))
1526 /* Normal finish */
1527 return grub_ehci_parse_success (dev, transfer, actual);
1528 else if ((token & GRUB_EHCI_TOTAL_MASK) != 0)
1529 /* Short packet condition */
1530 /* But currently we don't handle it - higher level will do it */
1531 return grub_ehci_parse_success (dev, transfer, actual);
1532 }
1533
1534 return GRUB_USB_ERR_WAIT;
1535 }
1536
1537 static grub_usb_err_t
1538 grub_ehci_cancel_transfer (grub_usb_controller_t dev,
1539 grub_usb_transfer_t transfer)
1540 {
1541 struct grub_ehci *e = dev->data;
1542 struct grub_ehci_transfer_controller_data *cdata =
1543 transfer->controller_data;
1544 grub_size_t actual;
1545 int i;
1546 grub_uint64_t maxtime;
1547 grub_uint32_t qh_phys;
1548
1549 /* QH can be active and should be de-activated and halted */
1550
1551 grub_dprintf ("ehci", "cancel_transfer: begin\n");
1552
1553 /* First check if EHCI is running and AL is enabled and if not,
1554 * there is no problem... */
1555 if (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1556 & GRUB_EHCI_ST_HC_HALTED) != 0) ||
1557 ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1558 & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0))
1559 {
1560 grub_ehci_pre_finish_transfer (transfer);
1561 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
1562 grub_ehci_free_td (e, cdata->td_alt_virt);
1563 grub_free (cdata);
1564 grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
1565 return GRUB_USB_ERR_NONE;
1566 }
1567
1568 /* EHCI and AL are running. What to do?
1569 * Try to Halt QH via de-scheduling QH. */
1570 /* Find index of previous QH */
1571 qh_phys = grub_dma_virt2phys(cdata->qh_virt, e->qh_chunk);
1572 for (i = 0; i < GRUB_EHCI_N_QH; i++)
1573 {
1574 if ((e->qh_virt[i].qh_hptr & GRUB_EHCI_QHTDPTR_MASK) == qh_phys)
1575 break;
1576 }
1577 if (i == GRUB_EHCI_N_QH)
1578 {
1579 grub_printf ("%s: prev not found, queues are corrupt\n", __func__);
1580 return GRUB_USB_ERR_UNRECOVERABLE;
1581 }
1582 /* Unlink QH from AL */
1583 e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
1584
1585 /* If this is an interrupt transfer, we just wait for the periodic
1586 * schedule to advance a few times and then assume that the EHCI
1587 * controller has read the updated QH. */
1588 if (cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK)
1589 {
1590 grub_millisleep(20);
1591 }
1592 else
1593 {
1594 /* For the asynchronous schedule we use the advance doorbell to find
1595 * out when the EHCI controller has read the updated QH. */
1596
1597 /* Ring the doorbell */
1598 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1599 GRUB_EHCI_CMD_AS_ADV_D
1600 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1601 /* Ensure command is written */
1602 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
1603 /* Wait answer with timeout */
1604 maxtime = grub_get_time_ms () + 2;
1605 while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1606 & GRUB_EHCI_ST_AS_ADVANCE) == 0)
1607 && (grub_get_time_ms () < maxtime));
1608
1609 /* We do not detect the timeout because if timeout occurs, it most
1610 * probably means something wrong with EHCI - maybe stopped etc. */
1611
1612 /* Shut up the doorbell */
1613 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1614 ~GRUB_EHCI_CMD_AS_ADV_D
1615 & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1616 grub_ehci_oper_write32 (e, GRUB_EHCI_STATUS,
1617 GRUB_EHCI_ST_AS_ADVANCE
1618 | grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1619 /* Ensure command is written */
1620 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
1621 }
1622
1623 /* Now is QH out of AL and we can do anything with it... */
1624 grub_ehci_pre_finish_transfer (transfer);
1625 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
1626 grub_ehci_free_td (e, cdata->td_alt_virt);
1627
1628 /* FIXME Putting the QH back on the list should work, but for some
1629 * strange reason doing that will affect other QHs on the periodic
1630 * list. So free the QH instead of putting it back on the list
1631 * which does seem to work, but I would like to know why. */
1632
1633 #if 0
1634 /* Finaly we should return QH back to the AL... */
1635 e->qh_virt[i].qh_hptr =
1636 grub_cpu_to_le32 (grub_dma_virt2phys
1637 (cdata->qh_virt, e->qh_chunk));
1638 #else
1639 /* Free the QH */
1640 cdata->qh_virt->ep_char = 0;
1641 cdata->qh_virt->qh_hptr =
1642 grub_cpu_to_le32 ((grub_dma_virt2phys (cdata->qh_virt,
1643 e->qh_chunk)
1644 & GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
1645 #endif
1646
1647 grub_free (cdata);
1648
1649 grub_dprintf ("ehci", "cancel_transfer: end\n");
1650
1651 return GRUB_USB_ERR_NONE;
1652 }
1653
1654 static int
1655 grub_ehci_hubports (grub_usb_controller_t dev)
1656 {
1657 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1658 grub_uint32_t portinfo;
1659
1660 portinfo = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1661 & GRUB_EHCI_SPARAMS_N_PORTS;
1662 grub_dprintf ("ehci", "root hub ports=%d\n", portinfo);
1663 return portinfo;
1664 }
1665
1666 static grub_err_t
1667 grub_ehci_portstatus (grub_usb_controller_t dev,
1668 unsigned int port, unsigned int enable)
1669 {
1670 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1671 grub_uint64_t endtime;
1672
1673 grub_dprintf ("ehci", "portstatus: EHCI STATUS: %08x\n",
1674 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1675 grub_dprintf ("ehci",
1676 "portstatus: begin, iobase=%p, port=%d, status=0x%02x\n",
1677 e->iobase, port, grub_ehci_port_read (e, port));
1678
1679 /* In any case we need to disable port:
1680 * - if enable==false - we should disable port
1681 * - if enable==true we will do the reset and the specification says
1682 * PortEnable should be FALSE in such case */
1683 /* Disable the port and wait for it. */
1684 grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_ENABLED);
1685 endtime = grub_get_time_ms () + 1000;
1686 while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED)
1687 if (grub_get_time_ms () > endtime)
1688 return grub_error (GRUB_ERR_IO, "portstatus: EHCI Timed out - disable");
1689
1690 if (!enable) /* We don't need reset port */
1691 {
1692 grub_dprintf ("ehci", "portstatus: Disabled.\n");
1693 grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n",
1694 grub_ehci_port_read (e, port));
1695 return GRUB_ERR_NONE;
1696 }
1697
1698 grub_dprintf ("ehci", "portstatus: enable\n");
1699
1700 /* Now we will do reset - if HIGH speed device connected, it will
1701 * result in Enabled state, otherwise port remains disabled. */
1702 /* Set RESET bit for 50ms */
1703 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_RESET);
1704 grub_millisleep (50);
1705
1706 /* Reset RESET bit and wait for the end of reset */
1707 grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_RESET);
1708 endtime = grub_get_time_ms () + 1000;
1709 while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_RESET)
1710 if (grub_get_time_ms () > endtime)
1711 return grub_error (GRUB_ERR_IO,
1712 "portstatus: EHCI Timed out - reset port");
1713 /* Remember "we did the reset" - needed by detect_dev */
1714 e->reset |= (1 << port);
1715 /* Test if port enabled, i.e. HIGH speed device connected */
1716 if ((grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED) != 0) /* yes! */
1717 {
1718 grub_dprintf ("ehci", "portstatus: Enabled!\n");
1719 /* "Reset recovery time" (USB spec.) */
1720 grub_millisleep (10);
1721 }
1722 else /* no... */
1723 {
1724 /* FULL speed device connected - change port ownership.
1725 * It results in disconnected state of this EHCI port. */
1726 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER);
1727 return GRUB_USB_ERR_BADDEVICE;
1728 }
1729
1730 /* XXX: Fix it! There is possible problem - we can say to calling
1731 * function that we lost device if it is FULL speed onlu via
1732 * return value <> GRUB_ERR_NONE. It (maybe) displays also error
1733 * message on screen - but this situation is not error, it is normal
1734 * state! */
1735
1736 grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n",
1737 grub_ehci_port_read (e, port));
1738
1739 return GRUB_ERR_NONE;
1740 }
1741
1742 static grub_usb_speed_t
1743 grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
1744 {
1745 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1746 grub_uint32_t status, line_state;
1747
1748 status = grub_ehci_port_read (e, port);
1749
1750 grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n",
1751 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1752 grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n",
1753 e->iobase, port, status);
1754
1755 /* Connect Status Change bit - it detects change of connection */
1756 if (status & GRUB_EHCI_PORT_CONNECT_CH)
1757 {
1758 *changed = 1;
1759 /* Reset bit Connect Status Change */
1760 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_CONNECT_CH);
1761 }
1762 else
1763 *changed = 0;
1764
1765 if (!(status & GRUB_EHCI_PORT_CONNECT))
1766 { /* We should reset related "reset" flag in not connected state */
1767 e->reset &= ~(1 << port);
1768 return GRUB_USB_SPEED_NONE;
1769 }
1770 /* Detected connected state, so we should return speed.
1771 * But we can detect only LOW speed device and only at connection
1772 * time when PortEnabled=FALSE. FULL / HIGH speed detection is made
1773 * later by EHCI-specific reset procedure.
1774 * Another thing - if detected speed is LOW at connection time,
1775 * we should change port ownership to companion controller.
1776 * So:
1777 * 1. If we detect connected and enabled and EHCI-owned port,
1778 * we can say it is HIGH speed.
1779 * 2. If we detect connected and not EHCI-owned port, we can say
1780 * NONE speed, because such devices are not handled by EHCI.
1781 * 3. If we detect connected, not enabled but reset port, we can say
1782 * NONE speed, because it means FULL device connected to port and
1783 * such devices are not handled by EHCI.
1784 * 4. If we detect connected, not enabled and not reset port, which
1785 * has line state != "K", we will say HIGH - it could be FULL or HIGH
1786 * device, we will see it later after end of EHCI-specific reset
1787 * procedure.
1788 * 5. If we detect connected, not enabled and not reset port, which
1789 * has line state == "K", we can say NONE speed, because LOW speed
1790 * device is connected and we should change port ownership. */
1791 if ((status & GRUB_EHCI_PORT_ENABLED) != 0) /* Port already enabled, return high speed. */
1792 return GRUB_USB_SPEED_HIGH;
1793 if ((status & GRUB_EHCI_PORT_OWNER) != 0) /* EHCI is not port owner */
1794 return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */
1795 if ((e->reset & (1 << port)) != 0) /* Port reset was done = FULL speed */
1796 return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */
1797 else /* Port connected but not enabled - test port speed. */
1798 {
1799 line_state = status & GRUB_EHCI_PORT_LINE_STAT;
1800 if (line_state != GRUB_EHCI_PORT_LINE_LOWSP)
1801 return GRUB_USB_SPEED_HIGH;
1802 /* Detected LOW speed device, we should change
1803 * port ownership.
1804 * XXX: Fix it!: There should be test if related companion
1805 * controler is available ! And what to do if it does not exist ? */
1806 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER);
1807 return GRUB_USB_SPEED_NONE; /* Ignore this port */
1808 /* Note: Reset of PORT_OWNER bit is done by EHCI HW when
1809 * device is really disconnected from port.
1810 * Don't do PORT_OWNER bit reset by SW when not connected signal
1811 * is detected in port register ! */
1812 }
1813 }
1814
1815 static void
1816 grub_ehci_inithw (void)
1817 {
1818 grub_pci_iterate (grub_ehci_pci_iter);
1819 }
1820
1821 static grub_err_t
1822 grub_ehci_restore_hw (void)
1823 {
1824 struct grub_ehci *e;
1825 grub_uint32_t n_ports;
1826 int i;
1827
1828 /* We should re-enable all EHCI HW similarly as on inithw */
1829 for (e = ehci; e; e = e->next)
1830 {
1831 /* Check if EHCI is halted and halt it if not */
1832 if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
1833 grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout");
1834
1835 /* Reset EHCI */
1836 if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
1837 grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout");
1838
1839 /* Setup some EHCI registers and enable EHCI */
1840 grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys);
1841 grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR,
1842 grub_dma_virt2phys (&e->qh_virt[1],
1843 e->qh_chunk));
1844 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1845 GRUB_EHCI_CMD_RUNSTOP |
1846 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1847
1848 /* Set ownership of root hub ports to EHCI */
1849 grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG,
1850 GRUB_EHCI_CF_EHCI_OWNER);
1851
1852 /* Enable asynchronous list */
1853 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1854 GRUB_EHCI_CMD_AS_ENABL
1855 | GRUB_EHCI_CMD_PS_ENABL
1856 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1857
1858 /* Now should be possible to power-up and enumerate ports etc. */
1859 if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1860 & GRUB_EHCI_SPARAMS_PPC) != 0)
1861 { /* EHCI has port powering control */
1862 /* Power on all ports */
1863 n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1864 & GRUB_EHCI_SPARAMS_N_PORTS;
1865 for (i = 0; i < (int) n_ports; i++)
1866 grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4,
1867 GRUB_EHCI_PORT_POWER
1868 | grub_ehci_oper_read32 (e,
1869 GRUB_EHCI_PORT_STAT_CMD
1870 + i * 4));
1871 }
1872 }
1873
1874 return GRUB_USB_ERR_NONE;
1875 }
1876
1877 static grub_err_t
1878 grub_ehci_fini_hw (int noreturn __attribute__ ((unused)))
1879 {
1880 struct grub_ehci *e;
1881
1882 /* We should disable all EHCI HW to prevent any DMA access etc. */
1883 for (e = ehci; e; e = e->next)
1884 {
1885 /* Check if EHCI is halted and halt it if not */
1886 if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
1887 grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout");
1888
1889 /* Reset EHCI */
1890 if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
1891 grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout");
1892 }
1893
1894 return GRUB_USB_ERR_NONE;
1895 }
1896
1897 static struct grub_usb_controller_dev usb_controller = {
1898 .name = "ehci",
1899 .iterate = grub_ehci_iterate,
1900 .setup_transfer = grub_ehci_setup_transfer,
1901 .check_transfer = grub_ehci_check_transfer,
1902 .cancel_transfer = grub_ehci_cancel_transfer,
1903 .hubports = grub_ehci_hubports,
1904 .portstatus = grub_ehci_portstatus,
1905 .detect_dev = grub_ehci_detect_dev
1906 };
1907
1908 GRUB_MOD_INIT (ehci)
1909 {
1910 COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64);
1911 COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96);
1912 grub_ehci_inithw ();
1913 grub_usb_controller_dev_register (&usb_controller);
1914 grub_loader_register_preboot_hook (grub_ehci_fini_hw, grub_ehci_restore_hw,
1915 GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
1916 }
1917
1918 GRUB_MOD_FINI (ehci)
1919 {
1920 grub_ehci_fini_hw (0);
1921 grub_usb_controller_dev_unregister (&usb_controller);
1922 }