diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 1995-05-11 17:39:37 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 1995-05-11 17:39:37 +0000 |
commit | ac7d5ef06a6d6e8d84abbd1f0b82162725f98326 (patch) | |
tree | 9304cf759a73f2a1c6fd3191948f00e870af3787 /c/src/lib/libbsp/shmdr/shm_driver.h | |
download | rtems-ac7d5ef06a6d6e8d84abbd1f0b82162725f98326.tar.bz2 |
Initial revision
Diffstat (limited to 'c/src/lib/libbsp/shmdr/shm_driver.h')
-rw-r--r-- | c/src/lib/libbsp/shmdr/shm_driver.h | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/shmdr/shm_driver.h b/c/src/lib/libbsp/shmdr/shm_driver.h new file mode 100644 index 0000000000..bee930138c --- /dev/null +++ b/c/src/lib/libbsp/shmdr/shm_driver.h @@ -0,0 +1,542 @@ +/* shm.h + * + * This include file contains all the constants, structures, + * and global variables for this RTEMS based shared memory + * communications interface driver. + * + * Processor board dependencies are in other files. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#ifndef __SHM_h +#define __SHM_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include <cpu.h> + +/* The information contained in the Node Status, Locked Queue, and + * Envelope Control Blocks must be maintained in a NEUTRAL format. + * Currently the neutral format may be selected as big or little + * endian by simply defining either NEUTRAL_BIG or NEUTRAL_LITTLE. + * + * It is CRITICAL to note that the neutral format can ONLY be + * changed by modifying this file and recompiling the ENTIRE + * SHM driver including ALL target specific support files. + * + * The following table details the memory contents for the endian + * field of the Node Status Control Block in the various + * data format configurations (data is in hexadecimal): + * + * NEUTRAL NATIVE BYTE 0 BYTE 1 BYTE 2 BYTE 3 + * ======= ====== ====== ====== ====== ====== + * BIG BIG 00 00 00 01 + * BIG LITTLE 10 00 00 00 + * LITTLE BIG 01 00 00 00 + * LITTLE LITTLE 00 00 00 10 + * + * + * NOTE: XXX + * PORTABILITY OF LOCKING INSTRUCTIONS + * =================================== + * The locking mechanism described below is not + * general enough. Where the hardware supports + * it we should use "atomic swap" instructions + * so the values in the lock can be tailored to + * support a CPU with only weak atomic memory + * instructions. There are combinations of + * CPUs with inflexible atomic memory instructions + * which appear to be incompatible. For example, + * the SPARClite instruction uses a byte which is + * 0xFF when locked. The PA-RISC uses 1 to indicate + * locked and 0 when unlocked. These CPUs appear to + * have incompatible lock instructions. But + * they could be used in a heterogenous system + * with does not mix SPARCs and PA-RISCs. For + * example, the i386 and SPARC or i386 and SPARC + * could work together. The bottom line is that + * not every CPU will work together using this + * locking scheme. There are supposed to be + * algorithms to do this without hardware assist + * and one of these should be incorporated into + * the shared memory driver. + * + * The most flexible scheme using the instructions + * of the various CPUs for efficiency would be to use + * "atomic swaps" wherever possible. Make the lock + * and unlock configurable much like BIG vs LITTLE + * endian use of shared memory is now. The values + * of the lock could then reflect the "worst" + * CPU in a system. This still results in mixes + * of CPUs which are incompatible. + * + * The current locking mechanism is based upon the MC68020 + * "tas" instruction which is atomic. All ports to other CPUs + * comply with the restrictive placement of lock bit by this + * instruction. The lock bit is the most significant bit in a + * big-endian rtems_unsigned32. On other processors, the lock is + * typically implemented via an atomic swap or atomic modify + * bits type instruction. + */ + +#define NEUTRAL_BIG + +#ifdef NEUTRAL_BIG +#define SHM_BIG 0x00000001 +#define SHM_LITTLE 0x10000000 +#endif + +#ifdef NEUTRAL_LITTLE +#define SHM_BIG 0x01000000 +#define SHM_LITTLE 0x00000010 +#endif + +/* + * The following are the values used to fill in the lock field. Some CPUs + * are able to write only a single value into field. By making the + * lock and unlock values configurable, CPUs which support "atomic swap" + * instructions can generally be made to work in any heterogeneous + * configuration. However, it is possible for two CPUs to be incompatible + * in regards to the lock field values. This occurs when two CPUs + * which write only a single value to the field are used in a system + * but the two CPUs write different incompatible values. + * + * NOTE: The following is a first attempt at defining values which + * have a chance at working together. The m68k should use + * chk2 instead of tas to be less restrictive. Target endian + * problems (like the Force CPU386 which has (broken) big endian + * view of the VMEbus address space) are not addressed yet. + */ + +#if defined(i960) +#define SHM_LOCK_VALUE 0x00000080 +#define SHM_UNLOCK_VALUE 0 +#elif defined(m68k) +#define SHM_LOCK_VALUE 0x80000000 +#define SHM_UNLOCK_VALUE 0 +#define SHM_LOCK_VALUE 0x80000000 +#define SHM_UNLOCK_VALUE 0 +#elif defined(i386) +#define SHM_LOCK_VALUE 0x80000000 +#define SHM_UNLOCK_VALUE 0 +#elif defined(hppa1_1) +#define SHM_LOCK_VALUE 0 +#define SHM_UNLOCK_VALUE 1 +#elif defined(unix) +#define SHM_LOCK_VALUE 0 +#define SHM_UNLOCK_VALUE 1 +#elif defined(no_cpu) /* for this values are irrelevant */ +#define SHM_LOCK_VALUE 1 +#define SHM_UNLOCK_VALUE 0 +#endif + +#define Shm_Convert( value ) \ + ((Shm_Configuration->convert) ? \ + (*Shm_Configuration->convert)(value) : (value)) + +/* constants */ + +#define SHM_MASTER 1 /* master initialization node */ +#define SHM_FIRST_NODE 1 + +/* size constants */ + +#define KILOBYTE (1024) +#define MEGABYTE (1024*1024) + +/* inter-node interrupt values */ + +#define NO_INTERRUPT 0 /* used for polled nodes */ +#define BYTE 1 +#define WORD 2 +#define LONG 4 + +/* operational mode constants -- used in SHM Configuration Table */ +#define POLLED_MODE 0 +#define INTR_MODE 1 + +/* error codes */ + +#define NO_ERROR 0 +#define SHM_NO_FREE_PKTS 0xf0000 + +/* null pointers of different types */ + +#define NULL_ENV_CB ((Shm_Envelope_control *) 0) +#define NULL_SHM_INFO ((struct shm_info *) 0) +#define NULL_CONVERT 0 +#if 0 +#define NULL_CONVERT (((rtems_unsigned32 *)())0) /* we want this */ +#endif + +/* The following is adjusted so envelopes are 0x80 bytes long. */ +/* It should be >= MIN_PKT_SIZE in rtems.h */ + +#define MAX_PACKET_SIZE (80) + +/* constants pertinent to Locked Queue routines */ + +#define LQ_UNLOCKED SHM_UNLOCK_VALUE +#define LQ_LOCKED SHM_LOCK_VALUE + +/* constants related to the Free Envelope Pool */ + +#define FREE_ENV_POOL 0 +#define FREE_ENV_CB (&Shm_Locked_queues[ FREE_ENV_POOL ]) + +/* The following are important when dealing with + * the shared memory communications interface area. + * + * NOTE: The starting address and length of the shared memory + * is defined in a system dependent file. + */ + +#if 0 +#define START_NS_CBS ( (rtems_unsigned8 *) START_SHARED_MEM ) +#define START_LQ_CBS ( ((rtems_unsigned8 *) START_NS_CBS) + \ + ( (sizeof (Shm_Node_status_control)) * (Shm_Maximum_nodes + 1) ) ) +#define START_ENVELOPES ( ((rtems_unsigned8 *) START_LQ_CBS) + \ + ( (sizeof (Shm_Locked_queue_Control)) * (Shm_Maximum_nodes + 1) ) ) +#define END_SHMCI_AREA ( (rtems_unsigned8 *) START_ENVELOPES + \ + ( (sizeof (Shm_Envelope_control)) * Shm_Maximum_envelopes ) ) +#define END_SHARED_MEM ((rtems_unsigned32)START_SHARED_MEM+SHARED_MEM_LEN) +#endif + +#define START_NS_CBS ((void *)Shm_Configuration->base) +#define START_LQ_CBS ((START_NS_CBS) + \ + ( (sizeof (Shm_Node_status_control)) * (Shm_Maximum_nodes + 1) ) ) +#define START_ENVELOPES ( ((void *) START_LQ_CBS) + \ + ( (sizeof (Shm_Locked_queue_Control)) * (Shm_Maximum_nodes + 1) ) ) +#define END_SHMCI_AREA ( (void *) START_ENVELOPES + \ + ( (sizeof (Shm_Envelope_control)) * Shm_Maximum_envelopes ) ) +#define END_SHARED_MEM (START_NS_CBS+Shm_Configuration->length) + +/* macros */ + +#define Shm_Is_master_node() \ + ( SHM_MASTER == Shm_Local_node ) + +#define Shm_Free_envelope( ecb ) \ + Shm_Locked_queue_Add( FREE_ENV_CB, (ecb) ) +#define Shm_Allocate_envelope() \ + Shm_Locked_queue_Get(FREE_ENV_CB) + +#define Shm_Initialize_receive_queue(node) \ + Shm_Locked_queue_Initialize( &Shm_Locked_queues[node], node ) + +#define Shm_Append_to_receive_queue(node, ecb) \ + Shm_Locked_queue_Add( &Shm_Locked_queues[node], (ecb) ) + +#define Shm_Envelope_control_to_packet_prefix_pointer(ecb) \ + ((void *)(ecb)->packet) + +#define Shm_Packet_prefix_to_envelope_control_pointer( pkt ) \ + ((Shm_Envelope_control *)((rtems_unsigned8 *)(pkt) - \ + (sizeof(Shm_Envelope_preamble) + 4*sizeof(vol_u32)))) + +#define Shm_Build_preamble(ecb, node) \ + (ecb)->Preamble.endian = Shm_Configuration->format + +#define Shm_Build_postamble( ecb ) + +/* structures */ + +typedef volatile rtems_unsigned8 vol_u8; +typedef volatile rtems_unsigned32 vol_u32; + +/* shm control information */ + +struct shm_info { + vol_u32 not_currently_used_0; + vol_u32 not_currently_used_1; + vol_u32 not_currently_used_2; + vol_u32 not_currently_used_3; +}; + +typedef struct { + /*byte start_of_text;*/ + vol_u32 endian; + vol_u32 not_currently_used_0; + vol_u32 not_currently_used_1; + vol_u32 not_currently_used_2; +} Shm_Envelope_preamble; + +typedef struct { + vol_u32 not_currently_used_0; + vol_u32 not_currently_used_1; + vol_u32 not_currently_used_2; + vol_u32 not_currently_used_3; + /*byte end_of_text;*/ +} Shm_Envelope_postable; + +/* WARNING! If you change this structure, don't forget to change + * Shm_Envelope_control_to_packet_prefix_pointer() and + * Shm_Packet_prefix_to_envelope_control_pointer() above. + */ + +/* This comment block describes the contents of each field + * of the Envelope Control Block: + * + * next - The index of the next envelope on this queue. + * queue - The index of the queue this envelope is on. + * index - The index of this envelope. + * Preamble - Generic packet preamble. One day this structure + * could be enhanced to contain routing information. + * packet - RTEMS MPCI packet. Untouched by SHM Driver + * other than copying and format conversion as + * documented in the RTEMS User's Guide. + * Postamble - Generic packet postamble. One day this structure + * could be enhanced to contain checksum information. + */ + +typedef struct { + vol_u32 next; /* next envelope on queue */ + vol_u32 queue; /* queue on which this resides */ + vol_u32 index; /* index into array of envelopes*/ + vol_u32 pad0; /* insure the next one is aligned */ + Shm_Envelope_preamble Preamble; /* header information */ + vol_u8 packet[MAX_PACKET_SIZE]; /* RTEMS INFO */ + Shm_Envelope_postable Postamble;/* trailer information */ +} Shm_Envelope_control; + +/* This comment block describes the contents of each field + * of the Locked Queue Control Block: + * + * lock - Lock used to insure mutually exclusive access. + * front - Index of first envelope on queue. This field + * is used to remove head of queue (receive). + * rear - Index of last envelope on queue. This field + * is used to add evelope to queue (send). + * owner - The node number of the recipient (owning) node. + * RTEMS does not use the node number zero (0). + * The zero node is used by the SHM Driver for the + * Free Envelope Queue shared by all nodes. + */ + +typedef struct { + vol_u32 lock; /* lock field for this queue */ + vol_u32 front; /* first envelope on queue */ + vol_u32 rear; /* last envelope on queue */ + vol_u32 owner; /* receiving (i.e. owning) node */ +} Shm_Locked_queue_Control; + +/* This comment block describes the contents of each field + * of the Node Status Control Block: + * + * status - Node status. Current values are Pending Initialization, + * Initialization Complete, and Active Node. Other values + * could be added to enhance fault tolerance. + * error - Zero if the node has not failed. Otherwise, + * this field contains a status indicating the + * failure reason. + * int_address, int_value, and int_length + * - These field are the Interrupt Information table + * for this node in neutral format. This is how + * each node knows how to generate interrupts. + */ + +typedef struct { + vol_u32 status; /* node status information */ + vol_u32 error; /* fatal error code */ + vol_u32 int_address; /* write here for interrupt */ + vol_u32 int_value; /* this value causes interrupt */ + vol_u32 int_length; /* for this length (0,1,2,4) */ + vol_u32 not_currently_used_0; + vol_u32 not_currently_used_1; + vol_u32 not_currently_used_2; +} Shm_Node_status_control; + +/* This comment block describes the contents of each field + * of the Interrupt Information Table. This table describes + * how another node can generate an interrupt to this node. + * This information is target board dependent. If the + * SHM Driver is in POLLED_MODE, then all fields should + * be initialized to NO_INTERRUPT. + * + * address - The address to which another node should + * write to cause an interrupt. + * value - The value which must be written + * length - The size of the value to write. Valid + * values are BYTE, WORD, and LONG. + * + * NOTE: The Node Status Control Block contains this + * information in neutral format and not in a + * structure to avoid potential alignment problems. + */ + +typedef struct { + vol_u32 *address; /* write here for interrupt */ + vol_u32 value; /* this value causes interrupt */ + vol_u32 length; /* for this length (0,1,2,4) */ +} Shm_Interrupt_information; + +/* SHM Configuration Table + * + * This comment block describes the contents of each field + * of the SHM Configuration Table. + * + * base - The base address of the shared memory. This + * address may be specific to this node. + * length - The length of the shared memory in bytes. + * format - The natural format for rtems_unsigned32's in the + * shared memory. Valid values are currently + * only SHM_LITTLE and SHM_BIG. + * convert - The address of the routine which converts + * between neutral and local format. + * poll_intr - The operational mode of the driver. Some + * target boards may not provide hardware for + * an interprocessor interrupt. If POLLED_MODE + * is selected, the SHM driver will install a + * wrapper around the Clock_isr() to poll for + * incoming packets. Throughput is dependent + * on the time between clock interrupts. + * Valid values are POLLED_MODE and INTR_MODE. + * cause_intr - This is the address of the routine used to + * write to a particular address and cause an + * interrupt on another node. This routine + * may need to be target dependent if something + * other than a normal write from C does not work. + * Intr - This structure describes the operation required + * to cause an interrupt to this node. The actual + * contents of this structure are described above. + */ + +struct shm_config_info { + vol_u32 *base; /* base address of SHM */ + vol_u32 length; /* length (in bytes) of SHM */ + vol_u32 format; /* SHM is big or little endian */ + vol_u32 (*convert)();/* neutral conversion routine */ + vol_u32 poll_intr;/* POLLED or INTR driven mode */ + void (*cause_intr)( rtems_unsigned32 ); + Shm_Interrupt_information Intr; /* cause intr information */ +}; + +typedef struct shm_config_info shm_config_table; + +/* global variables */ + +#ifdef _SHM_INIT +#define SHM_EXTERN +#else +#define SHM_EXTERN extern +#endif + +SHM_EXTERN shm_config_table *Shm_Configuration; +SHM_EXTERN Shm_Interrupt_information Shm_Interrupt_table[16]; +SHM_EXTERN Shm_Node_status_control *Shm_Node_statuses; +SHM_EXTERN Shm_Locked_queue_Control *Shm_Locked_queues; +SHM_EXTERN Shm_Envelope_control *Shm_Envelopes; +SHM_EXTERN rtems_configuration_table *Shm_RTEMS_Configuration; +SHM_EXTERN rtems_multiprocessing_table *Shm_RTEMS_MP_Configuration; +SHM_EXTERN rtems_unsigned32 Shm_Receive_message_count; +SHM_EXTERN rtems_unsigned32 Shm_Null_message_count; +SHM_EXTERN rtems_unsigned32 Shm_Interrupt_count; +SHM_EXTERN rtems_unsigned32 Shm_Local_node; +SHM_EXTERN Shm_Locked_queue_Control *Shm_Local_receive_queue; +SHM_EXTERN Shm_Node_status_control *Shm_Local_node_status; +SHM_EXTERN rtems_unsigned32 Shm_isrstat; + /* reported by shmdr */ + +SHM_EXTERN rtems_unsigned32 Shm_Pending_initialization; +SHM_EXTERN rtems_unsigned32 Shm_Initialization_complete; +SHM_EXTERN rtems_unsigned32 Shm_Active_node; + +SHM_EXTERN rtems_unsigned32 Shm_Maximum_nodes; +SHM_EXTERN rtems_unsigned32 Shm_Maximum_envelopes; + +SHM_EXTERN rtems_unsigned32 Shm_Locked_queue_End_of_list; +SHM_EXTERN rtems_unsigned32 Shm_Locked_queue_Not_on_list; + +/* functions */ + +/* locked queue routines */ +void Shm_Locked_queue_Add( + Shm_Locked_queue_Control *, Shm_Envelope_control * ); +Shm_Envelope_control *Shm_Locked_queue_Get( Shm_Locked_queue_Control * ); +void Shm_Locked_queue_Initialize( + Shm_Locked_queue_Control *, rtems_unsigned32 ); + /* Shm_Initialize_lock is CPU dependent */ + /* Shm_Lock is CPU dependent */ + /* Shm_Unlock is CPU dependent */ + +/* portable routines */ +void Init_env_pool(); +void Shm_Print_statistics( void ); +void MPCI_Fatal( rtems_unsigned32 ); +rtems_task Shm_Cause_interrupt( rtems_unsigned32 ); +void Shm_Poll(); +void Shm_setclockvec(); +void Shm_Convert_packet( rtems_packet_prefix * ); + +/* CPU specific routines are inlined in shmcpu.h */ + +/* target specific routines */ +void *Shm_Convert_address( void * ); +void Shm_Get_configuration( rtems_unsigned32, shm_config_table ** ); +void Shm_isr(); +void Shm_setvec( void ); + +void Shm_Initialize_lock( Shm_Locked_queue_Control * ); +void Shm_Lock( Shm_Locked_queue_Control * ); +void Shm_Unlock( Shm_Locked_queue_Control * ); + +/* MPCI entry points */ +rtems_mpci_entry Shm_Get_packet( + rtems_packet_prefix ** +); + +rtems_mpci_entry Shm_Initialization( + rtems_configuration_table *configuration, + rtems_cpu_table *cpu_configuration, + rtems_multiprocessing_table *mp_configuration +); + +rtems_mpci_entry Shm_Receive_packet( + rtems_packet_prefix ** +); + +rtems_mpci_entry Shm_Return_packet( + rtems_packet_prefix * +); + +rtems_mpci_entry Shm_Send_packet( + rtems_unsigned32, + rtems_packet_prefix * +); + +#ifdef _SHM_INIT + +/* multiprocessor communications interface (MPCI) table */ + +rtems_mpci_table MPCI_table = { + 100000, /* default timeout value in ticks */ + Shm_Initialization, /* initialization procedure */ + Shm_Get_packet, /* get packet procedure */ + Shm_Return_packet, /* return packet procedure */ + Shm_Send_packet, /* packet send procedure */ + Shm_Receive_packet /* packet receive procedure */ +}; + +#else + +extern rtems_mpci_table MPCI_table; + +#endif + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ |