Beispiel #1
0
/*
 * Device management cleanup function
 */
EXPORT void knl_devmgr_cleanup( void )
{
	OpnCB	*opncb;

	/* Do nothing if it is not used even once */
	if ( knl_resource_control_block.openq.next == NULL ) {
		return;
	}

	LockDM();

	/* Free suspend disable request */
	knl_DisSusCnt -= knl_resource_control_block.dissus;
	knl_resource_control_block.dissus = 0;

	/* Close all open devices */
	while ( !isQueEmpty(&(knl_resource_control_block.openq)) ) {
		opncb = RESQ_OPNCB(knl_resource_control_block.openq.next);

		/* Indicate that it is during close processing */
		opncb->resid = 0;

		UnlockDM();

		/* Device close processing */
		knl_close_device(opncb, 0);

		LockDM();
	}
	UnlockDM();

	return;
}
Beispiel #2
0
/*
 * Device close
 */
SYSCALL ER tk_cls_dev_impl( ID dd, UINT option )
{
	OpnCB	*opncb;
	ER	ercd;

	LockDM();

	ercd = knl_check_devdesc(dd, 0, &opncb);
	if ( ercd < E_OK ) {
		UnlockDM();
		goto err_ret;
	}

	opncb->resid = 0; /* Indicate that it is during close processing */

	UnlockDM();

	/* Device close processing */
	ercd = knl_close_device(opncb, option);

err_ret:
#ifdef DEBUG
	if ( ercd < E_OK ) {
		DEBUG_PRINT(("tk_cls_dev_impl ercd = %d\n", ercd));
	}
#endif
	return ercd;
}
Beispiel #3
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;
}
Beispiel #4
0
/*
 * Suspend
 */
