/******************************************************************************* Copyright(c) 1999 - 2002 Intel Corporation. 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; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: Linux NICS Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000.h" /* This is the only thing that needs to be changed to adjust the * maximum number of ports that the driver can manage. */ #define E1000_MAX_NIC 32 #define OPTION_UNSET -1 #define OPTION_DISABLED 0 #define OPTION_ENABLED 1 /* Module Parameters are always initialized to -1, so that the driver * can tell the difference between no user specified value or the * user asking for the default value. * The true default values are loaded in when e1000_check_options is called. * * This is a GCC extension to ANSI C. * See the item "Labeled Elements in Initializers" in the section * "Extensions to the C Language Family" of the GCC documentation. */ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } /* All parameters are treated the same, as an integer array of values. * This macro just reduces the need to repeat the same declaration code * over and over (plus this helps to avoid typo bugs). */ #define E1000_PARAM(X, S) \ static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \ MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \ MODULE_PARM_DESC(X, S); /* Transmit Descriptor Count * * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers * Valid Range: 80-4096 for 82544 * * Default Value: 256 */ E1000_PARAM(TxDescriptors, "Number of transmit descriptors"); /* Receive Descriptor Count * * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers * Valid Range: 80-4096 for 82544 * * Default Value: 80 */ E1000_PARAM(RxDescriptors, "Number of receive descriptors"); /* User Specified Speed Override * * Valid Range: 0, 10, 100, 1000 * - 0 - auto-negotiate at all supported speeds * - 10 - only link at 10 Mbps * - 100 - only link at 100 Mbps * - 1000 - only link at 1000 Mbps * * Default Value: 0 */ E1000_PARAM(Speed, "Speed setting"); /* User Specified Duplex Override * * Valid Range: 0-2 * - 0 - auto-negotiate for duplex * - 1 - only link at half duplex * - 2 - only link at full duplex * * Default Value: 0 */ E1000_PARAM(Duplex, "Duplex setting"); /* Auto-negotiation Advertisement Override * * Valid Range: 0x01-0x0F, 0x20-0x2F * * The AutoNeg value is a bit mask describing which speed and duplex * combinations should be advertised during auto-negotiation. * The supported speed and duplex modes are listed below * * Bit 7 6 5 4 3 2 1 0 * Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10 * Duplex Full Full Half Full Half * * Default Value: 0x2F */ E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting"); /* User Specified Flow Control Override * * Valid Range: 0-3 * - 0 - No Flow Control * - 1 - Rx only, respond to PAUSE frames but do not generate them * - 2 - Tx only, generate PAUSE frames but ignore them on receive * - 3 - Full Flow Control Support * * Default Value: Read flow control settings from the EEPROM */ E1000_PARAM(FlowControl, "Flow Control setting"); /* XsumRX - Receive Checksum Offload Enable/Disable * * Valid Range: 0, 1 * - 0 - disables all checksum offload * - 1 - enables receive IP/TCP/UDP checksum offload * on 82543 based NICs * * Default Value: 1 */ E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); /* Transmit Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 * * Default Value: 64 */ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); /* Transmit Absolute Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 * * Default Value: 0 */ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); /* Receive Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 * * Default Value: 0/128 */ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); /* Receive Absolute Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 * * Default Value: 128 */ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); #define AUTONEG_ADV_DEFAULT 0x2F #define AUTONEG_ADV_MASK 0x2F #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL #define DEFAULT_TXD 256 #define MAX_TXD 256 #define MIN_TXD 80 #define MAX_82544_TXD 4096 #define DEFAULT_RXD 80 #define MAX_RXD 256 #define MIN_RXD 80 #define MAX_82544_RXD 4096 #define DEFAULT_RDTR 0 #define MAX_RXDELAY 0xFFFF #define MIN_RXDELAY 0 #define DEFAULT_RADV 128 #define MAX_RXABSDELAY 0xFFFF #define MIN_RXABSDELAY 0 #define DEFAULT_TIDV 64 #define MAX_TXDELAY 0xFFFF #define MIN_TXDELAY 0 #define DEFAULT_TADV 64 #define MAX_TXABSDELAY 0xFFFF #define MIN_TXABSDELAY 0 struct e1000_option { enum { enable_option, range_option, list_option } type; char *name; char *err; int def; union { struct { /* range_option info */ int min; int max; } r; struct { /* list_option info */ int nr; struct e1000_opt_list { int i; char *str; } *p; } l; } arg; }; static int __devinit e1000_validate_option(int *value, struct e1000_option *opt) { if(*value == OPTION_UNSET) { *value = opt->def; return 0; } switch (opt->type) { case enable_option: switch (*value) { case OPTION_ENABLED: printk(KERN_INFO "%s Enabled\n", opt->name); return 0; case OPTION_DISABLED: printk(KERN_INFO "%s Disabled\n", opt->name); return 0; } break; case range_option: if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) { printk(KERN_INFO "%s set to %i\n", opt->name, *value); return 0; } break; case list_option: { int i; struct e1000_opt_list *ent; for(i = 0; i < opt->arg.l.nr; i++) { ent = &opt->arg.l.p[i]; if(*value == ent->i) { if(ent->str[0] != '\0') printk(KERN_INFO "%s\n", ent->str); return 0; } } } break; default: BUG(); } printk(KERN_INFO "Invalid %s specified (%i) %s\n", opt->name, *value, opt->err); *value = opt->def; return -1; } static void e1000_check_fiber_options(struct e1000_adapter *adapter); static void e1000_check_copper_options(struct e1000_adapter *adapter); /** * e1000_check_options - Range Checking for Command Line Parameters * @adapter: board private structure * * This routine checks all command line paramters for valid user * input. If an invalid value is given, or if no user specified * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. **/ void __devinit e1000_check_options(struct e1000_adapter *adapter) { int bd = adapter->bd_number; if(bd >= E1000_MAX_NIC) { printk(KERN_NOTICE "Warning: no configuration for board #%i\n", bd); printk(KERN_NOTICE "Using defaults for all values\n"); bd = E1000_MAX_NIC; } { /* Transmit Descriptor Count */ struct e1000_option opt = { .type = range_option, .name = "Transmit Descriptors", .err = "using default of " __MODULE_STRING(DEFAULT_TXD), .def = DEFAULT_TXD, .arg = { .r = { .min = MIN_TXD }} }; struct e1000_desc_ring *tx_ring = &adapter->tx_ring; e1000_mac_type mac_type = adapter->hw.mac_type; opt.arg.r.max = mac_type < e1000_82544 ? MAX_TXD : MAX_82544_TXD; tx_ring->count = TxDescriptors[bd]; e1000_validate_option(&tx_ring->count, &opt); E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE); } { /* Receive Descriptor Count */ struct e1000_option opt = { .type = range_option, .name = "Receive Descriptors", .err = "using default of " __MODULE_STRING(DEFAULT_RXD), .def = DEFAULT_RXD, .arg = { .r = { .min = MIN_RXD }} }; struct e1000_desc_ring *rx_ring = &adapter->rx_ring; e1000_mac_type mac_type = adapter->hw.mac_type; opt.arg.r.max = mac_type < e1000_82544 ? MAX_RXD : MAX_82544_RXD; rx_ring->count = RxDescriptors[bd]; e1000_validate_option(&rx_ring->count, &opt); E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); } { /* Checksum Offload Enable/Disable */ struct e1000_option opt = { .type = enable_option, .name = "Checksum Offload", .err = "defaulting to Enabled", .def = OPTION_ENABLED }; int rx_csum = XsumRX[bd]; e1000_validate_option(&rx_csum, &opt); adapter->rx_csum = rx_csum; } { /* Flow Control */ struct e1000_opt_list fc_list[] = {{ e1000_fc_none, "Flow Control Disabled" }, { e1000_fc_rx_pause,"Flow Control Receive Only" }, { e1000_fc_tx_pause,"Flow Control Transmit Only" }, { e1000_fc_full, "Flow Control Enabled" }, { e1000_fc_default, "Flow Control Hardware Default" }}; struct e1000_option opt = { .type = list_option, .name = "Flow Control", .err = "reading default settings from EEPROM", .def = e1000_fc_default, .arg = { .l = { .nr = ARRAY_SIZE(fc_list), .p = fc_list }} }; int fc = FlowControl[bd]; e1000_validate_option(&fc, &opt); adapter->hw.fc = adapter->hw.original_fc = fc; } { /* Transmit Interrupt Delay */ char *tidv = "using default of " __MODULE_STRING(DEFAULT_TIDV); struct e1000_option opt =
/*
    tests/test_copy_move_policies.cpp -- 'copy' and 'move' return value policies
                                         and related tests

    Copyright (c) 2016 Ben North <ben@redfrontdoor.org>

    All rights reserved. Use of this source code is governed by a
    BSD-style license that can be found in the LICENSE file.
*/

