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

📄 deviceio.c

📁 使用广泛的日本著名的开源嵌入式实时操作系统T-Kernel的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	ER	ercd;	ercd = request(dd, start, buf, size, tmout, TDC_READ);#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("_tk_rea_dev ercd = %d\n", ercd));	}#endif	return ercd;}/* * Synchronous reading from device */EXPORT ER _tk_srea_dev( ID dd, INT start, VP buf, INT size, INT *asize ){	ER	ercd, ioercd;	/* Precheck to avoid errors by 'tk_wai_dev' */	ercd = ChkSpaceRW(asize, sizeof(INT));	if ( ercd < E_OK ) {		goto err_ret;	}	ercd = _tk_rea_dev(dd, start, buf, size, TMO_FEVR);	if ( ercd < E_OK ) {		goto err_ret;	}	ercd = _tk_wai_dev(dd, ercd, asize, &ioercd, TMO_FEVR);	if ( ercd < E_OK ) {		goto err_ret;	}	return ioercd;err_ret:	DEBUG_PRINT(("_tk_srea_dev ercd = %d\n", ercd));	return ercd;}/* * Start writing to device */EXPORT ID _tk_wri_dev( ID dd, INT start, VP buf, INT size, TMO tmout ){	ER	ercd;	ercd = request(dd, start, buf, size, tmout, TDC_WRITE);#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("_tk_wri_dev ercd = %d\n", ercd));	}#endif	return ercd;}/* * Synchronous writing to device */EXPORT ER _tk_swri_dev( ID dd, INT start, VP buf, INT size, INT *asize ){	ER	ercd, ioercd;	/* Precheck to avoid errors by 'tk_wai_dev' */	ercd = ChkSpaceRW(asize, sizeof(INT));	if ( ercd < E_OK ) {		goto err_ret;	}	ercd = _tk_wri_dev(dd, start, buf, size, TMO_FEVR);	if ( ercd < E_OK ) {		goto err_ret;	}	ercd = _tk_wai_dev(dd, ercd, asize, &ioercd, TMO_FEVR);	if ( ercd < E_OK ) {		goto err_ret;	}	return ioercd;err_ret:	DEBUG_PRINT(("_tk_swri_dev ercd = %d\n", ercd));	return ercd;}/* * Request completion wait */EXPORT ID _tk_wai_dev( ID dd, ID reqid, INT *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;	ercd = ChkSpaceRW(asize, sizeof(INT));	if ( ercd < E_OK ) {		goto err_ret1;	}	ercd = ChkSpaceRW(ioer, sizeof(ER));	if ( ercd < E_OK ) {		goto err_ret1;	}	tskid = tk_get_tid();	LockDM();	/* Check whether there is a break request */	ercd = check_break();	if ( ercd < E_OK ) {		goto err_ret2;	}	ercd = 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 = 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 */#if TA_GP	reqno = CallDeviceDriver(devreq, nreq, tmout, exinf, (FP)waitfn, gp);#else	reqno = (*waitfn)(devreq, nreq, tmout, exinf);#endif	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 ) {		SyncSignalDM(opncb->abort_tskid);	}	/* 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 */	delReqCB(REQCB(reqid));	UnlockDM();	return reqid;err_ret2:	UnlockDM();err_ret1:	DEBUG_PRINT(("_tk_wai_dev ercd = %d\n", ercd));	return ercd;}/* ------------------------------------------------------------------------ *//* Suspend disable request count */LOCAL	INT	DisSusCnt;/* Maximum number of suspend disable request counts */#define MAX_DISSUS	0x7fff/* * Send driver request event to each device */LOCAL ER sendevt_alldevice( INT evttyp, BOOL disk ){	EVTFN	eventfn;	QUEUE	*q;	DevCB	*devcb;	BOOL	d;	ER	ercd = E_OK;	for ( q = UsedDevCB.next; q != &UsedDevCB; q = q->next ) {		devcb = (DevCB*)q;		d = ( (devcb->ddev.devatr & TD_DEVTYPE) == TDK_DISK )?							TRUE: FALSE;		if ( disk != d ) {			continue;		}		/* Device driver call */		eventfn = (EVTFN)devcb->ddev.eventfn;#if TA_GP		ercd = CallDeviceDriver(evttyp, NULL, devcb->ddev.exinf, 0,						(FP)eventfn, devcb->ddev.gp);#else		ercd = (*eventfn)(evttyp, NULL, devcb->ddev.exinf);#endif	}#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("sendevt_alldevice ercd = %d\n", ercd));	}#endif	return ercd;}/* * 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);#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("1. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));	}#endif	/* 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();	/* Processing after completion of subsystem suspend */	ercd = tk_evt_ssy(0, TSEVT_SUSPEND_DONE, 0, 0);#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("4. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));	}#endif	/* Transit to suspend state */	ercd = tk_set_pow(TPW_DOSUSPEND);#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("5. do_suspend -> tk_set_pow ercd = %d\n", ercd));	}#endif	/* Return from suspend state */	/* Processing before starting subsystem resume */	ercd = tk_evt_ssy(0, TSEVT_RESUME_BEGIN, 0, 0);#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("6. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));	}#endif	/* 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();	/* Processing after completion of subsystem resume */	ercd = tk_evt_ssy(0, TSEVT_RESUME_DONE, 0, 0);#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("9. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));	}#endif	return ercd;}/* * Suspend processing */EXPORT INT _tk_sus_dev( UINT mode ){	ResCB	*rescb;	BOOL	suspend = FALSE;	ER	ercd;	/* Get resource management information */	rescb = GetResCB(DEVICE_SVC, TSK_SELF);	if ( rescb == NULL ) {		ercd = E_CTX;		goto err_ret1;	}	LockDM();	switch ( mode & 0xf ) {	  case TD_SUSPEND:	/* Suspend */		if ( DisSusCnt > 0 && (mode & TD_FORCE) == 0 ) {			ercd = E_BUSY;			goto err_ret2;		}		suspend = TRUE;		break;	  case TD_DISSUS:	/* Disable suspend */		if ( DisSusCnt >= MAX_DISSUS ) {			ercd = E_QOVR;			goto err_ret2;		}		DisSusCnt++;		rescb->dissus++;		break;	  case TD_ENASUS:	/* Enable suspend */		if ( rescb->dissus > 0 ) {			rescb->dissus--;			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 DisSusCnt;err_ret2:	UnlockDM();err_ret1:	DEBUG_PRINT(("_tk_sus_dev ercd = %d\n", ercd));	return ercd;}/* ------------------------------------------------------------------------ *//* * Device driver abort function call */Inline ER call_abortfn( DevCB *devcb, ID tskid, T_DEVREQ *devreq, INT nreq ){	ABTFN	abortfn;	abortfn = (ABTFN)devcb->ddev.abortfn;#if TA_GP	return CallDeviceDriver(tskid, devreq, nreq, devcb->ddev.exinf,						(FP)abortfn, devcb->ddev.gp);#else	return (*abortfn)(tskid, devreq, nreq, devcb->ddev.exinf);#endif}/* * Device management break function */EXPORT void devmgr_break( ID tskid ){	ResCB	*rescb;	OpnCB	*opncb;	ReqCB	*reqcb;	QUEUE	*q, *r;	T_DEVREQ *devreq;	/* 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 */	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 ) {				/* Abort request: Device driver call */				call_abortfn(opncb->devcb, tskid,					opncb->waireqlst, opncb->nwaireq);				goto error_exit;			}		} 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 ) {					continue;				}				/* Abort request: Device driver call */				devreq = &reqcb->req;				devreq->abort = TRUE;				call_abortfn(opncb->devcb, tskid, devreq, 1);				goto error_exit;			}		}	}error_exit:	UnlockDM();}/* * Device management startup function */EXPORT void devmgr_startup( ID resid, INT info ){	ResCB	*rescb;	ER	ercd;	ercd = tk_get_res(resid, DEVICE_SVC, (VP*)&rescb);	if ( ercd < E_OK ) {		goto err_ret;	}	LockDM();	/* Initialization of open device management queue */	QueInit(&rescb->openq);	UnlockDM();	return;err_ret:	DEBUG_PRINT(("devmgr_cleanup ercd = %d\n", ercd));	return;}/* * 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, (VP*)&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 = 0;		UnlockDM();		/* Device close processing */		close_device(opncb, 0);		LockDM();	}	UnlockDM();	return;err_ret:	DEBUG_PRINT(("devmgr_cleanup ercd = %d\n", ercd));	return;}/* * Initialization sequence of device input/output-related */EXPORT ER initDevIO( void ){	INT	i;	ER	ercd;	i = _tk_get_cfn(SCTAG_TMAXOPNDEV, &MaxOpnDev, 1);	if ( i < 1 ) {		ercd = E_SYS;		goto err_ret;	}	i = _tk_get_cfn(SCTAG_TMAXREQDEV, &MaxReqDev, 1);	if ( i < 1 ) {		ercd = E_SYS;		goto err_ret;	}	/* Generate open management information table */	OpnCBtbl = Imalloc((UINT)MaxOpnDev * sizeof(OpnCB));	if ( OpnCBtbl == NULL ) {		ercd = E_NOMEM;		goto err_ret;	}	QueInit(&FreeOpnCB);	for ( i = 0; i < MaxOpnDev; ++i ) {		OpnCBtbl[i].resid = 0;		QueInsert(&OpnCBtbl[i].q, &FreeOpnCB);	}	/* Generate request management information table */	ReqCBtbl = Imalloc((UINT)MaxReqDev * sizeof(ReqCB));	if ( ReqCBtbl == NULL ) {		ercd = E_NOMEM;		goto err_ret;	}	QueInit(&FreeReqCB);	for ( i = 0; i < MaxReqDev; ++i ) {		ReqCBtbl[i].opncb = NULL;		QueInsert(&ReqCBtbl[i].q, &FreeReqCB);	}	return E_OK;err_ret:	DEBUG_PRINT(("initDevIO ercd = %d\n", ercd));	return ercd;}/* * Finalization sequence of device input/output-related */EXPORT ER finishDevIO( void ){	/* Delete each table */	if ( OpnCBtbl != NULL ) {		Ifree(OpnCBtbl);		OpnCBtbl = NULL;	}	if ( ReqCBtbl != NULL ) {		Ifree(ReqCBtbl);		ReqCBtbl = NULL;	}	return E_OK;}

⌨️ 快捷键说明

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