4.3BSD-UWisc/src/sys/vaxuba/aed.c

Compare this file to the similar file:
Show the results in this format:

/* aed.c 1.1		2/84
 *
 * Driver for the AED-512.  This driver uses raw block transfer.
 *
 * The driver has a kludge because we've been unable to get the AED board to
 * interrupt on completion of a DMA transfer.  Essentially the watch dog
 * routine will cause a pseudo interrupt if it detects that the current
 * operation has completed (i.e. word count = 0).  This kludge can be disabled
 * via the ioctl routine.
 *
 * Another kludge.  Because it is necessary to start the io on the AED board
 * before the device on the other side (eg. VICOM) begins the transfer a wait
 * for io initiated is available via aedioctl.  The proper sequence for an
 * read is:
 *
 *	if (fork())
 *	{
 *		read(aedfd, buffer, length);
 *		wait(0);
 *	}
 *	else
 *	{
 *		if (ioctl(aedfd, AEDSTARTED, NULL) == 0)
 *			start the VICOM transfer via serial line;
 *		_exit;
 *	}
 *
 * Notice that there is no protection from two processes trying to perform
 * simultaneous operations.  Things could become quite confused although
 * the system should not deadlock.  To protect against this use the AEDLOCK
 * control call (see below).
 *
 * To allow a process to make several tranfers without interference the AED
 * can be locked.  To lock the AED driver use:
 *		rc = ioctl(aedfd, AEDLOCK, NULL)
 * If the AED is already locked EBUSY will be returned otherwise the AED will
 * be locked so that only this process may perform transfers. To unlock it:
 *		ioctl(aedfd, AEDUNLOCK, NULL)
 * AEDRESET also forces the AED to unlock and permits any user to open it.
 *
 *****************************************************************************
 * Written by Dayton Clark (CIMS) September 1983.
 * Modified November 1983 for 4.2bsd by Lou Salkind.
 * Modified Feburary 1984 by Dayton Clark:
 *	Allow multiple processes to open the AED.
 *	Add AEDLOCK & AEDUNLOCK ioctl commands.
 *	Improve AEDRESET ioctl command.
 */

#ifdef lint
#define KERNEL 1
#define NAED 1
#else
#include 	"aed.h"
#endif
#if NAED > 0

#include "../machine/pte.h"

#include "param.h"
#include "user.h"
#include "proc.h"
#include "buf.h"
#include "systm.h"
#include "map.h"
#include "ioctl.h"
#include "uio.h"
#include "kernel.h"
#include "../ufs/fsdir.h"

#include "../vaxuba/aedreg.h"
#include "../vaxuba/ubavar.h"
#include "../vaxuba/ubareg.h"

/* Routines defined.
 */
int		aedprobe();
int		aedattach();
int		aedopen();
int		aedclose();
int		aedioctl();
int		aedread();
int		aedwrite();
int		aedio();
int		aedstrategy();
unsigned	aedmincnt();
int		aedintr();
int		aedwatch();
int		aedinprogress();

/* Miscellaneous constants.
 */
#define	MAXBLK		(2*65536)	/* Maximum transfer size, in bytes */
#define	AED_ADDRESS	0764040		/* AED device register address. */
#define AED_VECTOR	0170		/* AED interrupt vector location. */
#define WATCH_TIC	8		/* Watch dog interval. */
#define TICLIMIT	80		/* # tics til timeout. */
#define AED_PRIORITY	(PZERO+4)	/* Priority when waiting for IO. */

/* AEDUNIT(dev) extracts unit # from device descriptor.
 */
#define	AEDUNIT(dev) (minor(dev))

/* A few necessities for UNIBUS devices.
 */
unsigned short		aedstd []	/* Standard device address. */
				= {AED_ADDRESS};
struct uba_device	*aedinfo[NAED];	/* Device structures. */
struct uba_driver	aeddriver	/* Driver structure. */
				= {aedprobe, 0, aedattach, 0,
					aedstd, "aed", aedinfo};

/* Miscellaneous.
 */
