From owner-svn-soc-all@freebsd.org Tue Jul 21 18:14:11 2015 Return-Path: Delivered-To: svn-soc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E36FA9A7D2A for ; Tue, 21 Jul 2015 18:14:11 +0000 (UTC) (envelope-from iateaca@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C8B781A45 for ; Tue, 21 Jul 2015 18:14:11 +0000 (UTC) (envelope-from iateaca@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.15.2/8.15.2) with ESMTP id t6LIEB1h053537 for ; Tue, 21 Jul 2015 18:14:11 GMT (envelope-from iateaca@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.15.2/8.15.2/Submit) id t6LIEBu9052842 for svn-soc-all@FreeBSD.org; Tue, 21 Jul 2015 18:14:11 GMT (envelope-from iateaca@FreeBSD.org) Date: Tue, 21 Jul 2015 18:14:11 GMT Message-Id: <201507211814.t6LIEBu9052842@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to iateaca@FreeBSD.org using -f From: iateaca@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r288633 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Jul 2015 18:14:12 -0000 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; }