📄 devinfo.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel / Standard Extension * * Copyright (C) 2006 by Ken Sakamura. All rights reserved. * T-Kernel / Standard Extension is distributed * under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * * Version: 1.00.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* * devinfo.c (device) * * Device information */#include "devmgr.h"/* * Access mode management table * It is a simple array of ACCENT. Arrange devid in ascending order. */typedef struct { ID devid; /* Device ID of physical device */ H nsub; /* Subunit count (0= No subunit) */ UH mode[1]; /* [0]:Physical device. [1 to nsub]: Logical device */} ACCENT;LOCAL ACCENT *AccTbl; /* Access mode management table */LOCAL W AccTblSz; /* Valid size of AccTbl (Bytes) */#define ACCTBL_BLKSZ 256 /* Extension steps of AccTbl (Bytes) */Inline UW ACCENT_SZ( W nsub );Inline UW ACCTBL_SZ( UW s );LOCAL ER resizeAccTbl( W diff );LOCAL ACCENT* searchAccEnt( ID devid );LOCAL ER registAccEnt( ID devid, W nsub );LOCAL UW GetAccessMode( ID devid );#define TSD_RAE_MOD_0X0FFF 0x0fffU#define TSD_GAM_MOD_0X0FFF 0x0fffU#define TSD_TCD_MSK_0X0FFF 0x0fffU#define TSD_UAM_NSB_M1 (-1)#define TSD_ACS_VAL_3 3#define TSD_ACS_VAL_4 4#define TSD_CAM_MSK_0XF 0xfU#define TSD_CAM_SFT_4 4#define TSD_CAM_SFT_8 8Inline UW ACCENT_SZ( W nsub ){ /* To avoid misalignment access, it is defined as 4 bytes steps. */ return (((offsetof(ACCENT, mode[nsub + 1]) + (UW)TSD_ACS_VAL_3) / (UW)TSD_ACS_VAL_4) * (UW)TSD_ACS_VAL_4);}Inline UW ACCTBL_SZ( UW s ){ return ((s + (UW)(ACCTBL_BLKSZ - 1)) / (UW)ACCTBL_BLKSZ) * (UW)ACCTBL_BLKSZ;}/* * Change the size of the access mode management table. */LOCAL ER resizeAccTbl( W diff ){ W cursz, newsz; ACCENT *p; cursz = (W)ACCTBL_SZ((UW)AccTblSz); newsz = (W)ACCTBL_SZ((UW)(AccTblSz + diff)); if ( cursz != newsz ) { p = (ACCENT *)Vrealloc(AccTbl, (size_t)newsz); if ( (p == NULL) && (newsz > 0) ) { goto err_ret; } AccTbl = p; } return E_OK;err_ret: DEBUG_PRINT(("resizeAccTbl err = %d\n", E_NOMEM)); return E_NOMEM;}/* * Retrieve the access mode entry. */LOCAL ACCENT* searchAccEnt( ID devid ){ ACCENT *ent, *ep; UW sz; ep = (ACCENT*)((B*)AccTbl + AccTblSz); sz = (UW)0; for ( ent = AccTbl; ent < ep; ent = (ACCENT*)((B*)ent + sz) ) { if ( devid < ent->devid ) { break; } sz = ACCENT_SZ(ent->nsub); } if ( sz == (UW)0 ) { return NULL; } ent = (ACCENT*)((B*)ent - sz); if ( devid > (ent->devid + ent->nsub) ) { return NULL; } return ent;}/* * Register/Change/Deregister the access mode entry. * nsub >= 0 Register (Registered subunit count) * nsub < 0 Deregister */LOCAL ER registAccEnt( ID devid, W nsub ){ ACCENT *ent, *ep; W sz, i; ER err; /* Current registration information */ ent = searchAccEnt(devid); /* The size of the change of the access mode management table. */ sz = ( nsub < 0 )? 0: (W)ACCENT_SZ(nsub); /* New size */ sz -= ( ent == NULL )? 0: (W)ACCENT_SZ(ent->nsub); /* Current size */ /* Retrieve the registered position. */ ep = (ACCENT*)((B*)AccTbl + AccTblSz); for ( ent = AccTbl; ent < ep; ent = (ACCENT*)((B*)ent + ACCENT_SZ(ent->nsub)) ) { if ( ent->devid > devid ) { break; } } if ( sz != 0 ) { i = (B*)ent - (B*)AccTbl; if ( sz > 0 ) { err = resizeAccTbl(sz); if ( err < E_OK ) { goto err_ret; } } if ( ent != NULL ) { /* Move the size of the change. */ ent = (ACCENT*)((B*)AccTbl + i); memmove((B*)ent + sz, ent, (size_t)(AccTblSz - i)); } if ( sz < 0 ) { err = resizeAccTbl(sz); if ( err < E_OK ) { goto err_ret; } } AccTblSz += sz; ent = (ACCENT*)((B*)AccTbl + i); } if ( nsub < 0 ) { /* In the case of deletion, here is the end. */ return E_OK; } /* Update the registration information. */ ent = (ACCENT*)((B*)ent + sz - ACCENT_SZ(nsub)); if ( sz > 0 ) { i = ( sz == (W)ACCENT_SZ(nsub) )? 0: /* New */ (ent->nsub + 1); /* Addition */ while ( i <= nsub ) { ent->mode[i++] = (UH)TSD_RAE_MOD_0X0FFF; } } ent->devid = devid; ent->nsub = (H)nsub; return E_OK;err_ret: DEBUG_PRINT(("registAccEnt err = %d\n", err)); return err;}/* * Obtain the access mode. */LOCAL UW GetAccessMode( ID devid ){ ACCENT *ent; W unitno; UW mode = TSD_GAM_MOD_0X0FFF; LockDM(); /* Retrieve the access mode information. */ ent = searchAccEnt(devid); if ( ent == NULL ) { goto err_ret; } unitno = devid - ent->devid; mode = ent->mode[unitno];err_ret: UnlockDM(); return mode;}/* * Check the access mode. */EXPORT ER CheckAccessMode( UB *devnm, W omode ){ ID devid; UW mode, level; ER err; devid = tk_ref_dev(devnm, NULL); if ( devid < E_OK ) { err = ERtoERR(devid); goto err_ret; } /* Obtain the access mode. */ mode = GetAccessMode(devid); /* Obtain the user level. */ level = (UW)GetUserLevel(TSK_SELF); if ( ((UW)omode & D_READ) != 0 ) { if ( ((mode >> TSD_CAM_SFT_8) & TSD_CAM_MSK_0XF) < level ) { return E_OACV; } } if ( ((UW)omode & D_WRITE) != 0 ) { if ( ((mode >> TSD_CAM_SFT_4) & TSD_CAM_MSK_0XF) < level ) { return E_OACV; } } return E_OK;err_ret: DEBUG_PRINT(("CheckAccessMode err = %d\n", err)); return err;}/* * Check the access mode. (for T-Kernel I/F SystemCall) */EXPORT ER tkCheckAccessMode( UB *devnm, UINT omode ){ ID devid; UW mode, level; ER err; devid = tk_ref_dev(devnm, NULL); if ( devid < E_OK ) { err = devid; goto err_ret; } /* Obtain the access mode. */ mode = (UW)GetAccessMode(devid); /* Obtain the user level. */ level = (UW)GetUserLevel(TSK_SELF); if ( (omode & TD_READ) != 0 ) { if ( ((mode >> TSD_CAM_SFT_8) & TSD_CAM_MSK_0XF) < level ) { return E_OACV; } } if ( (omode & TD_WRITE) != 0 ) { if ( ((mode >> TSD_CAM_SFT_4) & TSD_CAM_MSK_0XF) < level ) { return E_OACV; } } return E_OK;err_ret: DEBUG_PRINT(("tkCheckAccessMode err = %d\n", err)); return err;}/* * Update the access mode by device registration/deregistration. * reg = TRUE Registration/Change * FALSE Deregistration */EXPORT ER UpdateAccessMode( ID devid, BOOL reg ){ UB devnm[L_DEVNM + 1]; T_RDEV rdev; ER err; if ( reg != 0 ) { /* Obtain the registration information. */ err = tk_get_dev(devid, devnm); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret1; } err = tk_ref_dev(devnm, &rdev); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret1; } } else { rdev.nsub = TSD_UAM_NSB_M1; } LockDM(); /* Registration/Change/Deregistration */ err = registAccEnt(devid, rdev.nsub); if ( err < E_OK ) { goto err_ret2; } UnlockDM(); return E_OK;err_ret2: UnlockDM();err_ret1: DEBUG_PRINT(("UpdateAccessMode err = %d\n", err)); return err;}/* * Change the device access mode. */EXPORT ER _tkse_chg_dmd( TC *dev, W mode ){ UB devnm[L_DEVNM + 1]; ID devid; ACCENT *ent; W unitno; ER err; err = CheckStrSpaceR(dev, 0); if ( err < E_OK ) { goto err_ret1; } if ( ((UW)mode & ~TSD_TCD_MSK_0X0FFF) != 0 ) { err = E_PAR; goto err_ret1; } /* Check the user level. */ if ( GetUserLevel(TSK_SELF) != 0 ) { err = E_OACV; goto err_ret1; } /* Convert the device name. */ err = ubdevnm(devnm, dev); if ( err < E_OK ) { goto err_ret1; } devid = tk_ref_dev(devnm, NULL); if ( devid < E_OK ) { err = ERtoERR(devid); goto err_ret1; } LockDM(); /* Retrieve the access mode information. */ ent = searchAccEnt(devid); if ( ent == NULL ) { err = E_SYS; goto err_ret2; } unitno = devid - ent->devid; /* Set the access mode. */ ent->mode[unitno] = (UH)mode; UnlockDM(); return E_OK;err_ret2: UnlockDM();err_ret1: DEBUG_PRINT(("_tkse_chg_dmd err = %d\n", err)); return err;}/* ------------------------------------------------------------------------ *//* * Obtain the device management information. */EXPORT ER _tkse_dev_sts( TC *dev, DEV_STATE *buf ){ UB devnm[L_DEVNM + 1]; T_RDEV rdev; ID devid; ER err; err = CheckSpaceRW(buf, sizeof(DEV_STATE)); if ( err < E_OK ) { goto err_ret; } err = CheckStrSpaceR(dev, 0); if ( err < E_OK ) { goto err_ret; } /* Convert the device name. */ err = ubdevnm(devnm, dev); if ( err < E_OK ) { goto err_ret; } /* Obtain the device information. */ devid = tk_ref_dev(devnm, &rdev); if ( devid < E_OK ) { err = ERtoERR(devid); goto err_ret; } buf->attr = rdev.devatr; buf->blksz = rdev.blksz; buf->wprt = ( (rdev.devatr & TD_PROTECT) != 0 )? 1: 0; buf->mode = GetAccessMode(devid); return E_OK;err_ret: DEBUG_PRINT(("_tkse_dev_sts err = %d\n", err)); return err;}/* * Obtain the device name. */EXPORT WER _tkse_get_dev2( TC *dev, W num ){ UB devnm[L_DEVNM + 1]; T_RDEV rdev; ER err; err = CheckSpaceRW(dev, (L_DEVNM + 1) * sizeof(TC)); if ( err < E_OK ) { goto err_ret; } /* Obtain the device name. */ err = tk_get_dev(num, devnm); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret; } /* Obtain the device information. */ err = tk_ref_dev(devnm, &rdev); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret; } /* Convert the device name. */ tcdevnm(dev, devnm, L_DEVNM + 1); return rdev.nsub;err_ret: DEBUG_PRINT(("_tkse_get_dev err = %d\n", err)); return err;}/* * Obtain the registered device. */EXPORT WER _tkse_lst_dev2( DEV_INFO *dev, W ndev ){ T_LDEV *ldev = NULL; W total, i; ER err; if ( ndev < 0 ) { err = E_PAR; goto err_ret1; } if ( dev == NULL ) { ndev = 0; } if ( ndev > 0 ) { err = CheckSpaceRW(dev, (W)sizeof(DEV_INFO) * ndev); if ( err < E_OK ) { goto err_ret1; } ldev = Vmalloc((size_t)((W)sizeof(T_LDEV) * ndev)); if ( ldev == NULL ) { err = E_NOMEM; goto err_ret1; } } /* Obtain the registered device. */ total = tk_lst_dev(ldev, 0, ndev); if ( total < E_OK ) { err = ERtoERR(total); goto err_ret2; } /* Convert the device name and store it. */ if ( ndev > total ) { ndev = total; } for ( i = 0; i < ndev; ++i ) { dev[i].attr = ldev[i].devatr; dev[i].nsub = ldev[i].nsub; tcdevnm(dev[i].name, ldev[i].devnm, L_DEVNM); } if ( ldev != NULL ) { Vfree(ldev); } return total;err_ret2: if ( ldev != NULL ) { Vfree(ldev); }err_ret1: DEBUG_PRINT(("_tkse_lst_dev err = %d\n", err)); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -