File:  [MW Coherent from dump] / coherent / d / PS2_KERNEL / ldrv / ldmain.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/* $Header: /var/lib/cvsd/repos/coherent/coherent/d/PS2_KERNEL/ldrv/ldmain.c,v 1.1.1.1 2019/05/29 04:56:39 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Loadable Driver - Process Handler.
 *
 * $Log: ldmain.c,v $
 * Revision 1.1.1.1  2019/05/29 04:56:39  root
 * coherent
 *
 * Revision 1.1  92/07/17  15:27:53  bin
 * Initial revision
 * 
 * Revision 1.2	89/03/31  16:19:36 	src
 * Bug:	Did not cancel either attached timed functions or deferred functions
 * 	during an unload.  As a result, if a driver did not explicitly do
 * 	this, then unloading the driver could cause a system panic.
 * Fix:	Now cancels the functions. (ABC)
 * 
 * Revision 1.1	88/03/24  08:30:44 	src
 * Initial revision
 * 
 * 87/12/03	Allan Cornish		/usr/src/sys/ldrv/ldmain.c
 * Initial version.
 */
#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/con.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>

extern CON con;

extern	saddr_t	ldrvsel[NDRV];
extern	saddr_t ldrvics[16];
extern	void  (*ldrvipc[16])();
extern	CON *	ldrvcon[NDRV];
extern	CON	ldrvpsy;
extern	saddr_t	ucs;

/*
 * Local variable - keeps track of the number of opens.
 * The loadable driver can't terminate until after the last close.
 * Openf is the loadable driver open routine.
 * Closef points to the driver's close routine.
 * The configuration table entries are taken over
 */
static	int	nopen = 0;
static	void	(*openf)() = NULL;
static	void	(*closef)() = NULL;

main()
{
	register int mind = con.c_mind;
	register int level;
	extern	void myopen();
	extern	void myclose();
	extern	void Kdefend();

	/*
	 * Loadable devices must identify the desired major device.
	 */
	if ( (mind == 0) || (mind >= drvn) ) {
		printf("ldrv:%d: bad dev\n", mind );
		uexit( 1 );
	}

	/*
	 * Loadable devices must use a unique [not in use] major device.
	 */
	if ( (drvl[mind].d_conp != NULL) || (ldrvcon[mind] != NULL) ) {
		printf("ldrv:%d: dev bsy\n", mind );
		uexit( 0 );
	}

	/*
	 * Intercept driver open/close requests.
	 * This allows the driver process to terminate after the last close,
	 *	if one or more signals have been received.
	 */
	openf		= con.c_open;
	closef		= con.c_close;
	con.c_open	= myopen;
	con.c_close	= myclose;

	/*
	 * Install the loadable driver pseudo device interface.
	 * The O/S will call the pseudo-device, which will call us.
	 * Record our driver configuration and code segment.
	 */
	drvl[mind].d_conp = &ldrvpsy;
	ldrvcon[mind] = &con;
	ldrvsel[mind] = ucs;

	/*
	 * Load the device driver.
	 */
	if ( con.c_load != NULL )
		(*con.c_load)( makedev(mind,0) );

	/*
	 * Sleep until a kill signal has arrived, and no device is open.
	 */
	do {
		sleep( (char *)&nopen, CVSWAP, IVSWAP, SVSWAP );

	} while ( ((SELF->p_ssig & 0x0100) == 0) || (nopen != 0) );

	/*
	 * Unload the device driver.
	 */
	if ( con.c_uload != NULL )
		(*con.c_uload)( makedev(mind,0) );

	/*
	 * Erase references to our kernel process.
	 */
	drvl[mind].d_conp = NULL;
	ldrvcon[mind] = NULL;
	ldrvsel[mind] = 0;

	/*
	 * Scan looking for attached interrupts.
	 * NOTE: This is to prevent dangling interrupt vectors.
	 */
	for ( level = 0; level < 16; level++ ) {

		/*
		 * Interrupt is not attached to us.
		 */
		if ( ldrvics[level] != ucs )
			continue;

		/*
		 * Disable interrupt.
		 */
		clrivec( level );

		/*
		 * Release loadable driver interrupt.
		 */
		ldrvics[level] = 0;
		ldrvipc[level] = NULL;
	}

	/*
	 * Service deferred functions BEFORE scanning for timed functions.
	 * This is in case a deferred function schedules a timed function.
	 */
	kcall( Kdefend );

	/*
	 * Scan for attached timed functions which have to be terminated.
	 */
	for ( level = 0; level < nel(timq); level++ ) {
		register TIM * tp;

		/*
		 * Access a specific timing queue.
		 */
		for ( tp = timq[level]; tp != NULL; ) {

			/*
			 * Timed function is in our loadable driver.
			 * Restart search at start of timing queue.
			 */
			if ( FP_SEL(tp->t_ldrv) == getcs() ) {
			  	timeout( tp, 0, NULL, 0 );
				tp = timq[ level ];
			}

			/*
			 * Not one of our timed functions.
			 * Advance to next function in queue.
			 */
			else
				tp = tp->t_next;
		}
	}

	/*
	 * Terminate with extreme prejudice.
	 */
	uexit( 0 );
}

static void
myopen( dev, mode )
dev_t dev;
int mode;
{
	/*
	 * Invoke the true open routine for the loadable driver.
	 */
	if ( openf != NULL )
		(*openf)(dev, mode );

	/*
	 * Adjust reference count if open succeeded.
	 */
	if ( u.u_error == 0 )
		nopen++;
}

static void
myclose( dev )
dev_t dev;
{
	/*
	 * Invoke the true close routine for the loadable driver.
	 */
	if ( closef != NULL )
		(*closef)( dev );

	/*
	 * Wakeup driver process after last close.
	 * This allows it to terminate if appropriate.
	 */
	if ( --nopen == 0 )
		wakeup( (char*) &nopen );
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.