RTEMS  5.1
shm_driver.h
1 /* shm_driver.h
2  *
3  * This include file contains all the constants, structures,
4  * and global variables for this RTEMS based shared memory
5  * communications interface driver.
6  *
7  * Processor board dependencies are in other files.
8  *
9  * COPYRIGHT (c) 1989-2007.
10  * On-Line Applications Research Corporation (OAR).
11  *
12  * The license and distribution terms for this file may be
13  * found in the file LICENSE in this distribution or at
14  * http://www.rtems.org/license/LICENSE.
15  */
16 
17 #ifndef __SHM_h
18 #define __SHM_h
19 
20 #include <rtems.h>
21 #include <rtems/clockdrv.h>
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 /* The information contained in the Node Status, Locked Queue, and
28  * Envelope Control Blocks must be maintained in a NEUTRAL format.
29  * Currently the neutral format may be selected as big or little
30  * endian by simply defining either NEUTRAL_BIG or NEUTRAL_LITTLE.
31  *
32  * It is CRITICAL to note that the neutral format can ONLY be
33  * changed by modifying this file and recompiling the ENTIRE
34  * SHM driver including ALL target specific support files.
35  *
36  * The following table details the memory contents for the endian
37  * field of the Node Status Control Block in the various
38  * data format configurations (data is in hexadecimal):
39  *
40  * NEUTRAL NATIVE BYTE 0 BYTE 1 BYTE 2 BYTE 3
41  * ======= ====== ====== ====== ====== ======
42  * BIG BIG 00 00 00 01
43  * BIG LITTLE 10 00 00 00
44  * LITTLE BIG 01 00 00 00
45  * LITTLE LITTLE 00 00 00 10
46  *
47  *
48  * NOTE: XXX
49  * PORTABILITY OF LOCKING INSTRUCTIONS
50  * ===================================
51  * The locking mechanism described below is not
52  * general enough. Where the hardware supports
53  * it we should use "atomic swap" instructions
54  * so the values in the lock can be tailored to
55  * support a CPU with only weak atomic memory
56  * instructions. There are combinations of
57  * CPUs with inflexible atomic memory instructions
58  * which appear to be incompatible. For example,
59  * the SPARClite instruction uses a byte which is
60  * 0xFF when locked. The PA-RISC uses 1 to indicate
61  * locked and 0 when unlocked. These CPUs appear to
62  * have incompatible lock instructions. But
63  * they could be used in a heterogenous system
64  * with does not mix SPARCs and PA-RISCs. For
65  * example, the i386 and SPARC or i386 and SPARC
66  * could work together. The bottom line is that
67  * not every CPU will work together using this
68  * locking scheme. There are supposed to be
69  * algorithms to do this without hardware assist
70  * and one of these should be incorporated into
71  * the shared memory driver.
72  *
73  * The most flexible scheme using the instructions
74  * of the various CPUs for efficiency would be to use
75  * "atomic swaps" wherever possible. Make the lock
76  * and unlock configurable much like BIG vs LITTLE
77  * endian use of shared memory is now. The values
78  * of the lock could then reflect the "worst"
79  * CPU in a system. This still results in mixes
80  * of CPUs which are incompatible.
81  *
82  * The current locking mechanism is based upon the MC68020
83  * "tas" instruction which is atomic. All ports to other CPUs
84  * comply with the restrictive placement of lock bit by this
85  * instruction. The lock bit is the most significant bit in a
86  * big-endian uint32_t . On other processors, the lock is
87  * typically implemented via an atomic swap or atomic modify
88  * bits type instruction.
89  */
90 
91 #define NEUTRAL_BIG
92 
93 #ifdef NEUTRAL_BIG
94 #define SHM_BIG 0x00000001
95 #define SHM_LITTLE 0x10000000
96 #endif
97 
98 #ifdef NEUTRAL_LITTLE
99 #define SHM_BIG 0x01000000
100 #define SHM_LITTLE 0x00000010
101 #endif
102 
103 /*
104  * The following are the values used to fill in the lock field. Some CPUs
105  * are able to write only a single value into field. By making the
106  * lock and unlock values configurable, CPUs which support "atomic swap"
107  * instructions can generally be made to work in any heterogeneous
108  * configuration. However, it is possible for two CPUs to be incompatible
109  * in regards to the lock field values. This occurs when two CPUs
110  * which write only a single value to the field are used in a system
111  * but the two CPUs write different incompatible values.
112  *
113  * NOTE: The following is a first attempt at defining values which
114  * have a chance at working together. The m68k should use
115  * chk2 instead of tas to be less restrictive. Target endian
116  * problems (like the Force CPU386 which has (broken) big endian
117  * view of the VMEbus address space) are not addressed yet.
118  */
119 
120 #if defined(__mc68000__)
121 #define SHM_LOCK_VALUE 0x80000000
122 #define SHM_UNLOCK_VALUE 0
123 #define SHM_LOCK_VALUE 0x80000000
124 #define SHM_UNLOCK_VALUE 0
125 #elif defined(__i386__)
126 #define SHM_LOCK_VALUE 0x80000000
127 #define SHM_UNLOCK_VALUE 0
128 #elif defined(__mips__)
129 #define SHM_LOCK_VALUE 0x80000000
130 #define SHM_UNLOCK_VALUE 0
131 #elif defined(__hppa__)
132 #define SHM_LOCK_VALUE 0
133 #define SHM_UNLOCK_VALUE 1
134 #elif defined(__PPC__)
135 #define SHM_LOCK_VALUE 1
136 #define SHM_UNLOCK_VALUE 0
137 #elif defined(__unix__)
138 #define SHM_LOCK_VALUE 0
139 #define SHM_UNLOCK_VALUE 1
140 #elif defined(_AM29K)
141 #define SHM_LOCK_VALUE 0
142 #define SHM_UNLOCK_VALUE 1
143 #elif defined(__nios2__)
144 #define SHM_LOCK_VALUE 1
145 #define SHM_UNLOCK_VALUE 0
146 #elif defined(__sparc__)
147 #define SHM_LOCK_VALUE 1
148 #define SHM_UNLOCK_VALUE 0
149 #elif defined(no_cpu) /* for this values are irrelevant */
150 #define SHM_LOCK_VALUE 1
151 #define SHM_UNLOCK_VALUE 0
152 #else
153 #error "shm_driver.h - no SHM_LOCK_VALUE defined for this CPU architecture"
154 #endif
155 
156 #define Shm_Convert( value ) \
157  ((Shm_Configuration->convert) ? \
158  (*Shm_Configuration->convert)(value) : (value))
159 
160 /* constants */
161 
162 #define SHM_MASTER 1 /* master initialization node */
163 #define SHM_FIRST_NODE 1
164 
165 /* size constants */
166 
167 #define KILOBYTE (1024)
168 #define MEGABYTE (1024*1024)
169 
170 /* inter-node interrupt values */
171 
172 #define NO_INTERRUPT 0 /* used for polled nodes */
173 #define BYTE 1
174 #define WORD 2
175 #define LONG 4
176 
177 /* operational mode constants -- used in SHM Configuration Table */
178 #define POLLED_MODE 0
179 #define INTR_MODE 1
180 
181 /* error codes */
182 
183 #define NO_ERROR 0
184 #define SHM_NO_FREE_PKTS 0xf0000
185 
186 /* null pointers of different types */
187 
188 #define NULL_ENV_CB ((Shm_Envelope_control *) 0)
189 #define NULL_CONVERT 0
190 
191 /*
192  * size of stuff before preamble in envelope.
193  * It must be a constant since we will use it to generate MAX_PACKET_SIZE
194  */
195 
196 #define SHM_ENVELOPE_PREFIX_OVERHEAD (4 * sizeof(vol_u32))
197 
198 /*
199  * The following is adjusted so envelopes are MAX_ENVELOPE_SIZE bytes long.
200  * It must be >= RTEMS_MINIMUM_PACKET_SIZE in mppkt.h.
201  */
202 
203 #ifndef MAX_ENVELOPE_SIZE
204 #define MAX_ENVELOPE_SIZE 0x180
205 #endif
206 
207 #define MAX_PACKET_SIZE (MAX_ENVELOPE_SIZE - \
208  SHM_ENVELOPE_PREFIX_OVERHEAD + \
209  sizeof(Shm_Envelope_preamble) + \
210  sizeof(Shm_Envelope_postamble))
211 
212 
213 /* constants pertinent to Locked Queue routines */
214 
215 #define LQ_UNLOCKED SHM_UNLOCK_VALUE
216 #define LQ_LOCKED SHM_LOCK_VALUE
217 
218 /* constants related to the Free Envelope Pool */
219 
220 #define FREE_ENV_POOL 0
221 #define FREE_ENV_CB (&Shm_Locked_queues[ FREE_ENV_POOL ])
222 
223 /* The following are important when dealing with
224  * the shared memory communications interface area.
225  *
226  * NOTE: The starting address and length of the shared memory
227  * is defined in a system dependent file.
228  */
229 
230 #define START_NS_CBS ((void *)Shm_Configuration->base)
231 #define START_LQ_CBS ((START_NS_CBS) + \
232  ( (sizeof (Shm_Node_status_control)) * (SHM_MAXIMUM_NODES + 1) ) )
233 #define START_ENVELOPES ( ((void *) START_LQ_CBS) + \
234  ( (sizeof (Shm_Locked_queue_Control)) * (SHM_MAXIMUM_NODES + 1) ) )
235 #define END_SHMCI_AREA ( (void *) START_ENVELOPES + \
236  ( (sizeof (Shm_Envelope_control)) * Shm_Maximum_envelopes ) )
237 #define END_SHARED_MEM (START_NS_CBS+Shm_Configuration->length)
238 
239 /* macros */
240 
241 #define Shm_Is_master_node() \
242  ( SHM_MASTER == rtems_object_get_local_node() )
243 
244 #define Shm_Free_envelope( ecb ) \
245  Shm_Locked_queue_Add( FREE_ENV_CB, (ecb) )
246 #define Shm_Allocate_envelope() \
247  Shm_Locked_queue_Get(FREE_ENV_CB)
248 
249 #define Shm_Initialize_receive_queue(node) \
250  Shm_Locked_queue_Initialize( &Shm_Locked_queues[node], node )
251 
252 #define Shm_Append_to_receive_queue(node, ecb) \
253  Shm_Locked_queue_Add( &Shm_Locked_queues[node], (ecb) )
254 
255 #define Shm_Envelope_control_to_packet_prefix_pointer(ecb) \
256  ((void *)(ecb)->packet)
257 
258 #define Shm_Packet_prefix_to_envelope_control_pointer( pkt ) \
259  ((Shm_Envelope_control *)((uint8_t*)(pkt) - \
260  (sizeof(Shm_Envelope_preamble) + SHM_ENVELOPE_PREFIX_OVERHEAD)))
261 
262 #define Shm_Build_preamble(ecb, node) \
263  (ecb)->Preamble.endian = Shm_Configuration->format
264 
265 #define Shm_Build_postamble( ecb )
266 
267 /* volatile types */
268 
269 typedef volatile uint8_t vol_u8;
270 typedef volatile uint32_t vol_u32;
271 
272 /* shm control information */
273 
274 struct shm_info {
275  vol_u32 not_currently_used_0;
276  vol_u32 not_currently_used_1;
277  vol_u32 not_currently_used_2;
278  vol_u32 not_currently_used_3;
279 };
280 
281 typedef struct {
282  /*byte start_of_text;*/
283  vol_u32 endian;
284  vol_u32 not_currently_used_0;
285  vol_u32 not_currently_used_1;
286  vol_u32 not_currently_used_2;
288 
289 typedef struct {
291 
292 /* WARNING! If you change this structure, don't forget to change
293  * SHM_ENVELOPE_PREFIX_OVERHEAD and
294  * Shm_Packet_prefix_to_envelope_control_pointer() above.
295  */
296 
297 /* This comment block describes the contents of each field
298  * of the Envelope Control Block:
299  *
300  * next - The index of the next envelope on this queue.
301  * queue - The index of the queue this envelope is on.
302  * index - The index of this envelope.
303  * Preamble - Generic packet preamble. One day this structure
304  * could be enhanced to contain routing information.
305  * packet - RTEMS MPCI packet. Untouched by SHM Driver
306  * other than copying and format conversion as
307  * documented in the RTEMS User's Guide.
308  * Postamble - Generic packet postamble. One day this structure
309  * could be enhanced to contain checksum information.
310  */
311 
312 typedef struct {
313  vol_u32 next; /* next envelope on queue */
314  vol_u32 queue; /* queue on which this resides */
315  vol_u32 index; /* index into array of envelopes*/
316  vol_u32 pad0; /* insure the next one is aligned */
317  Shm_Envelope_preamble Preamble; /* header information */
318  vol_u8 packet[MAX_PACKET_SIZE]; /* RTEMS INFO */
319  Shm_Envelope_postamble Postamble;/* trailer information */
321 
322 /* This comment block describes the contents of each field
323  * of the Locked Queue Control Block:
324  *
325  * lock - Lock used to insure mutually exclusive access.
326  * front - Index of first envelope on queue. This field
327  * is used to remove head of queue (receive).
328  * rear - Index of last envelope on queue. This field
329  * is used to add evelope to queue (send).
330  * owner - The node number of the recipient (owning) node.
331  * RTEMS does not use the node number zero (0).
332  * The zero node is used by the SHM Driver for the
333  * Free Envelope Queue shared by all nodes.
334  */
335 
336 typedef struct {
337  vol_u32 lock; /* lock field for this queue */
338  vol_u32 front; /* first envelope on queue */
339  vol_u32 rear; /* last envelope on queue */
340  vol_u32 owner; /* receiving (i.e. owning) node */
342 
343 /* This comment block describes the contents of each field
344  * of the Node Status Control Block:
345  *
346  * status - Node status. Current values are Pending Initialization,
347  * Initialization Complete, and Active Node. Other values
348  * could be added to enhance fault tolerance.
349  * error - Zero if the node has not failed. Otherwise,
350  * this field contains a status indicating the
351  * failure reason.
352  * int_address, int_value, and int_length
353  * - These field are the Interrupt Information table
354  * for this node in neutral format. This is how
355  * each node knows how to generate interrupts.
356  */
357 
358 typedef struct {
359  vol_u32 status; /* node status information */
360  vol_u32 error; /* fatal error code */
361  vol_u32 int_address; /* write here for interrupt */
362  vol_u32 int_value; /* this value causes interrupt */
363  vol_u32 int_length; /* for this length (0,1,2,4) */
364  vol_u32 not_currently_used_0;
365  vol_u32 not_currently_used_1;
366  vol_u32 not_currently_used_2;
368 
369 /* This comment block describes the contents of each field
370  * of the Interrupt Information Table. This table describes
371  * how another node can generate an interrupt to this node.
372  * This information is target board dependent. If the
373  * SHM Driver is in POLLED_MODE, then all fields should
374  * be initialized to NO_INTERRUPT.
375  *
376  * address - The address to which another node should
377  * write to cause an interrupt.
378  * value - The value which must be written
379  * length - The size of the value to write. Valid
380  * values are BYTE, WORD, and LONG.
381  *
382  * NOTE: The Node Status Control Block contains this
383  * information in neutral format and not in a
384  * structure to avoid potential alignment problems.
385  */
386 
387 typedef struct {
388  vol_u32 *address; /* write here for interrupt */
389  vol_u32 value; /* this value causes interrupt */
390  vol_u32 length; /* for this length (0,1,2,4) */
392 
393 /* SHM Configuration Table
394  *
395  * This comment block describes the contents of each field
396  * of the SHM Configuration Table.
397  *
398  * base - The base address of the shared memory. This
399  * address may be specific to this node.
400  * length - The length of the shared memory in bytes.
401  * format - The natural format for uint32_t 's in the
402  * shared memory. Valid values are currently
403  * only SHM_LITTLE and SHM_BIG.
404  * convert - The address of the routine which converts
405  * between neutral and local format.
406  * poll_intr - The operational mode of the driver. Some
407  * target boards may not provide hardware for
408  * an interprocessor interrupt. If POLLED_MODE
409  * is selected, the SHM driver will use a
410  * Classiv API Timer instance to poll for
411  * incoming packets. Throughput is dependent
412  * on the time between clock interrupts.
413  * Valid values are POLLED_MODE and INTR_MODE.
414  * cause_intr - This is the address of the routine used to
415  * write to a particular address and cause an
416  * interrupt on another node. This routine
417  * may need to be target dependent if something
418  * other than a normal write from C does not work.
419  * Intr - This structure describes the operation required
420  * to cause an interrupt to this node. The actual
421  * contents of this structure are described above.
422  */
423 
425  vol_u32 *base; /* base address of SHM */
426  vol_u32 length; /* length (in bytes) of SHM */
427  vol_u32 format; /* SHM is big or little endian */
428  uint32_t (*convert)( uint32_t );/* neutral conversion routine */
429  vol_u32 poll_intr;/* POLLED or INTR driven mode */
430  void (*cause_intr)( uint32_t);
431  Shm_Interrupt_information Intr; /* cause intr information */
432 };
433 
434 typedef struct shm_config_info shm_config_table;
435 
436 #define SHM_MAXIMUM_NODES _MPCI_Configuration.maximum_nodes
437 
438 /* global variables */
439 
440 #ifdef _SHM_INIT
441 #define SHM_EXTERN
442 #else
443 #define SHM_EXTERN extern
444 #endif
445 
446 SHM_EXTERN shm_config_table *Shm_Configuration;
447 SHM_EXTERN Shm_Interrupt_information *Shm_Interrupt_table;
448 SHM_EXTERN Shm_Node_status_control *Shm_Node_statuses;
449 SHM_EXTERN Shm_Locked_queue_Control *Shm_Locked_queues;
450 SHM_EXTERN Shm_Envelope_control *Shm_Envelopes;
451 SHM_EXTERN uint32_t Shm_Receive_message_count;
452 SHM_EXTERN uint32_t Shm_Null_message_count;
453 SHM_EXTERN uint32_t Shm_Interrupt_count;
454 SHM_EXTERN Shm_Locked_queue_Control *Shm_Local_receive_queue;
455 SHM_EXTERN Shm_Node_status_control *Shm_Local_node_status;
456 SHM_EXTERN uint32_t Shm_isrstat;
457  /* reported by shmdr */
458 
459 SHM_EXTERN uint32_t Shm_Pending_initialization;
460 SHM_EXTERN uint32_t Shm_Initialization_complete;
461 SHM_EXTERN uint32_t Shm_Active_node;
462 
463 SHM_EXTERN uint32_t Shm_Maximum_envelopes;
464 
465 SHM_EXTERN uint32_t Shm_Locked_queue_End_of_list;
466 SHM_EXTERN uint32_t Shm_Locked_queue_Not_on_list;
467 
468 /* functions */
469 
470 /* locked queue routines */
471 void Shm_Locked_queue_Add(
473 Shm_Envelope_control *Shm_Locked_queue_Get( Shm_Locked_queue_Control * );
474 void Shm_Locked_queue_Initialize(
475  Shm_Locked_queue_Control *, uint32_t);
476  /* Shm_Initialize_lock is CPU dependent */
477  /* Shm_Lock is CPU dependent */
478  /* Shm_Unlock is CPU dependent */
479 
480 /* portable routines */
481 void Init_env_pool( void );
482 void Shm_Print_statistics( void );
483 void MPCI_Fatal( rtems_fatal_source, bool, rtems_fatal_code );
484 rtems_task Shm_Cause_interrupt( uint32_t );
485 void Shm_install_timer( void );
486 void Shm_Convert_packet( rtems_packet_prefix * );
487 
488 /* CPU specific routines are inlined in shmcpu.h */
489 
490 /* target specific routines */
491 void *Shm_Convert_address( void * );
492 void Shm_Get_configuration( uint32_t, shm_config_table ** );
493 void Shm_isr( void );
494 void Shm_setvec( void );
495 
496 void Shm_Initialize_lock( Shm_Locked_queue_Control * );
497 void Shm_Lock( Shm_Locked_queue_Control * );
498 void Shm_Unlock( Shm_Locked_queue_Control * );
499 
500 /* MPCI entry points */
501 rtems_mpci_entry Shm_Get_packet(
502  rtems_packet_prefix **
503 );
504 
505 rtems_mpci_entry Shm_Initialization( void );
506 
507 rtems_mpci_entry Shm_Receive_packet(
508  rtems_packet_prefix **
509 );
510 
511 rtems_mpci_entry Shm_Return_packet(
512  rtems_packet_prefix *
513 );
514 
515 rtems_mpci_entry Shm_Send_packet(
516  uint32_t,
517  rtems_packet_prefix *
518 );
519 
520 extern rtems_mpci_table MPCI_table;
521 
522 #ifdef _SHM_INIT
523 
524 /* multiprocessor communications interface (MPCI) table */
525 
526 rtems_mpci_table MPCI_table = {
527  100000, /* default timeout value in ticks */
528  MAX_PACKET_SIZE, /* maximum packet size */
529  Shm_Initialization, /* initialization procedure */
530  Shm_Get_packet, /* get packet procedure */
531  Shm_Return_packet, /* return packet procedure */
532  Shm_Send_packet, /* packet send procedure */
533  Shm_Receive_packet /* packet receive procedure */
534 };
535 
536 #endif
537 
538 #ifdef __cplusplus
539 }
540 #endif
541 
542 #endif
543 /* end of include file */
Definition: shm_driver.h:274
Definition: shm_driver.h:312
Definition: shm_driver.h:358
void rtems_task
Definition: tasks.h:101
Definition: mknod-pack_dev.c:254
Definition: shm_driver.h:336
Internal_errors_Source
This type lists the possible sources from which an error can be reported.
Definition: interr.h:47
Definition: demand.c:51
Definition: shm_driver.h:289
Definition: shm_driver.h:387
Definition: shm_driver.h:424
Definition: shm_driver.h:281
Clock Driver API.
rtems_mpci_entry Shm_Send_packet(uint32_t node, rtems_packet_prefix *packet)
Definition: shmdr-send.c:32