Applied 0020-eoe-ip.patch

This commit is contained in:
Florian Pose 2022-06-23 12:39:52 +02:00
parent 5f84d54890
commit 8896d3b879
8 changed files with 94 additions and 72 deletions

View File

@ -726,9 +726,11 @@ void ec_mbox_prot_data_prealloc(
if ((size > 0) && (size <= EC_MAX_DATA_SIZE)) {
#ifdef EC_EOE
if (protocols & EC_MBOX_EOE) {
ec_mbox_data_prealloc(&slave->mbox_eoe_data, size);
ec_mbox_data_prealloc(&slave->mbox_eoe_frag_data, size);
ec_mbox_data_prealloc(&slave->mbox_eoe_init_data, size);
} else {
ec_mbox_data_clear(&slave->mbox_eoe_data);
ec_mbox_data_clear(&slave->mbox_eoe_frag_data);
ec_mbox_data_clear(&slave->mbox_eoe_init_data);
}
#endif
if (protocols & EC_MBOX_COE) {

View File

@ -409,7 +409,7 @@ int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */)
return PTR_ERR(data);
}
EC_WRITE_U8 (data, EC_EOE_FRAMETYPE_INIT_REQ); // Initiate EoE Request
EC_WRITE_U8 (data, EC_EOE_TYPE_FRAME_FRAG); // Initiate EoE Tx Request
EC_WRITE_U8 (data + 1, last_fragment);
EC_WRITE_U16(data + 2, ((eoe->tx_fragment_number & 0x3F) |
(complete_offset & 0x3F) << 6 |
@ -542,7 +542,7 @@ void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */)
eoe->rx_idle = 1;
ec_read_mbox_lock_clear(eoe->slave);
// check that data is not already received by another read request
if (eoe->slave->mbox_eoe_data.payload_size > 0) {
if (eoe->slave->mbox_eoe_frag_data.payload_size > 0) {
eoe->state = ec_eoe_state_rx_fetch_data;
eoe->state(eoe);
} else {
@ -593,7 +593,7 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
void ec_eoe_state_rx_fetch_data(ec_eoe_t *eoe /**< EoE handler */)
{
size_t rec_size, data_size;
uint8_t *data, frame_type, last_fragment, time_appended, mbox_prot;
uint8_t *data, eoe_type, last_fragment, time_appended, mbox_prot;
uint8_t fragment_offset, fragment_number;
#if EOE_DEBUG_LEVEL >= 2
uint8_t frame_number;
@ -603,8 +603,8 @@ void ec_eoe_state_rx_fetch_data(ec_eoe_t *eoe /**< EoE handler */)
unsigned int i;
#endif
if (eoe->slave->mbox_eoe_data.payload_size > 0) {
eoe->slave->mbox_eoe_data.payload_size = 0;
if (eoe->slave->mbox_eoe_frag_data.payload_size > 0) {
eoe->slave->mbox_eoe_frag_data.payload_size = 0;
} else {
// initiate a new mailbox read check if required data is not available
if (!ec_read_mbox_locked(eoe->slave)) {
@ -615,7 +615,7 @@ void ec_eoe_state_rx_fetch_data(ec_eoe_t *eoe /**< EoE handler */)
return;
}
data = ec_slave_mbox_fetch(eoe->slave, &eoe->slave->mbox_eoe_data,
data = ec_slave_mbox_fetch(eoe->slave, &eoe->slave->mbox_eoe_frag_data,
&mbox_prot, &rec_size);
if (IS_ERR(data)) {
eoe->stats.rx_errors++;
@ -637,13 +637,11 @@ void ec_eoe_state_rx_fetch_data(ec_eoe_t *eoe /**< EoE handler */)
return;
}
frame_type = EC_READ_U16(data) & 0x000F;
eoe_type = EC_READ_U8(data) & 0x0F;
if (frame_type != EC_EOE_FRAMETYPE_INIT_REQ) { // EoE Fragment Data
#if EOE_DEBUG_LEVEL >= 1
EC_SLAVE_WARN(eoe->slave, "%s: Other frame received."
" Dropping.\n", eoe->dev->name);
#endif
if (eoe_type != EC_EOE_TYPE_FRAME_FRAG) {
EC_SLAVE_ERR(eoe->slave, "%s: EoE iface handler received other EoE type"
" response (type %x). Dropping.\n", eoe->dev->name, eoe_type);
eoe->stats.rx_dropped++;
eoe->state = ec_eoe_state_tx_start;
return;

View File

@ -50,11 +50,12 @@
/** EoE frame types.
*/
enum {
EC_EOE_FRAMETYPE_INIT_REQ = 0x00, /** Initiate EoE Request. */
EC_EOE_FRAMETYPE_SET_IP_REQ = 0x02, /** Set IP Parameter Request. */
EC_EOE_FRAMETYPE_SET_IP_RES = 0x03, /** Set IP Parameter Response. */
EC_EOE_FRAMETYPE_FILT_REQ = 0x04, /** Set Address Filter Request. */
EC_EOE_FRAMETYPE_FILT_RES = 0x05, /** Set Address Filter Response. */
EC_EOE_TYPE_FRAME_FRAG = 0x00, /** EoE Frame Fragment Tx & Rx. */
EC_EOE_TYPE_TIMESTAMP_RES = 0x01, /** EoE Timestamp Response. */
EC_EOE_TYPE_INIT_REQ = 0x02, /** EoE Init, Set IP Parameter Request. */
EC_EOE_TYPE_INIT_RES = 0x03, /** EoE Init, Set IP Parameter Response. */
EC_EOE_TYPE_MACFILTER_REQ = 0x04, /** EoE Set MAC Address Filter Request. */
EC_EOE_TYPE_MACFILTER_RES = 0x05, /** EoE Set MAC Address Filter Response. */
};
/*****************************************************************************/

View File

@ -160,31 +160,20 @@ int ec_fsm_eoe_prepare_set(
ec_slave_t *slave = fsm->slave;
ec_master_t *master = slave->master;
ec_eoe_request_t *req = fsm->request;
size_t size = 8;
if (req->mac_address_included) {
size += ETH_ALEN;
}
if (req->ip_address_included) {
size += 4;
}
if (req->subnet_mask_included) {
size += 4;
}
if (req->gateway_included) {
size += 4;
}
if (req->dns_included) {
size += 4;
}
if (req->name_included) {
size += EC_MAX_HOSTNAME_SIZE;
}
// Note: based on wireshark packet filter it suggests that the EOE_INIT
// information is a fixed size with fixed information positions.
// see: packet-ecatmb.h and packet-ecatmb.c
// However, TwinCAT 2.1 testing also indicates that if a piece of
// information is missing then all subsequent items are ignored
// Also, if you want DHCP, then only set the mac address.
size_t size = 8 + // header + flags
ETH_ALEN + // mac address
4 + // ip address
4 + // subnet mask
4 + // gateway
4 + // dns server
EC_MAX_HOSTNAME_SIZE; // dns name
data = ec_slave_mbox_prepare_send(slave, datagram, EC_MBOX_TYPE_EOE,
size);
@ -192,9 +181,13 @@ int ec_fsm_eoe_prepare_set(
return PTR_ERR(data);
}
EC_WRITE_U8(data, EC_EOE_FRAMETYPE_SET_IP_REQ); // Set IP parameter req.
EC_WRITE_U8(data + 1, 0x01); // last fragment, no timestamps
EC_WRITE_U16(data + 2, 0x0000); // fragment no., offset, frame no.
// zero data
memset(data, 0, size);
// header
EC_WRITE_U8(data, EC_EOE_TYPE_INIT_REQ); // Set IP parameter req.
EC_WRITE_U8(data + 1, 0x00); // not used
EC_WRITE_U16(data + 2, 0x0000); // not used
EC_WRITE_U32(data + 4,
((req->mac_address_included != 0) << 0) |
@ -209,37 +202,37 @@ int ec_fsm_eoe_prepare_set(
if (req->mac_address_included) {
memcpy(cur, req->mac_address, ETH_ALEN);
cur += ETH_ALEN;
}
cur += ETH_ALEN;
if (req->ip_address_included) {
uint32_t swapped = htonl(req->ip_address);
memcpy(cur, &swapped, 4);
cur += 4;
}
cur += 4;
if (req->subnet_mask_included) {
uint32_t swapped = htonl(req->subnet_mask);
memcpy(cur, &swapped, 4);
cur += 4;
}
cur += 4;
if (req->gateway_included) {
uint32_t swapped = htonl(req->gateway);
memcpy(cur, &swapped, 4);
cur += 4;
}
cur += 4;
if (req->dns_included) {
uint32_t swapped = htonl(req->dns);
memcpy(cur, &swapped, 4);
cur += 4;
}
cur += 4;
if (req->name_included) {
memcpy(cur, req->name, EC_MAX_HOSTNAME_SIZE);
cur += EC_MAX_HOSTNAME_SIZE;
}
cur += EC_MAX_HOSTNAME_SIZE;
if (master->debug_level) {
EC_SLAVE_DBG(slave, 0, "Set IP parameter request:\n");
@ -376,7 +369,7 @@ void ec_fsm_eoe_set_ip_check(
unsigned long diff_ms;
// check that data is not already received by another read request
if (slave->mbox_eoe_data.payload_size > 0) {
if (slave->mbox_eoe_init_data.payload_size > 0) {
ec_read_mbox_lock_clear(slave);
fsm->state = ec_fsm_eoe_set_ip_response_data;
fsm->state(fsm, datagram);
@ -430,7 +423,7 @@ void ec_fsm_eoe_set_ip_response(
if (fsm->datagram->working_counter != 1) {
// only an error if data has not already been read by another read request
if (slave->mbox_eoe_data.payload_size == 0) {
if (slave->mbox_eoe_init_data.payload_size == 0) {
fsm->state = ec_fsm_eoe_error;
ec_read_mbox_lock_clear(slave);
EC_SLAVE_ERR(slave, "Reception of EoE read response failed: ");
@ -454,13 +447,13 @@ void ec_fsm_eoe_set_ip_response_data(
{
ec_slave_t *slave = fsm->slave;
ec_master_t *master = slave->master;
uint8_t *data, mbox_prot, frame_type;
uint8_t *data, mbox_prot, eoe_type;
size_t rec_size;
ec_eoe_request_t *req = fsm->request;
// process the data available or initiate a new mailbox read check
if (slave->mbox_eoe_data.payload_size > 0) {
slave->mbox_eoe_data.payload_size = 0;
if (slave->mbox_eoe_init_data.payload_size > 0) {
slave->mbox_eoe_init_data.payload_size = 0;
} else {
// initiate a new mailbox read check if required data is not available
if (ec_read_mbox_locked(slave)) {
@ -473,7 +466,7 @@ void ec_fsm_eoe_set_ip_response_data(
return;
}
data = ec_slave_mbox_fetch(slave, &slave->mbox_eoe_data, &mbox_prot, &rec_size);
data = ec_slave_mbox_fetch(slave, &slave->mbox_eoe_init_data, &mbox_prot, &rec_size);
if (IS_ERR(data)) {
fsm->state = ec_fsm_eoe_error;
return;
@ -499,11 +492,11 @@ void ec_fsm_eoe_set_ip_response_data(
return;
}
frame_type = EC_READ_U8(data) & 0x0f;
eoe_type = EC_READ_U8(data) & 0x0F;
if (frame_type != EC_EOE_FRAMETYPE_SET_IP_RES) {
EC_SLAVE_ERR(slave, "Received no set IP parameter response"
" (frame type %x).\n", frame_type);
if (eoe_type != EC_EOE_TYPE_INIT_RES) {
EC_SLAVE_ERR(slave, "EoE Init handler received other EoE type response"
" (type %x). Dropping.\n", eoe_type);
ec_print_data(data, rec_size);
fsm->state = ec_fsm_eoe_error;
return;

View File

@ -687,13 +687,13 @@ void ec_fsm_slave_state_eoe_request(
}
if (ec_fsm_eoe_success(&fsm->fsm_eoe)) {
req->state = EC_INT_REQUEST_SUCCESS;
EC_SLAVE_DBG(slave, 1, "Finished EoE request.\n");
req->state = EC_INT_REQUEST_SUCCESS;
EC_SLAVE_DBG(slave, 1, "Finished EoE request.\n");
}
else {
else {
req->state = EC_INT_REQUEST_FAILURE;
EC_SLAVE_ERR(slave, "Failed to process EoE request.\n");
}
}
wake_up_all(&slave->master->request_queue);
fsm->eoe_request = NULL;

View File

@ -1167,6 +1167,9 @@ void ec_master_receive_datagrams(
{
size_t frame_size, data_size;
uint8_t datagram_type, datagram_index, datagram_mbox_prot;
#ifdef EC_EOE
uint8_t eoe_type;
#endif
unsigned int cmd_follows, datagram_slave_addr, datagram_offset_addr, datagram_wc, matched;
const uint8_t *cur_data;
ec_datagram_t *datagram;
@ -1288,9 +1291,31 @@ void ec_master_receive_datagrams(
switch (datagram_mbox_prot) {
#ifdef EC_EOE
case EC_MBOX_TYPE_EOE:
if ((slave->mbox_eoe_data.data) && (data_size <= slave->mbox_eoe_data.data_size)) {
memcpy(slave->mbox_eoe_data.data, cur_data, data_size);
slave->mbox_eoe_data.payload_size = data_size;
// check EOE type and store in correct handlers mbox data cache
eoe_type = EC_READ_U8(cur_data + 6) & 0x0F;
switch (eoe_type) {
case EC_EOE_TYPE_FRAME_FRAG:
// EoE Frame Fragment handler
if ((slave->mbox_eoe_frag_data.data) && (data_size <= slave->mbox_eoe_frag_data.data_size)) {
memcpy(slave->mbox_eoe_frag_data.data, cur_data, data_size);
slave->mbox_eoe_frag_data.payload_size = data_size;
}
break;
case EC_EOE_TYPE_INIT_RES:
// EoE Init / Set IP response handler
if ((slave->mbox_eoe_init_data.data) && (data_size <= slave->mbox_eoe_init_data.data_size)) {
memcpy(slave->mbox_eoe_init_data.data, cur_data, data_size);
slave->mbox_eoe_init_data.payload_size = data_size;
}
break;
default:
EC_MASTER_DBG(master, 1, "Unhandled EoE protocol type from slave: %u Protocol: %u, Type: %x\n",
datagram_slave_addr, datagram_mbox_prot, eoe_type);
// copy instead received data into the datagram memory.
memcpy(datagram->data, cur_data, data_size);
break;
}
break;
#endif

View File

@ -169,7 +169,8 @@ void ec_slave_init(
rt_mutex_init(&slave->mbox_sem);
#ifdef EC_EOE
ec_mbox_data_init(&slave->mbox_eoe_data);
ec_mbox_data_init(&slave->mbox_eoe_frag_data);
ec_mbox_data_init(&slave->mbox_eoe_init_data);
#endif
ec_mbox_data_init(&slave->mbox_coe_data);
ec_mbox_data_init(&slave->mbox_foe_data);
@ -306,7 +307,8 @@ void ec_slave_clear(ec_slave_t *slave /**< EtherCAT slave */)
// free mailbox response data
#ifdef EC_EOE
ec_mbox_data_clear(&slave->mbox_eoe_data);
ec_mbox_data_clear(&slave->mbox_eoe_frag_data);
ec_mbox_data_clear(&slave->mbox_eoe_init_data);
#endif
ec_mbox_data_clear(&slave->mbox_coe_data);
ec_mbox_data_clear(&slave->mbox_foe_data);

View File

@ -261,7 +261,8 @@ struct ec_slave
struct rt_mutex mbox_sem; /**< Semaphore protecting the check_mbox variable. */
#ifdef EC_EOE
ec_mbox_data_t mbox_eoe_data; /**< Received mailbox data for EoE. */
ec_mbox_data_t mbox_eoe_frag_data; /**< Received mailbox data for EoE, type frame fragment. */
ec_mbox_data_t mbox_eoe_init_data; /**< Received mailbox data for EoE, type eoe init reponse. */
#endif
ec_mbox_data_t mbox_coe_data; /**< Received mailbox data for CoE. */
ec_mbox_data_t mbox_foe_data; /**< Received mailbox data for FoE. */