IgH EtherCAT Master  1.6.0-rc1
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.mailbox_protocols)) {
61  EC_SLAVE_ERR(slave, "Slave does not support mailbox"
62  " communication!\n");
63  return ERR_PTR(-EPROTONOSUPPORT);
64  }
65 
66  total_size = EC_MBOX_HEADER_SIZE + size;
67 
68  if (unlikely(total_size > slave->configured_rx_mailbox_size)) {
69  EC_SLAVE_ERR(slave, "Data size (%zu) does not fit in mailbox (%u)!\n",
70  total_size, slave->configured_rx_mailbox_size);
71  return ERR_PTR(-EOVERFLOW);
72  }
73 
74  ret = ec_datagram_fpwr(datagram, slave->station_address,
77  if (ret) {
78  return ERR_PTR(ret);
79  }
80 
81  EC_WRITE_U16(datagram->data, size); // mailbox service data length
82  EC_WRITE_U16(datagram->data + 2, slave->station_address); // station addr.
83  EC_WRITE_U8 (datagram->data + 4, 0x00); // channel & priority
84  EC_WRITE_U8 (datagram->data + 5, type); // underlying protocol type
85 
86  return datagram->data + EC_MBOX_HEADER_SIZE;
87 }
88 
89 /*****************************************************************************/
90 
98  ec_datagram_t *datagram
99  )
100 {
101  int ret = ec_datagram_fprd(datagram, slave->station_address, 0x808, 8);
102  if (ret)
103  return ret;
104 
105  ec_datagram_zero(datagram);
106  return 0;
107 }
108 
109 /*****************************************************************************/
110 
116 int ec_slave_mbox_check(const ec_datagram_t *datagram )
117 {
118  return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
119 }
120 
121 /*****************************************************************************/
122 
129  ec_datagram_t *datagram
130  )
131 {
132  int ret = ec_datagram_fprd(datagram, slave->station_address,
135  if (ret)
136  return ret;
137 
138  ec_datagram_zero(datagram);
139  return 0;
140 }
141 
142 /*****************************************************************************/
143 
149  {0x00000001, "MBXERR_SYNTAX"},
150  {0x00000002, "MBXERR_UNSUPPORTEDPROTOCOL"},
151  {0x00000003, "MBXERR_INVAILDCHANNEL"},
152  {0x00000004, "MBXERR_SERVICENOTSUPPORTED"},
153  {0x00000005, "MBXERR_INVALIDHEADER"},
154  {0x00000006, "MBXERR_SIZETOOSHORT"},
155  {0x00000007, "MBXERR_NOMOREMEMORY"},
156  {0x00000008, "MBXERR_INVALIDSIZE"},
157  {}
158 };
159 
160 /*****************************************************************************/
161 
166 uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave,
167  ec_mbox_data_t *response_data,
168  uint8_t *type,
169  size_t *size
170  )
171 {
172  size_t data_size;
173 
174  if (!response_data->data) {
175  EC_SLAVE_ERR(slave, "No mailbox response data received!\n");
176  return ERR_PTR(-EPROTO);
177  }
178 
179  data_size = EC_READ_U16(response_data->data);
180 
181  if (data_size + EC_MBOX_HEADER_SIZE > slave->configured_tx_mailbox_size) {
182  EC_SLAVE_ERR(slave, "Corrupt mailbox response received!\n");
183  ec_print_data(response_data->data, slave->configured_tx_mailbox_size);
184  return ERR_PTR(-EPROTO);
185  }
186 
187 #if 0
188  if (slave->master->debug_level) {
189  EC_SLAVE_DBG(slave, 1, "Mailbox data:\n");
190  ec_print_data(datagram->data, EC_MBOX_HEADER_SIZE + data_size);
191  }
192 #endif
193 
194  *type = EC_READ_U8(response_data->data + 5) & 0x0F;
195  *size = data_size;
196 
197  if (*type == 0x00) {
198  const ec_code_msg_t *mbox_msg;
199  uint16_t code = EC_READ_U16(response_data->data + 8);
200 
201  EC_SLAVE_ERR(slave, "Mailbox error response received - ");
202 
203  for (mbox_msg = mbox_error_messages; mbox_msg->code; mbox_msg++) {
204  if (mbox_msg->code != code)
205  continue;
206  printk(KERN_CONT "Code 0x%04X: \"%s\".\n",
207  mbox_msg->code, mbox_msg->message);
208  break;
209  }
210 
211  if (!mbox_msg->code) {
212  printk(KERN_CONT "Unknown error reply code 0x%04X.\n", code);
213  }
214 
215  if (slave->master->debug_level && data_size > 0) {
216  ec_print_data(response_data->data + EC_MBOX_HEADER_SIZE, data_size);
217  }
218 
219  return ERR_PTR(-EPROTO);
220  }
221 
222  return response_data->data + EC_MBOX_HEADER_SIZE;
223 }
224 
225 /*****************************************************************************/
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
ec_sii_t sii
Extracted SII data.
Definition: slave.h:246
uint16_t configured_tx_mailbox_size
Configured send mailbox size.
Definition: slave.h:224
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:107
uint16_t configured_tx_mailbox_offset
Configured send mailbox offset.
Definition: slave.h:222
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:128
uint32_t code
Code.
Definition: globals.h:282
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:2338
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:166
uint16_t station_address
Configured station address.
Definition: slave.h:207
const char * message
Message belonging to code.
Definition: globals.h:283
EtherCAT master structure.
EtherCAT slave.
Definition: slave.h:199
void ec_datagram_zero(ec_datagram_t *datagram)
Fills the datagram payload memory with zeros.
Definition: datagram.c:179
Code/Message pair.
Definition: globals.h:281
uint16_t mailbox_protocols
Supported mailbox protocols.
Definition: slave.h:170
unsigned int debug_level
Master debug level.
Definition: master.h:285
#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:2355
uint16_t configured_rx_mailbox_offset
Configured receive mailbox offset.
Definition: slave.h:218
ec_master_t * master
Master owning the slave.
Definition: slave.h:201
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:299
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:274
EtherCAT datagram structure.
const ec_code_msg_t mbox_error_messages[]
Mailbox error codes.
Definition: mailbox.c:148
#define EC_MBOX_HEADER_SIZE
Mailbox header size.
Definition: globals.h:89
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:345
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:97
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2250
Mailbox functionality.
uint16_t configured_rx_mailbox_size
Configured receive mailbox size.
Definition: slave.h:220
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:2234
int ec_slave_mbox_check(const ec_datagram_t *datagram)
Processes a mailbox state checking datagram.
Definition: mailbox.c:116