50 /** |
50 /** |
51 Prepares a mailbox-send command. |
51 Prepares a mailbox-send command. |
52 \return pointer to mailbox command data |
52 \return pointer to mailbox command data |
53 */ |
53 */ |
54 |
54 |
55 uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< slave */ |
55 uint8_t *ec_slave_mbox_prepare_send(const ec_slave_t *slave, /**< slave */ |
|
56 ec_command_t *command, /**< command */ |
56 uint8_t type, /**< mailbox protocol */ |
57 uint8_t type, /**< mailbox protocol */ |
57 size_t size /**< size of the data */ |
58 size_t size /**< size of the data */ |
58 ) |
59 ) |
59 { |
60 { |
60 ec_command_t *command = &slave->mbox_command; |
|
61 size_t total_size; |
61 size_t total_size; |
62 |
62 |
63 if (unlikely(!slave->sii_mailbox_protocols)) { |
63 if (unlikely(!slave->sii_mailbox_protocols)) { |
64 EC_ERR("Slave %i does not support mailbox communication!\n", |
64 EC_ERR("Slave %i does not support mailbox communication!\n", |
65 slave->ring_position); |
65 slave->ring_position); |
77 slave->sii_rx_mailbox_size)) |
77 slave->sii_rx_mailbox_size)) |
78 return NULL; |
78 return NULL; |
79 |
79 |
80 EC_WRITE_U16(command->data, size); // mailbox service data length |
80 EC_WRITE_U16(command->data, size); // mailbox service data length |
81 EC_WRITE_U16(command->data + 2, slave->station_address); // station address |
81 EC_WRITE_U16(command->data + 2, slave->station_address); // station address |
82 EC_WRITE_U8 (command->data + 4, 0x00); // hhannel & priority |
82 EC_WRITE_U8 (command->data + 4, 0x00); // channel & priority |
83 EC_WRITE_U8 (command->data + 5, type); // underlying protocol type |
83 EC_WRITE_U8 (command->data + 5, type); // underlying protocol type |
84 |
84 |
85 return command->data + 6; |
85 return command->data + 6; |
86 } |
86 } |
87 |
87 |
90 /** |
90 /** |
91 Prepares a command for checking the mailbox state. |
91 Prepares a command for checking the mailbox state. |
92 \return 0 in case of success, else < 0 |
92 \return 0 in case of success, else < 0 |
93 */ |
93 */ |
94 |
94 |
95 int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< slave */) |
95 int ec_slave_mbox_prepare_check(const ec_slave_t *slave, /**< slave */ |
96 { |
96 ec_command_t *command /**< command */ |
97 ec_command_t *command = &slave->mbox_command; |
97 ) |
98 |
98 { |
99 // FIXME: second sync manager? |
99 // FIXME: second sync manager? |
100 if (ec_command_nprd(command, slave->station_address, 0x808, 8)) |
100 if (ec_command_nprd(command, slave->station_address, 0x808, 8)) |
101 return -1; |
101 return -1; |
102 |
102 |
103 return 0; |
103 return 0; |
108 /** |
108 /** |
109 Processes a mailbox state checking command. |
109 Processes a mailbox state checking command. |
110 \return 0 in case of success, else < 0 |
110 \return 0 in case of success, else < 0 |
111 */ |
111 */ |
112 |
112 |
113 int ec_slave_mbox_check(const ec_slave_t *slave /**< slave */) |
113 int ec_slave_mbox_check(const ec_command_t *command /**< command */) |
114 { |
114 { |
115 return EC_READ_U8(slave->mbox_command.data + 5) & 8 ? 1 : 0; |
115 return EC_READ_U8(command->data + 5) & 8 ? 1 : 0; |
116 } |
116 } |
117 |
117 |
118 /*****************************************************************************/ |
118 /*****************************************************************************/ |
119 |
119 |
120 /** |
120 /** |
121 Prepares a command to fetch mailbox data. |
121 Prepares a command to fetch mailbox data. |
122 \return 0 in case of success, else < 0 |
122 \return 0 in case of success, else < 0 |
123 */ |
123 */ |
124 |
124 |
125 int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< slave */) |
125 int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, /**< slave */ |
126 { |
126 ec_command_t *command /**< command */ |
127 ec_command_t *command = &slave->mbox_command; |
127 ) |
128 |
128 { |
129 if (ec_command_nprd(command, slave->station_address, |
129 if (ec_command_nprd(command, slave->station_address, |
130 slave->sii_tx_mailbox_offset, |
130 slave->sii_tx_mailbox_offset, |
131 slave->sii_tx_mailbox_size)) return -1; |
131 slave->sii_tx_mailbox_size)) return -1; |
132 return 0; |
132 return 0; |
133 } |
133 } |
137 /** |
137 /** |
138 Processes received mailbox data. |
138 Processes received mailbox data. |
139 \return pointer to the received data |
139 \return pointer to the received data |
140 */ |
140 */ |
141 |
141 |
142 uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< slave */ |
142 uint8_t *ec_slave_mbox_fetch(const ec_slave_t *slave, /**< slave */ |
|
143 ec_command_t *command, /**< command */ |
143 uint8_t type, /**< expected mailbox protocol */ |
144 uint8_t type, /**< expected mailbox protocol */ |
144 size_t *size /**< size of the received data */ |
145 size_t *size /**< size of the received data */ |
145 ) |
146 ) |
146 { |
147 { |
147 ec_command_t *command = &slave->mbox_command; |
|
148 size_t data_size; |
148 size_t data_size; |
149 |
149 |
150 if ((EC_READ_U8(command->data + 5) & 0x0F) != type) { |
150 if ((EC_READ_U8(command->data + 5) & 0x0F) != type) { |
151 EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at" |
151 EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at" |
152 " slave %i!\n", EC_READ_U8(command->data + 5), type, |
152 " slave %i!\n", EC_READ_U8(command->data + 5), type, |
169 /** |
169 /** |
170 Sends a mailbox command and waits for its reception. |
170 Sends a mailbox command and waits for its reception. |
171 \return pointer to the received data |
171 \return pointer to the received data |
172 */ |
172 */ |
173 |
173 |
174 uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< slave */ |
174 uint8_t *ec_slave_mbox_simple_io(const ec_slave_t *slave, /**< slave */ |
|
175 ec_command_t *command, /**< command */ |
175 size_t *size /**< size of the received data */ |
176 size_t *size /**< size of the received data */ |
176 ) |
177 ) |
177 { |
178 { |
178 uint8_t type; |
179 uint8_t type; |
179 ec_command_t *command; |
180 |
180 |
|
181 command = &slave->mbox_command; |
|
182 type = EC_READ_U8(command->data + 5); |
181 type = EC_READ_U8(command->data + 5); |
183 |
182 |
184 if (unlikely(ec_master_simple_io(slave->master, command))) { |
183 if (unlikely(ec_master_simple_io(slave->master, command))) { |
185 EC_ERR("Mailbox checking failed on slave %i!\n", |
184 EC_ERR("Mailbox checking failed on slave %i!\n", |
186 slave->ring_position); |
185 slave->ring_position); |
187 return NULL; |
186 return NULL; |
188 } |
187 } |
189 |
188 |
190 return ec_slave_mbox_simple_receive(slave, type, size); |
189 return ec_slave_mbox_simple_receive(slave, command, type, size); |
191 } |
190 } |
192 |
191 |
193 /*****************************************************************************/ |
192 /*****************************************************************************/ |
194 |
193 |
195 /** |
194 /** |
196 Waits for the reception of a mailbox command. |
195 Waits for the reception of a mailbox command. |
197 \return pointer to the received data |
196 \return pointer to the received data |
198 */ |
197 */ |
199 |
198 |
200 uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< slave */ |
199 uint8_t *ec_slave_mbox_simple_receive(const ec_slave_t *slave, /**< slave */ |
|
200 ec_command_t *command, /**< command */ |
201 uint8_t type, /**< expected protocol */ |
201 uint8_t type, /**< expected protocol */ |
202 size_t *size /**< received data size */ |
202 size_t *size /**< received data size */ |
203 ) |
203 ) |
204 { |
204 { |
205 cycles_t start, end, timeout; |
205 cycles_t start, end, timeout; |
206 ec_command_t *command; |
206 |
207 |
|
208 command = &slave->mbox_command; |
|
209 start = get_cycles(); |
207 start = get_cycles(); |
210 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
208 timeout = (cycles_t) 100 * cpu_khz; // 100ms |
211 |
209 |
212 while (1) |
210 while (1) |
213 { |
211 { |
214 if (ec_slave_mbox_prepare_check(slave)) return NULL; |
212 if (ec_slave_mbox_prepare_check(slave, command)) return NULL; |
215 if (unlikely(ec_master_simple_io(slave->master, command))) { |
213 if (unlikely(ec_master_simple_io(slave->master, command))) { |
216 EC_ERR("Mailbox checking failed on slave %i!\n", |
214 EC_ERR("Mailbox checking failed on slave %i!\n", |
217 slave->ring_position); |
215 slave->ring_position); |
218 return NULL; |
216 return NULL; |
219 } |
217 } |
220 |
218 |
221 end = get_cycles(); |
219 end = get_cycles(); |
222 |
220 |
223 if (ec_slave_mbox_check(slave)) |
221 if (ec_slave_mbox_check(command)) |
224 break; // proceed with receiving data |
222 break; // proceed with receiving data |
225 |
223 |
226 if ((end - start) >= timeout) { |
224 if ((end - start) >= timeout) { |
227 EC_ERR("Mailbox check - Slave %i timed out.\n", |
225 EC_ERR("Mailbox check - Slave %i timed out.\n", |
228 slave->ring_position); |
226 slave->ring_position); |
230 } |
228 } |
231 |
229 |
232 udelay(100); |
230 udelay(100); |
233 } |
231 } |
234 |
232 |
235 if (ec_slave_mbox_prepare_fetch(slave)) return NULL; |
233 if (ec_slave_mbox_prepare_fetch(slave, command)) return NULL; |
236 if (unlikely(ec_master_simple_io(slave->master, command))) { |
234 if (unlikely(ec_master_simple_io(slave->master, command))) { |
237 EC_ERR("Mailbox receiving failed on slave %i!\n", |
235 EC_ERR("Mailbox receiving failed on slave %i!\n", |
238 slave->ring_position); |
236 slave->ring_position); |
239 return NULL; |
237 return NULL; |
240 } |
238 } |
241 |
239 |
242 if (unlikely(slave->master->debug_level) > 1) |
240 if (unlikely(slave->master->debug_level) > 1) |
243 EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000 |
241 EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000 |
244 / cpu_khz)); |
242 / cpu_khz)); |
245 |
243 |
246 return ec_slave_mbox_fetch(slave, type, size); |
244 return ec_slave_mbox_fetch(slave, command, type, size); |
247 } |
245 } |
248 |
246 |
249 /*****************************************************************************/ |
247 /*****************************************************************************/ |