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

📄 deviceio.c

📁 日本著名的的嵌入式实时操作系统T-Kernel的源码及用户手册。
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	if ( err < E_OK ) goto err_ret2;	UnlockDM();	return REQID(reqcb);err_ret2:	delReqCB(reqcb);err_ret1:	UnlockDM();	DEBUG_PRINT(("request err = %d\n", err));	return err;}/* * Start reading from device */EXPORT ID _tk_rea_dev( ID dd, INT start, VP buf, INT size, TMO tmout ){	ER	err;	err = request(dd, start, buf, size, tmout, TDC_READ);#ifdef DEBUG	if ( err < E_OK ) DEBUG_PRINT(("_tk_rea_dev err = %d\n", err));#endif	return err;}/* * Synchronous reading from device */EXPORT ER _tk_srea_dev( ID dd, INT start, VP buf, INT size, INT *asize ){	ER	err, ioerr;	/* Precheck to avoid errors by 'tk_wai_dev' */	err = ChkSpaceRW(asize, sizeof(INT));	if ( err < E_OK ) goto err_ret;	err = _tk_rea_dev(dd, start, buf, size, TMO_FEVR);	if ( err < E_OK ) goto err_ret;	err = _tk_wai_dev(dd, err, asize, &ioerr, TMO_FEVR);	if ( err < E_OK ) goto err_ret;	return ioerr;err_ret:	DEBUG_PRINT(("_tk_srea_dev err = %d\n", err));	return err;}/* * Start writing to device */EXPORT ID _tk_wri_dev( ID dd, INT start, VP buf, INT size, TMO tmout ){	ER	err;	err = request(dd, start, buf, size, tmout, TDC_WRITE);#ifdef DEBUG	if ( err < E_OK ) DEBUG_PRINT(("_tk_wri_dev err = %d\n", err));#endif	return err;}/* * Synchronous writing to device */EXPORT ER _tk_swri_dev( ID dd, INT start, VP buf, INT size, INT *asize ){	ER	err, ioerr;	/* Precheck to avoid errors by 'tk_wai_dev' */	err = ChkSpaceRW(asize, sizeof(INT));	if ( err < E_OK ) goto err_ret;	err = _tk_wri_dev(dd, start, buf, size, TMO_FEVR);	if ( err < E_OK ) goto err_ret;	err = _tk_wai_dev(dd, err, asize, &ioerr, TMO_FEVR);	if ( err < E_OK ) goto err_ret;	return ioerr;err_ret:	DEBUG_PRINT(("_tk_swri_dev err = %d\n", err));	return err;}/* * Request completion wait */EXPORT ID _tk_wai_dev( ID dd, ID reqid, INT *asize, ER *ioer, TMO tmout ){	INT	(*waitfn)( T_DEVREQ *devreq, INT nreq, TMO tmout, VP exinf );	VP	exinf;#if TA_GP	VP	gp;#endif	OpnCB	*opncb;	DevCB	*devcb;	ReqCB	*reqcb;	T_DEVREQ *devreq;	INT	reqno, nreq;	ID	tskid;	ER	err;	err = ChkSpaceRW(asize, sizeof(INT));	if ( err < E_OK ) goto err_ret1;	err = ChkSpaceRW(ioer, sizeof(ER));	if ( err < E_OK ) goto err_ret1;	tskid = tk_get_tid();	LockDM();	/* Check whether there is a break request */	err = check_break();	if ( err < E_OK ) goto err_ret2;	err = check_devdesc(dd, 0, &opncb);	if ( err < E_OK ) goto err_ret2;	devcb = opncb->devcb;	waitfn = (VP)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 )					{ err = E_OBJ; goto err_ret2; }		if ( isQueEmpty(&opncb->requestq) )					{ err = 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 ) { err = E_ID; goto err_ret2; }		if ( opncb->nwaireq > 0 || reqcb->tskid > 0 )					{ err = 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, waitfn, gp);#else	reqno = (*waitfn)(devreq, nreq, tmout, exinf);#endif	if ( reqno <  E_OK ) err = reqno;	if ( reqno >= nreq ) err = 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 ( err < E_OK ) goto err_ret2;	/* Unregister completed request */	delReqCB(REQCB(reqid));	UnlockDM();	return reqid;err_ret2:	UnlockDM();err_ret1:	DEBUG_PRINT(("_tk_wai_dev err = %d\n", err));	return err;}/* ------------------------------------------------------------------------ *//* 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 ){	INT	(*eventfn)( INT evttyp, VP evtinf, VP exinf );	QUEUE	*q;	DevCB	*devcb;	BOOL	d;	ER	err, error = 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 = (VP)devcb->ddev.eventfn;#if TA_GP		err = CallDeviceDriver(evttyp, NULL, devcb->ddev.exinf, 0,						eventfn, devcb->ddev.gp);#else		err = (*eventfn)(evttyp, NULL, devcb->ddev.exinf);#endif		if ( err < E_OK ) error = err;	}#ifdef DEBUG	if ( error < E_OK )		DEBUG_PRINT(("sendevt_alldevice err = %d\n", error));#endif	return error;}/* * Suspend */LOCAL ER do_suspend( void ){	ER	err, error = E_OK;	/* Stop accepting device registration/unregistration */	LockREG();	/* Processing before starting subsystem suspend */	err = tk_evt_ssy(0, TSEVT_SUSPEND_BEGIN, 0, 0);	if ( err < E_OK ) error = err;	/* Suspend processing of device except for disks */	err = sendevt_alldevice(TDV_SUSPEND, FALSE);	if ( err < E_OK ) error = err;	/* Suspend processing of disk device */	err = sendevt_alldevice(TDV_SUSPEND, TRUE);	if ( err < E_OK ) error = err;	/* Stop accepting new requests */	LockDM();	/* Processing after completion of subsystem suspend */	err = tk_evt_ssy(0, TSEVT_SUSPEND_DONE, 0, 0);	if ( err < E_OK ) error = err;	/* Transit to suspend state */	err = tk_set_pow(TPW_DOSUSPEND);	if ( err < E_OK ) error = err;	/* Return from suspend state */	/* Processing before starting subsystem resume */	err = tk_evt_ssy(0, TSEVT_RESUME_BEGIN, 0, 0);	if ( err < E_OK ) error = err;	/* Resume accepting requests */	UnlockDM();	/* Resume processing of disk device */	err = sendevt_alldevice(TDV_RESUME, TRUE);	if ( err < E_OK ) error = err;	/* Resume processing of device except for disks */	err = sendevt_alldevice(TDV_RESUME, FALSE);	if ( err < E_OK ) error = err;	/* Processing after completion of subsystem resume */	err = tk_evt_ssy(0, TSEVT_RESUME_DONE, 0, 0);	if ( err < E_OK ) error = err;	/* Resume accepting device registration/unregistration */	UnlockREG();#ifdef DEBUG	if ( error < E_OK ) DEBUG_PRINT(("do_suspend err = %d\n", error));#endif	return error;}/* * Suspend processing */EXPORT INT _tk_sus_dev( UINT mode ){	ResCB	*rescb;	BOOL	suspend = FALSE;	ER	err;	/* Get resource management information */	rescb = GetResCB(DEVICE_SVC, TSK_SELF);	if ( rescb == NULL ) { err = E_CTX; goto err_ret1; }	LockDM();	switch ( mode & 0xf ) {	  case TD_SUSPEND:	/* Suspend */		if ( DisSusCnt > 0 && (mode & TD_FORCE) == 0 )					{ err = E_BUSY; goto err_ret2; }		suspend = TRUE;		break;	  case TD_DISSUS:	/* Disable suspend */		if ( DisSusCnt >= MAX_DISSUS ) { err = 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:		err = E_PAR; goto err_ret2;	}	UnlockDM();	if ( suspend ) {		/* Suspend */		err = do_suspend();		if ( err < E_OK ) goto err_ret1;	}	return DisSusCnt;err_ret2:	UnlockDM();err_ret1:	DEBUG_PRINT(("_tk_sus_dev err = %d\n", err));	return err;}/* ------------------------------------------------------------------------ *//* * Device driver abort function call */Inline ER call_abortfn( DevCB *devcb, ID tskid, T_DEVREQ *devreq, INT nreq ){	ER	(*abortfn)( ID tskid, T_DEVREQ *devreq, INT nreq, VP exinf );	abortfn = (VP)devcb->ddev.abortfn;#if TA_GP	return CallDeviceDriver(tskid, devreq, nreq, devcb->ddev.exinf,						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 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 exit;			}		}	}exit:	UnlockDM();}/* * Device management startup function */EXPORT void devmgr_startup( ID resid, INT info ){	ResCB	*rescb;	ER	err;	err = tk_get_res(resid, DEVICE_SVC, (VP*)&rescb);	if ( err < E_OK ) goto err_ret;	LockDM();	/* Initialization of open device management queue */	QueInit(&rescb->openq);	UnlockDM();	return;err_ret:	DEBUG_PRINT(("devmgr_cleanup err = %d\n", err));	return;}/* * Device management cleanup function */EXPORT void devmgr_cleanup( ID resid, INT info ){	ResCB	*rescb;	OpnCB	*opncb;	ER	err;	err = tk_get_res(resid, DEVICE_SVC, (VP*)&rescb);	if ( err < 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 err = %d\n", err));	return;}/* * Initialization sequence of device input/output-related */EXPORT ER initDevIO( void ){	INT	i;	ER	err;	i = _tk_get_cfn("TMaxOpnDev", &MaxOpnDev, 1);	if ( i < 1 ) { err = E_SYS; goto err_ret; }	i = _tk_get_cfn("TMaxReqDev", &MaxReqDev, 1);	if ( i < 1 ) { err = E_SYS; goto err_ret; }	/* Generate open management information table */	OpnCBtbl = Imalloc(MaxOpnDev * sizeof(OpnCB));	if ( OpnCBtbl == NULL ) { err = 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(MaxReqDev * sizeof(ReqCB));	if ( ReqCBtbl == NULL ) { err = 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 err = %d\n", err));	return err;}/* * 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 + -