IgH EtherCAT Master  1.5.2
mailbox.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
6  *
7  * This file is part of the IgH EtherCAT Master.
8  *
9  * The IgH EtherCAT Master is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version 2, as
11  * published by the Free Software Foundation.
12  *
13  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with the IgH EtherCAT Master; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * ---
23  *
24  * The license mentioned above concerns the source code only. Using the
25  * EtherCAT technology and brand is only permitted in compliance with the
26  * industrial property and similar rights of Beckhoff Automation GmbH.
27  *
28  *****************************************************************************/
29 
35 /*****************************************************************************/
36 
37 #include <linux/slab.h>
38 #include <linux/delay.h>
39 
40 #include "mailbox.h"
41 #include "datagram.h"
42 #include "master.h"
43 
44 /*****************************************************************************/
45 
51 uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave,
52  ec_datagram_t *datagram,
53  uint8_t type,
54  size_t size
55  )
56 {
57  size_t total_size;
58  int ret;
59 
60  if (unlikely(!slave->sii_image)) {
61  EC_SLAVE_ERR(slave, "Slave cannot verify if mailbox communication"
62  " is supported!\n");
63  return ERR_PTR(-EAGAIN);
64  }
65 
66  if (unlikely(!slave->sii_image->sii.mailbox_protocols)) {
67  EC_SLAVE_ERR(slave, "Slave does not support mailbox"
68  " communication!\n");
69  return ERR_PTR(-EPROTONOSUPPORT);
70  }
71 
72  total_size = EC_MBOX_HEADER_SIZE + size;
73 
74  if (unlikely(total_size > slave->configured_rx_mailbox_size)) {
75  EC_SLAVE_ERR(slave, "Data size (%zu) does not fit in mailbox (%u)!\n",
76  total_size, slave->configured_rx_mailbox_size);
77  return ERR_PTR(-EOVERFLOW);
78  }
79 
80  ret = ec_datagram_fpwr(datagram, slave->station_address,
83  if (ret) {
84  return ERR_PTR(ret);
85  }
86 
87  EC_WRITE_U16(datagram->data, size); // mailbox service data length
88  EC_WRITE_U16(datagram->data + 2, slave->station_address); // station addr.
89  EC_WRITE_U8 (datagram->data + 4, 0x00); // channel & priority
90  EC_WRITE_U8 (datagram->data + 5, type); // underlying protocol type
91 
92  return datagram->data + EC_MBOX_HEADER_SIZE;
93 }
94 
95 /*****************************************************************************/
96 
104  ec_datagram_t *datagram
105  )
106 {
107  int ret = ec_datagram_fprd(datagram, slave->station_address, 0x808, 8);
108  if (ret)
109  return ret;
110 
111  ec_datagram_zero(datagram);
112  return 0;
113 }
114 
115 /*****************************************************************************/
116 
122 int ec_slave_mbox_check(const ec_datagram_t *datagram )
123 {
124  return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
125 }
126 
127 /*****************************************************************************/
128 
135  ec_datagram_t *datagram
136  )
137 {
138  int ret = ec_datagram_fprd(datagram, slave->station_address,
141  if (ret)
142  return ret;
143 
144  ec_datagram_zero(datagram);
145  return 0;
146 }
147 
148 /*****************************************************************************/
149 
155  {0x00000001, "MBXERR_SYNTAX"},
156  {0x00000002, "MBXERR_UNSUPPORTEDPROTOCOL"},
157  {0x00000003, "MBXERR_INVAILDCHANNEL"},
158  {0x00000004, "MBXERR_SERVICENOTSUPPORTED"},
159  {0x00000005, "MBXERR_INVALIDHEADER"},
160  {0x00000006, "MBXERR_SIZETOOSHORT"},
161  {0x00000007, "MBXERR_NOMOREMEMORY"},
162  {0x00000008, "MBXERR_INVALIDSIZE"},
163  {}
164 };
165 
166 /*****************************************************************************/
167 
172 uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave,
173  ec_mbox_data_t *response_data,
174  uint8_t *type,
175  size_t *size
176  )
177 {
178  size_t data_size;
179 
180  if (!response_data->data) {
181  EC_SLAVE_ERR(slave, "No mailbox response data received!\n");
182  return ERR_PTR(-EPROTO);
183  }
184 
185  data_size = EC_READ_U16(response_data->data);
186 
187  if (data_size + EC_MBOX_HEADER_SIZE > slave->configured_tx_mailbox_size) {
188  EC_SLAVE_ERR(slave, "Corrupt mailbox response received!\n");
189  ec_print_data(response_data->data, slave->configured_tx_mailbox_size);
190  return ERR_PTR(-EPROTO);
191  }
192 
193 #if 0
194  if (slave->master->debug_level) {
195  EC_SLAVE_DBG(slave, 1, "Mailbox data:\n");
196  ec_print_data(datagram->data, EC_MBOX_HEADER_SIZE + data_size);
197  }
198 #endif
199 
200  *type = EC_READ_U8(response_data->data + 5) & 0x0F;
201  *size = data_size;
202 
203  if (*type == 0x00) {
204  const ec_code_msg_t *mbox_msg;
205  uint16_t code = EC_READ_U16(response_data->data + 8);
206 
207  EC_SLAVE_ERR(slave, "Mailbox error response received - ");
208 
209  for (mbox_msg = mbox_error_messages; mbox_msg->code; mbox_msg++) {
210  if (mbox_msg->code != code)
211  continue;
212  printk(KERN_CONT "Code 0x%04X: \"%s\".\n",
213  mbox_msg->code, mbox_msg->message);
214  break;
215  }
216 
217  if (!mbox_msg->code) {
218  printk(KERN_CONT "Unknown error reply code 0x%04X.\n", code);
219  }
220 
221  if (slave->master->debug_level && data_size > 0) {
222  ec_print_data(response_data->data + EC_MBOX_HEADER_SIZE, data_size);
223  }
224 
225  return ERR_PTR(-EPROTO);
226  }
227 
228  return response_data->data + EC_MBOX_HEADER_SIZE;
229 }
230 
231 /*****************************************************************************/
uint8_t * data
Mailbox response data.
Definition: datagram.h:123
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:51
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:248
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:108
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:246
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:134
uint32_t code
Code.
Definition: globals.h:314
EtherCAT mailbox response data.
Definition: datagram.h:122
EtherCAT datagram.
Definition: datagram.h:88
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2642
uint8_t * ec_slave_mbox_fetch(const ec_slave_t *slave, ec_mbox_data_t *response_data, uint8_t *type, size_t *size)
Processes received mailbox data.
Definition: mailbox.c:172
uint16_t station_address
Configured station address.
Definition: slave.h:222
const char * message
Message belonging to code.
Definition: globals.h:315
EtherCAT master structure.
EtherCAT slave.
Definition: slave.h:214
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:179
ec_sii_image_t * sii_image
Current complete SII image.
Definition: slave.h:267
Code/Message pair.
Definition: globals.h:313
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:172
unsigned int debug_level
Master debug level.
Definition: master.h:310
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:77
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2659
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:242
ec_master_t * master
Master owning the slave.
Definition: slave.h:216
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:320
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:295
EtherCAT datagram structure.
const ec_code_msg_t mbox_error_messages[]
Mailbox error codes.
Definition: mailbox.c:154
#define EC_MBOX_HEADER_SIZE
Mailbox header size.
Definition: globals.h:100
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:355
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:103
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2554
Mailbox functionality.
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:244
uint8_t * data
Datagram payload.
Definition: datagram.h:95
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2538
ec_sii_t sii
Extracted SII data.
Definition: slave.h:207
int ec_slave_mbox_check(const ec_datagram_t *datagram)
Processes a mailbox state checking datagram.
Definition: mailbox.c:122