diff options
author | Nico Huber <nico.huber@secunet.com> | 2012-06-20 11:37:17 +0200 |
---|---|---|
committer | Nico Huber <nico.huber@secunet.com> | 2012-06-21 11:55:34 +0200 |
commit | 542fe85da956c62e46da1d9cfeb79c3d06b75427 (patch) | |
tree | 4f4471cdfe1a4e87a0d04a54d8260f5141123de6 | |
parent | 9951adeffd02c0226c5dd9dcbddbab9d86e28ee4 (diff) |
libpayload: Fix initialization of OHCI driver
This fixes some memory corruption, leaking and padding issues within
the initialization of the OHCI driver.
Change-Id: If6891f2a53e339d32c4324f4c9e0b1ed07596a60
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: http://review.coreboot.org/1126
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Tested-by: build bot (Jenkins)
-rw-r--r-- | payloads/libpayload/drivers/usb/ohci.c | 14 | ||||
-rw-r--r-- | payloads/libpayload/drivers/usb/ohci_private.h | 22 |
2 files changed, 21 insertions, 15 deletions
diff --git a/payloads/libpayload/drivers/usb/ohci.c b/payloads/libpayload/drivers/usb/ohci.c index be6d5e343a..6d98cc1100 100644 --- a/payloads/libpayload/drivers/usb/ohci.c +++ b/payloads/libpayload/drivers/usb/ohci.c @@ -129,17 +129,20 @@ ohci_init (pcidev_t addr) } int interval = OHCI_INST (controller)->opreg->HcFmInterval; - td_t *periodic_td = memalign(sizeof(*periodic_td), sizeof(*periodic_td)); - memset((void*)periodic_td, 0, sizeof(*periodic_td)); - for (i=0; i<32; i++) OHCI_INST (controller)->hcca->HccaInterruptTable[i] = virt_to_phys(periodic_td); - /* TODO: build HCCA data structures */ - OHCI_INST (controller)->opreg->HcCommandStatus = HostControllerReset; udelay (10); /* at most 10us for reset to complete. State must be set to Operational within 2ms (5.1.1.4) */ OHCI_INST (controller)->opreg->HcFmInterval = interval; OHCI_INST (controller)->hcca = memalign(256, 256); memset((void*)OHCI_INST (controller)->hcca, 0, 256); + /* Initialize interrupt table. */ + u32 *const intr_table = OHCI_INST(controller)->hcca->HccaInterruptTable; + ed_t *const periodic_ed = memalign(sizeof(ed_t), sizeof(ed_t)); + memset((void *)periodic_ed, 0, sizeof(*periodic_ed)); + for (i = 0; i < 32; ++i) + intr_table[i] = virt_to_phys(periodic_ed); + OHCI_INST (controller)->periodic_ed = periodic_ed; + OHCI_INST (controller)->opreg->HcHCCA = virt_to_phys(OHCI_INST (controller)->hcca); OHCI_INST (controller)->opreg->HcControl &= ~IsochronousEnable; // unused by this driver // disable everything, contrary to what OHCI spec says in 5.1.1.4, as we don't need IRQs @@ -167,6 +170,7 @@ ohci_shutdown (hci_t *controller) ohci_stop(controller); OHCI_INST (controller)->roothub->destroy (OHCI_INST (controller)-> roothub); + free ((void *)OHCI_INST (controller)->periodic_ed); free (OHCI_INST (controller)); free (controller); } diff --git a/payloads/libpayload/drivers/usb/ohci_private.h b/payloads/libpayload/drivers/usb/ohci_private.h index 0bcae03e97..3826db08ee 100644 --- a/payloads/libpayload/drivers/usb/ohci_private.h +++ b/payloads/libpayload/drivers/usb/ohci_private.h @@ -189,22 +189,15 @@ volatile u32 HcRhPortStatus[]; } __attribute__ ((packed)) opreg_t; - typedef struct { + typedef struct { /* should be 256 bytes according to spec */ u32 HccaInterruptTable[32]; volatile u16 HccaFrameNumber; volatile u16 HccaPad1; volatile u32 HccaDoneHead; - u8 reserved[116]; // pad to 256 byte + u8 reserved[116]; /* pad according to spec */ + u8 what[4]; /* really pad to 256 as spec only covers 252 */ } __attribute__ ((packed)) hcca_t; - typedef struct ohci { - opreg_t *opreg; - hcca_t *hcca; - usbdev_t *roothub; - } ohci_t; - - typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t; - typedef volatile struct { u32 config; u32 tail_pointer; @@ -259,4 +252,13 @@ #define OHCI_INST(controller) ((ohci_t*)((controller)->instance)) + typedef struct ohci { + opreg_t *opreg; + hcca_t *hcca; + usbdev_t *roothub; + ed_t *periodic_ed; + } ohci_t; + + typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t; + #endif |