Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/*
 * 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;
}