/*******************************************************************************
**
**	Dummy Ethernet Code for RPC
**
**  This code is part of the RPC system from CERN DD/OC and collaborators.
**
**
** FUNCTION:
**
**  This is the machine-dependent part of the code to allow the system to
**  communicate over ethernet. This version is for test only.
**
** HISTORY:
**
**     Sep 89	Written
**
*/

#include <stdio.h>

#define TS			/* We want TS_layer visibility */    
#define TS_INTERNALS		/* and internal data structures */

#include "syspec.h"
#include "rpcrts.h"		/* RPC structures including TS layer */
#include "rpc_code.h"		/*Coding conventions and trace */

/*	Module Variables
*/

    int		    eth_usage;	    /* Count of current usage of ethernet */


/*      Procedure:      Initialise the ethernet i/o
**	---------	---------------------------
**
**  This routine is called once only for this process, to initialise
**  any process-wide things.
**
** On exit,
**	return	    gives the return status
*/   
PUBLIC rpc_status rpc_eth_init()
{
    eth_usage = 0;
    CTRACE(tfp, "rpc_eth_init() called.\n");
    return RPC_S_NORMAL;
}

/*      Procedure:      Initialise the ethernet i/o for one channel
**	---------	-------------------------------------------
**
** On entry,
**	psocket	    points to a socket descriptor which has been set up
**		    with the correct ethernet addreess, type fields and masks.
** On exit,
**	return	    gives the return status
*/   
PUBLIC rpc_status rpc_eth_open(psocket)
	socket_type	psocket;
{
        register socket_type    soc = psocket;
        int eth_status;

	CTRACE(tfp, "rpc_th_open(%lx)\n", (long int)psocket);
	dump_socket(psocket);
	return RPC_S_NORMAL;
}
 
/*
**      Procedure:      DeInitialise the ethernet i/o for one channel
**	---------	---------------------------------------------
**
** This procedure in fact checks whether the very last open is being done,
** in which case it performs any global deinitialisation which may be required.
**
** On entry,
**	psocket	    points to a socket descriptor.
** On exit,
**	return	    gives the return status
*/   
PUBLIC rpc_eth_close(soc)
    socket_type	soc;
{
    eth_usage = eth_usage - 1;
    CTRACE(tfp, "rpc_eth_close(%lx)\n", (long int)soc);
    return RPC_S_NORMAL;
}

/*      Procedure:      Send ethernet packet
**	---------	--------------------	
**
**  On entry,
**	socket	    points to an initialised socket.
**
**      buffer	    points to a packet. The destination field and protocol type
**		    in the packet header are correct.
**	    m_socket	is valid
**	    m_index	is the number of bytes (excluding the header)
**		    The source address is not yet filled in.
**	bufsize     gives the number of bytes to be transmitted, EXCLUDING the
**		    ethernet header.
**  On exit,
**	return      Gives the status: if good, the packet has been sent.
**
*/
PUBLIC rpc_status rpc_eth_send(mes)
        rpc_message_pointer mes;
{
    int			    bufsize = (int)mes->m_index;
    register socket_type    soc = mes->m_socket;

    CTRACE(tfp, "rpc_eth_send(%lx)\n", (long int)mes);
    dump_message(mes);
    return RPC_S_NORMAL;
}
 
 
/*      Wait for ethernet message			      rpc_eth_receive()
**	-------------------------
**
** This procedure receives one ethernet message on the given socket.
** The packets are filtered by source address and protocol type according
** to the way the socket has been set up (wildcard or not).
**
** On entry,
**
**	ppmessage   points to a pointer to a suitable message buffer with
**		    the following fields set up:
**
**		    m_socket	Pointer to socket descriptor
**
**      timeout	    may be -1 for infinite timeout, or 0 for poll.
**		    else units of microseconds.
**
** On return,
**
**      return	    returns error code or normal or timeout.
**      *pmessage   may have been changed, ie the message swapped for another.
**      **pmessage  has the header and data fields both filled in.
**	    m_index	gives the number of data bytes in the message.
*/

PUBLIC rpc_status rpc_eth_receive(ppmessage, timeout)
        rpc_message_pointer     *ppmessage;
        int			timeout;
{

    register rpc_message *mes = *ppmessage;
    register socket_type soc =  mes->m_socket;
    CTRACE(tfp, "rpc_eth_receive(%lx->%lx, %x)\n",
	(long int)ppmessage, (long int)*ppmessage, timeout);
    dump_message(mes);
#ifdef ZAPPED
    return (RPC_S_TIMEOUT);	/* Simulate no response */
#else
    (*ppmessage)->body.rpc_b[1] = 2;	/* Cheat a "reply" type */
    return (RPC_S_NORMAL);	/* Simulate the same message back */
#endif
}

/*	Return the ethernet address of this host	    rpc_eth_my_address()
**	----------------------------------------
**
**  On entry,
**	host	    points to a 6-byte buffer
**
**  On exit,
**	*host	    is filled in with the address in binary of the local
**		    ethernet adapter if good status.
**
**	returns	    status if bad means *host is undefined but may be corrupted.
*/
#ifdef __STDC__
rpc_status rpc_eth_my_address(		    /* Return host address  */
    rpc_ethernet_address	host)	    /* Buffer for host address  */
#else
rpc_status rpc_eth_my_address(host)	    /* Return host address  */
    rpc_ethernet_address	host;	    /* Buffer for host address  */
#endif
{
    rpc_byte i;
    for (i=0; i<6; i++)
	host[i] = (i*34)+18;		    /* 123456789ABC */

    return RPC_S_NORMAL;
}

#ifdef AST
/*      Set up handler for next message to arrive	  rpc_eth_when_receive()
**	-----------------------------------------
**
**                    (Only if ASTs supported)
**
** On entry,
**	pmessage    points to an available message buffer, fields as follows:
**	    m_index	maximum length to be read
**	    m_status	(undefined)
**	    m_next	(undefined)
**	    m_socket	points to valid socket descriptor, includes fields
**		soc_user_ast	address of AST completion routine
*/
PUBLIC rpc_status eth_when_receive(pmessage)
        rpc_message_pointer     pmessage;
{
        register struct socket_struct *soc = pmessage->m_socket;
	CTRACE(tfp, "rpc_eth_when_receive(%lx)\n", (long int)pmessage);
	return RPC_S_NORMAL;
}
#endif /* AST */