]> rtime.felk.cvut.cz Git - frescor/fna.git/blobdiff - src_frescan/frescan.c
changes to use the FRSH FSA module to do the analysis and spare capacity. TODO: finis...
[frescor/fna.git] / src_frescan / frescan.c
index ae6134dfda45bcb922eaba474e3bb4c7db7206e2..3c6fc8ba5ec23dc3d8fa49e1f035dea30b1ba788 100644 (file)
  *
  * @license
  *
- * See MaRTE OS license
+ * -----------------------------------------------------------------------
+ *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
+ *
+ *    Universidad de Cantabria,              SPAIN
+ *    University of York,                    UK
+ *    Scuola Superiore Sant'Anna,            ITALY
+ *    Kaiserslautern University,             GERMANY
+ *    Univ. Politécnica  Valencia,           SPAIN
+ *    Czech Technical University in Prague,  CZECH REPUBLIC
+ *    ENEA                                   SWEDEN
+ *    Thales Communication S.A.              FRANCE
+ *    Visual Tools S.A.                      SPAIN
+ *    Rapita Systems Ltd                     UK
+ *    Evidence                               ITALY
+ *
+ *    See http://www.frescor.org for a link to partners' websites
+ *
+ *           FRESCOR project (FP6/2005/IST/5-034026) is funded
+ *        in part by the European Union Sixth Framework Programme
+ *        The European Union is not liable of any use that may be
+ *        made of this code.
+ *
+ *  This file is part of FRESCAN
+ *
+ *  FRESCAN is free software; you can  redistribute it and/or  modify
+ *  it under the terms of  the GNU General Public License as published by
+ *  the Free Software Foundation;  either  version 2, or (at  your option)
+ *  any later version.
+ *
+ *  FRESCAN  is distributed  in  the hope  that  it  will  be useful,  but
+ *  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
+ *  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
+ *  General Public License for more details.
+ *
+ *  You should have  received a  copy of  the  GNU  General Public License
+ *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
+ *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
+ *  02111-1307, USA.
+ *
+ * As a special exception, including FRESCAN header files in a file,
+ * instantiating FRESCAN generics or templates, or linking other files
+ * with FRESCAN objects to produce an executable application, does not
+ * by itself cause the resulting executable application to be covered
+ * by the GNU General Public License. This exception does not
+ * however invalidate any other reasons why the executable file might be
+ * covered by the GNU Public License.
+ * -----------------------------------------------------------------------
  *
  */
 
 #include <string.h> // memcpy
 
 #include <drivers/can.h>       // can_chip_t, can_frame_t
-#include <drivers/frescan.h>   // frescan_init_params_t, frescan_send_params_t
+#include "frescan.h"           // frescan_init_params_t, frescan_send_params_t
 #include "frescan_queues.h"    // init, enqueue, requeue
 #include "frescan_data.h"      // init, the_networks
 #include "frescan_servers.h"   // init, frame_sent
 #include "frescan_debug.h"     // DEBUG
 #include "frescan_id.h"        // frescan_id_set_field, frescan_id_get_field
 #include "frescan_hw_buffer.h" // frescan_hw_buffer_update
-#include "frescan_servers_replenishments.h" // frescan_replenishments_xxx
+#include "frescan_packets.h"
 
 static int frescan_hook_frame_recv (const struct can_chip_t *chip,
                                     struct can_frame_t *frame);
 
 static int frescan_hook_frame_sent(const struct can_chip_t *chip);
 
