static char sccsid[] = "%W% %Y% %Q% %G%";
static char rcsid[] = "$Header: xd_netman.c,v 800.0 85/09/30 17:04:42 root Exp $";

#include "ex.h"			/* Configuration constants */
#include "xm.h"			/* Defines download driver */
#include "xd.h"			/* Defines (TCI/DECnet) logical link driver */

#include	"../h/types.h"		/* Commonly used data types */

#include	"../machine/pte.h"	/* VM page table definitions */
#include	"../h/param.h"		/* Process, memory and file sys parameters */
#include	"../h/systm.h"		/* Kernel global variables */
#include	"../h/mbuf.h"		/* Net/Comm buffer definitions */
#include	"../h/socket.h"	/* Socket interface definitions */
#include	"../h/vmmac.h"		/* Virtual memory address conversion macros */
#include	"../h/map.h"		/* Resource allocation maps */
#include	"../h/ioctl.h"		/* System wide IOCTL definitions */
#include	"../h/dir.h"		/* File directory definitions */
#include	"../h/buf.h"
#include	"../h/inode.h"
#include	"../h/uio.h"
#include	"../h/user.h"		/* U Page definitions (per user blocks) */
						/*  ../h/user.h includes 
							../machine/pch.h
							../h/dmap.h
							../h/time.h
							../h/resource.h
							../h/errno.h
				 		*/
#include	"../h/proc.h"
#include	"../h/kernel.h"	/* Kernel variables */
#include "../net/if.h"		/* Network interface definitions */
#include "../netinet/if_ether.h"	/* Standard Ethernet definitions */


#include	"../s32dev/exreg.h"	/* EXOS 201 definitions */
#include	"../s32dev/exdef.h"	/* Standard EXOS definitions */
#include 	"../s32dev/exioctl.h"	/* Definition of ioctl's */
#include	"../tci/tci.h"		/* TCI standard definitions */
#include	"../tci/exos_decnet.h"	/* Decnet Exos interface */
#include	"../tci/community.h"	/* TCI/Community User Definitions */
#include	"../tci/exos_sync.h"	/* Sync/Kludge buffer defines */

#define	BSIZE CLBYTES

extern struct ex_softc EX_SOFTC(NEX);	/* Controller/driver state and data */
extern ExosSync exos_sync[];		/* Kludge (sync/reply) pool */

extern struct buf *ex_getbuf();
extern struct buf *geteblk();
extern LinkInfo llinfo[NLL];

ExosPacket *ll_findmsg();
ExosSync *ll_send();



bool nm_opened = FALSE;
#ifdef	DEBUG
short nm_debug = 0;
#endif



nmopen( dev ) 
dev_t dev;
	{

	/* Only the super user is allowed to do this */
	if( !suser() )
		return( u.u_error = EPERM );

	/* Check if network management file is already open */
	/* This code should only apply to the one netman file implementation */
	if( nm_opened )
		{
		DPRINT( nm_debug, 0, ( "/dev/netman is already open\n" ) );
		return( u.u_error = ETXTBSY );
		}

	/* Allocate link */
	nm_opened = TRUE;

	return(0);
	}



nmclose( dev ) 
dev_t dev;
	{
	register ExosSync *kp;

	/* If link not allocated, I/O error */
	if( !nm_opened )
		{
		return( u.u_error = EIO );
		}

	/* ok, close down the link! */
	nm_opened = FALSE;

	/*
	 * Clear all sync. buffers waiting for this process!
	 */
	for( kp = exos_sync; kp < &exos_sync[NUM_EXOS_SYNC]; ++kp )
		if( kp->xsy_proc == u.u_procp )
			kp->xsy_state = XSY_FREE;

	return( u.u_error = 0 );
	}






/*
 * nmread() -
 *
 *  There is no read defined for the network management device yet!
 */
nmread( dev, uio ) 
dev_t dev;
struct uio *uio;
	{

	return( u.u_error = EIO );
	}




/*
 *	nmwrite
 *
 *     There is no write defined for the network management device.
 */
