#ifndef _MSGS_H_
#define _MSGS_H_

/*
 * Message protocol used when communicating with the slave processor.
 *
 * Messages are simply a structure imposed on a stream of data.  Each
 *  message has a one-byte type as its first byte and a total size
 *  figure in the next four bytes; the rest of the message, if any, has
 *  a type-dependent format.  The size figure includes the five header
 *  bytes.  The currently-defined message formats are:
 *
 *	<MSG_CONSUMED-char> <msgsize-int> <see below>
 *	<MSG_ACK-char> <msgsize-int> <type-char>
 *	<MSG_BOOTDATA-char> <msgsize-int> <addr-int> <size-int> <data-char[size]>
 *	<MSG_BOOTEXEC-char> <msgsize-int> <addr-int>
 *	<MSG_DEBUG-char> <msgsize-int>
 *	<MSG_CLEAR-char> <msgsize-int>
 *	<MSG_DOWNLOAD-char> <msgsize-int> <addr-int> <size-int> <data-char[size]>
 *	<MSG_START-char> <msgsize-int> <addr-int>
 *	<MSG_STOP-char> <msgsize-int>
 *	<MSG_ALLOC-char> <msgsize-int> <addr-int> <size-int>
 *	<MSG_READONLY-char> <msgsize-int> <addr-int> <size-int>
 *	<MSG_IMPORT-char> <msgsize-int> <addr-int> <size-int> <phys-int>
 *	<MSG_EXPORT-char> <msgsize-int> <addr-int> <size-int> <phys-int>
 *	<MSG_SIGNAL-char> <msgsize-int> <signum-int>
 *	<MSG_VERSION-char> <msgsize-int> <see below>
 *	<MSG_SBRK-char> <msgsize-int> <size-or-addr-int>
 *	<MSG_AST-char> <msgsize-int> <entrypoint-int> <argument-int>
 *	<MSG_CRASH-char> <msgsize-int> <info-CRASHINFO>
 *
 * MSG_CONSUMED is a special type used to indicate a message that has
 *  already been handled.
 * MSG_ACK is generated by the minikernel to acknowlege a message of
 *  one of the other types.
 * MSG_BOOTDATA and MSG_BOOTEXEC are used when booting a minikernel;
 *  the others are commands to a minikernel.
 * MSG_DEBUG is used to trigger the minikernel debugger.
 * MSG_CLEAR causes the minikernel to initialize its user program.
 * MSG_DOWNLOAD is a command to download some part of a user program.
 * MSG_START is a command to start execution of a (previously
 *  downloaded) user program.
 * MSG_STOP is a command to stop execution of any user program that's
 *  currently running.
 * MSG_ALLOC is a command to create memory without specifying initial
 *  contents for it.
 * MSG_READONLY is a command to make memory read-only.
 * MSG_IMPORT and MSG_EXPORT are used to set up shared memory.
 * MSG_SIGNAL is used to send a signal to a UNIX process at the request
 *  of whatever is running on the slave processor.
 * MSG_VERSION is used to obtain the identification of the running
 *  minikernel.
 * MSG_SBRK is similar to MSG_ALLOC but allows the slave processor to
 *  pick the address rather than specifying it.
 * MSG_AST requests an AST on the slave.  Its primary use is debugging.
 * MSG_CRASH tells the arbiter about a slave user program crash.
 *
 * It is also possible to | in MSG_NOACK to indicate that the
 *  minikernel should not generate a MSG_ACK for the message; the
 *  semantics are otherwise the same.
 *
 * MSG_CONSUMED is used to indicate a message that has already been
 *  handled.  When the interrupt routine handles a message, it sets the
 *  type to MSG_CONSUMED.  All higher-level routines should ignore
 *  messages of this type, assuming that they have already been
 *  handled.  The size field permits skipping them trivially.  Nobody
 *  should ever send a message of this type.  (Presumably, when setting
 *  the type to MSG_CONSUMED, the interrupt routine will check and
 *  throw messages away when possible.)
 *
 * MSG_ACK has one byte of data, which is the type code from the
 *  message it is acking.  Each of the other messages causes the
 *  minikernel to produce a MSG_ACK message when it finishes
 *  processing.  This does not apply to the two boot messages
 *  (MSG_BOOTDATA and MSG_BOOTEXEC); they are sent blind because there
 *  *is* no minikernel at that point.
 *
 * MSG_BOOTDATA has two ints plus an indefinite number of bytes of
 *  data; the ints specify (respectively) an address and size for data
 *  to be downloaded; the data follows.
 *
 * MSG_BOOTEXEC has one int of data, this being a location to which
 *  control should be transferred.  Control is transferred via a jmp
 *  instruction, not a calls/callg.  All that is guaranteed of the
 *  machine state on transfer is:
 *	- IPL is 31
 *	- MAPEN is 0
 *	- PSL<IS> is 1
 *	- PSL<CURMOD> is (necessarily) zero (ie, kernel mode)
 *
 * MSG_DEBUG has no extra data.  It causes the minikernel to go into
 *  its console debugger.  The MSG_ACK is delayed until the console
 *  debugger exits.
 *
 * MSG_CLEAR has no extra data.  It causes the minikernel to throw out
 *  any currently-executing user program and clear all mappings and
 *  free all memory and such initializationy things.
 *
 * MSG_DOWNLOAD is just like MSG_BOOTDATA except for the implied
 *  context; it is a command to a minikernel rather than to the boot
 *  program.  (It therefore gets an ack message, which MSG_BOOTDATA
 *  doesn't.)
 *
 * MSG_START takes one int of data, this being the entry point for the
 *  program.  Control is transferred with a jmp rather than a call.
 *
 * MSG_STOP merely stops any presently executing user program.  It
 *  takes no extra data.
 *
 * MSG_ALLOC takes two ints of data, these specifying an address and a
 *  size.  The area of memory thus specified is created, but instead of
 *  downloading the contents as with MSG_DOWNLOAD, the memory is
 *  cleared to zeros.
 *
 * MSG_READONLY takes two ints specifying an address and a size.  Every
 *  existing page of memory that overlaps the specified area at all is
 *  made read-only.  This message does not cause any memory to be
 *  allocated, nor does it affect pages created by later MSG_DOWNLOADs
 *  or MSG_ALLOCs into the area thus marked read-only.
 *
 * MSG_IMPORT takes three ints, specifying (respectively) a virtual
 *  address, a size in bytes, and a Q-bus physical address.  Any memory
 *  allocated in the specified virtual region is freed and the virtual
 *  space is made to point to the Q-bus space.  It is assumed that
 *  there is either real memory there or that someone else has set up
 *  their Q-bus mapping registers to respond to the addresses in
 *  question.
 *
 * MSG_EXPORT takes three ints, specifying (respectively) a virtual
 *  address, a size in bytes, and a Q-bus physical address.  The Q-bus
 *  mapping registers are set to map the Q-bus region to the physical
 *  pages corresponding to the virtual region specified.  If any part
 *  of the virtual region does not have memory allocated, memory will
 *  be allocated and cleared to fill the gaps.
 *
 * MSG_SIGNAL takes one int of data, this being a UNIX signal number.
 *  This signal will be sent to the last process requesting reception
 *  of signals from the slave processor which sent the message,
 *  provided that it still has the device open.  If no process fits
 *  this criterion, the message is thrown away.
 *
 * MSG_VERSION has a variable amount of data, the amount being given by
 *  the total message size.  When sent from the arbiter to a slave, any
 *  data is ignored; the message is a request for the slave to send
 *  back a MSG_VERSION message with its version identification string.
 *  From the slave to the host, the data is, by convention, a text
 *  string *including* a terminating null; it is assumed to hold the
 *  identification of the running minikernel.  The minikernel does not
 *  send a MSG_ACK in response to a MSG_VERSION; instead, it sends a
 *  MSG_VERSION with its version identification string.
 *
 * MSG_SBRK takes one int of data.  When the arbiter is sending this
 *  message to a minikernel, this is a size.  New memory is allocated
 *  to the specified size and filled with zeros.  The minikernel then
 *  sends back a MSG_SBRK message with the data being the address at
 *  which it chose to allocate the memory.  (The minikernel does not
 *  send a MSG_ACK in response to a MSG_SBRK.)
 *
 * MSG_AST takes two ints of data, these being, respectively, the entry
 *  point of the AST routine and an argument to call it with.  The
 *  routine is executed as an AST on the slave.
 *
 * MSG_CRASH takes a structure of information; see kacrash.h for the
 *  definition of this structure.  The message is sent from the slave
 *  cpu to the arbiter and indicates that the user program on the slave
 *  has just crashed.
 *
 * It is assumed that messages are sent atomically, that is, no part of
 *  a message appears in the message area until the whole thing does.
 */

/* Message type 0 is not used - just a little fireproofing */
#define MSG_CONSUMED  1
#define MSG_ACK       2
#define MSG_BOOTDATA  3
#define MSG_BOOTEXEC  4
#define MSG_DEBUG     5
#define MSG_CLEAR     6
#define MSG_DOWNLOAD  7
#define MSG_START     8
#define MSG_STOP      9
#define MSG_ALLOC    10
#define MSG_READONLY 11
#define MSG_IMPORT   12
#define MSG_EXPORT   13
#define MSG_SIGNAL   14
#define MSG_VERSION  15
#define MSG_SBRK     16
#define MSG_AST      17
#define MSG_CRASH    18

#define MSG_MAXTYPE 18

#define MSG_NOACK 0x80

#define MSG_BITS 0x80
#define MSG_TYPE 0x7f

/* This macro assumes message types run 1..MSG_MAXTYPE */
#define VALIDTYPE(t) ((unsigned int)(((int)(t))-1) < MSG_MAXTYPE)

#endif