+static int frescan_hook_frame_aborted(const struct can_chip_t *chip);
+
 /**
  * frescan_init - initializes the network and the internal structures
  *
@@ -71,7 +119,7 @@ int frescan_init(frescan_init_params_t *params)
 
         fd = open (can_path, O_RDWR);
         if (fd == -1) {
-                ERROR ("could not open /dev/can%u\n", params->net);
+                FRESCAN_ERROR ("could not open /dev/can%u\n", params->net);
                 return -1;
         }
 
@@ -93,23 +141,30 @@ int frescan_init(frescan_init_params_t *params)
 
         ret = ioctl(fd, CAN_IOCTL_SET_FILTERS, &ioctl_filters);
         if (ret == -1) {
-                ERROR ("ioctl CAN_IOCTL_SET_FILTERS failed /dev/can%u\n",
+                FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_FILTERS failed /dev/can%u\n",
                        params->net);
                 return -1;
         }
 
-        DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set tx and rx hooks\n");
+        DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set tx, rx, abort hooks\n");
 
         ret = ioctl(fd, CAN_IOCTL_SET_TX_HOOK, frescan_hook_frame_sent);
         if (ret == -1) {
-                ERROR ("ioctl CAN_IOCTL_SET_TX_HOOK failed /dev/can%u\n",
+                FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_TX_HOOK failed /dev/can%u\n",
                        params->net);
                 return -1;
         }
 
         ret = ioctl(fd, CAN_IOCTL_SET_RX_HOOK, frescan_hook_frame_recv);
         if (ret == -1) {
-                ERROR ("ioctl CAN_IOCTL_SET_RX_HOOK failed /dev/can%u\n",
+                FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_RX_HOOK failed /dev/can%u\n",
+                       params->net);
+                return -1;
+        }
+
+        ret = ioctl(fd, CAN_IOCTL_SET_AB_HOOK, frescan_hook_frame_aborted);
+        if (ret == -1) {
+                FRESCAN_ERROR ("ioctl CAN_IOCTL_SET_AB_HOOK failed /dev/can%u\n",
                        params->net);
                 return -1;
         }
@@ -118,31 +173,25 @@ int frescan_init(frescan_init_params_t *params)
 
         ret = frescan_data_init(fd, params);
         if (ret != 0) {
-                ERROR("could not initialize the global data\n");
+                FRESCAN_ERROR("could not initialize the global data\n");
                 return -1;
         }
 
         ret = frescan_packets_init();
         if (ret != 0) {
-                ERROR("could not initialize the packets pool\n");
+                FRESCAN_ERROR("could not initialize the packets pool\n");
                 return -1;
         }
 
         ret = frescan_queues_init(&the_networks[params->net].queues, params);
         if (ret != 0) {
-                ERROR("could not initialize the queues\n");
+                FRESCAN_ERROR("could not initialize the queues\n");
                 return -1;
         }
 
         ret = frescan_servers_init(params->net);
         if (ret != 0) {
-                ERROR("could not initialize the servers\n");
-                return -1;
-        }
-
-        ret = frescan_replenishments_init(params->net);
-        if (ret != 0) {
-                ERROR("could not initialize the replenishments\n");
+                FRESCAN_ERROR("could not initialize the servers\n");
                 return -1;
         }
 
@@ -172,7 +221,7 @@ int frescan_send(const frescan_send_params_t *params,
               "checking arguments (msg size=%d)\n", size);
 
         if ((params == NULL) || (msg == NULL) || (size == 0)) {
-                ERROR("arguments are not ok\n");
+                FRESCAN_ERROR("arguments are not ok\n");
                 return -1;
         }
 
@@ -183,7 +232,7 @@ int frescan_send(const frescan_send_params_t *params,
         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
 
         if (packet == NULL) {
-                ERROR("could not allocate packet\n");
+                FRESCAN_ERROR("could not allocate packet\n");
                 return -1;
         }
         packet->flags = params->flags; // set the flags (to remember them)
@@ -195,7 +244,7 @@ int frescan_send(const frescan_send_params_t *params,
         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
 
         if (packet->frame == NULL) {
-                ERROR("could not allocate frame\n");
+                FRESCAN_ERROR("could not allocate frame\n");
                 return -1;
         }
 
@@ -256,7 +305,7 @@ int frescan_send(const frescan_send_params_t *params,
                 FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
 
                 if (ret != 0) {
-                        ERROR("could not enqueue the packet\n");
+                        FRESCAN_ERROR("could not enqueue the packet\n");
                         return -1;
                 }
         } else {
@@ -265,7 +314,7 @@ int frescan_send(const frescan_send_params_t *params,
                 FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
 
                 if (ret != 0) {
-                        ERROR("could not enqueue the packet\n");
+                        FRESCAN_ERROR("could not enqueue the packet\n");
                         return -1;
                 }
         }
@@ -275,7 +324,7 @@ int frescan_send(const frescan_send_params_t *params,
         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
 
         if (ret != 0) {
-                ERROR("could not update hw buffer\n");
+                FRESCAN_ERROR("could not update hw buffer\n");
                 return -1;
         }
 
@@ -321,12 +370,9 @@ int frescan_recv(const frescan_recv_params_t *params,
         pqueue = the_networks[params->net].queues.rx_channel_queues
                                                              [params->channel];
 
-        FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock);
         ret = frescan_pqueue_dequeue(pqueue, &head, prio, blocking);
-        FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
-
         if (ret != 0) {
-                ERROR ("could not dequeue packet\n");
+                FRESCAN_ERROR ("could not dequeue packet\n");
                 return -1;
         }
 
@@ -337,7 +383,7 @@ int frescan_recv(const frescan_recv_params_t *params,
                         *recv_bytes = 0;
                         return 0;
                 } else {
-                        ERROR ("blocking true, and packet = null\n");
+                        FRESCAN_ERROR ("blocking true, and packet = null\n");
                         return -1;
                 }
         }
@@ -356,19 +402,21 @@ int frescan_recv(const frescan_recv_params_t *params,
                        packet->frame->dlc);
                 *recv_bytes += packet->frame->dlc;
 
+                *from = (frescan_node_t)frescan_id_get_field(packet->frame->id,
+                                                             FRESCAN_FIELD_SRC);
                 DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
-                      "ID Packet, dlc: %u, frame pool pos: %u\n",
-                      packet->frame->dlc, packet->frame->pool_pos);
+                      "ID Packet, dlc: %u, frame pool pos: %u, from:%u\n",
+                      packet->frame->dlc, packet->frame->pool_pos, *from);
 
                 ret = can_framespool_free(packet->frame);
                 if (ret != 0) {
-                        ERROR("could not free frame\n");
+                        FRESCAN_ERROR("could not free frame\n");
                         return -1;
                 }
 
                 ret = frescan_packets_free(packet);
                 if (ret != 0) {
-                        ERROR("could not free packet\n");
+                        FRESCAN_ERROR("could not free packet\n");
                         return -1;
                 }
         }
@@ -378,7 +426,7 @@ int frescan_recv(const frescan_recv_params_t *params,
         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
 
         if (ret != 0) {
-                ERROR("could not free head packet\n");
+                FRESCAN_ERROR("could not free head packet\n");
                 return -1;
         }
 
@@ -441,10 +489,10 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip,
         packet = frescan_packets_alloc();
         packet->frame = frame;
 
-        if (frag_id == 0) {
-                head = the_networks[net].id_fp_queues[prio];
+        if (frag_id == FRESCAN_MX_IDS) {
+                head = the_networks[net].id_fp_queues[src][prio];
         } else {
-                head = the_networks[net].id_queues[frag_id];
+                head = the_networks[net].id_queues[src][frag_id];
         }
 
         if (head == NULL) {
@@ -454,10 +502,10 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip,
                 head = frescan_packets_alloc();
                 INIT_LIST_HEAD(&head->msg_list);
 
-                if (frag_id == 0) {
-                        the_networks[net].id_fp_queues[prio] = head;
+                if (frag_id == FRESCAN_MX_IDS) {
+                        the_networks[net].id_fp_queues[src][prio] = head;
                 } else {
-                        the_networks[net].id_queues[frag_id] = head;
+                        the_networks[net].id_queues[src][frag_id] = head;
                 }
         }
 
@@ -471,14 +519,14 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip,
                 pqueue = the_networks[net].queues.rx_channel_queues[channel];
                 ret = frescan_pqueue_enqueue(pqueue, head, prio);
                 if (ret != 0) {
-                        ERROR("could not enqueue message in channel queue\n");
+                        FRESCAN_ERROR("could not enqueue message in channel queue\n");
                         return -1;
                 }
 
-                if (frag_id == 0) {
-                        the_networks[net].id_fp_queues[prio] = NULL;
+                if (frag_id == FRESCAN_MX_IDS) {
+                        the_networks[net].id_fp_queues[src][prio] = NULL;
                 } else {
-                        the_networks[net].id_queues[frag_id] = NULL;
+                        the_networks[net].id_queues[src][frag_id] = NULL;
                 }
 
         } else {
@@ -493,7 +541,6 @@ static int frescan_hook_frame_recv (const struct can_chip_t *chip,
         return 0;
 };
 
-
 /**
  * frescan_hook_frame_sent - frame sent hook
  *
@@ -512,26 +559,20 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip)
 
         packet = the_networks[chip->minor].last_packet;
 
+        id = frescan_id_get_field(packet->frame->id,
+                                  FRESCAN_FIELD_FRAG_ID);
+
         DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
-              "frame sent, minor:%u flags:0x%X\n",
-              chip->minor, packet->flags);
+              "frame sent, minor:%u flags:0x%X frag_id:0x%X\n",
+              chip->minor, packet->flags, id);
 
         if (packet->flags & FRESCAN_SS) {
-                id = frescan_id_get_field(packet->frame->id,
-                                          FRESCAN_FIELD_FRAG_ID);
-
                 DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
                       "calling frame_sent + program repl for id:%u\n", id);
 
-                ret = frescan_replenishment_program(chip->minor, id);
-                if (ret != 0) {
-                        ERROR("could not program replenishment\n");
-                        return -1;
-                }
-
-                ret = frescan_servers_frame_sent(chip->minor, id);
+                ret = frescan_servers_frame_sent(chip->minor, id, packet);
                 if (ret != 0) {
-                        ERROR("could not let the server a frame was sent\n");
+                        FRESCAN_ERROR("could not let the server a frame was sent\n");
                         return -1;
                 }
         }
@@ -551,7 +592,7 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip)
                         pqueue = the_networks[chip->minor].queues.tx_fp_queue;
                         ret = frescan_pqueue_requeue(pqueue, packet, prio);
                         if (ret != 0) {
-                                ERROR("could not requeue the packet\n");
+                                FRESCAN_ERROR("could not requeue the packet\n");
                                 return -1;
                         }
                 } else if (packet->flags & FRESCAN_SS) {
@@ -559,11 +600,11 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip)
                               "requeue server %u packet\n", id);
                         ret = frescan_servers_requeue(chip->minor, id, packet);
                         if (ret != 0) {
-                                ERROR("could not requeue the packet\n");
+                                FRESCAN_ERROR("could not requeue the packet\n");
                                 return -1;
                         }
                 } else {
-                        ERROR("flags are not correct\n");
+                        FRESCAN_ERROR("flags are not correct\n");
                         return -1;
                 }
         } else {
@@ -572,26 +613,89 @@ static int frescan_hook_frame_sent(const struct can_chip_t *chip)
 
                 ret = can_framespool_free(packet->frame);
                 if (ret != 0)  {
-                        ERROR ("could not free the frame\n");
+                        FRESCAN_ERROR ("could not free the frame\n");
                         return ret;
                 }
 
                 ret = frescan_packets_free(packet);
                 if (ret != 0)  {
-                        ERROR ("could not free the packet\n");
+                        FRESCAN_ERROR ("could not free the packet\n");
                         return ret;
                 }
 
-                // TODO: signal semaphores, server consume budget...
+                // TODO: signal semaphore for send_sync
         }
 
         the_networks[chip->minor].last_packet = NULL;
 
         ret = frescan_hw_buffer_update(chip->minor);
         if (ret != 0) {
-                ERROR("could not update hw buffer\n");
+                FRESCAN_ERROR("could not update hw buffer\n");
                 return -1;
         }
 
         return 0;
 };
+
+/**
+ * frescan_hook_frame_aborted - frame frame aborted hook
+ *
+ * This function will be called by the CAN driver's IRQ handler when a frame
+ * is aborted (because another frame with higher priority is waiting). We
+ * have to requeue the frame and update the buffer.
+ */
+
+static int frescan_hook_frame_aborted(const struct can_chip_t *chip)
+{
+        int ret;
+        frescan_packet_t *packet;
+        frescan_prio_queue_t *pqueue;
+        frescan_prio_t prio;
+        frescan_ss_t id;
+
+        packet = the_networks[chip->minor].last_packet;
+
+        id = frescan_id_get_field(packet->frame->id,
+                                  FRESCAN_FIELD_FRAG_ID);
+
+        DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
+              "frame aborted, minor:%u flags:0x%X frag_id:0x%X\n",
+              chip->minor, packet->flags, id);
+
+        if (packet->flags & FRESCAN_FP) {
+                prio = frescan_id_get_field(packet->frame->id,
+                                            FRESCAN_FIELD_PRIO);
+
+                DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
+                      "requeue fp packet, prio:%u\n", prio);
+
+                pqueue = the_networks[chip->minor].queues.tx_fp_queue;
+                ret = frescan_pqueue_requeue(pqueue, packet, prio);
+                if (ret != 0) {
+                        FRESCAN_ERROR("could not requeue the packet\n");
+                        return -1;
+                }
+        } else if (packet->flags & FRESCAN_SS) {
+                DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
+                      "requeue server %u packet\n", id);
+
+                ret = frescan_servers_requeue(chip->minor, id, packet);
+                if (ret != 0) {
+                        FRESCAN_ERROR("could not requeue the packet\n");
+                        return -1;
+                }
+        } else {
+                FRESCAN_ERROR("flags are not correct\n");
+                return -1;
+        }
+
+        the_networks[chip->minor].last_packet = NULL;
+
+        ret = frescan_hw_buffer_update(chip->minor);
+        if (ret != 0) {
+                FRESCAN_ERROR("could not update hw buffer\n");
+                return -1;
+        }
+
+        return 0;
+}