HelenOS sources
This source file includes following definitions.
- nic_send_frame
- nic_callback_create
- nic_get_state
- nic_set_state
- nic_get_address
- nic_set_address
- nic_get_stats
- nic_get_device_info
- nic_get_cable_state
- nic_get_operation_mode
- nic_set_operation_mode
- nic_autoneg_enable
- nic_autoneg_disable
- nic_autoneg_probe
- nic_autoneg_restart
- nic_get_pause
- nic_set_pause
- nic_unicast_get_mode
- nic_unicast_set_mode
- nic_multicast_get_mode
- nic_multicast_set_mode
- nic_broadcast_get_mode
- nic_broadcast_set_mode
- nic_defective_get_mode
- nic_defective_set_mode
- nic_blocked_sources_get
- nic_blocked_sources_set
- nic_vlan_get_mask
- nic_vlan_set_mask
- nic_vlan_set_tag
- nic_wol_virtue_add
- nic_wol_virtue_remove
- nic_wol_virtue_probe
- nic_wol_virtue_list
- nic_wol_virtue_get_caps
- nic_wol_load_info
- nic_offload_probe
- nic_offload_set
- nic_poll_get_mode
- nic_poll_set_mode
- nic_poll_now
- remote_nic_send_frame
- remote_nic_callback_create
- remote_nic_get_state
- remote_nic_set_state
- remote_nic_get_address
- remote_nic_set_address
- remote_nic_get_stats
- remote_nic_get_device_info
- remote_nic_get_cable_state
- remote_nic_get_operation_mode
- remote_nic_set_operation_mode
- remote_nic_autoneg_enable
- remote_nic_autoneg_disable
- remote_nic_autoneg_probe
- remote_nic_autoneg_restart
- remote_nic_get_pause
- remote_nic_set_pause
- remote_nic_unicast_get_mode
- remote_nic_unicast_set_mode
- remote_nic_multicast_get_mode
- remote_nic_multicast_set_mode
- remote_nic_broadcast_get_mode
- remote_nic_broadcast_set_mode
- remote_nic_defective_get_mode
- remote_nic_defective_set_mode
- remote_nic_blocked_sources_get
- remote_nic_blocked_sources_set
- remote_nic_vlan_get_mask
- remote_nic_vlan_set_mask
- remote_nic_vlan_set_tag
- remote_nic_wol_virtue_add
- remote_nic_wol_virtue_remove
- remote_nic_wol_virtue_probe
- remote_nic_wol_virtue_list
- remote_nic_wol_virtue_get_caps
- remote_nic_wol_load_info
- remote_nic_offload_probe
- remote_nic_offload_set
- remote_nic_poll_get_mode
- remote_nic_poll_set_mode
- remote_nic_poll_now
#include <assert.h>
#include <async.h>
#include <errno.h>
#include <ipc/services.h>
#include <time.h>
#include <macros.h>
#include "ops/nic.h"
#include "nic_iface.h"
typedef enum {
NIC_SEND_MESSAGE = 0,
NIC_CALLBACK_CREATE,
NIC_GET_STATE,
NIC_SET_STATE,
NIC_GET_ADDRESS,
NIC_SET_ADDRESS,
NIC_GET_STATS,
NIC_GET_DEVICE_INFO,
NIC_GET_CABLE_STATE,
NIC_GET_OPERATION_MODE,
NIC_SET_OPERATION_MODE,
NIC_AUTONEG_ENABLE,
NIC_AUTONEG_DISABLE,
NIC_AUTONEG_PROBE,
NIC_AUTONEG_RESTART,
NIC_GET_PAUSE,
NIC_SET_PAUSE,
NIC_UNICAST_GET_MODE,
NIC_UNICAST_SET_MODE,
NIC_MULTICAST_GET_MODE,
NIC_MULTICAST_SET_MODE,
NIC_BROADCAST_GET_MODE,
NIC_BROADCAST_SET_MODE,
NIC_DEFECTIVE_GET_MODE,
NIC_DEFECTIVE_SET_MODE,
NIC_BLOCKED_SOURCES_GET,
NIC_BLOCKED_SOURCES_SET,
NIC_VLAN_GET_MASK,
NIC_VLAN_SET_MASK,
NIC_VLAN_SET_TAG,
NIC_WOL_VIRTUE_ADD,
NIC_WOL_VIRTUE_REMOVE,
NIC_WOL_VIRTUE_PROBE,
NIC_WOL_VIRTUE_LIST,
NIC_WOL_VIRTUE_GET_CAPS,
NIC_WOL_LOAD_INFO,
NIC_OFFLOAD_PROBE,
NIC_OFFLOAD_SET,
NIC_POLL_GET_MODE,
NIC_POLL_SET_MODE,
NIC_POLL_NOW
} nic_funcs_t;
errno_t nic_send_frame(async_sess_t *dev_sess, void *data, size_t size)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
ipc_call_t answer;
aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_SEND_MESSAGE, &answer);
errno_t retval = async_data_write_start(exch, data, size);
async_exchange_end(exch);
if (retval != EOK) {
async_forget(req);
return retval;
}
async_wait_for(req, &retval);
return retval;
}
errno_t nic_callback_create(async_sess_t *dev_sess, async_port_handler_t cfun,
void *carg)
{
ipc_call_t answer;
errno_t rc;
errno_t retval;
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t req = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_CALLBACK_CREATE, &answer);
port_id_t port;
rc = async_create_callback_port(exch, INTERFACE_NIC_CB, 0, 0,
cfun, carg, &port);
if (rc != EOK) {
async_forget(req);
return rc;
}
async_exchange_end(exch);
async_wait_for(req, &retval);
return retval;
}
errno_t nic_get_state(async_sess_t *dev_sess, nic_device_state_t *state)
{
assert(state);
sysarg_t _state;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_GET_STATE, &_state);
async_exchange_end(exch);
*state = (nic_device_state_t) _state;
return rc;
}
errno_t nic_set_state(async_sess_t *dev_sess, nic_device_state_t state)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_SET_STATE, state);
async_exchange_end(exch);
return rc;
}
errno_t nic_get_address(async_sess_t *dev_sess, nic_address_t *address)
{
assert(address);
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_GET_ADDRESS, NULL);
errno_t rc = async_data_read_start(exch, address, sizeof(nic_address_t));
async_exchange_end(exch);
errno_t res;
async_wait_for(aid, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_set_address(async_sess_t *dev_sess, const nic_address_t *address)
{
assert(address);
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_SET_ADDRESS, NULL);
errno_t rc = async_data_write_start(exch, address, sizeof(nic_address_t));
async_exchange_end(exch);
errno_t res;
async_wait_for(aid, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats)
{
assert(stats);
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_GET_STATS);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t));
async_exchange_end(exch);
return rc;
}
errno_t nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info)
{
assert(device_info);
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_GET_DEVICE_INFO, NULL);
errno_t rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t));
async_exchange_end(exch);
errno_t res;
async_wait_for(aid, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_get_cable_state(async_sess_t *dev_sess, nic_cable_state_t *cable_state)
{
assert(cable_state);
sysarg_t _cable_state;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_GET_CABLE_STATE, &_cable_state);
async_exchange_end(exch);
*cable_state = (nic_cable_state_t) _cable_state;
return rc;
}
errno_t nic_get_operation_mode(async_sess_t *dev_sess, int *speed,
nic_channel_mode_t *duplex, nic_role_t *role)
{
sysarg_t _speed;
sysarg_t _duplex;
sysarg_t _role;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_GET_OPERATION_MODE, &_speed, &_duplex, &_role);
async_exchange_end(exch);
if (speed)
*speed = (int) _speed;
if (duplex)
*duplex = (nic_channel_mode_t) _duplex;
if (role)
*role = (nic_role_t) _role;
return rc;
}
errno_t nic_set_operation_mode(async_sess_t *dev_sess, int speed,
nic_channel_mode_t duplex, nic_role_t role)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_SET_OPERATION_MODE, (sysarg_t) speed, (sysarg_t) duplex,
(sysarg_t) role);
async_exchange_end(exch);
return rc;
}
errno_t nic_autoneg_enable(async_sess_t *dev_sess, uint32_t advertisement)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_AUTONEG_ENABLE, (sysarg_t) advertisement);
async_exchange_end(exch);
return rc;
}
errno_t nic_autoneg_disable(async_sess_t *dev_sess)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_AUTONEG_DISABLE);
async_exchange_end(exch);
return rc;
}
errno_t nic_autoneg_probe(async_sess_t *dev_sess, uint32_t *our_advertisement,
uint32_t *their_advertisement, nic_result_t *result,
nic_result_t *their_result)
{
sysarg_t _our_advertisement;
sysarg_t _their_advertisement;
sysarg_t _result;
sysarg_t _their_result;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_4(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_AUTONEG_PROBE, &_our_advertisement, &_their_advertisement,
&_result, &_their_result);
async_exchange_end(exch);
if (our_advertisement)
*our_advertisement = (uint32_t) _our_advertisement;
if (*their_advertisement)
*their_advertisement = (uint32_t) _their_advertisement;
if (result)
*result = (nic_result_t) _result;
if (their_result)
*their_result = (nic_result_t) _their_result;
return rc;
}
errno_t nic_autoneg_restart(async_sess_t *dev_sess)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_AUTONEG_RESTART);
async_exchange_end(exch);
return rc;
}
errno_t nic_get_pause(async_sess_t *dev_sess, nic_result_t *we_send,
nic_result_t *we_receive, uint16_t *pause)
{
sysarg_t _we_send;
sysarg_t _we_receive;
sysarg_t _pause;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_GET_PAUSE, &_we_send, &_we_receive, &_pause);
async_exchange_end(exch);
if (we_send)
*we_send = _we_send;
if (we_receive)
*we_receive = _we_receive;
if (pause)
*pause = _pause;
return rc;
}
errno_t nic_set_pause(async_sess_t *dev_sess, int allow_send, int allow_receive,
uint16_t pause)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_SET_PAUSE, allow_send, allow_receive, pause);
async_exchange_end(exch);
return rc;
}
errno_t nic_unicast_get_mode(async_sess_t *dev_sess, nic_unicast_mode_t *mode,
size_t max_count, nic_address_t *address_list, size_t *address_count)
{
assert(mode);
sysarg_t _mode;
sysarg_t _address_count;
if (!address_list)
max_count = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_UNICAST_GET_MODE, max_count, &_mode, &_address_count);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
*mode = (nic_unicast_mode_t) _mode;
if (address_count)
*address_count = (size_t) _address_count;
if ((max_count) && (_address_count))
rc = async_data_read_start(exch, address_list,
max_count * sizeof(nic_address_t));
async_exchange_end(exch);
return rc;
}
errno_t nic_unicast_set_mode(async_sess_t *dev_sess, nic_unicast_mode_t mode,
const nic_address_t *address_list, size_t address_count)
{
if (address_list == NULL)
address_count = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_UNICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
errno_t rc;
if (address_count)
rc = async_data_write_start(exch, address_list,
address_count * sizeof(nic_address_t));
else
rc = EOK;
async_exchange_end(exch);
errno_t res;
async_wait_for(message_id, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_multicast_get_mode(async_sess_t *dev_sess, nic_multicast_mode_t *mode,
size_t max_count, nic_address_t *address_list, size_t *address_count)
{
assert(mode);
sysarg_t _mode;
if (!address_list)
max_count = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
sysarg_t ac;
errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_MULTICAST_GET_MODE, max_count, &_mode, &ac);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
*mode = (nic_multicast_mode_t) _mode;
if (address_count)
*address_count = (size_t) ac;
if ((max_count) && (ac))
rc = async_data_read_start(exch, address_list,
max_count * sizeof(nic_address_t));
async_exchange_end(exch);
return rc;
}
errno_t nic_multicast_set_mode(async_sess_t *dev_sess, nic_multicast_mode_t mode,
const nic_address_t *address_list, size_t address_count)
{
if (address_list == NULL)
address_count = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_MULTICAST_SET_MODE, (sysarg_t) mode, address_count, NULL);
errno_t rc;
if (address_count)
rc = async_data_write_start(exch, address_list,
address_count * sizeof(nic_address_t));
else
rc = EOK;
async_exchange_end(exch);
errno_t res;
async_wait_for(message_id, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_broadcast_get_mode(async_sess_t *dev_sess, nic_broadcast_mode_t *mode)
{
assert(mode);
sysarg_t _mode;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_BROADCAST_GET_MODE, &_mode);
async_exchange_end(exch);
*mode = (nic_broadcast_mode_t) _mode;
return rc;
}
errno_t nic_broadcast_set_mode(async_sess_t *dev_sess, nic_broadcast_mode_t mode)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_BROADCAST_SET_MODE, mode);
async_exchange_end(exch);
return rc;
}
errno_t nic_defective_get_mode(async_sess_t *dev_sess, uint32_t *mode)
{
assert(mode);
sysarg_t _mode;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_DEFECTIVE_GET_MODE, &_mode);
async_exchange_end(exch);
*mode = (uint32_t) _mode;
return rc;
}
errno_t nic_defective_set_mode(async_sess_t *dev_sess, uint32_t mode)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_DEFECTIVE_SET_MODE, mode);
async_exchange_end(exch);
return rc;
}
errno_t nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count,
nic_address_t *address_list, size_t *address_count)
{
if (!address_list)
max_count = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
sysarg_t ac;
errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_BLOCKED_SOURCES_GET, max_count, &ac);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
if (address_count)
*address_count = (size_t) ac;
if ((max_count) && (ac))
rc = async_data_read_start(exch, address_list,
max_count * sizeof(nic_address_t));
async_exchange_end(exch);
return rc;
}
errno_t nic_blocked_sources_set(async_sess_t *dev_sess,
const nic_address_t *address_list, size_t address_count)
{
if (address_list == NULL)
address_count = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_BLOCKED_SOURCES_SET, address_count, NULL);
errno_t rc;
if (address_count)
rc = async_data_write_start(exch, address_list,
address_count * sizeof(nic_address_t));
else
rc = EOK;
async_exchange_end(exch);
errno_t res;
async_wait_for(message_id, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask)
{
assert(mask);
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_VLAN_GET_MASK);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t));
async_exchange_end(exch);
return rc;
}
errno_t nic_vlan_set_mask(async_sess_t *dev_sess, const nic_vlan_mask_t *mask)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t message_id = async_send_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_VLAN_SET_MASK, mask != NULL, NULL);
errno_t rc;
if (mask != NULL)
rc = async_data_write_start(exch, mask, sizeof(nic_vlan_mask_t));
else
rc = EOK;
async_exchange_end(exch);
errno_t res;
async_wait_for(message_id, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_vlan_set_tag(async_sess_t *dev_sess, uint16_t tag, bool add, bool strip)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_4_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_VLAN_SET_TAG, (sysarg_t) tag, (sysarg_t) add, (sysarg_t) strip);
async_exchange_end(exch);
return rc;
}
errno_t nic_wol_virtue_add(async_sess_t *dev_sess, nic_wv_type_t type,
const void *data, size_t length, nic_wv_id_t *id)
{
assert(id);
bool send_data = ((data != NULL) && (length != 0));
async_exch_t *exch = async_exchange_begin(dev_sess);
ipc_call_t result;
aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_WOL_VIRTUE_ADD, (sysarg_t) type, send_data, &result);
errno_t res;
if (send_data) {
errno_t rc = async_data_write_start(exch, data, length);
if (rc != EOK) {
async_exchange_end(exch);
async_wait_for(message_id, &res);
return rc;
}
}
async_exchange_end(exch);
async_wait_for(message_id, &res);
*id = ipc_get_arg1(&result);
return res;
}
errno_t nic_wol_virtue_remove(async_sess_t *dev_sess, nic_wv_id_t id)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_WOL_VIRTUE_REMOVE, (sysarg_t) id);
async_exchange_end(exch);
return rc;
}
errno_t nic_wol_virtue_probe(async_sess_t *dev_sess, nic_wv_id_t id,
nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
{
sysarg_t _type;
sysarg_t _length;
if (data == NULL)
max_length = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_3_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_WOL_VIRTUE_PROBE, (sysarg_t) id, max_length,
&_type, &_length);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
if (type)
*type = _type;
if (length)
*length = _length;
if ((max_length) && (_length != 0))
rc = async_data_read_start(exch, data, max_length);
async_exchange_end(exch);
return rc;
}
errno_t nic_wol_virtue_list(async_sess_t *dev_sess, nic_wv_type_t type,
size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
{
if (id_list == NULL)
max_count = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
sysarg_t count;
errno_t rc = async_req_3_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_WOL_VIRTUE_LIST, (sysarg_t) type, max_count, &count);
if (id_count)
*id_count = (size_t) count;
if ((rc != EOK) || (!max_count)) {
async_exchange_end(exch);
return rc;
}
rc = async_data_read_start(exch, id_list,
max_count * sizeof(nic_wv_id_t));
async_exchange_end(exch);
return rc;
}
errno_t nic_wol_virtue_get_caps(async_sess_t *dev_sess, nic_wv_type_t type,
int *count)
{
assert(count);
sysarg_t _count;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_WOL_VIRTUE_GET_CAPS, (sysarg_t) type, &_count);
async_exchange_end(exch);
*count = (int) _count;
return rc;
}
errno_t nic_wol_load_info(async_sess_t *dev_sess, nic_wv_type_t *matched_type,
size_t max_length, uint8_t *frame, size_t *frame_length)
{
assert(matched_type);
sysarg_t _matched_type;
sysarg_t _frame_length;
if (frame == NULL)
max_length = 0;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_WOL_LOAD_INFO, max_length, &_matched_type, &_frame_length);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
*matched_type = (nic_wv_type_t) _matched_type;
if (frame_length)
*frame_length = (size_t) _frame_length;
if ((max_length != 0) && (_frame_length != 0))
rc = async_data_read_start(exch, frame, max_length);
async_exchange_end(exch);
return rc;
}
errno_t nic_offload_probe(async_sess_t *dev_sess, uint32_t *supported,
uint32_t *active)
{
assert(supported);
assert(active);
sysarg_t _supported;
sysarg_t _active;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_OFFLOAD_PROBE, &_supported, &_active);
async_exchange_end(exch);
*supported = (uint32_t) _supported;
*active = (uint32_t) _active;
return rc;
}
errno_t nic_offload_set(async_sess_t *dev_sess, uint32_t mask, uint32_t active)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_3_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_AUTONEG_RESTART, (sysarg_t) mask, (sysarg_t) active);
async_exchange_end(exch);
return rc;
}
errno_t nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode,
struct timespec *period)
{
assert(mode);
sysarg_t _mode;
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_POLL_GET_MODE, period != NULL, &_mode);
if (rc != EOK) {
async_exchange_end(exch);
return rc;
}
*mode = (nic_poll_mode_t) _mode;
if (period != NULL)
rc = async_data_read_start(exch, period, sizeof(struct timespec));
async_exchange_end(exch);
return rc;
}
errno_t nic_poll_set_mode(async_sess_t *dev_sess, nic_poll_mode_t mode,
const struct timespec *period)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE),
NIC_POLL_SET_MODE, (sysarg_t) mode, period != NULL, NULL);
errno_t rc;
if (period)
rc = async_data_write_start(exch, period, sizeof(struct timespec));
else
rc = EOK;
async_exchange_end(exch);
errno_t res;
async_wait_for(message_id, &res);
if (rc != EOK)
return rc;
return res;
}
errno_t nic_poll_now(async_sess_t *dev_sess)
{
async_exch_t *exch = async_exchange_begin(dev_sess);
errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_NOW);
async_exchange_end(exch);
return rc;
}
static void remote_nic_send_frame(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
assert(nic_iface->send_frame);
void *data;
size_t size;
errno_t rc;
rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
if (rc != EOK) {
async_answer_0(call, EINVAL);
return;
}
rc = nic_iface->send_frame(dev, data, size);
async_answer_0(call, rc);
free(data);
}
static void remote_nic_callback_create(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
assert(nic_iface->callback_create);
errno_t rc = nic_iface->callback_create(dev);
async_answer_0(call, rc);
}
static void remote_nic_get_state(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
assert(nic_iface->get_state);
nic_device_state_t state = NIC_STATE_MAX;
errno_t rc = nic_iface->get_state(dev, &state);
async_answer_1(call, rc, state);
}
static void remote_nic_set_state(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
assert(nic_iface->set_state);
nic_device_state_t state = (nic_device_state_t) ipc_get_arg2(call);
errno_t rc = nic_iface->set_state(dev, state);
async_answer_0(call, rc);
}
static void remote_nic_get_address(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
assert(nic_iface->get_address);
nic_address_t address;
memset(&address, 0, sizeof(nic_address_t));
errno_t rc = nic_iface->get_address(dev, &address);
if (rc == EOK) {
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (max_len != sizeof(nic_address_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
async_data_read_finalize(&data, &address,
sizeof(nic_address_t));
}
async_answer_0(call, rc);
}
static void remote_nic_set_address(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
ipc_call_t data;
size_t length;
if (!async_data_write_receive(&data, &length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (length > sizeof(nic_address_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
nic_address_t address;
if (async_data_write_finalize(&data, &address, length) != EOK) {
async_answer_0(call, EINVAL);
return;
}
if (nic_iface->set_address != NULL) {
errno_t rc = nic_iface->set_address(dev, &address);
async_answer_0(call, rc);
} else
async_answer_0(call, ENOTSUP);
}
static void remote_nic_get_stats(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->get_stats == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_device_stats_t stats;
memset(&stats, 0, sizeof(nic_device_stats_t));
errno_t rc = nic_iface->get_stats(dev, &stats);
if (rc == EOK) {
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (max_len < sizeof(nic_device_stats_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
async_data_read_finalize(&data, &stats,
sizeof(nic_device_stats_t));
}
async_answer_0(call, rc);
}
static void remote_nic_get_device_info(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->get_device_info == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_device_info_t info;
memset(&info, 0, sizeof(nic_device_info_t));
errno_t rc = nic_iface->get_device_info(dev, &info);
if (rc == EOK) {
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (max_len < sizeof (nic_device_info_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
async_data_read_finalize(&data, &info,
sizeof(nic_device_info_t));
}
async_answer_0(call, rc);
}
static void remote_nic_get_cable_state(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->get_cable_state == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_cable_state_t cs = NIC_CS_UNKNOWN;
errno_t rc = nic_iface->get_cable_state(dev, &cs);
async_answer_1(call, rc, (sysarg_t) cs);
}
static void remote_nic_get_operation_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->get_operation_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
int speed = 0;
nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
nic_role_t role = NIC_ROLE_UNKNOWN;
errno_t rc = nic_iface->get_operation_mode(dev, &speed, &duplex, &role);
async_answer_3(call, rc, (sysarg_t) speed, (sysarg_t) duplex,
(sysarg_t) role);
}
static void remote_nic_set_operation_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->set_operation_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
int speed = (int) ipc_get_arg2(call);
nic_channel_mode_t duplex = (nic_channel_mode_t) ipc_get_arg3(call);
nic_role_t role = (nic_role_t) ipc_get_arg4(call);
errno_t rc = nic_iface->set_operation_mode(dev, speed, duplex, role);
async_answer_0(call, rc);
}
static void remote_nic_autoneg_enable(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->autoneg_enable == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
uint32_t advertisement = (uint32_t) ipc_get_arg2(call);
errno_t rc = nic_iface->autoneg_enable(dev, advertisement);
async_answer_0(call, rc);
}
static void remote_nic_autoneg_disable(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->autoneg_disable == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
errno_t rc = nic_iface->autoneg_disable(dev);
async_answer_0(call, rc);
}
static void remote_nic_autoneg_probe(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->autoneg_probe == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
uint32_t our_adv = 0;
uint32_t their_adv = 0;
nic_result_t result = NIC_RESULT_NOT_AVAILABLE;
nic_result_t their_result = NIC_RESULT_NOT_AVAILABLE;
errno_t rc = nic_iface->autoneg_probe(dev, &our_adv, &their_adv, &result,
&their_result);
async_answer_4(call, rc, our_adv, their_adv, (sysarg_t) result,
(sysarg_t) their_result);
}
static void remote_nic_autoneg_restart(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->autoneg_restart == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
errno_t rc = nic_iface->autoneg_restart(dev);
async_answer_0(call, rc);
}
static void remote_nic_get_pause(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->get_pause == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_result_t we_send;
nic_result_t we_receive;
uint16_t pause;
errno_t rc = nic_iface->get_pause(dev, &we_send, &we_receive, &pause);
async_answer_3(call, rc, we_send, we_receive, pause);
}
static void remote_nic_set_pause(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->set_pause == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
int allow_send = (int) ipc_get_arg2(call);
int allow_receive = (int) ipc_get_arg3(call);
uint16_t pause = (uint16_t) ipc_get_arg4(call);
errno_t rc = nic_iface->set_pause(dev, allow_send, allow_receive,
pause);
async_answer_0(call, rc);
}
static void remote_nic_unicast_get_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->unicast_get_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
size_t max_count = ipc_get_arg2(call);
nic_address_t *address_list = NULL;
if (max_count != 0) {
address_list = malloc(max_count * sizeof (nic_address_t));
if (!address_list) {
async_answer_0(call, ENOMEM);
return;
}
}
memset(address_list, 0, max_count * sizeof(nic_address_t));
nic_unicast_mode_t mode = NIC_UNICAST_DEFAULT;
size_t address_count = 0;
errno_t rc = nic_iface->unicast_get_mode(dev, &mode, max_count, address_list,
&address_count);
if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
free(address_list);
async_answer_2(call, rc, mode, address_count);
return;
}
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_2(call, rc, mode, address_count);
free(address_list);
return;
}
if (max_len > address_count * sizeof(nic_address_t))
max_len = address_count * sizeof(nic_address_t);
if (max_len > max_count * sizeof(nic_address_t))
max_len = max_count * sizeof(nic_address_t);
async_data_read_finalize(&data, address_list, max_len);
free(address_list);
async_answer_2(call, rc, mode, address_count);
}
static void remote_nic_unicast_set_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
size_t length;
nic_unicast_mode_t mode = ipc_get_arg2(call);
size_t address_count = ipc_get_arg3(call);
nic_address_t *address_list = NULL;
if (address_count) {
ipc_call_t data;
if (!async_data_write_receive(&data, &length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (length != address_count * sizeof(nic_address_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
address_list = malloc(length);
if (address_list == NULL) {
async_answer_0(&data, ENOMEM);
async_answer_0(call, ENOMEM);
return;
}
if (async_data_write_finalize(&data, address_list,
length) != EOK) {
async_answer_0(call, EINVAL);
free(address_list);
return;
}
}
if (nic_iface->unicast_set_mode != NULL) {
errno_t rc = nic_iface->unicast_set_mode(dev, mode, address_list,
address_count);
async_answer_0(call, rc);
} else
async_answer_0(call, ENOTSUP);
free(address_list);
}
static void remote_nic_multicast_get_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->multicast_get_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
size_t max_count = ipc_get_arg2(call);
nic_address_t *address_list = NULL;
if (max_count != 0) {
address_list = malloc(max_count * sizeof(nic_address_t));
if (!address_list) {
async_answer_0(call, ENOMEM);
return;
}
}
memset(address_list, 0, max_count * sizeof(nic_address_t));
nic_multicast_mode_t mode = NIC_MULTICAST_BLOCKED;
size_t address_count = 0;
errno_t rc = nic_iface->multicast_get_mode(dev, &mode, max_count, address_list,
&address_count);
if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
free(address_list);
async_answer_2(call, rc, mode, address_count);
return;
}
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_2(call, rc, mode, address_count);
free(address_list);
return;
}
if (max_len > address_count * sizeof(nic_address_t))
max_len = address_count * sizeof(nic_address_t);
if (max_len > max_count * sizeof(nic_address_t))
max_len = max_count * sizeof(nic_address_t);
async_data_read_finalize(&data, address_list, max_len);
free(address_list);
async_answer_2(call, rc, mode, address_count);
}
static void remote_nic_multicast_set_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
nic_multicast_mode_t mode = ipc_get_arg2(call);
size_t address_count = ipc_get_arg3(call);
nic_address_t *address_list = NULL;
if (address_count) {
ipc_call_t data;
size_t length;
if (!async_data_write_receive(&data, &length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (length != address_count * sizeof (nic_address_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
address_list = malloc(length);
if (address_list == NULL) {
async_answer_0(&data, ENOMEM);
async_answer_0(call, ENOMEM);
return;
}
if (async_data_write_finalize(&data, address_list,
length) != EOK) {
async_answer_0(call, EINVAL);
free(address_list);
return;
}
}
if (nic_iface->multicast_set_mode != NULL) {
errno_t rc = nic_iface->multicast_set_mode(dev, mode, address_list,
address_count);
async_answer_0(call, rc);
} else
async_answer_0(call, ENOTSUP);
free(address_list);
}
static void remote_nic_broadcast_get_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->broadcast_get_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_broadcast_mode_t mode = NIC_BROADCAST_ACCEPTED;
errno_t rc = nic_iface->broadcast_get_mode(dev, &mode);
async_answer_1(call, rc, mode);
}
static void remote_nic_broadcast_set_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->broadcast_set_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_broadcast_mode_t mode = ipc_get_arg2(call);
errno_t rc = nic_iface->broadcast_set_mode(dev, mode);
async_answer_0(call, rc);
}
static void remote_nic_defective_get_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->defective_get_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
uint32_t mode = 0;
errno_t rc = nic_iface->defective_get_mode(dev, &mode);
async_answer_1(call, rc, mode);
}
static void remote_nic_defective_set_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->defective_set_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
uint32_t mode = ipc_get_arg2(call);
errno_t rc = nic_iface->defective_set_mode(dev, mode);
async_answer_0(call, rc);
}
static void remote_nic_blocked_sources_get(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->blocked_sources_get == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
size_t max_count = ipc_get_arg2(call);
nic_address_t *address_list = NULL;
if (max_count != 0) {
address_list = malloc(max_count * sizeof(nic_address_t));
if (!address_list) {
async_answer_0(call, ENOMEM);
return;
}
}
memset(address_list, 0, max_count * sizeof(nic_address_t));
size_t address_count = 0;
errno_t rc = nic_iface->blocked_sources_get(dev, max_count, address_list,
&address_count);
if ((rc != EOK) || (max_count == 0) || (address_count == 0)) {
async_answer_1(call, rc, address_count);
free(address_list);
return;
}
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_1(call, rc, address_count);
free(address_list);
return;
}
if (max_len > address_count * sizeof(nic_address_t))
max_len = address_count * sizeof(nic_address_t);
if (max_len > max_count * sizeof(nic_address_t))
max_len = max_count * sizeof(nic_address_t);
async_data_read_finalize(&data, address_list, max_len);
free(address_list);
async_answer_1(call, rc, address_count);
}
static void remote_nic_blocked_sources_set(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
size_t length;
size_t address_count = ipc_get_arg2(call);
nic_address_t *address_list = NULL;
if (address_count) {
ipc_call_t data;
if (!async_data_write_receive(&data, &length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (length != address_count * sizeof(nic_address_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
address_list = malloc(length);
if (address_list == NULL) {
async_answer_0(&data, ENOMEM);
async_answer_0(call, ENOMEM);
return;
}
if (async_data_write_finalize(&data, address_list,
length) != EOK) {
async_answer_0(call, EINVAL);
free(address_list);
return;
}
}
if (nic_iface->blocked_sources_set != NULL) {
errno_t rc = nic_iface->blocked_sources_set(dev, address_list,
address_count);
async_answer_0(call, rc);
} else
async_answer_0(call, ENOTSUP);
free(address_list);
}
static void remote_nic_vlan_get_mask(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->vlan_get_mask == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_vlan_mask_t vlan_mask;
memset(&vlan_mask, 0, sizeof(nic_vlan_mask_t));
errno_t rc = nic_iface->vlan_get_mask(dev, &vlan_mask);
if (rc == EOK) {
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (max_len != sizeof(nic_vlan_mask_t)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
async_data_read_finalize(&data, &vlan_mask, max_len);
}
async_answer_0(call, rc);
}
static void remote_nic_vlan_set_mask(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
nic_vlan_mask_t vlan_mask;
nic_vlan_mask_t *vlan_mask_pointer = NULL;
bool vlan_mask_set = (bool) ipc_get_arg2(call);
if (vlan_mask_set) {
ipc_call_t data;
size_t length;
if (!async_data_write_receive(&data, &length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (length != sizeof(nic_vlan_mask_t)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
if (async_data_write_finalize(&data, &vlan_mask,
length) != EOK) {
async_answer_0(call, EINVAL);
return;
}
vlan_mask_pointer = &vlan_mask;
}
if (nic_iface->vlan_set_mask != NULL) {
errno_t rc = nic_iface->vlan_set_mask(dev, vlan_mask_pointer);
async_answer_0(call, rc);
} else
async_answer_0(call, ENOTSUP);
}
static void remote_nic_vlan_set_tag(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->vlan_set_tag == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
uint16_t tag = (uint16_t) ipc_get_arg2(call);
bool add = (int) ipc_get_arg3(call);
bool strip = (int) ipc_get_arg4(call);
errno_t rc = nic_iface->vlan_set_tag(dev, tag, add, strip);
async_answer_0(call, rc);
}
static void remote_nic_wol_virtue_add(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
int send_data = (int) ipc_get_arg3(call);
ipc_call_t data;
if (nic_iface->wol_virtue_add == NULL) {
if (send_data) {
async_data_write_receive(&data, NULL);
async_answer_0(&data, ENOTSUP);
}
async_answer_0(call, ENOTSUP);
}
size_t length = 0;
void *virtue = NULL;
if (send_data) {
if (!async_data_write_receive(&data, &length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
virtue = malloc(length);
if (virtue == NULL) {
async_answer_0(&data, ENOMEM);
async_answer_0(call, ENOMEM);
return;
}
if (async_data_write_finalize(&data, virtue,
length) != EOK) {
async_answer_0(call, EINVAL);
free(virtue);
return;
}
}
nic_wv_id_t id = 0;
nic_wv_type_t type = (nic_wv_type_t) ipc_get_arg2(call);
errno_t rc = nic_iface->wol_virtue_add(dev, type, virtue, length, &id);
async_answer_1(call, rc, (sysarg_t) id);
free(virtue);
}
static void remote_nic_wol_virtue_remove(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->wol_virtue_remove == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_wv_id_t id = (nic_wv_id_t) ipc_get_arg2(call);
errno_t rc = nic_iface->wol_virtue_remove(dev, id);
async_answer_0(call, rc);
}
static void remote_nic_wol_virtue_probe(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->wol_virtue_probe == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_wv_id_t id = (nic_wv_id_t) ipc_get_arg2(call);
size_t max_length = ipc_get_arg3(call);
nic_wv_type_t type = NIC_WV_NONE;
size_t length = 0;
ipc_call_t data;
void *virtue = NULL;
if (max_length != 0) {
virtue = malloc(max_length);
if (virtue == NULL) {
async_answer_0(call, ENOMEM);
return;
}
}
memset(virtue, 0, max_length);
errno_t rc = nic_iface->wol_virtue_probe(dev, id, &type, max_length,
virtue, &length);
if ((max_length != 0) && (length != 0)) {
size_t req_length;
if (!async_data_read_receive(&data, &req_length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
free(virtue);
return;
}
if (req_length > length)
req_length = length;
if (req_length > max_length)
req_length = max_length;
async_data_read_finalize(&data, virtue, req_length);
}
async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) length);
free(virtue);
}
static void remote_nic_wol_virtue_list(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->wol_virtue_list == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_wv_type_t type = (nic_wv_type_t) ipc_get_arg2(call);
size_t max_count = ipc_get_arg3(call);
size_t count = 0;
nic_wv_id_t *id_list = NULL;
ipc_call_t data;
if (max_count != 0) {
id_list = malloc(max_count * sizeof(nic_wv_id_t));
if (id_list == NULL) {
async_answer_0(call, ENOMEM);
return;
}
}
memset(id_list, 0, max_count * sizeof (nic_wv_id_t));
errno_t rc = nic_iface->wol_virtue_list(dev, type, max_count, id_list,
&count);
if ((max_count != 0) && (count != 0)) {
size_t req_length;
if (!async_data_read_receive(&data, &req_length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
free(id_list);
return;
}
if (req_length > count * sizeof(nic_wv_id_t))
req_length = count * sizeof(nic_wv_id_t);
if (req_length > max_count * sizeof(nic_wv_id_t))
req_length = max_count * sizeof(nic_wv_id_t);
rc = async_data_read_finalize(&data, id_list, req_length);
}
async_answer_1(call, rc, (sysarg_t) count);
free(id_list);
}
static void remote_nic_wol_virtue_get_caps(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->wol_virtue_get_caps == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
int count = -1;
nic_wv_type_t type = (nic_wv_type_t) ipc_get_arg2(call);
errno_t rc = nic_iface->wol_virtue_get_caps(dev, type, &count);
async_answer_1(call, rc, (sysarg_t) count);
}
static void remote_nic_wol_load_info(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->wol_load_info == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
size_t max_length = (size_t) ipc_get_arg2(call);
size_t frame_length = 0;
nic_wv_type_t type = NIC_WV_NONE;
uint8_t *info = NULL;
if (max_length != 0) {
info = malloc(max_length);
if (info == NULL) {
async_answer_0(call, ENOMEM);
return;
}
}
memset(info, 0, max_length);
errno_t rc = nic_iface->wol_load_info(dev, &type, max_length, info,
&frame_length);
if (rc == EOK) {
ipc_call_t data;
size_t req_length;
if (!async_data_read_receive(&data, &req_length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
free(info);
return;
}
req_length = req_length > max_length ? max_length : req_length;
req_length = req_length > frame_length ? frame_length : req_length;
async_data_read_finalize(&data, info, req_length);
}
async_answer_2(call, rc, (sysarg_t) type, (sysarg_t) frame_length);
free(info);
}
static void remote_nic_offload_probe(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->offload_probe == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
uint32_t supported = 0;
uint32_t active = 0;
errno_t rc = nic_iface->offload_probe(dev, &supported, &active);
async_answer_2(call, rc, supported, active);
}
static void remote_nic_offload_set(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->offload_set == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
uint32_t mask = (uint32_t) ipc_get_arg2(call);
uint32_t active = (uint32_t) ipc_get_arg3(call);
errno_t rc = nic_iface->offload_set(dev, mask, active);
async_answer_0(call, rc);
}
static void remote_nic_poll_get_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->poll_get_mode == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
nic_poll_mode_t mode = NIC_POLL_IMMEDIATE;
int request_data = ipc_get_arg2(call);
struct timespec period = {
.tv_sec = 0,
.tv_nsec = 0
};
errno_t rc = nic_iface->poll_get_mode(dev, &mode, &period);
if ((rc == EOK) && (request_data)) {
ipc_call_t data;
size_t max_len;
if (!async_data_read_receive(&data, &max_len)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (max_len != sizeof(struct timespec)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
async_data_read_finalize(&data, &period,
sizeof(struct timespec));
}
async_answer_1(call, rc, (sysarg_t) mode);
}
static void remote_nic_poll_set_mode(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
nic_poll_mode_t mode = ipc_get_arg2(call);
int has_period = ipc_get_arg3(call);
struct timespec period_buf;
struct timespec *period = NULL;
size_t length;
if (has_period) {
ipc_call_t data;
if (!async_data_write_receive(&data, &length)) {
async_answer_0(&data, EINVAL);
async_answer_0(call, EINVAL);
return;
}
if (length != sizeof(struct timespec)) {
async_answer_0(&data, ELIMIT);
async_answer_0(call, ELIMIT);
return;
}
period = &period_buf;
if (async_data_write_finalize(&data, period,
length) != EOK) {
async_answer_0(call, EINVAL);
return;
}
}
if (nic_iface->poll_set_mode != NULL) {
errno_t rc = nic_iface->poll_set_mode(dev, mode, period);
async_answer_0(call, rc);
} else
async_answer_0(call, ENOTSUP);
}
static void remote_nic_poll_now(ddf_fun_t *dev, void *iface,
ipc_call_t *call)
{
nic_iface_t *nic_iface = (nic_iface_t *) iface;
if (nic_iface->poll_now == NULL) {
async_answer_0(call, ENOTSUP);
return;
}
errno_t rc = nic_iface->poll_now(dev);
async_answer_0(call, rc);
}
static const remote_iface_func_ptr_t remote_nic_iface_ops[] = {
[NIC_SEND_MESSAGE] = remote_nic_send_frame,
[NIC_CALLBACK_CREATE] = remote_nic_callback_create,
[NIC_GET_STATE] = remote_nic_get_state,
[NIC_SET_STATE] = remote_nic_set_state,
[NIC_GET_ADDRESS] = remote_nic_get_address,
[NIC_SET_ADDRESS] = remote_nic_set_address,
[NIC_GET_STATS] = remote_nic_get_stats,
[NIC_GET_DEVICE_INFO] = remote_nic_get_device_info,
[NIC_GET_CABLE_STATE] = remote_nic_get_cable_state,
[NIC_GET_OPERATION_MODE] = remote_nic_get_operation_mode,
[NIC_SET_OPERATION_MODE] = remote_nic_set_operation_mode,
[NIC_AUTONEG_ENABLE] = remote_nic_autoneg_enable,
[NIC_AUTONEG_DISABLE] = remote_nic_autoneg_disable,
[NIC_AUTONEG_PROBE] = remote_nic_autoneg_probe,
[NIC_AUTONEG_RESTART] = remote_nic_autoneg_restart,
[NIC_GET_PAUSE] = remote_nic_get_pause,
[NIC_SET_PAUSE] = remote_nic_set_pause,
[NIC_UNICAST_GET_MODE] = remote_nic_unicast_get_mode,
[NIC_UNICAST_SET_MODE] = remote_nic_unicast_set_mode,
[NIC_MULTICAST_GET_MODE] = remote_nic_multicast_get_mode,
[NIC_MULTICAST_SET_MODE] = remote_nic_multicast_set_mode,
[NIC_BROADCAST_GET_MODE] = remote_nic_broadcast_get_mode,
[NIC_BROADCAST_SET_MODE] = remote_nic_broadcast_set_mode,
[NIC_DEFECTIVE_GET_MODE] = remote_nic_defective_get_mode,
[NIC_DEFECTIVE_SET_MODE] = remote_nic_defective_set_mode,
[NIC_BLOCKED_SOURCES_GET] = remote_nic_blocked_sources_get,
[NIC_BLOCKED_SOURCES_SET] = remote_nic_blocked_sources_set,
[NIC_VLAN_GET_MASK] = remote_nic_vlan_get_mask,
[NIC_VLAN_SET_MASK] = remote_nic_vlan_set_mask,
[NIC_VLAN_SET_TAG] = remote_nic_vlan_set_tag,
[NIC_WOL_VIRTUE_ADD] = remote_nic_wol_virtue_add,
[NIC_WOL_VIRTUE_REMOVE] = remote_nic_wol_virtue_remove,
[NIC_WOL_VIRTUE_PROBE] = remote_nic_wol_virtue_probe,
[NIC_WOL_VIRTUE_LIST] = remote_nic_wol_virtue_list,
[NIC_WOL_VIRTUE_GET_CAPS] = remote_nic_wol_virtue_get_caps,
[NIC_WOL_LOAD_INFO] = remote_nic_wol_load_info,
[NIC_OFFLOAD_PROBE] = remote_nic_offload_probe,
[NIC_OFFLOAD_SET] = remote_nic_offload_set,
[NIC_POLL_GET_MODE] = remote_nic_poll_get_mode,
[NIC_POLL_SET_MODE] = remote_nic_poll_set_mode,
[NIC_POLL_NOW] = remote_nic_poll_now
};
const remote_iface_t remote_nic_iface = {
.method_count = ARRAY_SIZE(remote_nic_iface_ops),
.methods = remote_nic_iface_ops
};
HelenOS homepage, sources at GitHub