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
00030
00031
00032
00033
00039
00040
00041 #include <linux/slab.h>
00042 #include <linux/delay.h>
00043
00044 #include "mailbox.h"
00045 #include "datagram.h"
00046 #include "master.h"
00047
00048
00049
00055 uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave,
00056 ec_datagram_t *datagram,
00057 uint8_t type,
00058 size_t size
00059 )
00060 {
00061 size_t total_size;
00062
00063 if (unlikely(!slave->sii_mailbox_protocols)) {
00064 EC_ERR("Slave %i does not support mailbox communication!\n",
00065 slave->ring_position);
00066 return NULL;
00067 }
00068
00069 total_size = size + 6;
00070 if (unlikely(total_size > slave->sii_rx_mailbox_size)) {
00071 EC_ERR("Data size does not fit in mailbox!\n");
00072 return NULL;
00073 }
00074
00075 if (ec_datagram_npwr(datagram, slave->station_address,
00076 slave->sii_rx_mailbox_offset,
00077 slave->sii_rx_mailbox_size))
00078 return NULL;
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 + 6;
00086 }
00087
00088
00089
00095 int ec_slave_mbox_prepare_check(const ec_slave_t *slave,
00096 ec_datagram_t *datagram
00097 )
00098 {
00099
00100 if (ec_datagram_nprd(datagram, slave->station_address, 0x808, 8))
00101 return -1;
00102
00103 return 0;
00104 }
00105
00106
00107
00113 int ec_slave_mbox_check(const ec_datagram_t *datagram )
00114 {
00115 return EC_READ_U8(datagram->data + 5) & 8 ? 1 : 0;
00116 }
00117
00118
00119
00125 int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave,
00126 ec_datagram_t *datagram
00127 )
00128 {
00129 if (ec_datagram_nprd(datagram, slave->station_address,
00130 slave->sii_tx_mailbox_offset,
00131 slave->sii_tx_mailbox_size)) return -1;
00132 return 0;
00133 }
00134
00135
00136
00142 uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave,
00143 ec_datagram_t *datagram,
00144 uint8_t type,
00145 size_t *size
00146 )
00147 {
00148 size_t data_size;
00149
00150 if ((EC_READ_U8(datagram->data + 5) & 0x0F) != type) {
00151 EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at"
00152 " slave %i!\n", EC_READ_U8(datagram->data + 5), type,
00153 slave->ring_position);
00154 return NULL;
00155 }
00156
00157 if ((data_size = EC_READ_U16(datagram->data)) >
00158 slave->sii_tx_mailbox_size - 6) {
00159 EC_ERR("Currupt mailbox response detected!\n");
00160 return NULL;
00161 }
00162
00163 *size = data_size;
00164 return datagram->data + 6;
00165 }
00166
00167
00168
00174 uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *slave,
00175 ec_datagram_t *datagram,
00176 size_t *size
00177 )
00178 {
00179 uint8_t type;
00180
00181 type = EC_READ_U8(datagram->data + 5);
00182
00183 if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00184 EC_ERR("Mailbox checking failed on slave %i!\n",
00185 slave->ring_position);
00186 return NULL;
00187 }
00188
00189 return ec_slave_mbox_simple_receive(slave, datagram, type, size);
00190 }
00191
00192
00193
00199 uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave,
00200 ec_datagram_t *datagram,
00201 uint8_t type,
00202 size_t *size
00203 )
00204 {
00205 cycles_t start, end, timeout;
00206
00207 start = get_cycles();
00208 timeout = (cycles_t) 100 * cpu_khz;
00209
00210 while (1)
00211 {
00212 if (ec_slave_mbox_prepare_check(slave, datagram)) return NULL;
00213 if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00214 EC_ERR("Mailbox checking failed on slave %i!\n",
00215 slave->ring_position);
00216 return NULL;
00217 }
00218
00219 end = get_cycles();
00220
00221 if (ec_slave_mbox_check(datagram))
00222 break;
00223
00224 if ((end - start) >= timeout) {
00225 EC_ERR("Mailbox check - Slave %i timed out.\n",
00226 slave->ring_position);
00227 return NULL;
00228 }
00229
00230 udelay(100);
00231 }
00232
00233 if (ec_slave_mbox_prepare_fetch(slave, datagram)) return NULL;
00234 if (unlikely(ec_master_simple_io(slave->master, datagram))) {
00235 EC_ERR("Mailbox receiving failed on slave %i!\n",
00236 slave->ring_position);
00237 return NULL;
00238 }
00239
00240 if (unlikely(slave->master->debug_level) > 1)
00241 EC_DBG("Mailbox receive took %ius.\n",
00242 ((unsigned int) (end - start) * 1000 / cpu_khz));
00243
00244 return ec_slave_mbox_fetch(slave, datagram, type, size);
00245 }
00246
00247