source: grub-pc/trunk/fuentes/grub-core/bus/usb/ohci.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 45.4 KB
Line 
1/* ohci.c - OHCI Support.  */
2/*
3 *  GRUB  --  GRand Unified Bootloader
4 *  Copyright (C) 2008  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/cs5536.h>
30#include <grub/loader.h>
31#include <grub/disk.h>
32
33GRUB_MOD_LICENSE ("GPLv3+");
34
35struct grub_ohci_hcca
36{
37  /* Pointers to Interrupt Endpoint Descriptors.  Not used by
38     GRUB.  */
39  grub_uint32_t inttable[32];
40
41  /* Current frame number.  */
42  grub_uint16_t framenumber;
43
44  grub_uint16_t pad;
45
46  /* List of completed TDs.  */
47  grub_uint32_t donehead;
48
49  grub_uint8_t reserved[116];
50} GRUB_PACKED;
51
52/* OHCI General Transfer Descriptor */
53struct grub_ohci_td
54{
55  /* Information used to construct the TOKEN packet.  */
56  grub_uint32_t token;
57  grub_uint32_t buffer; /* LittleEndian physical address */
58  grub_uint32_t next_td; /* LittleEndian physical address */
59  grub_uint32_t buffer_end; /* LittleEndian physical address */
60  /* next values are not for OHCI HW */
61  volatile struct grub_ohci_td *link_td; /* pointer to next free/chained TD
62                          * pointer as uint32 */
63  grub_uint32_t prev_td_phys; /* we need it to find previous TD
64                               * physical address in CPU endian */
65  grub_uint32_t tr_index; /* index of TD in transfer */
66  grub_uint8_t pad[8 - sizeof (volatile struct grub_ohci_td *)]; /* padding to 32 bytes */
67} GRUB_PACKED;
68
69/* OHCI Endpoint Descriptor.  */
70struct grub_ohci_ed
71{
72  grub_uint32_t target;
73  grub_uint32_t td_tail;
74  grub_uint32_t td_head;
75  grub_uint32_t next_ed;
76} GRUB_PACKED;
77
78typedef volatile struct grub_ohci_td *grub_ohci_td_t;
79typedef volatile struct grub_ohci_ed *grub_ohci_ed_t;
80
81/* Experimental change of ED/TD allocation */
82/* Little bit similar as in UHCI */
83/* Implementation assumes:
84 *      32-bits architecture - XXX: fix for 64-bits
85 *      memory allocated by grub_memalign_dma32 must be continuous
86 *      in virtual and also in physical memory */
87struct grub_ohci
88{
89  volatile grub_uint32_t *iobase;
90  volatile struct grub_ohci_hcca *hcca;
91  grub_uint32_t hcca_addr;
92  struct grub_pci_dma_chunk *hcca_chunk;
93  grub_ohci_ed_t ed_ctrl; /* EDs for CONTROL */
94  grub_uint32_t ed_ctrl_addr;
95  struct grub_pci_dma_chunk *ed_ctrl_chunk;
96  grub_ohci_ed_t ed_bulk; /* EDs for BULK */
97  grub_uint32_t ed_bulk_addr;
98  struct grub_pci_dma_chunk *ed_bulk_chunk;
99  grub_ohci_td_t td; /* TDs */
100  grub_uint32_t td_addr;
101  struct grub_pci_dma_chunk *td_chunk;
102  struct grub_ohci *next;
103  grub_ohci_td_t td_free; /* Pointer to first free TD */
104};
105
106static struct grub_ohci *ohci;
107
108typedef enum
109{
110  GRUB_OHCI_REG_REVISION = 0x00,
111  GRUB_OHCI_REG_CONTROL,
112  GRUB_OHCI_REG_CMDSTATUS,
113  GRUB_OHCI_REG_INTSTATUS,
114  GRUB_OHCI_REG_INTENA,
115  GRUB_OHCI_REG_INTDIS,
116  GRUB_OHCI_REG_HCCA,
117  GRUB_OHCI_REG_PERIODIC,
118  GRUB_OHCI_REG_CONTROLHEAD,
119  GRUB_OHCI_REG_CONTROLCURR,
120  GRUB_OHCI_REG_BULKHEAD,
121  GRUB_OHCI_REG_BULKCURR,
122  GRUB_OHCI_REG_DONEHEAD,
123  GRUB_OHCI_REG_FRAME_INTERVAL,
124  GRUB_OHCI_REG_PERIODIC_START = 16,
125  GRUB_OHCI_REG_RHUBA = 18,
126  GRUB_OHCI_REG_RHUBPORT = 21,
127  GRUB_OHCI_REG_LEGACY_CONTROL = 0x100,
128  GRUB_OHCI_REG_LEGACY_INPUT = 0x104,
129  GRUB_OHCI_REG_LEGACY_OUTPUT = 0x108,
130  GRUB_OHCI_REG_LEGACY_STATUS = 0x10c
131} grub_ohci_reg_t;
132
133#define GRUB_OHCI_RHUB_PORT_POWER_MASK 0x300
134#define GRUB_OHCI_RHUB_PORT_ALL_POWERED 0x200
135
136#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK 0x8fff0000
137#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT 16
138#define GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT 0
139
140/* XXX: Is this choice of timings sane?  */
141#define GRUB_OHCI_FSMPS 0x2778
142#define GRUB_OHCI_PERIODIC_START 0x257f
143#define GRUB_OHCI_FRAME_INTERVAL 0x2edf
144
145#define GRUB_OHCI_SET_PORT_ENABLE (1 << 1)
146#define GRUB_OHCI_CLEAR_PORT_ENABLE (1 << 0)
147#define GRUB_OHCI_SET_PORT_RESET (1 << 4)
148#define GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE (1 << 20)
149
150#define GRUB_OHCI_REG_CONTROL_BULK_ENABLE (1 << 5)
151#define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4)
152
153#define GRUB_OHCI_RESET_CONNECT_CHANGE (1 << 16)
154#define GRUB_OHCI_CTRL_EDS 256
155#define GRUB_OHCI_BULK_EDS 510
156#define GRUB_OHCI_TDS 640
157
158#define GRUB_OHCI_ED_ADDR_MASK 0x7ff
159
160static inline grub_ohci_ed_t
161grub_ohci_ed_phys2virt (struct grub_ohci *o, int bulk, grub_uint32_t x)
162{
163  if (!x)
164    return NULL;
165  if (bulk)
166    return (grub_ohci_ed_t) (x - o->ed_bulk_addr
167                             + (grub_uint8_t *) o->ed_bulk);
168  return (grub_ohci_ed_t) (x - o->ed_ctrl_addr
169                           + (grub_uint8_t *) o->ed_ctrl);
170}
171
172static grub_uint32_t
173grub_ohci_virt_to_phys (struct grub_ohci *o, int bulk, grub_ohci_ed_t x)
174{
175  if (!x)
176    return 0;
177
178  if (bulk)
179    return (grub_uint8_t *) x - (grub_uint8_t *) o->ed_bulk + o->ed_bulk_addr;
180  return (grub_uint8_t *) x - (grub_uint8_t *) o->ed_ctrl + o->ed_ctrl_addr;
181}
182
183static inline grub_ohci_td_t
184grub_ohci_td_phys2virt (struct grub_ohci *o, grub_uint32_t x)
185{
186  if (!x)
187    return NULL;
188  return (grub_ohci_td_t) (x - o->td_addr + (grub_uint8_t *) o->td);
189}
190
191static grub_uint32_t
192grub_ohci_td_virt2phys (struct grub_ohci *o,  grub_ohci_td_t x)
193{
194  if (!x)
195    return 0;
196  return (grub_uint8_t *)x - (grub_uint8_t *)o->td + o->td_addr;
197}
198
199 
200static grub_uint32_t
201grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg)
202{
203  return grub_le_to_cpu32 (*(o->iobase + reg));
204}
205
206static void
207grub_ohci_writereg32 (struct grub_ohci *o,
208                      grub_ohci_reg_t reg, grub_uint32_t val)
209{
210  *(o->iobase + reg) = grub_cpu_to_le32 (val);
211}
212
213
214
215/* Iterate over all PCI devices.  Determine if a device is an OHCI
216   controller.  If this is the case, initialize it.  */
217static int
218grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
219                    void *data __attribute__ ((unused)))
220{
221  grub_uint32_t interf;
222  grub_uint32_t base;
223  grub_pci_address_t addr;
224  struct grub_ohci *o;
225  grub_uint32_t revision;
226  int j;
227 
228  /* Determine IO base address.  */
229  grub_dprintf ("ohci", "pciid = %x\n", pciid);
230
231  if (pciid == GRUB_CS5536_PCIID)
232    {
233      grub_uint64_t basereg;
234
235      basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE);
236      if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
237        {
238          /* Shouldn't happen.  */
239          grub_dprintf ("ohci", "No OHCI address is assigned\n");
240          return 0;
241        }
242      base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
243      basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
244      basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
245      basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
246      grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, basereg);
247    }
248  else
249    {
250      grub_uint32_t class_code;
251      grub_uint32_t class;
252      grub_uint32_t subclass;
253
254      addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
255      class_code = grub_pci_read (addr) >> 8;
256     
257      interf = class_code & 0xFF;
258      subclass = (class_code >> 8) & 0xFF;
259      class = class_code >> 16;
260
261      /* If this is not an OHCI controller, just return.  */
262      if (class != 0x0c || subclass != 0x03 || interf != 0x10)
263        return 0;
264
265      addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
266      base = grub_pci_read (addr);
267
268      base &= GRUB_PCI_ADDR_MEM_MASK;
269      if (!base)
270        {
271          grub_dprintf ("ehci",
272                        "EHCI: EHCI is not mapper\n");
273          return 0;
274        }
275
276      /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
277      addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
278      grub_pci_write_word(addr,
279                          GRUB_PCI_COMMAND_MEM_ENABLED
280                          | GRUB_PCI_COMMAND_BUS_MASTER
281                          | grub_pci_read_word(addr));
282
283      grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x\n",
284                    class, subclass, interf);
285    }
286
287  /* Allocate memory for the controller and register it.  */
288  o = grub_malloc (sizeof (*o));
289  if (! o)
290    return 1;
291  grub_memset ((void*)o, 0, sizeof (*o));
292  o->iobase = grub_pci_device_map_range (dev, base, 0x800);
293
294  grub_dprintf ("ohci", "base=%p\n", o->iobase);
295
296  /* Reserve memory for the HCCA.  */
297  o->hcca_chunk = grub_memalign_dma32 (256, 256);
298  if (! o->hcca_chunk)
299    goto fail;
300  o->hcca = grub_dma_get_virt (o->hcca_chunk);
301  o->hcca_addr = grub_dma_get_phys (o->hcca_chunk);
302  grub_memset ((void*)o->hcca, 0, sizeof(*o->hcca));
303  grub_dprintf ("ohci", "hcca: chunk=%p, virt=%p, phys=0x%02x\n",
304                o->hcca_chunk, o->hcca, o->hcca_addr);
305
306  /* Reserve memory for ctrl EDs.  */
307  o->ed_ctrl_chunk = grub_memalign_dma32 (16, sizeof(struct grub_ohci_ed)
308                                          * GRUB_OHCI_CTRL_EDS);
309  if (! o->ed_ctrl_chunk)
310    goto fail;
311  o->ed_ctrl = grub_dma_get_virt (o->ed_ctrl_chunk);
312  o->ed_ctrl_addr = grub_dma_get_phys (o->ed_ctrl_chunk);
313  /* Preset EDs */
314  grub_memset ((void *) o->ed_ctrl, 0, sizeof (struct grub_ohci_ed)
315               * GRUB_OHCI_CTRL_EDS);
316  for (j=0; j < GRUB_OHCI_CTRL_EDS; j++)
317    o->ed_ctrl[j].target = grub_cpu_to_le32 (1 << 14); /* skip */
318   
319  grub_dprintf ("ohci", "EDs-C: chunk=%p, virt=%p, phys=0x%02x\n",
320                o->ed_ctrl_chunk, o->ed_ctrl, o->ed_ctrl_addr);
321
322  /* Reserve memory for bulk EDs.  */
323  o->ed_bulk_chunk = grub_memalign_dma32 (16, sizeof (struct grub_ohci_ed)
324                                          * GRUB_OHCI_BULK_EDS);
325  if (! o->ed_bulk_chunk)
326    goto fail;
327  o->ed_bulk = grub_dma_get_virt (o->ed_bulk_chunk);
328  o->ed_bulk_addr = grub_dma_get_phys (o->ed_bulk_chunk);
329  /* Preset EDs */
330  grub_memset ((void*)o->ed_bulk, 0, sizeof(struct grub_ohci_ed) * GRUB_OHCI_BULK_EDS);
331  for (j=0; j < GRUB_OHCI_BULK_EDS; j++)
332    o->ed_bulk[j].target = grub_cpu_to_le32 (1 << 14); /* skip */
333
334  grub_dprintf ("ohci", "EDs-B: chunk=%p, virt=%p, phys=0x%02x\n",
335                o->ed_bulk_chunk, o->ed_bulk, o->ed_bulk_addr);
336
337  /* Reserve memory for TDs.  */
338  o->td_chunk = grub_memalign_dma32 (32, sizeof(struct grub_ohci_td)*GRUB_OHCI_TDS);
339  /* Why is it aligned on 32 boundary if spec. says 16 ?
340   * We have structure 32 bytes long and we don't want cross
341   * 4K boundary inside structure. */
342  if (! o->td_chunk)
343    goto fail;
344  o->td_free = o->td = grub_dma_get_virt (o->td_chunk);
345  o->td_addr = grub_dma_get_phys (o->td_chunk);
346  /* Preset free TDs chain in TDs */
347  grub_memset ((void*)o->td, 0, sizeof(struct grub_ohci_td) * GRUB_OHCI_TDS);
348  for (j=0; j < (GRUB_OHCI_TDS-1); j++)
349    o->td[j].link_td = &o->td[j+1];
350
351  grub_dprintf ("ohci", "TDs: chunk=%p, virt=%p, phys=0x%02x\n",
352                o->td_chunk, o->td, o->td_addr);
353
354  /* Check if the OHCI revision is actually 1.0 as supported.  */
355  revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION);
356  grub_dprintf ("ohci", "OHCI revision=0x%02x\n", revision & 0xFF);
357  if ((revision & 0xFF) != 0x10)
358    goto fail;
359
360  {
361    grub_uint32_t control;
362    /* Check SMM/BIOS ownership of OHCI (SMM = USB Legacy Support driver for BIOS) */
363    control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
364    if ((control & 0x100) != 0)
365      {
366        unsigned i;
367        grub_dprintf("ohci", "OHCI is owned by SMM\n");
368        /* Do change of ownership */
369        /* Ownership change request */
370        grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, (1<<3)); /* XXX: Magic.  */
371        /* Waiting for SMM deactivation */
372        for (i=0; i < 10; i++)
373          {
374            if ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & 0x100) == 0)
375              {
376                grub_dprintf("ohci", "Ownership changed normally.\n");
377                break;
378              }
379            grub_millisleep (100);
380          }
381        if (i >= 10)
382          {
383            grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
384                                  grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & ~0x100);
385            grub_dprintf("ohci", "Ownership changing timeout, change forced !\n");
386          }
387      }
388    else if (((control & 0x100) == 0) && 
389             ((control & 0xc0) != 0)) /* Not owned by SMM nor reset */
390      {
391        grub_dprintf("ohci", "OHCI is owned by BIOS\n");
392        /* Do change of ownership - not implemented yet... */
393        /* In fact we probably need to do nothing ...? */
394      }
395    else
396      {
397        grub_dprintf("ohci", "OHCI is not owned by SMM nor BIOS\n");
398        /* We can setup OHCI. */
399      } 
400  }
401
402  /* Suspend the OHCI by issuing a reset.  */
403  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic.  */
404  grub_millisleep (1);
405  grub_dprintf ("ohci", "OHCI reset\n");
406
407  grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL,
408                        (GRUB_OHCI_FSMPS
409                         << GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT)
410                        | (GRUB_OHCI_FRAME_INTERVAL
411                           << GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT));
412
413  grub_ohci_writereg32 (o, GRUB_OHCI_REG_PERIODIC_START,
414                        GRUB_OHCI_PERIODIC_START);
415
416  /* Setup the HCCA.  */
417  o->hcca->donehead = 0;
418  grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, o->hcca_addr);
419  grub_dprintf ("ohci", "OHCI HCCA\n");
420
421  /* Misc. pre-sets. */
422  o->hcca->donehead = 0;
423  grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
424  /* We don't want modify CONTROL/BULK HEAD registers.
425   * So we assign to HEAD registers zero ED from related array
426   * and we will not use this ED, it will be always skipped.
427   * It should not produce notable performance penalty (I hope). */
428  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr);
429  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
430  grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr);
431  grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
432
433  /* Check OHCI Legacy Support */
434  if ((revision & 0x100) != 0)
435    {
436      grub_dprintf ("ohci", "Legacy Support registers detected\n");
437      grub_dprintf ("ohci", "Current state of legacy control reg.: 0x%04x\n",
438                    grub_ohci_readreg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL));
439      grub_ohci_writereg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL,
440                            (grub_ohci_readreg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL)) & ~1);
441      grub_dprintf ("ohci", "OHCI Legacy Support disabled.\n");
442    }
443
444  /* Enable the OHCI + enable CONTROL and BULK LIST.  */
445  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
446                        (2 << 6)
447                        | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE
448                        | GRUB_OHCI_REG_CONTROL_BULK_ENABLE );
449  grub_dprintf ("ohci", "OHCI enable: 0x%02x\n",
450                (grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) >> 6) & 3);
451
452  /* Power on all ports */
453  grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBA,
454                       (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA)
455                        & ~GRUB_OHCI_RHUB_PORT_POWER_MASK)
456                       | GRUB_OHCI_RHUB_PORT_ALL_POWERED);
457#if 0 /* We don't need it at all, handled via hotplugging */
458  /* Now we have hot-plugging, we need to wait for stable power only */
459  grub_millisleep (100);
460#endif
461
462  /* Link to ohci now that initialisation is successful.  */
463  o->next = ohci;
464  ohci = o;
465
466  return 0;
467
468 fail:
469  if (o)
470    {
471      grub_dma_free (o->td_chunk);
472      grub_dma_free (o->ed_bulk_chunk);
473      grub_dma_free (o->ed_ctrl_chunk);
474      grub_dma_free (o->hcca_chunk);
475    }
476  grub_free (o);
477
478  return 0;
479}
480
481
482static void
483grub_ohci_inithw (void)
484{
485  grub_pci_iterate (grub_ohci_pci_iter, NULL);
486}
487
488
489
490static int
491grub_ohci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data)
492{
493  struct grub_ohci *o;
494  struct grub_usb_controller dev;
495
496  for (o = ohci; o; o = o->next)
497    {
498      dev.data = o;
499      if (hook (&dev, hook_data))
500        return 1;
501    }
502
503  return 0;
504}
505
506static grub_ohci_ed_t
507grub_ohci_find_ed (struct grub_ohci *o, int bulk, grub_uint32_t target)
508{
509  grub_ohci_ed_t ed, ed_next;
510  grub_uint32_t target_addr = target & GRUB_OHCI_ED_ADDR_MASK;
511  int count;
512  int i;
513
514  /* Use proper values and structures. */
515  if (bulk)
516    {   
517      count = GRUB_OHCI_BULK_EDS;
518      ed = o->ed_bulk;
519      ed_next = grub_ohci_ed_phys2virt(o, bulk,
520                  grub_le_to_cpu32 (ed->next_ed) );
521    }
522  else
523    {
524      count = GRUB_OHCI_CTRL_EDS;
525      ed = o->ed_ctrl;
526      ed_next = grub_ohci_ed_phys2virt(o, bulk,
527                  grub_le_to_cpu32 (ed->next_ed) );
528    }
529
530   /* First try to find existing ED with proper target address */
531  for (i = 0; ; )
532    {
533      if (i && /* We ignore zero ED */
534           ((ed->target & GRUB_OHCI_ED_ADDR_MASK) == target_addr))
535        return ed; /* Found proper existing ED */
536      i++;
537      if (ed_next && (i < count))
538        {
539          ed = ed_next;
540          ed_next = grub_ohci_ed_phys2virt(o, bulk,
541                      grub_le_to_cpu32 (ed->next_ed) );
542          continue;
543        }
544      break;
545    }
546  /* ED with target_addr does not exist, we have to add it */
547  /* Have we any free ED in array ? */
548  if (i >= count) /* No. */
549    return NULL;
550  /* Currently we simply take next ED in array, no allocation
551   * function is used. It should be no problem until hot-plugging
552   * will be implemented, i.e. until we will need to de-allocate EDs
553   * of unplugged devices. */
554  /* We can link new ED to previous ED safely as the new ED should
555   * still have set skip bit. */
556  ed->next_ed = grub_cpu_to_le32 ( grub_ohci_virt_to_phys (o,
557                                     bulk, &ed[1]));
558  return &ed[1];
559}
560
561static grub_ohci_td_t
562grub_ohci_alloc_td (struct grub_ohci *o)
563{
564  grub_ohci_td_t ret;
565
566  /* Check if there is a Transfer Descriptor available.  */
567  if (! o->td_free)
568    return NULL;
569
570  ret = o->td_free; /* Take current free TD */
571  o->td_free = (grub_ohci_td_t)ret->link_td; /* Advance to next free TD in chain */
572  ret->link_td = 0; /* Reset link_td in allocated TD */
573  return ret;
574}
575
576static void
577grub_ohci_free_td (struct grub_ohci *o, grub_ohci_td_t td)
578{
579  grub_memset ( (void*)td, 0, sizeof(struct grub_ohci_td) ); 
580  td->link_td = o->td_free; /* Cahin new free TD & rest */
581  o->td_free = td; /* Change address of first free TD */
582}
583
584static void
585grub_ohci_free_tds (struct grub_ohci *o, grub_ohci_td_t td)
586{
587  if (!td)
588    return;
589   
590  /* Unchain first TD from previous TD if it is chained */
591  if (td->prev_td_phys)
592    {
593      grub_ohci_td_t td_prev_virt = grub_ohci_td_phys2virt(o,
594                                      td->prev_td_phys);
595
596      if (td == (grub_ohci_td_t) td_prev_virt->link_td)
597        td_prev_virt->link_td = 0;
598    }
599 
600  /* Free all TDs from td  (chained by link_td) */
601  while (td)
602    {
603      grub_ohci_td_t tdprev;
604     
605      /* Unlink the queue.  */
606      tdprev = td;
607      td = (grub_ohci_td_t) td->link_td;
608
609      /* Free the TD.  */
610      grub_ohci_free_td (o, tdprev);
611    }
612}
613
614static void
615grub_ohci_transaction (grub_ohci_td_t td,
616                       grub_transfer_type_t type, unsigned int toggle,
617                       grub_size_t size, grub_uint32_t data)
618{
619  grub_uint32_t token;
620  grub_uint32_t buffer;
621  grub_uint32_t buffer_end;
622
623  grub_dprintf ("ohci", "OHCI transaction td=%p type=%d, toggle=%d, size=%lu\n",
624                td, type, toggle, (unsigned long) size);
625
626  switch (type)
627    {
628    case GRUB_USB_TRANSFER_TYPE_SETUP:
629      token = 0 << 19;
630      break;
631    case GRUB_USB_TRANSFER_TYPE_IN:
632      token = 2 << 19;
633      break;
634    case GRUB_USB_TRANSFER_TYPE_OUT:
635      token = 1 << 19;
636      break;
637    default:
638      token = 0;
639      break;
640    }
641
642  /* Set the token */
643  token |= ( 7 << 21); /* Never generate interrupt */
644  token |= toggle << 24;
645  token |= 1 << 25;
646
647  /* Set "Not accessed" error code */
648  token |= 15 << 28;
649
650  buffer = data;
651  buffer_end = buffer + size - 1;
652
653  /* Set correct buffer values in TD if zero transfer occurs */
654  if (size)
655    {
656      buffer = (grub_uint32_t) data;
657      buffer_end = buffer + size - 1;
658      td->buffer = grub_cpu_to_le32 (buffer);
659      td->buffer_end = grub_cpu_to_le32 (buffer_end);
660    }
661  else 
662    {
663      td->buffer = 0;
664      td->buffer_end = 0;
665    }
666
667  /* Set the rest of TD */
668  td->token = grub_cpu_to_le32 (token);
669  td->next_td = 0;
670}
671
672struct grub_ohci_transfer_controller_data
673{
674  grub_uint32_t tderr_phys;
675  grub_uint32_t td_last_phys;
676  grub_ohci_ed_t ed_virt;
677  grub_ohci_td_t td_current_virt;
678  grub_ohci_td_t td_head_virt;
679};
680
681static grub_usb_err_t
682grub_ohci_setup_transfer (grub_usb_controller_t dev,
683                          grub_usb_transfer_t transfer)
684{
685  struct grub_ohci *o = (struct grub_ohci *) dev->data;
686  int bulk = 0;
687  grub_ohci_td_t td_next_virt;
688  grub_uint32_t target;
689  grub_uint32_t td_head_phys;
690  grub_uint32_t td_tail_phys;
691  int i;
692  struct grub_ohci_transfer_controller_data *cdata;
693
694  cdata = grub_zalloc (sizeof (*cdata));
695  if (!cdata)
696    return GRUB_USB_ERR_INTERNAL;
697
698  /* Pre-set target for ED - we need it to find proper ED */
699  /* Set the device address.  */
700  target = transfer->devaddr;
701  /* Set the endpoint. It should be masked, we need 4 bits only. */
702  target |= (transfer->endpoint & 15) << 7;
703  /* Set the device speed.  */
704  target |= (transfer->dev->speed == GRUB_USB_SPEED_LOW) << 13;
705  /* Set the maximum packet size.  */
706  target |= transfer->max << 16;
707
708  /* Determine if transfer type is bulk - we need to select proper ED */
709  switch (transfer->type)
710    {
711      case GRUB_USB_TRANSACTION_TYPE_BULK:
712        bulk = 1;
713        break;
714
715      case GRUB_USB_TRANSACTION_TYPE_CONTROL:
716        break;
717
718      default:
719        grub_free (cdata);
720        return GRUB_USB_ERR_INTERNAL;
721    }
722
723  /* Find proper ED or add new ED */
724  cdata->ed_virt = grub_ohci_find_ed (o, bulk, target);
725  if (!cdata->ed_virt)
726    {
727      grub_dprintf ("ohci","Fatal: No free ED !\n");
728      grub_free (cdata);
729      return GRUB_USB_ERR_INTERNAL;
730    }
731 
732  /* Take pointer to first TD from ED */
733  td_head_phys = grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf;
734  td_tail_phys = grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf;
735
736  /* Sanity check - td_head should be equal to td_tail */
737  if (td_head_phys != td_tail_phys) /* Should never happen ! */
738    {
739      grub_dprintf ("ohci", "Fatal: HEAD is not equal to TAIL !\n");
740      grub_dprintf ("ohci", "HEAD = 0x%02x, TAIL = 0x%02x\n",
741                    td_head_phys, td_tail_phys);
742      /* XXX: Fix: What to do ? */
743      grub_free (cdata);
744      return GRUB_USB_ERR_INTERNAL;
745    }
746 
747  /* Now we should handle first TD. If ED is newly allocated,
748   * we must allocate the first TD. */
749  if (!td_head_phys)
750    {
751      cdata->td_head_virt = grub_ohci_alloc_td (o);
752      if (!cdata->td_head_virt)
753        return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */
754      /* We can set td_head only when ED is not active, i.e.
755       * when it is newly allocated. */
756      cdata->ed_virt->td_head
757        = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_head_virt));
758      cdata->ed_virt->td_tail = cdata->ed_virt->td_head;
759    }
760  else
761    cdata->td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys );
762   
763  /* Set TDs */
764  cdata->td_last_phys = td_head_phys; /* initial value to make compiler happy... */
765  for (i = 0, cdata->td_current_virt = cdata->td_head_virt;
766       i < transfer->transcnt; i++)
767    {
768      grub_usb_transaction_t tr = &transfer->transactions[i];
769
770      grub_ohci_transaction (cdata->td_current_virt, tr->pid, tr->toggle,
771                             tr->size, tr->data);
772
773      /* Set index of TD in transfer */
774      cdata->td_current_virt->tr_index = (grub_uint32_t) i;
775     
776      /* Remember last used (processed) TD phys. addr. */
777      cdata->td_last_phys = grub_ohci_td_virt2phys (o, cdata->td_current_virt);
778     
779      /* Allocate next TD */
780      td_next_virt = grub_ohci_alloc_td (o);
781      if (!td_next_virt) /* No free TD, cancel transfer and free TDs except head TD */
782        {
783          if (i) /* if i==0 we have nothing to free... */
784            grub_ohci_free_tds (o, grub_ohci_td_phys2virt(o,
785                                                          grub_le_to_cpu32 (cdata->td_head_virt->next_td)));
786          /* Reset head TD */
787          grub_memset ( (void*)cdata->td_head_virt, 0,
788                        sizeof(struct grub_ohci_td) );
789          grub_dprintf ("ohci", "Fatal: No free TD !");
790          grub_free (cdata);
791          return GRUB_USB_ERR_INTERNAL;
792        }
793
794      /* Chain TDs */
795
796      cdata->td_current_virt->link_td = td_next_virt;
797      cdata->td_current_virt->next_td = grub_cpu_to_le32 (
798                                   grub_ohci_td_virt2phys (o,
799                                     td_next_virt) );
800      td_next_virt->prev_td_phys = grub_ohci_td_virt2phys (o,
801                                cdata->td_current_virt);
802      cdata->td_current_virt = td_next_virt;
803    }
804
805  grub_dprintf ("ohci", "Tail TD (not processed) = %p\n",
806                cdata->td_current_virt);
807 
808  /* Setup the Endpoint Descriptor for transfer.  */
809  /* First set necessary fields in TARGET but keep (or set) skip bit */
810  /* Note: It could be simpler if speed, format and max. packet
811   * size never change after first allocation of ED.
812   * But unfortunately max. packet size may change during initial
813   * setup sequence and we must handle it. */
814  cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14));
815  /* Set td_tail */
816  cdata->ed_virt->td_tail
817    = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_current_virt));
818  /* Now reset skip bit */
819  cdata->ed_virt->target = grub_cpu_to_le32 (target);
820  /* ed_virt->td_head = grub_cpu_to_le32 (td_head); Must not be changed, it is maintained by OHCI */
821  /* ed_virt->next_ed = grub_cpu_to_le32 (0); Handled by grub_ohci_find_ed, do not change ! */
822
823  grub_dprintf ("ohci", "program OHCI\n");
824
825  /* Program the OHCI to actually transfer.  */
826  switch (transfer->type)
827    {
828    case GRUB_USB_TRANSACTION_TYPE_BULK:
829      {
830        grub_dprintf ("ohci", "BULK list filled\n");
831        /* Set BulkListFilled.  */
832        grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1 << 2);
833        /* Read back of register should ensure it is really written */
834        grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
835        break;
836      }
837
838    case GRUB_USB_TRANSACTION_TYPE_CONTROL:
839      {
840        grub_dprintf ("ohci", "CONTROL list filled\n");
841        /* Set ControlListFilled.  */
842        grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1 << 1);
843        /* Read back of register should ensure it is really written */
844        grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
845        break;
846      }
847    }
848
849  transfer->controller_data = cdata;
850
851  return GRUB_USB_ERR_NONE;
852}
853
854static void
855pre_finish_transfer (grub_usb_controller_t dev,
856                     grub_usb_transfer_t transfer)
857{
858  struct grub_ohci *o = dev->data;
859  struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
860  grub_uint32_t target;
861  grub_uint32_t status;
862  grub_uint32_t control;
863  grub_uint32_t intstatus;
864
865  /* There are many ways how the loop above can finish:
866   * - normally without any error via INTSTATUS WDH bit
867   *   : tderr_phys == td_last_phys, td_head == td_tail
868   * - normally with error via HALT bit in ED TD HEAD
869   *   : td_head = next TD after TD with error
870   *   : tderr_phys = last processed and retired TD with error,
871   *     i.e. should be != 0
872   *   : if bad_OHCI == TRUE, tderr_phys will be probably invalid
873   * - unrecoverable error - I never seen it but it could be
874   *   : err_unrec == TRUE, other values can contain anything...
875   * - timeout, it can be caused by:
876   *  -- bad USB device - some devices have some bugs, see Linux source
877   *     and related links
878   *  -- bad OHCI controller - e.g. lost interrupts or does not set
879   *     proper bits in INTSTATUS when real IRQ not enabled etc.,
880   *     see Linux source and related links
881   *     One known bug is handled - if transfer finished
882   *     successfully (i.e. HEAD==TAIL, last transfer TD is retired,
883   *     HALT bit is not set) and WDH bit is not set in INTSTATUS - in
884   *     this case we set o->bad_OHCI=TRUE and do alternate loop
885   *     and error handling - but there is problem how to find retired
886   *     TD with error code if HALT occurs and if DONEHEAD is not
887   *     working - we need to find TD previous to current ED HEAD
888   *  -- bad code of this driver or some unknown reasons - :-(
889   *     it can be e.g. bad handling of EDs/TDs/toggle bit...
890   */
891
892  /* Remember target for debug and set skip flag in ED */
893  /* It should be normaly not necessary but we need it at least
894   * in case of timeout */
895  target = grub_le_to_cpu32 ( cdata->ed_virt->target );
896  cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14));
897  /* Read registers for debug - they should be read now because
898   * debug prints case unwanted delays, so something can happen
899   * in the meantime... */
900  control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
901  status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
902  intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
903  /* Now print debug values - to have full info what happened */
904  grub_dprintf ("ohci", "loop finished: control=0x%02x status=0x%02x\n",
905                control, status);
906  grub_dprintf ("ohci", "intstatus=0x%02x, td_last_phys=0x%02x\n",
907                intstatus, cdata->td_last_phys);
908  grub_dprintf ("ohci", "TARGET=0x%02x, HEAD=0x%02x, TAIL=0x%02x\n",
909                target,
910                grub_le_to_cpu32 (cdata->ed_virt->td_head),
911                grub_le_to_cpu32 (cdata->ed_virt->td_tail) );
912
913}
914
915static void
916finish_transfer (grub_usb_controller_t dev,
917                 grub_usb_transfer_t transfer)
918{
919  struct grub_ohci *o = dev->data;
920  struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
921
922  /* Set empty ED - set HEAD = TAIL = last (not processed) TD */
923  cdata->ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf); 
924
925  /* At this point always should be:
926   * ED has skip bit set and halted or empty or after next SOF,
927   *    i.e. it is safe to free all TDs except last not processed
928   * ED HEAD == TAIL == phys. addr. of td_current_virt */
929
930  /* Un-chainig of last TD */
931  if (cdata->td_current_virt->prev_td_phys)
932    {
933      grub_ohci_td_t td_prev_virt
934        = grub_ohci_td_phys2virt (o, cdata->td_current_virt->prev_td_phys);
935     
936      if (cdata->td_current_virt == (grub_ohci_td_t) td_prev_virt->link_td)
937        td_prev_virt->link_td = 0;
938
939      cdata->td_current_virt->prev_td_phys = 0;
940    }
941
942  grub_dprintf ("ohci", "OHCI finished, freeing\n");
943  grub_ohci_free_tds (o, cdata->td_head_virt);
944  grub_free (cdata);
945}
946
947static grub_usb_err_t
948parse_halt (grub_usb_controller_t dev,
949            grub_usb_transfer_t transfer,
950            grub_size_t *actual)
951{
952  struct grub_ohci *o = dev->data;
953  struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
954  grub_uint8_t errcode = 0;
955  grub_usb_err_t err = GRUB_USB_ERR_NAK;
956  grub_ohci_td_t tderr_virt = NULL;
957
958  *actual = 0;
959
960  pre_finish_transfer (dev, transfer);
961
962  /* First we must get proper tderr_phys value */
963  /* Retired TD with error should be previous TD to ED->td_head */
964  cdata->tderr_phys = grub_ohci_td_phys2virt (o,
965                                                grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf )
966                      ->prev_td_phys;
967
968  /* Prepare pointer to last processed TD and get error code */
969  tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys);
970  /* Set index of last processed TD */
971  if (tderr_virt)
972    {
973      errcode = grub_le_to_cpu32 (tderr_virt->token) >> 28;
974      transfer->last_trans = tderr_virt->tr_index;
975    }
976  else
977    transfer->last_trans = -1;
978 
979  /* Evaluation of error code */
980  grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n",
981                cdata->tderr_phys, errcode);
982  switch (errcode)
983    {
984    case 0:
985      /* XXX: Should not happen!  */
986      grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason");
987      err = GRUB_USB_ERR_INTERNAL;
988      break;
989
990    case 1:
991      /* XXX: CRC error.  */
992      err = GRUB_USB_ERR_TIMEOUT;
993      break;
994
995    case 2:
996      err = GRUB_USB_ERR_BITSTUFF;
997      break;
998
999    case 3:
1000      /* XXX: Data Toggle error.  */
1001      err = GRUB_USB_ERR_DATA;
1002      break;
1003
1004    case 4:
1005      err = GRUB_USB_ERR_STALL;
1006      break;
1007
1008    case 5:
1009      /* XXX: Not responding.  */
1010      err = GRUB_USB_ERR_TIMEOUT;
1011      break;
1012
1013    case 6:
1014      /* XXX: PID Check bits failed.  */
1015      err = GRUB_USB_ERR_BABBLE;
1016      break;
1017
1018    case 7:
1019      /* XXX: PID unexpected failed.  */
1020      err = GRUB_USB_ERR_BABBLE;
1021      break;
1022
1023    case 8:
1024      /* XXX: Data overrun error.  */
1025      err = GRUB_USB_ERR_DATA;
1026      grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n",
1027                    tderr_virt, tderr_virt->tr_index);
1028      break;
1029
1030    case 9:
1031      /* XXX: Data underrun error.  */
1032      grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n",
1033                    tderr_virt, tderr_virt->tr_index);
1034      if (transfer->last_trans == -1)
1035        break;
1036      *actual = transfer->transactions[transfer->last_trans].size
1037        - (grub_le_to_cpu32 (tderr_virt->buffer_end)
1038           - grub_le_to_cpu32 (tderr_virt->buffer))
1039        + transfer->transactions[transfer->last_trans].preceding;
1040      err = GRUB_USB_ERR_NONE;
1041      break;
1042
1043    case 10:
1044      /* XXX: Reserved.  */
1045      err = GRUB_USB_ERR_NAK;
1046      break;
1047
1048    case 11:
1049      /* XXX: Reserved.  */
1050      err = GRUB_USB_ERR_NAK;
1051      break;
1052
1053    case 12:
1054      /* XXX: Buffer overrun.  */
1055      err = GRUB_USB_ERR_DATA;
1056      break;
1057
1058    case 13:
1059      /* XXX: Buffer underrun.  */
1060      err = GRUB_USB_ERR_DATA;
1061      break;
1062
1063    default:
1064      err = GRUB_USB_ERR_NAK;
1065      break;
1066    }
1067
1068  finish_transfer (dev, transfer);
1069
1070  return err;
1071}
1072
1073static grub_usb_err_t
1074parse_success (grub_usb_controller_t dev,
1075               grub_usb_transfer_t transfer,
1076               grub_size_t *actual)
1077{
1078  struct grub_ohci *o = dev->data;
1079  struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
1080  grub_ohci_td_t tderr_virt = NULL;
1081
1082  pre_finish_transfer (dev, transfer);
1083
1084  /* I hope we can do it as transfer (most probably) finished OK */
1085  cdata->tderr_phys = cdata->td_last_phys;
1086
1087  /* Prepare pointer to last processed TD */
1088  tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys);
1089 
1090  /* Set index of last processed TD */
1091  if (tderr_virt)
1092    transfer->last_trans = tderr_virt->tr_index;
1093  else
1094    transfer->last_trans = -1;
1095  *actual = transfer->size + 1;
1096
1097  finish_transfer (dev, transfer);
1098
1099  return GRUB_USB_ERR_NONE;
1100}
1101
1102static grub_usb_err_t
1103parse_unrec (grub_usb_controller_t dev,
1104             grub_usb_transfer_t transfer,
1105             grub_size_t *actual)
1106{
1107  struct grub_ohci *o = dev->data;
1108
1109  *actual = 0;
1110
1111  pre_finish_transfer (dev, transfer);
1112
1113  /* Don't try to get error code and last processed TD for proper
1114   * toggle bit value - anything can be invalid */
1115  grub_dprintf("ohci", "Unrecoverable error!");
1116
1117  /* Do OHCI reset in case of unrecoverable error - maybe we will need
1118   * do more - re-enumerate bus etc. (?) */
1119
1120  /* Suspend the OHCI by issuing a reset.  */
1121  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic.  */
1122  /* Read back of register should ensure it is really written */
1123  grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
1124  grub_millisleep (1);
1125  grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n");
1126
1127  /* Misc. resets. */
1128  o->hcca->donehead = 0;
1129  grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
1130  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr);
1131  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
1132  grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr);
1133  grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
1134  /* Read back of register should ensure it is really written */
1135  grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
1136
1137  /* Enable the OHCI.  */
1138  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
1139                        (2 << 6)
1140                        | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE
1141                        | GRUB_OHCI_REG_CONTROL_BULK_ENABLE );
1142  finish_transfer (dev, transfer);
1143
1144  return GRUB_USB_ERR_UNRECOVERABLE;
1145}
1146
1147static grub_usb_err_t
1148grub_ohci_check_transfer (grub_usb_controller_t dev,
1149                          grub_usb_transfer_t transfer,
1150                          grub_size_t *actual)
1151{
1152  struct grub_ohci *o = dev->data;
1153  struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
1154  grub_uint32_t intstatus;
1155
1156  /* Check transfer status */
1157  intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
1158
1159  if ((intstatus & 0x10) != 0)
1160    /* Unrecoverable error - only reset can help...! */
1161    return parse_unrec (dev, transfer, actual);
1162
1163  /* Detected a HALT.  */
1164  if ((grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1))
1165    return parse_halt (dev, transfer, actual);
1166
1167  /* Finished ED detection */
1168  if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) ==
1169       (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */
1170    {
1171      /* Check the HALT bit */
1172      /* It looks like nonsense - it was tested previously...
1173       * but it can change because OHCI is working
1174       * simultaneously via DMA... */
1175      if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1)
1176        return parse_halt (dev, transfer, actual);
1177      else
1178        return parse_success (dev, transfer, actual);
1179    }
1180
1181  return GRUB_USB_ERR_WAIT;
1182}
1183
1184static grub_usb_err_t
1185grub_ohci_cancel_transfer (grub_usb_controller_t dev,
1186                           grub_usb_transfer_t transfer)
1187{
1188  struct grub_ohci *o = dev->data;
1189  struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
1190  grub_ohci_td_t tderr_virt = NULL;
1191
1192  pre_finish_transfer (dev, transfer);
1193
1194  grub_dprintf("ohci", "Timeout !\n");
1195
1196  /* We should wait for next SOF to be sure that ED is unaccessed
1197   * by OHCI */
1198  /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */
1199  grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2));
1200  /* Wait for new SOF */
1201  while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0);
1202
1203  /* Possible retired TD with error should be previous TD to ED->td_head */
1204  cdata->tderr_phys
1205    = grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head)
1206                              & ~0xf)->prev_td_phys;
1207   
1208  tderr_virt = grub_ohci_td_phys2virt (o,cdata-> tderr_phys);
1209
1210  grub_dprintf ("ohci", "Cancel: tderr_phys=0x%x, tderr_virt=%p\n",
1211                cdata->tderr_phys, tderr_virt);
1212
1213  if (tderr_virt)
1214    transfer->last_trans = tderr_virt->tr_index;
1215  else
1216    transfer->last_trans = -1;
1217
1218  finish_transfer (dev, transfer);
1219
1220  return GRUB_USB_ERR_NONE;
1221}
1222
1223static grub_usb_err_t
1224grub_ohci_portstatus (grub_usb_controller_t dev,
1225                      unsigned int port, unsigned int enable)
1226{
1227   struct grub_ohci *o = (struct grub_ohci *) dev->data;
1228   grub_uint64_t endtime;
1229   int i;
1230
1231   grub_dprintf ("ohci", "begin of portstatus=0x%02x\n",
1232                 grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
1233
1234   if (!enable) /* We don't need reset port */
1235     {
1236       /* Disable the port and wait for it. */
1237       grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
1238                             GRUB_OHCI_CLEAR_PORT_ENABLE);
1239       endtime = grub_get_time_ms () + 1000;
1240       while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)
1241               & (1 << 1)))
1242         if (grub_get_time_ms () > endtime)
1243           return GRUB_USB_ERR_TIMEOUT;
1244
1245       grub_dprintf ("ohci", "end of portstatus=0x%02x\n",
1246         grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
1247       return GRUB_USB_ERR_NONE;
1248     }
1249     
1250   /* OHCI does one reset signal 10ms long but USB spec.
1251    * requests 50ms for root hub (no need to be continuous).
1252    * So, we do reset 5 times... */
1253   for (i = 0; i < 5; i++)
1254     {
1255       /* Reset the port - timing of reset is done by OHCI */
1256       grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
1257                             GRUB_OHCI_SET_PORT_RESET);
1258
1259       /* Wait for reset completion */
1260       endtime = grub_get_time_ms () + 1000;
1261       while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)
1262               & GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE))
1263         if (grub_get_time_ms () > endtime)
1264           return GRUB_USB_ERR_TIMEOUT;
1265
1266       /* End the reset signaling - reset the reset status change */
1267       grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
1268                             GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE);
1269       grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
1270     }
1271
1272   /* Enable port */
1273   grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
1274                         GRUB_OHCI_SET_PORT_ENABLE);
1275   grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
1276   
1277   /* Wait for signal enabled */
1278   endtime = grub_get_time_ms () + 1000;
1279   while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)
1280           & (1 << 1)))
1281     if (grub_get_time_ms () > endtime)
1282       return GRUB_USB_ERR_TIMEOUT;
1283
1284   /* Reset bit Connect Status Change */
1285   grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
1286                         GRUB_OHCI_RESET_CONNECT_CHANGE);
1287
1288   /* "Reset recovery time" (USB spec.) */
1289   grub_millisleep (10);
1290   
1291   grub_dprintf ("ohci", "end of portstatus=0x%02x\n",
1292                 grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
1293 
1294   return GRUB_USB_ERR_NONE;
1295}
1296
1297static grub_usb_speed_t
1298grub_ohci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
1299{
1300   struct grub_ohci *o = (struct grub_ohci *) dev->data;
1301   grub_uint32_t status;
1302
1303   status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
1304
1305   grub_dprintf ("ohci", "detect_dev status=0x%02x\n", status);
1306
1307   /* Connect Status Change bit - it detects change of connection */
1308   if (status & GRUB_OHCI_RESET_CONNECT_CHANGE)
1309     {
1310       *changed = 1;
1311       /* Reset bit Connect Status Change */
1312       grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
1313                             GRUB_OHCI_RESET_CONNECT_CHANGE);
1314     }
1315   else
1316     *changed = 0;
1317
1318   if (! (status & 1))
1319     return GRUB_USB_SPEED_NONE;
1320   else if (status & (1 << 9))
1321     return GRUB_USB_SPEED_LOW;
1322   else
1323     return GRUB_USB_SPEED_FULL;
1324}
1325
1326static int
1327grub_ohci_hubports (grub_usb_controller_t dev)
1328{
1329  struct grub_ohci *o = (struct grub_ohci *) dev->data;
1330  grub_uint32_t portinfo;
1331
1332  portinfo = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA);
1333
1334  grub_dprintf ("ohci", "root hub ports=%d\n", portinfo & 0xFF);
1335
1336  return portinfo & 0xFF;
1337}
1338
1339static grub_err_t
1340grub_ohci_fini_hw (int noreturn __attribute__ ((unused)))
1341{
1342  struct grub_ohci *o;
1343
1344  for (o = ohci; o; o = o->next)
1345    {
1346      int i, nports = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) & 0xff;
1347      grub_uint64_t maxtime;
1348
1349      /* Set skip in all EDs */
1350      if (o->ed_bulk)
1351        for (i=0; i < GRUB_OHCI_BULK_EDS; i++)
1352          o->ed_bulk[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */
1353      if (o->ed_ctrl)
1354        for (i=0; i < GRUB_OHCI_CTRL_EDS; i++)
1355          o->ed_ctrl[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */
1356
1357      /* We should wait for next SOF to be sure that all EDs are
1358       * unaccessed by OHCI. But OHCI can be non-functional, so
1359       * more than 1ms timeout have to be applied. */
1360      /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */
1361      grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2));
1362      maxtime = grub_get_time_ms () + 2;
1363      /* Wait for new SOF or timeout */
1364      while ( ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4)
1365                 == 0) || (grub_get_time_ms () >= maxtime) );
1366
1367      for (i = 0; i < nports; i++)
1368        grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + i,
1369                              GRUB_OHCI_CLEAR_PORT_ENABLE);
1370
1371      grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1);
1372      grub_millisleep (1);
1373      grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, 0);
1374      grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0);
1375      grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
1376      grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0);
1377      grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
1378      grub_ohci_writereg32 (o, GRUB_OHCI_REG_DONEHEAD, 0);
1379      grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, 0);
1380      /* Read back of register should ensure it is really written */
1381      grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
1382
1383#if 0 /* Is this necessary before booting? Probably not .(?)
1384       * But it must be done if module is removed ! (Or not ?)
1385       * How to do it ? - Probably grub_ohci_restore_hw should be more
1386       * complicated. (?)
1387       * (If we do it, we need to reallocate EDs and TDs in function
1388       * grub_ohci_restore_hw ! */
1389
1390      /* Free allocated EDs and TDs */
1391      grub_dma_free (o->td_chunk);
1392      grub_dma_free (o->ed_bulk_chunk);
1393      grub_dma_free (o->ed_ctrl_chunk);
1394      grub_dma_free (o->hcca_chunk);
1395#endif
1396    }
1397  grub_millisleep (10);
1398
1399  return GRUB_ERR_NONE;
1400}
1401
1402static grub_err_t
1403grub_ohci_restore_hw (void)
1404{
1405  struct grub_ohci *o;
1406
1407  for (o = ohci; o; o = o->next)
1408    {
1409      grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, o->hcca_addr);
1410      o->hcca->donehead = 0;
1411      grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
1412      grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr);
1413      grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
1414      grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr);
1415      grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
1416      /* Read back of register should ensure it is really written */
1417      grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
1418
1419      /* Enable the OHCI.  */
1420      grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
1421                            (2 << 6)
1422                            | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE
1423                            | GRUB_OHCI_REG_CONTROL_BULK_ENABLE );
1424    }
1425
1426  return GRUB_ERR_NONE;
1427}
1428
1429
1430static struct grub_usb_controller_dev usb_controller =
1431{
1432  .name = "ohci",
1433  .iterate = grub_ohci_iterate,
1434  .setup_transfer = grub_ohci_setup_transfer,
1435  .check_transfer = grub_ohci_check_transfer,
1436  .cancel_transfer = grub_ohci_cancel_transfer,
1437  .hubports = grub_ohci_hubports,
1438  .portstatus = grub_ohci_portstatus,
1439  .detect_dev = grub_ohci_detect_dev,
1440  /* estimated max. count of TDs for one bulk transfer */
1441  .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4
1442};
1443
1444static struct grub_preboot *fini_hnd;
1445
1446GRUB_MOD_INIT(ohci)
1447{
1448  COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32);
1449  COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16);
1450
1451  grub_stop_disk_firmware ();
1452
1453  grub_ohci_inithw ();
1454  grub_usb_controller_dev_register (&usb_controller);
1455  fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw,
1456                                                grub_ohci_restore_hw,
1457                                                GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
1458}
1459
1460GRUB_MOD_FINI(ohci)
1461{
1462  grub_ohci_fini_hw (0);
1463  grub_loader_unregister_preboot_hook (fini_hnd);
1464  grub_usb_controller_dev_unregister (&usb_controller);
1465}
Note: See TracBrowser for help on using the repository browser.