static int	aed_debug = 0;		/* Debug print flag. */
static int	aedwatch_active = 0;	/* Watch dog routine active flag. */
static int	aed_priviledged_users [] = {90, 0};
				/* Users who can always open the AED. 90=tom@ai */

/* Device software control blocks for the AED-512's.
 */
struct aed_softc
{
	int			sc_flags;   /* NEW */
	int			sc_user;	/* User id. */
	int			sc_lock;	/* Access lock (process). */
	int			sc_ubinfo;	/* UNIBUS addr. user buf. */
	int			sc_tics;	/* Watch dog counter. */
	struct buf		sc_buf;		/* Buffer header. */
	struct aeddevice	sc_reg;		/* Copy of AED registers. */
};
static struct aed_softc aed_softc [NAED];

/* Control block flags.
 */
#define	SC_IN_PROGRESS	0x0001	/* Operation in progress. */
#define SC_OPENED	0x0002	/* Device opened. */
#define SC_BUSY		0x0008	/* Control block is in use. */
#define SC_STARTED	0x0020	/* Operation has been started. */
#define SC_CANCELLED	0x0040	/* Operation has been cancelled. */
#define SC_PSEUDO_INTR	0x0100	/* Non-interrupt operation kludge. */
#define SC_SWAP_BYTES	0x0200	/* Swap bytes on transfer. */
#define SC_NEX_MEMORY	0x2000	/* Non-existant memory. */
#define	SC_TIMED_OUT	0x4000	/* Operation timed out. */
#define	SC_ERROR	0x8000	/* Error in operation. */

/* Format string for the sc_flags.
 */
#define AED_SC_FLAGS_BITS "\20\20ERROR\17TIMEOUT\16NEX\12SWAP\11PSEINTR\7CANCELLED\6STARTED\4BUSY\2OPENED\1INPROGRESS"

/* Aedprobe(reg) sets the AED boards interrupt vector and returns 1
 * to indicate that the AED is available.  Reg points to the AED
 * device registers.
 */
/* ARGSUSED */
aedprobe(reg)
	caddr_t		reg;
{
	register int	br, cvec;	/* must be like this, don't touch. */

	if (aed_debug)
		printf("entered aedprobe()\n");

#ifdef lint
	br = 0; cvec = br; br = cvec;
#endif
	/* Assume the vector is at AED_VECTOR.
	 * This can perhaps be fixed, though I doubt it.
	 */
	cvec = AED_VECTOR;
	br = 0x15;

	if (aed_debug)
		printf("exited aedprobe()\n");
	return(1);
}


/* Aedattach(ui) performs some initialization.
 */
aedattach(ui)
	struct uba_device		*ui;
{
	register struct aed_softc	*sc;
	register struct aeddevice	*aedaddr;

	if (aed_debug)
		printf("entered aedattach()\n");

	sc = &aed_softc [ui->ui_unit];
	aedaddr = (struct aeddevice *) ui->ui_addr;

	/* Clear the control block fields.
	 * Clear the device registers and control block copies.
	 */
	sc->sc_flags = 0;
	sc->sc_user = 0;
	sc->sc_lock = 0;
	sc->sc_ubinfo = 0;
	sc->sc_tics = 0;
	aedaddr->aed_cosi = sc->sc_reg.aed_cosi = 0;
	aedaddr->aed_ba   = sc->sc_reg.aed_ba   = 0;
	aedaddr->aed_iset = sc->sc_reg.aed_iset = 0;
	aedaddr->aed_wc   = sc->sc_reg.aed_wc   = 0;

	if (aed_debug)
		printf("exited aedattach()\n");
	
}

/* Aedopen(dev, flag) opens the AED device. Dev indicates the device to be
 * opened, flag is the read/write flag and is currently ignored.  Aedopen
 * first checks that the unit number is ok then it checks that this user
 * can open the device (i.e. the open doesn't conflict with another user).
 * If all is ok the device is opened and the watchdog timer is started.
 */
/* ARGSUSED */
aedopen(dev, flag)
	dev_t	dev;
	int	flag;
{
	register int			unit;
	register struct aed_softc	*sc;
	register struct uba_device	*ui;
	int				uid;
	int				rc;

	/* If the unit # is out of range or there is no uba_device
	 * exit with ENXIO error.
	 * If it's not opened then open it.
	 * If it's already opened but ok for this user to reopen it, OK.
	 * Otherwise return EBUSY.
	 */
	if (aed_debug)
		printf("entered aedopen(), flag = %x\n",flag);

	unit = AEDUNIT(dev);
	if     (unit >= NAED ||
		(ui = aedinfo[unit]) == 0 ||
		ui->ui_alive == 0)

		rc = ENXIO;
	else
	{
		sc = &aed_softc[unit];
		uid = u.u_uid;
		if     ((sc->sc_flags & SC_OPENED) == 0)
		{
			sc->sc_user = uid;
			sc->sc_flags = SC_OPENED;
			if (aedwatch_active == 0) aedwatch((caddr_t) 0);
			rc = 0;
		}
		else if ((sc->sc_user == uid) || aed_priviledged_user(uid))

			rc = 0;
		else
			rc = EBUSY;
	}
	if (aed_debug)
		printf("exiting aedopen() with rc = %x\n",rc);

	return(rc);
}

/* Aed_priviledged_user(uid) returns 1 if the user indicated by uid is a
 * priviledged user for the AED.
 */
aed_priviledged_user(uid)
	int	uid;
{
	int	*puid;

	puid = aed_priviledged_users;
	do
		if (*puid == uid) return(1);
		while (*puid++ != 0);
	return(0);
}

/* Aedclose(dev, flags) closes the AED-512 unit specified by  dev.  Flags is
 * currently ignored.
 */
/* ARGSUSED */
aedclose(dev, flag)
	dev_t				dev;
	int				flag;
{
	register int			unit;
	register struct aed_softc	*sc;
	register struct uba_device	*ui;
	register struct aeddevice	*aedaddr;

	if (aed_debug)
		printf("entered aedclose() flag = %x\n",flag);

	unit = AEDUNIT(dev);
	sc = &aed_softc[unit];
	ui = aedinfo[unit];
	aedaddr = (struct aeddevice *) ui->ui_addr;

	/* Clear everything.
	 */
	sc->sc_flags = 0;
	sc->sc_user = 0;
	sc->sc_lock = 0;
	sc->sc_ubinfo = 0;
	sc->sc_tics = 0;
	aedaddr->aed_cosi = sc->sc_reg.aed_cosi = 0;
	aedaddr->aed_ba   = sc->sc_reg.aed_ba   = 0;
	aedaddr->aed_iset = sc->sc_reg.aed_iset = 0;
	aedaddr->aed_wc   = sc->sc_reg.aed_wc   = 0;

	if (aed_debug)
		printf("exiting aedclose()\n");
}

/* Aedioctl(dev, cmd, data, flag) performs the io control functions.  Dev is
 * the device code, cmd is the desired command code (from aedreg.h),
 * data points to the area to receive the status for the AEDSTATUS command.
 * Flag is not currently used.
 */
