Xinu7/src/serve11/sys/ethinter.c

/* ethinter.c - ethinter */

#include <conf.h>
#include <kernel.h>
#include <proc.h>
#include <network.h>

/*------------------------------------------------------------------------
 *  ethinter - ethernet interrupt processing procedure
 *------------------------------------------------------------------------
 */
INTPROC	ethinter(etptr)
	struct	etblk	*etptr;
{
	struct	dqregs	*dqptr;
	register struct	dcmd	*dcmptr;
	short	csr;
	int	pid;
	Bool	doresch;

	dqptr = etptr->eioaddr;
	dqptr->d_csr = csr = dqptr->d_csr;	/* clear RINT, XINT */

	/* check BOTH receive and xmit completion before resched */

	doresch = FALSE;
	if (csr & DQ_RINT) {
		dcmptr = etptr->ercmd;
		if ( (dcmptr->dc_st1 & DC_LUSE) != DC_ERRU) {
			pid = etptr->etrpid;
			etptr->etrpid = BADPID;
			send(pid, OK);
		} else {	/* error, so retry operation */
			dcmptr->dc_st1 = dcmptr->dc_st2 = DC_INIT;
			dcmptr->dc_flag = DC_NUSED;
			dqptr->d_rcmd = (short) dcmptr;
			dqptr->d_rcmdh = (short) NULL;
		}
	}
	if (csr & DQ_XINT) {
		dcmptr = etptr->ewcmd;
		if ( (dcmptr->dc_st1 & DC_LUSE) != DC_ERRU) {
			if (etptr->etsetup == DC_NORM) {
				etptr->etlen = 0;
				freebuf( dcmptr->dc_buf );
				signal(etptr->etwsem);
			}
			doresch = FALSE;
		} else if (etptr->etwtry-- > 0) { /* retry on error */
			while (! (dqptr->d_csr & DQ_XLI) )
				;
			dcmptr->dc_st1 = dcmptr->dc_st2 = DC_INIT;
			dcmptr->dc_flag = DC_NUSED;
			dqptr->d_wcmd = (short) dcmptr;
			dqptr->d_wcmdh = (short) NULL;
		} else {
			if (etptr->etsetup == DC_NORM) {
				freebuf(dcmptr->dc_buf);
				signal(etptr->etwsem);
			}
			doresch = FALSE;
		}
	}
	if (doresch)
		resched();
}