/* * Request for starting input/output to device */ EXPORT ID knl_request( ID dd, W start, VP buf, W size, TMO tmout, INT cmd ) { EXCFN execfn; VP exinf; #if TA_GP VP gp; #endif OpnCB *opncb; DevCB *devcb; ReqCB *reqcb; UINT m; ER ercd; LockDM(); if ( start <= -0x00010000 && start >= -0x7fffffff ) { m = 0; /* Ignore open mode */ } else { m = ( cmd == TDC_READ )? TD_READ: TD_WRITE; } ercd = knl_check_devdesc(dd, m, &opncb); if ( ercd < E_OK ) { goto err_ret1; } devcb = opncb->devcb; execfn = (EXCFN)devcb->ddev.execfn; exinf = devcb->ddev.exinf; #if TA_GP gp = devcb->ddev.gp; #endif /* Get request management block */ reqcb = newReqCB(opncb); if ( reqcb == NULL ) { ercd = E_LIMIT; goto err_ret1; } /* Set request packet */ reqcb->req.next = NULL; reqcb->req.exinf = NULL; reqcb->req.devid = DEVID(devcb, opncb->unitno); reqcb->req.cmd = cmd; reqcb->req.abort = FALSE; reqcb->req.start = start; reqcb->req.size = size; reqcb->req.buf = buf; reqcb->req.asize = 0; reqcb->req.error = 0; /* Indicate that it is during processing */ reqcb->tskid = tk_get_tid_impl(); UnlockDM(); /* Device driver call */ DISABLE_INTERRUPT; knl_ctxtsk->sysmode++; ENABLE_INTERRUPT; #if TA_GP ercd = CallDeviceDriver(&reqcb->req, tmout, exinf, 0, (FP)execfn, gp); #else ercd = (*execfn)(&reqcb->req, tmout, exinf); #endif DISABLE_INTERRUPT; knl_ctxtsk->sysmode--; ENABLE_INTERRUPT; LockDM(); /* Indicate that it is not during processing */ reqcb->tskid = 0; /* If there is an abort completion wait task, notify abort completion */ if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) { tk_sig_sem_impl(opncb->abort_semid, 1); } if ( ercd < E_OK ) { goto err_ret2; } UnlockDM(); return REQID(reqcb); err_ret2: knl_delReqCB(reqcb); err_ret1: UnlockDM(); DEBUG_PRINT(("knl_request ercd = %d\n", ercd)); return ercd; }
/* * Request for starting input/output to device */ LOCAL ID request( ID dd, D start, void *buf, INT size, TMO_U tmout, INT cmd, enum ReqType syncreq ) { ATR drvatr; OpnCB *opncb; DevCB *devcb; ReqCB *reqcb; UINT m; ER ercd; LockDM(); /* Check whether there is a break request */ ercd = check_break(); if ( ercd < E_OK ) { goto err_ret1; } m = ( cmd == TDC_READ )? TD_READ: TD_WRITE; ercd = check_devdesc(dd, m, &opncb); if ( ercd < E_OK ) { goto err_ret1; } if ( syncreq == SyncReq ) { /* synchronous I/O is prohibited while there are pending I/O requests for completion */ if ( opncb->nwaireq > 0 ) { ercd = E_OBJ; goto err_ret1; } opncb->syncreq++; } devcb = opncb->devcb; drvatr = devcb->ddev.drvatr; /* check the range of parameter value */ if ( (drvatr & TDA_DEV_D) == 0 ) { if ( start > 0x7fffffff || start < (-0x7fffffff-1) ) { ercd = E_PAR; goto err_ret2; } } /* Get request management block */ reqcb = newReqCB(opncb); if ( reqcb == NULL ) { ercd = E_LIMIT; goto err_ret2; } /* Set request packet */ MEMSET(&reqcb->req, 0, sizeof(DEVREQ)); reqcb->req.c.devid = DEVID(devcb, opncb->unitno); reqcb->req.c.cmd = cmd; if ( (opncb->omode & TD_NOLOCK) != 0 ) { reqcb->req.c.nolock = TRUE; } if ( (drvatr & TDA_DEV_D) == 0 ) { reqcb->req.s.start = start; reqcb->req.s.size = size; reqcb->req.s.buf = buf; } else { reqcb->req.l.start_d = start; reqcb->req.l.size = size; reqcb->req.l.buf = buf; } ercd = tk_get_tsp(TSK_SELF, &reqcb->req.c.tskspc); if ( ercd < E_OK ) { goto err_ret3; } /* Indicate that it is during processing */ reqcb->tskid = tk_get_tid(); /* Device driver call */ UnlockDM(); ercd = call_execfn(devcb, &reqcb->req, tmout); LockDM(); LockDAbort(); /* Indicate that it is not during processing */ reqcb->tskid = 0; /* If there is an abort completion wait task, notify abort completion */ if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) { SyncSignalDM(opncb->abort_tskid); } UnlockDAbort(); if ( ercd < E_OK ) { goto err_ret3; } UnlockDM(); return REQID(reqcb); err_ret3: delReqCB(reqcb); err_ret2: if ( syncreq == SyncReq ) { opncb->syncreq--; } err_ret1: UnlockDM(); DEBUG_PRINT(("request ercd = %d\n", ercd)); return ercd; }