/*
 * Device registration
 */
RAW_U32 _tk_def_dev( CONST UB *devnm, CONST T_DDEV *ddev, void *caller_gp )
{
	DevCB	*devcb;
	INT	len, evttyp;
	ER	ercd;


	len = ChkSpaceBstrR(devnm, 0);
	
	if ( len <= 0 || len > MaxRegDev ) {
		
		RAW_ASSERT(0);
	}


	/* Search whether 'devnm' device is registered */
	devcb = searchDevCB(devnm);
	if ( devcb == 0 ) {
		if ( ddev == 0 ) {
			ercd = E_NOEXS;
			goto err_ret2;
		}

		/* Get 'devcb' for new registration because it is not
		   registered */
		devcb = newDevCB(devnm);
		if ( devcb == NULL ) {
			ercd = E_LIMIT;
			goto err_ret2;
		}
	}

	if ( ddev != NULL ) {
		/* Set/update device registration information */
		devcb->ddev = *ddev;

		evttyp = TSEVT_DEVICE_REGIST;
	} else {
		if ( !isQueEmpty(&devcb->openq) ) {
			/* In use (open) */
			ercd = E_BUSY;
			goto err_ret2;
		}

		/* Device unregistration */
		delDevCB(devcb);
		evttyp = TSEVT_DEVICE_DELETE;
	}

	return DID(devcb);
}
Exemple #2
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;
}