#include "pybind11_tests.h"
#include "constructor_stats.h"
#include <pybind11/stl.h>

template <typename derived>
struct empty {
    static const derived& get_one() { return instance_; }
    static derived instance_;
};

struct lacking_copy_ctor : public empty<lacking_copy_ctor> {
    lacking_copy_ctor() = default;
    lacking_copy_ctor(const lacking_copy_ctor& other) = delete;
};

template <> lacking_copy_ctor empty<lacking_copy_ctor>::instance_ = {};

struct lacking_move_ctor : public empty<lacking_move_ctor> {
    lacking_move_ctor() = default;
    lacking_move_ctor(const lacking_move_ctor& other) = delete;
    lacking_move_ctor(lacking_move_ctor&& other) = delete;
};

template <> lacking_move_ctor empty<lacking_move_ctor>::instance_ = {};

/* Custom type caster move/copy test classes */
class MoveOnlyInt {
public:
    MoveOnlyInt() { print_default_created(this); }
    MoveOnlyInt(int v) : value{std::move(v)} { print_created(this, value); }
    MoveOnlyInt(MoveOnlyInt &&m) { print_move_created(this, m.value); std::swap(value, m.value); }
    MoveOnlyInt &operator=(MoveOnlyInt &&m) { print_move_assigned(this, m.value); std::swap(value, m.value); return *this; }
    MoveOnlyInt(const MoveOnlyInt &) = delete;
    MoveOnlyInt &operator=(const MoveOnlyInt &) = delete;
    ~MoveOnlyInt() { print_destroyed(this); }

