~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to grub-core/bus/usb/ehci.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-09-13 18:02:04 UTC
  • mfrom: (1.17.15 upstream)
  • mto: (17.6.27 experimental)
  • mto: This revision was merged to the branch mainline in revision 145.
  • Revision ID: package-import@ubuntu.com-20120913180204-mojnmocbimlom4im
Tags: upstream-2.00
ImportĀ upstreamĀ versionĀ 2.00

Show diffs side-by-side

added added

removed removed

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