--- a/master/ethernet.c Mon May 08 16:46:43 2006 +0000
+++ b/master/ethernet.c Tue May 09 09:45:42 2006 +0000
@@ -43,6 +43,15 @@
void ec_eoe_flush(ec_eoe_t *);
void ec_eoedev_init(struct net_device *);
+
+// state functions
+void ec_eoe_state_rx_start(ec_eoe_t *);
+void ec_eoe_state_rx_check(ec_eoe_t *);
+void ec_eoe_state_rx_fetch(ec_eoe_t *);
+void ec_eoe_state_tx_start(ec_eoe_t *);
+void ec_eoe_state_tx_sent(ec_eoe_t *);
+
+// net_device functions
int ec_eoedev_open(struct net_device *);
int ec_eoedev_stop(struct net_device *);
int ec_eoedev_tx(struct sk_buff *, struct net_device *);
@@ -53,36 +62,55 @@
/**
EoE constructor.
-*/
-
-int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
+ Initializes the EoE object, creates a net_device and registeres it.
+*/
+
+int ec_eoe_init(ec_eoe_t *eoe, /**< EoE object */
+ ec_slave_t *slave /**< assigned slave */
+ )
{
ec_eoe_t **priv;
- int result;
+ int result, i;
eoe->slave = slave;
- eoe->state = EC_EOE_RX_START;
+ eoe->state = ec_eoe_state_rx_start;
eoe->opened = 0;
- eoe->skb = NULL;
- eoe->expected_fragment = 0;
+ eoe->rx_skb = NULL;
+ eoe->rx_expected_fragment = 0;
INIT_LIST_HEAD(&eoe->tx_queue);
+ eoe->tx_frame = NULL;
eoe->tx_queue_active = 0;
- eoe->queued_frames = 0;
+ eoe->tx_queued_frames = 0;
eoe->tx_queue_lock = SPIN_LOCK_UNLOCKED;
eoe->tx_frame_number = 0xFF;
memset(&eoe->stats, 0, sizeof(struct net_device_stats));
if (!(eoe->dev =
- alloc_netdev(sizeof(ec_eoe_t *), "eoe%d", ec_eoedev_init))) {
+ alloc_netdev(sizeof(ec_eoe_t *), "eoe%d", ether_setup))) {
EC_ERR("Unable to allocate net_device for EoE object!\n");
goto out_return;
}
- // set EoE object reference
+ // initialize net_device
+ eoe->dev->open = ec_eoedev_open;
+ eoe->dev->stop = ec_eoedev_stop;
+ eoe->dev->hard_start_xmit = ec_eoedev_tx;
+ eoe->dev->get_stats = ec_eoedev_stats;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ eoe->dev->dev_addr[i] = i | (i << 4);
+
+ // initialize private data
priv = netdev_priv(eoe->dev);
*priv = eoe;
+ // Usually setting the MTU appropriately makes the upper layers
+ // do the frame fragmenting. In some cases this doesn't work
+ // so the MTU is left on the Ethernet standard value and fragmenting
+ // is done "manually".
+#if 0
eoe->dev->mtu = slave->sii_rx_mailbox_size - ETH_HLEN - 10;
+#endif
// connect the net_device to the kernel
if ((result = register_netdev(eoe->dev))) {
@@ -90,6 +118,9 @@
goto out_free;
}
+ // make the last address octet unique
+ eoe->dev->dev_addr[ETH_ALEN - 1] = (uint8_t) eoe->dev->ifindex;
+
return 0;
out_free:
@@ -103,9 +134,10 @@
/**
EoE destructor.
-*/
-
-void ec_eoe_clear(ec_eoe_t *eoe)
+ Unregisteres the net_device and frees allocated memory.
+*/
+
+void ec_eoe_clear(ec_eoe_t *eoe /**< EoE object */)
{
if (eoe->dev) {
unregister_netdev(eoe->dev);
@@ -114,6 +146,13 @@
// empty transmit queue
ec_eoe_flush(eoe);
+
+ if (eoe->tx_frame) {
+ dev_kfree_skb(eoe->tx_frame->skb);
+ kfree(eoe->tx_frame);
+ }
+
+ if (eoe->rx_skb) dev_kfree_skb(eoe->rx_skb);
}
/*****************************************************************************/
@@ -122,7 +161,7 @@
Empties the transmit queue.
*/
-void ec_eoe_flush(ec_eoe_t *eoe)
+void ec_eoe_flush(ec_eoe_t *eoe /**< EoE object */)
{
ec_eoe_frame_t *frame, *next;
@@ -133,7 +172,7 @@
dev_kfree_skb(frame->skb);
kfree(frame);
}
- eoe->queued_frames = 0;
+ eoe->tx_queued_frames = 0;
spin_unlock_bh(&eoe->tx_queue_lock);
}
@@ -144,9 +183,8 @@
Sends a frame or the next fragment.
*/
-int ec_eoe_send(ec_eoe_t *eoe)
-{
- ec_eoe_frame_t *frame = eoe->tx_frame;
+int ec_eoe_send(ec_eoe_t *eoe /**< EoE object */)
+{
size_t remaining_size, current_size, complete_offset;
unsigned int last_fragment;
uint8_t *data;
@@ -154,7 +192,7 @@
unsigned int i;
#endif
- remaining_size = frame->skb->len - eoe->tx_offset;
+ remaining_size = eoe->tx_frame->skb->len - eoe->tx_offset;
if (remaining_size <= eoe->slave->sii_tx_mailbox_size - 10) {
current_size = remaining_size;
@@ -176,7 +214,7 @@
EC_DBG("EoE TX sending %sfragment %i with %i octets (%i)."
" %i frames queued.\n", last_fragment ? "last " : "",
eoe->tx_fragment_number, current_size, complete_offset,
- eoe->queued_frames);
+ eoe->tx_queued_frames);
#endif
#if EOE_DEBUG_LEVEL > 1
@@ -201,7 +239,7 @@
(complete_offset & 0x3F) << 6 |
(eoe->tx_frame_number & 0x0F) << 12));
- memcpy(data + 4, frame->skb->data + eoe->tx_offset, current_size);
+ memcpy(data + 4, eoe->tx_frame->skb->data + eoe->tx_offset, current_size);
ec_master_queue_command(eoe->slave->master, &eoe->slave->mbox_command);
eoe->tx_offset += current_size;
@@ -216,248 +254,12 @@
Runs the EoE state machine.
*/
-void ec_eoe_run(ec_eoe_t *eoe)
-{
- uint8_t *data;
- ec_master_t *master;
- size_t rec_size, data_size;
- off_t offset;
- uint8_t fragment_number, frame_number, last_fragment, time_appended;
- uint8_t fragment_offset, frame_type;
- ec_eoe_frame_t *frame;
- unsigned int wakeup = 0;
-#if EOE_DEBUG_LEVEL > 1
- unsigned int i;
-#endif
-
+void ec_eoe_run(ec_eoe_t *eoe /**< EoE object */)
+{
if (!eoe->opened) return;
- master = eoe->slave->master;
-
- switch (eoe->state) {
- case EC_EOE_RX_START:
- ec_slave_mbox_prepare_check(eoe->slave);
- ec_master_queue_command(master, &eoe->slave->mbox_command);
- eoe->state = EC_EOE_RX_CHECK;
- break;
-
- case EC_EOE_RX_CHECK:
- if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
- eoe->stats.rx_errors++;
- eoe->state = EC_EOE_TX_START;
- break;
- }
- if (!ec_slave_mbox_check(eoe->slave)) {
- eoe->state = EC_EOE_TX_START;
- break;
- }
- ec_slave_mbox_prepare_fetch(eoe->slave);
- ec_master_queue_command(master, &eoe->slave->mbox_command);
- eoe->state = EC_EOE_RX_FETCH;
- break;
-
- case EC_EOE_RX_FETCH:
- if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
- eoe->stats.rx_errors++;
- eoe->state = EC_EOE_TX_START;
- break;
- }
- if (!(data = ec_slave_mbox_fetch(eoe->slave, 0x02, &rec_size))) {
- eoe->stats.rx_errors++;
- eoe->state = EC_EOE_TX_START;
- break;
- }
-
- frame_type = EC_READ_U16(data) & 0x000F;
-
- if (frame_type == 0x00) { // EoE Fragment Request
- last_fragment = (EC_READ_U16(data) >> 8) & 0x0001;
- time_appended = (EC_READ_U16(data) >> 9) & 0x0001;
- fragment_number = EC_READ_U16(data + 2) & 0x003F;
- fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F;
- frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F;
-
-#if EOE_DEBUG_LEVEL > 0
- EC_DBG("EoE RX fragment %i, offset %i, frame %i%s%s,"
- " %i octets\n", fragment_number, fragment_offset,
- frame_number,
- last_fragment ? ", last fragment" : "",
- time_appended ? ", + timestamp" : "",
- time_appended ? rec_size - 8 : rec_size - 4);
-
-#if EOE_DEBUG_LEVEL > 1
- EC_DBG("");
- for (i = 0; i < rec_size - 4; i++) {
- printk("%02X ", data[i + 4]);
- if ((i + 1) % 16 == 0) {
- printk("\n");
- EC_DBG("");
- }
- }
- printk("\n");
-#endif
-#endif
-
- data_size = time_appended ? rec_size - 8 : rec_size - 4;
-
- if (!fragment_number) {
- if (eoe->skb) {
- EC_WARN("EoE RX freeing old socket buffer...\n");
- dev_kfree_skb(eoe->skb);
- }
-
- // new socket buffer
- if (!(eoe->skb = dev_alloc_skb(fragment_offset * 32))) {
- if (printk_ratelimit())
- EC_WARN("EoE RX low on mem. frame dropped.\n");
- eoe->stats.rx_dropped++;
- eoe->state = EC_EOE_TX_START;
- break;
- }
- eoe->skb_offset = 0;
- eoe->skb_size = fragment_offset * 32;
- eoe->expected_fragment = 0;
- }
- else {
- if (!eoe->skb) {
- eoe->stats.rx_dropped++;
- eoe->state = EC_EOE_TX_START;
- break;
- }
-
- offset = fragment_offset * 32;
- if (offset != eoe->skb_offset ||
- offset + data_size > eoe->skb_size ||
- fragment_number != eoe->expected_fragment) {
- eoe->stats.rx_errors++;
- eoe->state = EC_EOE_TX_START;
- dev_kfree_skb(eoe->skb);
- eoe->skb = NULL;
- break;
- }
- }
-
- // copy fragment into socket buffer
- memcpy(skb_put(eoe->skb, data_size), data + 4, data_size);
- eoe->skb_offset += data_size;
-
- if (last_fragment) {
- // update statistics
- eoe->stats.rx_packets++;
- eoe->stats.rx_bytes += eoe->skb->len;
-
-#if EOE_DEBUG_LEVEL > 0
- EC_DBG("EoE RX frame completed with %u octets.\n",
- eoe->skb->len);
-#endif
-
- // pass socket buffer to network stack
- eoe->skb->dev = eoe->dev;
- eoe->skb->protocol = eth_type_trans(eoe->skb, eoe->dev);
- eoe->skb->ip_summed = CHECKSUM_UNNECESSARY;
- //eoe->skb->pkt_type = PACKET_HOST;
- if (netif_rx(eoe->skb)) {
- EC_WARN("EoE RX netif_rx failed.\n");
- }
- eoe->skb = NULL;
-
- eoe->state = EC_EOE_TX_START;
- }
- else {
- eoe->expected_fragment++;
-#if EOE_DEBUG_LEVEL > 0
- EC_DBG("EoE RX expecting fragment %i\n",
- eoe->expected_fragment);
-#endif
- eoe->state = EC_EOE_RX_START;
- }
- }
- else {
-#if EOE_DEBUG_LEVEL > 0
- EC_DBG("other frame received.\n");
-#endif
- eoe->stats.rx_dropped++;
- eoe->state = EC_EOE_TX_START;
- }
- break;
-
- case EC_EOE_TX_START:
- spin_lock_bh(&eoe->tx_queue_lock);
-
- if (!eoe->queued_frames || list_empty(&eoe->tx_queue)) {
- spin_unlock_bh(&eoe->tx_queue_lock);
- eoe->state = EC_EOE_RX_START;
- break;
- }
-
- // take the first frame out of the queue
- frame = list_entry(eoe->tx_queue.next, ec_eoe_frame_t, queue);
- list_del(&frame->queue);
- if (!eoe->tx_queue_active &&
- eoe->queued_frames == EC_EOE_TX_QUEUE_SIZE / 2) {
- netif_wake_queue(eoe->dev);
- eoe->tx_queue_active = 1;
- wakeup = 1;
- }
- eoe->queued_frames--;
- spin_unlock_bh(&eoe->tx_queue_lock);
-
- eoe->tx_frame_number++;
- eoe->tx_frame_number %= 16;
- eoe->tx_frame = frame;
- eoe->tx_fragment_number = 0;
- eoe->tx_offset = 0;
-
- if (ec_eoe_send(eoe)) {
- dev_kfree_skb(frame->skb);
- kfree(frame);
- eoe->stats.tx_errors++;
- eoe->state = EC_EOE_RX_START;
- break;
- }
-
-#if EOE_DEBUG_LEVEL > 0
- if (wakeup) EC_DBG("waking up TX queue...\n");
-#endif
-
- eoe->state = EC_EOE_TX_SENT;
- break;
-
- case EC_EOE_TX_SENT:
- if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
- eoe->stats.tx_errors++;
- eoe->state = EC_EOE_RX_START;
- break;
- }
- if (eoe->slave->mbox_command.working_counter != 1) {
- eoe->stats.tx_errors++;
- eoe->state = EC_EOE_RX_START;
- break;
- }
-
- // frame completely sent
- if (eoe->tx_offset >= eoe->tx_frame->skb->len) {
- eoe->stats.tx_packets++;
- eoe->stats.tx_bytes += eoe->tx_frame->skb->len;
- dev_kfree_skb(eoe->tx_frame->skb);
- kfree(eoe->tx_frame);
- eoe->state = EC_EOE_RX_START;
- }
- else { // send next fragment
- if (ec_eoe_send(eoe)) {
- dev_kfree_skb(eoe->tx_frame->skb);
- kfree(eoe->tx_frame);
- eoe->stats.tx_errors++;
- eoe->state = EC_EOE_RX_START;
- break;
- }
- }
-
- break;
-
- default:
- break;
- }
+ // call state function
+ eoe->state(eoe);
}
/*****************************************************************************/
@@ -466,41 +268,301 @@
Prints EoE object information.
*/
-void ec_eoe_print(const ec_eoe_t *eoe)
+void ec_eoe_print(const ec_eoe_t *eoe /**< EoE object */)
{
EC_INFO(" EoE slave %i\n", eoe->slave->ring_position);
- EC_INFO(" State %i\n", eoe->state);
EC_INFO(" Assigned device: %s (%s)\n", eoe->dev->name,
eoe->opened ? "opened" : "closed");
}
-/*****************************************************************************/
-
-/**
- Initializes a net_device structure for an EoE object.
-*/
-
-void ec_eoedev_init(struct net_device *dev /**< pointer to the net_device */)
-{
- ec_eoe_t *priv;
- unsigned int i;
-
- // initialize net_device
- ether_setup(dev);
- dev->open = ec_eoedev_open;
- dev->stop = ec_eoedev_stop;
- dev->hard_start_xmit = ec_eoedev_tx;
- dev->get_stats = ec_eoedev_stats;
-
- for (i = 0; i < ETH_ALEN; i++)
- dev->dev_addr[i] = i | (i << 4);
-
- // initialize private data
- priv = netdev_priv(dev);
- memset(priv, 0, sizeof(ec_eoe_t *));
-}
-
-/*****************************************************************************/
+/******************************************************************************
+ * STATE PROCESSING FUNCTIONS
+ *****************************************************************************/
+
+/**
+ State: RX_START.
+ Starts a new receiving sequence by queuing a command that checks the
+ slave's mailbox for a new command.
+*/
+
+void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE object */)
+{
+ ec_slave_mbox_prepare_check(eoe->slave);
+ ec_master_queue_command(eoe->slave->master, &eoe->slave->mbox_command);
+ eoe->state = ec_eoe_state_rx_check;
+}
+
+/*****************************************************************************/
+
+/**
+ State: RX_CHECK.
+ Processes the checking command sent in RX_START and issues a receive
+ command, if new data is available.
+*/
+
+void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE object */)
+{
+ if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
+ eoe->stats.rx_errors++;
+ eoe->state = ec_eoe_state_tx_start;
+ return;
+ }
+
+ if (!ec_slave_mbox_check(eoe->slave)) {
+ eoe->state = ec_eoe_state_tx_start;
+ return;
+ }
+
+ ec_slave_mbox_prepare_fetch(eoe->slave);
+ ec_master_queue_command(eoe->slave->master, &eoe->slave->mbox_command);
+ eoe->state = ec_eoe_state_rx_fetch;
+}
+
+/*****************************************************************************/
+
+/**
+ State: RX_FETCH.
+ Checks if the requested data of RX_CHECK was received and processes the
+ EoE command.
+*/
+
+void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE object */)
+{
+ size_t rec_size, data_size;
+ uint8_t *data, frame_type, last_fragment, time_appended;
+ uint8_t frame_number, fragment_offset, fragment_number;
+ off_t offset;
+
+ if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
+ eoe->stats.rx_errors++;
+ eoe->state = ec_eoe_state_tx_start;
+ return;
+ }
+
+ if (!(data = ec_slave_mbox_fetch(eoe->slave, 0x02, &rec_size))) {
+ eoe->stats.rx_errors++;
+ eoe->state = ec_eoe_state_tx_start;
+ return;
+ }
+
+ frame_type = EC_READ_U16(data) & 0x000F;
+
+ if (frame_type == 0x00) { // EoE Fragment Request
+ last_fragment = (EC_READ_U16(data) >> 8) & 0x0001;
+ time_appended = (EC_READ_U16(data) >> 9) & 0x0001;
+ fragment_number = EC_READ_U16(data + 2) & 0x003F;
+ fragment_offset = (EC_READ_U16(data + 2) >> 6) & 0x003F;
+ frame_number = (EC_READ_U16(data + 2) >> 12) & 0x000F;
+
+#if EOE_DEBUG_LEVEL > 0
+ EC_DBG("EoE RX fragment %i, offset %i, frame %i%s%s,"
+ " %i octets\n", fragment_number, fragment_offset,
+ frame_number,
+ last_fragment ? ", last fragment" : "",
+ time_appended ? ", + timestamp" : "",
+ time_appended ? rec_size - 8 : rec_size - 4);
+#endif
+
+#if EOE_DEBUG_LEVEL > 1
+ EC_DBG("");
+ for (i = 0; i < rec_size - 4; i++) {
+ printk("%02X ", data[i + 4]);
+ if ((i + 1) % 16 == 0) {
+ printk("\n");
+ EC_DBG("");
+ }
+ }
+ printk("\n");
+#endif
+
+ data_size = time_appended ? rec_size - 8 : rec_size - 4;
+
+ if (!fragment_number) {
+ if (eoe->rx_skb) {
+ EC_WARN("EoE RX freeing old socket buffer...\n");
+ dev_kfree_skb(eoe->rx_skb);
+ }
+
+ // new socket buffer
+ if (!(eoe->rx_skb = dev_alloc_skb(fragment_offset * 32))) {
+ if (printk_ratelimit())
+ EC_WARN("EoE RX low on mem. frame dropped.\n");
+ eoe->stats.rx_dropped++;
+ eoe->state = ec_eoe_state_tx_start;
+ return;
+ }
+
+ eoe->rx_skb_offset = 0;
+ eoe->rx_skb_size = fragment_offset * 32;
+ eoe->rx_expected_fragment = 0;
+ }
+ else {
+ if (!eoe->rx_skb) {
+ eoe->stats.rx_dropped++;
+ eoe->state = ec_eoe_state_tx_start;
+ return;
+ }
+
+ offset = fragment_offset * 32;
+ if (offset != eoe->rx_skb_offset ||
+ offset + data_size > eoe->rx_skb_size ||
+ fragment_number != eoe->rx_expected_fragment) {
+ eoe->stats.rx_errors++;
+ eoe->state = ec_eoe_state_tx_start;
+ dev_kfree_skb(eoe->rx_skb);
+ eoe->rx_skb = NULL;
+ return;
+ }
+ }
+
+ // copy fragment into socket buffer
+ memcpy(skb_put(eoe->rx_skb, data_size), data + 4, data_size);
+ eoe->rx_skb_offset += data_size;
+
+ if (last_fragment) {
+ // update statistics
+ eoe->stats.rx_packets++;
+ eoe->stats.rx_bytes += eoe->rx_skb->len;
+
+#if EOE_DEBUG_LEVEL > 0
+ EC_DBG("EoE RX frame completed with %u octets.\n",
+ eoe->rx_skb->len);
+#endif
+
+ // pass socket buffer to network stack
+ eoe->rx_skb->dev = eoe->dev;
+ eoe->rx_skb->protocol = eth_type_trans(eoe->rx_skb, eoe->dev);
+ eoe->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
+ if (netif_rx(eoe->rx_skb)) {
+ EC_WARN("EoE RX netif_rx failed.\n");
+ }
+ eoe->rx_skb = NULL;
+
+ eoe->state = ec_eoe_state_tx_start;
+ }
+ else {
+ eoe->rx_expected_fragment++;
+#if EOE_DEBUG_LEVEL > 0
+ EC_DBG("EoE RX expecting fragment %i\n",
+ eoe->rx_expected_fragment);
+#endif
+ eoe->state = ec_eoe_state_rx_start;
+ }
+ }
+ else {
+#if EOE_DEBUG_LEVEL > 0
+ EC_DBG("other frame received.\n");
+#endif
+ eoe->stats.rx_dropped++;
+ eoe->state = ec_eoe_state_tx_start;
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ State: TX START.
+ Starts a new transmit sequence. If no data is available, a new receive
+ sequence is started instead.
+*/
+
+void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE object */)
+{
+#if EOE_DEBUG_LEVEL > 0
+ unsigned int wakeup;
+#endif
+
+ spin_lock_bh(&eoe->tx_queue_lock);
+
+ if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) {
+ spin_unlock_bh(&eoe->tx_queue_lock);
+ // no data available.
+ // start a new receive immediately.
+ ec_eoe_state_rx_start(eoe);
+ return;
+ }
+
+ // take the first frame out of the queue
+ eoe->tx_frame = list_entry(eoe->tx_queue.next, ec_eoe_frame_t, queue);
+ list_del(&eoe->tx_frame->queue);
+ if (!eoe->tx_queue_active &&
+ eoe->tx_queued_frames == EC_EOE_TX_QUEUE_SIZE / 2) {
+ netif_wake_queue(eoe->dev);
+ eoe->tx_queue_active = 1;
+#if EOE_DEBUG_LEVEL > 0
+ wakeup = 1;
+#endif
+ }
+
+ eoe->tx_queued_frames--;
+ spin_unlock_bh(&eoe->tx_queue_lock);
+
+ eoe->tx_frame_number++;
+ eoe->tx_frame_number %= 16;
+ eoe->tx_fragment_number = 0;
+ eoe->tx_offset = 0;
+
+ if (ec_eoe_send(eoe)) {
+ dev_kfree_skb(eoe->tx_frame->skb);
+ kfree(eoe->tx_frame);
+ eoe->tx_frame = NULL;
+ eoe->stats.tx_errors++;
+ eoe->state = ec_eoe_state_rx_start;
+ return;
+ }
+
+#if EOE_DEBUG_LEVEL > 0
+ if (wakeup) EC_DBG("waking up TX queue...\n");
+#endif
+
+ eoe->state = ec_eoe_state_tx_sent;
+}
+
+/*****************************************************************************/
+
+/**
+ State: TX SENT.
+ Checks is the previous transmit command succeded and sends the next
+ fragment, if necessary.
+*/
+
+void ec_eoe_state_tx_sent(ec_eoe_t *eoe /**< EoE object */)
+{
+ if (eoe->slave->mbox_command.state != EC_CMD_RECEIVED) {
+ eoe->stats.tx_errors++;
+ eoe->state = ec_eoe_state_rx_start;
+ return;
+ }
+
+ if (eoe->slave->mbox_command.working_counter != 1) {
+ eoe->stats.tx_errors++;
+ eoe->state = ec_eoe_state_rx_start;
+ return;
+ }
+
+ // frame completely sent
+ if (eoe->tx_offset >= eoe->tx_frame->skb->len) {
+ eoe->stats.tx_packets++;
+ eoe->stats.tx_bytes += eoe->tx_frame->skb->len;
+ dev_kfree_skb(eoe->tx_frame->skb);
+ kfree(eoe->tx_frame);
+ eoe->tx_frame = NULL;
+ eoe->state = ec_eoe_state_rx_start;
+ }
+ else { // send next fragment
+ if (ec_eoe_send(eoe)) {
+ dev_kfree_skb(eoe->tx_frame->skb);
+ kfree(eoe->tx_frame);
+ eoe->tx_frame = NULL;
+ eoe->stats.tx_errors++;
+ eoe->state = ec_eoe_state_rx_start;
+ }
+ }
+}
+
+/******************************************************************************
+ * NET_DEVICE functions
+ *****************************************************************************/
/**
Opens the virtual network device.
@@ -567,8 +629,8 @@
spin_lock_bh(&eoe->tx_queue_lock);
list_add_tail(&frame->queue, &eoe->tx_queue);
- eoe->queued_frames++;
- if (eoe->queued_frames == EC_EOE_TX_QUEUE_SIZE) {
+ eoe->tx_queued_frames++;
+ if (eoe->tx_queued_frames == EC_EOE_TX_QUEUE_SIZE) {
netif_stop_queue(dev);
eoe->tx_queue_active = 0;
}
@@ -576,7 +638,7 @@
#if EOE_DEBUG_LEVEL > 0
EC_DBG("EoE TX queued frame with %i octets (%i frames queued).\n",
- skb->len, eoe->queued_frames);
+ skb->len, eoe->tx_queued_frames);
if (!eoe->tx_queue_active)
EC_WARN("EoE TX queue is now full.\n");
#endif