source: rtems/c/src/libchip/shmdr/shm_driver.h @ 354fb2e

4.104.115
Last change on this file since 354fb2e was 354fb2e, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 3, 2009 at 2:23:29 PM

2009-08-03 Roger Dahlkvist <ruppe@…>

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