    int value;
};
class MoveOrCopyInt {
public:
    MoveOrCopyInt() { print_default_created(this); }
    MoveOrCopyInt(int v) : value{std::move(v)} { print_created(this, value); }
    MoveOrCopyInt(MoveOrCopyInt &&m) { print_move_created(this, m.value); std::swap(value, m.value); }
    MoveOrCopyInt &operator=(MoveOrCopyInt &&m) { print_move_assigned(this, m.value); std::swap(value, m.value); return *this; }
    MoveOrCopyInt(const MoveOrCopyInt &c) { print_copy_created(this, c.value); value = c.value; }
    MoveOrCopyInt &operator=(const MoveOrCopyInt &c) { print_copy_assigned(this, c.value); value = c.value; return *this; }
    ~MoveOrCopyInt() { print_destroyed(this); }

    int value;
};
class CopyOnlyInt {
public:
    CopyOnlyInt() { print_default_created(this); }
    CopyOnlyInt(int v) : value{std::move(v)} { print_created(this, value); }
    CopyOnlyInt(const CopyOnlyInt &c) { print_copy_created(this, c.value); value = c.value; }
    CopyOnlyInt &operator=(const CopyOnlyInt &c) { print_copy_assigned(this, c.value); value = c.value; return *this; }
    ~CopyOnlyInt() { print_destroyed(this); }

    int value;
};
PYBIND11_NAMESPACE_BEGIN(pybind11)
PYBIND11_NAMESPACE_BEGIN(detail)
template <> struct type_caster<MoveOnlyInt> {
    PYBIND11_TYPE_CASTER(MoveOnlyInt, _("MoveOnlyInt"));
    bool load(handle src, bool) { value = MoveOnlyInt(src.cast<int>()); return true; }
    static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
};

template <> struct type_caster<MoveOrCopyInt> {
    PYBIND11_TYPE_CASTER(MoveOrCopyInt, _("MoveOrCopyInt"));
    bool load(handle src, bool) { value = MoveOrCopyInt(src.cast<int>()); return true; }
    static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
};

template <> struct type_caster<CopyOnlyInt> {
protected:
    CopyOnlyInt value;
public:
    static constexpr auto name = _("CopyOnlyInt");
    bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; }
    static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
    static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) {
        if (!src) return none().release();
        return cast(*src, policy, parent);
    }
    operator CopyOnlyInt*() { return &value; }
    operator CopyOnlyInt&() { return value; }
    template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
};
PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(pybind11)

