1 | /* |
2 | * QEMU USB OHCI Emulation |
3 | * Copyright (c) 2004 Gianni Tedesco |
4 | * Copyright (c) 2006 CodeSourcery |
5 | * Copyright (c) 2006 Openedhand Ltd. |
6 | * |
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. |
11 | * |
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. |
16 | * |
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/>. |
19 | */ |
20 | |
21 | #include "qemu/osdep.h" |
22 | #include "qapi/error.h" |
23 | #include "qemu/timer.h" |
24 | #include "hw/usb.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" |
30 | #include "trace.h" |
31 | #include "hcd-ohci.h" |
32 | |
33 | #define TYPE_PCI_OHCI "pci-ohci" |
34 | #define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI) |
35 | |
36 | typedef struct { |
37 | /*< private >*/ |
38 | PCIDevice parent_obj; |
39 | /*< public >*/ |
40 | |
41 | OHCIState state; |
42 | char *masterbus; |
43 | uint32_t num_ports; |
44 | uint32_t firstport; |
45 | } OHCIPCIState; |
46 | |
47 | /** |
48 | * A typical PCI OHCI will additionally set PERR in its configspace to |
49 | * signal that it got an error. |
50 | */ |
51 | static void ohci_pci_die(struct OHCIState *ohci) |
52 | { |
53 | OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state); |
54 | |
55 | ohci_sysbus_die(ohci); |
56 | |
57 | pci_set_word(dev->parent_obj.config + PCI_STATUS, |
58 | PCI_STATUS_DETECTED_PARITY); |
59 | } |
60 | |
61 | static void usb_ohci_realize_pci(PCIDevice *dev, Error **errp) |
62 | { |
63 | Error *err = NULL; |
64 | OHCIPCIState *ohci = PCI_OHCI(dev); |
65 | |
66 | dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */ |
67 | dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ |
68 | |
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); |
72 | if (err) { |
73 | error_propagate(errp, err); |
74 | return; |
75 | } |
76 | |
77 | ohci->state.irq = pci_allocate_irq(dev); |
78 | pci_register_bar(dev, 0, 0, &ohci->state.mem); |
79 | } |
80 | |
81 | static void usb_ohci_exit(PCIDevice *dev) |
82 | { |
83 | OHCIPCIState *ohci = PCI_OHCI(dev); |
84 | OHCIState *s = &ohci->state; |
85 | |
86 | trace_usb_ohci_exit(s->name); |
87 | ohci_bus_stop(s); |
88 | |
89 | if (s->async_td) { |
90 | usb_cancel_packet(&s->usb_packet); |
91 | s->async_td = 0; |
92 | } |
93 | ohci_stop_endpoints(s); |
94 | |
95 | if (!ohci->masterbus) { |
96 | usb_bus_release(&s->bus); |
97 | } |
98 | |
99 | timer_del(s->eof_timer); |
100 | timer_free(s->eof_timer); |
101 | } |
102 | |
103 | static void usb_ohci_reset_pci(DeviceState *d) |
104 | { |
105 | PCIDevice *dev = PCI_DEVICE(d); |
106 | OHCIPCIState *ohci = PCI_OHCI(dev); |
107 | OHCIState *s = &ohci->state; |
108 | |
109 | ohci_hard_reset(s); |
110 | } |
111 | |
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(), |
117 | }; |
118 | |
119 | static const VMStateDescription vmstate_ohci = { |
120 | .name = "ohci" , |
121 | .version_id = 1, |
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() |
127 | } |
128 | }; |
129 | |
130 | static void ohci_pci_class_init(ObjectClass *klass, void *data) |
131 | { |
132 | DeviceClass *dc = DEVICE_CLASS(klass); |
133 | PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); |
134 | |
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 | dc->props = ohci_pci_properties; |
143 | dc->hotpluggable = false; |
144 | dc->vmsd = &vmstate_ohci; |
145 | dc->reset = usb_ohci_reset_pci; |
146 | } |
147 | |
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 }, |
155 | { }, |
156 | }, |
157 | }; |
158 | |
159 | static void ohci_pci_register_types(void) |
160 | { |
161 | type_register_static(&ohci_pci_info); |
162 | } |
163 | |
164 | type_init(ohci_pci_register_types) |
165 | |