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

📄 device.c

📁 使用广泛的日本著名的开源嵌入式实时操作系统T-Kernel的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *---------------------------------------------------------------------- *    T-Kernel * *    Copyright (C) 2004-2006 by Ken Sakamura. All rights reserved. *    T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * *    Version:   1.02.02 *    Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/9. * *---------------------------------------------------------------------- *//* *	device.c (T-Kernel/SM) *	Device Management Function */#include "sysmgr.h"#include <sys/rominfo.h>#include <sys/svc/ifdevmgr.h>/* Lock for device management exclusive control */EXPORT	FastMLock	DevMgrLock;/* Semaphore for device management synchronous control */EXPORT	ID		DevMgrSync;/* Device initial setting information */LOCAL	T_IDEV		DefaultIDev;/* Set Object Name in .exinf for DEBUG */#define OBJNAME_DMMBF	"DEvt"		/* Event notification mbf */#define OBJNAME_DMSEM	"DMSy"		/* semaphore of synchronous control */#define OBJNAME_DMLOCK	"DMLk"		/* Multi-lock for Dev.Mgr. *//* * Initialization of device initial setting information */LOCAL ER initIDev( void ){	T_CMBF	cmbf;	INT	val[2];	ER	ercd;	/* Get system information */	ercd = _tk_get_cfn(SCTAG_TDEVTMBFSZ, val, 2);	if ( ercd < 2 ) {		val[0] = -1;	}	if ( val[0] >= 0 ) {		/* Generate message buffer for event notification */		SetOBJNAME(cmbf.exinf, OBJNAME_DMMBF);		cmbf.mbfatr = TA_TFIFO;		cmbf.bufsz  = val[0];		cmbf.maxmsz = val[1];		ercd = tk_cre_mbf(&cmbf);		if ( ercd < E_OK ) {			goto err_ret;		}		DefaultIDev.evtmbfid = ercd;	} else {		/* Do not use message buffer for event notification */		DefaultIDev.evtmbfid = 0;	}	return E_OK;err_ret:	DEBUG_PRINT(("initIDev ercd = %d\n", ercd));	return ercd;}/* * Unregister device initial setting information */LOCAL ER delIDev( void ){	ER	ercd = E_OK;	/* Delete message buffer for event notification */	if ( DefaultIDev.evtmbfid > 0 ) {		ercd = tk_del_mbf(DefaultIDev.evtmbfid);		DefaultIDev.evtmbfid = 0;	}#ifdef DEBUG	if ( ercd < E_OK ) {		DEBUG_PRINT(("delIDev ercd = %d\n", ercd));	}#endif	return ercd;}/* ------------------------------------------------------------------------ *//* *	Device registration management */EXPORT	DevCB		*DevCBtbl;	/* Device registration information					   table */EXPORT	QUEUE		UsedDevCB;	/* In-use queue */LOCAL	QUEUE		FreeDevCB;	/* Unused queue */LOCAL	INT		MaxRegDev;	/* Maximum number of device					   registrations */#define MAX_UNIT	255		/* Maximum number of subunits *//* * Verify validity of device ID */Inline ER check_devid( ID devid ){	devid >>= 8;	if ( devid < 1 || devid > MaxRegDev ) {		return E_ID;	}	return E_OK;}/* * Initialization of device registration information table */LOCAL ER initDevCB( void ){	DevCB	*devcb;	INT	num;	ER	ercd;	/* Get system information */	ercd = _tk_get_cfn(SCTAG_TMAXREGDEV, &MaxRegDev, 1);	if ( ercd < 1 ) {		ercd = E_SYS;		goto err_ret;	}	num = MaxRegDev;	/* Generate device registration information table */	DevCBtbl = Imalloc((UINT)num * sizeof(DevCB));	if ( DevCBtbl == NULL ) {		ercd = E_NOMEM;		goto err_ret;	}	QueInit(&UsedDevCB);	QueInit(&FreeDevCB);	devcb = DevCBtbl;	while ( num-- > 0 ) {		QueInsert(&devcb->q, &FreeDevCB);		devcb->devnm[0] = '\0';		devcb++;	}	return E_OK;err_ret:	DEBUG_PRINT(("initDevCB ercd = %d\n", ercd));	return ercd;}/* * Search registration device */EXPORT DevCB* searchDevCB( UB *devnm ){	QUEUE	*q;	DevCB	*devcb;	for ( q = UsedDevCB.next; q != &UsedDevCB; q = q->next ) {		devcb = (DevCB*)q;		if ( devcb->devnm[0] == devnm[0] && strcmp((char*)devcb->devnm, (char*)devnm) == 0 ) {			return devcb; /* Found */		}	}	return NULL;}/* * Get DevCB for new registration */LOCAL DevCB* newDevCB( UB *devnm ){	DevCB	*devcb;	devcb = (DevCB*)QueRemoveNext(&FreeDevCB);	if ( devcb == NULL ) {		return NULL; /* No space */	}	strncpy((char*)devcb->devnm, (char*)devnm, L_DEVNM+1);	QueInit(&devcb->openq);	QueInsert(&devcb->q, &UsedDevCB);	return devcb;}/* * Free DevCB */LOCAL void delDevCB( DevCB *devcb ){	QueRemove(&devcb->q);	QueInsert(&devcb->q, &FreeDevCB);	devcb->devnm[0] = '\0';}/* * Device registration */LOCAL ID _tk_def_dev( UB *devnm, T_DDEV *ddev, T_IDEV *idev, VP caller_gp ){	DevCB	*devcb;	INT	len, evttyp;	ER	ercd;	LockREG();	len = ChkSpaceBstrR(devnm, 0);	if ( len < E_OK ) {		ercd = len;		goto err_ret1;	}	if ( len <= 0 || len > L_DEVNM ) {		ercd = E_PAR;		goto err_ret1;	}	if ( ddev != NULL ) {		ercd = ChkSpaceR(ddev, sizeof(T_DDEV));		if ( ercd < E_OK ) {			goto err_ret1;		}		if ( ddev->nsub < 0 || ddev->nsub > MAX_UNIT ) {			ercd = E_PAR;			goto err_ret1;		}		/* Make sure that the length of the logical device name		   does not exceed the character limit */		if ( ddev->nsub > 0   ) {			++len;		}		if ( ddev->nsub > 10  ) {			++len;		}		if ( ddev->nsub > 100 ) {			++len;		}		if ( len > L_DEVNM ) {			ercd = E_PAR;			goto err_ret1;		}	}	if ( idev != NULL ) {		ercd = ChkSpaceRW(idev, sizeof(T_IDEV));		if ( ercd < E_OK ) {			goto err_ret1;		}	}	LockDM();	/* Search whether 'devnm' device is registered */	devcb = searchDevCB(devnm);	if ( devcb == NULL ) {		if ( ddev == NULL ) {			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;#if TA_GP		if ( (ddev->drvatr & TA_GP) == 0 ) {			/* Apply caller 'gp' if TA_GP is not specified */			devcb->ddev.gp = caller_gp;		}#endif		if ( idev != NULL ) {			/* Device initial setting information */			*idev = DefaultIDev;		}		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;	}	UnlockDM();	UnlockREG();	/* Device registration/unregistration notification */	tk_evt_ssy(0, evttyp, 0, DID(devcb));	return DID(devcb);err_ret2:	UnlockDM();err_ret1:	UnlockREG();	DEBUG_PRINT(("_tk_def_dev ercd = %d\n", ercd));	return ercd;}/* * Check device initial information */LOCAL ER _tk_ref_idv( T_IDEV *idev ){	ER	ercd;	ercd = ChkSpaceRW(idev, sizeof(T_IDEV));	if ( ercd < E_OK ) {		goto err_ret;	}	LockDM();	*idev = DefaultIDev;	UnlockDM();	return E_OK;err_ret:	DEBUG_PRINT(("_tk_ref_idv ercd = %d\n", ercd));	return ercd;}/* ------------------------------------------------------------------------ *//* * Get logical device name *	Get the logical device name from *	the physical device name (pdevnm) and the subunit number (unitno). */LOCAL void logdevnm( UB *ldevnm, UB *pdevnm, INT unitno ){	UB	unostr[12], *cp;	strcpy((char*)ldevnm, (char*)pdevnm);	if ( unitno > 0 ) {		cp = &unostr[11];		*cp = '\0';		while (*ldevnm != '\0') {			++ldevnm;		}		--unitno;		do {			*(--cp) = (UB)('0' + (unitno % 10));			unitno /= 10;		} while (unitno);		strcat((char*)ldevnm, (char*)cp);	}}/* * Get physical device name *	Get the subunit number (return value)  *	from the logical device name (ldevnm) and the physical *	device name (pdevnm). */EXPORT INT phydevnm( UB *pdevnm, UB *ldevnm ){	UB	c;	INT	unitno;	while ( (c = *ldevnm) != '\0' ) {		if ( c >= '0' && c <= '9' ) {			break;		}		*pdevnm++ = c;		ldevnm++;	}	*pdevnm = '\0';	unitno = 0;	if (c != '\0') {		while ( (c = *ldevnm) != '\0' ) {			unitno = unitno * 10 + (c - '0');			ldevnm++;		}		++unitno;	}	return unitno;}/* * Get device name */LOCAL ID _tk_get_dev( ID devid, UB *devnm ){	DevCB	*devcb;	ER	ercd;	ercd = ChkSpaceRW(devnm, (L_DEVNM + 1) * sizeof(UB));

⌨️ 快捷键说明

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