[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/3] hw/usb/hcd-ohci.c: Move sysbus and PCI code to
From: |
Ákos Kovács |
Subject: |
[Qemu-devel] [PATCH 1/3] hw/usb/hcd-ohci.c: Move sysbus and PCI code to new files |
Date: |
Fri, 23 Aug 2013 03:18:50 +0200 |
Move the existing sysbus and PCI logic to hcd-ohci-sysbus.c and
hcd-ohci-pci.c from hcd-ohci.c. Create a new hcd-ohci.h header for the
shared declarations and macros.
Signed-off-by: Ákos Kovács <address@hidden>
---
hw/usb/hcd-ohci-pci.c | 96 ++++++++++
hw/usb/hcd-ohci-sysbus.c | 84 +++++++++
hw/usb/hcd-ohci.c | 434 +++-------------------------------------------
hw/usb/hcd-ohci.h | 311 +++++++++++++++++++++++++++++++++
4 files changed, 514 insertions(+), 411 deletions(-)
create mode 100644 hw/usb/hcd-ohci-pci.c
create mode 100644 hw/usb/hcd-ohci-sysbus.c
create mode 100644 hw/usb/hcd-ohci.h
diff --git a/hw/usb/hcd-ohci-pci.c b/hw/usb/hcd-ohci-pci.c
new file mode 100644
index 0000000..ac50951
--- /dev/null
+++ b/hw/usb/hcd-ohci-pci.c
@@ -0,0 +1,96 @@
+/*
+ * QEMU USB OHCI Emulation
+ * Copyright (c) 2004 Gianni Tedesco
+ * Copyright (c) 2006 CodeSourcery
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * TODO:
+ * o Isochronous transfers
+ * o Allocate bandwidth in frames properly
+ * o Disable timers when nothing needs to be done, or remove timer usage
+ * all together.
+ * o BIOS work to boot from USB storage
+*/
+
+#include "hw/usb/hcd-ohci.h"
+
+#define TYPE_PCI_OHCI "pci-ohci"
+#define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
+
+typedef struct {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
+ OHCIState state;
+ char *masterbus;
+ uint32_t num_ports;
+ uint32_t firstport;
+} OHCIPCIState;
+
+static Property ohci_pci_properties[] = {
+ DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
+ DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
+ DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static int usb_ohci_initfn_pci(PCIDevice *dev)
+{
+ OHCIPCIState *ohci = PCI_OHCI(dev);
+
+ dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */
+ dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
+
+ if (usb_ohci_init(&ohci->state, DEVICE(dev), ohci->num_ports, 0,
+ ohci->masterbus, ohci->firstport,
+ pci_get_address_space(dev)) != 0) {
+ return -1;
+ }
+ ohci->state.irq = dev->irq[0];
+
+ pci_register_bar(dev, 0, 0, &ohci->state.mem);
+ return 0;
+}
+
+static void ohci_pci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = usb_ohci_initfn_pci;
+ k->vendor_id = PCI_VENDOR_ID_APPLE;
+ k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+ k->no_hotplug = 1;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
+ dc->desc = "Apple USB Controller";
+ dc->props = ohci_pci_properties;
+}
+
+static const TypeInfo ohci_pci_info = {
+ .name = TYPE_PCI_OHCI,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(OHCIPCIState),
+ .class_init = ohci_pci_class_init,
+};
+
+static void ohci_pci_register_type(void)
+{
+ type_register_static(&ohci_pci_info);
+}
+
+type_init(ohci_pci_register_type)
diff --git a/hw/usb/hcd-ohci-sysbus.c b/hw/usb/hcd-ohci-sysbus.c
new file mode 100644
index 0000000..b9d15db
--- /dev/null
+++ b/hw/usb/hcd-ohci-sysbus.c
@@ -0,0 +1,84 @@
+/*
+ * QEMU USB OHCI Emulation
+ * Copyright (c) 2004 Gianni Tedesco
+ * Copyright (c) 2006 CodeSourcery
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * TODO:
+ * o Isochronous transfers
+ * o Allocate bandwidth in frames properly
+ * o Disable timers when nothing needs to be done, or remove timer usage
+ * all together.
+ * o BIOS work to boot from USB storage
+*/
+
+#include "hw/sysbus.h"
+#include "hw/usb/hcd-ohci.h"
+
+#define TYPE_SYSBUS_OHCI "sysbus-ohci"
+#define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
+
+typedef struct {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ OHCIState ohci;
+ uint32_t num_ports;
+ dma_addr_t dma_offset;
+} OHCISysBusState;
+
+static Property ohci_sysbus_properties[] = {
+ DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
+ DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 3),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ohci_realize_pxa(DeviceState *dev, Error **errp)
+{
+ OHCISysBusState *s = SYSBUS_OHCI(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ /* Cannot fail as we pass NULL for masterbus */
+ usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
+ &address_space_memory);
+ sysbus_init_irq(sbd, &s->ohci.irq);
+ sysbus_init_mmio(sbd, &s->ohci.mem);
+}
+
+static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = ohci_realize_pxa;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
+ dc->desc = "OHCI USB Controller";
+ dc->props = ohci_sysbus_properties;
+}
+
+static const TypeInfo ohci_sysbus_info = {
+ .name = TYPE_SYSBUS_OHCI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(OHCISysBusState),
+ .class_init = ohci_sysbus_class_init,
+};
+
+static void ohci_sysbus_register_type(void)
+{
+ type_register_static(&ohci_sysbus_info);
+}
+
+type_init(ohci_sysbus_register_type)
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index d7836d6..a2a5a0b 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -25,290 +25,15 @@
* o BIOS work to boot from USB storage
*/
-#include "hw/hw.h"
-#include "qemu/timer.h"
-#include "hw/usb.h"
-#include "hw/pci/pci.h"
-#include "hw/sysbus.h"
-#include "hw/qdev-dma.h"
-
-//#define DEBUG_OHCI
-/* Dump packet contents. */
-//#define DEBUG_PACKET
-//#define DEBUG_ISOCH
-/* This causes frames to occur 1000x slower */
-//#define OHCI_TIME_WARP 1
-
-#ifdef DEBUG_OHCI
-#define DPRINTF printf
-#else
-#define DPRINTF(...)
-#endif
-
-/* Number of Downstream Ports on the root hub. */
-
-#define OHCI_MAX_PORTS 15
+#include "hw/usb/hcd-ohci.h"
static int64_t usb_frame_time;
static int64_t usb_bit_time;
-typedef struct OHCIPort {
- USBPort port;
- uint32_t ctrl;
-} OHCIPort;
-
-typedef struct {
- USBBus bus;
- qemu_irq irq;
- MemoryRegion mem;
- AddressSpace *as;
- int num_ports;
- const char *name;
-
- QEMUTimer *eof_timer;
- int64_t sof_time;
-
- /* OHCI state */
- /* Control partition */
- uint32_t ctl, status;
- uint32_t intr_status;
- uint32_t intr;
-
- /* memory pointer partition */
- uint32_t hcca;
- uint32_t ctrl_head, ctrl_cur;
- uint32_t bulk_head, bulk_cur;
- uint32_t per_cur;
- uint32_t done;
- int done_count;
-
- /* Frame counter partition */
- uint32_t fsmps:15;
- uint32_t fit:1;
- uint32_t fi:14;
- uint32_t frt:1;
- uint16_t frame_number;
- uint16_t padding;
- uint32_t pstart;
- uint32_t lst;
-
- /* Root Hub partition */
- uint32_t rhdesc_a, rhdesc_b;
- uint32_t rhstatus;
- OHCIPort rhport[OHCI_MAX_PORTS];
-
- /* PXA27x Non-OHCI events */
- uint32_t hstatus;
- uint32_t hmask;
- uint32_t hreset;
- uint32_t htest;
-
- /* SM501 local memory offset */
- dma_addr_t localmem_base;
-
- /* Active packets. */
- uint32_t old_ctl;
- USBPacket usb_packet;
- uint8_t usb_buf[8192];
- uint32_t async_td;
- int async_complete;
-
-} OHCIState;
-
-/* Host Controller Communications Area */
-struct ohci_hcca {
- uint32_t intr[32];
- uint16_t frame, pad;
- uint32_t done;
-};
-#define HCCA_WRITEBACK_OFFSET offsetof(struct ohci_hcca, frame)
-#define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */
-
-#define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
-#define ED_WBACK_SIZE 4
-
+static void ohci_die(OHCIState *ohci);
static void ohci_bus_stop(OHCIState *ohci);
static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
-/* Bitfields for the first word of an Endpoint Desciptor. */
-#define OHCI_ED_FA_SHIFT 0
-#define OHCI_ED_FA_MASK (0x7f<<OHCI_ED_FA_SHIFT)
-#define OHCI_ED_EN_SHIFT 7
-#define OHCI_ED_EN_MASK (0xf<<OHCI_ED_EN_SHIFT)
-#define OHCI_ED_D_SHIFT 11
-#define OHCI_ED_D_MASK (3<<OHCI_ED_D_SHIFT)
-#define OHCI_ED_S (1<<13)
-#define OHCI_ED_K (1<<14)
-#define OHCI_ED_F (1<<15)
-#define OHCI_ED_MPS_SHIFT 16
-#define OHCI_ED_MPS_MASK (0x7ff<<OHCI_ED_MPS_SHIFT)
-
-/* Flags in the head field of an Endpoint Desciptor. */
-#define OHCI_ED_H 1
-#define OHCI_ED_C 2
-
-/* Bitfields for the first word of a Transfer Desciptor. */
-#define OHCI_TD_R (1<<18)
-#define OHCI_TD_DP_SHIFT 19
-#define OHCI_TD_DP_MASK (3<<OHCI_TD_DP_SHIFT)
-#define OHCI_TD_DI_SHIFT 21
-#define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT)
-#define OHCI_TD_T0 (1<<24)
-#define OHCI_TD_T1 (1<<25)
-#define OHCI_TD_EC_SHIFT 26
-#define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT)
-#define OHCI_TD_CC_SHIFT 28
-#define OHCI_TD_CC_MASK (0xf<<OHCI_TD_CC_SHIFT)
-
-/* Bitfields for the first word of an Isochronous Transfer Desciptor. */
-/* CC & DI - same as in the General Transfer Desciptor */
-#define OHCI_TD_SF_SHIFT 0
-#define OHCI_TD_SF_MASK (0xffff<<OHCI_TD_SF_SHIFT)
-#define OHCI_TD_FC_SHIFT 24
-#define OHCI_TD_FC_MASK (7<<OHCI_TD_FC_SHIFT)
-
-/* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
-#define OHCI_TD_PSW_CC_SHIFT 12
-#define OHCI_TD_PSW_CC_MASK (0xf<<OHCI_TD_PSW_CC_SHIFT)
-#define OHCI_TD_PSW_SIZE_SHIFT 0
-#define OHCI_TD_PSW_SIZE_MASK (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
-
-#define OHCI_PAGE_MASK 0xfffff000
-#define OHCI_OFFSET_MASK 0xfff
-
-#define OHCI_DPTR_MASK 0xfffffff0
-
-#define OHCI_BM(val, field) \
- (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
-
-#define OHCI_SET_BM(val, field, newval) do { \
- val &= ~OHCI_##field##_MASK; \
- val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
- } while(0)
-
-/* endpoint descriptor */
-struct ohci_ed {
- uint32_t flags;
- uint32_t tail;
- uint32_t head;
- uint32_t next;
-};
-
-/* General transfer descriptor */
-struct ohci_td {
- uint32_t flags;
- uint32_t cbp;
- uint32_t next;
- uint32_t be;
-};
-
-/* Isochronous transfer descriptor */
-struct ohci_iso_td {
- uint32_t flags;
- uint32_t bp;
- uint32_t next;
- uint32_t be;
- uint16_t offset[8];
-};
-
-#define USB_HZ 12000000
-
-/* OHCI Local stuff */
-#define OHCI_CTL_CBSR ((1<<0)|(1<<1))
-#define OHCI_CTL_PLE (1<<2)
-#define OHCI_CTL_IE (1<<3)
-#define OHCI_CTL_CLE (1<<4)
-#define OHCI_CTL_BLE (1<<5)
-#define OHCI_CTL_HCFS ((1<<6)|(1<<7))
-#define OHCI_USB_RESET 0x00
-#define OHCI_USB_RESUME 0x40
-#define OHCI_USB_OPERATIONAL 0x80
-#define OHCI_USB_SUSPEND 0xc0
-#define OHCI_CTL_IR (1<<8)
-#define OHCI_CTL_RWC (1<<9)
-#define OHCI_CTL_RWE (1<<10)
-
-#define OHCI_STATUS_HCR (1<<0)
-#define OHCI_STATUS_CLF (1<<1)
-#define OHCI_STATUS_BLF (1<<2)
-#define OHCI_STATUS_OCR (1<<3)
-#define OHCI_STATUS_SOC ((1<<6)|(1<<7))
-
-#define OHCI_INTR_SO (1<<0) /* Scheduling overrun */
-#define OHCI_INTR_WD (1<<1) /* HcDoneHead writeback */
-#define OHCI_INTR_SF (1<<2) /* Start of frame */
-#define OHCI_INTR_RD (1<<3) /* Resume detect */
-#define OHCI_INTR_UE (1<<4) /* Unrecoverable error */
-#define OHCI_INTR_FNO (1<<5) /* Frame number overflow */
-#define OHCI_INTR_RHSC (1<<6) /* Root hub status change */
-#define OHCI_INTR_OC (1<<30) /* Ownership change */
-#define OHCI_INTR_MIE (1<<31) /* Master Interrupt Enable */
-
-#define OHCI_HCCA_SIZE 0x100
-#define OHCI_HCCA_MASK 0xffffff00
-
-#define OHCI_EDPTR_MASK 0xfffffff0
-
-#define OHCI_FMI_FI 0x00003fff
-#define OHCI_FMI_FSMPS 0xffff0000
-#define OHCI_FMI_FIT 0x80000000
-
-#define OHCI_FR_RT (1<<31)
-
-#define OHCI_LS_THRESH 0x628
-
-#define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */
-#define OHCI_RHA_PSM (1<<8)
-#define OHCI_RHA_NPS (1<<9)
-#define OHCI_RHA_DT (1<<10)
-#define OHCI_RHA_OCPM (1<<11)
-#define OHCI_RHA_NOCP (1<<12)
-#define OHCI_RHA_POTPGT_MASK 0xff000000
-
-#define OHCI_RHS_LPS (1<<0)
-#define OHCI_RHS_OCI (1<<1)
-#define OHCI_RHS_DRWE (1<<15)
-#define OHCI_RHS_LPSC (1<<16)
-#define OHCI_RHS_OCIC (1<<17)
-#define OHCI_RHS_CRWE (1<<31)
-
-#define OHCI_PORT_CCS (1<<0)
-#define OHCI_PORT_PES (1<<1)
-#define OHCI_PORT_PSS (1<<2)
-#define OHCI_PORT_POCI (1<<3)
-#define OHCI_PORT_PRS (1<<4)
-#define OHCI_PORT_PPS (1<<8)
-#define OHCI_PORT_LSDA (1<<9)
-#define OHCI_PORT_CSC (1<<16)
-#define OHCI_PORT_PESC (1<<17)
-#define OHCI_PORT_PSSC (1<<18)
-#define OHCI_PORT_OCIC (1<<19)
-#define OHCI_PORT_PRSC (1<<20)
-#define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
- |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
-
-#define OHCI_TD_DIR_SETUP 0x0
-#define OHCI_TD_DIR_OUT 0x1
-#define OHCI_TD_DIR_IN 0x2
-#define OHCI_TD_DIR_RESERVED 0x3
-
-#define OHCI_CC_NOERROR 0x0
-#define OHCI_CC_CRC 0x1
-#define OHCI_CC_BITSTUFFING 0x2
-#define OHCI_CC_DATATOGGLEMISMATCH 0x3
-#define OHCI_CC_STALL 0x4
-#define OHCI_CC_DEVICENOTRESPONDING 0x5
-#define OHCI_CC_PIDCHECKFAILURE 0x6
-#define OHCI_CC_UNDEXPETEDPID 0x7
-#define OHCI_CC_DATAOVERRUN 0x8
-#define OHCI_CC_DATAUNDERRUN 0x9
-#define OHCI_CC_BUFFEROVERRUN 0xc
-#define OHCI_CC_BUFFERUNDERRUN 0xd
-
-#define OHCI_HRESET_FSBIR (1 << 0)
-
-static void ohci_die(OHCIState *ohci);
-
/* Update IRQ levels */
static inline void ohci_intr_update(OHCIState *ohci)
{
@@ -1844,7 +1569,27 @@ static USBPortOps ohci_port_ops = {
static USBBusOps ohci_bus_ops = {
};
-static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
+/** A typical O/EHCI will stop operating, set itself into error state
+ * (which can be queried by MMIO) and will set PERR in its config
+ * space to signal that it got an error
+ */
+void ohci_die(OHCIState *ohci)
+{
+ BusState *qbus = BUS(&ohci->bus);
+ DeviceState *dev = qbus->parent;
+ PCIDevice *pci = (PCIDevice *)object_dynamic_cast(OBJECT(dev),
TYPE_PCI_DEVICE);
+
+ fprintf(stderr, "%s: DMA error\n", __func__);
+
+ ohci_set_interrupt(ohci, OHCI_INTR_UE);
+ ohci_bus_stop(ohci);
+ if (pci) {
+ pci_set_word(pci->config + PCI_STATUS,
+ PCI_STATUS_DETECTED_PARITY);
+ }
+}
+
+int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
int num_ports, dma_addr_t localmem_base,
char *masterbus, uint32_t firstport,
AddressSpace *as)
@@ -1901,136 +1646,3 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState
*dev,
return 0;
}
-
-#define TYPE_PCI_OHCI "pci-ohci"
-#define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
-
-typedef struct {
- /*< private >*/
- PCIDevice parent_obj;
- /*< public >*/
-
- OHCIState state;
- char *masterbus;
- uint32_t num_ports;
- uint32_t firstport;
-} OHCIPCIState;
-
-/** A typical O/EHCI will stop operating, set itself into error state
- * (which can be queried by MMIO) and will set PERR in its config
- * space to signal that it got an error
- */
-static void ohci_die(OHCIState *ohci)
-{
- OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state);
-
- fprintf(stderr, "%s: DMA error\n", __func__);
-
- ohci_set_interrupt(ohci, OHCI_INTR_UE);
- ohci_bus_stop(ohci);
- pci_set_word(dev->parent_obj.config + PCI_STATUS,
- PCI_STATUS_DETECTED_PARITY);
-}
-
-static int usb_ohci_initfn_pci(PCIDevice *dev)
-{
- OHCIPCIState *ohci = PCI_OHCI(dev);
-
- dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */
- dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
-
- if (usb_ohci_init(&ohci->state, DEVICE(dev), ohci->num_ports, 0,
- ohci->masterbus, ohci->firstport,
- pci_get_address_space(dev)) != 0) {
- return -1;
- }
- ohci->state.irq = dev->irq[0];
-
- pci_register_bar(dev, 0, 0, &ohci->state.mem);
- return 0;
-}
-
-#define TYPE_SYSBUS_OHCI "sysbus-ohci"
-#define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
-
-typedef struct {
- /*< private >*/
- SysBusDevice parent_obj;
- /*< public >*/
-
- OHCIState ohci;
- uint32_t num_ports;
- dma_addr_t dma_offset;
-} OHCISysBusState;
-
-static void ohci_realize_pxa(DeviceState *dev, Error **errp)
-{
- OHCISysBusState *s = SYSBUS_OHCI(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-
- /* Cannot fail as we pass NULL for masterbus */
- usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
- &address_space_memory);
- sysbus_init_irq(sbd, &s->ohci.irq);
- sysbus_init_mmio(sbd, &s->ohci.mem);
-}
-
-static Property ohci_pci_properties[] = {
- DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
- DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
- DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ohci_pci_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
- k->init = usb_ohci_initfn_pci;
- k->vendor_id = PCI_VENDOR_ID_APPLE;
- k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
- k->class_id = PCI_CLASS_SERIAL_USB;
- k->no_hotplug = 1;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- dc->desc = "Apple USB Controller";
- dc->props = ohci_pci_properties;
-}
-
-static const TypeInfo ohci_pci_info = {
- .name = TYPE_PCI_OHCI,
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(OHCIPCIState),
- .class_init = ohci_pci_class_init,
-};
-
-static Property ohci_sysbus_properties[] = {
- DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
- DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 3),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = ohci_realize_pxa;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- dc->desc = "OHCI USB Controller";
- dc->props = ohci_sysbus_properties;
-}
-
-static const TypeInfo ohci_sysbus_info = {
- .name = TYPE_SYSBUS_OHCI,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(OHCISysBusState),
- .class_init = ohci_sysbus_class_init,
-};
-
-static void ohci_register_types(void)
-{
- type_register_static(&ohci_pci_info);
- type_register_static(&ohci_sysbus_info);
-}
-
-type_init(ohci_register_types)
diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h
new file mode 100644
index 0000000..8be00f2
--- /dev/null
+++ b/hw/usb/hcd-ohci.h
@@ -0,0 +1,311 @@
+/*
+ * QEMU USB OHCI Emulation
+ * Copyright (c) 2004 Gianni Tedesco
+ * Copyright (c) 2006 CodeSourcery
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * TODO:
+ * o Isochronous transfers
+ * o Allocate bandwidth in frames properly
+ * o Disable timers when nothing needs to be done, or remove timer usage
+ * all together.
+ * o BIOS work to boot from USB storage
+*/
+
+#ifndef HW_USB_OHCI_H
+#define HW_USB_OHCI_H 1
+
+#include "hw/hw.h"
+#include "qemu/timer.h"
+#include "hw/usb.h"
+#include "hw/qdev-dma.h"
+#include "hw/pci/pci.h"
+
+//#define DEBUG_OHCI
+/* Dump packet contents. */
+//#define DEBUG_PACKET
+//#define DEBUG_ISOCH
+/* This causes frames to occur 1000x slower */
+//#define OHCI_TIME_WARP 1
+
+#ifdef DEBUG_OHCI
+#define DPRINTF printf
+#else
+#define DPRINTF(...)
+#endif
+
+/* Number of Downstream Ports on the root hub. */
+
+#define OHCI_MAX_PORTS 15
+
+typedef struct OHCIPort {
+ USBPort port;
+ uint32_t ctrl;
+} OHCIPort;
+
+typedef struct {
+ USBBus bus;
+ qemu_irq irq;
+ MemoryRegion mem;
+ AddressSpace *as;
+ int num_ports;
+ const char *name;
+
+ QEMUTimer *eof_timer;
+ int64_t sof_time;
+
+ /* OHCI state */
+ /* Control partition */
+ uint32_t ctl, status;
+ uint32_t intr_status;
+ uint32_t intr;
+
+ /* memory pointer partition */
+ uint32_t hcca;
+ uint32_t ctrl_head, ctrl_cur;
+ uint32_t bulk_head, bulk_cur;
+ uint32_t per_cur;
+ uint32_t done;
+ int done_count;
+
+ /* Frame counter partition */
+ uint32_t fsmps:15;
+ uint32_t fit:1;
+ uint32_t fi:14;
+ uint32_t frt:1;
+ uint16_t frame_number;
+ uint16_t padding;
+ uint32_t pstart;
+ uint32_t lst;
+
+ /* Root Hub partition */
+ uint32_t rhdesc_a, rhdesc_b;
+ uint32_t rhstatus;
+ OHCIPort rhport[OHCI_MAX_PORTS];
+
+ /* PXA27x Non-OHCI events */
+ uint32_t hstatus;
+ uint32_t hmask;
+ uint32_t hreset;
+ uint32_t htest;
+
+ /* SM501 local memory offset */
+ dma_addr_t localmem_base;
+
+ /* Active packets. */
+ uint32_t old_ctl;
+ USBPacket usb_packet;
+ uint8_t usb_buf[8192];
+ uint32_t async_td;
+ int async_complete;
+
+} OHCIState;
+
+/* Host Controller Communications Area */
+struct ohci_hcca {
+ uint32_t intr[32];
+ uint16_t frame, pad;
+ uint32_t done;
+};
+#define HCCA_WRITEBACK_OFFSET offsetof(struct ohci_hcca, frame)
+#define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */
+
+#define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
+#define ED_WBACK_SIZE 4
+
+/* Bitfields for the first word of an Endpoint Desciptor. */
+#define OHCI_ED_FA_SHIFT 0
+#define OHCI_ED_FA_MASK (0x7f<<OHCI_ED_FA_SHIFT)
+#define OHCI_ED_EN_SHIFT 7
+#define OHCI_ED_EN_MASK (0xf<<OHCI_ED_EN_SHIFT)
+#define OHCI_ED_D_SHIFT 11
+#define OHCI_ED_D_MASK (3<<OHCI_ED_D_SHIFT)
+#define OHCI_ED_S (1<<13)
+#define OHCI_ED_K (1<<14)
+#define OHCI_ED_F (1<<15)
+#define OHCI_ED_MPS_SHIFT 16
+#define OHCI_ED_MPS_MASK (0x7ff<<OHCI_ED_MPS_SHIFT)
+
+/* Flags in the head field of an Endpoint Desciptor. */
+#define OHCI_ED_H 1
+#define OHCI_ED_C 2
+
+/* Bitfields for the first word of a Transfer Desciptor. */
+#define OHCI_TD_R (1<<18)
+#define OHCI_TD_DP_SHIFT 19
+#define OHCI_TD_DP_MASK (3<<OHCI_TD_DP_SHIFT)
+#define OHCI_TD_DI_SHIFT 21
+#define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT)
+#define OHCI_TD_T0 (1<<24)
+#define OHCI_TD_T1 (1<<25)
+#define OHCI_TD_EC_SHIFT 26
+#define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT)
+#define OHCI_TD_CC_SHIFT 28
+#define OHCI_TD_CC_MASK (0xf<<OHCI_TD_CC_SHIFT)
+
+/* Bitfields for the first word of an Isochronous Transfer Desciptor. */
+/* CC & DI - same as in the General Transfer Desciptor */
+#define OHCI_TD_SF_SHIFT 0
+#define OHCI_TD_SF_MASK (0xffff<<OHCI_TD_SF_SHIFT)
+#define OHCI_TD_FC_SHIFT 24
+#define OHCI_TD_FC_MASK (7<<OHCI_TD_FC_SHIFT)
+
+/* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
+#define OHCI_TD_PSW_CC_SHIFT 12
+#define OHCI_TD_PSW_CC_MASK (0xf<<OHCI_TD_PSW_CC_SHIFT)
+#define OHCI_TD_PSW_SIZE_SHIFT 0
+#define OHCI_TD_PSW_SIZE_MASK (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
+
+#define OHCI_PAGE_MASK 0xfffff000
+#define OHCI_OFFSET_MASK 0xfff
+
+#define OHCI_DPTR_MASK 0xfffffff0
+
+#define OHCI_BM(val, field) \
+ (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
+
+#define OHCI_SET_BM(val, field, newval) do { \
+ val &= ~OHCI_##field##_MASK; \
+ val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
+ } while(0)
+
+/* endpoint descriptor */
+struct ohci_ed {
+ uint32_t flags;
+ uint32_t tail;
+ uint32_t head;
+ uint32_t next;
+};
+
+/* General transfer descriptor */
+struct ohci_td {
+ uint32_t flags;
+ uint32_t cbp;
+ uint32_t next;
+ uint32_t be;
+};
+
+/* Isochronous transfer descriptor */
+struct ohci_iso_td {
+ uint32_t flags;
+ uint32_t bp;
+ uint32_t next;
+ uint32_t be;
+ uint16_t offset[8];
+};
+
+#define USB_HZ 12000000
+
+/* OHCI Local stuff */
+#define OHCI_CTL_CBSR ((1<<0)|(1<<1))
+#define OHCI_CTL_PLE (1<<2)
+#define OHCI_CTL_IE (1<<3)
+#define OHCI_CTL_CLE (1<<4)
+#define OHCI_CTL_BLE (1<<5)
+#define OHCI_CTL_HCFS ((1<<6)|(1<<7))
+#define OHCI_USB_RESET 0x00
+#define OHCI_USB_RESUME 0x40
+#define OHCI_USB_OPERATIONAL 0x80
+#define OHCI_USB_SUSPEND 0xc0
+#define OHCI_CTL_IR (1<<8)
+#define OHCI_CTL_RWC (1<<9)
+#define OHCI_CTL_RWE (1<<10)
+
+#define OHCI_STATUS_HCR (1<<0)
+#define OHCI_STATUS_CLF (1<<1)
+#define OHCI_STATUS_BLF (1<<2)
+#define OHCI_STATUS_OCR (1<<3)
+#define OHCI_STATUS_SOC ((1<<6)|(1<<7))
+
+#define OHCI_INTR_SO (1<<0) /* Scheduling overrun */
+#define OHCI_INTR_WD (1<<1) /* HcDoneHead writeback */
+#define OHCI_INTR_SF (1<<2) /* Start of frame */
+#define OHCI_INTR_RD (1<<3) /* Resume detect */
+#define OHCI_INTR_UE (1<<4) /* Unrecoverable error */
+#define OHCI_INTR_FNO (1<<5) /* Frame number overflow */
+#define OHCI_INTR_RHSC (1<<6) /* Root hub status change */
+#define OHCI_INTR_OC (1<<30) /* Ownership change */
+#define OHCI_INTR_MIE (1<<31) /* Master Interrupt Enable */
+
+#define OHCI_HCCA_SIZE 0x100
+#define OHCI_HCCA_MASK 0xffffff00
+
+#define OHCI_EDPTR_MASK 0xfffffff0
+
+#define OHCI_FMI_FI 0x00003fff
+#define OHCI_FMI_FSMPS 0xffff0000
+#define OHCI_FMI_FIT 0x80000000
+
+#define OHCI_FR_RT (1<<31)
+
+#define OHCI_LS_THRESH 0x628
+
+#define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */
+#define OHCI_RHA_PSM (1<<8)
+#define OHCI_RHA_NPS (1<<9)
+#define OHCI_RHA_DT (1<<10)
+#define OHCI_RHA_OCPM (1<<11)
+#define OHCI_RHA_NOCP (1<<12)
+#define OHCI_RHA_POTPGT_MASK 0xff000000
+
+#define OHCI_RHS_LPS (1<<0)
+#define OHCI_RHS_OCI (1<<1)
+#define OHCI_RHS_DRWE (1<<15)
+#define OHCI_RHS_LPSC (1<<16)
+#define OHCI_RHS_OCIC (1<<17)
+#define OHCI_RHS_CRWE (1<<31)
+
+#define OHCI_PORT_CCS (1<<0)
+#define OHCI_PORT_PES (1<<1)
+#define OHCI_PORT_PSS (1<<2)
+#define OHCI_PORT_POCI (1<<3)
+#define OHCI_PORT_PRS (1<<4)
+#define OHCI_PORT_PPS (1<<8)
+#define OHCI_PORT_LSDA (1<<9)
+#define OHCI_PORT_CSC (1<<16)
+#define OHCI_PORT_PESC (1<<17)
+#define OHCI_PORT_PSSC (1<<18)
+#define OHCI_PORT_OCIC (1<<19)
+#define OHCI_PORT_PRSC (1<<20)
+#define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
+ |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
+
+#define OHCI_TD_DIR_SETUP 0x0
+#define OHCI_TD_DIR_OUT 0x1
+#define OHCI_TD_DIR_IN 0x2
+#define OHCI_TD_DIR_RESERVED 0x3
+
+#define OHCI_CC_NOERROR 0x0
+#define OHCI_CC_CRC 0x1
+#define OHCI_CC_BITSTUFFING 0x2
+#define OHCI_CC_DATATOGGLEMISMATCH 0x3
+#define OHCI_CC_STALL 0x4
+#define OHCI_CC_DEVICENOTRESPONDING 0x5
+#define OHCI_CC_PIDCHECKFAILURE 0x6
+#define OHCI_CC_UNDEXPETEDPID 0x7
+#define OHCI_CC_DATAOVERRUN 0x8
+#define OHCI_CC_DATAUNDERRUN 0x9
+#define OHCI_CC_BUFFEROVERRUN 0xc
+#define OHCI_CC_BUFFERUNDERRUN 0xd
+
+#define OHCI_HRESET_FSBIR (1 << 0)
+
+int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
+ int num_ports, dma_addr_t localmem_base,
+ char *masterbus, uint32_t firstport,
+ AddressSpace *as);
+
+#endif /* HW_USB_OHCI_H */
--
1.7.10.4