nmwrite( dev, uio )
dev_t dev;
struct uio *uio;
	{

	return( u.u_error = EIO );
	}







/*
 *	nmioctl() -
 *
 */
nmioctl( dev, cmd, addr, flag )
dev_t dev;
int cmd;
u_char *addr;
int flag;
	{
	register ExosPacket *mp;
	register ExosSync *kp;
	register struct buf *opn;		/* Pointer to open block I/O buf */
	register struct ex_softc *xs;
	register short datasize = IOCTLDATASIZE(cmd);
	register short returnvalue;		/* Returned from on-board LL driver */
	register short min_dev;

	DPRINT( nm_debug, 1, ( "nmioctl:(%x,%x,%x,%x,%x)\n",
			dev, cmd, addr, (caddr_t)(*((long *)addr)), flag ) );

	min_dev = minor( dev );
	xs = &EX_SOFTC( 0 );		/* controller 0 */

	/* Logical Link Status routine */
	if( cmd == NETM_LL_STAT )
		{
		nm_ll_stat();
		return( u.u_error = 0 );
		}

	/* get a UNIX buffer for the data */
	if( ( opn = ex_getbuf() ) == NULL )
		{
		panic( "nmioctl: no more UNIX buffs" );
		return( u.u_error = EIO );
		}
	
	/* Get EXOS message buffer.  This will block until one is available */
	if( ( mp = ll_findmsg (xs, DNopen ) ) == NULL )
		{
		/* this should not happen; ll_findmsg() blocks */
		panic( "nmioctl: no more EXOS buffs" );
		return( u.u_error = EIO );
		}

	DPRINT( nm_debug, 1, ( "nmioctl: command 0x%x\n", IOCTLNUM( cmd ) ) );


	/* 
	 * Fill in EXOS buff with address and length of the data
	 * Note that EXOS gets a physical address!
	 */
	mp->ex_bd.eb_addr = (caddr_t)vtop(opn->b_adrs);
	mp->ex_bd.eb_len = datasize;

	/* Fill in other information into the EXOS driver */
	mp->ex_lcn = 0;
	mp->ex_dev_type = DEV_NETM;
	mp->ex_fd = min_dev;
	mp->ex_cmd_type = DNioctl;		/* Command for on-board LL driver */
	mp->ex_mdata.ioctl_func = IOCTLNUM( cmd );

	/* copy the data from the ioctl block into System space */
	bcopy( addr, opn->b_adrs, datasize );

	/*
	 * Send message buffer to on-board LL driver.
	 * This will block until the board responds!
	 */
	kp = ll_send( xs, 0, mp, 0, TRUE );

	/*
 	 * The ioctl has been processed!
	 */

	/* Check the return value and set the file's state accordingly */
	returnvalue = kp->xsy_ret_status;

	/*
	 * Copy the EXOS-generated data back to the user
	 * And free the UNIX I/O buffer
	 */
	bcopy( opn->b_adrs, addr, datasize );
	brelse( opn, BSIZE );

	/* get rid of the sync. buffer */
	free_sync_buffer( kp, xs );

	/*
	 * The mdata.ret_status field is returned from the on-board LL driver
	 * and saved in the kuldge buffer in llintr.
	 * We inspect the value and then return a number to the
	 * user program.
	 */
	return( u.u_error = returnvalue );
	}





/*
 * Routine:	nm_ll_stat()
 *
 * Access type:	Private (to xd_netman.c)
 *
 * Abstract:	This prints out to the console statistics on the logical
 *			links.  Should be changed to return rather than the console.
 *
 * Inputs:	None.
 *
 * Outputs:	None.
 *
 * Returns:	None.
 *
 * Side Effects:	Prints logical link stats to the console.
 *
 * Assumptions:	Unknonw.
 */
nm_ll_stat()
	{
	register int i;

	for( i = 1; i < NLL; ++i )
		{
		printf( "Link %d: state %d, link %d, pid %d\n", i,
			llinfo[i].li_state, llinfo[i].li_link, llinfo[i].li_pid );
		}
	}

