Example #1
0
/*
 * Device close processing
 */
LOCAL ER close_device( OpnCB *opncb, UINT option )
{
	ID	devid;
	DevCB	*devcb;
	INT	unitno;
	WaitQ	waiq;
	ER	ercd = E_OK;

	/* Abort all requests during processing */
	abort_allrequest(opncb);

	LockDM();

	devcb  = opncb->devcb;
	unitno = opncb->unitno;
	devid = DEVID(devcb, unitno);

	/* Multiple tasks can initiate open/close processing,
	   so ensure processing only by one task at a time. */
	if ( enterSyncWait(&devcb->syncq, &waiq) ) {
		/* Wait for synchronization for concurrent open/close */
		UnlockDM();
		SyncWaitDM();
		LockDM();
	}

	/* Is device driver call required? */
	if ( chkopen(devcb, unitno, opncb) ) {
		if ( (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) {
			goto no_drvcall;
		}
		option &= ~TD_EJECT;	/* EJECT is effective at last close */
	}
	/* Device driver call */
	UnlockDM();
	ercd = call_closefn(devcb, DEVID(devcb, unitno), option);
	LockDM();

no_drvcall:
	/* Free open management block */
	delOpnCB(opncb);

       /* Wake up task waiting for synchronization for concurrent open/close */
	leaveSyncWait(&devcb->syncq, &waiq);

	UnlockDM();

	ERCD_PRINT(("close_device ercd = %d\n", ercd));

	return ercd;
}
Example #2
0
/*
 * Device close processing
 */
EXPORT ER knl_close_device( OpnCB *opncb, UINT option )
{
	CLSFN	closefn;
	VP	exinf;
#if TA_GP
	VP	gp;
#endif
	ID	devid;
	DevCB	*devcb;
	INT	unitno;
	ER	ercd = E_OK;

	/* Abort all requests during processing */
	abort_allrequest(opncb);

	LockDM();

	devcb  = opncb->devcb;
	unitno = opncb->unitno;
	closefn = (CLSFN)devcb->ddev.closefn;
	exinf = devcb->ddev.exinf;
#if TA_GP
	gp = devcb->ddev.gp;
#endif
	devid = DEVID(devcb, unitno);

	/* Delete semaphore for completion check of abortion */
	tk_del_sem_impl(opncb->abort_semid);

	/* Free open management block */
	knl_delOpnCB(opncb, FALSE);

	/* Is device driver call required? */
	if ( knl_chkopen(devcb, unitno) ) {
		option &= ~TD_EJECT;
		if ( (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) {
			closefn = NULL;
		}
	}

	UnlockDM();

	if ( closefn != NULL ) {
		/* Device driver call */
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode++;
		ENABLE_INTERRUPT;
#if TA_GP
		ercd = CallDeviceDriver(devid, option, exinf, 0, (FP)closefn, gp);
#else
		ercd = (*closefn)(devid, option, exinf);
#endif
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode--;
		ENABLE_INTERRUPT;
	}

	LockDM();
	/* Return open management block to FreeQue */
	QueInsert(&opncb->q, &knl_FreeOpnCB);
	UnlockDM();

#ifdef DEBUG
	if ( ercd < E_OK ) {
		DEBUG_PRINT(("knl_close_device ercd = %d\n", ercd));
	}
#endif
	return ercd;
}