/*ARGSUSED*/
aedioctl(dev, cmd, data, flag)
	dev_t				dev;
	int				cmd;
	caddr_t				data;
	int 				flag;
{
	register struct aed_softc	*sc;
	register struct uba_device	*ui;
	register struct aeddevice	*aedaddr;
	struct buf			*bp;
	int				unit;
	struct aedstatus		*sp;
	int				s;
	int				rc;

	if (aed_debug)
		printf("Aedioctl(%x, %d, %x, %d)\n", dev, cmd, data, flag);

	unit = AEDUNIT(dev);
	sc = &aed_softc [unit];
	bp = &sc->sc_buf;
	ui = aedinfo [unit];
	aedaddr = (struct aeddevice *) ui->ui_addr;
	rc = 0;

	switch(cmd) {

	case AEDPSEUDO:

		/* Enable pseudo interrupts.
		 */
		sc->sc_flags |= SC_PSEUDO_INTR;
		break;

	case AEDNOPSEUDO:

		/* Disable pseudo interrupts.
		 */
		sc->sc_flags &= ~SC_PSEUDO_INTR;
		break;

	case AEDRESET:

		/* AEDRESET does the following:
		 * 	Clear the AED's device registers.
		 *	Wakeup processes that may be waiting anyplace
		 *		associated with this device.
		 *	Unlock the device.
		 *
		 * This is a pretty brutal reset and is intended for
		 * emergency use.  It may have to be repeated several
		 * times to clear everything out of the system.
		 * NOTE: once a reset has been done the device must
		 * be opened again before operations can be performed.
		 */
		aedaddr->aed_cosi = sc->sc_reg.aed_cosi = 0;
		aedaddr->aed_ba   = sc->sc_reg.aed_ba   = 0;
		aedaddr->aed_iset = sc->sc_reg.aed_iset = 0;
		aedaddr->aed_wc   = sc->sc_reg.aed_wc   = 0;
		sc->sc_user = 0;
		sc->sc_lock = 0;
		sc->sc_flags = SC_CANCELLED;
		wakeup((caddr_t) sc);
		wakeup((caddr_t) &(sc->sc_reg));
		break;

	case AEDSTARTED:

		/* If the AED is locked or not opened, error exit.
		 * Wait until SC_STARTED is set.
		 */
		if ((sc->sc_lock) && (sc->sc_lock != u.u_procp->p_pid))
			rc = EBUSY;
		else
		{
			s = spl5();		/* ********CRITICAL SECTION */
			while ((sc->sc_flags &
				(SC_STARTED | SC_CANCELLED)) == 0)

				sleep((caddr_t) &(sc->sc_reg), AED_PRIORITY);

			if (sc->sc_flags & SC_CANCELLED) rc = EIO;
			sc->sc_flags &= ~(SC_STARTED | SC_CANCELLED);
			splx(s);		/* ****END CRITICAL SECTION */
		}
		break;

	case AEDDEBUG:

		/* Turn on the debug flag.
		 */
		aed_debug = 1;
		break;

	case AEDNODEBUG:

		/* Turn off the debug flag.
		 */
		aed_debug = 0;
		break;

	case AEDLOCK:

		/* If the device is already locked return EBUSY.
		 * Otherwise lock the AED.
		 */
		if ((sc->sc_lock) && (sc->sc_lock != u.u_procp->p_pid))
			rc = EBUSY;
		else
			sc->sc_lock = u.u_procp->p_pid;
		break;

	case AEDUNLOCK:

		/* If this is the process that has the AED locked then
		 * unlock it otherwise return EBUSY.
		 */
		if ((sc->sc_lock) && (sc->sc_lock != u.u_procp->p_pid))
			rc = EBUSY;
		else
			sc->sc_lock = 0;
		break;

	case AEDSTATUS:

		/* Report the status of the AED.
		 */
		sp = (struct aedstatus *) data;
		sp->aed_flags = sc->sc_flags;
		sp->aed_user = sc->sc_user;
		sp->aed_lock = sc->sc_lock;
		sp->aed_tics = sc->sc_tics;
		sp->aed_b_flags = sc->sc_buf.b_flags;
		sp->aed_b_error = sc->sc_buf.b_error;
		sp->aed_cosi = sc->sc_reg.aed_cosi;
		sp->aed_iset = sc->sc_reg.aed_iset;
		sp->aed_ba = sc->sc_reg.aed_ba;
		sp->aed_wc = sc->sc_reg.aed_wc;
		break;

	case AEDSWAPBYTES:

		/* Set the swap bytes flag.
		 */
		sc->sc_flags |= SC_SWAP_BYTES;
		break;

	case AEDNOSWAPBYTES:

		/* Clear the swap bytes flag.
		 */
		sc->sc_flags &= ~SC_SWAP_BYTES;
		break;

	default:
		rc = ENOTTY;
	}
	if (aed_debug)
		printf("exiting aedioctl with rc = %x\n",rc);

	return(rc);
}

/* Aedread(dev) performs a DMA read using dev.
 */
