Revision b19487e2

b/hw/e1000.c
642 642
    uint16_t vlan_special = 0;
643 643
    uint8_t vlan_status = 0, vlan_offset = 0;
644 644
    uint8_t min_buf[MIN_BUF_SIZE];
645
    size_t desc_offset;
646
    size_t desc_size;
647
    size_t total_size;
645 648

  
646 649
    if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
647 650
        return -1;
......
654 657
        size = sizeof(min_buf);
655 658
    }
656 659

  
657
    if (size > s->rxbuf_size) {
658
        DBGOUT(RX, "packet too large for buffers (%lu > %d)\n",
659
               (unsigned long)size, s->rxbuf_size);
660
        return -1;
661
    }
662

  
663 660
    if (!receive_filter(s, buf, size))
664 661
        return size;
665 662

  
......
672 669
    }
673 670

  
674 671
    rdh_start = s->mac_reg[RDH];
672
    desc_offset = 0;
673
    total_size = size + fcs_len(s);
675 674
    do {
675
        desc_size = total_size - desc_offset;
676
        if (desc_size > s->rxbuf_size) {
677
            desc_size = s->rxbuf_size;
678
        }
676 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;
677 682
            set_ics(s, 0, E1000_ICS_RXO);
678 683
            return -1;
679 684
        }
......
683 688
        desc.special = vlan_special;
684 689
        desc.status |= (vlan_status | E1000_RXD_STAT_DD);
685 690
        if (desc.buffer_addr) {
686
            cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
687
                                      (void *)(buf + vlan_offset), size);
688
            desc.length = cpu_to_le16(size + fcs_len(s));
689
            desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;
691
            if (desc_offset < size) {
692
                size_t copy_size = size - desc_offset;
693
                if (copy_size > s->rxbuf_size) {
694
                    copy_size = s->rxbuf_size;
695
                }
696
                cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
697
                                          (void *)(buf + desc_offset + vlan_offset),
698
                                          copy_size);
699
            }
700
            desc_offset += desc_size;
701
            if (desc_offset >= total_size) {
702
                desc.length = cpu_to_le16(desc_size);
703
                desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM;
704
            } else {
705
                desc.length = cpu_to_le16(desc_size);
706
            }
690 707
        } else { // as per intel docs; skip descriptors with null buf addr
691 708
            DBGOUT(RX, "Null RX descriptor!!\n");
692 709
        }
......
702 719
            set_ics(s, 0, E1000_ICS_RXO);
703 720
            return -1;
704 721
        }
705
    } while (desc.buffer_addr == 0);
722
    } while (desc_offset < total_size);
706 723

  
707 724
    s->mac_reg[GPRC]++;
708 725
    s->mac_reg[TPR]++;

Also available in: Unified diff