* o Allocate bandwidth in frames properly
* o Disable timers when nothing needs to be done, or remove timer usage
* all together.
- * o Handle unrecoverable errors properly
* o BIOS work to boot from USB storage
*/
#include "hw/hw.h"
-#include "qemu-timer.h"
+#include "qemu/timer.h"
#include "hw/usb.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
#include "hw/sysbus.h"
#include "hw/qdev-dma.h"
USBBus bus;
qemu_irq irq;
MemoryRegion mem;
- DMAContext *dma;
+ AddressSpace *as;
int num_ports;
const char *name;
#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_INTR_SO (1U<<0) /* Scheduling overrun */
+#define OHCI_INTR_WD (1U<<1) /* HcDoneHead writeback */
+#define OHCI_INTR_SF (1U<<2) /* Start of frame */
+#define OHCI_INTR_RD (1U<<3) /* Resume detect */
+#define OHCI_INTR_UE (1U<<4) /* Unrecoverable error */
+#define OHCI_INTR_FNO (1U<<5) /* Frame number overflow */
+#define OHCI_INTR_RHSC (1U<<6) /* Root hub status change */
+#define OHCI_INTR_OC (1U<<30) /* Ownership change */
+#define OHCI_INTR_MIE (1U<<31) /* Master Interrupt Enable */
#define OHCI_HCCA_SIZE 0x100
#define OHCI_HCCA_MASK 0xffffff00
#define OHCI_FMI_FSMPS 0xffff0000
#define OHCI_FMI_FIT 0x80000000
-#define OHCI_FR_RT (1<<31)
+#define OHCI_FR_RT (1U<<31)
#define OHCI_LS_THRESH 0x628
#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_RHS_LPS (1U<<0)
+#define OHCI_RHS_OCI (1U<<1)
+#define OHCI_RHS_DRWE (1U<<15)
+#define OHCI_RHS_LPSC (1U<<16)
+#define OHCI_RHS_OCIC (1U<<17)
+#define OHCI_RHS_CRWE (1U<<31)
#define OHCI_PORT_CCS (1<<0)
#define OHCI_PORT_PES (1<<1)
#define OHCI_HRESET_FSBIR (1 << 0)
+static void ohci_die(OHCIState *ohci);
+
/* Update IRQ levels */
static inline void ohci_intr_update(OHCIState *ohci)
{
return NULL;
}
+static void ohci_stop_endpoints(OHCIState *ohci)
+{
+ USBDevice *dev;
+ int i, j;
+
+ for (i = 0; i < ohci->num_ports; i++) {
+ dev = ohci->rhport[i].port.dev;
+ if (dev && dev->attached) {
+ usb_device_ep_stopped(dev, &dev->ep_ctl);
+ for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
+ usb_device_ep_stopped(dev, &dev->ep_in[j]);
+ usb_device_ep_stopped(dev, &dev->ep_out[j]);
+ }
+ }
+ }
+}
+
/* Reset the controller */
static void ohci_reset(void *opaque)
{
usb_cancel_packet(&ohci->usb_packet);
ohci->async_td = 0;
}
+ ohci_stop_endpoints(ohci);
DPRINTF("usb-ohci: Reset %s\n", ohci->name);
}
addr += ohci->localmem_base;
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
- dma_memory_read(ohci->dma, addr, buf, sizeof(*buf));
+ if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
+ return -1;
+ }
*buf = le32_to_cpu(*buf);
}
- return 1;
+ return 0;
}
/* Put an array of dwords in to main memory */
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
uint32_t tmp = cpu_to_le32(*buf);
- dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp));
+ if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
+ return -1;
+ }
}
- return 1;
+ return 0;
}
/* Get an array of words from main memory */
addr += ohci->localmem_base;
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
- dma_memory_read(ohci->dma, addr, buf, sizeof(*buf));
+ if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
+ return -1;
+ }
*buf = le16_to_cpu(*buf);
}
- return 1;
+ return 0;
}
/* Put an array of words in to main memory */
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
uint16_t tmp = cpu_to_le16(*buf);
- dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp));
+ if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
+ return -1;
+ }
}
- return 1;
+ return 0;
}
static inline int ohci_read_ed(OHCIState *ohci,
static inline int ohci_read_iso_td(OHCIState *ohci,
dma_addr_t addr, struct ohci_iso_td *td)
{
- return (get_dwords(ohci, addr, (uint32_t *)td, 4) &&
- get_words(ohci, addr + 16, td->offset, 8));
+ return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
+ get_words(ohci, addr + 16, td->offset, 8);
}
static inline int ohci_read_hcca(OHCIState *ohci,
dma_addr_t addr, struct ohci_hcca *hcca)
{
- dma_memory_read(ohci->dma, addr + ohci->localmem_base, hcca, sizeof(*hcca));
- return 1;
+ return dma_memory_read(ohci->as, addr + ohci->localmem_base,
+ hcca, sizeof(*hcca));
}
static inline int ohci_put_ed(OHCIState *ohci,
static inline int ohci_put_iso_td(OHCIState *ohci,
dma_addr_t addr, struct ohci_iso_td *td)
{
- return (put_dwords(ohci, addr, (uint32_t *)td, 4) &&
- put_words(ohci, addr + 16, td->offset, 8));
+ return put_dwords(ohci, addr, (uint32_t *)td, 4 ||
+ put_words(ohci, addr + 16, td->offset, 8));
}
static inline int ohci_put_hcca(OHCIState *ohci,
dma_addr_t addr, struct ohci_hcca *hcca)
{
- dma_memory_write(ohci->dma,
- addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
- (char *)hcca + HCCA_WRITEBACK_OFFSET,
- HCCA_WRITEBACK_SIZE);
- return 1;
+ return dma_memory_write(ohci->as,
+ addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
+ (char *)hcca + HCCA_WRITEBACK_OFFSET,
+ HCCA_WRITEBACK_SIZE);
}
/* Read/Write the contents of a TD from/to main memory. */
-static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
- uint8_t *buf, int len, DMADirection dir)
+static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
+ uint8_t *buf, int len, DMADirection dir)
{
dma_addr_t ptr, n;
n = 0x1000 - (ptr & 0xfff);
if (n > len)
n = len;
- dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir);
- if (n == len)
- return;
+
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
+ return -1;
+ }
+ if (n == len) {
+ return 0;
+ }
ptr = td->be & ~0xfffu;
buf += n;
- dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir);
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
+ len - n, dir)) {
+ return -1;
+ }
+ return 0;
}
/* Read/Write the contents of an ISO TD from/to main memory. */
-static void ohci_copy_iso_td(OHCIState *ohci,
- uint32_t start_addr, uint32_t end_addr,
- uint8_t *buf, int len, DMADirection dir)
+static int ohci_copy_iso_td(OHCIState *ohci,
+ uint32_t start_addr, uint32_t end_addr,
+ uint8_t *buf, int len, DMADirection dir)
{
dma_addr_t ptr, n;
n = 0x1000 - (ptr & 0xfff);
if (n > len)
n = len;
- dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir);
- if (n == len)
- return;
+
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
+ return -1;
+ }
+ if (n == len) {
+ return 0;
+ }
ptr = end_addr & ~0xfffu;
buf += n;
- dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir);
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
+ len - n, dir)) {
+ return -1;
+ }
+ return 0;
}
static void ohci_process_lists(OHCIState *ohci, int completion);
addr = ed->head & OHCI_DPTR_MASK;
- if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
+ if (ohci_read_iso_td(ohci, addr, &iso_td)) {
printf("usb-ohci: ISO_TD read error at %x\n", addr);
+ ohci_die(ohci);
return 0;
}
i = OHCI_BM(iso_td.flags, TD_DI);
if (i < ohci->done_count)
ohci->done_count = i;
- ohci_put_iso_td(ohci, addr, &iso_td);
+ if (ohci_put_iso_td(ohci, addr, &iso_td)) {
+ ohci_die(ohci);
+ return 1;
+ }
return 0;
}
}
if (len && dir != OHCI_TD_DIR_IN) {
- ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
- DMA_DIRECTION_TO_DEVICE);
+ if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
+ DMA_DIRECTION_TO_DEVICE)) {
+ ohci_die(ohci);
+ return 1;
+ }
}
if (!completion) {
OHCI_BM(iso_td.flags, TD_DI) == 0;
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
- usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false, int_req);
+ usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
usb_handle_packet(dev, &ohci->usb_packet);
if (ohci->usb_packet.status == USB_RET_ASYNC) {
/* Writeback */
if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
/* IN transfer succeeded */
- ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
- DMA_DIRECTION_FROM_DEVICE);
+ if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
+ DMA_DIRECTION_FROM_DEVICE)) {
+ ohci_die(ohci);
+ return 1;
+ }
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
OHCI_CC_NOERROR);
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
if (i < ohci->done_count)
ohci->done_count = i;
}
- ohci_put_iso_td(ohci, addr, &iso_td);
+ if (ohci_put_iso_td(ohci, addr, &iso_td)) {
+ ohci_die(ohci);
+ }
return 1;
}
#endif
return 1;
}
- if (!ohci_read_td(ohci, addr, &td)) {
+ if (ohci_read_td(ohci, addr, &td)) {
fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
+ ohci_die(ohci);
return 0;
}
pktlen = len;
}
if (!completion) {
- ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
- DMA_DIRECTION_TO_DEVICE);
+ if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
+ DMA_DIRECTION_TO_DEVICE)) {
+ ohci_die(ohci);
+ }
}
}
}
}
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
- usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r,
+ usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
OHCI_BM(td.flags, TD_DI) == 0);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
usb_handle_packet(dev, &ohci->usb_packet);
if (ret >= 0) {
if (dir == OHCI_TD_DIR_IN) {
- ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
- DMA_DIRECTION_FROM_DEVICE);
+ if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
+ DMA_DIRECTION_FROM_DEVICE)) {
+ ohci_die(ohci);
+ }
#ifdef DEBUG_PACKET
DPRINTF(" data:");
for (i = 0; i < ret; i++)
switch (ret) {
case USB_RET_IOERROR:
case USB_RET_NODEV:
+ DPRINTF("usb-ohci: got DEV ERROR\n");
OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
+ break;
case USB_RET_NAK:
DPRINTF("usb-ohci: got NAK\n");
return 1;
if (i < ohci->done_count)
ohci->done_count = i;
exit_no_retire:
- ohci_put_td(ohci, addr, &td);
+ if (ohci_put_td(ohci, addr, &td)) {
+ ohci_die(ohci);
+ return 1;
+ }
return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
}
return 0;
for (cur = head; cur; cur = next_ed) {
- if (!ohci_read_ed(ohci, cur, &ed)) {
+ if (ohci_read_ed(ohci, cur, &ed)) {
fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
+ ohci_die(ohci);
return 0;
}
if (ohci->async_td && addr == ohci->async_td) {
usb_cancel_packet(&ohci->usb_packet);
ohci->async_td = 0;
+ usb_device_ep_stopped(ohci->usb_packet.ep->dev,
+ ohci->usb_packet.ep);
}
continue;
}
}
}
- ohci_put_ed(ohci, cur, &ed);
+ if (ohci_put_ed(ohci, cur, &ed)) {
+ ohci_die(ohci);
+ return 0;
+ }
}
return active;
/* Generate a SOF event, and set a timer for EOF */
static void ohci_sof(OHCIState *ohci)
{
- ohci->sof_time = qemu_get_clock_ns(vm_clock);
- qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time);
+ ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
ohci_set_interrupt(ohci, OHCI_INTR_SF);
}
OHCIState *ohci = opaque;
struct ohci_hcca hcca;
- ohci_read_hcca(ohci, ohci->hcca, &hcca);
+ if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
+ fprintf(stderr, "usb-ohci: HCCA read error at %x\n", ohci->hcca);
+ ohci_die(ohci);
+ return;
+ }
/* Process all the lists at the end of the frame */
if (ohci->ctl & OHCI_CTL_PLE) {
}
/* Cancel all pending packets if either of the lists has been disabled. */
- if (ohci->async_td &&
- ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
- usb_cancel_packet(&ohci->usb_packet);
- ohci->async_td = 0;
+ if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
+ if (ohci->async_td) {
+ usb_cancel_packet(&ohci->usb_packet);
+ ohci->async_td = 0;
+ }
+ ohci_stop_endpoints(ohci);
}
ohci->old_ctl = ohci->ctl;
ohci_process_lists(ohci, 0);
+ /* Stop if UnrecoverableError happened or ohci_sof will crash */
+ if (ohci->intr_status & OHCI_INTR_UE) {
+ return;
+ }
+
/* Frame boundary, so do EOF stuf here */
ohci->frt = ohci->fit;
ohci_sof(ohci);
/* Writeback HCCA */
- ohci_put_hcca(ohci, ohci->hcca, &hcca);
+ if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
+ ohci_die(ohci);
+ }
}
/* Start sending SOF tokens across the USB bus, lists are processed in
*/
static int ohci_bus_start(OHCIState *ohci)
{
- ohci->eof_timer = qemu_new_timer_ns(vm_clock,
+ ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
ohci_frame_boundary,
ohci);
if (ohci->eof_timer == NULL) {
- fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name);
- /* TODO: Signal unrecoverable error */
+ fprintf(stderr, "usb-ohci: %s: timer_new_ns failed\n", ohci->name);
+ ohci_die(ohci);
return 0;
}
static void ohci_bus_stop(OHCIState *ohci)
{
if (ohci->eof_timer)
- qemu_del_timer(ohci->eof_timer);
+ timer_del(ohci->eof_timer);
ohci->eof_timer = NULL;
}
/* Being in USB operational state guarnatees sof_time was
* set already.
*/
- tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time;
+ tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
/* avoid muldiv if possible */
if (tks >= usb_frame_time)
/* PXA27x specific registers */
case 24: /* HcStatus */
ohci->hstatus &= ~(val & ohci->hmask);
+ break;
case 25: /* HcHReset */
ohci->hreset = val & ~OHCI_HRESET_FSBIR;
static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
int num_ports, dma_addr_t localmem_base,
char *masterbus, uint32_t firstport,
- DMAContext *dma)
+ AddressSpace *as)
{
int i;
- ohci->dma = dma;
+ ohci->as = as;
if (usb_frame_time == 0) {
#ifdef OHCI_TIME_WARP
return -1;
}
} else {
- usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
+ usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev);
for (i = 0; i < num_ports; i++) {
usb_register_port(&ohci->bus, &ohci->rhport[i].port,
ohci, i, &ohci_port_ops,
}
}
- memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
+ memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops,
+ ohci, "ohci", 256);
ohci->localmem_base = localmem_base;
ohci->name = object_get_typename(OBJECT(dev));
return 0;
}
+#define TYPE_PCI_OHCI "pci-ohci"
+#define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
+
typedef struct {
- PCIDevice pci_dev;
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
OHCIState state;
char *masterbus;
uint32_t num_ports;
uint32_t firstport;
} OHCIPCIState;
-static int usb_ohci_initfn_pci(struct PCIDevice *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
+ */
+static void ohci_die(OHCIState *ohci)
{
- OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
+ OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state);
- ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
- ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
+ fprintf(stderr, "%s: DMA error\n", __func__);
- if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
+ 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_dma_context(dev)) != 0) {
+ pci_get_address_space(dev)) != 0) {
return -1;
}
- ohci->state.irq = ohci->pci_dev.irq[0];
+ ohci->state.irq = pci_allocate_irq(dev);
- /* TODO: avoid cast below by using dev */
- pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem);
+ 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 {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
OHCIState ohci;
uint32_t num_ports;
dma_addr_t dma_offset;
} OHCISysBusState;
-static int ohci_init_pxa(SysBusDevice *dev)
+static void ohci_realize_pxa(DeviceState *dev, Error **errp)
{
- OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
+ 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->qdev, s->num_ports, s->dma_offset, NULL, 0,
- &dma_context_memory);
- sysbus_init_irq(dev, &s->ohci.irq);
- sysbus_init_mmio(dev, &s->ohci.mem);
-
- return 0;
+ 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[] = {
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;
+ dc->hotpluggable = false;
}
-static TypeInfo ohci_pci_info = {
- .name = "pci-ohci",
+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_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
- sbc->init = ohci_init_pxa;
+ dc->realize = ohci_realize_pxa;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
dc->desc = "OHCI USB Controller";
dc->props = ohci_sysbus_properties;
}
-static TypeInfo ohci_sysbus_info = {
- .name = "sysbus-ohci",
+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,