summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Huber <nico.huber@secunet.com>2012-06-20 11:37:17 +0200
committerNico Huber <nico.huber@secunet.com>2012-06-21 11:55:34 +0200
commit542fe85da956c62e46da1d9cfeb79c3d06b75427 (patch)
tree4f4471cdfe1a4e87a0d04a54d8260f5141123de6
parent9951adeffd02c0226c5dd9dcbddbab9d86e28ee4 (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.c14
-rw-r--r--payloads/libpayload/drivers/usb/ohci_private.h22
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