310 * STATE PROCESSING FUNCTIONS |
312 * STATE PROCESSING FUNCTIONS |
311 *****************************************************************************/ |
313 *****************************************************************************/ |
312 |
314 |
313 /** |
315 /** |
314 State: RX_START. |
316 State: RX_START. |
315 Starts a new receiving sequence by queueing a command that checks the |
317 Starts a new receiving sequence by queueing a datagram that checks the |
316 slave's mailbox for a new EoE command. |
318 slave's mailbox for a new EoE datagram. |
317 */ |
319 */ |
318 |
320 |
319 void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */) |
321 void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */) |
320 { |
322 { |
321 if (!eoe->slave->online || !eoe->slave->master->device->link_state) |
323 if (!eoe->slave->online || !eoe->slave->master->device->link_state) |
322 return; |
324 return; |
323 |
325 |
324 ec_slave_mbox_prepare_check(eoe->slave, &eoe->command); |
326 ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram); |
325 ec_master_queue_command(eoe->slave->master, &eoe->command); |
327 ec_master_queue_datagram(eoe->slave->master, &eoe->datagram); |
326 eoe->state = ec_eoe_state_rx_check; |
328 eoe->state = ec_eoe_state_rx_check; |
327 } |
329 } |
328 |
330 |
329 /*****************************************************************************/ |
331 /*****************************************************************************/ |
330 |
332 |
331 /** |
333 /** |
332 State: RX_CHECK. |
334 State: RX_CHECK. |
333 Processes the checking command sent in RX_START and issues a receive |
335 Processes the checking datagram sent in RX_START and issues a receive |
334 command, if new data is available. |
336 datagram, if new data is available. |
335 */ |
337 */ |
336 |
338 |
337 void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */) |
339 void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */) |
338 { |
340 { |
339 if (eoe->command.state != EC_CMD_RECEIVED) { |
341 if (eoe->datagram.state != EC_CMD_RECEIVED) { |
340 eoe->stats.rx_errors++; |
342 eoe->stats.rx_errors++; |
341 eoe->state = ec_eoe_state_tx_start; |
343 eoe->state = ec_eoe_state_tx_start; |
342 return; |
344 return; |
343 } |
345 } |
344 |
346 |
345 if (!ec_slave_mbox_check(&eoe->command)) { |
347 if (!ec_slave_mbox_check(&eoe->datagram)) { |
346 eoe->state = ec_eoe_state_tx_start; |
348 eoe->state = ec_eoe_state_tx_start; |
347 return; |
349 return; |
348 } |
350 } |
349 |
351 |
350 ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->command); |
352 ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram); |
351 ec_master_queue_command(eoe->slave->master, &eoe->command); |
353 ec_master_queue_datagram(eoe->slave->master, &eoe->datagram); |
352 eoe->state = ec_eoe_state_rx_fetch; |
354 eoe->state = ec_eoe_state_rx_fetch; |
353 } |
355 } |
354 |
356 |
355 /*****************************************************************************/ |
357 /*****************************************************************************/ |
356 |
358 |
357 /** |
359 /** |
358 State: RX_FETCH. |
360 State: RX_FETCH. |
359 Checks if the requested data of RX_CHECK was received and processes the |
361 Checks if the requested data of RX_CHECK was received and processes the |
360 EoE command. |
362 EoE datagram. |
361 */ |
363 */ |
362 |
364 |
363 void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */) |
365 void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */) |
364 { |
366 { |
365 size_t rec_size, data_size; |
367 size_t rec_size, data_size; |
366 uint8_t *data, frame_type, last_fragment, time_appended; |
368 uint8_t *data, frame_type, last_fragment, time_appended; |
367 uint8_t frame_number, fragment_offset, fragment_number; |
369 uint8_t frame_number, fragment_offset, fragment_number; |
368 off_t offset; |
370 off_t offset; |
369 |
371 |
370 if (eoe->command.state != EC_CMD_RECEIVED) { |
372 if (eoe->datagram.state != EC_CMD_RECEIVED) { |
371 eoe->stats.rx_errors++; |
373 eoe->stats.rx_errors++; |
372 eoe->state = ec_eoe_state_tx_start; |
374 eoe->state = ec_eoe_state_tx_start; |
373 return; |
375 return; |
374 } |
376 } |
375 |
377 |
376 if (!(data = ec_slave_mbox_fetch(eoe->slave, &eoe->command, |
378 if (!(data = ec_slave_mbox_fetch(eoe->slave, &eoe->datagram, |
377 0x02, &rec_size))) { |
379 0x02, &rec_size))) { |
378 eoe->stats.rx_errors++; |
380 eoe->stats.rx_errors++; |
379 eoe->state = ec_eoe_state_tx_start; |
381 eoe->state = ec_eoe_state_tx_start; |
380 return; |
382 return; |
381 } |
383 } |
382 |
384 |
383 frame_type = EC_READ_U16(data) & 0x000F; |
385 frame_type = EC_READ_U16(data) & 0x000F; |
384 |
386 |
385 if (frame_type == 0x00) { // EoE Fragment Request |
387 if (frame_type != 0x00) { |
386 last_fragment = (EC_READ_U16(data) >> 8) & 0x0001; |
|
387 time_appended = (EC_READ_U16(data) >> 9) & 0x0001; |
|
388 fragment_number = EC_READ_U16(data + 2) & 0x003F; |
|
389 fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F; |
|
390 frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F; |
|
391 |
|
392 #if EOE_DEBUG_LEVEL > 0 |
|
393 EC_DBG("EoE RX fragment %i, offset %i, frame %i%s%s," |
|
394 " %i octets\n", fragment_number, fragment_offset, |
|
395 frame_number, |
|
396 last_fragment ? ", last fragment" : "", |
|
397 time_appended ? ", + timestamp" : "", |
|
398 time_appended ? rec_size - 8 : rec_size - 4); |
|
399 #endif |
|
400 |
|
401 #if EOE_DEBUG_LEVEL > 1 |
|
402 EC_DBG(""); |
|
403 for (i = 0; i < rec_size - 4; i++) { |
|
404 printk("%02X ", data[i + 4]); |
|
405 if ((i + 1) % 16 == 0) { |
|
406 printk("\n"); |
|
407 EC_DBG(""); |
|
408 } |
|
409 } |
|
410 printk("\n"); |
|
411 #endif |
|
412 |
|
413 data_size = time_appended ? rec_size - 8 : rec_size - 4; |
|
414 |
|
415 if (!fragment_number) { |
|
416 if (eoe->rx_skb) { |
|
417 EC_WARN("EoE RX freeing old socket buffer...\n"); |
|
418 dev_kfree_skb(eoe->rx_skb); |
|
419 } |
|
420 |
|
421 // new socket buffer |
|
422 if (!(eoe->rx_skb = dev_alloc_skb(fragment_offset * 32))) { |
|
423 if (printk_ratelimit()) |
|
424 EC_WARN("EoE RX low on mem. frame dropped.\n"); |
|
425 eoe->stats.rx_dropped++; |
|
426 eoe->state = ec_eoe_state_tx_start; |
|
427 return; |
|
428 } |
|
429 |
|
430 eoe->rx_skb_offset = 0; |
|
431 eoe->rx_skb_size = fragment_offset * 32; |
|
432 eoe->rx_expected_fragment = 0; |
|
433 } |
|
434 else { |
|
435 if (!eoe->rx_skb) { |
|
436 eoe->stats.rx_dropped++; |
|
437 eoe->state = ec_eoe_state_tx_start; |
|
438 return; |
|
439 } |
|
440 |
|
441 offset = fragment_offset * 32; |
|
442 if (offset != eoe->rx_skb_offset || |
|
443 offset + data_size > eoe->rx_skb_size || |
|
444 fragment_number != eoe->rx_expected_fragment) { |
|
445 eoe->stats.rx_errors++; |
|
446 eoe->state = ec_eoe_state_tx_start; |
|
447 dev_kfree_skb(eoe->rx_skb); |
|
448 eoe->rx_skb = NULL; |
|
449 return; |
|
450 } |
|
451 } |
|
452 |
|
453 // copy fragment into socket buffer |
|
454 memcpy(skb_put(eoe->rx_skb, data_size), data + 4, data_size); |
|
455 eoe->rx_skb_offset += data_size; |
|
456 |
|
457 if (last_fragment) { |
|
458 // update statistics |
|
459 eoe->stats.rx_packets++; |
|
460 eoe->stats.rx_bytes += eoe->rx_skb->len; |
|
461 |
|
462 #if EOE_DEBUG_LEVEL > 0 |
|
463 EC_DBG("EoE RX frame completed with %u octets.\n", |
|
464 eoe->rx_skb->len); |
|
465 #endif |
|
466 |
|
467 // pass socket buffer to network stack |
|
468 eoe->rx_skb->dev = eoe->dev; |
|
469 eoe->rx_skb->protocol = eth_type_trans(eoe->rx_skb, eoe->dev); |
|
470 eoe->rx_skb->ip_summed = CHECKSUM_UNNECESSARY; |
|
471 if (netif_rx(eoe->rx_skb)) { |
|
472 EC_WARN("EoE RX netif_rx failed.\n"); |
|
473 } |
|
474 eoe->rx_skb = NULL; |
|
475 |
|
476 eoe->state = ec_eoe_state_tx_start; |
|
477 } |
|
478 else { |
|
479 eoe->rx_expected_fragment++; |
|
480 #if EOE_DEBUG_LEVEL > 0 |
|
481 EC_DBG("EoE RX expecting fragment %i\n", |
|
482 eoe->rx_expected_fragment); |
|
483 #endif |
|
484 eoe->state = ec_eoe_state_rx_start; |
|
485 } |
|
486 } |
|
487 else { |
|
488 #if EOE_DEBUG_LEVEL > 0 |
388 #if EOE_DEBUG_LEVEL > 0 |
489 EC_DBG("other frame received.\n"); |
389 EC_DBG("other frame received.\n"); |
490 #endif |
390 #endif |
491 eoe->stats.rx_dropped++; |
391 eoe->stats.rx_dropped++; |
492 eoe->state = ec_eoe_state_tx_start; |
392 eoe->state = ec_eoe_state_tx_start; |
|
393 return; |
|
394 } |
|
395 |
|
396 // EoE Fragment Request received |
|
397 |
|
398 last_fragment = (EC_READ_U16(data) >> 8) & 0x0001; |
|
399 time_appended = (EC_READ_U16(data) >> 9) & 0x0001; |
|
400 fragment_number = EC_READ_U16(data + 2) & 0x003F; |
|
401 fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F; |
|
402 frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F; |
|
403 |
|
404 #if EOE_DEBUG_LEVEL > 0 |
|
405 EC_DBG("EoE RX fragment %i, offset %i, frame %i%s%s," |
|
406 " %i octets\n", fragment_number, fragment_offset, |
|
407 frame_number, |
|
408 last_fragment ? ", last fragment" : "", |
|
409 time_appended ? ", + timestamp" : "", |
|
410 time_appended ? rec_size - 8 : rec_size - 4); |
|
411 #endif |
|
412 |
|
413 #if EOE_DEBUG_LEVEL > 1 |
|
414 EC_DBG(""); |
|
415 for (i = 0; i < rec_size - 4; i++) { |
|
416 printk("%02X ", data[i + 4]); |
|
417 if ((i + 1) % 16 == 0) { |
|
418 printk("\n"); |
|
419 EC_DBG(""); |
|
420 } |
|
421 } |
|
422 printk("\n"); |
|
423 #endif |
|
424 |
|
425 data_size = time_appended ? rec_size - 8 : rec_size - 4; |
|
426 |
|
427 if (!fragment_number) { |
|
428 if (eoe->rx_skb) { |
|
429 EC_WARN("EoE RX freeing old socket buffer...\n"); |
|
430 dev_kfree_skb(eoe->rx_skb); |
|
431 } |
|
432 |
|
433 // new socket buffer |
|
434 if (!(eoe->rx_skb = dev_alloc_skb(fragment_offset * 32))) { |
|
435 if (printk_ratelimit()) |
|
436 EC_WARN("EoE RX low on mem. frame dropped.\n"); |
|
437 eoe->stats.rx_dropped++; |
|
438 eoe->state = ec_eoe_state_tx_start; |
|
439 return; |
|
440 } |
|
441 |
|
442 eoe->rx_skb_offset = 0; |
|
443 eoe->rx_skb_size = fragment_offset * 32; |
|
444 eoe->rx_expected_fragment = 0; |
|
445 } |
|
446 else { |
|
447 if (!eoe->rx_skb) { |
|
448 eoe->stats.rx_dropped++; |
|
449 eoe->state = ec_eoe_state_tx_start; |
|
450 return; |
|
451 } |
|
452 |
|
453 offset = fragment_offset * 32; |
|
454 if (offset != eoe->rx_skb_offset || |
|
455 offset + data_size > eoe->rx_skb_size || |
|
456 fragment_number != eoe->rx_expected_fragment) { |
|
457 dev_kfree_skb(eoe->rx_skb); |
|
458 eoe->rx_skb = NULL; |
|
459 eoe->stats.rx_errors++; |
|
460 eoe->state = ec_eoe_state_tx_start; |
|
461 return; |
|
462 } |
|
463 } |
|
464 |
|
465 // copy fragment into socket buffer |
|
466 memcpy(skb_put(eoe->rx_skb, data_size), data + 4, data_size); |
|
467 eoe->rx_skb_offset += data_size; |
|
468 |
|
469 if (last_fragment) { |
|
470 // update statistics |
|
471 eoe->stats.rx_packets++; |
|
472 eoe->stats.rx_bytes += eoe->rx_skb->len; |
|
473 |
|
474 #if EOE_DEBUG_LEVEL > 0 |
|
475 EC_DBG("EoE RX frame completed with %u octets.\n", |
|
476 eoe->rx_skb->len); |
|
477 #endif |
|
478 |
|
479 // pass socket buffer to network stack |
|
480 eoe->rx_skb->dev = eoe->dev; |
|
481 eoe->rx_skb->protocol = eth_type_trans(eoe->rx_skb, eoe->dev); |
|
482 eoe->rx_skb->ip_summed = CHECKSUM_UNNECESSARY; |
|
483 if (netif_rx(eoe->rx_skb)) { |
|
484 EC_WARN("EoE RX netif_rx failed.\n"); |
|
485 } |
|
486 eoe->rx_skb = NULL; |
|
487 |
|
488 eoe->state = ec_eoe_state_tx_start; |
|
489 } |
|
490 else { |
|
491 eoe->rx_expected_fragment++; |
|
492 #if EOE_DEBUG_LEVEL > 0 |
|
493 EC_DBG("EoE RX expecting fragment %i\n", |
|
494 eoe->rx_expected_fragment); |
|
495 #endif |
|
496 eoe->state = ec_eoe_state_rx_start; |
493 } |
497 } |
494 } |
498 } |
495 |
499 |
496 /*****************************************************************************/ |
500 /*****************************************************************************/ |
497 |
501 |