IgH EtherCAT Master  1.6.1
mailbox.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
4  *
5  * This file is part of the IgH EtherCAT Master.
6  *
7  * The IgH EtherCAT Master is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version 2, as
9  * published by the Free Software Foundation.
10  *
11  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with the IgH EtherCAT Master; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  ****************************************************************************/
21 
27 /****************************************************************************/
28 
29 #include <linux/slab.h>
30 #include <linux/delay.h>
31 
32 #include "mailbox.h"
33 #include "datagram.h"
34 #include "master.h"
35 
36 /****************************************************************************/
37 
43 uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave,
44  ec_datagram_t *datagram,
45  uint8_t type,
46  size_t size
47  )
48 {
49  size_t total_size;
50  int ret;
51 
52  if (unlikely(!slave->sii.mailbox_protocols)) {
53  EC_SLAVE_ERR(slave, "Slave does not support mailbox"
54  " communication!\n");
55  return ERR_PTR(-EPROTONOSUPPORT);
56  }
57 
58  total_size = EC_MBOX_HEADER_SIZE + size;
59 
60  if (unlikely(total_size > slave->configured_rx_mailbox_size)) {
61  EC_SLAVE_ERR(slave, "Data size (%zu) does not fit in mailbox (%u)!\n",
62  total_size, slave->configured_rx_mailbox_size);
63  return ERR_PTR(-ENOBUFS);
64  }
65 
66  ret = ec_datagram_fpwr(datagram, slave->station_address,
69  if (ret)
70  return ERR_PTR(ret);
71 
72  EC_WRITE_U16(datagram->data, size); // mailbox service data length
73  EC_WRITE_U16(datagram->data + 2, slave->station_address); // station addr.
74  EC_WRITE_U8 (datagram->data + 4, 0x00); // channel & priority
75  EC_WRITE_U8 (datagram->data + 5, type); // underlying protocol type
76 
77  return datagram->data + EC_MBOX_HEADER_SIZE;
78 }
79 
80 /****************************************************************************/
81 
89  ec_datagram_t *datagram
90  )
91 {
92  int ret = ec_datagram_fprd(datagram, slave->station_address, 0x808, 8);
93  if (ret)
94  return ret;
95 
96  ec_datagram_zero(datagram);
97  return 0;
98 }
99 
100 /****************************************************************************/
101 
107 int ec_slave_mbox_check(const ec_datagram_t *datagram )
108 {
109  return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
110 }
111 
112 /****************************************************************************/
113 
120  ec_datagram_t *datagram
121  )
122 {
123  int ret = ec_datagram_fprd(datagram, slave->station_address,
126  if (ret)
127  return ret;
128 
129  ec_datagram_zero(datagram);
130  return 0;
131 }
132 
133 /****************************************************************************/
134 
140  {0x00000001, "MBXERR_SYNTAX"},
141  {0x00000002, "MBXERR_UNSUPPORTEDPROTOCOL"},
142  {0x00000003, "MBXERR_INVAILDCHANNEL"},
143  {0x00000004, "MBXERR_SERVICENOTSUPPORTED"},
144  {0x00000005, "MBXERR_INVALIDHEADER"},
145  {0x00000006, "MBXERR_SIZETOOSHORT"},
146  {0x00000007, "MBXERR_NOMOREMEMORY"},
147  {0x00000008, "MBXERR_INVALIDSIZE"},
148  {}
149 };
150 
151 /****************************************************************************/
152 
157 uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave,
158  const ec_datagram_t *datagram,
159  uint8_t *type,
160  size_t *size
161  )
162 {
163  size_t data_size;
164 
165  data_size = EC_READ_U16(datagram->data);
166 
167  if (data_size + EC_MBOX_HEADER_SIZE > slave->configured_tx_mailbox_size) {
168  EC_SLAVE_ERR(slave, "Corrupt mailbox response received!\n");
169  ec_print_data(datagram->data, slave->configured_tx_mailbox_size);
170  return ERR_PTR(-EPROTO);
171  }
172 
173  *type = EC_READ_U8(datagram->data + 5) & 0x0F;
174  *size = data_size;
175 
176  if (*type == 0x00) {
177  const ec_code_msg_t *mbox_msg;
178  uint16_t code = EC_READ_U16(datagram->data + 8);
179 
180  EC_SLAVE_ERR(slave, "Mailbox error response received - ");
181 
182  for (mbox_msg = mbox_error_messages; mbox_msg->code; mbox_msg++) {
183  if (mbox_msg->code != code)
184  continue;
185  printk(KERN_CONT "Code 0x%04X: \"%s\".\n",
186  mbox_msg->code, mbox_msg->message);
187  break;
188  }
189 
190  if (!mbox_msg->code) {
191  printk(KERN_CONT "Unknown error reply code 0x%04X.\n", code);
192  }
193 
194  if (slave->master->debug_level)
195  ec_print_data(datagram->data + EC_MBOX_HEADER_SIZE, data_size);
196 
197  return ERR_PTR(-EPROTO);
198  }
199 
200  return datagram->data + EC_MBOX_HEADER_SIZE;
201 }
202 
203 /****************************************************************************/
uint8_t * ec_slave_mbox_prepare_send(const ec_slave_t *slave, ec_datagram_t *datagram, uint8_t type, size_t size)
Prepares a mailbox-send datagram.
Definition: mailbox.c:43
ec_sii_t sii
Extracted SII data.
Definition: slave.h:215
uint8_t * ec_slave_mbox_fetch(const ec_slave_t *slave, const ec_datagram_t *datagram, uint8_t *type, size_t *size)
Processes received mailbox data.
Definition: mailbox.c:157
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:193
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:191
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram to fetch mailbox data.
Definition: mailbox.c:119
uint32_t code
Code.
Definition: globals.h:276
EtherCAT datagram.
Definition: datagram.h:79
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3137
uint16_t station_address
Configured station address.
Definition: slave.h:176
const char * message
Message belonging to code.
Definition: globals.h:277
EtherCAT master structure.
EtherCAT slave.
Definition: slave.h:168
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:170
Code/Message pair.
Definition: globals.h:275
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:139
unsigned int debug_level
Master debug level.
Definition: master.h:275
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:68
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:3154
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:187
ec_master_t * master
Master owning the slave.
Definition: slave.h:170
int ec_datagram_fpwr(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPWR datagram.
Definition: datagram.c:290
int ec_datagram_fprd(ec_datagram_t *datagram, uint16_t configured_address, uint16_t mem_address, size_t data_size)
Initializes an EtherCAT FPRD datagram.
Definition: datagram.c:265
EtherCAT datagram structure.
const ec_code_msg_t mbox_error_messages[]
Mailbox error codes.
Definition: mailbox.c:139
#define EC_MBOX_HEADER_SIZE
Mailbox header size.
Definition: globals.h:83
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:344
int ec_slave_mbox_prepare_check(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram for checking the mailbox state.
Definition: mailbox.c:88
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3045
Mailbox functionality.
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:189
uint8_t * data
Datagram payload.
Definition: datagram.h:88
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:3029
int ec_slave_mbox_check(const ec_datagram_t *datagram)
Processes a mailbox state checking datagram.
Definition: mailbox.c:107