+++ /dev/null
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+++ /dev/null
-/*********************************************************
- * Copyright (C) 2004 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation version 2 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- *********************************************************/
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/systm.h>
-
-/*
- * FreeBSD 5.3 introduced an MP-safe (multiprocessor-safe) network stack.
- * I.e., drivers must either request Giant's protection or handle locking
- * themselves. For performance reasons, the vmxnet driver is now MPSAFE.
- */
-#if __FreeBSD_version >= 503000
-# define VXN_MPSAFE
-# include <sys/lock.h>
-# include <sys/mutex.h>
-#endif
-
-/*
- * FreeBSD 7.0-RELEASE changed the bus_setup_intr API to include a device_filter_t
- * parameter.
- */
-#if __FreeBSD_version >= 700031
-# define VXN_NEWNEWBUS
-#endif
-
-#if __FreeBSD_version < 600000
-#include <machine/bus_pio.h>
-#else
-#include <net/if_types.h>
-#endif
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <machine/clock.h>
-
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/ethernet.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-
-#include <net/bpf.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#if __FreeBSD__ >= 5
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-#else
-#include <pci/pcireg.h>
-#include <pci/pcivar.h>
-#endif
-
-/* define INLINE the way gcc likes it */
-#define INLINE __inline__
-
-#ifndef VMX86_TOOLS
-#define VMX86_TOOLS
-#endif
-#include "vm_basic_types.h"
-#include "vmxnet_def.h"
-#include "vmxnet2_def.h"
-#include "vm_device_version.h"
-#include "net_compat.h"
-
-#define VMXNET_ID_STRING "VMware PCI Ethernet Adpater"
-#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
-#define ETHER_ALIGN 2
-
-/* number of milliseconds to wait for pending transmits to complete on stop */
-#define MAX_TX_WAIT_ON_STOP 2000
-
-static int vxn_probe (device_t);
-static int vxn_attach (device_t);
-static int vxn_detach (device_t);
-
-typedef struct vxn_softc {
-#ifdef VXN_NEEDARPCOM
- struct arpcom arpcom;
-#else
- struct ifnet *vxn_ifp;
- struct ifmedia media;
-#endif
-#ifdef VXN_MPSAFE
- struct mtx vxn_mtx;
-#endif
- struct resource *vxn_io;
- bus_space_handle_t vxn_iobhandle;
- bus_space_tag_t vxn_iobtag;
- struct resource *vxn_irq;
- void *vxn_intrhand;
- Vmxnet2_DriverData *vxn_dd;
- uint32 vxn_dd_phys;
- int vxn_num_rx_bufs;
- int vxn_num_tx_bufs;
- Vmxnet2_RxRingEntry *vxn_rx_ring;
- Vmxnet2_TxRingEntry *vxn_tx_ring;
- int vxn_tx_pending;
- int vxn_rings_allocated;
- uint32 vxn_max_tx_frags;
-
- struct mbuf *vxn_tx_buffptr[VMXNET2_MAX_NUM_TX_BUFFERS];
- struct mbuf *vxn_rx_buffptr[VMXNET2_MAX_NUM_RX_BUFFERS];
-
-} vxn_softc_t;
-
-/*
- * Driver entry points
- */
-static void vxn_init(void *);
-static void vxn_start(struct ifnet *);
-static int vxn_ioctl(struct ifnet *, u_long, caddr_t);
-#if __FreeBSD_version < 900000
-static void vxn_watchdog(struct ifnet *);
-#endif
-static void vxn_intr (void *);
-
-static void vxn_rx(vxn_softc_t *sc);
-static void vxn_tx_complete(vxn_softc_t *sc);
-static int vxn_init_rings(vxn_softc_t *sc);
-static void vxn_release_rings(vxn_softc_t *);
-static void vxn_stop(vxn_softc_t *);
-
-/*
- * Locked counterparts above functions
- */
-static void vxn_initl(vxn_softc_t *);
-static void vxn_startl(struct ifnet *);
-static void vxn_stopl(vxn_softc_t *);
-
-static device_method_t vxn_methods[] = {
- DEVMETHOD(device_probe, vxn_probe),
- DEVMETHOD(device_attach, vxn_attach),
- DEVMETHOD(device_detach, vxn_detach),
-
- { 0, 0 }
-};
-
-static driver_t vxn_driver = {
- "vxn",
- vxn_methods,
- sizeof(struct vxn_softc)
-};
-
-static devclass_t vxn_devclass;
-
-MODULE_DEPEND(if_vxn, pci, 1, 1, 1);
-DRIVER_MODULE(if_vxn, pci, vxn_driver, vxn_devclass, 0, 0);
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_probe --
- * Probe device. Called when module is loaded
- *
- * Results:
- * Returns 0 for success, negative errno value otherwise.
- *
- * Side effects:
- * Register device name with OS
- *-----------------------------------------------------------------------------
- */
-static int
-vxn_probe(device_t dev)
-{
- if ((pci_get_vendor(dev) == PCI_VENDOR_ID_VMWARE) &&
- (pci_get_device(dev) == PCI_DEVICE_ID_VMWARE_NET)) {
- device_set_desc(dev, VMXNET_ID_STRING);
- return 0;
- }
-
- return ENXIO;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_execute_4 --
- * Execute command returing 4 bytes on vmxnet. Used to retrieve
- * number of TX/RX buffers and to get hardware capabilities and
- * features.
- *
- * Results:
- * Returns value reported by hardware.
- *
- * Side effects:
- * All commands supported are read-only, so no side effects.
- *-----------------------------------------------------------------------------
- */
-static u_int32_t
-vxn_execute_4(const vxn_softc_t *sc, /* IN: adapter */
- u_int32_t cmd) /* IN: command */
-{
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR, cmd);
- return bus_space_read_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR);
-}
-
-static int
-vxn_check_link(vxn_softc_t *sc)
-{
- uint32 status;
- int ok;
-
- status = bus_space_read_4(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_STATUS_ADDR);
- ok = (status & VMXNET_STATUS_CONNECTED) != 0;
- return ok;
-}
-
-/*
- *-----------------------------------------------------------------------------
- *
- * vxn_media_status --
- *
- * This routine is called when the user quries the status of interface
- * using ifconfig. Checks link state and updates media state accorgingly.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static void
-vxn_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
-{
- vxn_softc_t *sc = ifp->if_softc;
- int connected = 0;
-
- VXN_LOCK((vxn_softc_t *)ifp->if_softc);
- connected = vxn_check_link(sc);
-
- ifmr->ifm_status = IFM_AVALID;
- ifmr->ifm_active = IFM_ETHER;
-
- if (!connected) {
- ifmr->ifm_status &= ~IFM_ACTIVE;
- VXN_UNLOCK((vxn_softc_t *)ifp->if_softc);
- return;
- }
-
- ifmr->ifm_status |= IFM_ACTIVE;
-
- VXN_UNLOCK((vxn_softc_t *)ifp->if_softc);
- return;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * vxn_media_change --
- *
- * This routine is called when the user changes speed/duplex using
- * media/mediopt option with ifconfig.
- *
- * Results:
- * Returns 0 for success, error code otherwise.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static int
-vxn_media_change(struct ifnet * ifp)
-{
- vxn_softc_t *sc = ifp->if_softc;
- struct ifmedia *ifm = &sc->media;
-
- if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
- return (EINVAL);
-
- if (IFM_SUBTYPE(ifm->ifm_media) != IFM_AUTO)
- printf("Media subtype is not AUTO, it is : %d.\n",
- IFM_SUBTYPE(ifm->ifm_media));
-
- return (0);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_attach --
- * Initialize data structures and attach driver to stack
- *
- * Results:
- * Returns 0 for success, negative errno value otherwise.
- *
- * Side effects:
- * Check device version number. Map interrupts.
- *-----------------------------------------------------------------------------
- */
-static int
-vxn_attach(device_t dev)
-{
- struct ifnet *ifp = NULL;
- int error = 0;
- int s, i;
- vxn_softc_t *sc;
- int unit;
- int rid;
- u_int32_t r;
- u_int32_t vLow, vHigh;
- int driverDataSize;
- u_char mac[6];
-
- s = splimp();
-
- unit = device_get_unit(dev);
-
- sc = device_get_softc(dev);
- VXN_MTX_INIT(&sc->vxn_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF);
- sc->vxn_io = NULL;
- sc->vxn_irq = NULL;
- sc->vxn_intrhand = NULL;
- sc->vxn_dd = NULL;
- sc->vxn_tx_pending = 0;
- sc->vxn_rings_allocated = 0;
- sc->vxn_max_tx_frags = 1;
-
- pci_enable_busmaster(dev);
-
- /*
- * enable the I/O ports on the device
- */
- pci_enable_io(dev, SYS_RES_IOPORT);
- r = pci_read_config(dev, PCIR_COMMAND, 4);
- if (!(r & PCIM_CMD_PORTEN)) {
- printf("vxn%d: failed to enable I/O ports\n", unit);
- error = ENXIO;
- goto fail;
- }
- rid = VXN_PCIR_MAPS;
- sc->vxn_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
- 1, RF_ACTIVE);
- if (sc->vxn_io == NULL) {
- printf ("vxn%d: couldn't map I/O ports\n", unit);
- error = ENXIO;
- goto fail;
- }
- sc->vxn_iobtag = rman_get_bustag(sc->vxn_io);
- sc->vxn_iobhandle = rman_get_bushandle(sc->vxn_io);
-
- /*
- * check the version number of the device implementation
- */
- vLow = bus_space_read_4(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_LOW_VERSION);
- vHigh = bus_space_read_4(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_HIGH_VERSION);
- if ((vLow & 0xffff0000) != (VMXNET2_MAGIC & 0xffff0000)) {
- printf("vxn%d: driver version 0x%08X doesn't match %s version 0x%08X\n",
- unit, VMXNET2_MAGIC, "VMware", rid);
- error = ENXIO;
- goto fail;
- } else {
- if ((VMXNET2_MAGIC < vLow) ||
- (VMXNET2_MAGIC > vHigh)) {
- printf("vxn%d: driver version 0x%08X doesn't match %s version 0x%08X,0x%08X\n",
- unit, VMXNET2_MAGIC, "VMware", vLow, vHigh);
- error = ENXIO;
- goto fail;
- }
- }
-
- /*
- * map interrupt for the the device
- */
- rid = 0;
- sc->vxn_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0,
- 1, RF_SHAREABLE | RF_ACTIVE);
- if (sc->vxn_irq == NULL) {
- printf("vxn%d: couldn't map interrupt\n", unit);
- error = ENXIO;
- goto fail;
- }
-#if defined(VXN_NEWNEWBUS)
- error = bus_setup_intr(dev, sc->vxn_irq, INTR_TYPE_NET | INTR_MPSAFE,
- NULL, vxn_intr, sc, &sc->vxn_intrhand);
-#elif defined(VXN_MPSAFE)
- error = bus_setup_intr(dev, sc->vxn_irq, INTR_TYPE_NET | INTR_MPSAFE,
- vxn_intr, sc, &sc->vxn_intrhand);
-#else
- error = bus_setup_intr(dev, sc->vxn_irq, INTR_TYPE_NET,
- vxn_intr, sc, &sc->vxn_intrhand);
-#endif
- if (error) {
- printf("vxn%d: couldn't set up irq\n", unit);
- error = ENXIO;
- goto fail;
- }
-
- /*
- * allocate and initialize our private and shared data structures
- */
- r = vxn_execute_4(sc, VMXNET_CMD_GET_NUM_RX_BUFFERS);
- if (r == 0 || r > VMXNET2_MAX_NUM_RX_BUFFERS) {
- r = VMXNET2_DEFAULT_NUM_RX_BUFFERS;
- }
- sc->vxn_num_rx_bufs = r;
-
- r = vxn_execute_4(sc, VMXNET_CMD_GET_NUM_TX_BUFFERS);
- if (r == 0 || r > VMXNET2_MAX_NUM_TX_BUFFERS) {
- r = VMXNET2_DEFAULT_NUM_TX_BUFFERS;
- }
- sc->vxn_num_tx_bufs = r;
-
- driverDataSize =
- sizeof(Vmxnet2_DriverData) +
- /* numRxBuffers + 1 for the dummy rxRing2 (used only by Windows) */
- (sc->vxn_num_rx_bufs + 1) * sizeof(Vmxnet2_RxRingEntry) +
- sc->vxn_num_tx_bufs * sizeof(Vmxnet2_TxRingEntry);
-
- sc->vxn_dd = contigmalloc(driverDataSize, M_DEVBUF, M_NOWAIT,
- 0, 0xffffffff, PAGE_SIZE, 0);
- if (sc->vxn_dd == NULL) {
- printf("vxn%d: can't contigmalloc %d bytes for vxn_dd\n",
- unit, driverDataSize);
- error = ENOMEM;
- goto fail;
- }
-
- memset(sc->vxn_dd, 0, driverDataSize);
-
- /* So that the vmkernel can check it is compatible */
- sc->vxn_dd->magic = VMXNET2_MAGIC;
- sc->vxn_dd->length = driverDataSize;
-
- /* This downcast is OK because we've asked for vxn_dd to fit in 32 bits */
- sc->vxn_dd_phys = (uint32)vtophys(sc->vxn_dd);
-
- /*
- * set up entry points, data and defaults for the kernel
- */
- ifp = VXN_IF_ALLOC(sc);
- if (ifp == NULL) {
- printf("vxn%d: if_alloc() failed\n", unit);
- error = ENOMEM;
- goto fail;
- }
- ifp->if_softc = sc;
- VXN_IF_INITNAME(ifp, device_get_name(dev), unit);
- ifp->if_mtu = ETHERMTU;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = vxn_ioctl;
- ifp->if_output = ether_output;
- ifp->if_start = vxn_start;
-#if __FreeBSD_version < 900000
- ifp->if_watchdog = vxn_watchdog;
-#endif
- ifp->if_init = vxn_init;
- ifp->if_baudrate = 1000000000;
- ifp->if_snd.ifq_maxlen = sc->vxn_num_tx_bufs;
- ifp->if_capenable = ifp->if_capabilities;
-
- /*
- * read the MAC address from the device
- */
- for (i = 0; i < 6; i++) {
- mac[i] = bus_space_read_1(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_MAC_ADDR
- + i);
- }
-
-#ifdef VXN_NEEDARPCOM
- /*
- * FreeBSD 4.x requires that we manually record the device's MAC address to
- * the attached arpcom structure prior to calling ether_ifattach().
- */
- bcopy(mac, sc->arpcom.ac_enaddr, 6);
-#endif
-
- /*
- * success
- */
- VXN_ETHER_IFATTACH(ifp, mac);
- printf("vxn%d: attached [num_rx_bufs=(%d*%d) num_tx_bufs=(%d*%d) driverDataSize=%d]\n",
- unit,
- sc->vxn_num_rx_bufs, (int)sizeof(Vmxnet2_RxRingEntry),
- sc->vxn_num_tx_bufs, (int)sizeof(Vmxnet2_TxRingEntry),
- driverDataSize);
-
- /*
- * Specify the media types supported by this adapter and register
- * callbacks to update media and link information
- */
- ifmedia_init(&sc->media, IFM_IMASK, vxn_media_change,
- vxn_media_status);
- ifmedia_add(&sc->media, IFM_ETHER | IFM_FDX, 0, NULL);
- ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
- ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_T, 0, NULL);
- ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
-
-
- goto done;
-
-fail:
-
- if (sc->vxn_intrhand != NULL) {
- bus_teardown_intr(dev, sc->vxn_irq, sc->vxn_intrhand);
- }
- if (sc->vxn_irq != NULL) {
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vxn_irq);
- }
- if (sc->vxn_io != NULL) {
- bus_release_resource(dev, SYS_RES_IOPORT, VXN_PCIR_MAPS, sc->vxn_io);
- }
- if (sc->vxn_dd != NULL) {
- contigfree(sc->vxn_dd, sc->vxn_dd->length, M_DEVBUF);
- }
- if (ifp != NULL) {
- VXN_IF_FREE(sc);
- }
-
- pci_disable_io(dev, SYS_RES_IOPORT);
- pci_disable_busmaster(dev);
- VXN_MTX_DESTROY(&sc->vxn_mtx);
-
- done:
-
- splx(s);
- return error;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_detach --
- * Free data structures and detach driver from stack
- *
- * Results:
- * Returns 0 for success (always)
- *
- * Side effects:
- * None
- *-----------------------------------------------------------------------------
- */
-static int
-vxn_detach(device_t dev)
-{
- int s;
- vxn_softc_t *sc;
- struct ifnet *ifp;
-
- s = splimp();
-
- sc = device_get_softc(dev);
-
- ifp = VXN_SC2IFP(sc);
- if (device_is_attached(dev)) {
- vxn_stop(sc);
- /*
- * detach from stack
- */
- VXN_ETHER_IFDETACH(ifp);
- }
-
- /*
- * Cleanup - release resources and memory
- */
- VXN_IF_FREE(sc);
- contigfree(sc->vxn_dd, sc->vxn_dd->length, M_DEVBUF);
- bus_teardown_intr(dev, sc->vxn_irq, sc->vxn_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vxn_irq);
- bus_release_resource(dev, SYS_RES_IOPORT, VXN_PCIR_MAPS, sc->vxn_io);
- pci_disable_io(dev, SYS_RES_IOPORT);
- pci_disable_busmaster(dev);
- VXN_MTX_DESTROY(&sc->vxn_mtx);
-
- splx(s);
- return 0;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_stop --
- * Called when the interface is brought down
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_stop(vxn_softc_t *sc)
-{
- VXN_LOCK(sc);
- vxn_stopl(sc);
- VXN_UNLOCK(sc);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_stopl --
- * Called when the interface is brought down & is locked
- *
- * Results:
- * None
- *
- * Side effects:
- * Don't do anything if not running. Flush pending transmits. Release
- * private data structures.
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_stopl(vxn_softc_t *sc)
-{
- int i;
- struct ifnet *ifp = VXN_SC2IFP(sc);
-
- VXN_LOCK_ASSERT(sc);
-
- if (!(VXN_GET_IF_DRV_FLAGS(ifp) & VXN_IFF_RUNNING)) {
- return;
- }
-
- /*
- * Disable device interrupts
- */
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR, VMXNET_CMD_INTR_DISABLE);
-
- /*
- * Try to flush pending transmits
- */
- if (sc->vxn_tx_pending) {
- printf("vxn%d: waiting for %d pending transmits\n",
- VXN_IF_UNIT(ifp), sc->vxn_tx_pending);
- for (i = 0; i < MAX_TX_WAIT_ON_STOP && sc->vxn_tx_pending; i++) {
- DELAY(1000);
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR, VMXNET_CMD_CHECK_TX_DONE);
- vxn_tx_complete(sc);
- }
- if (sc->vxn_tx_pending) {
- printf("vxn%d: giving up on %d pending transmits\n",
- VXN_IF_UNIT(ifp), sc->vxn_tx_pending);
- }
- }
-
- /*
- * Stop hardware
- */
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_INIT_ADDR, 0);
-
- VXN_CLR_IF_DRV_FLAGS(ifp, VXN_IFF_RUNNING);
-
- /*
- * Free ring
- */
- vxn_release_rings(sc);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_load_multicast --
- * Called to change set of addresses to listen to.
- *
- * Results:
- * None
- *
- * Side effects:
- * Sets device multicast table
- *-----------------------------------------------------------------------------
- */
-static int
-vxn_load_multicast(vxn_softc_t *sc)
-{
- struct ifmultiaddr *ifma;
- struct ifnet *ifp = VXN_SC2IFP(sc);
- Vmxnet2_DriverData *dd = sc->vxn_dd;
- volatile uint16 *mcast_table = (uint16 *)dd->LADRF;
- int i, bit, byte;
- uint32 crc, poly = CRC_POLYNOMIAL_LE;
- int any = 0;
-
- if (ifp->if_flags & IFF_ALLMULTI) {
- dd->LADRF[0] = 0xffffffff;
- dd->LADRF[1] = 0xffffffff;
-
- any++;
- goto done;
- }
-
- dd->LADRF[0] = 0;
- dd->LADRF[1] = 0;
-
- VXN_IF_ADDR_LOCK(ifp);
- for (ifma = VXN_IFMULTI_FIRST(&ifp->if_multiaddrs);
- ifma != NULL;
- ifma = VXN_IFMULTI_NEXT(ifma, ifma_link)) {
- char *addrs = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
-
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
-
- any++;
- crc = 0xffffffff;
- for (byte = 0; byte < 6; byte++) {
- for (bit = *addrs++, i = 0; i < 8; i++, bit >>= 1) {
- int test;
-
- test = ((bit ^ crc) & 0x01);
- crc >>= 1;
-
- if (test) {
- crc = crc ^ poly;
- }
- }
- }
-
- crc = crc >> 26;
- mcast_table[crc >> 4] |= 1 << (crc & 0xf);
- }
- VXN_IF_ADDR_UNLOCK(ifp);
-
- done:
- if (VXN_GET_IF_DRV_FLAGS(ifp) & VXN_IFF_RUNNING) {
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR, VMXNET_CMD_UPDATE_LADRF);
- }
- return any;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_init --
- * Called when the interface is brought up.
- *
- * Results:
- * None
- *
- * Side effects:
- *
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_init(void *v)
-{
- vxn_softc_t *sc = (vxn_softc_t *)v;
- VXN_LOCK(sc);
- vxn_initl(sc);
- VXN_UNLOCK(sc);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_initl --
- * Called by vxn_init() after lock acquired.
- *
- * Results:
- * None
- *
- * Side effects:
- * Initialize rings, Register driver data structures with device,
- * Enable interrupts on device.
- *
- *-----------------------------------------------------------------------------
- */
-
-static void
-vxn_initl(vxn_softc_t *sc)
-{
- Vmxnet2_DriverData *dd = sc->vxn_dd;
- struct ifnet *ifp = VXN_SC2IFP(sc);
- uint32 r, i;
- u_char mac_addr[6];
-
- VXN_LOCK_ASSERT(sc);
-
- if (!(VXN_GET_IF_DRV_FLAGS(ifp) & VXN_IFF_RUNNING)) {
- u_int32_t capabilities;
- u_int32_t features;
-
- if (vxn_init_rings(sc) != 0) {
- printf("vxn%d: ring intitialization failed\n", VXN_IF_UNIT(ifp));
- return;
- }
-
- /* Get MAC address from interface and set it in hardware */
-#if __FreeBSD_version >= 700000
- printf("addrlen : %d. \n", ifp->if_addrlen);
- bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr), mac_addr,
- ifp->if_addrlen > 6 ? 6 : ifp->if_addrlen);
-#else
- if (!ifaddr_byindex(ifp->if_index)) {
- printf("vxn:%d Invalid link address, interface index :%d.\n",
- VXN_IF_UNIT(ifp), ifp->if_index);
- } else {
- bcopy(LLADDR((struct sockaddr_dl *)ifaddr_byindex(ifp->if_index)->ifa_addr),
- mac_addr, ifp->if_addrlen);
- }
-#endif
- printf("vxn%d: MAC Address : %02x:%02x:%02x:%02x:%02x:%02x \n",
- VXN_IF_UNIT(ifp), mac_addr[0], mac_addr[1], mac_addr[2],
- mac_addr[3], mac_addr[4], mac_addr[5]);
- for (i = 0; i < 6; i++) {
- bus_space_write_1(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_MAC_ADDR +
- i, mac_addr[i]);
- }
-
- /*
- * Start hardware
- */
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_INIT_ADDR, sc->vxn_dd_phys);
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_INIT_LENGTH, sc->vxn_dd->length);
-
- /* Make sure the initialization succeeded for the hardware. */
- r = bus_space_read_4(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_INIT_LENGTH);
- if (!r) {
- vxn_release_rings(sc);
- printf("vxn%d: device intitialization failed: %x\n", VXN_IF_UNIT(ifp), r);
- return;
- }
- capabilities = vxn_execute_4(sc, VMXNET_CMD_GET_CAPABILITIES);
- features = vxn_execute_4(sc, VMXNET_CMD_GET_FEATURES);
- if ((capabilities & VMNET_CAP_SG) &&
- (features & VMXNET_FEATURE_ZERO_COPY_TX)) {
- sc->vxn_max_tx_frags = VMXNET2_SG_DEFAULT_LENGTH;
- } else {
- sc->vxn_max_tx_frags = 1;
- }
-
- VXN_SET_IF_DRV_FLAGS(ifp, VXN_IFF_RUNNING);
- VXN_CLR_IF_DRV_FLAGS(ifp, VXN_IFF_OACTIVE);
- }
-
- dd->ifflags &= ~(VMXNET_IFF_PROMISC
- |VMXNET_IFF_BROADCAST
- |VMXNET_IFF_MULTICAST);
-
- if (ifp->if_flags & IFF_PROMISC) {
- printf("vxn%d: promiscuous mode enabled\n", VXN_IF_UNIT(ifp));
- dd->ifflags |= VMXNET_IFF_PROMISC;
- }
- if (ifp->if_flags & IFF_BROADCAST) {
- dd->ifflags |= VMXNET_IFF_BROADCAST;
- }
- /*
- * vnx_load_multicast does the right thing for IFF_ALLMULTI
- */
- if (vxn_load_multicast(sc)) {
- dd->ifflags |= VMXNET_IFF_MULTICAST;
- }
-
- /*
- * enable interrupts on the card
- */
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR, VMXNET_CMD_INTR_ENABLE);
-
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR, VMXNET_CMD_UPDATE_IFF);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_encap --
- * Stick packet address and length in given ring entry
- *
- * Results:
- * 0 on success, 1 on error
- *
- * Side effects:
- * Allocate a new mbuf cluster and copy data, if mbuf chain is too
- * fragmented for us to include in our scatter/gather array
- *
- *-----------------------------------------------------------------------------
- */
-static int
-vxn_encap(struct ifnet *ifp,
- Vmxnet2_TxRingEntry *xre,
- struct mbuf *m_head,
- struct mbuf **pbuffptr)
-{
- vxn_softc_t *sc = ifp->if_softc;
- int frag = 0;
- struct mbuf *m;
-
- xre->sg.length = 0;
- xre->flags = 0;
-
- /*
- * Go through mbuf chain and drop packet pointers into ring
- * scatter/gather array
- */
- for (m = m_head; m != NULL; m = m->m_next) {
- if (m->m_len) {
- if (frag == sc->vxn_max_tx_frags) {
- break;
- }
-
- xre->sg.sg[frag].addrLow = (uint32)vtophys(mtod(m, vm_offset_t));
- xre->sg.sg[frag].length = m->m_len;
- frag++;
- }
- }
-
- /*
- * Allocate a new mbuf cluster and copy data if we can't use the mbuf chain
- * as such
- */
- if (m != NULL) {
- struct mbuf *m_new = NULL;
-
- MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new == NULL) {
- printf("vxn%d: no memory for tx list\n", VXN_IF_UNIT(ifp));
- return 1;
- }
-
- if (m_head->m_pkthdr.len > MHLEN) {
- MCLGET(m_new, M_DONTWAIT);
- if (!(m_new->m_flags & M_EXT)) {
- m_freem(m_new);
- printf("vxn%d: no memory for tx list\n", VXN_IF_UNIT(ifp));
- return 1;
- }
- }
-
- m_copydata(m_head, 0, m_head->m_pkthdr.len,
- mtod(m_new, caddr_t));
- m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
- m_freem(m_head);
- m_head = m_new;
-
- xre->sg.sg[0].addrLow = (uint32)vtophys(mtod(m_head, vm_offset_t));
- xre->sg.sg[0].length = m_head->m_pkthdr.len;
- frag = 1;
- }
-
- xre->sg.length = frag;
-
- /*
- * Mark ring entry as "NIC owned"
- */
- if (frag > 0) {
- if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) {
- xre->flags |= VMXNET2_TX_HW_XSUM;
- }
- xre->sg.addrType = NET_SG_PHYS_ADDR;
- *pbuffptr = m_head;
- xre->ownership = VMXNET2_OWNERSHIP_NIC;
- xre->flags |= VMXNET2_TX_CAN_KEEP;
- }
-
- return 0;
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_start --
- * Called to transmit a packet. Acquires device mutex & hands off to
- * vxn_startl.
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *
- *-----------------------------------------------------------------------------
- */
-
-static void
-vxn_start(struct ifnet *ifp)
-{
- VXN_LOCK((vxn_softc_t *)ifp->if_softc);
- vxn_startl(ifp);
- VXN_UNLOCK((vxn_softc_t *)ifp->if_softc);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_startl --
- * Called to transmit a packet (lock acquired)
- *
- * Results:
- * None
- *
- * Side effects:
- * Bounces a copy to possible BPF listener. Sets RING_LOW flag
- * if ring is getting crowded. Starts device TX. Aggressively cleans
- * up tx ring after starting TX.
- *
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_startl(struct ifnet *ifp)
-{
- vxn_softc_t *sc = ifp->if_softc;
- Vmxnet2_DriverData *dd = sc->vxn_dd;
-
- VXN_LOCK_ASSERT(sc);
-
- if (VXN_GET_IF_DRV_FLAGS(ifp) & VXN_IFF_OACTIVE) {
- return;
- }
-
- /*
- * No room on ring
- */
- if (sc->vxn_tx_buffptr[dd->txDriverNext]) {
- dd->txStopped = TRUE;
- }
-
- /*
- * Dequeue packets from send queue and drop them into tx ring
- */
- while (sc->vxn_tx_buffptr[dd->txDriverNext] == NULL) {
- struct mbuf *m_head = NULL;
- Vmxnet2_TxRingEntry *xre;
-
- IF_DEQUEUE(&ifp->if_snd, m_head);
- if (m_head == NULL) {
- break;
- }
-
- xre = &sc->vxn_tx_ring[dd->txDriverNext];
- if (vxn_encap(ifp, xre, m_head, &(sc->vxn_tx_buffptr[dd->txDriverNext]))) {
- IF_PREPEND(&ifp->if_snd, m_head);
- break;
- }
-
- /*
- * Bounce copy to (possible) BPF listener
- */
- VXN_BPF_MTAP(ifp, sc->vxn_tx_buffptr[dd->txDriverNext]);
-
- if (sc->vxn_tx_pending > (dd->txRingLength - 5)) {
- xre->flags |= VMXNET2_TX_RING_LOW;
- }
-
- VMXNET_INC(dd->txDriverNext, dd->txRingLength);
- dd->txNumDeferred++;
- sc->vxn_tx_pending++;
- ifp->if_opackets++;
- }
-
- /*
- * Transmit, if number of pending packets > tx cluster length
- */
- if (dd->txNumDeferred >= dd->txClusterLength) {
- dd->txNumDeferred = 0;
-
- /*
- * reading this port causes the implementation to transmit everything
- * in the ring
- */
- bus_space_read_4(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_TX_ADDR);
- }
-
- /*
- * Clean up tx ring after calling into vmkernel, as TX completion intrs
- * are not guaranteed.
- */
- vxn_tx_complete(sc);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_ioctl --
- * IOCTL
- *
- * Results:
- * Returns 0 for success, negative errno value otherwise.
- *
- * Side effects:
- * None
- *-----------------------------------------------------------------------------
- */
-static int
-vxn_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
-{
- int error = 0;
- int s;
- vxn_softc_t *sc = ifp->if_softc;
-
- s = splimp();
-
- switch(command) {
- case SIOCSIFADDR:
- case SIOCGIFADDR:
- case SIOCSIFMTU:
- error = ether_ioctl(ifp, command, data);
- break;
-
- case SIOCSIFFLAGS:
- VXN_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- vxn_initl(sc);
- } else {
- vxn_stopl(sc);
- }
- VXN_UNLOCK(sc);
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- VXN_LOCK(sc);
- vxn_load_multicast(sc);
- VXN_UNLOCK(sc);
- error = 0;
- break;
-
- case SIOCSIFMEDIA:
- case SIOCGIFMEDIA:
- ifmedia_ioctl(ifp, (struct ifreq *)data, &sc->media, command);
-
- default:
- error = EINVAL;
- break;
- }
-
- splx(s);
-
- return error;
-}
-
-#if __FreeBSD_version < 900000
-/*
- *-----------------------------------------------------------------------------
- * vxn_watchdog --
- * Watchdog function
- *
- * Results:
- * None
- *
- * Side effects:
- * Not implemented.
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_watchdog(struct ifnet *ifp)
-{
- printf("vxn%d: watchdog\n", VXN_IF_UNIT(ifp));
-}
-#endif
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_intr --
- * Interrupt handler
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_intr (void *v)
-{
- vxn_softc_t *sc = (vxn_softc_t *)v;
- struct ifnet *ifp = VXN_SC2IFP(sc);
-
- VXN_LOCK(sc);
-
- /*
- * Without rings being allocated we have nothing to do. We should not
- * need even this INTR_ACK, as our hardware should be disabled when
- * rings are not allocated, but on other side INTR_ACK should be noop
- * then, and this makes sure that some bug will not force IRQ line
- * active forever.
- */
- bus_space_write_4(sc->vxn_iobtag, sc->vxn_iobhandle,
- VMXNET_COMMAND_ADDR, VMXNET_CMD_INTR_ACK);
-
- if (sc->vxn_rings_allocated) {
- vxn_rx(sc);
- vxn_tx_complete(sc);
- /*
- * After having freed some of the transmit ring, go ahead and refill
- * it, if possible, while we're here. (Idea stolen from if_sis.c.)
- */
- if (!VXN_IFQ_IS_EMPTY(&ifp->if_snd)) {
- vxn_startl(ifp);
- }
- }
-
- VXN_UNLOCK(sc);
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_rx --
- * RX handler
- *
- * Results:
- * None
- *
- * Side effects:
- * Scan RX ring and pass legit packets up to FreeBSD. Allocate a
- * new mbuf for each packet pulled out, stick it into the ring and
- * pass ownership back to NIC.
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_rx(vxn_softc_t *sc)
-{
- short pkt_len;
- struct ifnet *ifp = VXN_SC2IFP(sc);
- Vmxnet2_DriverData *dd = sc->vxn_dd;
-
- /*
- * receive packets from all the descriptors that the device implementation
- * has given back to us
- */
- while (1) {
- Vmxnet2_RxRingEntry *rre;
- VXN_LOCK_ASSERT(sc);
-
- rre = &sc->vxn_rx_ring[dd->rxDriverNext];
- if (rre->ownership != VMXNET2_OWNERSHIP_DRIVER) {
- break;
- }
-
- pkt_len = rre->actualLength;
-
- if (pkt_len < (60 - 4)) {
- /*
- * Ethernet header vlan tags are 4 bytes. Some vendors generate
- * 60byte frames including vlan tags. When vlan tag
- * is stripped, such frames become 60 - 4. (PR106153)
- */
- if (pkt_len != 0) {
- printf("vxn%d: runt packet\n", VXN_IF_UNIT(ifp));
- }
- } else {
- struct mbuf *m_new = NULL;
-
- /*
- * Allocate a new mbuf cluster to replace the current one
- */
- MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new != NULL) {
- MCLGET(m_new, M_DONTWAIT);
- if (m_new->m_flags & M_EXT) {
- m_adj(m_new, ETHER_ALIGN);
- } else {
- m_freem(m_new);
- m_new = NULL;
- }
- }
-
- /*
- * replace the current mbuf in the descriptor with the new one
- * and pass the packet up to the kernel
- */
- if (m_new != NULL) {
- struct mbuf *m = sc->vxn_rx_buffptr[dd->rxDriverNext];
-
- sc->vxn_rx_buffptr[dd->rxDriverNext] = m_new;
- rre->paddr = (uint32)vtophys(mtod(m_new, caddr_t));
-
- ifp->if_ipackets++;
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = m->m_len = pkt_len;
-
- if (rre->flags & VMXNET2_RX_HW_XSUM_OK) {
- m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m->m_pkthdr.csum_data = 0xffff;
- }
-
- /*
- * "Drop the driver lock around calls to if_input to avoid a LOR
- * when the packets are immediately returned for sending (e.g. when
- * bridging or packet forwarding). There are more efficient ways to
- * do this but for now use the least intrusive approach."
- * - Sam Leffler (sam@FreeBSD.org), if_sis.c rev 1.90
- *
- * This function is only called by the interrupt handler, and said
- * handler isn't reentrant. (Interrupts are masked.) I.e., the
- * receive rings are still protected while we give up the mutex.
- */
- VXN_UNLOCK(sc);
- VXN_ETHER_INPUT(ifp, m);
- VXN_LOCK(sc);
- }
- }
-
- /*
- * Give the descriptor back to the device implementation
- */
- rre->ownership = VMXNET2_OWNERSHIP_NIC;
- VMXNET_INC(dd->rxDriverNext, dd->rxRingLength);
- }
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_tx_complete --
- * Loop through the tx ring looking for completed transmits
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_tx_complete(vxn_softc_t *sc)
-{
- Vmxnet2_DriverData *dd = sc->vxn_dd;
-
- while (1) {
- Vmxnet2_TxRingEntry *xre = &sc->vxn_tx_ring[dd->txDriverCur];
-
- if (xre->ownership != VMXNET2_OWNERSHIP_DRIVER ||
- sc->vxn_tx_buffptr[dd->txDriverCur] == NULL) {
- break;
- }
-
- m_freem(sc->vxn_tx_buffptr[dd->txDriverCur]);
- sc->vxn_tx_buffptr[dd->txDriverCur] = NULL;
- sc->vxn_tx_pending--;
- VMXNET_INC(dd->txDriverCur, dd->txRingLength);
- dd->txStopped = FALSE;
- }
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_init_rings --
- * Loop through the tx ring looking for completed transmits
- *
- * Results:
- * Returns 0 for success, negative errno value otherwise.
- *
- * Side effects:
- * None
- *-----------------------------------------------------------------------------
- */
-static int
-vxn_init_rings(vxn_softc_t *sc)
-{
- Vmxnet2_DriverData *dd = sc->vxn_dd;
- /*struct ifnet *ifp = &sc->arpcom.ac_if;*/
- int i;
- int32 offset;
-
- offset = sizeof(*dd);
-
- dd->rxRingLength = sc->vxn_num_rx_bufs;
- dd->rxRingOffset = offset;
- sc->vxn_rx_ring = (Vmxnet2_RxRingEntry *)((uintptr_t)dd + offset);
- offset += sc->vxn_num_rx_bufs * sizeof(Vmxnet2_RxRingEntry);
-
- /* dummy rxRing2, only used by windows */
- dd->rxRingLength2 = 1;
- dd->rxRingOffset2 = offset;
- offset += sizeof(Vmxnet2_RxRingEntry);
-
- dd->txRingLength = sc->vxn_num_tx_bufs;
- dd->txRingOffset = offset;
- sc->vxn_tx_ring = (Vmxnet2_TxRingEntry *)((uintptr_t)dd + offset);
- offset += sc->vxn_num_tx_bufs * sizeof(Vmxnet2_TxRingEntry);
-
- /*
- * Allocate receive buffers
- */
- for (i = 0; i < sc->vxn_num_rx_bufs; i++) {
- struct mbuf *m_new = NULL;
-
- /*
- * Allocate an mbuf and initialize it to contain a packet header and
- * internal data.
- */
- MGETHDR(m_new, M_DONTWAIT, MT_DATA);
- if (m_new != NULL) {
- /* Allocate and attach an mbuf cluster to mbuf. */
- MCLGET(m_new, M_DONTWAIT);
- if (m_new->m_flags & M_EXT) {
- m_adj(m_new, ETHER_ALIGN);
- sc->vxn_rx_ring[i].paddr = (uint32)vtophys(mtod(m_new, caddr_t));
- sc->vxn_rx_ring[i].bufferLength = MCLBYTES;
- sc->vxn_rx_ring[i].actualLength = 0;
- sc->vxn_rx_buffptr[i] = m_new;
- sc->vxn_rx_ring[i].ownership = VMXNET2_OWNERSHIP_NIC;
- } else {
- /*
- * Allocation and attachment of mbuf clusters failed.
- */
- m_freem(m_new);
- m_new = NULL;
- goto err_release_ring;
- }
- } else {
- /* Allocation of mbuf failed. */
- goto err_release_ring;
- }
- }
-
- /* dummy rxRing2 tacked on to the end, with a single unusable entry */
- sc->vxn_rx_ring[i].paddr = 0;
- sc->vxn_rx_ring[i].bufferLength = 0;
- sc->vxn_rx_ring[i].actualLength = 0;
- sc->vxn_rx_buffptr[i] = 0;
- sc->vxn_rx_ring[i].ownership = VMXNET2_OWNERSHIP_DRIVER;
-
- dd->rxDriverNext = 0;
-
- /*
- * Give tx ring ownership to DRIVER
- */
- for (i = 0; i < sc->vxn_num_tx_bufs; i++) {
- sc->vxn_tx_ring[i].ownership = VMXNET2_OWNERSHIP_DRIVER;
- sc->vxn_tx_buffptr[i] = NULL;
- sc->vxn_tx_ring[i].sg.sg[0].addrHi = 0;
- }
-
- dd->txDriverCur = dd->txDriverNext = 0;
- dd->txStopped = FALSE;
-
- sc->vxn_rings_allocated = 1;
- return 0;
-err_release_ring:
- /*
- * Clearup already allocated mbufs and attached clusters.
- */
- for (--i; i >= 0; i--) {
- m_freem(sc->vxn_rx_buffptr[i]);
- sc->vxn_rx_buffptr[i] = NULL;
- sc->vxn_rx_ring[i].paddr = 0;
- sc->vxn_rx_ring[i].bufferLength = 0;
- sc->vxn_rx_ring[i].ownership = 0;
- }
- return ENOMEM;
-
-}
-
-/*
- *-----------------------------------------------------------------------------
- * vxn_release_rings --
- * Free tx and rx ring driverdata
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *-----------------------------------------------------------------------------
- */
-static void
-vxn_release_rings(vxn_softc_t *sc)
-{
- int i;
-
- sc->vxn_rings_allocated = 0;
-
- /*
- * Free rx ring packets
- */
- for (i = 0; i < sc->vxn_num_rx_bufs; i++) {
- if (sc->vxn_rx_buffptr[i] != NULL) {
- m_freem(sc->vxn_rx_buffptr[i]);
- sc->vxn_rx_buffptr[i] = NULL;
- }
- }
-
- /*
- * Free tx ring packets
- */
- for (i = 0; i < sc->vxn_num_tx_bufs; i++) {
- if (sc->vxn_tx_buffptr[i] != NULL) {
- m_freem(sc->vxn_tx_buffptr[i]);
- sc->vxn_tx_buffptr[i] = NULL;
- }
- }
-}
-