aedread(dev, uio)
	dev_t		dev;
	struct uio	*uio;
{
	return(aedio(dev, uio, B_READ));
}

/* Aedwrite(dev) performs a DMA write using dev.
 */
aedwrite(dev, uio)
	dev_t		dev;
	struct uio	*uio;
{
	return(aedio(dev, uio, B_WRITE));
}

/* Aedio(dev, uio, rw) performs the read or write. Rw indicates the direction
 * of the transfer, either B_READ or B_WRITE.
 */
aedio(dev, uio, rw)
	dev_t		dev;
	struct	uio	*uio;
	int		rw;
{
	register struct buf		*bp;
	register struct aed_softc	*sc;
	int				unit;
	int				rc;
	int				s;

	if (aed_debug) printf ("aedio(%x, %x, %x)\n", dev, uio, rw);

	unit = AEDUNIT(dev);
	sc = &aed_softc [unit];
	bp = &sc->sc_buf;

	/* If the open flag is off, most likely someone has done AEDRESET.
	 * Skip all operations until this is reopened.
	 */
	if ((sc->sc_flags & SC_OPENED) == 0) return (EBADF);

	/* Wait until any previous IO is completed.
	 * Turn off the various completion flags.
	 * If the control block is locked by another process cancel
	 * the operation and return EBUSY.
	 * Otherwise, perform the IO, this won't return until IO is complete.
	 * If the IO was not successful, display message for the user.
	 * Release the control block and notify anyone waiting for it.
	 */
	s = spl5();				/* ********CRITICAL SECTION */
	while (sc->sc_flags & SC_BUSY) sleep((caddr_t) sc, AED_PRIORITY);
	sc->sc_flags |= SC_BUSY;
	splx(s);				/* ****END CRITICAL SECTION */

	sc->sc_flags &= ~(SC_NEX_MEMORY | SC_TIMED_OUT | SC_ERROR);
	if ((sc->sc_lock) && (sc->sc_lock != u.u_procp->p_pid))
	{
		sc->sc_flags |= SC_CANCELLED;
		wakeup((caddr_t) &(sc->sc_reg));
		rc = EBUSY;
	}
	else
		rc = physio(aedstrategy, bp, dev, rw, aedmincnt, uio);

	if (sc->sc_flags & SC_ERROR)
	{
		uprintf("AED unit %d error:\n   flags=%b\n",
			unit, sc->sc_flags, AED_SC_FLAGS_BITS);
		uprintf("  registers:\n    cosi=%b\n    iset=%b\n",
			sc->sc_reg.aed_cosi, AED_COSI_BITS,
			sc->sc_reg.aed_iset, AED_ISET_BITS);
		uprintf("    ba=%x wc=%x\n",
			sc->sc_reg.aed_ba, sc->sc_reg.aed_wc);
	}

	sc->sc_flags &= ~SC_BUSY;
	wakeup((caddr_t) sc);
	if (aed_debug)
		printf("exited aedio() with rc = %x\n",rc);
	return(rc);
}

/* Aedstrategy(bp) performs a DMA transfer using buffer pointed to by bp.
 */
aedstrategy(bp)
	register struct buf		*bp;
{
	register struct aed_softc	*sc;
	register struct uba_device	*ui;
	register struct aeddevice	*aedaddr;
	int				unit;

	if (aed_debug) printf("aedstrategy(%x)\n", bp);

	unit = AEDUNIT(bp->b_dev);
	ui = aedinfo[unit];
	sc = &aed_softc[unit];
	aedaddr = (struct aeddevice *) ui->ui_addr;

	/* Clear the watch dog counter.
	 * Set the control block pointer to the buffer.
	 * Get the necessary UNIBUS map registers.
	 */
	sc->sc_tics = 0;
	if (aed_debug)
		printf("going to do ubasetup()\n");
	sc->sc_flags |= SC_IN_PROGRESS;
#ifdef UW
	/* changed from UBA_NEEDBDP because there aren't enough
	 * of them and it will *never* come back if it just
	 * sits there and waits for it.
	 */
	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_LIKEBDP|UBA_CANTWAIT);
