/*----------------------------------------------------------------------------- msg.h -- Messages and message queues Copyright (c) 1994 JANZ Computer AG All Rights Reserved Created 94/10/11 by Soenke Hansen Version 1.7 of 99/12/07 Messages consist of a specifier for its contents, the (address of its) contents, and the relevant length of the contents. Messages are allocated from the heap with the maximum length of the contents specified. The relevant length is useful when transmitting the message outside the local address space. Messages can be linked to form message queues or lists. -----------------------------------------------------------------------------*/ #ifndef msg_DEFINED #define msg_DEFINED #ifdef __cplusplus extern "C" { #endif #include "defs.h" /* Mode or format type of a message */ #define MMODE_LOCAL 0x01 /* internal compiler specific format */ #define MMODE_TRANSFER 0x02 /* external format for transfer */ /* Maximum length definitions */ #define BCAN_LEN 8 /* max data length in CAN message */ #define MB_LEN 16 /* max data length in bounded sized message */ /* Message contents types */ struct m_m1 { /* multiple purpose message (local format) */ WORD_t w[6]; }; struct m_m2 { /* for BCAN messages (local format) */ WORD_t r; /* request id */ WORD_t d; /* descriptor */ BYTE_t b[BCAN_LEN]; /* data bytes */ }; struct m_m3 { /* generic transfer data buffer */ BYTE_t len; /* length, number of relevant bytes */ BYTE_t gap; /* just to align component b[] */ BYTE_t b[MB_LEN]; /* bounded buffer */ BYTE_t *pb; /* allocated buffer if len > MB_LEN */ }; struct m_m4 { /* transfer data buffer for bulk purposes */ BYTE_t len; /* length, number of relevant bytes */ BYTE_t gap1; /* just to align component b[] */ BYTE_t available; BYTE_t gap2; /* align */ WORD_t actByteCount; /* actual usage of bulk buffer */ LWORD_t actTime; /* last write time of this bulk buffer */ BYTE_t *pActData; /* pointer to actual write-data location */ BYTE_t gap3[4]; /* gap */ BYTE_t *pb; /* allocated buffer */ }; /* Message object definition */ struct message { BYTE_t spec; /* message contents specifier */ BYTE_t mode; /* mode (message format type) */ union { /* message contents */ WORD_t align; /* mode == MMODE_LOCAL */ struct m_m1 m1; struct m_m2 m2; /* mode == MMODE_TRANSFER */ struct m_m3 m3; /* mode == MMODE_TRANSFER for bulk/sniff buffer */ struct m_m4 m4; } u; struct message *next; /* next on list/queue */ }; #define NIL_MESSAGE (struct message *)0 /* Message components for mode==MMODE_TRANSFER */ #define mlen u.m3.len /* usage: m->mlen (if: struct message *m) */ #define fdata u.m3.b /* pointer to fixed length data buffer */ #define vdata u.m3.pb /* pointer to variable length data buffer */ /* Pointer to beginning of data buffer */ #define m_data(m) (((m)->mlen > MB_LEN) ? (m)->vdata : (m)->fdata) /* definitions for bulk buffer transfer */ /* (always MMODE_TRANSFER, always variable length data buffer) */ #define mBulkAvailable u.m4.available /* usage: m->mBulkAvailable */ #define mBulkActByteCount u.m4.actByteCount /* usage: m->mBulkActByteCount */ #define mBulkActTim u.m4.actTime /* usage: m->mBulkActTime */ #define mBulkDataAddr u.m4.pActData /* usage: m->mBulkDataAddr */ /* definitions for sniff buffer transfer */ /* (always MMODE_TRANSFER, always variable length data buffer) */ #define mSniffAvailable u.m4.available /* usage: m->mSniffAvailable */ #define mSniffActByteCount u.m4.actByteCount /* usage: m->mSniffActByteCount */ #define mSniffActTim u.m4.actTime /* usage: m->mSniffActTime */ #define mSniffDataAddr u.m4.pActData /* usage: m->mSniffDataAddr */ /* Components of a timer message (struct m_m1) */ #define timer_period u.m1.w[0] #define timer_req u.m1.w[0] #define timer_tid u.m1.w[1] #define timer_tleft u.m1.w[2] /* Components of a filter message (struct m_m1) */ #define afil_id u.m1.w[0] #define afil_idlow u.m1.w[0] #define afil_idhigh u.m1.w[1] /* Components of contents of struct m_m1 message */ #define bcan_reset u.m1.w[0] /* !=0 if reset for M_BCAN_SET*req */ #define bcan_acm u.m1.w[1] /* M_BCAN_SET_ACM_req */ #define bcan_btr u.m1.w[1] /* M_BCAN_SET_BTR_req */ #define bcan_evt u.m1.w[0] /* M_BCAN_EVENT_ind */ #define bcan_evt_e0 u.m1.w[1] /* M_BCAN_EVENT_ind extended error */ #define bcan_evt_e1 u.m1.w[2] /* M_BCAN_EVENT_ind extended error*/ #define bcan_evt_e2 u.m1.w[3] /* M_BCAN_EVENT_ind extended error*/ #define bcan_evt_e3 u.m1.w[4] /* M_BCAN_EVENT_ind extended error*/ #define bcan_txreq u.m1.w[0] /* M_BCAN_TX_con */ #define bcan_txcon u.m1.w[1] /* M_BCAN_TX_con */ /* Components of a BCAN message (struct m_m2) */ #define bcan_req u.m2.r #define bcan_desc u.m2.d #define bcan_data u.m2.b /* Message queues */ struct mqueue { struct message *head; /* first element on queue */ struct message *tail; /* last element on queue */ struct message *pos; /* current position in queue */ }; #define NIL_MQUEUE (struct mqueue *)0 /* Get pointer to the first message in a queue */ #define head_mqueue(q) ((q)->head) #define first_mqueue(q) ((q)->head) /* Remove the head from a non-empty queue */ #define rmhead_mqueue(q) do { \ if ((q)->head != (q)->tail) (q)->head = (q)->head->next; \ else (q)->head = (q)->tail = NIL_MESSAGE; \ } while (0) /* Allocate a message */ extern struct message *new_message _PARAMS((int, int)); /* Deallocate a message */ extern void delete_message _PARAMS((struct message *)); /* Allocate a message queue */ extern struct mqueue *new_mqueue _PARAMS((void)); /* Deallocate a message queue. Any messages in the queue are also deallocated. */ extern void delete_mqueue _PARAMS((struct mqueue *)); /* Remove the first message from a queue. The address of the message is returned. */ extern struct message * extract_mqueue _PARAMS((struct mqueue *)); /* Append a message to a queue */ extern void append_mqueue _PARAMS((struct mqueue *, struct message *)); /* Rewind queue for looping through its elements */ extern void rewind_mqueue _PARAMS((struct mqueue *)); /* Get next message from queue */ extern struct message *getnext_mqueue _PARAMS((struct mqueue *)); /* Delete the successor of a message from a queue. The deleted (not freed!) message is returned. */ extern struct message * delsuc_mqueue _PARAMS((struct mqueue *, struct message *)); /* Insert a message into the queue after a specified message. */ extern void insert_mqueue _PARAMS((struct mqueue *, struct message *, struct message *)); #ifdef __cplusplus } #endif #endif /* !msg_DEFINED */