Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / bus / usb / ehci.c
blob8ece40086ec9a88ac2e8510c947f8688fd63e46a
1 /* ehci.c - EHCI Support. */
2 /*
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/>.
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 #include <grub/disk.h>
33 GRUB_MOD_LICENSE ("GPLv3+");
35 /* This simple GRUB implementation of EHCI driver:
36 * - assumes no IRQ
37 * - is not supporting isochronous transfers (iTD, siTD)
38 * - is not supporting interrupt transfers
41 #define GRUB_EHCI_PCI_SBRN_REG 0x60
43 /* Capability registers offsets */
44 enum
46 GRUB_EHCI_EHCC_CAPLEN = 0x00, /* byte */
47 GRUB_EHCI_EHCC_VERSION = 0x02, /* word */
48 GRUB_EHCI_EHCC_SPARAMS = 0x04, /* dword */
49 GRUB_EHCI_EHCC_CPARAMS = 0x08, /* dword */
50 GRUB_EHCI_EHCC_PROUTE = 0x0c, /* 60 bits */
53 #define GRUB_EHCI_EECP_MASK (0xff << 8)
54 #define GRUB_EHCI_EECP_SHIFT 8
56 #define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
57 #define GRUB_EHCI_POINTER_MASK (~0x1f)
59 /* Capability register SPARAMS bits */
60 enum
62 GRUB_EHCI_SPARAMS_N_PORTS = (0xf << 0),
63 GRUB_EHCI_SPARAMS_PPC = (1 << 4), /* Power port control */
64 GRUB_EHCI_SPARAMS_PRR = (1 << 7), /* Port routing rules */
65 GRUB_EHCI_SPARAMS_N_PCC = (0xf << 8), /* No of ports per comp. */
66 GRUB_EHCI_SPARAMS_NCC = (0xf << 12), /* No of com. controllers */
67 GRUB_EHCI_SPARAMS_P_IND = (1 << 16), /* Port indicators present */
68 GRUB_EHCI_SPARAMS_DEBUG_P = (0xf << 20) /* Debug port */
71 #define GRUB_EHCI_MAX_N_PORTS 15 /* Max. number of ports */
73 /* Capability register CPARAMS bits */
74 enum
76 GRUB_EHCI_CPARAMS_64BIT = (1 << 0),
77 GRUB_EHCI_CPARAMS_PROG_FRAMELIST = (1 << 1),
78 GRUB_EHCI_CPARAMS_PARK_CAP = (1 << 2)
81 #define GRUB_EHCI_N_FRAMELIST 1024
82 #define GRUB_EHCI_N_QH 256
83 #define GRUB_EHCI_N_TD 640
85 #define GRUB_EHCI_QH_EMPTY 1
87 /* USBLEGSUP bits and related OS OWNED byte offset */
88 enum
90 GRUB_EHCI_BIOS_OWNED = (1 << 16),
91 GRUB_EHCI_OS_OWNED = (1 << 24)
94 /* Operational registers offsets */
95 enum
97 GRUB_EHCI_COMMAND = 0x00,
98 GRUB_EHCI_STATUS = 0x04,
99 GRUB_EHCI_INTERRUPT = 0x08,
100 GRUB_EHCI_FRAME_INDEX = 0x0c,
101 GRUB_EHCI_64BIT_SEL = 0x10,
102 GRUB_EHCI_FL_BASE = 0x14,
103 GRUB_EHCI_CUR_AL_ADDR = 0x18,
104 GRUB_EHCI_CONFIG_FLAG = 0x40,
105 GRUB_EHCI_PORT_STAT_CMD = 0x44
108 /* Operational register COMMAND bits */
109 enum
111 GRUB_EHCI_CMD_RUNSTOP = (1 << 0),
112 GRUB_EHCI_CMD_HC_RESET = (1 << 1),
113 GRUB_EHCI_CMD_FL_SIZE = (3 << 2),
114 GRUB_EHCI_CMD_PS_ENABL = (1 << 4),
115 GRUB_EHCI_CMD_AS_ENABL = (1 << 5),
116 GRUB_EHCI_CMD_AS_ADV_D = (1 << 6),
117 GRUB_EHCI_CMD_L_HC_RES = (1 << 7),
118 GRUB_EHCI_CMD_AS_PARKM = (3 << 8),
119 GRUB_EHCI_CMD_AS_PARKE = (1 << 11),
120 GRUB_EHCI_CMD_INT_THRS = (0xff << 16)
123 /* Operational register STATUS bits */
124 enum
126 GRUB_EHCI_ST_INTERRUPT = (1 << 0),
127 GRUB_EHCI_ST_ERROR_INT = (1 << 1),
128 GRUB_EHCI_ST_PORT_CHG = (1 << 2),
129 GRUB_EHCI_ST_FL_ROLLOVR = (1 << 3),
130 GRUB_EHCI_ST_HS_ERROR = (1 << 4),
131 GRUB_EHCI_ST_AS_ADVANCE = (1 << 5),
132 GRUB_EHCI_ST_HC_HALTED = (1 << 12),
133 GRUB_EHCI_ST_RECLAM = (1 << 13),
134 GRUB_EHCI_ST_PS_STATUS = (1 << 14),
135 GRUB_EHCI_ST_AS_STATUS = (1 << 15)
138 /* Operational register PORT_STAT_CMD bits */
139 enum
141 GRUB_EHCI_PORT_CONNECT = (1 << 0),
142 GRUB_EHCI_PORT_CONNECT_CH = (1 << 1),
143 GRUB_EHCI_PORT_ENABLED = (1 << 2),
144 GRUB_EHCI_PORT_ENABLED_CH = (1 << 3),
145 GRUB_EHCI_PORT_OVERCUR = (1 << 4),
146 GRUB_EHCI_PORT_OVERCUR_CH = (1 << 5),
147 GRUB_EHCI_PORT_RESUME = (1 << 6),
148 GRUB_EHCI_PORT_SUSPEND = (1 << 7),
149 GRUB_EHCI_PORT_RESET = (1 << 8),
150 GRUB_EHCI_PORT_LINE_STAT = (3 << 10),
151 GRUB_EHCI_PORT_POWER = (1 << 12),
152 GRUB_EHCI_PORT_OWNER = (1 << 13),
153 GRUB_EHCI_PORT_INDICATOR = (3 << 14),
154 GRUB_EHCI_PORT_TEST = (0xf << 16),
155 GRUB_EHCI_PORT_WON_CONN_E = (1 << 20),
156 GRUB_EHCI_PORT_WON_DISC_E = (1 << 21),
157 GRUB_EHCI_PORT_WON_OVER_E = (1 << 22),
159 GRUB_EHCI_PORT_LINE_SE0 = (0 << 10),
160 GRUB_EHCI_PORT_LINE_K = (1 << 10),
161 GRUB_EHCI_PORT_LINE_J = (2 << 10),
162 GRUB_EHCI_PORT_LINE_UNDEF = (3 << 10),
163 GRUB_EHCI_PORT_LINE_LOWSP = GRUB_EHCI_PORT_LINE_K, /* K state means low speed */
164 GRUB_EHCI_PORT_WMASK = ~(GRUB_EHCI_PORT_CONNECT_CH
165 | GRUB_EHCI_PORT_ENABLED_CH
166 | GRUB_EHCI_PORT_OVERCUR_CH)
169 /* Operational register CONFIGFLAGS bits */
170 enum
172 GRUB_EHCI_CF_EHCI_OWNER = (1 << 0)
175 /* Queue Head & Transfer Descriptor constants */
176 #define GRUB_EHCI_HPTR_OFF 5 /* Horiz. pointer bit offset */
177 enum
179 GRUB_EHCI_HPTR_TYPE_MASK = (3 << 1),
180 GRUB_EHCI_HPTR_TYPE_ITD = (0 << 1),
181 GRUB_EHCI_HPTR_TYPE_QH = (1 << 1),
182 GRUB_EHCI_HPTR_TYPE_SITD = (2 << 1),
183 GRUB_EHCI_HPTR_TYPE_FSTN = (3 << 1)
186 enum
188 GRUB_EHCI_C = (1 << 27),
189 GRUB_EHCI_MAXPLEN_MASK = (0x7ff << 16),
190 GRUB_EHCI_H = (1 << 15),
191 GRUB_EHCI_DTC = (1 << 14),
192 GRUB_EHCI_SPEED_MASK = (3 << 12),
193 GRUB_EHCI_SPEED_FULL = (0 << 12),
194 GRUB_EHCI_SPEED_LOW = (1 << 12),
195 GRUB_EHCI_SPEED_HIGH = (2 << 12),
196 GRUB_EHCI_SPEED_RESERVED = (3 << 12),
197 GRUB_EHCI_EP_NUM_MASK = (0xf << 8),
198 GRUB_EHCI_DEVADDR_MASK = 0x7f,
199 GRUB_EHCI_TARGET_MASK = (GRUB_EHCI_EP_NUM_MASK | GRUB_EHCI_DEVADDR_MASK)
202 enum
204 GRUB_EHCI_MAXPLEN_OFF = 16,
205 GRUB_EHCI_SPEED_OFF = 12,
206 GRUB_EHCI_EP_NUM_OFF = 8
209 enum
211 GRUB_EHCI_MULT_MASK = (3 << 30),
212 GRUB_EHCI_MULT_RESERVED = (0 << 30),
213 GRUB_EHCI_MULT_ONE = (1 << 30),
214 GRUB_EHCI_MULT_TWO = (2 << 30),
215 GRUB_EHCI_MULT_THREE = (3 << 30),
216 GRUB_EHCI_DEVPORT_MASK = (0x7f << 23),
217 GRUB_EHCI_HUBADDR_MASK = (0x7f << 16),
218 GRUB_EHCI_CMASK_MASK = (0xff << 8),
219 GRUB_EHCI_SMASK_MASK = (0xff << 0),
222 enum
224 GRUB_EHCI_MULT_OFF = 30,
225 GRUB_EHCI_DEVPORT_OFF = 23,
226 GRUB_EHCI_HUBADDR_OFF = 16,
227 GRUB_EHCI_CMASK_OFF = 8,
228 GRUB_EHCI_SMASK_OFF = 0,
231 #define GRUB_EHCI_TERMINATE (1<<0)
233 #define GRUB_EHCI_TOGGLE (1<<31)
235 enum
237 GRUB_EHCI_TOTAL_MASK = (0x7fff << 16),
238 GRUB_EHCI_CERR_MASK = (3 << 10),
239 GRUB_EHCI_CERR_0 = (0 << 10),
240 GRUB_EHCI_CERR_1 = (1 << 10),
241 GRUB_EHCI_CERR_2 = (2 << 10),
242 GRUB_EHCI_CERR_3 = (3 << 10),
243 GRUB_EHCI_PIDCODE_OUT = (0 << 8),
244 GRUB_EHCI_PIDCODE_IN = (1 << 8),
245 GRUB_EHCI_PIDCODE_SETUP = (2 << 8),
246 GRUB_EHCI_STATUS_MASK = 0xff,
247 GRUB_EHCI_STATUS_ACTIVE = (1 << 7),
248 GRUB_EHCI_STATUS_HALTED = (1 << 6),
249 GRUB_EHCI_STATUS_BUFERR = (1 << 5),
250 GRUB_EHCI_STATUS_BABBLE = (1 << 4),
251 GRUB_EHCI_STATUS_TRANERR = (1 << 3),
252 GRUB_EHCI_STATUS_MISSDMF = (1 << 2),
253 GRUB_EHCI_STATUS_SPLITST = (1 << 1),
254 GRUB_EHCI_STATUS_PINGERR = (1 << 0)
257 enum
259 GRUB_EHCI_TOTAL_OFF = 16,
260 GRUB_EHCI_CERR_OFF = 10
263 #define GRUB_EHCI_BUFPTR_MASK (0xfffff<<12)
264 #define GRUB_EHCI_QHTDPTR_MASK 0xffffffe0
266 #define GRUB_EHCI_TD_BUF_PAGES 5
268 #define GRUB_EHCI_BUFPAGELEN 0x1000
269 #define GRUB_EHCI_MAXBUFLEN 0x5000
271 struct grub_ehci_td;
272 struct grub_ehci_qh;
273 typedef volatile struct grub_ehci_td *grub_ehci_td_t;
274 typedef volatile struct grub_ehci_qh *grub_ehci_qh_t;
276 /* EHCI Isochronous Transfer Descriptor */
277 /* Currently not supported */
279 /* EHCI Split Transaction Isochronous Transfer Descriptor */
280 /* Currently not supported */
282 /* EHCI Queue Element Transfer Descriptor (qTD) */
283 /* Align to 32-byte boundaries */
284 struct grub_ehci_td
286 /* EHCI HW part */
287 grub_uint32_t next_td; /* Pointer to next qTD */
288 grub_uint32_t alt_next_td; /* Pointer to alternate next qTD */
289 grub_uint32_t token; /* Toggle, Len, Interrupt, Page, Error, PID, Status */
290 grub_uint32_t buffer_page[GRUB_EHCI_TD_BUF_PAGES]; /* Buffer pointer (+ cur. offset in page 0 */
291 /* 64-bits part */
292 grub_uint32_t buffer_page_high[GRUB_EHCI_TD_BUF_PAGES];
293 /* EHCI driver part */
294 grub_uint32_t link_td; /* pointer to next free/chained TD */
295 grub_uint32_t size;
296 grub_uint32_t pad[1]; /* padding to some multiple of 32 bytes */
299 /* EHCI Queue Head */
300 /* Align to 32-byte boundaries */
301 /* QH allocation is made in the similar/same way as in OHCI driver,
302 * because unlninking QH from the Asynchronous list is not so
303 * trivial as on UHCI (at least it is time consuming) */
304 struct grub_ehci_qh
306 /* EHCI HW part */
307 grub_uint32_t qh_hptr; /* Horiz. pointer & Terminate */
308 grub_uint32_t ep_char; /* EP characteristics */
309 grub_uint32_t ep_cap; /* EP capabilities */
310 grub_uint32_t td_current; /* current TD link pointer */
311 struct grub_ehci_td td_overlay; /* TD overlay area = 64 bytes */
312 /* EHCI driver part */
313 grub_uint32_t pad[4]; /* padding to some multiple of 32 bytes */
316 /* EHCI Periodic Frame Span Traversal Node */
317 /* Currently not supported */
319 struct grub_ehci
321 volatile grub_uint32_t *iobase_ehcc; /* Capability registers */
322 volatile grub_uint32_t *iobase; /* Operational registers */
323 struct grub_pci_dma_chunk *framelist_chunk; /* Currently not used */
324 volatile grub_uint32_t *framelist_virt;
325 grub_uint32_t framelist_phys;
326 struct grub_pci_dma_chunk *qh_chunk; /* GRUB_EHCI_N_QH Queue Heads */
327 grub_ehci_qh_t qh_virt;
328 grub_uint32_t qh_phys;
329 struct grub_pci_dma_chunk *td_chunk; /* GRUB_EHCI_N_TD Transfer Descriptors */
330 grub_ehci_td_t td_virt;
331 grub_uint32_t td_phys;
332 grub_ehci_td_t tdfree_virt; /* Free Transfer Descriptors */
333 int flag64;
334 grub_uint32_t reset; /* bits 1-15 are flags if port was reset from connected time or not */
335 struct grub_ehci *next;
338 static struct grub_ehci *ehci;
340 /* EHCC registers access functions */
341 static inline grub_uint32_t
342 grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
344 return
345 grub_le_to_cpu32 (*((volatile grub_uint32_t *) e->iobase_ehcc +
346 (addr / sizeof (grub_uint32_t))));
349 static inline grub_uint16_t
350 grub_ehci_ehcc_read16 (struct grub_ehci *e, grub_uint32_t addr)
352 return
353 grub_le_to_cpu16 (*((volatile grub_uint16_t *) e->iobase_ehcc +
354 (addr / sizeof (grub_uint16_t))));
357 static inline grub_uint8_t
358 grub_ehci_ehcc_read8 (struct grub_ehci *e, grub_uint32_t addr)
360 return *((volatile grub_uint8_t *) e->iobase_ehcc + addr);
363 /* Operational registers access functions */
364 static inline grub_uint32_t
365 grub_ehci_oper_read32 (struct grub_ehci *e, grub_uint32_t addr)
367 return
368 grub_le_to_cpu32 (*
369 ((volatile grub_uint32_t *) e->iobase +
370 (addr / sizeof (grub_uint32_t))));
373 static inline void
374 grub_ehci_oper_write32 (struct grub_ehci *e, grub_uint32_t addr,
375 grub_uint32_t value)
377 *((volatile grub_uint32_t *) e->iobase + (addr / sizeof (grub_uint32_t))) =
378 grub_cpu_to_le32 (value);
381 static inline grub_uint32_t
382 grub_ehci_port_read (struct grub_ehci *e, grub_uint32_t port)
384 return grub_ehci_oper_read32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4);
387 static inline void
388 grub_ehci_port_resbits (struct grub_ehci *e, grub_uint32_t port,
389 grub_uint32_t bits)
391 grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4,
392 grub_ehci_port_read (e,
393 port) & GRUB_EHCI_PORT_WMASK &
394 ~(bits));
395 grub_ehci_port_read (e, port);
398 static inline void
399 grub_ehci_port_setbits (struct grub_ehci *e, grub_uint32_t port,
400 grub_uint32_t bits)
402 grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4,
403 (grub_ehci_port_read (e, port) &
404 GRUB_EHCI_PORT_WMASK) | bits);
405 grub_ehci_port_read (e, port);
408 /* Halt if EHCI HC not halted */
409 static grub_usb_err_t
410 grub_ehci_halt (struct grub_ehci *e)
412 grub_uint64_t maxtime;
414 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & GRUB_EHCI_ST_HC_HALTED) == 0) /* EHCI is not halted */
416 /* Halt EHCI */
417 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
418 ~GRUB_EHCI_CMD_RUNSTOP
419 & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
420 /* Ensure command is written */
421 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
422 maxtime = grub_get_time_ms () + 1000; /* Fix: Should be 2ms ! */
423 while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
424 & GRUB_EHCI_ST_HC_HALTED) == 0)
425 && (grub_get_time_ms () < maxtime));
426 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
427 & GRUB_EHCI_ST_HC_HALTED) == 0)
428 return GRUB_USB_ERR_TIMEOUT;
431 return GRUB_USB_ERR_NONE;
434 /* EHCI HC reset */
435 static grub_usb_err_t
436 grub_ehci_reset (struct grub_ehci *e)
438 grub_uint64_t maxtime;
440 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
441 GRUB_EHCI_CMD_HC_RESET
442 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
443 /* Ensure command is written */
444 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
445 /* XXX: How long time could take reset of HC ? */
446 maxtime = grub_get_time_ms () + 1000;
447 while (((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)
448 & GRUB_EHCI_CMD_HC_RESET) != 0)
449 && (grub_get_time_ms () < maxtime));
450 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)
451 & GRUB_EHCI_CMD_HC_RESET) != 0)
452 return GRUB_USB_ERR_TIMEOUT;
454 return GRUB_USB_ERR_NONE;
457 /* PCI iteration function... */
458 static int
459 grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
460 void *data __attribute__ ((unused)))
462 grub_uint8_t release;
463 grub_uint32_t class_code;
464 grub_uint32_t interf;
465 grub_uint32_t subclass;
466 grub_uint32_t class;
467 grub_uint32_t base, base_h;
468 struct grub_ehci *e;
469 grub_uint32_t eecp_offset;
470 grub_uint32_t fp;
471 int i;
472 grub_uint32_t usblegsup = 0;
473 grub_uint64_t maxtime;
474 grub_uint32_t n_ports;
475 grub_uint8_t caplen;
477 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
479 if (pciid == GRUB_CS5536_PCIID)
481 grub_uint64_t basereg;
483 basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
484 if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
486 /* Shouldn't happen. */
487 grub_dprintf ("ehci", "No EHCI address is assigned\n");
488 return 0;
490 base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
491 basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
492 basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
493 basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
494 basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
495 grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
497 else
499 grub_pci_address_t addr;
500 addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
501 class_code = grub_pci_read (addr) >> 8;
502 interf = class_code & 0xFF;
503 subclass = (class_code >> 8) & 0xFF;
504 class = class_code >> 16;
506 /* If this is not an EHCI controller, just return. */
507 if (class != 0x0c || subclass != 0x03 || interf != 0x20)
508 return 0;
510 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
512 /* Check Serial Bus Release Number */
513 addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
514 release = grub_pci_read_byte (addr);
515 if (release != 0x20)
517 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
518 release);
519 return 0;
521 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
523 /* Determine EHCI EHCC registers base address. */
524 addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
525 base = grub_pci_read (addr);
526 addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
527 base_h = grub_pci_read (addr);
528 /* Stop if registers are mapped above 4G - GRUB does not currently
529 * work with registers mapped above 4G */
530 if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
531 && (base_h != 0))
533 grub_dprintf ("ehci",
534 "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
535 return 0;
537 base &= GRUB_PCI_ADDR_MEM_MASK;
538 if (!base)
540 grub_dprintf ("ehci",
541 "EHCI: EHCI is not mapped\n");
542 return 0;
545 /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
546 addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
547 grub_pci_write_word(addr,
548 GRUB_PCI_COMMAND_MEM_ENABLED
549 | GRUB_PCI_COMMAND_BUS_MASTER
550 | grub_pci_read_word(addr));
552 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
555 /* Allocate memory for the controller and fill basic values. */
556 e = grub_zalloc (sizeof (*e));
557 if (!e)
558 return 1;
559 e->framelist_chunk = NULL;
560 e->td_chunk = NULL;
561 e->qh_chunk = NULL;
562 e->iobase_ehcc = grub_pci_device_map_range (dev,
563 (base & GRUB_EHCI_ADDR_MEM_MASK),
564 0x100);
566 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
567 (base & GRUB_EHCI_ADDR_MEM_MASK));
568 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n",
569 grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
570 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n",
571 grub_ehci_ehcc_read16 (e, GRUB_EHCI_EHCC_VERSION));
572 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: SPARAMS: %08x\n",
573 grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS));
574 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CPARAMS: %08x\n",
575 grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS));
577 /* Determine base address of EHCI operational registers */
578 caplen = grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN);
579 #ifndef GRUB_HAVE_UNALIGNED_ACCESS
580 if (caplen & (sizeof (grub_uint32_t) - 1))
582 grub_dprintf ("ehci", "Unaligned caplen\n");
583 return 0;
585 e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
586 + (caplen / sizeof (grub_uint32_t)));
587 #else
588 e->iobase = (volatile grub_uint32_t *)
589 ((grub_uint8_t *) e->iobase_ehcc + caplen);
590 #endif
592 grub_dprintf ("ehci",
593 "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
594 (base & GRUB_EHCI_ADDR_MEM_MASK) + caplen);
595 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
596 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
597 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
598 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
599 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n",
600 grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT));
601 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n",
602 grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX));
603 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n",
604 grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE));
605 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n",
606 grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR));
607 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
608 grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
610 /* Is there EECP ? */
611 eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
612 & GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT;
614 /* Check format of data structures requested by EHCI */
615 /* XXX: In fact it is not used at any place, it is prepared for future
616 * This implementation uses 32-bits pointers only */
617 e->flag64 = ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
618 & GRUB_EHCI_CPARAMS_64BIT) != 0);
620 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: flag64=%d\n", e->flag64);
622 /* Reserve a page for the frame list - it is accurate for max.
623 * possible size of framelist. But currently it is not used. */
624 e->framelist_chunk = grub_memalign_dma32 (4096, 4096);
625 if (!e->framelist_chunk)
626 goto fail;
627 e->framelist_virt = grub_dma_get_virt (e->framelist_chunk);
628 e->framelist_phys = grub_dma_get_phys (e->framelist_chunk);
629 grub_memset ((void *) e->framelist_virt, 0, 4096);
631 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: framelist mem=%p. OK\n",
632 e->framelist_virt);
634 /* Allocate memory for the QHs and register it in "e". */
635 e->qh_chunk = grub_memalign_dma32 (4096,
636 sizeof (struct grub_ehci_qh) *
637 GRUB_EHCI_N_QH);
638 if (!e->qh_chunk)
639 goto fail;
640 e->qh_virt = (grub_ehci_qh_t) grub_dma_get_virt (e->qh_chunk);
641 e->qh_phys = grub_dma_get_phys (e->qh_chunk);
642 grub_memset ((void *) e->qh_virt, 0,
643 sizeof (struct grub_ehci_qh) * GRUB_EHCI_N_QH);
645 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH mem=%p. OK\n",
646 e->qh_virt);
648 /* Allocate memory for the TDs and register it in "e". */
649 e->td_chunk = grub_memalign_dma32 (4096,
650 sizeof (struct grub_ehci_td) *
651 GRUB_EHCI_N_TD);
652 if (!e->td_chunk)
653 goto fail;
654 e->td_virt = (grub_ehci_td_t) grub_dma_get_virt (e->td_chunk);
655 e->td_phys = grub_dma_get_phys (e->td_chunk);
656 grub_memset ((void *) e->td_virt, 0,
657 sizeof (struct grub_ehci_td) * GRUB_EHCI_N_TD);
659 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: TD mem=%p. OK\n",
660 e->td_virt);
662 /* Setup all frame list pointers. Since no isochronous transfers
663 are supported, they all point to the (same!) queue
664 head with index 0. */
665 fp = grub_cpu_to_le32 ((e->qh_phys & GRUB_EHCI_POINTER_MASK)
666 | GRUB_EHCI_HPTR_TYPE_QH);
667 for (i = 0; i < GRUB_EHCI_N_FRAMELIST; i++)
668 e->framelist_virt[i] = fp;
669 /* Prepare chain of all TDs and set Terminate in all TDs */
670 for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++)
672 e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td);
673 e->td_virt[i].next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
674 e->td_virt[i].alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
676 e->td_virt[GRUB_EHCI_N_TD - 1].next_td =
677 grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
678 e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td =
679 grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
680 e->tdfree_virt = e->td_virt;
681 /* Set Terminate in first QH, which is used in framelist */
682 e->qh_virt[0].qh_hptr = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH);
683 e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
684 e->qh_virt[0].td_overlay.alt_next_td =
685 grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
686 /* Also set Halted bit in token */
687 e->qh_virt[0].td_overlay.token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
688 /* Set the H bit in first QH used for AL */
689 e->qh_virt[1].ep_char = grub_cpu_to_le32_compile_time (GRUB_EHCI_H);
690 /* Set Terminate into TD in rest of QHs and set horizontal link
691 * pointer to itself - these QHs will be used for asynchronous
692 * schedule and they should have valid value in horiz. link */
693 for (i = 1; i < GRUB_EHCI_N_QH; i++)
695 e->qh_virt[i].qh_hptr =
696 grub_cpu_to_le32 ((grub_dma_virt2phys (&e->qh_virt[i],
697 e->qh_chunk) &
698 GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
699 e->qh_virt[i].td_overlay.next_td =
700 grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
701 e->qh_virt[i].td_overlay.alt_next_td =
702 grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
703 /* Also set Halted bit in token */
704 e->qh_virt[i].td_overlay.token =
705 grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
708 /* Note: QH 0 and QH 1 are reserved and must not be used anywhere.
709 * QH 0 is used as empty QH for framelist
710 * QH 1 is used as starting empty QH for asynchronous schedule
711 * QH 1 must exist at any time because at least one QH linked to
712 * itself must exist in asynchronous schedule
713 * QH 1 has the H flag set to one */
715 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n");
717 /* Determine and change ownership. */
718 /* EECP offset valid in HCCPARAMS */
719 /* Ownership can be changed via EECP only */
720 if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
722 grub_pci_address_t pciaddr_eecp;
723 pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
725 usblegsup = grub_pci_read (pciaddr_eecp);
726 if (usblegsup & GRUB_EHCI_BIOS_OWNED)
728 grub_boot_time ("Taking ownership of EHCI controller");
729 grub_dprintf ("ehci",
730 "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
731 /* Ownership change - set OS_OWNED bit */
732 grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
733 /* Ensure PCI register is written */
734 grub_pci_read (pciaddr_eecp);
736 /* Wait for finish of ownership change, EHCI specification
737 * doesn't say how long it can take... */
738 maxtime = grub_get_time_ms () + 1000;
739 while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
740 && (grub_get_time_ms () < maxtime));
741 if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
743 grub_dprintf ("ehci",
744 "EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
745 /* Change ownership in "hard way" - reset BIOS ownership */
746 grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
747 /* Ensure PCI register is written */
748 grub_pci_read (pciaddr_eecp);
751 else if (usblegsup & GRUB_EHCI_OS_OWNED)
752 /* XXX: What to do in this case - nothing ? Can it happen ? */
753 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
754 else
756 grub_dprintf ("ehci",
757 "EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
758 /* XXX: What to do in this case ? Can it happen ?
759 * Is code below correct ? */
760 /* Ownership change - set OS_OWNED bit */
761 grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
762 /* Ensure PCI register is written */
763 grub_pci_read (pciaddr_eecp);
766 /* Disable SMI, just to be sure. */
767 pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
768 grub_pci_write (pciaddr_eecp, 0);
769 /* Ensure PCI register is written */
770 grub_pci_read (pciaddr_eecp);
774 grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
776 /* Now we can setup EHCI (maybe...) */
778 /* Check if EHCI is halted and halt it if not */
779 if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
781 grub_error (GRUB_ERR_TIMEOUT,
782 "EHCI grub_ehci_pci_iter: EHCI halt timeout");
783 goto fail;
786 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: halted OK\n");
788 /* Reset EHCI */
789 if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
791 grub_error (GRUB_ERR_TIMEOUT,
792 "EHCI grub_ehci_pci_iter: EHCI reset timeout");
793 goto fail;
796 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: reset OK\n");
798 /* Setup list address registers */
799 grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys);
800 grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR,
801 grub_dma_virt2phys (&e->qh_virt[1],
802 e->qh_chunk));
804 /* Set ownership of root hub ports to EHCI */
805 grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG, GRUB_EHCI_CF_EHCI_OWNER);
807 /* Enable both lists */
808 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
809 GRUB_EHCI_CMD_AS_ENABL
810 | GRUB_EHCI_CMD_PS_ENABL
811 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
813 /* Now should be possible to power-up and enumerate ports etc. */
814 if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
815 & GRUB_EHCI_SPARAMS_PPC) != 0)
816 { /* EHCI has port powering control */
817 /* Power on all ports */
818 n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
819 & GRUB_EHCI_SPARAMS_N_PORTS;
820 for (i = 0; i < (int) n_ports; i++)
821 grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4,
822 GRUB_EHCI_PORT_POWER
823 | grub_ehci_oper_read32 (e,
824 GRUB_EHCI_PORT_STAT_CMD
825 + i * 4));
828 /* Ensure all commands are written */
829 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
831 /* Enable EHCI */
832 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
833 GRUB_EHCI_CMD_RUNSTOP
834 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
836 /* Ensure command is written */
837 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
839 /* Link to ehci now that initialisation is successful. */
840 e->next = ehci;
841 ehci = e;
843 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
845 grub_dprintf ("ehci",
846 "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
847 (base & GRUB_EHCI_ADDR_MEM_MASK));
848 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
849 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
850 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
851 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
852 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n",
853 grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT));
854 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n",
855 grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX));
856 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n",
857 grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE));
858 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n",
859 grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR));
860 grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
861 grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
863 return 0;
865 fail:
866 if (e)
868 if (e->td_chunk)
869 grub_dma_free ((void *) e->td_chunk);
870 if (e->qh_chunk)
871 grub_dma_free ((void *) e->qh_chunk);
872 if (e->framelist_chunk)
873 grub_dma_free (e->framelist_chunk);
875 grub_free (e);
877 return 0;
880 static int
881 grub_ehci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data)
883 struct grub_ehci *e;
884 struct grub_usb_controller dev;
886 for (e = ehci; e; e = e->next)
888 dev.data = e;
889 if (hook (&dev, hook_data))
890 return 1;
893 return 0;
896 static void
897 grub_ehci_setup_qh (grub_ehci_qh_t qh, grub_usb_transfer_t transfer)
899 grub_uint32_t ep_char = 0;
900 grub_uint32_t ep_cap = 0;
902 /* Note: Another part of code is responsible to this QH is
903 * Halted ! But it can be linked in AL, so we cannot erase or
904 * change qh_hptr ! */
905 /* We will not change any TD field because they should/must be
906 * in safe state from previous use. */
908 /* EP characteristic setup */
909 /* Currently not used NAK counter (RL=0),
910 * C bit set if EP is not HIGH speed and is control,
911 * Max Packet Length is taken from transfer structure,
912 * H bit = 0 (because QH[1] has this bit set),
913 * DTC bit set to 1 because we are using our own toggle bit control,
914 * SPEED is selected according to value from transfer structure,
915 * EP number is taken from transfer structure
916 * "I" bit must not be set,
917 * Device Address is taken from transfer structure
918 * */
919 if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH)
920 && (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL))
921 ep_char |= GRUB_EHCI_C;
922 ep_char |= (transfer->max << GRUB_EHCI_MAXPLEN_OFF)
923 & GRUB_EHCI_MAXPLEN_MASK;
924 ep_char |= GRUB_EHCI_DTC;
925 switch (transfer->dev->speed)
927 case GRUB_USB_SPEED_LOW:
928 ep_char |= GRUB_EHCI_SPEED_LOW;
929 break;
930 case GRUB_USB_SPEED_FULL:
931 ep_char |= GRUB_EHCI_SPEED_FULL;
932 break;
933 case GRUB_USB_SPEED_HIGH:
934 default:
935 ep_char |= GRUB_EHCI_SPEED_HIGH;
936 /* XXX: How we will handle unknown value of speed? */
938 ep_char |= (transfer->endpoint << GRUB_EHCI_EP_NUM_OFF)
939 & GRUB_EHCI_EP_NUM_MASK;
940 ep_char |= transfer->devaddr & GRUB_EHCI_DEVADDR_MASK;
941 qh->ep_char = grub_cpu_to_le32 (ep_char);
942 /* EP capabilities setup */
943 /* MULT field - we try to use max. number
944 * PortNumber - included now in device structure referenced
945 * inside transfer structure
946 * HubAddress - included now in device structure referenced
947 * inside transfer structure
948 * SplitCompletionMask - AFAIK it is ignored in asynchronous list,
949 * InterruptScheduleMask - AFAIK it should be zero in async. list */
950 ep_cap |= GRUB_EHCI_MULT_THREE;
951 ep_cap |= (transfer->dev->split_hubport << GRUB_EHCI_DEVPORT_OFF)
952 & GRUB_EHCI_DEVPORT_MASK;
953 ep_cap |= (transfer->dev->split_hubaddr << GRUB_EHCI_HUBADDR_OFF)
954 & GRUB_EHCI_HUBADDR_MASK;
955 if (transfer->dev->speed == GRUB_USB_SPEED_LOW
956 && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL)
958 ep_cap |= (1<<0) << GRUB_EHCI_SMASK_OFF;
959 ep_cap |= (7<<2) << GRUB_EHCI_CMASK_OFF;
961 qh->ep_cap = grub_cpu_to_le32 (ep_cap);
963 grub_dprintf ("ehci", "setup_qh: qh=%p, not changed: qh_hptr=%08x\n",
964 qh, grub_le_to_cpu32 (qh->qh_hptr));
965 grub_dprintf ("ehci", "setup_qh: ep_char=%08x, ep_cap=%08x\n",
966 ep_char, ep_cap);
967 grub_dprintf ("ehci", "setup_qh: end\n");
968 grub_dprintf ("ehci", "setup_qh: not changed: td_current=%08x\n",
969 grub_le_to_cpu32 (qh->td_current));
970 grub_dprintf ("ehci", "setup_qh: not changed: next_td=%08x\n",
971 grub_le_to_cpu32 (qh->td_overlay.next_td));
972 grub_dprintf ("ehci", "setup_qh: not changed: alt_next_td=%08x\n",
973 grub_le_to_cpu32 (qh->td_overlay.alt_next_td));
974 grub_dprintf ("ehci", "setup_qh: not changed: token=%08x\n",
975 grub_le_to_cpu32 (qh->td_overlay.token));
978 static grub_ehci_qh_t
979 grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
981 grub_uint32_t target, mask;
982 int i;
983 grub_ehci_qh_t qh = e->qh_virt;
984 grub_ehci_qh_t head;
985 grub_uint32_t qh_phys;
986 grub_uint32_t qh_terminate =
987 GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH;
988 grub_ehci_qh_t qh_iter;
990 /* Prepare part of EP Characteristic to find existing QH */
991 target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) |
992 transfer->devaddr) & GRUB_EHCI_TARGET_MASK;
993 target = grub_cpu_to_le32 (target);
994 mask = grub_cpu_to_le32_compile_time (GRUB_EHCI_TARGET_MASK);
996 /* low speed interrupt transfers are linked to the periodic */
997 /* schedule, everything else to the asynchronous schedule */
998 if (transfer->dev->speed == GRUB_USB_SPEED_LOW
999 && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL)
1000 head = &qh[0];
1001 else
1002 head = &qh[1];
1004 /* First try to find existing QH with proper target in proper list */
1005 qh_phys = grub_le_to_cpu32( head->qh_hptr );
1006 if (qh_phys != qh_terminate)
1007 qh_iter = grub_dma_phys2virt ( qh_phys & GRUB_EHCI_QHTDPTR_MASK,
1008 e->qh_chunk );
1009 else
1010 qh_iter = NULL;
1012 for (
1013 i = 0;
1014 (qh_phys != qh_terminate) && (qh_iter != NULL) &&
1015 (qh_iter != head) && (i < GRUB_EHCI_N_QH);
1016 i++ )
1018 if (target == (qh_iter->ep_char & mask))
1020 /* Found proper existing (and linked) QH, do setup of QH */
1021 grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
1022 grub_ehci_setup_qh (qh_iter, transfer);
1023 return qh_iter;
1026 qh_phys = grub_le_to_cpu32( qh_iter->qh_hptr );
1027 if (qh_phys != qh_terminate)
1028 qh_iter = grub_dma_phys2virt ( qh_phys & GRUB_EHCI_QHTDPTR_MASK,
1029 e->qh_chunk );
1030 else
1031 qh_iter = NULL;
1034 /* variable "i" should be never equal to GRUB_EHCI_N_QH here */
1035 if (i >= GRUB_EHCI_N_QH)
1036 { /* Something very bad happened in QH list(s) ! */
1037 grub_dprintf ("ehci", "find_qh: Mismatch in QH list! head=%p\n",
1038 head);
1041 /* QH with target_addr does not exist, we have to find and add it */
1042 for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */
1044 if (!qh[i].ep_char)
1045 break; /* Found first not-allocated QH, finish */
1048 /* Have we any free QH in array ? */
1049 if (i >= GRUB_EHCI_N_QH) /* No. */
1051 grub_dprintf ("ehci", "find_qh: end - no free QH\n");
1052 return NULL;
1054 grub_dprintf ("ehci", "find_qh: new, i=%d, QH=%p\n",
1055 i, &qh[i]);
1056 /* Currently we simply take next (current) QH in array, no allocation
1057 * function is used. It should be no problem until we will need to
1058 * de-allocate QHs of unplugged devices. */
1059 /* We should preset new QH and link it into AL */
1060 grub_ehci_setup_qh (&qh[i], transfer);
1062 /* Linking - this new (last) QH will copy the QH from the head QH */
1063 qh[i].qh_hptr = head->qh_hptr;
1064 /* Linking - the head QH will point to this new QH */
1065 head->qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_HPTR_TYPE_QH
1066 | grub_dma_virt2phys (&qh[i],
1067 e->qh_chunk));
1069 return &qh[i];
1072 static grub_ehci_td_t
1073 grub_ehci_alloc_td (struct grub_ehci *e)
1075 grub_ehci_td_t ret;
1077 /* Check if there is a Transfer Descriptor available. */
1078 if (!e->tdfree_virt)
1080 grub_dprintf ("ehci", "alloc_td: end - no free TD\n");
1081 return NULL;
1084 ret = e->tdfree_virt; /* Take current free TD */
1085 /* Advance to next free TD in chain */
1086 if (ret->link_td)
1087 e->tdfree_virt = grub_dma_phys2virt (ret->link_td, e->td_chunk);
1088 else
1089 e->tdfree_virt = NULL;
1090 ret->link_td = 0; /* Reset link_td in allocated TD */
1091 return ret;
1094 static void
1095 grub_ehci_free_td (struct grub_ehci *e, grub_ehci_td_t td)
1097 /* Chain new free TD & rest */
1098 if (e->tdfree_virt)
1099 td->link_td = grub_dma_virt2phys (e->tdfree_virt, e->td_chunk);
1100 else
1101 td->link_td = 0;
1102 e->tdfree_virt = td; /* Change address of first free TD */
1105 static void
1106 grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td,
1107 grub_usb_transfer_t transfer, grub_size_t * actual)
1109 int i; /* Index of TD in transfer */
1110 grub_uint32_t token, to_transfer;
1112 /* Note: Another part of code is responsible to this QH is
1113 * INACTIVE ! */
1114 *actual = 0;
1116 /* Free the TDs in this queue and set last_trans. */
1117 for (i = 0; td; i++)
1119 grub_ehci_td_t tdprev;
1121 token = grub_le_to_cpu32 (td->token);
1122 to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF;
1124 /* Check state of TD - if it did not transfered
1125 * whole data then set last_trans - it should be last executed TD
1126 * in case when something went wrong. */
1127 if (transfer && (td->size != to_transfer))
1128 transfer->last_trans = i;
1130 *actual += td->size - to_transfer;
1132 /* Unlink the TD */
1133 tdprev = td;
1134 if (td->link_td)
1135 td = grub_dma_phys2virt (td->link_td, e->td_chunk);
1136 else
1137 td = NULL;
1139 /* Free the TD. */
1140 grub_ehci_free_td (e, tdprev);
1143 /* Check if last_trans was set. If not and something was
1144 * transferred (it should be all data in this case), set it
1145 * to index of last TD, i.e. i-1 */
1146 if (transfer && (transfer->last_trans < 0) && (*actual != 0))
1147 transfer->last_trans = i - 1;
1149 /* XXX: Fix it: last_trans may be set to bad index.
1150 * Probably we should test more error flags to distinguish
1151 * if TD was at least partialy executed or not at all.
1152 * Generaly, we still could have problem with toggling because
1153 * EHCI can probably split transactions into smaller parts then
1154 * we defined in transaction even if we did not exceed MaxFrame
1155 * length - it probably could happen at the end of microframe (?)
1156 * and if the buffer is crossing page boundary (?). */
1159 static grub_ehci_td_t
1160 grub_ehci_transaction (struct grub_ehci *e,
1161 grub_transfer_type_t type,
1162 unsigned int toggle, grub_size_t size,
1163 grub_uint32_t data, grub_ehci_td_t td_alt)
1165 grub_ehci_td_t td;
1166 grub_uint32_t token;
1167 grub_uint32_t bufadr;
1168 int i;
1170 /* Test of transfer size, it can be:
1171 * <= GRUB_EHCI_MAXBUFLEN if data aligned to page boundary
1172 * <= GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN if not aligned
1173 * (worst case)
1175 if ((((data % GRUB_EHCI_BUFPAGELEN) == 0)
1176 && (size > GRUB_EHCI_MAXBUFLEN))
1178 (((data % GRUB_EHCI_BUFPAGELEN) != 0)
1179 && (size > (GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN))))
1181 grub_error (GRUB_ERR_OUT_OF_MEMORY,
1182 "too long data buffer for EHCI transaction");
1183 return 0;
1186 /* Grab a free Transfer Descriptor and initialize it. */
1187 td = grub_ehci_alloc_td (e);
1188 if (!td)
1190 grub_error (GRUB_ERR_OUT_OF_MEMORY,
1191 "no transfer descriptors available for EHCI transfer");
1192 return 0;
1195 grub_dprintf ("ehci",
1196 "transaction: type=%d, toggle=%d, size=%lu data=0x%x td=%p\n",
1197 type, toggle, (unsigned long) size, data, td);
1199 /* Fill whole TD by zeros */
1200 grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td));
1202 /* Don't point to any TD yet, just terminate. */
1203 td->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
1204 /* Set alternate pointer. When short packet occurs, alternate TD
1205 * will not be really fetched because it is not active. But don't
1206 * forget, EHCI will try to fetch alternate TD every scan of AL
1207 * until QH is halted. */
1208 td->alt_next_td = grub_cpu_to_le32 (grub_dma_virt2phys (td_alt,
1209 e->td_chunk));
1210 /* token:
1211 * TOGGLE - according to toggle
1212 * TOTAL SIZE = size
1213 * Interrupt On Complete = FALSE, we don't need IRQ
1214 * Current Page = 0
1215 * Error Counter = max. value = 3
1216 * PID Code - according to type
1217 * STATUS:
1218 * ACTIVE bit should be set to one
1219 * SPLIT TRANS. STATE bit should be zero. It is ignored
1220 * in HIGH speed transaction, and should be zero for LOW/FULL
1221 * speed to indicate state Do Split Transaction */
1222 token = toggle ? GRUB_EHCI_TOGGLE : 0;
1223 token |= (size << GRUB_EHCI_TOTAL_OFF) & GRUB_EHCI_TOTAL_MASK;
1224 token |= GRUB_EHCI_CERR_3;
1225 switch (type)
1227 case GRUB_USB_TRANSFER_TYPE_IN:
1228 token |= GRUB_EHCI_PIDCODE_IN;
1229 break;
1230 case GRUB_USB_TRANSFER_TYPE_OUT:
1231 token |= GRUB_EHCI_PIDCODE_OUT;
1232 break;
1233 case GRUB_USB_TRANSFER_TYPE_SETUP:
1234 token |= GRUB_EHCI_PIDCODE_SETUP;
1235 break;
1236 default: /* XXX: Should not happen, but what to do if it does ? */
1237 break;
1239 token |= GRUB_EHCI_STATUS_ACTIVE;
1240 td->token = grub_cpu_to_le32 (token);
1242 /* Fill buffer pointers according to size */
1243 bufadr = data;
1244 td->buffer_page[0] = grub_cpu_to_le32 (bufadr);
1245 bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN;
1246 for (i = 1; ((bufadr - data) < size) && (i < GRUB_EHCI_TD_BUF_PAGES); i++)
1248 td->buffer_page[i] = grub_cpu_to_le32 (bufadr & GRUB_EHCI_BUFPTR_MASK);
1249 bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN;
1252 /* Remember data size for future use... */
1253 td->size = (grub_uint32_t) size;
1255 grub_dprintf ("ehci", "td=%p\n", td);
1256 grub_dprintf ("ehci", "HW: next_td=%08x, alt_next_td=%08x\n",
1257 grub_le_to_cpu32 (td->next_td),
1258 grub_le_to_cpu32 (td->alt_next_td));
1259 grub_dprintf ("ehci", "HW: token=%08x, buffer[0]=%08x\n",
1260 grub_le_to_cpu32 (td->token),
1261 grub_le_to_cpu32 (td->buffer_page[0]));
1262 grub_dprintf ("ehci", "HW: buffer[1]=%08x, buffer[2]=%08x\n",
1263 grub_le_to_cpu32 (td->buffer_page[1]),
1264 grub_le_to_cpu32 (td->buffer_page[2]));
1265 grub_dprintf ("ehci", "HW: buffer[3]=%08x, buffer[4]=%08x\n",
1266 grub_le_to_cpu32 (td->buffer_page[3]),
1267 grub_le_to_cpu32 (td->buffer_page[4]));
1268 grub_dprintf ("ehci", "link_td=%08x, size=%08x\n",
1269 td->link_td, td->size);
1271 return td;
1274 struct grub_ehci_transfer_controller_data
1276 grub_ehci_qh_t qh_virt;
1277 grub_ehci_td_t td_first_virt;
1278 grub_ehci_td_t td_alt_virt;
1279 grub_ehci_td_t td_last_virt;
1280 grub_uint32_t td_last_phys;
1283 static grub_usb_err_t
1284 grub_ehci_setup_transfer (grub_usb_controller_t dev,
1285 grub_usb_transfer_t transfer)
1287 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1288 grub_ehci_td_t td = NULL;
1289 grub_ehci_td_t td_prev = NULL;
1290 int i;
1291 struct grub_ehci_transfer_controller_data *cdata;
1293 /* Check if EHCI is running and AL is enabled */
1294 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1295 & GRUB_EHCI_ST_HC_HALTED) != 0)
1296 /* XXX: Fix it: Currently we don't do anything to restart EHCI */
1297 return GRUB_USB_ERR_INTERNAL;
1298 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1299 & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
1300 /* XXX: Fix it: Currently we don't do anything to restart EHCI */
1301 return GRUB_USB_ERR_INTERNAL;
1303 /* Allocate memory for controller transfer data. */
1304 cdata = grub_malloc (sizeof (*cdata));
1305 if (!cdata)
1306 return GRUB_USB_ERR_INTERNAL;
1307 cdata->td_first_virt = NULL;
1309 /* Allocate a queue head for the transfer queue. */
1310 cdata->qh_virt = grub_ehci_find_qh (e, transfer);
1311 if (!cdata->qh_virt)
1313 grub_free (cdata);
1314 return GRUB_USB_ERR_INTERNAL;
1317 /* To detect short packet we need some additional "alternate" TD,
1318 * allocate it first. */
1319 cdata->td_alt_virt = grub_ehci_alloc_td (e);
1320 if (!cdata->td_alt_virt)
1322 grub_free (cdata);
1323 return GRUB_USB_ERR_INTERNAL;
1325 /* Fill whole alternate TD by zeros (= inactive) and set
1326 * Terminate bits and Halt bit */
1327 grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td));
1328 cdata->td_alt_virt->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
1329 cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
1330 cdata->td_alt_virt->token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
1332 /* Allocate appropriate number of TDs and set */
1333 for (i = 0; i < transfer->transcnt; i++)
1335 grub_usb_transaction_t tr = &transfer->transactions[i];
1337 td = grub_ehci_transaction (e, tr->pid, tr->toggle, tr->size,
1338 tr->data, cdata->td_alt_virt);
1340 if (!td) /* de-allocate and free all */
1342 grub_size_t actual = 0;
1344 if (cdata->td_first_virt)
1345 grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual);
1347 grub_free (cdata);
1348 return GRUB_USB_ERR_INTERNAL;
1351 /* Register new TD in cdata or previous TD */
1352 if (!cdata->td_first_virt)
1353 cdata->td_first_virt = td;
1354 else
1356 td_prev->link_td = grub_dma_virt2phys (td, e->td_chunk);
1357 td_prev->next_td =
1358 grub_cpu_to_le32 (grub_dma_virt2phys (td, e->td_chunk));
1360 td_prev = td;
1363 /* Remember last TD */
1364 cdata->td_last_virt = td;
1365 cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk);
1366 /* Last TD should not have set alternate TD */
1367 cdata->td_last_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
1369 grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n",
1370 cdata,cdata->qh_virt);
1371 grub_dprintf ("ehci", "setup_transfer: td_first=%p, td_alt=%p\n",
1372 cdata->td_first_virt,
1373 cdata->td_alt_virt);
1374 grub_dprintf ("ehci", "setup_transfer: td_last=%p\n",
1375 cdata->td_last_virt);
1377 /* Start transfer: */
1378 /* Unlink possible alternate pointer in QH */
1379 cdata->qh_virt->td_overlay.alt_next_td =
1380 grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
1381 /* Link new TDs with QH via next_td */
1382 cdata->qh_virt->td_overlay.next_td =
1383 grub_cpu_to_le32 (grub_dma_virt2phys
1384 (cdata->td_first_virt, e->td_chunk));
1385 /* Reset Active and Halted bits in QH to activate Advance Queue,
1386 * i.e. reset token */
1387 cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
1389 /* Finito */
1390 transfer->controller_data = cdata;
1392 return GRUB_USB_ERR_NONE;
1395 /* This function expects QH is not active.
1396 * Function set Halt bit in QH TD overlay and possibly prints
1397 * necessary debug information. */
1398 static void
1399 grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer)
1401 struct grub_ehci_transfer_controller_data *cdata =
1402 transfer->controller_data;
1404 /* Collect debug data here if necessary */
1406 /* Set Halt bit in not active QH. AL will not attempt to do
1407 * Advance Queue on QH with Halt bit set, i.e., we can then
1408 * safely manipulate with QH TD part. */
1409 cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token
1411 grub_cpu_to_le32_compile_time
1412 (GRUB_EHCI_STATUS_HALTED)) &
1413 grub_cpu_to_le32_compile_time (~GRUB_EHCI_STATUS_ACTIVE);
1415 /* Print debug data here if necessary */
1419 static grub_usb_err_t
1420 grub_ehci_parse_notrun (grub_usb_controller_t dev,
1421 grub_usb_transfer_t transfer, grub_size_t * actual)
1423 struct grub_ehci *e = dev->data;
1424 struct grub_ehci_transfer_controller_data *cdata =
1425 transfer->controller_data;
1427 grub_dprintf ("ehci", "parse_notrun: info\n");
1429 /* QH can be in any state in this case. */
1430 /* But EHCI or AL is not running, so QH is surely not active
1431 * even if it has Active bit set... */
1432 grub_ehci_pre_finish_transfer (transfer);
1433 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1434 grub_ehci_free_td (e, cdata->td_alt_virt);
1435 grub_free (cdata);
1437 /* Additionally, do something with EHCI to make it running (what?) */
1438 /* Try enable EHCI and AL */
1439 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1440 GRUB_EHCI_CMD_RUNSTOP | GRUB_EHCI_CMD_AS_ENABL
1441 | GRUB_EHCI_CMD_PS_ENABL
1442 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1443 /* Ensure command is written */
1444 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
1446 return GRUB_USB_ERR_UNRECOVERABLE;
1449 static grub_usb_err_t
1450 grub_ehci_parse_halt (grub_usb_controller_t dev,
1451 grub_usb_transfer_t transfer, grub_size_t * actual)
1453 struct grub_ehci *e = dev->data;
1454 struct grub_ehci_transfer_controller_data *cdata =
1455 transfer->controller_data;
1456 grub_uint32_t token;
1457 grub_usb_err_t err = GRUB_USB_ERR_NAK;
1459 /* QH should be halted and not active in this case. */
1461 grub_dprintf ("ehci", "parse_halt: info\n");
1463 /* Remember token before call pre-finish function */
1464 token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token);
1466 /* Do things like in normal finish */
1467 grub_ehci_pre_finish_transfer (transfer);
1468 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1469 grub_ehci_free_td (e, cdata->td_alt_virt);
1470 grub_free (cdata);
1472 /* Evaluation of error code - currently we don't have GRUB USB error
1473 * codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
1474 * Order of evaluation is critical, specially bubble/stall. */
1475 if ((token & GRUB_EHCI_STATUS_BABBLE) != 0)
1476 err = GRUB_USB_ERR_BABBLE;
1477 else if ((token & GRUB_EHCI_CERR_MASK) != 0)
1478 err = GRUB_USB_ERR_STALL;
1479 else if ((token & GRUB_EHCI_STATUS_TRANERR) != 0)
1480 err = GRUB_USB_ERR_DATA;
1481 else if ((token & GRUB_EHCI_STATUS_BUFERR) != 0)
1482 err = GRUB_USB_ERR_DATA;
1483 else if ((token & GRUB_EHCI_STATUS_MISSDMF) != 0)
1484 err = GRUB_USB_ERR_DATA;
1486 return err;
1489 static grub_usb_err_t
1490 grub_ehci_parse_success (grub_usb_controller_t dev,
1491 grub_usb_transfer_t transfer, grub_size_t * actual)
1493 struct grub_ehci *e = dev->data;
1494 struct grub_ehci_transfer_controller_data *cdata =
1495 transfer->controller_data;
1497 grub_dprintf ("ehci", "parse_success: info\n");
1499 /* QH should be not active in this case, but it is not halted. */
1500 grub_ehci_pre_finish_transfer (transfer);
1501 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual);
1502 grub_ehci_free_td (e, cdata->td_alt_virt);
1503 grub_free (cdata);
1505 return GRUB_USB_ERR_NONE;
1509 static grub_usb_err_t
1510 grub_ehci_check_transfer (grub_usb_controller_t dev,
1511 grub_usb_transfer_t transfer, grub_size_t * actual)
1513 struct grub_ehci *e = dev->data;
1514 struct grub_ehci_transfer_controller_data *cdata =
1515 transfer->controller_data;
1516 grub_uint32_t token, token_ftd;
1518 grub_dprintf ("ehci",
1519 "check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
1520 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
1521 cdata, cdata->qh_virt);
1522 grub_dprintf ("ehci", "check_transfer: qh_hptr=%08x, ep_char=%08x\n",
1523 grub_le_to_cpu32 (cdata->qh_virt->qh_hptr),
1524 grub_le_to_cpu32 (cdata->qh_virt->ep_char));
1525 grub_dprintf ("ehci", "check_transfer: ep_cap=%08x, td_current=%08x\n",
1526 grub_le_to_cpu32 (cdata->qh_virt->ep_cap),
1527 grub_le_to_cpu32 (cdata->qh_virt->td_current));
1528 grub_dprintf ("ehci", "check_transfer: next_td=%08x, alt_next_td=%08x\n",
1529 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td),
1530 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.alt_next_td));
1531 grub_dprintf ("ehci", "check_transfer: token=%08x, buffer[0]=%08x\n",
1532 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token),
1533 grub_le_to_cpu32 (cdata->qh_virt->td_overlay.buffer_page[0]));
1535 /* Check if EHCI is running and AL is enabled */
1536 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1537 & GRUB_EHCI_ST_HC_HALTED) != 0)
1538 return grub_ehci_parse_notrun (dev, transfer, actual);
1539 if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1540 & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
1541 return grub_ehci_parse_notrun (dev, transfer, actual);
1543 token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token);
1544 /* If the transfer consist from only one TD, we should check */
1545 /* if the TD was really executed and deactivated - to prevent */
1546 /* false detection of transfer finish. */
1547 token_ftd = grub_le_to_cpu32 (cdata->td_first_virt->token);
1549 /* Detect QH halted */
1550 if ((token & GRUB_EHCI_STATUS_HALTED) != 0)
1551 return grub_ehci_parse_halt (dev, transfer, actual);
1553 /* Detect QH not active - QH is not active and no next TD */
1554 if (token && ((token & GRUB_EHCI_STATUS_ACTIVE) == 0)
1555 && ((token_ftd & GRUB_EHCI_STATUS_ACTIVE) == 0))
1557 /* It could be finish at all or short packet condition */
1558 if ((grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td)
1559 & GRUB_EHCI_TERMINATE) &&
1560 ((grub_le_to_cpu32 (cdata->qh_virt->td_current)
1561 & GRUB_EHCI_QHTDPTR_MASK) == cdata->td_last_phys))
1562 /* Normal finish */
1563 return grub_ehci_parse_success (dev, transfer, actual);
1564 else if ((token & GRUB_EHCI_TOTAL_MASK) != 0)
1565 /* Short packet condition */
1566 /* But currently we don't handle it - higher level will do it */
1567 return grub_ehci_parse_success (dev, transfer, actual);
1570 return GRUB_USB_ERR_WAIT;
1573 static grub_usb_err_t
1574 grub_ehci_cancel_transfer (grub_usb_controller_t dev,
1575 grub_usb_transfer_t transfer)
1577 struct grub_ehci *e = dev->data;
1578 struct grub_ehci_transfer_controller_data *cdata =
1579 transfer->controller_data;
1580 grub_size_t actual;
1581 int i;
1582 grub_uint64_t maxtime;
1583 grub_uint32_t qh_phys;
1584 grub_uint32_t interrupt =
1585 cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK;
1587 /* QH can be active and should be de-activated and halted */
1589 grub_dprintf ("ehci", "cancel_transfer: begin\n");
1591 /* First check if EHCI is running - if not, there is no problem */
1592 /* to cancel any transfer. Or, if transfer is asynchronous, check */
1593 /* if AL is enabled - if not, transfer can be canceled also. */
1594 if (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) &
1595 GRUB_EHCI_ST_HC_HALTED) != 0) ||
1596 (!interrupt && ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) &
1597 (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)))
1599 grub_ehci_pre_finish_transfer (transfer);
1600 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
1601 grub_ehci_free_td (e, cdata->td_alt_virt);
1602 grub_free (cdata);
1603 grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
1604 return GRUB_USB_ERR_NONE;
1607 /* EHCI and (AL or SL) are running. What to do? */
1608 /* Try to Halt QH via de-scheduling QH. */
1609 /* Find index of previous QH */
1610 qh_phys = grub_dma_virt2phys(cdata->qh_virt, e->qh_chunk);
1611 for (i = 0; i < GRUB_EHCI_N_QH; i++)
1613 if ((grub_le_to_cpu32(e->qh_virt[i].qh_hptr)
1614 & GRUB_EHCI_QHTDPTR_MASK) == qh_phys)
1615 break;
1617 if (i == GRUB_EHCI_N_QH)
1619 grub_printf ("%s: prev not found, queues are corrupt\n", __func__);
1620 return GRUB_USB_ERR_UNRECOVERABLE;
1622 /* Unlink QH from AL */
1623 e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
1625 /* If this is an interrupt transfer, we just wait for the periodic
1626 * schedule to advance a few times and then assume that the EHCI
1627 * controller has read the updated QH. */
1628 if (cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK)
1630 grub_millisleep(20);
1632 else
1634 /* For the asynchronous schedule we use the advance doorbell to find
1635 * out when the EHCI controller has read the updated QH. */
1637 /* Ring the doorbell */
1638 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1639 GRUB_EHCI_CMD_AS_ADV_D
1640 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1641 /* Ensure command is written */
1642 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
1643 /* Wait answer with timeout */
1644 maxtime = grub_get_time_ms () + 2;
1645 while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
1646 & GRUB_EHCI_ST_AS_ADVANCE) == 0)
1647 && (grub_get_time_ms () < maxtime));
1649 /* We do not detect the timeout because if timeout occurs, it most
1650 * probably means something wrong with EHCI - maybe stopped etc. */
1652 /* Shut up the doorbell */
1653 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1654 ~GRUB_EHCI_CMD_AS_ADV_D
1655 & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1656 grub_ehci_oper_write32 (e, GRUB_EHCI_STATUS,
1657 GRUB_EHCI_ST_AS_ADVANCE
1658 | grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1659 /* Ensure command is written */
1660 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
1663 /* Now is QH out of AL and we can do anything with it... */
1664 grub_ehci_pre_finish_transfer (transfer);
1665 grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
1666 grub_ehci_free_td (e, cdata->td_alt_virt);
1668 /* "Free" the QH - link it to itself */
1669 cdata->qh_virt->ep_char = 0;
1670 cdata->qh_virt->qh_hptr =
1671 grub_cpu_to_le32 ((grub_dma_virt2phys (cdata->qh_virt,
1672 e->qh_chunk)
1673 & GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
1675 grub_free (cdata);
1677 grub_dprintf ("ehci", "cancel_transfer: end\n");
1679 return GRUB_USB_ERR_NONE;
1682 static int
1683 grub_ehci_hubports (grub_usb_controller_t dev)
1685 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1686 grub_uint32_t portinfo;
1688 portinfo = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1689 & GRUB_EHCI_SPARAMS_N_PORTS;
1690 grub_dprintf ("ehci", "root hub ports=%d\n", portinfo);
1691 return portinfo;
1694 static grub_usb_err_t
1695 grub_ehci_portstatus (grub_usb_controller_t dev,
1696 unsigned int port, unsigned int enable)
1698 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1699 grub_uint64_t endtime;
1701 grub_dprintf ("ehci", "portstatus: EHCI STATUS: %08x\n",
1702 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1703 grub_dprintf ("ehci",
1704 "portstatus: begin, iobase=%p, port=%d, status=0x%02x\n",
1705 e->iobase, port, grub_ehci_port_read (e, port));
1707 /* In any case we need to disable port:
1708 * - if enable==false - we should disable port
1709 * - if enable==true we will do the reset and the specification says
1710 * PortEnable should be FALSE in such case */
1711 /* Disable the port and wait for it. */
1712 grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_ENABLED);
1713 endtime = grub_get_time_ms () + 1000;
1714 while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED)
1715 if (grub_get_time_ms () > endtime)
1716 return GRUB_USB_ERR_TIMEOUT;
1718 if (!enable) /* We don't need reset port */
1720 grub_dprintf ("ehci", "portstatus: Disabled.\n");
1721 grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n",
1722 grub_ehci_port_read (e, port));
1723 return GRUB_USB_ERR_NONE;
1726 grub_dprintf ("ehci", "portstatus: enable\n");
1728 grub_boot_time ("Resetting port %d", port);
1730 /* Now we will do reset - if HIGH speed device connected, it will
1731 * result in Enabled state, otherwise port remains disabled. */
1732 /* Set RESET bit for 50ms */
1733 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_RESET);
1734 grub_millisleep (50);
1736 /* Reset RESET bit and wait for the end of reset */
1737 grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_RESET);
1738 endtime = grub_get_time_ms () + 1000;
1739 while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_RESET)
1740 if (grub_get_time_ms () > endtime)
1741 return GRUB_USB_ERR_TIMEOUT;
1742 grub_boot_time ("Port %d reset", port);
1743 /* Remember "we did the reset" - needed by detect_dev */
1744 e->reset |= (1 << port);
1745 /* Test if port enabled, i.e. HIGH speed device connected */
1746 if ((grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED) != 0) /* yes! */
1748 grub_dprintf ("ehci", "portstatus: Enabled!\n");
1749 /* "Reset recovery time" (USB spec.) */
1750 grub_millisleep (10);
1752 else /* no... */
1754 /* FULL speed device connected - change port ownership.
1755 * It results in disconnected state of this EHCI port. */
1756 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER);
1757 return GRUB_USB_ERR_BADDEVICE;
1760 /* XXX: Fix it! There is possible problem - we can say to calling
1761 * function that we lost device if it is FULL speed onlu via
1762 * return value <> GRUB_ERR_NONE. It (maybe) displays also error
1763 * message on screen - but this situation is not error, it is normal
1764 * state! */
1766 grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n",
1767 grub_ehci_port_read (e, port));
1769 return GRUB_USB_ERR_NONE;
1772 static grub_usb_speed_t
1773 grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
1775 struct grub_ehci *e = (struct grub_ehci *) dev->data;
1776 grub_uint32_t status, line_state;
1778 status = grub_ehci_port_read (e, port);
1780 grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n",
1781 grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
1782 grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n",
1783 e->iobase, port, status);
1785 /* Connect Status Change bit - it detects change of connection */
1786 if (status & GRUB_EHCI_PORT_CONNECT_CH)
1788 *changed = 1;
1789 /* Reset bit Connect Status Change */
1790 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_CONNECT_CH);
1792 else
1793 *changed = 0;
1795 if (!(status & GRUB_EHCI_PORT_CONNECT))
1796 { /* We should reset related "reset" flag in not connected state */
1797 e->reset &= ~(1 << port);
1798 return GRUB_USB_SPEED_NONE;
1800 /* Detected connected state, so we should return speed.
1801 * But we can detect only LOW speed device and only at connection
1802 * time when PortEnabled=FALSE. FULL / HIGH speed detection is made
1803 * later by EHCI-specific reset procedure.
1804 * Another thing - if detected speed is LOW at connection time,
1805 * we should change port ownership to companion controller.
1806 * So:
1807 * 1. If we detect connected and enabled and EHCI-owned port,
1808 * we can say it is HIGH speed.
1809 * 2. If we detect connected and not EHCI-owned port, we can say
1810 * NONE speed, because such devices are not handled by EHCI.
1811 * 3. If we detect connected, not enabled but reset port, we can say
1812 * NONE speed, because it means FULL device connected to port and
1813 * such devices are not handled by EHCI.
1814 * 4. If we detect connected, not enabled and not reset port, which
1815 * has line state != "K", we will say HIGH - it could be FULL or HIGH
1816 * device, we will see it later after end of EHCI-specific reset
1817 * procedure.
1818 * 5. If we detect connected, not enabled and not reset port, which
1819 * has line state == "K", we can say NONE speed, because LOW speed
1820 * device is connected and we should change port ownership. */
1821 if ((status & GRUB_EHCI_PORT_ENABLED) != 0) /* Port already enabled, return high speed. */
1822 return GRUB_USB_SPEED_HIGH;
1823 if ((status & GRUB_EHCI_PORT_OWNER) != 0) /* EHCI is not port owner */
1824 return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */
1825 if ((e->reset & (1 << port)) != 0) /* Port reset was done = FULL speed */
1826 return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */
1827 else /* Port connected but not enabled - test port speed. */
1829 line_state = status & GRUB_EHCI_PORT_LINE_STAT;
1830 if (line_state != GRUB_EHCI_PORT_LINE_LOWSP)
1831 return GRUB_USB_SPEED_HIGH;
1832 /* Detected LOW speed device, we should change
1833 * port ownership.
1834 * XXX: Fix it!: There should be test if related companion
1835 * controler is available ! And what to do if it does not exist ? */
1836 grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER);
1837 return GRUB_USB_SPEED_NONE; /* Ignore this port */
1838 /* Note: Reset of PORT_OWNER bit is done by EHCI HW when
1839 * device is really disconnected from port.
1840 * Don't do PORT_OWNER bit reset by SW when not connected signal
1841 * is detected in port register ! */
1845 static void
1846 grub_ehci_inithw (void)
1848 grub_pci_iterate (grub_ehci_pci_iter, NULL);
1851 static grub_err_t
1852 grub_ehci_restore_hw (void)
1854 struct grub_ehci *e;
1855 grub_uint32_t n_ports;
1856 int i;
1858 /* We should re-enable all EHCI HW similarly as on inithw */
1859 for (e = ehci; e; e = e->next)
1861 /* Check if EHCI is halted and halt it if not */
1862 if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE)
1863 grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout");
1865 /* Reset EHCI */
1866 if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE)
1867 grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout");
1869 /* Setup some EHCI registers and enable EHCI */
1870 grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys);
1871 grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR,
1872 grub_dma_virt2phys (&e->qh_virt[1],
1873 e->qh_chunk));
1874 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1875 GRUB_EHCI_CMD_RUNSTOP |
1876 grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1878 /* Set ownership of root hub ports to EHCI */
1879 grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG,
1880 GRUB_EHCI_CF_EHCI_OWNER);
1882 /* Enable asynchronous list */
1883 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1884 GRUB_EHCI_CMD_AS_ENABL
1885 | GRUB_EHCI_CMD_PS_ENABL
1886 | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1888 /* Now should be possible to power-up and enumerate ports etc. */
1889 if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1890 & GRUB_EHCI_SPARAMS_PPC) != 0)
1891 { /* EHCI has port powering control */
1892 /* Power on all ports */
1893 n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)
1894 & GRUB_EHCI_SPARAMS_N_PORTS;
1895 for (i = 0; i < (int) n_ports; i++)
1896 grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4,
1897 GRUB_EHCI_PORT_POWER
1898 | grub_ehci_oper_read32 (e,
1899 GRUB_EHCI_PORT_STAT_CMD
1900 + i * 4));
1904 return GRUB_ERR_NONE;
1907 static grub_err_t
1908 grub_ehci_fini_hw (int noreturn __attribute__ ((unused)))
1910 struct grub_ehci *e;
1912 /* We should disable all EHCI HW to prevent any DMA access etc. */
1913 for (e = ehci; e; e = e->next)
1915 /* Disable both lists */
1916 grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
1917 ~(GRUB_EHCI_CMD_AS_ENABL | GRUB_EHCI_CMD_PS_ENABL)
1918 & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
1920 /* Check if EHCI is halted and halt it if not */
1921 grub_ehci_halt (e);
1923 /* Reset EHCI */
1924 grub_ehci_reset (e);
1927 return GRUB_ERR_NONE;
1930 static struct grub_usb_controller_dev usb_controller = {
1931 .name = "ehci",
1932 .iterate = grub_ehci_iterate,
1933 .setup_transfer = grub_ehci_setup_transfer,
1934 .check_transfer = grub_ehci_check_transfer,
1935 .cancel_transfer = grub_ehci_cancel_transfer,
1936 .hubports = grub_ehci_hubports,
1937 .portstatus = grub_ehci_portstatus,
1938 .detect_dev = grub_ehci_detect_dev,
1939 /* estimated max. count of TDs for one bulk transfer */
1940 .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4
1943 GRUB_MOD_INIT (ehci)
1945 COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64);
1946 COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96);
1948 grub_stop_disk_firmware ();
1950 grub_boot_time ("Initing EHCI hardware");
1951 grub_ehci_inithw ();
1952 grub_boot_time ("Registering EHCI driver");
1953 grub_usb_controller_dev_register (&usb_controller);
1954 grub_boot_time ("EHCI driver registered");
1955 grub_loader_register_preboot_hook (grub_ehci_fini_hw, grub_ehci_restore_hw,
1956 GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
1959 GRUB_MOD_FINI (ehci)
1961 grub_ehci_fini_hw (0);
1962 grub_usb_controller_dev_unregister (&usb_controller);