⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb-ohci.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Set the frame interval - frame interval toggle is manipulated by the hcd only */static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val){    val &= OHCI_FMI_FI;    if (val != ohci->fi) {        dprintf("usb-ohci: %s: FrameInterval = 0x%x (%u)\n",            ohci->pci_dev.name, ohci->fi, ohci->fi);    }    ohci->fi = val;}static void ohci_port_power(OHCIState *ohci, int i, int p){    if (p) {        ohci->rhport[i].ctrl |= OHCI_PORT_PPS;    } else {        ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|                    OHCI_PORT_CCS|                    OHCI_PORT_PSS|                    OHCI_PORT_PRS);    }}/* Set HcControlRegister */static void ohci_set_ctl(OHCIState *ohci, uint32_t val){    uint32_t old_state;    uint32_t new_state;    old_state = ohci->ctl & OHCI_CTL_HCFS;    ohci->ctl = val;    new_state = ohci->ctl & OHCI_CTL_HCFS;    /* no state change */    if (old_state == new_state)        return;    switch (new_state) {    case OHCI_USB_OPERATIONAL:        ohci_bus_start(ohci);        break;    case OHCI_USB_SUSPEND:        ohci_bus_stop(ohci);        dprintf("usb-ohci: %s: USB Suspended\n", ohci->pci_dev.name);        break;    case OHCI_USB_RESUME:        dprintf("usb-ohci: %s: USB Resume\n", ohci->pci_dev.name);        break;    case OHCI_USB_RESET:        dprintf("usb-ohci: %s: USB Reset\n", ohci->pci_dev.name);        break;    }}static uint32_t ohci_get_frame_remaining(OHCIState *ohci){    uint16_t fr;    int64_t tks;    if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)        return (ohci->frt << 31);    /* Being in USB operational state guarnatees sof_time was     * set already.     */    tks = qemu_get_clock(vm_clock) - ohci->sof_time;    /* avoid muldiv if possible */    if (tks >= usb_frame_time)        return (ohci->frt << 31);    tks = muldiv64(1, tks, usb_bit_time);    fr = (uint16_t)(ohci->fi - tks);    return (ohci->frt << 31) | fr;}/* Set root hub status */static void ohci_set_hub_status(OHCIState *ohci, uint32_t val){    uint32_t old_state;    old_state = ohci->rhstatus;    /* write 1 to clear OCIC */    if (val & OHCI_RHS_OCIC)        ohci->rhstatus &= ~OHCI_RHS_OCIC;    if (val & OHCI_RHS_LPS) {        int i;        for (i = 0; i < ohci->num_ports; i++)            ohci_port_power(ohci, i, 0);        dprintf("usb-ohci: powered down all ports\n");    }    if (val & OHCI_RHS_LPSC) {        int i;        for (i = 0; i < ohci->num_ports; i++)            ohci_port_power(ohci, i, 1);        dprintf("usb-ohci: powered up all ports\n");    }    if (val & OHCI_RHS_DRWE)        ohci->rhstatus |= OHCI_RHS_DRWE;    if (val & OHCI_RHS_CRWE)        ohci->rhstatus &= ~OHCI_RHS_DRWE;    if (old_state != ohci->rhstatus)        ohci_set_interrupt(ohci, OHCI_INTR_RHSC);}/* Set root hub port status */static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val){    uint32_t old_state;    OHCIPort *port;    port = &ohci->rhport[portnum];    old_state = port->ctrl;    /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */    if (val & OHCI_PORT_WTC)        port->ctrl &= ~(val & OHCI_PORT_WTC);    if (val & OHCI_PORT_CCS)        port->ctrl &= ~OHCI_PORT_PES;    ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS))        dprintf("usb-ohci: port %d: SUSPEND\n", portnum);    if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {        dprintf("usb-ohci: port %d: RESET\n", portnum);        usb_send_msg(port->port.dev, USB_MSG_RESET);        port->ctrl &= ~OHCI_PORT_PRS;        /* ??? Should this also set OHCI_PORT_PESC.  */        port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;    }    /* Invert order here to ensure in ambiguous case, device is     * powered up...     */    if (val & OHCI_PORT_LSDA)        ohci_port_power(ohci, portnum, 0);    if (val & OHCI_PORT_PPS)        ohci_port_power(ohci, portnum, 1);    if (old_state != port->ctrl)        ohci_set_interrupt(ohci, OHCI_INTR_RHSC);    return;}static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr){    OHCIState *ohci = ptr;    addr -= ohci->mem_base;    /* Only aligned reads are allowed on OHCI */    if (addr & 3) {        fprintf(stderr, "usb-ohci: Mis-aligned read\n");        return 0xffffffff;    }    if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {        /* HcRhPortStatus */        return ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;    }    switch (addr >> 2) {    case 0: /* HcRevision */        return 0x10;    case 1: /* HcControl */        return ohci->ctl;    case 2: /* HcCommandStatus */        return ohci->status;    case 3: /* HcInterruptStatus */        return ohci->intr_status;    case 4: /* HcInterruptEnable */    case 5: /* HcInterruptDisable */        return ohci->intr;    case 6: /* HcHCCA */        return ohci->hcca;    case 7: /* HcPeriodCurrentED */        return ohci->per_cur;    case 8: /* HcControlHeadED */        return ohci->ctrl_head;    case 9: /* HcControlCurrentED */        return ohci->ctrl_cur;    case 10: /* HcBulkHeadED */        return ohci->bulk_head;    case 11: /* HcBulkCurrentED */        return ohci->bulk_cur;    case 12: /* HcDoneHead */        return ohci->done;    case 13: /* HcFmInterval */        return (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);    case 14: /* HcFmRemaining */        return ohci_get_frame_remaining(ohci);    case 15: /* HcFmNumber */        return ohci->frame_number;    case 16: /* HcPeriodicStart */        return ohci->pstart;    case 17: /* HcLSThreshold */        return ohci->lst;    case 18: /* HcRhDescriptorA */        return ohci->rhdesc_a;    case 19: /* HcRhDescriptorB */        return ohci->rhdesc_b;    case 20: /* HcRhStatus */        return ohci->rhstatus;    default:        fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);        return 0xffffffff;    }}static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val){    OHCIState *ohci = ptr;    addr -= ohci->mem_base;    /* Only aligned reads are allowed on OHCI */    if (addr & 3) {        fprintf(stderr, "usb-ohci: Mis-aligned write\n");        return;    }    if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {        /* HcRhPortStatus */        ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);        return;    }    switch (addr >> 2) {    case 1: /* HcControl */        ohci_set_ctl(ohci, val);        break;    case 2: /* HcCommandStatus */        /* SOC is read-only */        val = (val & ~OHCI_STATUS_SOC);        /* Bits written as '0' remain unchanged in the register */        ohci->status |= val;        if (ohci->status & OHCI_STATUS_HCR)            ohci_reset(ohci);        break;    case 3: /* HcInterruptStatus */        ohci->intr_status &= ~val;        ohci_intr_update(ohci);        break;    case 4: /* HcInterruptEnable */        ohci->intr |= val;        ohci_intr_update(ohci);        break;    case 5: /* HcInterruptDisable */        ohci->intr &= ~val;        ohci_intr_update(ohci);        break;    case 6: /* HcHCCA */        ohci->hcca = val & OHCI_HCCA_MASK;        break;    case 8: /* HcControlHeadED */        ohci->ctrl_head = val & OHCI_EDPTR_MASK;        break;    case 9: /* HcControlCurrentED */        ohci->ctrl_cur = val & OHCI_EDPTR_MASK;        break;    case 10: /* HcBulkHeadED */        ohci->bulk_head = val & OHCI_EDPTR_MASK;        break;    case 11: /* HcBulkCurrentED */        ohci->bulk_cur = val & OHCI_EDPTR_MASK;        break;    case 13: /* HcFmInterval */        ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;        ohci->fit = (val & OHCI_FMI_FIT) >> 31;        ohci_set_frame_interval(ohci, val);        break;    case 16: /* HcPeriodicStart */        ohci->pstart = val & 0xffff;        break;    case 17: /* HcLSThreshold */        ohci->lst = val & 0xffff;        break;    case 18: /* HcRhDescriptorA */        ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;        ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;        break;    case 19: /* HcRhDescriptorB */        break;    case 20: /* HcRhStatus */        ohci_set_hub_status(ohci, val);        break;    default:        fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr);        break;    }}/* Only dword reads are defined on OHCI register space */static CPUReadMemoryFunc *ohci_readfn[3]={    ohci_mem_read,    ohci_mem_read,    ohci_mem_read};/* Only dword writes are defined on OHCI register space */static CPUWriteMemoryFunc *ohci_writefn[3]={    ohci_mem_write,    ohci_mem_write,    ohci_mem_write};static void ohci_mapfunc(PCIDevice *pci_dev, int i,            uint32_t addr, uint32_t size, int type){    OHCIState *ohci = (OHCIState *)pci_dev;    ohci->mem_base = addr;    cpu_register_physical_memory(addr, size, ohci->mem);}void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn){    OHCIState *ohci;    int vid = 0x106b;    int did = 0x003f;    int i;    if (usb_frame_time == 0) {#if OHCI_TIME_WARP        usb_frame_time = ticks_per_sec;        usb_bit_time = muldiv64(1, ticks_per_sec, USB_HZ/1000);#else        usb_frame_time = muldiv64(1, ticks_per_sec, 1000);        if (ticks_per_sec >= USB_HZ) {            usb_bit_time = muldiv64(1, ticks_per_sec, USB_HZ);        } else {            usb_bit_time = 1;        }#endif        dprintf("usb-ohci: usb_bit_time=%lli usb_frame_time=%lli\n",                usb_frame_time, usb_bit_time);    }    ohci = (OHCIState *)pci_register_device(bus, "OHCI USB", sizeof(*ohci),                                            devfn, NULL, NULL);    if (ohci == NULL) {        fprintf(stderr, "usb-ohci: Failed to register PCI device\n");        return;    }    ohci->pci_dev.config[0x00] = vid & 0xff;    ohci->pci_dev.config[0x01] = (vid >> 8) & 0xff;    ohci->pci_dev.config[0x02] = did & 0xff;    ohci->pci_dev.config[0x03] = (did >> 8) & 0xff;    ohci->pci_dev.config[0x09] = 0x10; /* OHCI */    ohci->pci_dev.config[0x0a] = 0x3;    ohci->pci_dev.config[0x0b] = 0xc;    ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */    ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci);    pci_register_io_region((struct PCIDevice *)ohci, 0, 256,                           PCI_ADDRESS_SPACE_MEM, ohci_mapfunc);    ohci->num_ports = num_ports;    for (i = 0; i < num_ports; i++) {        qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);    }    ohci->async_td = 0;    ohci_reset(ohci);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -