Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsconfig.h"
|
||||
#include <string.h>
|
||||
#include "ethernet_mac_api.h"
|
||||
#include "eventOS_event.h"
|
||||
#include "nsdynmemLIB.h"
|
||||
#include "common_functions.h"
|
||||
#include "MAC/rf_driver_storage.h"
|
||||
#include "Core/include/ns_monitor.h"
|
||||
|
||||
typedef struct eth_mac_internal_s {
|
||||
eth_mac_api_t *mac_api;
|
||||
arm_device_driver_list_s *dev_driver;
|
||||
uint8_t *mtu_ptr;
|
||||
uint16_t mtu_size;
|
||||
uint8_t mac48_iid64[8];
|
||||
bool active_data_request;
|
||||
int8_t tasklet_id;
|
||||
//linked list link
|
||||
} eth_mac_internal_t;
|
||||
|
||||
static eth_mac_internal_t mac_store = { //Hack only at this point, later put into linked list
|
||||
.tasklet_id = -1
|
||||
};
|
||||
|
||||
#define ETH_INIT_EVENT 0
|
||||
#define ETH_DATA_IND_EVENT 1
|
||||
#define ETH_DATA_CNF_EVENT 2
|
||||
|
||||
|
||||
#define ETHERNET_HDROFF_DST_ADDR 0
|
||||
#define ETHERNET_HDROFF_SRC_ADDR 6
|
||||
#define ETHERNET_HDROFF_TYPE 12
|
||||
#define ETHERNET_HDRLEN 14
|
||||
|
||||
static int8_t eth_mac_api_init(eth_mac_api_t *api, eth_mac_data_confirm *conf_cb, eth_mac_data_indication *ind_cb, uint8_t parent_id);
|
||||
static void data_req(const eth_mac_api_t *api, const eth_data_req_t *data);
|
||||
static int8_t mac48_address_set(const eth_mac_api_t *api, const uint8_t *mac48);
|
||||
static int8_t mac48_address_get(const eth_mac_api_t *api, uint8_t *mac48_buf);
|
||||
static int8_t iid64_address_set(const eth_mac_api_t *api, const uint8_t *iid64);
|
||||
static int8_t iid64_address_get(const eth_mac_api_t *api, uint8_t *iid64_buf);
|
||||
|
||||
static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id);
|
||||
static int8_t eth_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
|
||||
static void ethernet_mac_tasklet(arm_event_s *event);
|
||||
|
||||
int8_t ethernet_mac_destroy(eth_mac_api_t *mac_api)
|
||||
{
|
||||
if (!mac_api || mac_store.mac_api != mac_api) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mac_store.active_data_request = false;
|
||||
ns_dyn_mem_free(mac_store.mac_api);
|
||||
mac_store.mac_api = NULL;
|
||||
mac_store.dev_driver = NULL;
|
||||
ns_dyn_mem_free(mac_store.mtu_ptr);
|
||||
mac_store.mtu_ptr = NULL;
|
||||
mac_store.mtu_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
eth_mac_api_t *ethernet_mac_create(int8_t driver_id)
|
||||
{
|
||||
//TODO: Refactor this away, Drivers should be stored in MAC layer in future
|
||||
arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
|
||||
if (!driver || !driver->phy_driver) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Accept to return same mac if mac is generated and driver is same
|
||||
if (mac_store.mac_api) {
|
||||
if (mac_store.dev_driver == driver) {
|
||||
return mac_store.mac_api;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *buffer_ptr = NULL;
|
||||
uint16_t buffer_length = 0;
|
||||
bool address_resolution_needed = true;
|
||||
|
||||
switch (driver->phy_driver->link_type) {
|
||||
|
||||
case PHY_LINK_SLIP:
|
||||
case PHY_LINK_PPP:
|
||||
//Do not Allocate
|
||||
address_resolution_needed = false;
|
||||
buffer_length = 0;
|
||||
break;
|
||||
|
||||
case PHY_LINK_TUN:
|
||||
address_resolution_needed = false;
|
||||
buffer_length = 1500 + 4;
|
||||
break;
|
||||
case PHY_LINK_ETHERNET_TYPE:
|
||||
|
||||
buffer_length = 1500 + ETHERNET_HDRLEN;
|
||||
|
||||
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
if (buffer_length) {
|
||||
buffer_ptr = ns_dyn_mem_alloc(buffer_length);
|
||||
if (!buffer_ptr) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
eth_mac_api_t *this = ns_dyn_mem_alloc(sizeof(eth_mac_api_t));
|
||||
if (!this) {
|
||||
ns_dyn_mem_free(buffer_ptr);
|
||||
return NULL;
|
||||
}
|
||||
memset(this, 0, sizeof(eth_mac_api_t));
|
||||
this->mac_initialize = ð_mac_api_init;
|
||||
this->data_req = &data_req;
|
||||
|
||||
if (driver->phy_driver->link_type == PHY_LINK_PPP) {
|
||||
this->iid64_get = &iid64_address_get;
|
||||
this->iid64_set = &iid64_address_set;
|
||||
} else {
|
||||
this->mac48_get = &mac48_address_get;
|
||||
this->mac48_set = &mac48_address_set;
|
||||
}
|
||||
|
||||
this->address_resolution_needed = address_resolution_needed;
|
||||
|
||||
memset(&mac_store.mac48_iid64, 0, 8);
|
||||
mac_store.active_data_request = false;
|
||||
mac_store.mac_api = this;
|
||||
mac_store.dev_driver = driver;
|
||||
mac_store.mtu_ptr = buffer_ptr;
|
||||
mac_store.mtu_size = buffer_length;
|
||||
|
||||
if (driver->phy_driver->link_type == PHY_LINK_PPP) {
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 8);
|
||||
} else {
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
|
||||
}
|
||||
if (mac_store.tasklet_id == -1) {
|
||||
mac_store.tasklet_id = eventOS_event_handler_create(ðernet_mac_tasklet, ETH_INIT_EVENT);
|
||||
}
|
||||
arm_net_phy_init(driver->phy_driver, ð_mac_net_phy_rx, ð_mac_net_phy_tx_done);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static void ethernet_mac_tasklet(arm_event_s *event)
|
||||
{
|
||||
uint8_t event_type = event->event_type;
|
||||
|
||||
switch (event_type) {
|
||||
case ETH_DATA_IND_EVENT: {
|
||||
eth_data_ind_t *data_ind = event->data_ptr;
|
||||
mac_store.mac_api->data_ind_cb(mac_store.mac_api, data_ind);
|
||||
ns_dyn_mem_free(((eth_data_ind_t *)event->data_ptr)->msdu);
|
||||
ns_dyn_mem_free(event->data_ptr);
|
||||
break;
|
||||
}
|
||||
case ETH_DATA_CNF_EVENT: {
|
||||
eth_data_conf_t *data_conf = event->data_ptr;
|
||||
mac_store.mac_api->data_conf_cb(mac_store.mac_api, data_conf);
|
||||
ns_dyn_mem_free(event->data_ptr);
|
||||
mac_store.active_data_request = false;
|
||||
break;
|
||||
}
|
||||
case ETH_INIT_EVENT:
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int8_t eth_mac_api_init(eth_mac_api_t *api, eth_mac_data_confirm *conf_cb, eth_mac_data_indication *ind_cb, uint8_t parent_id)
|
||||
{
|
||||
if (mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
eth_mac_api_t *cur = mac_store.mac_api;
|
||||
cur->data_conf_cb = conf_cb;
|
||||
cur->data_ind_cb = ind_cb;
|
||||
cur->parent_id = parent_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void data_req(const eth_mac_api_t *api, const eth_data_req_t *data)
|
||||
{
|
||||
if (mac_store.mac_api != api || !mac_store.dev_driver->phy_driver || !data || !data->msduLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *data_ptr;
|
||||
uint16_t data_length;
|
||||
|
||||
//Build header
|
||||
switch (mac_store.dev_driver->phy_driver->link_type) {
|
||||
case PHY_LINK_ETHERNET_TYPE:
|
||||
|
||||
if (data->msduLength + ETHERNET_HDRLEN > mac_store.mtu_size || !data->dstAddress || !data->srcAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
data_ptr = mac_store.mtu_ptr;
|
||||
data_length = data->msduLength + ETHERNET_HDRLEN;
|
||||
memcpy(data_ptr + ETHERNET_HDROFF_DST_ADDR, data->dstAddress, 6);
|
||||
memcpy(data_ptr + ETHERNET_HDROFF_SRC_ADDR, data->srcAddress, 6);
|
||||
common_write_16_bit(data->etehernet_type, data_ptr + ETHERNET_HDROFF_TYPE);
|
||||
memcpy(data_ptr + ETHERNET_HDRLEN, data->msdu, data->msduLength);
|
||||
break;
|
||||
|
||||
case PHY_LINK_TUN:
|
||||
if (data->msduLength + 4 > mac_store.mtu_size) {
|
||||
return;
|
||||
}
|
||||
data_ptr = mac_store.mtu_ptr;
|
||||
/* TUN header
|
||||
* [ TUN FLAGS 2B | PROTOCOL 2B | PAYLOAD ]
|
||||
* Tun flags may be 0, and protocol is same as in ether-type field, so
|
||||
* replace flags with e.g. IFF_TUN and packet is converted to TUN frame
|
||||
*/
|
||||
common_write_16_bit(0, data_ptr);
|
||||
common_write_16_bit(data->etehernet_type, data_ptr + 2);
|
||||
memcpy(data_ptr + 4, data->msdu, data->msduLength);
|
||||
data_length = data->msduLength + 4;
|
||||
break;
|
||||
|
||||
default: //SLIP
|
||||
data_ptr = data->msdu;
|
||||
data_length = data->msduLength;
|
||||
break;
|
||||
}
|
||||
|
||||
mac_store.active_data_request = true;
|
||||
mac_store.dev_driver->phy_driver->tx(data_ptr, data_length, 0, PHY_LAYER_PAYLOAD);
|
||||
}
|
||||
|
||||
static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id)
|
||||
{
|
||||
arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
|
||||
if (!data_ptr || !driver || driver != mac_store.dev_driver) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ns_monitor_packet_allocation_allowed()) {
|
||||
// stack can not handle new packets for routing
|
||||
return -1;
|
||||
}
|
||||
|
||||
eth_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(eth_data_ind_t));
|
||||
if (!data_ind) {
|
||||
return -1;
|
||||
}
|
||||
memset(data_ind, 0, sizeof(eth_data_ind_t));
|
||||
|
||||
if (driver->phy_driver->link_type == PHY_LINK_ETHERNET_TYPE) {
|
||||
if (data_len < ETHERNET_HDRLEN + 1) {
|
||||
ns_dyn_mem_free(data_ind);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data_ind->dstAddress, data_ptr + ETHERNET_HDROFF_DST_ADDR, 6);
|
||||
memcpy(data_ind->srcAddress, data_ptr + ETHERNET_HDROFF_SRC_ADDR, 6);
|
||||
|
||||
data_ind->etehernet_type = common_read_16_bit(data_ptr + ETHERNET_HDROFF_TYPE);
|
||||
|
||||
data_ptr += ETHERNET_HDRLEN;
|
||||
data_len -= ETHERNET_HDRLEN;
|
||||
|
||||
} else if (driver->phy_driver->link_type == PHY_LINK_TUN) {
|
||||
if (data_len < 5) {
|
||||
ns_dyn_mem_free(data_ind);
|
||||
return -1;
|
||||
}
|
||||
/* TUN header
|
||||
* [ TUN FLAGS 2B | PROTOCOL 2B | PAYLOAD ]
|
||||
* Protocol is ether-type id.
|
||||
*/
|
||||
data_ind->etehernet_type = common_read_16_bit(data_ptr + 2);
|
||||
|
||||
data_len -= 4;
|
||||
data_ptr += 4;
|
||||
} else if (driver->phy_driver->link_type == PHY_LINK_SLIP || driver->phy_driver->link_type == PHY_LINK_PPP) {
|
||||
data_ind->etehernet_type = ETHERTYPE_IPV6;
|
||||
}
|
||||
|
||||
data_ind->msdu = ns_dyn_mem_temporary_alloc(data_len);
|
||||
if (!data_ind->msdu) {
|
||||
ns_dyn_mem_free(data_ind);
|
||||
return -1;
|
||||
}
|
||||
memcpy(data_ind->msdu, data_ptr, data_len);
|
||||
data_ind->msduLength = data_len;
|
||||
data_ind->dbm = dbm;
|
||||
data_ind->link_quality = link_quality;
|
||||
|
||||
arm_event_s event = {
|
||||
.receiver = mac_store.tasklet_id,
|
||||
.sender = 0,
|
||||
.event_id = 0,
|
||||
.data_ptr = data_ind,
|
||||
.event_type = ETH_DATA_IND_EVENT,
|
||||
.priority = ARM_LIB_HIGH_PRIORITY_EVENT,
|
||||
};
|
||||
|
||||
if (eventOS_event_send(&event)) {
|
||||
ns_dyn_mem_free(data_ind->msdu);
|
||||
ns_dyn_mem_free(data_ind);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t eth_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
|
||||
{
|
||||
(void)tx_handle;
|
||||
(void)cca_retry;
|
||||
(void)tx_retry;
|
||||
arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
|
||||
if (!driver) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mac_store.active_data_request) {
|
||||
mac_store.active_data_request = false;
|
||||
eth_data_conf_t *data_conf = ns_dyn_mem_temporary_alloc(sizeof(eth_data_conf_t));
|
||||
if (!data_conf) {
|
||||
return -1;
|
||||
}
|
||||
data_conf->status = status;
|
||||
arm_event_s event = {
|
||||
.receiver = mac_store.tasklet_id,
|
||||
.sender = 0,
|
||||
.event_id = 0,
|
||||
.data_ptr = data_conf,
|
||||
.event_type = ETH_DATA_CNF_EVENT,
|
||||
.priority = ARM_LIB_HIGH_PRIORITY_EVENT,
|
||||
};
|
||||
|
||||
return eventOS_event_send(&event);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t mac48_address_set(const eth_mac_api_t *api, const uint8_t *mac48)
|
||||
{
|
||||
if (!mac48 || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(mac_store.mac48_iid64, mac48, 6);
|
||||
phy_device_driver_s *driver = mac_store.dev_driver->phy_driver;
|
||||
if (driver->address_write) {
|
||||
driver->address_write(PHY_MAC_48BIT, mac_store.mac48_iid64);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t mac48_address_get(const eth_mac_api_t *api, uint8_t *mac48_buf)
|
||||
{
|
||||
if (!mac48_buf || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
|
||||
memcpy(mac48_buf, mac_store.mac48_iid64, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t iid64_address_set(const eth_mac_api_t *api, const uint8_t *iid64)
|
||||
{
|
||||
if (!iid64 || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(mac_store.mac48_iid64, iid64, 8);
|
||||
phy_device_driver_s *driver = mac_store.dev_driver->phy_driver;
|
||||
if (driver->address_write) {
|
||||
driver->address_write(PHY_MAC_48BIT, mac_store.mac48_iid64);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t iid64_address_get(const eth_mac_api_t *api, uint8_t *iid64_buf)
|
||||
{
|
||||
if (!iid64_buf || !api || mac_store.mac_api != api) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(&mac_store.mac48_iid64, mac_store.dev_driver->phy_driver->PHY_MAC, 8);
|
||||
memcpy(iid64_buf, mac_store.mac48_iid64, 8);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user