summaryrefslogtreecommitdiff
path: root/common/ipmbox/queue.h
blob: 3c5a4e64821a4b01c10d0150fec3fa5c09b37487 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#ifndef common_ipmbox_queue_h
#define common_ipmbox_queue_h
/* Cesar project {{{
 *
 * Copyright (C) 2011 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    common/ipmbox/queue.h
 * \brief   IPMbox queue management
 *
 * This file contains interfaces used to access the different queues for
 * IPMbox.
 */
#include "common/universe.h"

/**
 * Shared queue management pointers.
 * They must follow each others in memory. A structure is used to prevent too
 * much indirections when accessing those pointers.
 * Order of pointers is important and must not be changed (otherwise
 * everything will fail).
 * Only contains physical address.
 */
typedef struct ipmbox_queue_ptr_t
{
    unsigned long tail;
    unsigned long head;
} ipmbox_queue_ptr_t;

/**
 * A queue (implemented as a circular ring).
 */
typedef struct ipmbox_queue_t
{
    /** Base address of start of the queue. */
    u32 *base_ptr;
    /** End of the queue (past the queue). */
    u32 *end_ptr;
#if !CESAR
    /** Virtual to physical address offset. */
    u32 virt_to_phys_offset;
#endif
    /** Pointers of queue. */
    volatile ipmbox_queue_ptr_t *ptr;
    /** Queue size in words. */
    unsigned int size;
} ipmbox_queue_t;

/**
 * List of queues in the IPMBox.
 */
typedef enum ipmbox_queue_type_t
{
    /** All other types of messages (MME, RPC, debug types). */
    IPMBOX_QUEUE_MBX = 0,
    /** Empty buffer to free or for storing message (empty buf only). */
    IPMBOX_QUEUE_EMPTY_BUF,
    /** Data (PLC frame) queue (type data only). */
    IPMBOX_QUEUE_DATA,
    IPMBOX_QUEUE_TYPE_NB
} ipmbox_queue_type_t;

/**
 * IPMbox direction.
 */
typedef enum ipmbox_queue_direction_t
{
    /** ARM to Leon. */
    IPMBOX_A2L = 0,
    /** Leon to ARM. */
    IPMBOX_L2A,
    IPMBOX_QUEUE_DIRECTION_NB
} ipmbox_queue_direction_t;

/**
 * Convert virtual address to physical address for a pointer into a queue.
 * \param  queue  queue context
 * \param  virt  virtual address
 * \return  physical address
 */
extern inline u32
ipmbox_queue_virt_to_phys (ipmbox_queue_t *queue, void *virt)
{
#if CESAR
    return (u32) virt;
#else
    return (u32) virt + queue->virt_to_phys_offset;
#endif
}

/**
 * Convert physical address to virtual address for a pointer into a queue.
 * \param  queue  queue context
 * \param  phys  physical address
 * \return  virtual address
 */
extern inline void *
ipmbox_queue_phys_to_virt (ipmbox_queue_t *queue, u32 phys)
{
#if CESAR
    return (void *) phys;
#else
    return (void *) (phys - queue->virt_to_phys_offset);
#endif
}

/**
 * Get free space in a queue.
 * \param  queue  queue to check
 * \return  free size in words
 */
extern inline unsigned int
ipmbox_queue_get_free_space (ipmbox_queue_t *queue)
{
    u32 *tail, *head;

    /* Check parameter. */
    dbg_claim (queue);

    tail = (u32 *) queue->ptr->tail;
    head = (u32 *) queue->ptr->head;

    if (tail >= head)
        return queue->size - (tail - head) - 1;
    else
        return head - tail - 1;
}

/**
 * Get used space in a queue.
 * \param  queue  queue to check
 * \return  used size in words
 */
extern inline unsigned int
ipmbox_queue_get_used_space (ipmbox_queue_t *queue)
{
    u32 *tail, *head;

    /* Check parameter. */
    dbg_claim (queue);

    tail = (u32 *) queue->ptr->tail;
    head = (u32 *) queue->ptr->head;

    if (tail >= head)
        return tail - head;
    else
        return queue->size + tail - head;
}

/**
 * Copy data to a queue.
 * \param  queue  queue in which to add data
 * \param  data  pointer to the data
 * \param  size  data size in words
 *
 * \warning  callee is responsible to check there is enough space in queue
 * to copy data.
 */
void
ipmbox_queue_copy_to (ipmbox_queue_t *queue, u32 *data,
                      unsigned int size);

/**
 * Copy data from a queue.
 * \param  queue  queue in which to get data from
 * \param  data  pointer to the data where to store them
 * \param  size  data size in words (space available in data buffer)
 *
 * \warning  Callee is responsible to check that size is in sync with current
 * queue size: size must be inferior or equal to used space in queue (never
 * over queue size - 1).
 */
void
ipmbox_queue_copy_from (ipmbox_queue_t *queue, u32 *data,
                        unsigned int size);


#endif /* common_ipmbox_queue_h */