socsvn commit: r288633 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Tue Jul 21 18:14:12 UTC 2015
Author: iateaca
Date: Tue Jul 21 18:14:10 2015
New Revision: 288633
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=288633
Log:
add support for the read-only registers in page0 and handle the monitor mode
Modified:
soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c
Modified: soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c
==============================================================================
--- soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c Tue Jul 21 17:19:03 2015 (r288632)
+++ soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c Tue Jul 21 18:14:10 2015 (r288633)
@@ -34,10 +34,11 @@
#define NE2000_P1 1
#define NE2000_P2 2
#define NE2000_P3 3
+#define NE2000_P0_RO 4
#define NE2000_MEM_SIZE 32768
#define NE2000_PAGE_SIZE 0x10
-#define NE2000_PAGE_COUNT 4
+#define NE2000_PAGE_COUNT 5
#define NE2000_BAR_NIC 0
#define NE2000_BAR_ASIC 1
@@ -98,7 +99,7 @@
static void
ne2000_set_reg_by_offset(struct pci_ne2000_softc *sc, uint8_t page,
uint8_t offset, uint8_t value);
-static int
+static uint8_t
ne2000_get_reg_by_offset(struct pci_ne2000_softc *sc, uint8_t page,
uint8_t offset);
static void
@@ -158,7 +159,7 @@
sc->nic_regs[page][offset] = value;
}
-static int
+static uint8_t
ne2000_get_reg_by_offset(struct pci_ne2000_softc *sc, uint8_t page,
uint8_t offset)
{
@@ -270,11 +271,8 @@
DPRINTF("Receive Packet: from tap interface of %zd bytes", read_len);
- if (!ne2000_ether_frame_is_valid(sc))
- return -1;
-
- if (!ne2000_receive_ring_is_valid(sc)) {
- DPRINTF("Drop the packet since the ring is not valid");
+ if (!ne2000_ether_frame_is_valid(sc)) {
+ DPRINTF("Drop the packet since the ether frame did not match");
return 0;
}
@@ -305,10 +303,11 @@
DPRINTF("Receive Packet: size: %d psize: %d next_curr: %d index: %d",
size, psize, next_curr, index);
- ne2000_set_field_by_offset(sc, NE2000_P0, ED_P0_RSR, 0xff, ED_RSR_PRX);
+ ne2000_set_field_by_offset(sc, NE2000_P0_RO, ED_P0_RSR,
+ 0xff, ED_RSR_PRX);
ed_hdr = (struct ed_ring *)(sc->ram + index);
- ed_hdr->rsr = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_RSR);
+ ed_hdr->rsr = ne2000_get_reg_by_offset(sc, NE2000_P0_RO, ED_P0_RSR);
ed_hdr->next_packet = next_curr;
ed_hdr->count = size + sizeof(struct ed_ring);
@@ -383,6 +382,8 @@
uint8_t curr = 0;
uint8_t bnry = 0;
+ assert(ne2000_receive_ring_is_valid(sc));
+
pstart = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_PSTART);
pstop = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_PSTOP);
curr = ne2000_get_reg_by_offset(sc, NE2000_P1, ED_P1_CURR);
@@ -407,10 +408,15 @@
static int
ne2000_ether_frame_is_valid(struct pci_ne2000_softc *sc)
{
- /*
- * TODO implement a better validation taking in consideration the
- * Receiver Configuration Register (RCR) and maybe the frame's CRC
- */
+ uint8_t rcr = 0;
+ uint8_t broadcast_addr[] = {[0 ... (ETHER_ADDR_LEN - 1)] = 0xff};
+
+ rcr = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_RCR);
+
+ if (rcr & ED_RCR_MON) {
+ DPRINTF("The NIC card is in Monitor Mode");
+ return 0;
+ }
/* is valid if the destination MAC matches the NIC's address */
if (sc->rcv_buf[0] == sc->ram[0] &&
@@ -422,13 +428,10 @@
return 1;
/* is valid if the destination MAC is the broadcast address */
- if (sc->rcv_buf[0] == 0xff &&
- sc->rcv_buf[1] == 0xff &&
- sc->rcv_buf[2] == 0xff &&
- sc->rcv_buf[3] == 0xff &&
- sc->rcv_buf[4] == 0xff &&
- sc->rcv_buf[5] == 0xff)
- return 1;
+ if (rcr & ED_RCR_AB) {
+ if (memcmp(sc->rcv_buf, broadcast_addr, ETHER_ADDR_LEN) == 0)
+ return 1;
+ }
return 0;
}
@@ -771,6 +774,9 @@
ne2000_set_field_by_offset(sc, NE2000_P0, ED_P0_ISR, value, 0);
pci_ne2000_update_intr(sc);
break;
+ case ED_P0_RCR:
+ DPRINTF("RCR Register: %d", value);
+ break;
}
return 0;
@@ -835,17 +841,41 @@
{
uint8_t value = 0;
- /* check is not a RTL8029 Register Defined in Page0 */
+ /*
+ * check is either a RTL8029 Register Defined in Page0
+ * or is a read-only Register Defined in Page0
+ */
if (sc->page == NE2000_P0) {
- if (offset == ED_RTL80X9_80X9ID0)
- return ED_RTL80X9_ID0;
- else if (offset == ED_RTL80X9_80X9ID1)
- return ED_RTL8029_ID1;
+ switch (offset) {
+ case ED_RTL80X9_80X9ID0:
+ value = ED_RTL80X9_ID0;
+ break;
+ case ED_RTL80X9_80X9ID1:
+ value = ED_RTL8029_ID1;
+ break;
+ case ED_P0_CLDA0:
+ case ED_P0_CLDA1:
+ case ED_P0_TSR:
+ case ED_P0_NCR:
+ case ED_P0_FIFO:
+ case ED_P0_CRDA0:
+ case ED_P0_CRDA1:
+ case ED_P0_RSR:
+ case ED_P0_CNTR0:
+ case ED_P0_CNTR1:
+ case ED_P0_CNTR2:
+ /* read a read-only register from page 0 */
+ value = ne2000_get_reg_by_offset(sc, NE2000_P0_RO, offset);
+ break;
+ default:
+ value = ne2000_get_reg_by_offset(sc, NE2000_P0, offset);
+ break;
+ }
+ } else {
+ /* read a general NE2000 register */
+ value = ne2000_get_reg_by_offset(sc, sc->page, offset);
}
- /* read a general NE2000 register */
- value = ne2000_get_reg_by_offset(sc, sc->page, offset);
-
return value;
}
More information about the svn-soc-all
mailing list