00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00035
00036
00037 #include <linux/slab.h>
00038 #include <linux/delay.h>
00039
00040 #include "mailbox.h"
00041 #include "datagram.h"
00042 #include "master.h"
00043
00044
00045
00051 uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave,
00052 ec_datagram_t *datagram,
00053 uint8_t type,
00054 size_t size
00055 )
00056 {
00057 size_t total_size;
00058 int ret;
00059
00060 if (unlikely(!slave->sii.mailbox_protocols)) {
00061 EC_SLAVE_ERR(slave, "Slave does not support mailbox"
00062 " communication!\n");
00063 return ERR_PTR(-EPROTONOSUPPORT);
00064 }
00065
00066 total_size = EC_MBOX_HEADER_SIZE + size;
00067
00068 if (unlikely(total_size > slave->configured_rx_mailbox_size)) {
00069 EC_SLAVE_ERR(slave, "Data size (%zu) does not fit in mailbox (%u)!\n",
00070 total_size, slave->configured_rx_mailbox_size);
00071 return ERR_PTR(-EOVERFLOW);
00072 }
00073
00074 ret = ec_datagram_fpwr(datagram, slave->station_address,
00075 slave->configured_rx_mailbox_offset,
00076 slave->configured_rx_mailbox_size);
00077 if (ret)
00078 return ERR_PTR(ret);
00079
00080 EC_WRITE_U16(datagram->data, size);
00081 EC_WRITE_U16(datagram->data + 2, slave->station_address);
00082 EC_WRITE_U8 (datagram->data + 4, 0x00);
00083 EC_WRITE_U8 (datagram->data + 5, type);
00084
00085 return datagram->data + EC_MBOX_HEADER_SIZE;
00086 }
00087
00088
00089
00096 int ec_slave_mbox_prepare_check(const ec_slave_t *slave,
00097 ec_datagram_t *datagram
00098 )
00099 {
00100 int ret = ec_datagram_fprd(datagram, slave->station_address, 0x808, 8);
00101 if (ret)
00102 return ret;
00103
00104 ec_datagram_zero(datagram);
00105 return 0;
00106 }
00107
00108
00109
00115 int ec_slave_mbox_check(const ec_datagram_t *datagram )
00116 {
00117 return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
00118 }
00119
00120
00121
00127 int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave,
00128 ec_datagram_t *datagram
00129 )
00130 {
00131 int ret = ec_datagram_fprd(datagram, slave->station_address,
00132 slave->configured_tx_mailbox_offset,
00133 slave->configured_tx_mailbox_size);
00134 if (ret)
00135 return ret;
00136
00137 ec_datagram_zero(datagram);
00138 return 0;
00139 }
00140
00141
00142
00147 const ec_code_msg_t mbox_error_messages[] = {
00148 {0x00000001, "MBXERR_SYNTAX"},
00149 {0x00000002, "MBXERR_UNSUPPORTEDPROTOCOL"},
00150 {0x00000003, "MBXERR_INVAILDCHANNEL"},
00151 {0x00000004, "MBXERR_SERVICENOTSUPPORTED"},
00152 {0x00000005, "MBXERR_INVALIDHEADER"},
00153 {0x00000006, "MBXERR_SIZETOOSHORT"},
00154 {0x00000007, "MBXERR_NOMOREMEMORY"},
00155 {0x00000008, "MBXERR_INVALIDSIZE"},
00156 {}
00157 };
00158
00159
00160
00165 uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave,
00166 const ec_datagram_t *datagram,
00167 uint8_t *type,
00168 size_t *size
00169 )
00170 {
00171 size_t data_size;
00172
00173 data_size = EC_READ_U16(datagram->data);
00174
00175 if (data_size + EC_MBOX_HEADER_SIZE > slave->configured_tx_mailbox_size) {
00176 EC_SLAVE_ERR(slave, "Corrupt mailbox response received!\n");
00177 ec_print_data(datagram->data, slave->configured_tx_mailbox_size);
00178 return ERR_PTR(-EPROTO);
00179 }
00180
00181 *type = EC_READ_U8(datagram->data + 5) & 0x0F;
00182 *size = data_size;
00183
00184 if (*type == 0x00) {
00185 const ec_code_msg_t *mbox_msg;
00186 uint16_t code = EC_READ_U16(datagram->data + 8);
00187
00188 EC_SLAVE_ERR(slave, "Mailbox error response received - ");
00189
00190 for (mbox_msg = mbox_error_messages; mbox_msg->code; mbox_msg++) {
00191 if (mbox_msg->code != code)
00192 continue;
00193 printk("Code 0x%04X: \"%s\".\n",
00194 mbox_msg->code, mbox_msg->message);
00195 break;
00196 }
00197
00198 if (!mbox_msg->code)
00199 printk("Unknown error reply code 0x%04X.\n", code);
00200
00201 if (slave->master->debug_level)
00202 ec_print_data(datagram->data + EC_MBOX_HEADER_SIZE, data_size);
00203
00204 return ERR_PTR(-EPROTO);
00205 }
00206
00207 return datagram->data + EC_MBOX_HEADER_SIZE;
00208 }
00209
00210