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