+/*!
+ * @file frescan_types.h
+ *
+ * @brief types used in FRESCAN
+ *
+ * @version 0.01
+ *
+ * @date 16-Nov-2008
+ *
+ * @author
+ * Daniel Sangorrin
+ *
+ * @comments
+ *
+ * This file contains the types used in FRESCAN protocol
+ *
+ * @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.
+ * -----------------------------------------------------------------------
+ *
+ */
+
+#ifndef _FRESCAN_TYPES_H_
+#define _FRESCAN_TYPES_H_
+
+#include <stdint.h> // uint8_t, uint32_t..
+#include <stdbool.h> // bool
+#include <unistd.h> // size_t
+#include <time.h> // struct timespec, timer_t
+#include <semaphore.h> // sem_t
+
+#include "frsh.h" // for frsh_contract_t
+#include "fsa.h" // for frsh_sa_scenario_t
+#include "fosa_opaque_types.h" // for FOSA_ETIMEDOUT
+#include "fosa_threads_and_signals.h" // fosa_thread_id_t
+#include "frescan_config.h"
+
+#include <misc/linux_list.h> // struct list_head
+#include <drivers/can.h> // can_frame_t
+#include <misc/freelist.h> // freelist_t
+
+typedef uint8_t frescan_network_t;
+typedef uint8_t frescan_node_t;
+typedef uint8_t frescan_channel_t;
+typedef uint8_t frescan_prio_t;
+typedef uint8_t frescan_ss_t;
+typedef uint32_t frescan_budget_t;
+
+typedef struct {
+ int size;
+ frescan_ss_t ss[FRESCAN_BWRES_MAX_GROUP_OPS];
+} frescan_ss_group_t;
+
+/**
+ * frescan_flags_t - frescan flags
+ *
+ * @FRESCAN_SS: send the message using sporadic servers
+ * @FRESCAN_FP: send the message using fixed priorities
+ * @FRESCAN_POLL: no buffer copy, only pointer and use the ID to poll status
+ * @FRESCAN_SYNC: no buffer copy, only pointer and block until it is sent
+ * @FRESCAN_ASYNC: use buffer copy and return immediately
+ */
+
+typedef enum {
+ FRESCAN_SS = 1<<4, // sporadic server
+ FRESCAN_FP = 1<<3, // fixed priorities
+ FRESCAN_POLL = 1<<2, // polling
+ FRESCAN_SYNC = 1<<1, // synchronous
+ FRESCAN_ASYNC = 1 // asynchronous
+} frescan_flags_t;
+
+/**
+ * frescan_send_params_t - send parameters
+ *
+ * @net: the network to use
+ * @to: the node where the message shoud be sent to
+ * @channel: the channel in 'to' where the message shoud be sent to
+ * @flags: the flags (see frescan_flags_t)
+ * @prio: the priority for the message if (flags & FRESCAN_FP)
+ * @ss: the sporadic server for the message if (flags & FRESCAN_SS)
+ */
+
+typedef struct {
+ frescan_network_t net;
+ frescan_node_t to;
+ frescan_channel_t channel;
+ frescan_flags_t flags;
+ union {
+ frescan_prio_t prio;
+ frescan_ss_t ss;
+ };
+} frescan_send_params_t;
+
+/**
+ * frescan_recv_params_t - receive parameters
+ *
+ * @net: the network to use
+ * @channel: the channel from which we want to extract a message
+ * @flags: FRESCAN_SYNC/ASYNC
+ */
+
+typedef struct {
+ frescan_network_t net;
+ frescan_channel_t channel;
+ frescan_flags_t flags;
+} frescan_recv_params_t;
+
+/**
+ * frescan_init_params_t - initialization parameters
+ *
+ * @net: network to initialize (minor number ie: /dev/can0 -> 0)
+ * @node: set the local node identificator
+ * @tx_fp_max_prio: maximum number of priorities for the fixed priority
+ * transmission queues. (prio = 0 .. max_prio - 1)
+ * @rx_num_of_channels: number of rx channels (0 .. rx_num_of_channels - 1)
+ * @rx_channel_max_prio: array (range rx_num_of_channels) saying the number
+ * of priorities for each channel. If this parameter is
+ * NULL tx_fp_max_prio will be used for all queues.
+ */
+
+typedef struct {
+ frescan_network_t net;
+ frescan_node_t node;
+ uint32_t tx_fp_max_prio;
+ uint32_t rx_num_of_channels;
+ uint32_t *rx_channel_max_prio;
+} frescan_init_params_t;
+
+/**
+ * frescan_packet_t - a frescan packet
+ *
+ * This structure is very important and it is used to store a FRESCAN packet.
+ * As we support fragmentation, a FRESCAN packet can be composed of several
+ * CAN frames. This 'frescan_packet_t' structure is used in two main cases:
+ *
+ * 1.- When we are sending data. In this case, the buffer pointers store the
+ * real data we want to sent and we use a 'buffer_read_pointer' to know
+ * how many bytes of the buffer we already sent. In 'frame', we store the
+ * last sent frame (with the corresponding CAN id fields). We will have
+ * to update the fragmentation fields as long as we send more packets.
+ * The 'fifo_list' is used to chained frescan packets of the same priority
+ * or that belong to the same sporadic server. Finally, 'flags', specify
+ * if we are sending ASYNC or SYNC. If we are sending SYNC the buffer
+ * pointers are pointing to the buffer sent by the user (zero copying),
+ * while if we use ASYNC, a copy of the data is done to the buffer.
+ *
+ * 2.- When we are receiving data, we only use 'frame' and 'fifo_list' fields.
+ * The IRQ handler of the chip allocates a CAN frame and calls to our hook.
+ * We store the pointer to that frame in 'frame' and we make a chain with
+ * frames of the same message (using the fragmentation fields). When we
+ * have all of them, we move the packet list to the corresponding
+ * receiving channel to wait for the user to perform a receive operation
+ * when we will copy the data and free both the packets and the frames.
+ *
+ * @flags: to know if the packet is to be sent SYNC or ASYNC, FP or SERVER...
+ * @frame: pointer to the last sent frame or the received frame
+ * @fifo_list: list to put several packets together
+ * @msg_list: list to put packets of the same message together
+ * @buffer_head: pointer to first byte of the buffer that is going to be sent
+ * @buffer_read_pointer: pointer to the part of the buffer being read
+ * @buffer_pending_bytes: bytes waiting to be sent
+ * @timestamp: time when the packet was enqueued (activation time)
+ * @pool_pos: position in the packets pool to know how to free it
+ *
+ * NOTE: the buffers could also be used on the receiving part to support
+ * sequential reads, instead of reading the whole message at once.
+ *
+ */
+
+typedef struct {
+ frescan_flags_t flags;
+ struct can_frame_t *frame;
+ struct list_head fifo_list;
+ struct list_head msg_list;
+ uint8_t *buffer_head; // only for sending packets
+ uint8_t *buffer_read_pointer; // only for sending packets
+ uint32_t buffer_pending_bytes; // only for sending packets
+ struct timespec timestamp;
+ int pool_pos;
+} frescan_packet_t;
+
+/**
+ * frescan_repl_op_t - a replenishment operation
+ *
+ * @when: when the replenishment operation is programmed at
+ * @amount: number of frames to add to the available budget
+ * @repl_list: to chain the replenishments for a certain sporadic server
+ * @pool_pos: to know how to free it from the replenishment pool
+ */
+
+typedef struct {
+ struct timespec when;
+ frescan_budget_t amount;
+ struct list_head repl_list;
+ int pool_pos;
+} frescan_repl_op_t;
+
+/**
+ * frescan_server_params_t - server parameters
+ *
+ * @budget: the budget in CAN 8-byte frames
+ * @period: the replenishment period for the server
+ * @prio: the priority of the server
+ */
+
+typedef struct {
+ frescan_budget_t budget;
+ struct timespec period;
+ frescan_prio_t prio;
+} frescan_server_params_t;
+
+/**
+ * frescan_ss_data_t - sporadic server data
+ *
+ * @committed_params: the committed params (C,T,Prio) for the server
+ * @perceived_params: the params perceived by the user (we can lie to him)
+ * @current_priority: the current priority (0=background)
+ * @repl_list: the list of pending replenishment operations
+ * @repl_timer: the timer for the replenishments associated to this server
+ * NOTE: we could use a single timer for all but for now this is simpler
+ * @act_time: the last activation time for the server
+ * @packet_list: the packets enqueued on this server
+ * @servers_list: the list of servers
+ */
+
+typedef struct {
+ frescan_server_params_t committed_params;
+ frescan_server_params_t perceived_params;
+ frescan_network_t net;
+ frescan_ss_t id;
+ frescan_prio_t current_priority;
+ frescan_budget_t pending_packets;
+ frescan_repl_op_t replenishments; // TODO: use struct list_head
+ timer_t repl_timer;
+ struct timespec act_time;
+ frescan_packet_t packet_list; // TODO: use struct list_head
+ struct list_head servers_list;
+} frescan_ss_data_t;
+
+/**
+ * frescan_prio_queue_t - priority queue
+ *
+ * FRESCAN priority queues are implemented as an array of one 'fifo_queue' for
+ * each priority. Where the 'fifo_queues' are implemented using the
+ * 'struct list_head fifo_list;' field of each packet structure (Linux lists).
+ *
+ * So far mutual exclusion is achieved by disabling interrupts and
+ * synchronization is done using a semaphore. This is because the queues
+ * are accesed concurrently from user threads and the IRQ handler.
+ *
+ * @net: the network this priority queue belongs to (mainly for locking)
+ * @fifo_queues: an array of packets for each priority where each packet
+ * is just the head of a fifo_list. The array is allocated
+ * from the heap, using malloc, at initialization with range
+ * 0..max_prio-1
+ * @max_prio: defines the number of priorities as (0 .. max_prio - 1)
+ * @sem: semaphore used for synchronization
+ */
+
+typedef struct {
+ frescan_network_t net;
+ frescan_packet_t *fifo_queues;
+ uint32_t max_prio;
+ sem_t sem;
+} frescan_prio_queue_t;
+
+/**
+ * frescan_queues_t - the set of FRESCAN queues for each instance of a protocol
+ *
+ * @tx_fp_queue: priority queue for the fixed priority packets
+ * @rx_channel_queues: a priority queue for each receiving channel
+ *
+ * TODO: add here the sporadic server queues...
+ */
+
+typedef struct {
+ frescan_prio_queue_t *tx_fp_queue;
+ frescan_prio_queue_t **rx_channel_queues;
+ uint32_t num_rx_channels;
+} frescan_queues_t;
+
+
+// BWRES TYPES
+
+typedef unsigned int frescan_bwres_robj_id_t; /* 0 .. MX_REPLY_OBJECTS-1 */
+#define FRESCAN_ETIMEDOUT FOSA_ETIMEDOUT
+
+/**
+ * frescan_bwres_vres_t - a frescan virtual resource
+ *
+ * @contract: the contract of the virtual resource
+ * @node: the node where the vres belongs to
+ * @ss: the sporadic server identifier
+ * @list: the list of vres. Note that this is the list of all the vres
+ * in the network instace. As this is a master-slave protocol the master
+ * knows everything about the contracts of the rest of nodes.
+ */
+
+typedef enum {
+ FRESCAN_BWRES_MC_PERIOD_DEC = 1<<5,
+ FRESCAN_BWRES_MC_PERIOD_INC = 1<<4,
+ FRESCAN_BWRES_MC_BUDGET_DEC = 1<<3,
+ FRESCAN_BWRES_MC_BUDGET_INC = 1<<2,
+ FRESCAN_BWRES_MC_PRIO_DEC = 1<<1,
+ FRESCAN_BWRES_MC_PRIO_INC = 1
+} frescan_bwres_mode_change_type_t;
+
+typedef struct {
+ frsh_contract_t contract;
+ frescan_node_t node;
+ frescan_ss_t ss;
+ frsh_sa_vres_id_t fsa_vres_global_id;
+ struct list_head list;
+ // mode change variables
+ frsh_sa_time_t old_c;
+ frsh_sa_time_t old_t;
+ frsh_sa_prio_t old_p;
+ frescan_bwres_mode_change_type_t mode_change_type;
+ struct list_head mode_change_list;
+} frescan_bwres_vres_t;
+
+/**
+ * frescan_bwres_request_data_t
+ *
+ * This are the data contained in a request to perform the negotiation of
+ * contracts.
+ *
+ * @type: indicates the type of the request
+ * @contract: a contract to (re)negotiate
+ * @contract_ref: a pointer to the contract to (re)negotiate (optimization)
+ * @ss: the local sporadic server ID
+ * @request_node: the node that performed the request
+ * @req: the request id of the SLAVE to identify the request in the reply
+ * @return_value: the value returned in a Reply (accepted or not)
+ * @final_values: the values for the ss after the negotiation
+ * @net: the network instance where this request belongs to
+ * @robj: a reply object to wait until a negotiation is completed
+ *
+ */
+
+typedef uint16_t frescan_bwres_request_id_t; /* 0 .. MX_REQUESTS */
+
+typedef enum {
+ FRESCAN_BWRES_REQ_GN = 0, // group negotiation
+ FRESCAN_BWRES_REP_GN = 1, // negotiation reply
+ FRESCAN_BWRES_REQ_MC = 2, // mode change
+ FRESCAN_BWRES_REQ_RES = 3, // reservation negotiation
+ FRESCAN_BWRES_REQ_RES_GET = 4, // reservation get values
+ FRESCAN_BWRES_REP_RES_GET = 5, // reservation get values reply
+ FRESCAN_BWRES_REQ_RES_SET = 6, // reservation set values
+ FRESCAN_BWRES_REQ_RES_COMMIT = 7, // reservation commit
+ FRESCAN_BWRES_REQ_RES_CANCEL = 8, // reservation cancel
+} frescan_bwres_request_type_t;
+
+typedef enum {
+ FRESCAN_BWRES_REQ_ACCEPTED = 0, // negotiation accepted
+ FRESCAN_BWRES_REQ_NOT_ACCEPTED = 1, // negotiation not accepted
+ FRESCAN_BWRES_REQ_ERROR = 2, // there was an error
+} frescan_bwres_request_retval_t;
+
+typedef struct {
+ frescan_network_t net;
+ frescan_bwres_request_type_t type;
+ frescan_bwres_request_id_t req;
+ frescan_node_t request_node;
+ frescan_bwres_request_retval_t return_value;
+ frescan_bwres_robj_id_t robj;
+ // contracts and ss groups
+ frsh_contracts_group_t *contracts_to_neg;
+ frsh_contracts_group_t *contracts_to_reneg;
+ frescan_ss_group_t *ss_to_reneg;
+ frescan_ss_group_t *ss_to_cancel;
+ frescan_ss_group_t *ss_new;
+ // contracts and ss groups data (to store the info at master node)
+ frsh_contracts_group_t contracts_to_neg_data;
+ frsh_contracts_group_t contracts_to_reneg_data;
+ frescan_ss_group_t ss_to_reneg_data;
+ frescan_ss_group_t ss_to_cancel_data;
+ frescan_ss_group_t ss_new_data;
+ // for FRESCAN_BWRES_REQ_MC
+ frescan_bwres_mode_change_type_t mode_change_type;
+} frescan_bwres_request_data_t;
+
+/**
+ * frescan_bwres_sa_scenario_t - the scheduling analysis scenario
+ */
+
+typedef struct {
+ frescan_prio_t max_prio;
+ frescan_prio_t min_prio;
+} frescan_bwres_sa_init_params_t;
+
+typedef struct {
+ frescan_bwres_sa_init_params_t init_params;
+ frescan_bwres_vres_t vres_pool[FRESCAN_MX_NODES][FRESCAN_MX_IDS];
+ frescan_bwres_vres_t vres_head; // TODO: use struct list_head
+ freelist_t fsa_vres_global_id_freelist;
+ frsh_sa_scenario_t fsa_scenario;
+ frsh_contracts_group_t backup_contracts_to_reneg;
+ frsh_contracts_group_t backup_contracts_to_cancel;
+} frescan_bwres_sa_scenario_t;
+
+/**
+ * frescan_network_data_t - data for each network instance
+ *
+ * @local_node: the local node id for that network. The implementation does not
+ * support several interfaces for the same network.
+ * @fd: file descriptor associated to /dev/canXX
+ * @repl_thread_id: replenishment thread id
+ * @manager_thread_id: manager thread id
+ * @acceptor_thread_id: acceptor thread id
+ * @neg_messages_ss_id: sporadic server for negotiation messages
+ * @queues: the queues of this network instance
+ * @last_packet: pointer to the last packet from which a frame was inserted
+ * in the chip and its transmission is not complete.
+ * @last_packet_prio: prio of the packet in the buffer
+ * @id_queues: queues to store received packets while the whole message is
+ * not complete (fragmentation). (id = 0 .. FRESCAN_MX_IDS - 1)
+ * @id_fp_queues: the same as id_queues but for fp messages, which have
+ * id=FRESCAN_MX_IDS and are distinguised through their
+ * priorities.
+ * @scenario: the scheduling analysis scenario for the network
+ * @mode_change_list: list of sa_vres that have changes to commit
+ * @mode_change_type: what type of changes are to commit
+ *
+ * the implementation can handle several FRESCAN networks at the same time
+ * in the same node, so we need a place to store its internal data. The data
+ * is allocated as an array where the index is the MINOR number (which also
+ * identifies the /dev/canx device for that network)
+ */
+
+typedef struct {
+ FRESCAN_MLOCK_T lock;
+ frescan_node_t local_node;
+ int fd;
+ fosa_thread_id_t repl_thread_id;
+ frescan_packet_t *last_packet;
+ frescan_prio_t last_packet_prio;
+ frescan_queues_t queues;
+ frescan_packet_t *id_queues[FRESCAN_MX_NODES][FRESCAN_MX_IDS]; // TODO: alloc at init
+ frescan_packet_t *id_fp_queues[FRESCAN_MX_NODES][FRESCAN_MX_PRIOS]; // TODO: alloc at init
+ frescan_ss_data_t ss_data[FRESCAN_MX_IDS];
+ freelist_t ss_id_freelist;
+ frescan_ss_data_t ss_active_head; // TODO: use struct list_head
+ // BWRES data
+ fosa_thread_id_t manager_thread_id;
+ fosa_thread_id_t acceptor_thread_id;
+ frescan_ss_t neg_messages_ss_id;
+ frescan_bwres_sa_scenario_t scenario;
+ struct list_head mode_change_list[FRESCAN_MX_NODES];
+ frescan_bwres_mode_change_type_t mode_change_type[FRESCAN_MX_NODES];
+} frescan_network_data_t;
+
+#endif // _FRESCAN_TYPES_H_