2 * QEMU USB OHCI Emulation
3 * Copyright (c) 2004 Gianni Tedesco
4 * Copyright (c) 2006 CodeSourcery
5 * Copyright (c) 2006 Openedhand Ltd.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "qemu/timer.h"
25 #include "migration/vmstate.h"
26 #include "hw/pci/pci.h"
27 #include "hw/sysbus.h"
28 #include "hw/qdev-dma.h"
29 #include "hw/qdev-properties.h"
33 #define TYPE_PCI_OHCI "pci-ohci"
34 #define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI)
48 * A typical PCI OHCI will additionally set PERR in its configspace to
49 * signal that it got an error.
51 static void ohci_pci_die(struct OHCIState
*ohci
)
53 OHCIPCIState
*dev
= container_of(ohci
, OHCIPCIState
, state
);
55 ohci_sysbus_die(ohci
);
57 pci_set_word(dev
->parent_obj
.config
+ PCI_STATUS
,
58 PCI_STATUS_DETECTED_PARITY
);
61 static void usb_ohci_realize_pci(PCIDevice
*dev
, Error
**errp
)
64 OHCIPCIState
*ohci
= PCI_OHCI(dev
);
66 dev
->config
[PCI_CLASS_PROG
] = 0x10; /* OHCI */
67 dev
->config
[PCI_INTERRUPT_PIN
] = 0x01; /* interrupt pin A */
69 usb_ohci_init(&ohci
->state
, DEVICE(dev
), ohci
->num_ports
, 0,
70 ohci
->masterbus
, ohci
->firstport
,
71 pci_get_address_space(dev
), ohci_pci_die
, &err
);
73 error_propagate(errp
, err
);
77 ohci
->state
.irq
= pci_allocate_irq(dev
);
78 pci_register_bar(dev
, 0, 0, &ohci
->state
.mem
);
81 static void usb_ohci_exit(PCIDevice
*dev
)
83 OHCIPCIState
*ohci
= PCI_OHCI(dev
);
84 OHCIState
*s
= &ohci
->state
;
86 trace_usb_ohci_exit(s
->name
);
90 usb_cancel_packet(&s
->usb_packet
);
93 ohci_stop_endpoints(s
);
95 if (!ohci
->masterbus
) {
96 usb_bus_release(&s
->bus
);
99 timer_del(s
->eof_timer
);
100 timer_free(s
->eof_timer
);
103 static void usb_ohci_reset_pci(DeviceState
*d
)
105 PCIDevice
*dev
= PCI_DEVICE(d
);
106 OHCIPCIState
*ohci
= PCI_OHCI(dev
);
107 OHCIState
*s
= &ohci
->state
;
112 static Property ohci_pci_properties
[] = {
113 DEFINE_PROP_STRING("masterbus", OHCIPCIState
, masterbus
),
114 DEFINE_PROP_UINT32("num-ports", OHCIPCIState
, num_ports
, 3),
115 DEFINE_PROP_UINT32("firstport", OHCIPCIState
, firstport
, 0),
116 DEFINE_PROP_END_OF_LIST(),
119 static const VMStateDescription vmstate_ohci
= {
122 .minimum_version_id
= 1,
123 .fields
= (VMStateField
[]) {
124 VMSTATE_PCI_DEVICE(parent_obj
, OHCIPCIState
),
125 VMSTATE_STRUCT(state
, OHCIPCIState
, 1, vmstate_ohci_state
, OHCIState
),
126 VMSTATE_END_OF_LIST()
130 static void ohci_pci_class_init(ObjectClass
*klass
, void *data
)
132 DeviceClass
*dc
= DEVICE_CLASS(klass
);
133 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
135 k
->realize
= usb_ohci_realize_pci
;
136 k
->exit
= usb_ohci_exit
;
137 k
->vendor_id
= PCI_VENDOR_ID_APPLE
;
138 k
->device_id
= PCI_DEVICE_ID_APPLE_IPID_USB
;
139 k
->class_id
= PCI_CLASS_SERIAL_USB
;
140 set_bit(DEVICE_CATEGORY_USB
, dc
->categories
);
141 dc
->desc
= "Apple USB Controller";
142 device_class_set_props(dc
, ohci_pci_properties
);
143 dc
->hotpluggable
= false;
144 dc
->vmsd
= &vmstate_ohci
;
145 dc
->reset
= usb_ohci_reset_pci
;
148 static const TypeInfo ohci_pci_info
= {
149 .name
= TYPE_PCI_OHCI
,
150 .parent
= TYPE_PCI_DEVICE
,
151 .instance_size
= sizeof(OHCIPCIState
),
152 .class_init
= ohci_pci_class_init
,
153 .interfaces
= (InterfaceInfo
[]) {
154 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
159 static void ohci_pci_register_types(void)
161 type_register_static(&ohci_pci_info
);
164 type_init(ohci_pci_register_types
)