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