{------------------------------------------------------------------------------
{
{              D D D   0 0
{              D     D     0
{              D    0 D     0
{              D    0 D     0
{              D    0 D     0
{              D     0     0
{              D D D   0 0         ------- D0 Online Software
{
{
{    ITC Message Transfer Module --  MESSAGE_XFER.EPAS
{
{    Purpose and Methods : Routines used for data (message) transfer
{
{    Arguments : None
{    Exports   : ITC_Read
{		 ITC_Write
{
{    Created on November 18, 1989  by John Featherly
{
{------------------------------------------------------------------------------
}

Module Message_Xfer;
Include $KERNELMSG, GLOBAL, SETUP_INIT;

{------------------------------------------------------------------------------
{	ITC_Read
{
{	Reads a message from an active channel.
{
{	Inputs:
{  		Channel	- Longword Integer 1..Max_Channel by reference
{			  Active channel that will be read from
{
{	Output:
{		Message	- String by descriptor, fixed len, varying or dynamic
{			  Information retrieved from the channel
{  		Length	- Longword Integer by reference
{			  Length of returned message
{
{	2 Feb 1989 : P.Wilhelm
{	Major changes in function: - Unloads the ring_buffer from 1 message
{	Unloads it until it finds a message.
{	When the ring_buffer has enough room will resart QIO in the channels
{	which where stopped.
{	Minor : - Resets CCB^[Channel].InUse to FALSE if disconection has
{	been done.
{
{------------------------------------------------------------------------------
}
Function ITC_Read
	  ( VAR Channel : CHANNEL_RANGE;	{ VAR in order to acc FORTRAN }
	    VAR RData	: STRING(<n>);
	    VAR Length  : INTEGER ) : INTEGER;

Var
  QMess		: ^MESSBLK;

Begin
  If not ( (Channel > None) and (Channel <= Number_of_Channels) )
				Then ITC_Read := ITC__Bad_Arg
  Else If not (init and CCB[Channel].In_Use)
				Then ITC_Read := ITC__No_Channel
  Else With CCB[Channel] Do Begin
    Remove_Entry ( MLQH, QMess::^QUEUE_ENTRY, MQ_Empty, QUEUE$HEAD );
    RData  := Substr ( QMess^.Info^, 1, QMess^.Length );
    Length := QMess^.Length;
    If QMess^.Trunc
	Then ITC_Read := ITC__Truncated
	Else ITC_Read := ITC__Success;
    Delete (QMess^.Mess);
    Dispose (QMess)
  End { last else clause }
End  { Function ITC Read };


{------------------------------------------------------------------------------
{	ITC_Write
{
{	Writes a message on a channel after checking that the channel is
{  connected (active) and that the message argument is valid.
{
{
{	Inputs:
{		Channel	- Integer in 1..Number_of_Channels, value semantics
{			  Active channel on which to write the message
{		Message	- String by descriptor, fixed len, varying or dynamic
{			  Information to be sent over the channel
{
{	Output: none
{
{------------------------------------------------------------------------------
}
Function ITC_Write
	  ( VAR Channel	: CHANNEL_RANGE;
	        WData	: STRING(<n>) ): INTEGER;

Var
  Status	: INTEGER;
  Message_Obj	: MESSAGE;
  Message_Data	: ^STRING(Max_Message_Size);

Begin
  If not ( (Channel > None) and (Channel <= Number_of_Channels) )
				Then ITC_Write := ITC__Bad_Chan
  Else If not (init and CCB[Channel].Connected)
				Then ITC_Write := ITC__No_Channel
  Else If not (n > 0)
				Then ITC_Write := ITC__Bad_Arg
  Else If (CCB[Channel].In_Disco)
				Then ITC_Write := ITC__InDisco
  Else Begin 
    Create_Message (Message_Obj, Message_Data, STATUS := Status );
    Message_Data^ := WData;
    Send (Message_Obj, CCB[Channel].IO_Port, SIZE := n, STATUS := Status );
    If Status = KER$_Success	Then ITC_Write := ITC__Success
				Else ITC_Write := Status
  End  { last else clause }
End  { Function ITC Write };

{------------------------------------------------------------------------------
{	ITC_Find_Activity
{
{    Purpose and Methods : Reads (destructively) and returns next item from
{			   the activity buffer (ring buffer)
{
{	Returns the channel number and type of activity for any ITC events.
{  The activity buffer is time ordered FIFO.
{
{	Input:	None
{
{	Output:
{  	     	Channel	- Longword Integer 1..Max_Channel by reference
{			  Number of the channel on which activity was found
{		AType	- Integer by reference
{			  Type of activity found, message, connect etc.
{
{------------------------------------------------------------------------------
}
Function ITC_Find_Activity
	  ( VAR Channel : CHANNEL_RANGE;
	    VAR AType	: INTEGER ) : INTEGER;

Begin
  If Head = Tail Then ITC_Find_Activity := ITC__No_Activity
  Else Begin
    ITC_Find_Activity := ITC__Success;
    Channel := Ring_Buff[Tail].Chan;
    AType   := Ring_Buff[Tail].Class;
{    If Atype<>ITC_K_Message Then }
				{*** unload ring buffer only}
				{for non message information}
{    Begin }
	Tail := (Tail + 1) mod Ring_Buff_Size;
	Ring_Buff_Length := Ring_Buff_Length - 1
{    End; }
  End {Else Head<>Tail}
End  { ITC Find Activity };

End  { ITC Message Transfer Module }.
