Date: Tue, 18 Aug 2015 08:35:39 GMT From: iateaca@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r289857 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve Message-ID: <201508180835.t7I8ZdZX080841@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: iateaca Date: Tue Aug 18 08:35:38 2015 New Revision: 289857 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=289857 Log: implement the software reset workaround, and the software reset routine 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 Aug 18 06:28:37 2015 (r289856) +++ soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_ne2000.c Tue Aug 18 08:35:38 2015 (r289857) @@ -286,13 +286,18 @@ /* clear the Receiver Status Register */ ne2000_set_reg_by_offset(sc, NE2000_P0_RO, ED_P0_RSR, 0x00); + if (!ne2000_receive_ring_is_valid(sc)) { + DPRINTF("Drop the packet: the ring is not valid"); + return 0; + } + if (!ne2000_ether_frame_is_valid(sc)) { - DPRINTF("Drop the packet since the ether frame did not match"); + DPRINTF("Drop the packet: the ether frame did not match"); return 0; } if (ne2000_receive_ring_is_full(sc)) { - DPRINTF("Drop the packet since the ring is full"); + DPRINTF("Drop the packet: the ring is full"); return 0; } @@ -367,12 +372,20 @@ static int ne2000_receive_ring_is_valid(struct pci_ne2000_softc *sc) { + uint8_t cr = 0; + uint8_t pstart = 0; uint8_t pstop = 0; uint8_t curr = 0; uint8_t bnry = 0; + cr = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_CR); + if (cr & ED_CR_STP) { + DPRINTF("Ring is not valid: the NIC is Stopped"); + return 0; + } + pstart = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_PSTART); pstop = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_PSTOP); @@ -772,6 +785,8 @@ uint16_t tbcr = 0; uint8_t tpsr = 0; + uint8_t old_cr = 0; + /* check is not selected a new page */ switch (value & (ED_CR_PS0 | ED_CR_PS1)) { case ED_CR_PAGE_0: @@ -789,10 +804,14 @@ break; } + old_cr = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_CR); + /* emulate any command specified in the CR register */ - if (value & ED_CR_STP) { - err = ne2000_software_reset(sc); - assert(err == 0); + if (value & ED_CR_STA) { + if ((old_cr & ED_CR_STA) == 0) { + ne2000_set_field_by_offset(sc, NE2000_P0, ED_P0_ISR, + ED_ISR_RST, 0); + } } if (value & ED_CR_RD2) assert(!(sc->remote_read || sc->remote_write)); @@ -910,6 +929,18 @@ static int ne2000_software_reset(struct pci_ne2000_softc *sc) { + DPRINTF("The NIC is in Software Reset State"); + + /* reset the Receive Ring Registers */ + ne2000_set_reg_by_offset(sc, NE2000_P0, ED_P0_PSTART, 0); + ne2000_set_reg_by_offset(sc, NE2000_P0, ED_P0_PSTOP, 0); + ne2000_set_reg_by_offset(sc, NE2000_P1, ED_P1_CURR, 0); + ne2000_set_reg_by_offset(sc, NE2000_P0, ED_P0_BNRY, 0); + + /* disable the interrupts */ + ne2000_set_reg_by_offset(sc, NE2000_P0, ED_P0_IMR, 0); + + /* the NIC enters the reset state */ ne2000_set_field_by_offset(sc, NE2000_P0, ED_P0_ISR, ED_ISR_RST, ED_ISR_RST); @@ -952,7 +983,9 @@ static uint8_t ne2000_read_nic(struct pci_ne2000_softc *sc, uint8_t offset) { + int err; uint8_t value = 0; + uint8_t cr = 0; /* * check is either a RTL8029 Register Defined in Page0 @@ -980,6 +1013,21 @@ /* read a read-only register from page 0 */ value = ne2000_get_reg_by_offset(sc, NE2000_P0_RO, offset); break; + case ED_P0_ISR: + /* + * Software Reset Workaround: the NIC enters the reset state + * in about 5us after the STP bit was set. Because of this + * we don't reset it every time the STP bit is set, but only + * when the ED driver polls the ISR register looking for + * the RST bit. + */ + cr = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_CR); + if (cr & ED_CR_STP) { + err = ne2000_software_reset(sc); + assert(err == 0); + } + value = ne2000_get_reg_by_offset(sc, NE2000_P0, ED_P0_ISR); + break; default: value = ne2000_get_reg_by_offset(sc, NE2000_P0, offset); break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508180835.t7I8ZdZX080841>