📄 device.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel * * Copyright (C) 2004 by Ken Sakamura. All rights reserved. * T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * * Version: 1.01.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* * device.c (T-Kernel/SM) * Device Management Function */#include "sysmgr.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;/* * Initialization of device initial setting information */LOCAL ER initIDev( void ){ T_CMBF cmbf; INT val[2]; ER err; /* Get system information */ err = _tk_get_cfn("TDEvtMbfSz", val, 2); if ( err < 2 ) val[0] = -1; if ( val[0] >= 0 ) { /* Generate message buffer for event notification */ SetOBJNAME(cmbf.exinf, "DEvt"); cmbf.mbfatr = TA_TFIFO; cmbf.bufsz = val[0]; cmbf.maxmsz = val[1]; err = tk_cre_mbf(&cmbf); if ( err < E_OK ) goto err_ret; DefaultIDev.evtmbfid = err; } else { /* Do not use message buffer for event notification */ DefaultIDev.evtmbfid = 0; } return E_OK;err_ret: DEBUG_PRINT(("initIDev err = %d\n", err)); return err;}/* * Unregister device initial setting information */LOCAL ER delIDev( void ){ ER err, error = E_OK; /* Delete message buffer for event notification */ if ( DefaultIDev.evtmbfid > 0 ) { err = tk_del_mbf(DefaultIDev.evtmbfid); if ( err < E_OK ) error = err; DefaultIDev.evtmbfid = 0; }#ifdef DEBUG if ( error < E_OK ) DEBUG_PRINT(("delIDev error = %d\n", error));#endif return error;}/* ------------------------------------------------------------------------ *//* * 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 err; /* Get system information */ err = _tk_get_cfn("TMaxRegDev", &MaxRegDev, 1); if ( err < 1 ) { err = E_SYS; goto err_ret; } num = MaxRegDev; /* Generate device registration information table */ DevCBtbl= Imalloc(num * sizeof(DevCB)); if ( DevCBtbl == NULL ) { err = 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 err = %d\n", err)); return err;}/* * 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(devcb->devnm, 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(devcb->devnm, 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 err; LockREG(); len = ChkSpaceBstrR(devnm, 0); if ( len < E_OK ) { err = len; goto err_ret1; } if ( len <= 0 || len > L_DEVNM ) { err = E_PAR; goto err_ret1; } if ( ddev != NULL ) { err = ChkSpaceR(ddev, sizeof(T_DDEV)); if ( err < E_OK ) goto err_ret1; if ( ddev->nsub < 0 || ddev->nsub > MAX_UNIT ) { err = 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 ) { err = E_PAR; goto err_ret1; } } if ( idev != NULL ) { err = ChkSpaceRW(idev, sizeof(T_IDEV)); if ( err < E_OK ) goto err_ret1; } LockDM(); /* Search whether 'devnm' device is registered */ devcb = searchDevCB(devnm); if ( devcb == NULL ) { if ( ddev == NULL ) { err = E_NOEXS; goto err_ret2; } /* Get 'devcb' for new registration because it is not registered */ devcb = newDevCB(devnm); if ( devcb == NULL ) { err = 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) */ err = 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 err = %d\n", err)); return err;}/* * Check device initial information */LOCAL ER _tk_ref_idv( T_IDEV *idev ){ ER err; err = ChkSpaceRW(idev, sizeof(T_IDEV)); if ( err < E_OK ) goto err_ret; LockDM(); *idev = DefaultIDev; UnlockDM(); return E_OK;err_ret: DEBUG_PRINT(("_tk_ref_idv err = %d\n", err)); return err;}/* ------------------------------------------------------------------------ *//* * 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(ldevnm, pdevnm); if ( unitno > 0 ) { cp = &unostr[11]; *cp = '\0'; while (*ldevnm != '\0') ++ldevnm; --unitno; do { *--cp = '0' + (unitno % 10); unitno /= 10; } while (unitno); strcat(ldevnm, 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 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -