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