/* * 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; }
/* * 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; }