⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deviceio.c

📁 uT Kernel os source code for AT91
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *---------------------------------------------------------------------- *    micro T-Kernel * *    Copyright (C) 2006-2007 by Ken Sakamura. All rights reserved. *    micro T-Kernel is distributed under the micro T-License. *---------------------------------------------------------------------- * *    Version:   1.00.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2007/03/26. * *---------------------------------------------------------------------- *//* *	deviceio.c *	Device Management Function: Input/Output *//** [BEGIN Common Definitions] */#include "kernel.h"#include "sysmgr.h"#include "device.h"/** [END Common Definitions] */#if CFN_MAX_REGDEV#ifdef USE_FUNC_OPNCBTBLNoinit(EXPORT OpnCB	knl_OpnCBtbl[CFN_MAX_OPNDEV]);	/* Open management information table */Noinit(EXPORT QUEUE	knl_FreeOpnCB);	/* Unused queue */#endif /* USE_FUNC_OPNCBTBL */#ifdef USE_FUNC_REQCBTBLNoinit(EXPORT ReqCB	knl_ReqCBtbl[CFN_MAX_REQDEV]);	/* Request management information table */Noinit(EXPORT QUEUE	knl_FreeReqCB);	/* Unused queue */#endif /* USE_FUNC_REQCBTBL */#ifdef USE_FUNC_RESOURCE_CONTROL_BLOCKNoinit(EXPORT ResCB knl_resource_control_block);#endif /* USE_FUNC_RESOURCE_CONTROL_BLOCK */#ifdef USE_FUNC_GETRESCB/* * 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;}#endif /* USE_FUNC_GETRESCB */#ifdef USE_FUNC_CHECK_DEVDESC/* * Verify validity of device descriptor */EXPORT ER knl_check_devdesc( ID dd, UINT mode, OpnCB **p_opncb ){	OpnCB	*opncb;	if ( dd < 1 || dd > CFN_MAX_OPNDEV ) {		return E_ID;	}	opncb = OPNCB(dd);	if ( opncb->resid == 0 ) {		return E_ID;	}	if ( mode != 0 ) {		if ( (opncb->omode & mode) == 0 ) {			return E_OACV;		}	}	*p_opncb = opncb;	return E_OK;}#endif /* USE_FUNC_CHECK_DEVDESC */#ifdef USE_FUNC_DELOPNCB/* * Free open management block */EXPORT void knl_delOpnCB( OpnCB *opncb, BOOL free ){	QueRemove(&opncb->q);	QueRemove(&opncb->resq);	if ( free ) {		QueInsert(&opncb->q, &knl_FreeOpnCB);	}	opncb->resid = 0;}#endif /* USE_FUNC_DELOPNCB */#ifdef USE_FUNC_DELREQCB/* * Free request management block */EXPORT void knl_delReqCB( ReqCB *reqcb ){	QueRemove(&reqcb->q);	QueInsert(&reqcb->q, &knl_FreeReqCB);	reqcb->opncb = NULL;}#endif /* USE_FUNC_DELREQCB *//* ------------------------------------------------------------------------ */#ifdef USE_FUNC_CHKOPEN/* * TRUE if specified device is open. */EXPORT BOOL knl_chkopen( DevCB *devcb, INT unitno ){	QUEUE	*q;	for ( q = devcb->openq.next; q != &devcb->openq; q = q->next ) {		if ( ((OpnCB*)q)->unitno == unitno ) {			return TRUE;		}	}	return FALSE;}#endif /* USE_FUNC_CHKOPEN */#ifdef USE_FUNC_TK_OPN_DEVLOCAL T_CSEM knl_pk_csem_DM = {	NULL,	TA_TFIFO | TA_FIRST,	0,	1,};/* * Get open management block */LOCAL OpnCB* newOpnCB( DevCB *devcb, INT unitno, UINT omode, ResCB *rescb ){	OpnCB	*opncb;	/* Get space in open management block */	opncb = (OpnCB*)QueRemoveNext(&knl_FreeOpnCB);	if ( opncb == NULL ) {		return NULL; /* No space */	}	/* Register as open device */	QueInsert(&opncb->q, &devcb->openq);	QueInsert(&opncb->resq, &rescb->openq);	opncb->devcb  = devcb;	opncb->unitno = unitno;	opncb->omode  = omode;	QueInit(&opncb->requestq);	opncb->waitone = 0;	opncb->nwaireq = 0;	opncb->abort_tskid = 0;	opncb->resid  = 0; /* Indicate that open processing is not completed */	return opncb;}/* * Check open mode */LOCAL ER chkopenmode( DevCB *devcb, INT unitno, UINT omode ){	QUEUE	*q;	OpnCB	*opncb;	INT	read, write, rexcl, wexcl;	if ( (omode & TD_UPDATE) == 0 ) {		return E_PAR;	}	/* Check current open state */	read = write = rexcl = wexcl = 0;	for ( q = devcb->openq.next; q != &devcb->openq; q = q->next ) {		opncb = (OpnCB*)q;		if ( unitno == 0 || opncb->unitno == 0 || opncb->unitno == unitno ) {			if ( (opncb->omode & TD_READ)  != 0 ) {				read++;			}			if ( (opncb->omode & TD_WRITE) != 0 ) {				write++;			}			if ( (opncb->omode & (TD_EXCL|TD_REXCL)) != 0) {				rexcl++;			}			if ( (opncb->omode & (TD_EXCL|TD_WEXCL)) != 0) {				wexcl++;			}		}	}	/* Is it able to open? */	if ( (omode & (TD_EXCL|TD_REXCL)) != 0 && read  > 0 ) {		return E_BUSY;	}	if ( (omode & (TD_EXCL|TD_WEXCL)) != 0 && write > 0 ) {		return E_BUSY;	}	if ( (omode & TD_READ)  != 0 && rexcl > 0 ) {		return E_BUSY;	}	if ( (omode & TD_WRITE) != 0 && wexcl > 0 ) {		return E_BUSY;	}	return E_OK;}/* * 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;}#endif /* USE_FUNC_TK_OPN_DEV */#ifdef USE_FUNC_CLOSE_DEVICE/* * 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();}/* * 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;}#endif /* USE_FUNC_CLOSE_DEVICE */#ifdef USE_FUNC_TK_CLS_DEV/* * 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;}#endif /* USE_FUNC_TK_CLS_DEV *//* ------------------------------------------------------------------------ */#ifdef USE_FUNC_REQUEST/* * Get request management block */LOCAL ReqCB* newReqCB( OpnCB *opncb ){	ReqCB	*reqcb;	/* Get space in request management block */	reqcb = (ReqCB*)QueRemoveNext(&knl_FreeReqCB);	if ( reqcb == NULL ) {		return NULL; /* No space */	}	/* Register as requested open device */	QueInsert(&reqcb->q, &opncb->requestq);	reqcb->opncb = opncb;	return reqcb;}/* * 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;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -