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

📄 usb-ohci.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * QEMU USB OHCI Emulation * Copyright (c) 2004 Gianni Tedesco * Copyright (c) 2006 CodeSourcery * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * TODO: *  o Isochronous transfers *  o Allocate bandwidth in frames properly *  o Disable timers when nothing needs to be done, or remove timer usage *    all together. *  o Handle unrecoverable errors properly *  o BIOS work to boot from USB storage*/#include "vl.h"//#define DEBUG_OHCI/* Dump packet contents.  *///#define DEBUG_PACKET/* This causes frames to occur 1000x slower *///#define OHCI_TIME_WARP 1#ifdef DEBUG_OHCI#define dprintf printf#else#define dprintf(...)#endif/* Number of Downstream Ports on the root hub.  */#define OHCI_MAX_PORTS 15static int64_t usb_frame_time;static int64_t usb_bit_time;typedef struct OHCIPort {    USBPort port;    uint32_t ctrl;} OHCIPort;typedef struct {    struct PCIDevice pci_dev;    target_phys_addr_t mem_base;    int mem;    int num_ports;    QEMUTimer *eof_timer;    int64_t sof_time;    /* OHCI state */    /* Control partition */    uint32_t ctl, status;    uint32_t intr_status;    uint32_t intr;    /* memory pointer partition */    uint32_t hcca;    uint32_t ctrl_head, ctrl_cur;    uint32_t bulk_head, bulk_cur;    uint32_t per_cur;    uint32_t done;    int done_count;    /* Frame counter partition */    uint32_t fsmps:15;    uint32_t fit:1;    uint32_t fi:14;    uint32_t frt:1;    uint16_t frame_number;    uint16_t padding;    uint32_t pstart;    uint32_t lst;    /* Root Hub partition */    uint32_t rhdesc_a, rhdesc_b;    uint32_t rhstatus;    OHCIPort rhport[OHCI_MAX_PORTS];    /* Active packets.  */    uint32_t old_ctl;    USBPacket usb_packet;    uint8_t usb_buf[8192];    uint32_t async_td;    int async_complete;} OHCIState;/* Host Controller Communications Area */struct ohci_hcca {    uint32_t intr[32];    uint16_t frame, pad;    uint32_t done;};/* Bitfields for the first word of an Endpoint Desciptor.  */#define OHCI_ED_FA_SHIFT  0#define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)#define OHCI_ED_EN_SHIFT  7#define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)#define OHCI_ED_D_SHIFT   11#define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)#define OHCI_ED_S         (1<<13)#define OHCI_ED_K         (1<<14)#define OHCI_ED_F         (1<<15)#define OHCI_ED_MPS_SHIFT 7#define OHCI_ED_MPS_MASK  (0xf<<OHCI_ED_FA_SHIFT)/* Flags in the head field of an Endpoint Desciptor.  */#define OHCI_ED_H         1#define OHCI_ED_C         2/* Bitfields for the first word of a Transfer Desciptor.  */#define OHCI_TD_R         (1<<18)#define OHCI_TD_DP_SHIFT  19#define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)#define OHCI_TD_DI_SHIFT  21#define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)#define OHCI_TD_T0        (1<<24)#define OHCI_TD_T1        (1<<24)#define OHCI_TD_EC_SHIFT  26#define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)#define OHCI_TD_CC_SHIFT  28#define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)#define OHCI_DPTR_MASK    0xfffffff0#define OHCI_BM(val, field) \  (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)#define OHCI_SET_BM(val, field, newval) do { \    val &= ~OHCI_##field##_MASK; \    val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \    } while(0)/* endpoint descriptor */struct ohci_ed {    uint32_t flags;    uint32_t tail;    uint32_t head;    uint32_t next;};/* General transfer descriptor */struct ohci_td {    uint32_t flags;    uint32_t cbp;    uint32_t next;    uint32_t be;};#define USB_HZ                      12000000/* OHCI Local stuff */#define OHCI_CTL_CBSR         ((1<<0)|(1<<1))#define OHCI_CTL_PLE          (1<<2)#define OHCI_CTL_IE           (1<<3)#define OHCI_CTL_CLE          (1<<4)#define OHCI_CTL_BLE          (1<<5)#define OHCI_CTL_HCFS         ((1<<6)|(1<<7))#define  OHCI_USB_RESET       0x00#define  OHCI_USB_RESUME      0x40#define  OHCI_USB_OPERATIONAL 0x80#define  OHCI_USB_SUSPEND     0xc0#define OHCI_CTL_IR           (1<<8)#define OHCI_CTL_RWC          (1<<9)#define OHCI_CTL_RWE          (1<<10)#define OHCI_STATUS_HCR       (1<<0)#define OHCI_STATUS_CLF       (1<<1)#define OHCI_STATUS_BLF       (1<<2)#define OHCI_STATUS_OCR       (1<<3)#define OHCI_STATUS_SOC       ((1<<6)|(1<<7))#define OHCI_INTR_SO          (1<<0) /* Scheduling overrun */#define OHCI_INTR_WD          (1<<1) /* HcDoneHead writeback */#define OHCI_INTR_SF          (1<<2) /* Start of frame */#define OHCI_INTR_RD          (1<<3) /* Resume detect */#define OHCI_INTR_UE          (1<<4) /* Unrecoverable error */#define OHCI_INTR_FNO         (1<<5) /* Frame number overflow */#define OHCI_INTR_RHSC        (1<<6) /* Root hub status change */#define OHCI_INTR_OC          (1<<30) /* Ownership change */#define OHCI_INTR_MIE         (1<<31) /* Master Interrupt Enable */#define OHCI_HCCA_SIZE        0x100#define OHCI_HCCA_MASK        0xffffff00#define OHCI_EDPTR_MASK       0xfffffff0#define OHCI_FMI_FI           0x00003fff#define OHCI_FMI_FSMPS        0xffff0000#define OHCI_FMI_FIT          0x80000000#define OHCI_FR_RT            (1<<31)#define OHCI_LS_THRESH        0x628#define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */#define OHCI_RHA_PSM          (1<<8)#define OHCI_RHA_NPS          (1<<9)#define OHCI_RHA_DT           (1<<10)#define OHCI_RHA_OCPM         (1<<11)#define OHCI_RHA_NOCP         (1<<12)#define OHCI_RHA_POTPGT_MASK  0xff000000#define OHCI_RHS_LPS          (1<<0)#define OHCI_RHS_OCI          (1<<1)#define OHCI_RHS_DRWE         (1<<15)#define OHCI_RHS_LPSC         (1<<16)#define OHCI_RHS_OCIC         (1<<17)#define OHCI_RHS_CRWE         (1<<31)#define OHCI_PORT_CCS         (1<<0)#define OHCI_PORT_PES         (1<<1)#define OHCI_PORT_PSS         (1<<2)#define OHCI_PORT_POCI        (1<<3)#define OHCI_PORT_PRS         (1<<4)#define OHCI_PORT_PPS         (1<<8)#define OHCI_PORT_LSDA        (1<<9)#define OHCI_PORT_CSC         (1<<16)#define OHCI_PORT_PESC        (1<<17)#define OHCI_PORT_PSSC        (1<<18)#define OHCI_PORT_OCIC        (1<<19)#define OHCI_PORT_PRSC        (1<<20)#define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \                               |OHCI_PORT_OCIC|OHCI_PORT_PRSC)#define OHCI_TD_DIR_SETUP     0x0#define OHCI_TD_DIR_OUT       0x1#define OHCI_TD_DIR_IN        0x2#define OHCI_TD_DIR_RESERVED  0x3#define OHCI_CC_NOERROR             0x0#define OHCI_CC_CRC                 0x1#define OHCI_CC_BITSTUFFING         0x2#define OHCI_CC_DATATOGGLEMISMATCH  0x3#define OHCI_CC_STALL               0x4#define OHCI_CC_DEVICENOTRESPONDING 0x5#define OHCI_CC_PIDCHECKFAILURE     0x6#define OHCI_CC_UNDEXPETEDPID       0x7#define OHCI_CC_DATAOVERRUN         0x8#define OHCI_CC_DATAUNDERRUN        0x9#define OHCI_CC_BUFFEROVERRUN       0xc#define OHCI_CC_BUFFERUNDERRUN      0xd/* Update IRQ levels */static inline void ohci_intr_update(OHCIState *ohci){    int level = 0;    if ((ohci->intr & OHCI_INTR_MIE) &&        (ohci->intr_status & ohci->intr))        level = 1;    pci_set_irq(&ohci->pci_dev, 0, level);}/* Set an interrupt */static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr){    ohci->intr_status |= intr;    ohci_intr_update(ohci);}/* Attach or detach a device on a root hub port.  */static void ohci_attach(USBPort *port1, USBDevice *dev){    OHCIState *s = port1->opaque;    OHCIPort *port = &s->rhport[port1->index];    uint32_t old_state = port->ctrl;    if (dev) {        if (port->port.dev) {            usb_attach(port1, NULL);        }        /* set connect status */        port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;        /* update speed */        if (dev->speed == USB_SPEED_LOW)            port->ctrl |= OHCI_PORT_LSDA;        else            port->ctrl &= ~OHCI_PORT_LSDA;        port->port.dev = dev;        /* send the attach message */        usb_send_msg(dev, USB_MSG_ATTACH);        dprintf("usb-ohci: Attached port %d\n", port1->index);    } else {        /* set connect status */        if (port->ctrl & OHCI_PORT_CCS) {            port->ctrl &= ~OHCI_PORT_CCS;            port->ctrl |= OHCI_PORT_CSC;        }        /* disable port */        if (port->ctrl & OHCI_PORT_PES) {            port->ctrl &= ~OHCI_PORT_PES;            port->ctrl |= OHCI_PORT_PESC;        }        dev = port->port.dev;        if (dev) {            /* send the detach message */            usb_send_msg(dev, USB_MSG_DETACH);        }        port->port.dev = NULL;        dprintf("usb-ohci: Detached port %d\n", port1->index);    }    if (old_state != port->ctrl)        ohci_set_interrupt(s, OHCI_INTR_RHSC);}/* Reset the controller */static void ohci_reset(OHCIState *ohci){    OHCIPort *port;    int i;    ohci->ctl = 0;    ohci->old_ctl = 0;    ohci->status = 0;    ohci->intr_status = 0;    ohci->intr = OHCI_INTR_MIE;    ohci->hcca = 0;    ohci->ctrl_head = ohci->ctrl_cur = 0;    ohci->bulk_head = ohci->bulk_cur = 0;    ohci->per_cur = 0;    ohci->done = 0;    ohci->done_count = 7;    /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?     * I took the value linux sets ...     */    ohci->fsmps = 0x2778;    ohci->fi = 0x2edf;    ohci->fit = 0;    ohci->frt = 0;    ohci->frame_number = 0;    ohci->pstart = 0;    ohci->lst = OHCI_LS_THRESH;    ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;    ohci->rhdesc_b = 0x0; /* Impl. specific */    ohci->rhstatus = 0;    for (i = 0; i < ohci->num_ports; i++)      {        port = &ohci->rhport[i];        port->ctrl = 0;        if (port->port.dev)            ohci_attach(&port->port, port->port.dev);      }    if (ohci->async_td) {        usb_cancel_packet(&ohci->usb_packet);        ohci->async_td = 0;    }    dprintf("usb-ohci: Reset %s\n", ohci->pci_dev.name);}/* Get an array of dwords from main memory */static inline int get_dwords(uint32_t addr, uint32_t *buf, int num){    int i;    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {        cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0);        *buf = le32_to_cpu(*buf);    }    return 1;}/* Put an array of dwords in to main memory */static inline int put_dwords(uint32_t addr, uint32_t *buf, int num){    int i;    for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {        uint32_t tmp = cpu_to_le32(*buf);        cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1);    }    return 1;}static inline int ohci_read_ed(uint32_t addr, struct ohci_ed *ed){    return get_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);}static inline int ohci_read_td(uint32_t addr, struct ohci_td *td){    return get_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);}static inline int ohci_put_ed(uint32_t addr, struct ohci_ed *ed){    return put_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2);}static inline int ohci_put_td(uint32_t addr, struct ohci_td *td){    return put_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2);}/* Read/Write the contents of a TD from/to main memory.  */static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write){    uint32_t ptr;    uint32_t n;

⌨️ 快捷键说明

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