1*34d97308SThomas Huth /* 2*34d97308SThomas Huth * QEMU USB OHCI Emulation 3*34d97308SThomas Huth * Copyright (c) 2004 Gianni Tedesco 4*34d97308SThomas Huth * Copyright (c) 2006 CodeSourcery 5*34d97308SThomas Huth * Copyright (c) 2006 Openedhand Ltd. 6*34d97308SThomas Huth * 7*34d97308SThomas Huth * This library is free software; you can redistribute it and/or 8*34d97308SThomas Huth * modify it under the terms of the GNU Lesser General Public 9*34d97308SThomas Huth * License as published by the Free Software Foundation; either 10*34d97308SThomas Huth * version 2.1 of the License, or (at your option) any later version. 11*34d97308SThomas Huth * 12*34d97308SThomas Huth * This library is distributed in the hope that it will be useful, 13*34d97308SThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*34d97308SThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15*34d97308SThomas Huth * Lesser General Public License for more details. 16*34d97308SThomas Huth * 17*34d97308SThomas Huth * You should have received a copy of the GNU Lesser General Public 18*34d97308SThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19*34d97308SThomas Huth */ 20*34d97308SThomas Huth 21*34d97308SThomas Huth #include "qemu/osdep.h" 22*34d97308SThomas Huth #include "hw/hw.h" 23*34d97308SThomas Huth #include "qapi/error.h" 24*34d97308SThomas Huth #include "qemu/timer.h" 25*34d97308SThomas Huth #include "hw/usb.h" 26*34d97308SThomas Huth #include "hw/pci/pci.h" 27*34d97308SThomas Huth #include "hw/sysbus.h" 28*34d97308SThomas Huth #include "hw/qdev-dma.h" 29*34d97308SThomas Huth #include "trace.h" 30*34d97308SThomas Huth #include "hcd-ohci.h" 31*34d97308SThomas Huth 32*34d97308SThomas Huth #define TYPE_PCI_OHCI "pci-ohci" 33*34d97308SThomas Huth #define PCI_OHCI(obj) OBJECT_CHECK(OHCIPCIState, (obj), TYPE_PCI_OHCI) 34*34d97308SThomas Huth 35*34d97308SThomas Huth typedef struct { 36*34d97308SThomas Huth /*< private >*/ 37*34d97308SThomas Huth PCIDevice parent_obj; 38*34d97308SThomas Huth /*< public >*/ 39*34d97308SThomas Huth 40*34d97308SThomas Huth OHCIState state; 41*34d97308SThomas Huth char *masterbus; 42*34d97308SThomas Huth uint32_t num_ports; 43*34d97308SThomas Huth uint32_t firstport; 44*34d97308SThomas Huth } OHCIPCIState; 45*34d97308SThomas Huth 46*34d97308SThomas Huth /** 47*34d97308SThomas Huth * A typical PCI OHCI will additionally set PERR in its configspace to 48*34d97308SThomas Huth * signal that it got an error. 49*34d97308SThomas Huth */ 50*34d97308SThomas Huth static void ohci_pci_die(struct OHCIState *ohci) 51*34d97308SThomas Huth { 52*34d97308SThomas Huth OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state); 53*34d97308SThomas Huth 54*34d97308SThomas Huth ohci_sysbus_die(ohci); 55*34d97308SThomas Huth 56*34d97308SThomas Huth pci_set_word(dev->parent_obj.config + PCI_STATUS, 57*34d97308SThomas Huth PCI_STATUS_DETECTED_PARITY); 58*34d97308SThomas Huth } 59*34d97308SThomas Huth 60*34d97308SThomas Huth static void usb_ohci_realize_pci(PCIDevice *dev, Error **errp) 61*34d97308SThomas Huth { 62*34d97308SThomas Huth Error *err = NULL; 63*34d97308SThomas Huth OHCIPCIState *ohci = PCI_OHCI(dev); 64*34d97308SThomas Huth 65*34d97308SThomas Huth dev->config[PCI_CLASS_PROG] = 0x10; /* OHCI */ 66*34d97308SThomas Huth dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ 67*34d97308SThomas Huth 68*34d97308SThomas Huth usb_ohci_init(&ohci->state, DEVICE(dev), ohci->num_ports, 0, 69*34d97308SThomas Huth ohci->masterbus, ohci->firstport, 70*34d97308SThomas Huth pci_get_address_space(dev), ohci_pci_die, &err); 71*34d97308SThomas Huth if (err) { 72*34d97308SThomas Huth error_propagate(errp, err); 73*34d97308SThomas Huth return; 74*34d97308SThomas Huth } 75*34d97308SThomas Huth 76*34d97308SThomas Huth ohci->state.irq = pci_allocate_irq(dev); 77*34d97308SThomas Huth pci_register_bar(dev, 0, 0, &ohci->state.mem); 78*34d97308SThomas Huth } 79*34d97308SThomas Huth 80*34d97308SThomas Huth static void usb_ohci_exit(PCIDevice *dev) 81*34d97308SThomas Huth { 82*34d97308SThomas Huth OHCIPCIState *ohci = PCI_OHCI(dev); 83*34d97308SThomas Huth OHCIState *s = &ohci->state; 84*34d97308SThomas Huth 85*34d97308SThomas Huth trace_usb_ohci_exit(s->name); 86*34d97308SThomas Huth ohci_bus_stop(s); 87*34d97308SThomas Huth 88*34d97308SThomas Huth if (s->async_td) { 89*34d97308SThomas Huth usb_cancel_packet(&s->usb_packet); 90*34d97308SThomas Huth s->async_td = 0; 91*34d97308SThomas Huth } 92*34d97308SThomas Huth ohci_stop_endpoints(s); 93*34d97308SThomas Huth 94*34d97308SThomas Huth if (!ohci->masterbus) { 95*34d97308SThomas Huth usb_bus_release(&s->bus); 96*34d97308SThomas Huth } 97*34d97308SThomas Huth 98*34d97308SThomas Huth timer_del(s->eof_timer); 99*34d97308SThomas Huth timer_free(s->eof_timer); 100*34d97308SThomas Huth } 101*34d97308SThomas Huth 102*34d97308SThomas Huth static void usb_ohci_reset_pci(DeviceState *d) 103*34d97308SThomas Huth { 104*34d97308SThomas Huth PCIDevice *dev = PCI_DEVICE(d); 105*34d97308SThomas Huth OHCIPCIState *ohci = PCI_OHCI(dev); 106*34d97308SThomas Huth OHCIState *s = &ohci->state; 107*34d97308SThomas Huth 108*34d97308SThomas Huth ohci_hard_reset(s); 109*34d97308SThomas Huth } 110*34d97308SThomas Huth 111*34d97308SThomas Huth static Property ohci_pci_properties[] = { 112*34d97308SThomas Huth DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus), 113*34d97308SThomas Huth DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3), 114*34d97308SThomas Huth DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0), 115*34d97308SThomas Huth DEFINE_PROP_END_OF_LIST(), 116*34d97308SThomas Huth }; 117*34d97308SThomas Huth 118*34d97308SThomas Huth static const VMStateDescription vmstate_ohci = { 119*34d97308SThomas Huth .name = "ohci", 120*34d97308SThomas Huth .version_id = 1, 121*34d97308SThomas Huth .minimum_version_id = 1, 122*34d97308SThomas Huth .fields = (VMStateField[]) { 123*34d97308SThomas Huth VMSTATE_PCI_DEVICE(parent_obj, OHCIPCIState), 124*34d97308SThomas Huth VMSTATE_STRUCT(state, OHCIPCIState, 1, vmstate_ohci_state, OHCIState), 125*34d97308SThomas Huth VMSTATE_END_OF_LIST() 126*34d97308SThomas Huth } 127*34d97308SThomas Huth }; 128*34d97308SThomas Huth 129*34d97308SThomas Huth static void ohci_pci_class_init(ObjectClass *klass, void *data) 130*34d97308SThomas Huth { 131*34d97308SThomas Huth DeviceClass *dc = DEVICE_CLASS(klass); 132*34d97308SThomas Huth PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 133*34d97308SThomas Huth 134*34d97308SThomas Huth k->realize = usb_ohci_realize_pci; 135*34d97308SThomas Huth k->exit = usb_ohci_exit; 136*34d97308SThomas Huth k->vendor_id = PCI_VENDOR_ID_APPLE; 137*34d97308SThomas Huth k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; 138*34d97308SThomas Huth k->class_id = PCI_CLASS_SERIAL_USB; 139*34d97308SThomas Huth set_bit(DEVICE_CATEGORY_USB, dc->categories); 140*34d97308SThomas Huth dc->desc = "Apple USB Controller"; 141*34d97308SThomas Huth dc->props = ohci_pci_properties; 142*34d97308SThomas Huth dc->hotpluggable = false; 143*34d97308SThomas Huth dc->vmsd = &vmstate_ohci; 144*34d97308SThomas Huth dc->reset = usb_ohci_reset_pci; 145*34d97308SThomas Huth } 146*34d97308SThomas Huth 147*34d97308SThomas Huth static const TypeInfo ohci_pci_info = { 148*34d97308SThomas Huth .name = TYPE_PCI_OHCI, 149*34d97308SThomas Huth .parent = TYPE_PCI_DEVICE, 150*34d97308SThomas Huth .instance_size = sizeof(OHCIPCIState), 151*34d97308SThomas Huth .class_init = ohci_pci_class_init, 152*34d97308SThomas Huth .interfaces = (InterfaceInfo[]) { 153*34d97308SThomas Huth { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 154*34d97308SThomas Huth { }, 155*34d97308SThomas Huth }, 156*34d97308SThomas Huth }; 157*34d97308SThomas Huth 158*34d97308SThomas Huth static void ohci_pci_register_types(void) 159*34d97308SThomas Huth { 160*34d97308SThomas Huth type_register_static(&ohci_pci_info); 161*34d97308SThomas Huth } 162*34d97308SThomas Huth 163*34d97308SThomas Huth type_init(ohci_pci_register_types) 164