TEST_SUBMODULE(copy_move_policies, m) {
    // test_lacking_copy_ctor
    py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor")
        .def_static("get_one", &lacking_copy_ctor::get_one,
                    py::return_value_policy::copy);
    // test_lacking_move_ctor
    py::class_<lacking_move_ctor>(m, "lacking_move_ctor")
        .def_static("get_one", &lacking_move_ctor::get_one,
                    py::return_value_policy::move);

    // test_move_and_copy_casts
    m.def("move_and_copy_casts", [](py::object o) {
        int r = 0;
        r += py::cast<MoveOrCopyInt>(o).value; /* moves */
        r += py::cast<MoveOnlyInt>(o).value; /* moves */
        r += py::cast<CopyOnlyInt>(o).value; /* copies */
        auto m1(py::cast<MoveOrCopyInt>(o)); /* moves */
        auto m2(py::cast<MoveOnlyInt>(o)); /* moves */
        auto m3(py::cast<CopyOnlyInt>(o)); /* copies */
        r += m1.value + m2.value + m3.value;

        return r;
    });

    // test_move_and_copy_loads
    m.def("move_only", [](MoveOnlyInt m) { return m.value; });
    m.def("move_or_copy", [](MoveOrCopyInt m) { return m.value; });
    m.def("copy_only", [](CopyOnlyInt m) { return m.value; });
    m.def("move_pair", [](std::pair<MoveOnlyInt, MoveOrCopyInt> p) {
        return p.first.value + p.second.value;
    });
    m.def("move_tuple", [](std::tuple<MoveOnlyInt, MoveOrCopyInt, MoveOnlyInt> t) {
        return std::get<0>(t).value + std::get<1>(t).value + std::get<2>(t).value;
    });
    m.def("copy_tuple", [](std::tuple<CopyOnlyInt, CopyOnlyInt> t) {
        return std::get<0>(t).value + std::get<1>(t).value;
    });
    m.def("move_copy_nested", [](std::pair<MoveOnlyInt, std::pair<std::tuple<MoveOrCopyInt, CopyOnlyInt, std::tuple<MoveOnlyInt>>, MoveOrCopyInt>> x) {
        return x.first.value + std::get<0>(x.second.first).value + std::get<1>(x.second.first).value +
            std::get<0>(std::get<2>(x.second.first)).value + x.second.second.value;
    });
    m.def("move_and_copy_cstats", []() {
        ConstructorStats::gc();
        // Reset counts to 0 so that previous tests don't affect later ones:
        auto &mc = ConstructorStats::get<MoveOrCopyInt>();
        mc.move_assignments = mc.move_constructions = mc.copy_assignments = mc.copy_constructions = 0;
        auto &mo = ConstructorStats::get<MoveOnlyInt>();
        mo.move_assignments = mo.move_constructions = mo.copy_assignments = mo.copy_constructions = 0;
        auto &co = ConstructorStats::get<CopyOnlyInt>();
        co.move_assignments = co.move_constructions = co.copy_assignments = co.copy_constructions = 0;
        py::dict d;
        d["MoveOrCopyInt"] = py::cast(mc, py::return_value_policy::reference);
        d["MoveOnlyInt"] = py::cast(mo, py::return_value_policy::reference);
        d["CopyOnlyInt"] = py::cast(co, py::return_value_policy::reference);
        return d;
    });
#ifdef PYBIND11_HAS_OPTIONAL
    // test_move_and_copy_load_optional
    m.attr("has_optional") = true;
    m.def("move_optional", [](std::optional<MoveOnlyInt> o) {
        return o->value;
    });
    m.def("move_or_copy_optional", [](std::optional<MoveOrCopyInt> o) {
        return o->value;
    });
    m.def("copy_optional", [](std::optional<CopyOnlyInt> o) {
        return o->value;
    });
    m.def("move_optional_tuple", [](std::optional<std::tuple<MoveOrCopyInt, MoveOnlyInt, CopyOnlyInt>> x) {
        return std::get<0>(*x).value + std::get<1>(*x).value + std::get<2>(*x).value;
    });
#else
    m.attr("has_optional") = false;
#endif

    // #70 compilation issue if operator new is not public - simple body added
    // but not needed on most compilers; MSVC and nvcc don't like a local
    // struct not having a method defined when declared, since it can not be
    // added later.
    struct PrivateOpNew {
        int value = 1;
    private:
        void *operator new(size_t bytes) {
            void *ptr = std::malloc(bytes);
            if (ptr)
                return ptr;
            else
                throw std::bad_alloc{};
        }
    };
    py::class_<PrivateOpNew>(m, "PrivateOpNew").def_readonly("value", &PrivateOpNew::value);
    m.def("private_op_new_value", []() { return PrivateOpNew(); });
    m.def("private_op_new_reference", []() -> const PrivateOpNew & {
        static PrivateOpNew x{};
        return x;
    }, py::return_value_policy::reference);

    // test_move_fallback
    // #389: rvp::move should fall-through to copy on non-movable objects
    struct MoveIssue1 {
        int v;
        MoveIssue1(int v) : v{v} {}
        MoveIssue1(const MoveIssue1 &c) = default;
        MoveIssue1(MoveIssue1 &&) = delete;
    };
    py::class_<MoveIssue1>(m, "MoveIssue1").def(py::init<int>()).def_readwrite("value", &MoveIssue1::v);

    struct MoveIssue2 {
        int v;
        MoveIssue2(int v) : v{v} {}
        MoveIssue2(MoveIssue2 &&) = default;
    };
    py::class_<MoveIssue2>(m, "MoveIssue2").def(py::init<int>()).def_readwrite("value", &MoveIssue2::v);

    m.def("get_moveissue1", [](int i) { return new MoveIssue1(i); }, py::return_value_policy::move);
    m.def("get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
}