Revision 322fd48a hw/e1000.c

b/hw/e1000.c
631 631
    return (s->mac_reg[RCTL] & E1000_RCTL_EN);
632 632
}
633 633

  
634
static bool e1000_has_rxbufs(E1000State *s, size_t total_size)
635
{
636
    int bufs;
637
    /* Fast-path short packets */
638
    if (total_size <= s->rxbuf_size) {
639
        return s->mac_reg[RDH] != s->mac_reg[RDT] || !s->check_rxov;
640
    }
641
    if (s->mac_reg[RDH] < s->mac_reg[RDT]) {
642
        bufs = s->mac_reg[RDT] - s->mac_reg[RDH];
643
    } else if (s->mac_reg[RDH] > s->mac_reg[RDT] || !s->check_rxov) {
644
        bufs = s->mac_reg[RDLEN] /  sizeof(struct e1000_rx_desc) +
645
            s->mac_reg[RDT] - s->mac_reg[RDH];
646
    } else {
647
        return false;
648
    }
649
    return total_size <= bufs * s->rxbuf_size;
650
}
651

  
634 652
static ssize_t
635 653
e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
636 654
{
......
671 689
    rdh_start = s->mac_reg[RDH];
672 690
    desc_offset = 0;
673 691
    total_size = size + fcs_len(s);
692
    if (!e1000_has_rxbufs(s, total_size)) {
693
            set_ics(s, 0, E1000_ICS_RXO);
694
            return -1;
695
    }
674 696
    do {
675 697
        desc_size = total_size - desc_offset;
676 698
        if (desc_size > s->rxbuf_size) {
677 699
            desc_size = s->rxbuf_size;
678 700
        }
679
        if (s->mac_reg[RDH] == s->mac_reg[RDT] && s->check_rxov) {
680
            /* Discard all data written so far */
681
            s->mac_reg[RDH] = rdh_start;
682
            set_ics(s, 0, E1000_ICS_RXO);
683
            return -1;
684
        }
685 701
        base = ((uint64_t)s->mac_reg[RDBAH] << 32) + s->mac_reg[RDBAL] +
686 702
               sizeof(desc) * s->mac_reg[RDH];
687 703
        cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));

Also available in: Unified diff