LOCAL ER do_suspend( void )
{
	ER	ercd;

	/* Stop accepting device registration/unregistration */
	LockREG();

	/* Suspend processing of device except for disks */
	ercd = sendevt_alldevice(TDV_SUSPEND, FALSE);
#ifdef DEBUG
	if ( ercd < E_OK ) {
		DEBUG_PRINT(("2. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
	}
#endif

	/* Suspend processing of disk device */
	ercd = sendevt_alldevice(TDV_SUSPEND, TRUE);
#ifdef DEBUG
	if ( ercd < E_OK ) {
		DEBUG_PRINT(("3. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
	}
#endif

	/* Stop accepting new requests */
	LockDM();

	/*
	 * Insert code to transit to suspend state here
	 */

	/*
	 * Insert code executed on returning from suspend state
	 */


	/* Resume accepting requests */
	UnlockDM();

	/* Resume processing of disk device */
	ercd = sendevt_alldevice(TDV_RESUME, TRUE);
#ifdef DEBUG
	if ( ercd < E_OK ) {
		DEBUG_PRINT(("7. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
	}
#endif

	/* Resume processing of device except for disks */
	ercd = sendevt_alldevice(TDV_RESUME, FALSE);
#ifdef DEBUG
	if ( ercd < E_OK ) {
		DEBUG_PRINT(("8. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
	}
#endif

	/* Resume accepting device registration/unregistration */
	UnlockREG();

	return ercd;
}
Beispiel #5
0
/*
 * Suspend
 */
LOCAL ER do_suspend( void )
{
	ER	ercd;

	/* Stop accepting device registration/unregistration */
	LockREG();

	/* Processing before starting subsystem suspend */
	ercd = tk_evt_ssy(0, TSEVT_SUSPEND_BEGIN, 0, 0);
	ERCD_PRINT(("1. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));

	/* Suspend processing of device except for disks */
	ercd = sendevt_alldevice(TDV_SUSPEND, FALSE);
	ERCD_PRINT(("2. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));

	/* Suspend processing of disk device */
	ercd = sendevt_alldevice(TDV_SUSPEND, TRUE);
	ERCD_PRINT(("3. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));

	/* Stop accepting new requests */
	LockDM();

	/* Processing after completion of subsystem suspend */
	ercd = tk_evt_ssy(0, TSEVT_SUSPEND_DONE, 0, 0);
	ERCD_PRINT(("4. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));

	/* Transit to suspend state */
	ercd = tk_set_pow(TPW_DOSUSPEND);
	ERCD_PRINT(("5. do_suspend -> tk_set_pow ercd = %d\n", ercd));

	/* Return from suspend state */

	/* Processing before starting subsystem resume */
	ercd = tk_evt_ssy(0, TSEVT_RESUME_BEGIN, 0, 0);
	ERCD_PRINT(("6. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));

	/* Resume accepting requests */
	UnlockDM();

	/* Resume processing of disk device */
	ercd = sendevt_alldevice(TDV_RESUME, TRUE);
	ERCD_PRINT(("7. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));

	/* Resume processing of device except for disks */
	ercd = sendevt_alldevice(TDV_RESUME, FALSE);
	ERCD_PRINT(("8. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));

	/* Resume accepting device registration/unregistration */
	UnlockREG();

	/* Processing after completion of subsystem resume */
	ercd = tk_evt_ssy(0, TSEVT_RESUME_DONE, 0, 0);
	ERCD_PRINT(("9. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));

	return ercd;
}
Beispiel #6
0
/*
 * Device management cleanup function
 */
EXPORT void devmgr_cleanup( ID resid, INT info )
{
	ResCB	*rescb;
	OpnCB	*opncb;
	ER	ercd;

	ercd = tk_get_res(resid, DEVICE_SVC, (void**)&rescb);
	if ( ercd < E_OK ) {
		goto err_ret;
	}

	/* Do nothing if it is not used even once */
	if ( rescb->openq.next == NULL ) {
		return;
	}

	LockDM();

	/* Free suspend disable request */
	DisSusCnt -= rescb->dissus;
	rescb->dissus = 0;

	/* Close all open devices */
	while ( !isQueEmpty(&rescb->openq) ) {
		opncb = RESQ_OPNCB(rescb->openq.next);

		/* Indicate that it is during close processing */
		opncb->resid = -1;

		/* Device close processing */
		UnlockDM();
		close_device(opncb, 0);
		LockDM();
	}
	UnlockDM();

	return;

err_ret:
	DEBUG_PRINT(("devmgr_cleanup ercd = %d\n", ercd));
	return;
}
Beispiel #7
0
/*
 * Device management break function
 */
EXPORT void devmgr_break( ID tskid )
{
	ResCB	*rescb;
	OpnCB	*opncb;
	ReqCB	*reqcb;
	QUEUE	*q, *r;
	DEVREQ	*devreq = NULL;
	INT	nreq;

	/* Get resource management block */
	rescb = GetResCB(DEVICE_SVC, tskid);
	if ( rescb == NULL ) {
		return;
	}

	LockDM();

	/* Search the request if 'tskid' task is executing and request abort */
	nreq = 0;
	for ( q = rescb->openq.next; q != &rescb->openq; q = q->next ) {
		opncb = RESQ_OPNCB(q);

		if ( opncb->nwaireq > 0 ) {
			/* Multiple requests wait */
			reqcb = DEVREQ_REQCB(opncb->waireqlst);
			if ( reqcb->tskid == tskid ) {
				devreq = opncb->waireqlst;
				nreq   = opncb->nwaireq;
			}
		} else {
			/* Start request or single request wait */
			for ( r = opncb->requestq.next;
					r != &opncb->requestq; r = r->next ) {
				reqcb = (ReqCB*)r;
				if ( reqcb->tskid == tskid ) {
					devreq = &reqcb->req;
					devreq->c.abort = TRUE;
					nreq = 1;
					break;
				}
			}
		}
		if ( nreq > 0 ) {
			LockDAbort();
			break;
		}
	}
	UnlockDM();
	if ( nreq > 0 ) {
		/* Abort request: Device driver call */
		call_abortfn(opncb->devcb, tskid, devreq, nreq);
		UnlockDAbort();
	}
}
Beispiel #8
0
/*
 * Device management startup function
 */
EXPORT void knl_devmgr_startup( void )
{
	LockDM();

	/* Initialization of open device management queue */
	QueInit(&(knl_resource_control_block.openq));
	knl_resource_control_block.dissus = 0;
	
	UnlockDM();

	return;
}
Beispiel #9
0
/*
 * Get resource management information
 */
EXPORT ResCB* knl_GetResCB( void )
{
	LockDM();

	/* If the startup function is not called, initialize at this point */
	if ( knl_resource_control_block.openq.next == NULL ) {
		/* Initialization of open device management queue */
		QueInit(&(knl_resource_control_block.openq));
	}

	UnlockDM();

	return &knl_resource_control_block;
}
Beispiel #10
0
/*
 * Device close
 */
EXPORT ER _tk_cls_dev( ID dd, UINT option )
{
	OpnCB	*opncb;
	ER	ercd;

	LockDM();

	ercd = check_devdesc(dd, 0, &opncb);
	if ( ercd < E_OK ) {
		UnlockDM();
		goto err_ret;
	}

	opncb->resid = -1; /* Indicate that it is during close processing */

	UnlockDM();

	/* Device close processing */
	ercd = close_device(opncb, option);

err_ret:
	ERCD_PRINT(("_tk_cls_dev ercd = %d\n", ercd));
	return ercd;
}
Beispiel #11
0
/*
 * Get resource management information
 */
LOCAL ResCB* GetResCB( ID ssid, ID tskid )
{
	ResCB	*rescb;

	rescb = GetResBlk(ssid, tskid);
	if ( rescb == NULL ) {
		return NULL;
	}

	LockDM();

	/* If the startup function is not called, initialize at this point */
	if ( rescb->openq.next == NULL ) {
		/* Initialization of open device management queue */
		QueInit(&rescb->openq);
	}

	UnlockDM();

	return rescb;
}
Beispiel #12
0
/*
 * Device management startup function
 */
EXPORT void devmgr_startup( ID resid, INT info )
{
	ResCB	*rescb;
	ER	ercd;

	ercd = tk_get_res(resid, DEVICE_SVC, (void**)&rescb);
	if ( ercd < E_OK ) {
		goto err_ret;
	}

	LockDM();

	/* Initialization of open device management queue */
	QueInit(&rescb->openq);
	rescb->dissus = 0;

	UnlockDM();

	return;

err_ret:
	DEBUG_PRINT(("devmgr_cleanup ercd = %d\n", ercd));
	return;
}
Beispiel #13
0
/*
 * Suspend processing
 */
SYSCALL INT tk_sus_dev_impl( UINT mode )
{
	ResCB	*rescb;
	BOOL	suspend = FALSE;
	ER	ercd;

	/* Get resource management information */
	rescb = knl_GetResCB();
	if ( rescb == NULL ) {
		ercd = E_CTX;
		goto err_ret1;
	}

	LockDM();

	switch ( mode & 0xf ) {
	  case TD_SUSPEND:	/* Suspend */
		if ( knl_DisSusCnt > 0 && (mode & TD_FORCE) == 0 ) {
			ercd = E_BUSY;
			goto err_ret2;
		}
		suspend = TRUE;
		break;

	  case TD_DISSUS:	/* Disable suspend */
		if ( knl_DisSusCnt >= MAX_DISSUS ) {
			ercd = E_QOVR;
			goto err_ret2;
		}
		knl_DisSusCnt++;
		rescb->dissus++;
		break;
	  case TD_ENASUS:	/* Enable suspend */
		if ( rescb->dissus > 0 ) {
			rescb->dissus--;
			knl_DisSusCnt--;
		}
		break;

	  case TD_CHECK:	/* Get suspend disable request count */
		break;

	  default:
		ercd = E_PAR;
		goto err_ret2;
	}

	UnlockDM();

	if ( suspend ) {
		/* Suspend */
		ercd = do_suspend();
		if ( ercd < E_OK ) {
			goto err_ret1;
		}
	}

	return knl_DisSusCnt;

err_ret2:
	UnlockDM();
err_ret1:
	DEBUG_PRINT(("tk_sus_dev_impl ercd = %d\n", ercd));
	return ercd;
}
Beispiel #14
0
/*
 * Request completion wait
 */
SYSCALL ID tk_wai_dev_impl( ID dd, ID reqid, W *asize, ER *ioer, TMO tmout )
{
	WAIFN	waitfn;
	VP	exinf;
#if TA_GP
	VP	gp;
#endif
	OpnCB	*opncb;
	DevCB	*devcb;
	ReqCB	*reqcb;
	T_DEVREQ *devreq;
	INT	reqno, nreq;
	ID	tskid;
	ER	ercd;

	tskid = tk_get_tid_impl();

	LockDM();

	ercd = knl_check_devdesc(dd, 0, &opncb);
	if ( ercd < E_OK ) {
		goto err_ret2;
	}

	devcb = opncb->devcb;
	waitfn = (WAIFN)devcb->ddev.waitfn;
	exinf = devcb->ddev.exinf;
#if TA_GP
	gp = devcb->ddev.gp;
#endif

	if ( reqid == 0 ) {
		/* When waiting for completion of any of requests for 'dd' */
		if ( opncb->nwaireq > 0 || opncb->waitone > 0 ) {
			ercd = E_OBJ;
			goto err_ret2;
		}
		if ( isQueEmpty(&opncb->requestq) ) {
			ercd = E_NOEXS;
			goto err_ret2;
		}

		/* Create wait request list */
		reqcb = (ReqCB*)opncb->requestq.next;
		for ( nreq = 1;; nreq++ ) {
			reqcb->tskid = tskid;
			devreq = &reqcb->req;
			reqcb = (ReqCB*)reqcb->q.next;
			if ( reqcb == (ReqCB*)&opncb->requestq ) {
				break;
			}
			devreq->next = &reqcb->req;
		}
		devreq->next = NULL;
		devreq = &((ReqCB*)opncb->requestq.next)->req;

		opncb->waireqlst = devreq;
		opncb->nwaireq = nreq;
	} else {
		/* Wait for completion of abort request processing */
		reqcb = knl_check_reqid(reqid, opncb);
		if ( reqcb == NULL ) {
			ercd = E_ID;
			goto err_ret2;
		}
		if ( opncb->nwaireq > 0 || reqcb->tskid > 0 ) {
			ercd = E_OBJ;
			goto err_ret2;
		}

		/* Create waiting request list */
		reqcb->tskid = tskid;
		devreq = &reqcb->req;
		devreq->next = NULL;
		nreq = 1;

		opncb->waitone++;
	}

	UnlockDM();

	/* Device driver call */
	DISABLE_INTERRUPT;
	knl_ctxtsk->sysmode++;
	ENABLE_INTERRUPT;
#if TA_GP
	reqno = CallDeviceDriver(devreq, nreq, tmout, exinf, (FP)waitfn, gp);
#else
	reqno = (*waitfn)(devreq, nreq, tmout, exinf);
#endif
	DISABLE_INTERRUPT;
	knl_ctxtsk->sysmode--;
	ENABLE_INTERRUPT;

	if ( reqno <  E_OK ) {
		ercd = reqno;
	}
	if ( reqno >= nreq ) {
		ercd = E_SYS;
	}

	LockDM();

	/* Free wait processing */
	if ( reqid == 0 ) {
		opncb->nwaireq = 0;
	} else {
		opncb->waitone--;
	}

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

	/* Get processing result */
	while ( devreq != NULL ) {
		reqcb = DEVREQ_REQCB(devreq);
		if ( reqno-- == 0 ) {
			reqid = REQID(reqcb);
			*asize = devreq->asize;
			*ioer  = devreq->error;
		}
		reqcb->tskid = 0;
		devreq = devreq->next;
	}

	if ( ercd < E_OK ) {
		goto err_ret2;
	}

	/* Unregister completed request */
	knl_delReqCB(REQCB(reqid));

	UnlockDM();

	return reqid;

err_ret2:
	UnlockDM();
	DEBUG_PRINT(("tk_wai_dev_impl ercd = %d\n", ercd));
	return ercd;
}
Beispiel #15
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 #16
0
/*
 * Device open
 */
EXPORT ID _tk_opn_dev( CONST UB *devnm, UINT omode )
{
	UB	pdevnm[L_DEVNM + 1];
	INT	unitno;
	ResCB	*rescb;
	DevCB	*devcb;
	OpnCB	*opncb;
	WaitQ	waiq;
	ER	ercd;

	ercd = ChkSpaceBstrR(devnm, 0);
	if ( ercd < E_OK ) {
		goto err_ret1;
	}

	unitno = phydevnm(pdevnm, devnm);

	/* Get resource management information */
	rescb = GetResCB(DEVICE_SVC, TSK_SELF);
	if ( rescb == NULL ) {
		ercd = E_CTX;
		goto err_ret1;
	}

	LockDM();

	/* Search device to open */
	devcb = searchDevCB(pdevnm);
	if ( devcb == NULL || unitno > devcb->ddev.nsub ) {
		ercd = E_NOEXS;
		goto err_ret2;
	}

	/* Check open mode */
	ercd = chkopenmode(devcb, unitno, omode);
	if ( ercd < E_OK ) {
		goto err_ret2;
	}

	/* Get open management block */
	opncb = newOpnCB(devcb, unitno, omode, rescb);
	if ( opncb == NULL ) {
		ercd = E_LIMIT;
		goto err_ret2;
	}

	/* 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) &&
				(devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) ) {
		/* Device driver call */
		UnlockDM();
		ercd = call_openfn(devcb, DEVID(devcb, unitno), omode);
		LockDM();
		if ( ercd < E_OK ) {
			goto err_ret3;
		}
	}
	opncb->resid = tk_get_rid(TSK_SELF);
			/* Indicate that open processing is completed */

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

	return DD(opncb);

err_ret3:
	delOpnCB(opncb);
	leaveSyncWait(&devcb->syncq, &waiq);
err_ret2:
	UnlockDM();
err_ret1:
	DEBUG_PRINT(("_tk_opn_dev ercd = %d\n", ercd));
	return ercd;
}
Beispiel #17
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;
}
Beispiel #18
0
/*
 * Abort all requests
 */
LOCAL void abort_allrequest( OpnCB *opncb )
{
	ABTFN	abortfn;
	WAIFN	waitfn;
	VP	exinf;
#if TA_GP
	VP	gp;
#endif
	DevCB	*devcb;
	ReqCB	*reqcb;
	QUEUE	*q;

	/* If 'execfn' and 'waitfn' are called, execute abort request. */
	LockDM();

	devcb = opncb->devcb;
	abortfn = (ABTFN)devcb->ddev.abortfn;
	waitfn  = (WAIFN)devcb->ddev.waitfn;
	exinf   = devcb->ddev.exinf;
#if TA_GP
	gp = devcb->ddev.gp;
#endif

	opncb->abort_tskid = tk_get_tid_impl();
	opncb->abort_cnt = 0;

	if ( opncb->nwaireq > 0 ) {
		/* Multiple requests wait */
		reqcb = DEVREQ_REQCB(opncb->waireqlst);

		/* Device driver call */
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode++;
		ENABLE_INTERRUPT;
#if TA_GP
		CallDeviceDriver(reqcb->tskid, opncb->waireqlst,
					opncb->nwaireq, exinf, (FP)abortfn, gp);
#else
		(*abortfn)(reqcb->tskid, opncb->waireqlst, opncb->nwaireq,
								exinf);
#endif
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode--;
		ENABLE_INTERRUPT;

		opncb->abort_cnt++;
	} else {
		/* Start request or single request wait */
		for ( q = opncb->requestq.next; q != &opncb->requestq; q = q->next ) {
			reqcb = (ReqCB*)q;
			if ( reqcb->tskid == 0 ) {
				continue;
			}

			reqcb->req.abort = TRUE;

			/* Device driver call */
			DISABLE_INTERRUPT;
			knl_ctxtsk->sysmode++;
			ENABLE_INTERRUPT;
#if TA_GP
			CallDeviceDriver(reqcb->tskid, &reqcb->req, 1, exinf,
								(FP)abortfn, gp);
#else
			(*abortfn)(reqcb->tskid, &reqcb->req, 1, exinf);
#endif
			DISABLE_INTERRUPT;
			knl_ctxtsk->sysmode--;
			ENABLE_INTERRUPT;

			opncb->abort_cnt++;
		}
	}

	UnlockDM();

	if ( opncb->abort_cnt > 0 ) {
		/* Wait for completion of abort request processing */
		tk_wai_sem_impl(opncb->abort_semid, 1, TMO_FEVR);
	}
	opncb->abort_tskid = 0;

	/* Abort remaining requests and wait for completion */
	LockDM();
	while ( !isQueEmpty(&opncb->requestq) ) {
		reqcb = (ReqCB*)opncb->requestq.next;
		reqcb->req.abort = TRUE;

		UnlockDM();

		/* Device driver call */
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode++;
		ENABLE_INTERRUPT;
#if TA_GP
		CallDeviceDriver(&reqcb->req, 1, TMO_FEVR, exinf, (FP)waitfn, gp);
#else
		(*waitfn)(&reqcb->req, 1, TMO_FEVR, exinf);
#endif
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode--;
		ENABLE_INTERRUPT;

		LockDM();

		/* Unregister completed request */
		knl_delReqCB(reqcb);
	}
	UnlockDM();
}
Beispiel #19
0
/*
 * Device open
 */
SYSCALL ID tk_opn_dev_impl( UB *devnm, UINT omode )
{
	OPNFN	openfn;
	VP	exinf;
#if TA_GP
	VP	gp;
#endif
	UB	pdevnm[L_DEVNM + 1];
	INT	unitno;
	ResCB	*rescb;
	DevCB	*devcb;
	OpnCB	*opncb;
	ER	ercd;
	ID	semid;

	unitno = knl_phydevnm(pdevnm, devnm);

	/* Get resource management information */
	rescb = knl_GetResCB();
	if ( rescb == NULL ) {
		ercd = E_CTX;
		goto err_ret1;
	}

	LockDM();

	/* Search device to open */
	devcb = knl_searchDevCB(pdevnm);
	if ( devcb == NULL || unitno > devcb->ddev.nsub ) {
		ercd = E_NOEXS;
		goto err_ret2;
	}

	/* Check open mode */
	ercd = chkopenmode(devcb, unitno, omode);
	if ( ercd < E_OK ) {
		goto err_ret2;
	}

	openfn = (OPNFN)devcb->ddev.openfn;
	exinf = devcb->ddev.exinf;
#if TA_GP
	gp = devcb->ddev.gp;
#endif

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

	/* Get open management block */
	opncb = newOpnCB(devcb, unitno, omode, rescb);
	if ( opncb == NULL ) {
		ercd = E_LIMIT;
		goto err_ret2;
	}

	semid = tk_cre_sem_impl(&knl_pk_csem_DM);
	if ( semid < E_OK ) {
		ercd = E_SYS;
		goto err_ret2_5;
	}
	opncb->abort_semid = semid;

	UnlockDM();

	if ( openfn != NULL ) {
		/* Device driver call */
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode++;
		ENABLE_INTERRUPT;
#if TA_GP
		ercd = CallDeviceDriver(DEVID(devcb, unitno), omode, exinf, 0,
								(FP)openfn, gp);
#else
		ercd = (*openfn)(DEVID(devcb, unitno), omode, exinf);
#endif
		DISABLE_INTERRUPT;
		knl_ctxtsk->sysmode--;
		ENABLE_INTERRUPT;

		if ( ercd < E_OK ) {
			goto err_ret3;
		}
	}

	LockDM();
	opncb->resid = 1; /* Indicate that open processing is completed */
	UnlockDM();

	return DD(opncb);

err_ret3:
	LockDM();
err_ret2_5:
	knl_delOpnCB(opncb, TRUE);
err_ret2:
	UnlockDM();
err_ret1:
	DEBUG_PRINT(("tk_opn_dev_impl ercd = %d\n", ercd));
	return ercd;
}
Beispiel #20
0
/*
 * Abort all requests
 */
LOCAL void abort_allrequest( OpnCB *opncb )
{
	DevCB	*devcb;
	ReqCB	*reqcb;
	QUEUE	*q;

	/* If 'execfn' and 'waitfn' are called, execute abort request. */
	LockDM();

	devcb = opncb->devcb;
	opncb->abort_tskid = tk_get_tid();
	opncb->abort_cnt = 0;

	LockDAbort();
	UnlockDM();

	if ( opncb->nwaireq > 0 ) {
		/* Multiple requests wait */
		reqcb = DEVREQ_REQCB(opncb->waireqlst);

		/* Device driver call */
		call_abortfn(devcb, reqcb->tskid, opncb->waireqlst,
							opncb->nwaireq);
		opncb->abort_cnt++;
	} else {
		/* Start request or single request wait */
		for ( q = opncb->requestq.next;
					q != &opncb->requestq; q = q->next ) {
			reqcb = (ReqCB*)q;
			if ( reqcb->tskid == 0 ) {
				continue;
			}
			reqcb->req.c.abort = TRUE;

			/* Device driver call */
			call_abortfn(devcb, reqcb->tskid, &reqcb->req, 1);
			opncb->abort_cnt++;
		}
	}
	UnlockDAbort();

	if ( opncb->abort_cnt > 0 ) {
		/* Wait for completion of abort request processing */
		SyncWaitDM();
	}
	opncb->abort_tskid = 0;

	/* Abort remaining requests and wait for completion */
	LockDM();
	while ( !isQueEmpty(&opncb->requestq) ) {
		reqcb = (ReqCB*)opncb->requestq.next;
		reqcb->req.c.abort = TRUE;

		/* Device driver waitfn call */
		UnlockDM();
		call_waitfn(devcb, &reqcb->req, 1, TMO_FEVR);
		LockDM();

		/* Unregister completed request */
		delReqCB(reqcb);
	}
	UnlockDM();
}
Beispiel #21
0
/*
 * wait for I/O completion for a device
 */
LOCAL ID waitcomplete( ID dd, ID reqid, W *asize, ER *ioer,
					TMO_U tmout, enum ReqType syncreq )
{
	ATR	drvatr;
	OpnCB	*opncb;
	DevCB	*devcb;
	ReqCB	*reqcb;
	DEVREQ	*devreq;
	INT	reqno, nreq;
	ID	tskid;
	BOOL	abort;
	ER	ercd;

	tskid = tk_get_tid();

	LockDM();

	ercd = check_devdesc(dd, 0, &opncb);
	if ( ercd < E_OK ) {
		goto err_ret1;
	}

	/* Check whether there is a break request */
	abort = FALSE;
	ercd = check_break();
	if ( ercd < E_OK ) {
		if ( syncreq == AsyncReq ) goto err_ret1;
		abort = TRUE;
	}

	devcb = opncb->devcb;
	drvatr = devcb->ddev.drvatr;

	if ( reqid == 0 ) {
		/* When waiting for completion of any of requests for 'dd' */
		if ( opncb->nwaireq > 0 || opncb->waitone > 0
		     || opncb->syncreq > 0 ) {
			ercd = E_OBJ;
			goto err_ret1;
		}
		if ( isQueEmpty(&opncb->requestq) ) {
			ercd = E_NOEXS;
			goto err_ret1;
		}

		/* Create wait request list */
		reqcb = (ReqCB*)opncb->requestq.next;
		for ( nreq = 1;; nreq++ ) {
			reqcb->tskid = tskid;
			devreq = &reqcb->req;
			reqcb = (ReqCB*)reqcb->q.next;
			if ( reqcb == (ReqCB*)&opncb->requestq ) {
				break;
			}
			devreq->c.next = &reqcb->req;
		}
		devreq->c.next = NULL;
		devreq = &((ReqCB*)opncb->requestq.next)->req;
		opncb->waireqlst = devreq;
		opncb->nwaireq = nreq;
	} else {
		/* Wait for completion of abort request processing */
		reqcb = check_reqid(reqid, opncb);
		if ( reqcb == NULL ) {
			ercd = E_ID;
			goto err_ret1;
		}
		if ( opncb->nwaireq > 0 || reqcb->tskid > 0 ) {
			ercd = E_OBJ;
			goto err_ret1;
		}

		/* Create waiting request list */
		reqcb->tskid = tskid;
		devreq = &reqcb->req;
		devreq->c.next = NULL;
		if ( abort ) devreq->c.abort = TRUE;
		nreq = 1;
		opncb->waitone++;
	}

	/* Device driver call */
	UnlockDM();
	reqno = call_waitfn(devcb, devreq, nreq, tmout);
	LockDM();
	if ( reqno <  E_OK ) {
		ercd = reqno;
	} else if ( reqno >= nreq ) {
		ercd = E_SYS;
	}

	LockDAbort();

	/* Free wait processing */
	if ( reqid == 0 ) {
		opncb->nwaireq = 0;
	} else {
		opncb->waitone--;
	}

	/* If there is an abort completion wait task,
	   notify abort completion */
	if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) {
		SyncSignalDM(opncb->abort_tskid);
	}

	/* Get processing result */
	while ( devreq != NULL ) {
		reqcb = DEVREQ_REQCB(devreq);
		if ( reqno-- == 0 ) {
			reqid = REQID(reqcb);
			if ( (drvatr & TDA_DEV_D) == 0 ) {
				*asize = devreq->s.asize;
				*ioer  = devreq->s.error;
			} else {
				*asize = devreq->l.asize;
				*ioer  = devreq->l.error;
			}
		}
		reqcb->tskid = 0;
		devreq = devreq->c.next;
	}
	UnlockDAbort();

	if ( ercd < E_OK ) {
		goto err_ret1;
	}

	if ( syncreq == SyncReq ) {
		opncb->syncreq--;
	}

	/* Unregister completed request */
	delReqCB(REQCB(reqid));

	UnlockDM();

	return reqid;

err_ret1:
	if ( syncreq == SyncReq ) {
		opncb->syncreq--;
	}
	UnlockDM();
	DEBUG_PRINT(("waitcomplete ercd = %d\n", ercd));
	return ercd;
}
Beispiel #22
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;
}