#else UW
	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
#endif UW

	if (aed_debug)
		printf("done ubasetuo()\n");


	/* Load the device register and the sc's copies to start the
	 * transfer.
	 *	ba	UNIBUS address of the user's buffer.
	 *	cosi	AED_ALWAYS_ON plus the read/write flag from
	 *		bp->b_flags.
	 *	iset	AED_IENABLE (if SC_PSEUDO_INTR not set) and
	 *		the extended bus address bits shifted into the
	 *		proper position.
	 *	wc	The # of words to transfer, negated. (NOTE: loading
	 *		the wc register initiates the transfer.)
	 */
	aedaddr->aed_cosi = sc->sc_reg.aed_cosi = AED_ALWAYS_ON |
				((bp->b_flags & B_READ) ?
						AED_READ : AED_WRITE);
	aedaddr->aed_ba   = sc->sc_reg.aed_ba   =
					(unsigned short) sc->sc_ubinfo;
	aedaddr->aed_iset = sc->sc_reg.aed_iset =
		((sc->sc_flags & SC_PSEUDO_INTR) ? 0 : AED_IENABLE) |
		((sc->sc_flags & SC_SWAP_BYTES) ? AED_SWAP_BYTES : 0) |
		((sc->sc_ubinfo >> AED_SHIFT_XBA) & AED_XBA);
	aedaddr->aed_wc   = sc->sc_reg.aed_wc   =
					- (short) (bp->b_bcount >> 1);

	/* Signal that io has been initiated.  A co-process may be waiting
	 * on an AEDSTARTED command.
	 */
	sc->sc_flags |= SC_STARTED;
	wakeup((caddr_t) &(sc->sc_reg));

	if (aed_debug)
		printf("exited aedstrategy\n");

}

unsigned
aedmincnt(bp)
	struct buf *bp;
{
	if (bp->b_bcount > MAXBLK) bp->b_bcount = MAXBLK;
}

/* Aedintr(UNIT) is the interrupt service routine.  Unit is the number
 * of the unit causing the interrupt.
 */
aedintr(unit)
	int				unit;
{
	register struct aed_softc	*sc;
	register struct uba_device	*ui;
	register struct aeddevice	*aedaddr;
	struct buf			*bp;

	if (aed_debug) printf("aedintr(%d)\n", unit);

	sc = &aed_softc[unit];
	bp = &sc->sc_buf;
	ui = aedinfo[unit];
	aedaddr = (struct aeddevice *) ui->ui_addr;

	/* Get a copy of the device registers for safe keeping and for
	 * future reference.
	 * Then turn the device off.
	 * Clear the SC_IN_PROGRESS flag in the control block.
	 */
	sc->sc_reg.aed_cosi = aedaddr->aed_cosi;
	sc->sc_reg.aed_iset = aedaddr->aed_iset;
	sc->sc_reg.aed_ba   = aedaddr->aed_ba;
	sc->sc_reg.aed_wc   = aedaddr->aed_wc;
	aedaddr->aed_cosi = 0;
	aedaddr->aed_iset = 0;
	aedaddr->aed_ba   = 0;
	aedaddr->aed_wc   = 0;
	sc->sc_flags &= ~SC_IN_PROGRESS;

	/* Before we complete the io let's find out what has happened.
	 * Check for possible errors found in the iset register.
	 * If there's been an errors then set the buffer's error flag.
	 * NOTE that errors may have been detected elsewhere particularly
	 * by the watchdog routine.
	 * Release the UNIBUS map registers.
	 */
	if (sc->sc_reg.aed_iset & AED_BUS_TIMEOUT)
		sc->sc_flags |= SC_ERROR | SC_NEX_MEMORY;
	if (sc->sc_flags & SC_ERROR) bp->b_flags |= B_ERROR;

	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
	biodone(bp);

	if (aed_debug) 
		printf("exited aedintr()\n");
}

/* Aedwatch(dum) is the watch dog routine.  It's original purpose is to
 * insure that an AED io request doesnt get hung up because of a lost
 * interrupt.  However, because we can't get the AED board to interrupt
 * on CSD1, aedwatch serves the additional function of watching for
 * completion and generating pseudo interrupts.
 */
/* ARGSUSED */
aedwatch(dum)
	caddr_t				dum;
{
	register struct aed_softc	*sc;
	int				unit;
	int				nopened = 0;	/* # of open AED's. */

	/* For each AED unit:
	 * 	If it's not open then ignore it.
	 *	Otherwise count it and check for io in progress.
	 *	If there is io in progress then handle it.
	 */

#ifdef notdef
	if (aed_debug)
		printf("entered aedwatch\n");
#endif

	for (unit=0; unit<NAED; unit++)
	{
		sc = &aed_softc[unit];
#ifdef notdef
		if (aed_debug)
		{
			printf("aedwatch: nopened = %d\n",nopened);
			printf("aedwatch: sc->sc_flags = 0x%x\n",sc->sc_flags);
		}
#endif
		if ((sc->sc_flags & SC_OPENED))
		{
			nopened++;
#ifdef notdef
			if (aed_debug)
			{
				printf("aedwatch: nopened = %d\n",nopened);
				printf("aedwatch: sc->sc_flags = 0x%x\n",sc->sc_flags);
			}
#endif
			if (sc->sc_flags & SC_IN_PROGRESS)
				aedinprogress(unit, sc);
		}
	}

	/* If there's any open devices, restart the watch dog
	 * otherwise shut it down.
	 */
	if (nopened)
	{
#ifdef notdef
		if (aed_debug)
			printf("aedwatch: calling timeout\n");
#endif
		timeout(aedwatch, (caddr_t) 0, WATCH_TIC);
		aedwatch_active = 1;
	}
	else
	{
		aedwatch_active = 0;
#ifdef notdef
		if (aed_debug)	
			printf("aedwatch: setting aedwatch_active to 0\n");
#endif
	}
	
#ifdef notdef
	if (aed_debug)
		printf("exited aedwatch()\n");
#endif
}

/* Aedinprogress(unit, sc) takes care of io in progress for the watchdog
 * routine.  Unit is the AED unit number and sc points to the software
 * control block.
 */
aedinprogress(unit, sc)
	int				unit;
	register struct aed_softc	*sc;
{
	register struct aeddevice	*aedaddr;
	struct uba_device		*ui;
	int s;				/* Hold processor priority. */

	/* Get the uba info for this device then grab a copy of the
	 * device registers for safe keeping & future reference.
	 */

	if (aed_debug)
		printf("entered aedinprogress()\n");

	ui = aedinfo[unit];
	aedaddr = (struct aeddevice *) ui->ui_addr;
	sc->sc_reg.aed_cosi = aedaddr->aed_cosi;
	sc->sc_reg.aed_iset = aedaddr->aed_iset;
	sc->sc_reg.aed_ba   = aedaddr->aed_ba;
	sc->sc_reg.aed_wc   = aedaddr->aed_wc;

	/* Check for a timeout.  If we've exceeded the TICLIMIT then
	 * set the appropiate flags.
	 */
	if (++(sc->sc_tics) > TICLIMIT)
		sc->sc_flags |= SC_ERROR | SC_TIMED_OUT;

	/* Now should we fake an interrupt?  There are two reasons to do so.
	 * One is that pseudo interrupts have been requested and the io
	 * operation has completed (a kludge to get this to work on CSD1).
	 * The other is that a timeout has been detected,  the fake interrupt
	 * should clean up the mess.
	 * The processor priority is raised for calling the interrupt so
	 * that it feels at home.
	 */
	if (((sc->sc_flags & SC_PSEUDO_INTR) && (sc->sc_reg.aed_wc == 0)) ||
		(sc->sc_flags & SC_TIMED_OUT))
	{
		s = spl5();			/* ********CRITICAL SECTION */
		aedintr(unit);
		splx(s);			/* ****END CRITICAL SECTION */
	}

	if (aed_debug)
		printf("exited aedinprogress()\n");
}
#endif	NAED