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

📄 e1000.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
        tp->tso_frames++;    }    if (tp->sum_needed & E1000_TXD_POPTS_TXSM)        putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse);    if (tp->sum_needed & E1000_TXD_POPTS_IXSM)        putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse);    qemu_send_packet(s->vc, tp->data, tp->size);    s->mac_reg[TPT]++;    s->mac_reg[GPTC]++;    n = s->mac_reg[TOTL];    if ((s->mac_reg[TOTL] += s->tx.size) < n)        s->mac_reg[TOTH]++;}static voidprocess_tx_desc(E1000State *s, struct e1000_tx_desc *dp){    uint32_t txd_lower = le32_to_cpu(dp->lower.data);    uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);    unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;    unsigned int msh = 0xfffff, hdr = 0;    uint64_t addr;    struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;    struct e1000_tx *tp = &s->tx;    if (dtype == E1000_TXD_CMD_DEXT) {	// context descriptor        op = le32_to_cpu(xp->cmd_and_length);        tp->ipcss = xp->lower_setup.ip_fields.ipcss;        tp->ipcso = xp->lower_setup.ip_fields.ipcso;        tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse);        tp->tucss = xp->upper_setup.tcp_fields.tucss;        tp->tucso = xp->upper_setup.tcp_fields.tucso;        tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse);        tp->paylen = op & 0xfffff;        tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len;        tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss);        tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0;        tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0;        tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0;        tp->tso_frames = 0;        if (tp->tucso == 0) {	// this is probably wrong            DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");            tp->tucso = tp->tucss + (tp->tcp ? 16 : 6);        }        return;    } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)){        // data descriptor        tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;        tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;    } else        // legacy descriptor        tp->cptse = 0;    addr = le64_to_cpu(dp->buffer_addr);    if (tp->tse && tp->cptse) {        hdr = tp->hdr_len;        msh = hdr + tp->mss;        do {            bytes = split_size;            if (tp->size + bytes > msh)                bytes = msh - tp->size;            cpu_physical_memory_read(addr, tp->data + tp->size, bytes);            if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)                memmove(tp->header, tp->data, hdr);            tp->size = sz;            addr += bytes;            if (sz == msh) {                xmit_seg(s);                memmove(tp->data, tp->header, hdr);                tp->size = hdr;            }        } while (split_size -= bytes);    } else if (!tp->tse && tp->cptse) {        // context descriptor TSE is not set, while data descriptor TSE is set        DBGOUT(TXERR, "TCP segmentaion Error\n");    } else {        cpu_physical_memory_read(addr, tp->data + tp->size, split_size);        tp->size += split_size;    }    if (!(txd_lower & E1000_TXD_CMD_EOP))        return;    if (!(tp->tse && tp->cptse && tp->size < hdr))        xmit_seg(s);    tp->tso_frames = 0;    tp->sum_needed = 0;    tp->size = 0;    tp->cptse = 0;}static uint32_ttxdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp){    uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);    if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS)))        return 0;    txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) &                ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);    dp->upper.data = cpu_to_le32(txd_upper);    cpu_physical_memory_write(base + ((char *)&dp->upper - (char *)dp),                              (void *)&dp->upper, sizeof(dp->upper));    return E1000_ICR_TXDW;}static voidstart_xmit(E1000State *s){    target_phys_addr_t base;    struct e1000_tx_desc desc;    uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE;    if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) {        DBGOUT(TX, "tx disabled\n");        return;    }    while (s->mac_reg[TDH] != s->mac_reg[TDT]) {        base = ((uint64_t)s->mac_reg[TDBAH] << 32) + s->mac_reg[TDBAL] +               sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];        cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));        DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],               (void *)desc.buffer_addr, desc.lower.data,               desc.upper.data);        process_tx_desc(s, &desc);        cause |= txdesc_writeback(base, &desc);        if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN])            s->mac_reg[TDH] = 0;        /*         * the following could happen only if guest sw assigns         * bogus values to TDT/TDLEN.         * there's nothing too intelligent we could do about this.         */        if (s->mac_reg[TDH] == tdh_start) {            DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",                   tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);            break;        }    }    set_ics(s, 0, cause);}static intreceive_filter(E1000State *s, const uint8_t *buf, int size){    static uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};    static int mta_shift[] = {4, 3, 2, 0};    uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;    if (rctl & E1000_RCTL_UPE)			// promiscuous        return 1;    if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE))	// promiscuous mcast        return 1;    if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast))        return 1;    for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) {        if (!(rp[1] & E1000_RAH_AV))            continue;        ra[0] = cpu_to_le32(rp[0]);        ra[1] = cpu_to_le32(rp[1]);        if (!memcmp(buf, (uint8_t *)ra, 6)) {            DBGOUT(RXFILTER,                   "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",                   (int)(rp - s->mac_reg - RA)/2,                   buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);            return 1;        }    }    DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n",           buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);    f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];    f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;    if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f)))        return 1;    DBGOUT(RXFILTER,           "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n",           buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],           (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5,           s->mac_reg[MTA + (f >> 5)]);    return 0;}static inte1000_can_receive(void *opaque){    E1000State *s = opaque;    return (!(s->mac_reg[RCTL] & E1000_RCTL_EN) ||            s->mac_reg[RDH] != s->mac_reg[RDT]);}static voide1000_receive(void *opaque, const uint8_t *buf, int size){    E1000State *s = opaque;    struct e1000_rx_desc desc;    target_phys_addr_t base;    unsigned int n, rdt;    uint32_t rdh_start;    if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))        return;    if (size > s->rxbuf_size) {        DBGOUT(RX, "packet too large for buffers (%d > %d)\n", size,               s->rxbuf_size);        return;    }    if (!receive_filter(s, buf, size))        return;    rdh_start = s->mac_reg[RDH];    size += 4; // for the header    do {        if (s->mac_reg[RDH] == s->mac_reg[RDT] && s->check_rxov) {            set_ics(s, 0, E1000_ICS_RXO);            return;        }        base = ((uint64_t)s->mac_reg[RDBAH] << 32) + s->mac_reg[RDBAL] +               sizeof(desc) * s->mac_reg[RDH];        cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));        desc.status |= E1000_RXD_STAT_DD;        if (desc.buffer_addr) {            cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),                                      (void *)buf, size);            desc.length = cpu_to_le16(size);            desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;        } else // as per intel docs; skip descriptors with null buf addr            DBGOUT(RX, "Null RX descriptor!!\n");        cpu_physical_memory_write(base, (void *)&desc, sizeof(desc));        if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])            s->mac_reg[RDH] = 0;        s->check_rxov = 1;        /* see comment in start_xmit; same here */        if (s->mac_reg[RDH] == rdh_start) {            DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",                   rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);            set_ics(s, 0, E1000_ICS_RXO);            return;        }    } while (desc.buffer_addr == 0);    s->mac_reg[GPRC]++;    s->mac_reg[TPR]++;    n = s->mac_reg[TORL];    if ((s->mac_reg[TORL] += size) < n)        s->mac_reg[TORH]++;    n = E1000_ICS_RXT0;    if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])        rdt += s->mac_reg[RDLEN] / sizeof(desc);    if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) << s->rxbuf_min_shift >=        s->mac_reg[RDLEN])        n |= E1000_ICS_RXDMT0;    set_ics(s, 0, n);}static uint32_tmac_readreg(E1000State *s, int index){    return s->mac_reg[index];}static uint32_tmac_icr_read(E1000State *s, int index){    uint32_t ret = s->mac_reg[ICR];    DBGOUT(INTERRUPT, "ICR read: %x\n", ret);    set_interrupt_cause(s, 0, 0);    return ret;}static uint32_tmac_read_clr4(E1000State *s, int index){    uint32_t ret = s->mac_reg[index];    s->mac_reg[index] = 0;    return ret;}static uint32_tmac_read_clr8(E1000State *s, int index){    uint32_t ret = s->mac_reg[index];    s->mac_reg[index] = 0;    s->mac_reg[index-1] = 0;    return ret;}static voidmac_writereg(E1000State *s, int index, uint32_t val){    s->mac_reg[index] = val;}static voidset_rdt(E1000State *s, int index, uint32_t val){    s->check_rxov = 0;    s->mac_reg[index] = val & 0xffff;}static voidset_16bit(E1000State *s, int index, uint32_t val){    s->mac_reg[index] = val & 0xffff;}static voidset_dlen(E1000State *s, int index, uint32_t val){    s->mac_reg[index] = val & 0xfff80;}static voidset_tctl(E1000State *s, int index, uint32_t val){    s->mac_reg[index] = val;    s->mac_reg[TDT] &= 0xffff;    start_xmit(s);}

⌨️ 快捷键说明

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