1 /* 2 * USB UHCI controller emulation 3 * PCI code 4 * 5 * Copyright (c) 2005 Fabrice Bellard 6 * 7 * Copyright (c) 2008 Max Krasnyansky 8 * Magor rewrite of the UHCI data structures parser and frame processor 9 * Support for fully async operation and multiple outstanding transactions 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining a copy 12 * of this software and associated documentation files (the "Software"), to deal 13 * in the Software without restriction, including without limitation the rights 14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 * copies of the Software, and to permit persons to whom the Software is 16 * furnished to do so, subject to the following conditions: 17 * 18 * The above copyright notice and this permission notice shall be included in 19 * all copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 * THE SOFTWARE. 28 */ 29 30 #include "qemu/osdep.h" 31 #include "hw/irq.h" 32 #include "hw/usb.h" 33 #include "migration/vmstate.h" 34 #include "hw/pci/pci.h" 35 #include "hw/qdev-properties.h" 36 #include "qapi/error.h" 37 #include "qemu/main-loop.h" 38 #include "qemu/module.h" 39 #include "qom/object.h" 40 #include "hcd-uhci-pci.h" 41 42 struct UHCIPCIDeviceClass { 43 PCIDeviceClass parent_class; 44 UHCIPCIInfo info; 45 }; 46 47 static const VMStateDescription vmstate_uhci = { 48 .name = "pci_uhci", 49 .version_id = 1, 50 .minimum_version_id = 1, 51 .fields = (const VMStateField[]) { 52 VMSTATE_PCI_DEVICE(dev, UHCIPCIState), 53 VMSTATE_STRUCT(state, UHCIPCIState, 1, vmstate_uhci_state, UHCIState), 54 VMSTATE_END_OF_LIST() 55 } 56 }; 57 58 static void uhci_pci_reset(UHCIState *uhci) 59 { 60 UHCIPCIState *pstate = container_of(uhci, UHCIPCIState, state); 61 PCIDevice *d = &pstate->dev; 62 63 d->config[0x6a] = 0x01; /* usb clock */ 64 d->config[0x6b] = 0x00; 65 66 uhci_state_reset(uhci); 67 } 68 69 void usb_uhci_common_realize_pci(PCIDevice *dev, Error **errp) 70 { 71 Error *err = NULL; 72 UHCIPCIDeviceClass *u = UHCI_PCI_GET_CLASS(dev); 73 UHCIPCIState *uhci = UHCI_PCI(dev); 74 UHCIState *s = &uhci->state; 75 uint8_t *pci_conf = dev->config; 76 77 pci_conf[PCI_CLASS_PROG] = 0x00; 78 /* TODO: reset value should be 0. */ 79 pci_conf[USB_SBRN] = USB_RELEASE_1; /* release number */ 80 pci_config_set_interrupt_pin(pci_conf, u->info.irq_pin + 1); 81 82 s->irq = pci_allocate_irq(dev); 83 s->masterbus = uhci->masterbus; 84 s->firstport = uhci->firstport; 85 s->maxframes = uhci->maxframes; 86 s->frame_bandwidth = uhci->frame_bandwidth; 87 s->as = pci_get_address_space(dev); 88 s->uhci_reset = uhci_pci_reset; 89 90 usb_uhci_init(s, DEVICE(dev), &err); 91 92 /* 93 * Use region 4 for consistency with real hardware. BSD guests seem 94 * to rely on this. 95 */ 96 pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->mem); 97 } 98 99 static void uhci_pci_reset_pci(DeviceState *dev) 100 { 101 PCIDevice *d = PCI_DEVICE(dev); 102 UHCIPCIState *uhci = UHCI_PCI(d); 103 104 uhci_pci_reset(&uhci->state); 105 } 106 107 static void usb_uhci_pci_exit(PCIDevice *dev) 108 { 109 UHCIPCIState *uhci = UHCI_PCI(dev); 110 UHCIState *s = &uhci->state; 111 112 usb_uhci_exit(s); 113 114 qemu_free_irq(s->irq); 115 } 116 117 static Property uhci_properties_companion[] = { 118 DEFINE_PROP_STRING("masterbus", UHCIPCIState, masterbus), 119 DEFINE_PROP_UINT32("firstport", UHCIPCIState, firstport, 0), 120 DEFINE_PROP_UINT32("bandwidth", UHCIPCIState, frame_bandwidth, 1280), 121 DEFINE_PROP_UINT32("maxframes", UHCIPCIState, maxframes, 128), 122 DEFINE_PROP_END_OF_LIST(), 123 }; 124 static Property uhci_properties_standalone[] = { 125 DEFINE_PROP_UINT32("bandwidth", UHCIPCIState, frame_bandwidth, 1280), 126 DEFINE_PROP_UINT32("maxframes", UHCIPCIState, maxframes, 128), 127 DEFINE_PROP_END_OF_LIST(), 128 }; 129 130 static void uhci_pci_class_init(ObjectClass *klass, void *data) 131 { 132 DeviceClass *dc = DEVICE_CLASS(klass); 133 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 134 135 k->class_id = PCI_CLASS_SERIAL_USB; 136 dc->vmsd = &vmstate_uhci; 137 device_class_set_legacy_reset(dc, uhci_pci_reset_pci); 138 set_bit(DEVICE_CATEGORY_USB, dc->categories); 139 } 140 141 static const TypeInfo uhci_pci_type_info = { 142 .name = TYPE_UHCI_PCI, 143 .parent = TYPE_PCI_DEVICE, 144 .instance_size = sizeof(UHCIPCIState), 145 .class_size = sizeof(UHCIPCIDeviceClass), 146 .class_init = uhci_pci_class_init, 147 .interfaces = (InterfaceInfo[]) { 148 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 149 { }, 150 }, 151 }; 152 153 void uhci_pci_data_class_init(ObjectClass *klass, void *data) 154 { 155 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 156 DeviceClass *dc = DEVICE_CLASS(klass); 157 UHCIPCIDeviceClass *u = UHCI_PCI_CLASS(klass); 158 UHCIPCIInfo *info = data; 159 160 k->realize = info->realize ? info->realize : usb_uhci_common_realize_pci; 161 k->exit = info->unplug ? usb_uhci_pci_exit : NULL; 162 k->vendor_id = info->vendor_id; 163 k->device_id = info->device_id; 164 k->revision = info->revision; 165 if (!info->unplug) { 166 /* uhci controllers in companion setups can't be hotplugged */ 167 dc->hotpluggable = false; 168 device_class_set_props(dc, uhci_properties_companion); 169 } else { 170 device_class_set_props(dc, uhci_properties_standalone); 171 } 172 if (info->notuser) { 173 dc->user_creatable = false; 174 } 175 u->info = *info; 176 } 177 178 static UHCIPCIInfo uhci_pci_info[] = { 179 { 180 .name = TYPE_PIIX3_USB_UHCI, 181 .vendor_id = PCI_VENDOR_ID_INTEL, 182 .device_id = PCI_DEVICE_ID_INTEL_82371SB_2, 183 .revision = 0x01, 184 .irq_pin = 3, 185 .unplug = true, 186 },{ 187 .name = TYPE_PIIX4_USB_UHCI, 188 .vendor_id = PCI_VENDOR_ID_INTEL, 189 .device_id = PCI_DEVICE_ID_INTEL_82371AB_2, 190 .revision = 0x01, 191 .irq_pin = 3, 192 .unplug = true, 193 },{ 194 .name = TYPE_ICH9_USB_UHCI(1), /* 00:1d.0 */ 195 .vendor_id = PCI_VENDOR_ID_INTEL, 196 .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI1, 197 .revision = 0x03, 198 .irq_pin = 0, 199 .unplug = false, 200 },{ 201 .name = TYPE_ICH9_USB_UHCI(2), /* 00:1d.1 */ 202 .vendor_id = PCI_VENDOR_ID_INTEL, 203 .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI2, 204 .revision = 0x03, 205 .irq_pin = 1, 206 .unplug = false, 207 },{ 208 .name = TYPE_ICH9_USB_UHCI(3), /* 00:1d.2 */ 209 .vendor_id = PCI_VENDOR_ID_INTEL, 210 .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI3, 211 .revision = 0x03, 212 .irq_pin = 2, 213 .unplug = false, 214 },{ 215 .name = TYPE_ICH9_USB_UHCI(4), /* 00:1a.0 */ 216 .vendor_id = PCI_VENDOR_ID_INTEL, 217 .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI4, 218 .revision = 0x03, 219 .irq_pin = 0, 220 .unplug = false, 221 },{ 222 .name = TYPE_ICH9_USB_UHCI(5), /* 00:1a.1 */ 223 .vendor_id = PCI_VENDOR_ID_INTEL, 224 .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI5, 225 .revision = 0x03, 226 .irq_pin = 1, 227 .unplug = false, 228 },{ 229 .name = TYPE_ICH9_USB_UHCI(6), /* 00:1a.2 */ 230 .vendor_id = PCI_VENDOR_ID_INTEL, 231 .device_id = PCI_DEVICE_ID_INTEL_82801I_UHCI6, 232 .revision = 0x03, 233 .irq_pin = 2, 234 .unplug = false, 235 } 236 }; 237 238 static void uhci_pci_register_types(void) 239 { 240 TypeInfo type_info = { 241 .parent = TYPE_UHCI_PCI, 242 .class_init = uhci_pci_data_class_init, 243 }; 244 int i; 245 246 type_register_static(&uhci_pci_type_info); 247 248 for (i = 0; i < ARRAY_SIZE(uhci_pci_info); i++) { 249 type_info.name = uhci_pci_info[i].name; 250 type_info.class_data = uhci_pci_info + i; 251 type_register(&type_info); 252 } 253 } 254 255 type_init(uhci_pci_register_types) 256