112 |
157 |
113 void ec_eoe_run(ec_eoe_t *eoe) |
158 void ec_eoe_run(ec_eoe_t *eoe) |
114 { |
159 { |
115 uint8_t *data; |
160 uint8_t *data; |
116 ec_master_t *master; |
161 ec_master_t *master; |
117 size_t rec_size; |
162 size_t rec_size, data_size; |
|
163 off_t offset; |
118 uint8_t fragment_number, frame_number, last_fragment, time_appended; |
164 uint8_t fragment_number, frame_number, last_fragment, time_appended; |
119 uint8_t fragment_offset, frame_type; |
165 uint8_t fragment_offset, frame_type; |
|
166 ec_eoe_frame_t *frame; |
|
167 unsigned int wakeup = 0; |
120 |
168 |
121 if (!eoe->opened) return; |
169 if (!eoe->opened) return; |
122 |
170 |
123 master = eoe->slave->master; |
171 master = eoe->slave->master; |
124 |
172 |
125 if (eoe->rx_state == EC_EOE_IDLE) { |
173 switch (eoe->state) { |
126 ec_slave_mbox_prepare_check(eoe->slave); |
174 case EC_EOE_RX_START: |
127 ec_master_queue_command(master, &eoe->slave->mbox_command); |
175 ec_slave_mbox_prepare_check(eoe->slave); |
128 eoe->rx_state = EC_EOE_CHECKING; |
176 ec_master_queue_command(master, &eoe->slave->mbox_command); |
129 return; |
177 eoe->state = EC_EOE_RX_CHECK; |
130 } |
178 break; |
131 |
179 |
132 if (eoe->rx_state == EC_EOE_CHECKING) { |
180 case EC_EOE_RX_CHECK: |
133 if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) { |
181 if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) { |
134 master->stats.eoe_errors++; |
182 eoe->stats.rx_errors++; |
135 eoe->rx_state = EC_EOE_IDLE; |
183 eoe->state = EC_EOE_TX_START; |
136 return; |
184 break; |
137 } |
185 } |
138 if (!ec_slave_mbox_check(eoe->slave)) { |
186 if (!ec_slave_mbox_check(eoe->slave)) { |
139 eoe->rx_state = EC_EOE_IDLE; |
187 eoe->state = EC_EOE_TX_START; |
140 return; |
188 break; |
141 } |
189 } |
142 ec_slave_mbox_prepare_fetch(eoe->slave); |
190 ec_slave_mbox_prepare_fetch(eoe->slave); |
143 ec_master_queue_command(master, &eoe->slave->mbox_command); |
191 ec_master_queue_command(master, &eoe->slave->mbox_command); |
144 eoe->rx_state = EC_EOE_FETCHING; |
192 eoe->state = EC_EOE_RX_FETCH; |
145 return; |
193 break; |
146 } |
194 |
147 |
195 case EC_EOE_RX_FETCH: |
148 if (eoe->rx_state == EC_EOE_FETCHING) { |
196 if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) { |
149 if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) { |
197 eoe->stats.rx_errors++; |
150 master->stats.eoe_errors++; |
198 eoe->state = EC_EOE_TX_START; |
151 eoe->rx_state = EC_EOE_IDLE; |
199 break; |
152 return; |
200 } |
153 } |
201 if (!(data = ec_slave_mbox_fetch(eoe->slave, 0x02, &rec_size))) { |
154 if (!(data = ec_slave_mbox_fetch(eoe->slave, 0x02, &rec_size))) { |
202 eoe->stats.rx_errors++; |
155 master->stats.eoe_errors++; |
203 eoe->state = EC_EOE_TX_START; |
156 eoe->rx_state = EC_EOE_IDLE; |
204 break; |
157 return; |
205 } |
158 } |
206 |
159 |
207 frame_type = EC_READ_U16(data) & 0x000F; |
160 frame_type = EC_READ_U16(data) & 0x000F; |
208 |
161 |
209 if (frame_type == 0x00) { // EoE Fragment Request |
162 if (frame_type == 0x00) { // EoE Fragment Request |
210 last_fragment = (EC_READ_U16(data) >> 8) & 0x0001; |
163 last_fragment = (EC_READ_U16(data) >> 8) & 0x0001; |
211 time_appended = (EC_READ_U16(data) >> 9) & 0x0001; |
164 time_appended = (EC_READ_U16(data) >> 9) & 0x0001; |
212 fragment_number = EC_READ_U16(data + 2) & 0x003F; |
165 fragment_number = EC_READ_U16(data + 2) & 0x003F; |
213 fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F; |
166 fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F; |
214 frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F; |
167 frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F; |
215 |
168 |
216 EC_DBG("EoE RX fragment %i, offset %i, frame %i%s%s," |
169 #if 0 |
217 " %i octets\n", fragment_number, fragment_offset, |
170 EC_DBG("EOE fragment req received, fragment: %i, offset: %i," |
218 frame_number, |
171 " frame %i%s%s, %i bytes\n", fragment_number, |
219 last_fragment ? ", last fragment" : "", |
172 fragment_offset, frame_number, |
220 time_appended ? ", + timestamp" : "", |
173 last_fragment ? ", last fragment" : "", |
221 time_appended ? rec_size - 8 : rec_size - 4); |
174 time_appended ? ", + timestamp" : "", |
222 |
175 time_appended ? rec_size - 8 : rec_size - 4); |
223 data_size = time_appended ? rec_size - 8 : rec_size - 4; |
176 |
224 |
177 #if 0 |
225 if (!fragment_number) { |
178 EC_DBG(""); |
226 if (eoe->skb) { |
179 for (i = 0; i < rec_size - 4; i++) { |
227 EC_WARN("EoE RX freeing old socket buffer...\n"); |
180 printk("%02X ", data[i + 4]); |
228 dev_kfree_skb(eoe->skb); |
181 if ((i + 1) % 16 == 0) { |
229 } |
182 printk("\n"); |
230 |
183 EC_DBG(""); |
231 // new socket buffer |
|
232 if (!(eoe->skb = dev_alloc_skb(fragment_offset * 32))) { |
|
233 if (printk_ratelimit()) |
|
234 EC_WARN("EoE RX low on mem. frame dropped.\n"); |
|
235 eoe->stats.rx_dropped++; |
|
236 eoe->state = EC_EOE_TX_START; |
|
237 break; |
|
238 } |
|
239 eoe->skb_offset = 0; |
|
240 eoe->skb_size = fragment_offset * 32; |
|
241 eoe->expected_fragment = 0; |
184 } |
242 } |
185 } |
243 else { |
186 printk("\n"); |
244 if (!eoe->skb) { |
187 #endif |
245 eoe->stats.rx_dropped++; |
188 #endif |
246 eoe->state = EC_EOE_TX_START; |
189 |
247 break; |
190 ec_eoedev_rx(eoe->dev, data + 4, |
248 } |
191 time_appended ? rec_size - 8 : rec_size - 4); |
249 |
192 } |
250 offset = fragment_offset * 32; |
193 else { |
251 if (offset != eoe->skb_offset || |
194 #if 1 |
252 offset + data_size > eoe->skb_size || |
195 EC_DBG("other frame received.\n"); |
253 fragment_number != eoe->expected_fragment) { |
196 #endif |
254 eoe->stats.rx_errors++; |
197 } |
255 eoe->state = EC_EOE_TX_START; |
198 |
256 dev_kfree_skb(eoe->skb); |
199 eoe->rx_state = EC_EOE_IDLE; |
257 eoe->skb = NULL; |
200 return; |
258 break; |
|
259 } |
|
260 } |
|
261 |
|
262 // copy fragment into socket buffer |
|
263 memcpy(skb_put(eoe->skb, data_size), data + 4, data_size); |
|
264 eoe->skb_offset += data_size; |
|
265 |
|
266 if (last_fragment) { |
|
267 // update statistics |
|
268 eoe->stats.rx_packets++; |
|
269 eoe->stats.rx_bytes += eoe->skb->len; |
|
270 |
|
271 EC_DBG("EoE RX frame completed with %u octets.\n", |
|
272 eoe->skb->len); |
|
273 |
|
274 // pass socket buffer to network stack |
|
275 eoe->skb->dev = eoe->dev; |
|
276 eoe->skb->protocol = eth_type_trans(eoe->skb, eoe->dev); |
|
277 eoe->skb->ip_summed = CHECKSUM_NONE; |
|
278 if (netif_rx(eoe->skb)) { |
|
279 EC_WARN("EoE RX netif_rx failed.\n"); |
|
280 } |
|
281 eoe->skb = NULL; |
|
282 |
|
283 eoe->state = EC_EOE_TX_START; |
|
284 } |
|
285 else { |
|
286 eoe->expected_fragment++; |
|
287 EC_DBG("EoE RX expecting fragment %i\n", |
|
288 eoe->expected_fragment); |
|
289 eoe->state = EC_EOE_RX_START; |
|
290 } |
|
291 } |
|
292 else { |
|
293 EC_DBG("other frame received.\n"); |
|
294 eoe->stats.rx_dropped++; |
|
295 eoe->state = EC_EOE_TX_START; |
|
296 } |
|
297 break; |
|
298 |
|
299 case EC_EOE_TX_START: |
|
300 spin_lock_bh(&eoe->tx_queue_lock); |
|
301 |
|
302 if (!eoe->queued_frames || list_empty(&eoe->tx_queue)) { |
|
303 spin_unlock_bh(&eoe->tx_queue_lock); |
|
304 eoe->state = EC_EOE_RX_START; |
|
305 break; |
|
306 } |
|
307 |
|
308 // take the first frame out of the queue |
|
309 frame = list_entry(eoe->tx_queue.next, ec_eoe_frame_t, queue); |
|
310 list_del(&frame->queue); |
|
311 if (!eoe->tx_queue_active && |
|
312 eoe->queued_frames == EC_EOE_TX_QUEUE_SIZE / 2) { |
|
313 netif_wake_queue(eoe->dev); |
|
314 eoe->tx_queue_active = 1; |
|
315 wakeup = 1; |
|
316 } |
|
317 eoe->queued_frames--; |
|
318 spin_unlock_bh(&eoe->tx_queue_lock); |
|
319 |
|
320 EC_DBG("EoE TX Sending frame with %i octets." |
|
321 " (%i frames queued).\n", |
|
322 frame->skb->len, eoe->queued_frames); |
|
323 |
|
324 if (wakeup) EC_DBG("waking up TX queue...\n"); |
|
325 |
|
326 if (!(data = ec_slave_mbox_prepare_send(eoe->slave, 0x02, |
|
327 frame->skb->len + 4))) { |
|
328 dev_kfree_skb(frame->skb); |
|
329 kfree(frame); |
|
330 eoe->stats.tx_errors++; |
|
331 eoe->state = EC_EOE_RX_START; |
|
332 break; |
|
333 } |
|
334 |
|
335 eoe->tx_frame_number++; |
|
336 eoe->tx_frame_number %= 16; |
|
337 |
|
338 EC_WRITE_U16(data, 0x0100); // eoe fragment req. |
|
339 EC_WRITE_U16(data + 2, (eoe->tx_frame_number & 0x0F) << 12); |
|
340 |
|
341 memcpy(data + 4, frame->skb->data, frame->skb->len); |
|
342 ec_master_queue_command(master, &eoe->slave->mbox_command); |
|
343 |
|
344 eoe->last_tx_bytes = frame->skb->len; |
|
345 dev_kfree_skb(frame->skb); |
|
346 kfree(frame); |
|
347 |
|
348 eoe->state = EC_EOE_TX_SENT; |
|
349 break; |
|
350 |
|
351 case EC_EOE_TX_SENT: |
|
352 if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) { |
|
353 eoe->stats.tx_errors++; |
|
354 eoe->state = EC_EOE_RX_START; |
|
355 break; |
|
356 } |
|
357 if (eoe->slave->mbox_command.working_counter != 1) { |
|
358 eoe->stats.tx_errors++; |
|
359 eoe->state = EC_EOE_RX_START; |
|
360 break; |
|
361 } |
|
362 |
|
363 eoe->stats.tx_packets++; |
|
364 eoe->stats.tx_bytes += eoe->last_tx_bytes; |
|
365 eoe->state = EC_EOE_RX_START; |
|
366 break; |
|
367 |
|
368 default: |
|
369 break; |
201 } |
370 } |
202 } |
371 } |
203 |
372 |
204 /*****************************************************************************/ |
373 /*****************************************************************************/ |
205 |
374 |
279 int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */ |
452 int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */ |
280 struct net_device *dev /**< EoE net_device */ |
453 struct net_device *dev /**< EoE net_device */ |
281 ) |
454 ) |
282 { |
455 { |
283 ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev)); |
456 ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev)); |
|
457 ec_eoe_frame_t *frame; |
|
458 |
|
459 if (skb->len + 10 > eoe->slave->sii_tx_mailbox_size) { |
|
460 EC_WARN("EoE TX frame (%i octets) exceeds MTU. dropping.\n", skb->len); |
|
461 dev_kfree_skb(skb); |
|
462 eoe->stats.tx_dropped++; |
|
463 return 0; |
|
464 } |
|
465 |
|
466 if (!(frame = |
|
467 (ec_eoe_frame_t *) kmalloc(sizeof(ec_eoe_frame_t), GFP_ATOMIC))) { |
|
468 if (printk_ratelimit()) |
|
469 EC_WARN("EoE TX: low on mem. frame dropped.\n"); |
|
470 return 1; |
|
471 } |
|
472 |
|
473 frame->skb = skb; |
284 |
474 |
285 spin_lock_bh(&eoe->tx_queue_lock); |
475 spin_lock_bh(&eoe->tx_queue_lock); |
286 |
476 list_add_tail(&frame->queue, &eoe->tx_queue); |
287 #if 0 |
477 eoe->queued_frames++; |
288 eoe->stats.tx_packets++; |
478 if (eoe->queued_frames == EC_EOE_TX_QUEUE_SIZE) { |
289 dev_kfree_skb(skb); |
|
290 EC_INFO("EoE device sent %i octets.\n", skb->len); |
|
291 #endif |
|
292 |
|
293 if (eoe->queued_frames == EC_EOE_TX_QUEUE_SIZE) |
|
294 netif_stop_queue(dev); |
479 netif_stop_queue(dev); |
295 |
480 eoe->tx_queue_active = 0; |
|
481 } |
296 spin_unlock_bh(&eoe->tx_queue_lock); |
482 spin_unlock_bh(&eoe->tx_queue_lock); |
297 |
483 |
|
484 EC_DBG("EoE TX queued frame with %i octets (%i frames queued).\n", |
|
485 skb->len, eoe->queued_frames); |
|
486 if (!eoe->tx_queue_active) |
|
487 EC_WARN("EoE TX queue is now full.\n"); |
|
488 |
298 return 0; |
489 return 0; |
299 } |
|
300 |
|
301 /*****************************************************************************/ |
|
302 |
|
303 /** |
|
304 Receives data from the bus and passes it to the network stack. |
|
305 */ |
|
306 |
|
307 void ec_eoedev_rx(struct net_device *dev, /**< EoE net_device */ |
|
308 const uint8_t *data, /**< pointer to the data */ |
|
309 size_t size /**< size of the received data */ |
|
310 ) |
|
311 { |
|
312 ec_eoe_t *eoe = *((ec_eoe_t **) netdev_priv(dev)); |
|
313 |
|
314 // allocate socket buffer |
|
315 if (!(eoe->skb = dev_alloc_skb(size + 2))) { |
|
316 if (printk_ratelimit()) |
|
317 EC_WARN("EoE RX: low on mem. frame dropped.\n"); |
|
318 eoe->stats.rx_dropped++; |
|
319 return; |
|
320 } |
|
321 |
|
322 // copy received data to socket buffer |
|
323 memcpy(skb_put(eoe->skb, size), data, size); |
|
324 |
|
325 // set socket buffer fields |
|
326 eoe->skb->dev = dev; |
|
327 eoe->skb->protocol = eth_type_trans(eoe->skb, dev); |
|
328 eoe->skb->ip_summed = CHECKSUM_UNNECESSARY; |
|
329 |
|
330 // update statistics |
|
331 eoe->stats.rx_packets++; |
|
332 eoe->stats.rx_bytes += size; |
|
333 |
|
334 // pass socket buffer to network stack |
|
335 netif_rx(eoe->skb); |
|
336 eoe->skb = NULL; |
|
337 } |
490 } |
338 |
491 |
339 /*****************************************************************************/ |
492 /*****************************************************************************/ |
340 |
493 |
341 /** |
494 /** |