Revision 5010d4dc
b/hw/usb/hcd-ehci.c | ||
---|---|---|
385 | 385 |
typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead; |
386 | 386 |
|
387 | 387 |
struct EHCIState { |
388 |
PCIDevice dev; |
|
389 | 388 |
USBBus bus; |
390 | 389 |
qemu_irq irq; |
391 | 390 |
MemoryRegion mem; |
... | ... | |
447 | 446 |
bool int_req_by_async; |
448 | 447 |
}; |
449 | 448 |
|
449 |
typedef struct EHCIPCIState { |
|
450 |
PCIDevice pcidev; |
|
451 |
EHCIState ehci; |
|
452 |
} EHCIPCIState; |
|
453 |
|
|
450 | 454 |
#define SET_LAST_RUN_CLOCK(s) \ |
451 | 455 |
(s)->last_run_ns = qemu_get_clock_ns(vm_clock); |
452 | 456 |
|
... | ... | |
2553 | 2557 |
.endianness = DEVICE_LITTLE_ENDIAN, |
2554 | 2558 |
}; |
2555 | 2559 |
|
2556 |
static int usb_ehci_initfn(PCIDevice *dev); |
|
2560 |
static int usb_ehci_pci_initfn(PCIDevice *dev);
|
|
2557 | 2561 |
|
2558 | 2562 |
static USBPortOps ehci_port_ops = { |
2559 | 2563 |
.attach = ehci_attach, |
... | ... | |
2614 | 2618 |
} |
2615 | 2619 |
|
2616 | 2620 |
static const VMStateDescription vmstate_ehci = { |
2617 |
.name = "ehci", |
|
2621 |
.name = "ehci-core",
|
|
2618 | 2622 |
.version_id = 2, |
2619 | 2623 |
.minimum_version_id = 1, |
2620 | 2624 |
.post_load = usb_ehci_post_load, |
2621 | 2625 |
.fields = (VMStateField[]) { |
2622 |
VMSTATE_PCI_DEVICE(dev, EHCIState), |
|
2623 | 2626 |
/* mmio registers */ |
2624 | 2627 |
VMSTATE_UINT32(usbcmd, EHCIState), |
2625 | 2628 |
VMSTATE_UINT32(usbsts, EHCIState), |
... | ... | |
2650 | 2653 |
} |
2651 | 2654 |
}; |
2652 | 2655 |
|
2653 |
static Property ehci_properties[] = { |
|
2654 |
DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128), |
|
2656 |
static const VMStateDescription vmstate_ehci_pci = { |
|
2657 |
.name = "ehci", |
|
2658 |
.version_id = 2, |
|
2659 |
.minimum_version_id = 1, |
|
2660 |
.post_load = usb_ehci_post_load, |
|
2661 |
.fields = (VMStateField[]) { |
|
2662 |
VMSTATE_PCI_DEVICE(pcidev, EHCIPCIState), |
|
2663 |
VMSTATE_STRUCT(ehci, EHCIPCIState, 2, vmstate_ehci, EHCIState), |
|
2664 |
} |
|
2665 |
}; |
|
2666 |
|
|
2667 |
static Property ehci_pci_properties[] = { |
|
2668 |
DEFINE_PROP_UINT32("maxframes", EHCIPCIState, ehci.maxframes, 128), |
|
2655 | 2669 |
DEFINE_PROP_END_OF_LIST(), |
2656 | 2670 |
}; |
2657 | 2671 |
|
... | ... | |
2660 | 2674 |
DeviceClass *dc = DEVICE_CLASS(klass); |
2661 | 2675 |
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); |
2662 | 2676 |
|
2663 |
k->init = usb_ehci_initfn; |
|
2677 |
k->init = usb_ehci_pci_initfn;
|
|
2664 | 2678 |
k->vendor_id = PCI_VENDOR_ID_INTEL; |
2665 | 2679 |
k->device_id = PCI_DEVICE_ID_INTEL_82801D; /* ich4 */ |
2666 | 2680 |
k->revision = 0x10; |
2667 | 2681 |
k->class_id = PCI_CLASS_SERIAL_USB; |
2668 | 2682 |
dc->vmsd = &vmstate_ehci; |
2669 |
dc->props = ehci_properties; |
|
2683 |
dc->props = ehci_pci_properties;
|
|
2670 | 2684 |
} |
2671 | 2685 |
|
2672 | 2686 |
static TypeInfo ehci_info = { |
... | ... | |
2681 | 2695 |
DeviceClass *dc = DEVICE_CLASS(klass); |
2682 | 2696 |
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); |
2683 | 2697 |
|
2684 |
k->init = usb_ehci_initfn; |
|
2698 |
k->init = usb_ehci_pci_initfn;
|
|
2685 | 2699 |
k->vendor_id = PCI_VENDOR_ID_INTEL; |
2686 | 2700 |
k->device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1; |
2687 | 2701 |
k->revision = 0x03; |
2688 | 2702 |
k->class_id = PCI_CLASS_SERIAL_USB; |
2689 | 2703 |
dc->vmsd = &vmstate_ehci; |
2690 |
dc->props = ehci_properties; |
|
2704 |
dc->props = ehci_pci_properties;
|
|
2691 | 2705 |
} |
2692 | 2706 |
|
2693 | 2707 |
static TypeInfo ich9_ehci_info = { |
... | ... | |
2697 | 2711 |
.class_init = ich9_ehci_class_init, |
2698 | 2712 |
}; |
2699 | 2713 |
|
2700 |
static int usb_ehci_initfn(PCIDevice *dev)
|
|
2714 |
static void usb_ehci_initfn(EHCIState *s, DeviceState *dev)
|
|
2701 | 2715 |
{ |
2702 |
EHCIState *s = DO_UPCAST(EHCIState, dev, dev); |
|
2703 |
uint8_t *pci_conf = s->dev.config; |
|
2704 | 2716 |
int i; |
2705 | 2717 |
|
2706 |
pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); |
|
2707 |
|
|
2708 |
/* capabilities pointer */ |
|
2709 |
pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); |
|
2710 |
//pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); |
|
2711 |
|
|
2712 |
pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ |
|
2713 |
pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); |
|
2714 |
pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); |
|
2715 |
|
|
2716 |
// pci_conf[0x50] = 0x01; // power management caps |
|
2717 |
|
|
2718 |
pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); // release number (2.1.4) |
|
2719 |
pci_set_byte(&pci_conf[0x61], 0x20); // frame length adjustment (2.1.5) |
|
2720 |
pci_set_word(&pci_conf[0x62], 0x00); // port wake up capability (2.1.6) |
|
2721 |
|
|
2722 |
pci_conf[0x64] = 0x00; |
|
2723 |
pci_conf[0x65] = 0x00; |
|
2724 |
pci_conf[0x66] = 0x00; |
|
2725 |
pci_conf[0x67] = 0x00; |
|
2726 |
pci_conf[0x68] = 0x01; |
|
2727 |
pci_conf[0x69] = 0x00; |
|
2728 |
pci_conf[0x6a] = 0x00; |
|
2729 |
pci_conf[0x6b] = 0x00; // USBLEGSUP |
|
2730 |
pci_conf[0x6c] = 0x00; |
|
2731 |
pci_conf[0x6d] = 0x00; |
|
2732 |
pci_conf[0x6e] = 0x00; |
|
2733 |
pci_conf[0x6f] = 0xc0; // USBLEFCTLSTS |
|
2734 |
|
|
2735 |
s->capsbase = 0x00; |
|
2736 |
s->opregbase = 0x20; |
|
2737 |
|
|
2738 | 2718 |
/* 2.2 host controller interface version */ |
2739 | 2719 |
s->caps[0x00] = (uint8_t)(s->opregbase - s->capsbase); |
2740 | 2720 |
s->caps[0x01] = 0x00; |
... | ... | |
2745 | 2725 |
s->caps[0x06] = 0x00; |
2746 | 2726 |
s->caps[0x07] = 0x00; |
2747 | 2727 |
s->caps[0x08] = 0x80; /* We can cache whole frame, no 64-bit */ |
2748 |
s->caps[0x09] = 0x68; /* EECP */ |
|
2749 | 2728 |
s->caps[0x0a] = 0x00; |
2750 | 2729 |
s->caps[0x0b] = 0x00; |
2751 | 2730 |
|
2752 |
s->irq = s->dev.irq[3]; |
|
2753 |
|
|
2754 |
s->dma = pci_dma_context(dev); |
|
2755 |
|
|
2756 |
usb_bus_new(&s->bus, &ehci_bus_ops, &s->dev.qdev); |
|
2731 |
usb_bus_new(&s->bus, &ehci_bus_ops, dev); |
|
2757 | 2732 |
for(i = 0; i < NB_PORTS; i++) { |
2758 | 2733 |
usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, |
2759 | 2734 |
USB_SPEED_MASK_HIGH); |
... | ... | |
2781 | 2756 |
memory_region_add_subregion(&s->mem, s->opregbase, &s->mem_opreg); |
2782 | 2757 |
memory_region_add_subregion(&s->mem, s->opregbase + PORTSC_BEGIN, |
2783 | 2758 |
&s->mem_ports); |
2759 |
} |
|
2760 |
|
|
2761 |
static int usb_ehci_pci_initfn(PCIDevice *dev) |
|
2762 |
{ |
|
2763 |
EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev); |
|
2764 |
EHCIState *s = &i->ehci; |
|
2765 |
uint8_t *pci_conf = dev->config; |
|
2766 |
|
|
2767 |
pci_set_byte(&pci_conf[PCI_CLASS_PROG], 0x20); |
|
2768 |
|
|
2769 |
/* capabilities pointer */ |
|
2770 |
pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x00); |
|
2771 |
/* pci_set_byte(&pci_conf[PCI_CAPABILITY_LIST], 0x50); */ |
|
2772 |
|
|
2773 |
pci_set_byte(&pci_conf[PCI_INTERRUPT_PIN], 4); /* interrupt pin D */ |
|
2774 |
pci_set_byte(&pci_conf[PCI_MIN_GNT], 0); |
|
2775 |
pci_set_byte(&pci_conf[PCI_MAX_LAT], 0); |
|
2776 |
|
|
2777 |
/* pci_conf[0x50] = 0x01; *//* power management caps */ |
|
2778 |
|
|
2779 |
pci_set_byte(&pci_conf[USB_SBRN], USB_RELEASE_2); /* release # (2.1.4) */ |
|
2780 |
pci_set_byte(&pci_conf[0x61], 0x20); /* frame length adjustment (2.1.5) */ |
|
2781 |
pci_set_word(&pci_conf[0x62], 0x00); /* port wake up capability (2.1.6) */ |
|
2782 |
|
|
2783 |
pci_conf[0x64] = 0x00; |
|
2784 |
pci_conf[0x65] = 0x00; |
|
2785 |
pci_conf[0x66] = 0x00; |
|
2786 |
pci_conf[0x67] = 0x00; |
|
2787 |
pci_conf[0x68] = 0x01; |
|
2788 |
pci_conf[0x69] = 0x00; |
|
2789 |
pci_conf[0x6a] = 0x00; |
|
2790 |
pci_conf[0x6b] = 0x00; /* USBLEGSUP */ |
|
2791 |
pci_conf[0x6c] = 0x00; |
|
2792 |
pci_conf[0x6d] = 0x00; |
|
2793 |
pci_conf[0x6e] = 0x00; |
|
2794 |
pci_conf[0x6f] = 0xc0; /* USBLEFCTLSTS */ |
|
2795 |
|
|
2796 |
s->caps[0x09] = 0x68; /* EECP */ |
|
2797 |
|
|
2798 |
s->irq = dev->irq[3]; |
|
2799 |
s->dma = pci_dma_context(dev); |
|
2800 |
|
|
2801 |
s->capsbase = 0x00; |
|
2802 |
s->opregbase = 0x20; |
|
2784 | 2803 |
|
2785 |
pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); |
|
2804 |
usb_ehci_initfn(s, DEVICE(dev)); |
|
2805 |
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); |
|
2786 | 2806 |
|
2787 | 2807 |
return 0; |
2788 | 2808 |
} |
Also available in: Unified diff