gonzui


Format: Advanced Search

tkernel_2/monitor/hwdepend/tef_em1d/src/diskio.cbare sourcepermlink (0.01 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   11:  *
   12:  *----------------------------------------------------------------------
   13:  */
   14: 
   15: /*
   16:  *      diskio.c
   17:  *
   18:  *       Disk I/O
   19:  */
   20: 
   21: #include "hwdepend.h"
   22: #include <device/disk.h>
   23: 
   24: /*
   25:  * misaligned data is read as a little-endian data
   26:  */
   27: #define GMW(vp)         ( (UW)((UB*)vp)[0]       \
   28:                         | (UW)((UB*)vp)[1] << 8  \
   29:                         | (UW)((UB*)vp)[2] << 16 \
   30:                         | (UW)((UB*)vp)[3] << 24 )
   31: #define GMH(vp)         ( (UH)((UB*)vp)[0]       \
   32:                         | (UH)((UB*)vp)[1] << 8  )
   33: 
   34: /*
   35:  * control block for a disk drive
   36:  *       When their number is smaller than the number of disks,
   37:  *       already used block is re-used in place of missing block after it is cleared
   38:  */
   39: #define N_DISKCB        3
   40: LOCAL struct dcblist {
   41:         const CFGDISK  *cfg;    /* target device */
   42:         DISKCB         dcb;
   43: } dcbList[N_DISKCB];
   44: 
   45: LOCAL W last_dcb = 0;   /* the last allocated number from dcbList */
   46: 
   47: /*
   48:  * allocating a disk control block
   49:  */
   50: LOCAL DISKCB* getDISKCB( const CFGDISK *cfg )
   51: {
   52:         W      i, n;
   53:         DISKCB *dcb;
   54: 
   55:         /* searching for disk drive control block */
   56:         n = last_dcb;
   57:         do {
   58:                 i = n;
   59:                 if ( dcbList[i].cfg == cfg ) break;
   60:                 if ( ++n >= N_DISKCB ) n = 0;
   61:         } while ( n != last_dcb );
   62:         dcb = &dcbList[i].dcb;
   63:         last_dcb = i;
   64:         if ( dcbList[i].cfg != cfg ) {
   65:                 /* re-use after clear */
   66:                 memset(dcb, 0, sizeof(DISKCB));
   67:                 dcbList[i].cfg = cfg;
   68:         }
   69: 
   70:         return dcb;
   71: }
   72: 
   73: /*
   74:  * search for a device
   75:  *       return the configuration information of device (indicated by devnm) to cfg_p.
   76:  *       return value is a partition number or error.
   77:  */
   78: LOCAL W searchDevice( const UB *devnm, const CFGDISK **cfg_p )
   79: {
   80:         UB     name[L_DEVNM + 1];
   81:         W      i, pno, c;
   82: 
   83:         /* checking device name */
   84:         strncpy(name, devnm, L_DEVNM + 1);
   85:         if ( name[L_DEVNM] != '\0' ) return E_PAR;
   86:         i = strlen(name);
   87:         if ( i <= 0 ) return E_PAR;
   88: 
   89:         /* check for logical device (partition: 0-3) */
   90:         pno = 0;
   91:         c = name[i - 1];
   92:         if ( c >= '0' && c <='3' ) {
   93:                 if ( --i <= 0 ) return E_PAR;
   94:                 name[i] = '\0';               /* partition number is removed */
   95:                 pno = c - '0' + 1;    /* partition number (1 - ) */
   96:         }
   97: 
   98:         /* search for a device */
   99:         for ( i = 0; i < N_ConfigDisk; i++ ) {
  100:                 if ( strncmp(name, ConfigDisk[i].name, L_DEVNM) == 0 ) break;
  101:         }
  102:         if ( i >= N_ConfigDisk ) return E_NOEXS;
  103: 
  104:         *cfg_p = &ConfigDisk[i];
  105:         return pno;
  106: }
  107: 
  108: /*
  109:  * obtain partition information
  110:  */
  111: LOCAL ER readPart( DISKCB *dcb )
  112: {
  113:         DiskBlock0     buf;
  114:         W              i, pno;
  115:         ER             err;
  116: 
  117:         dcb->boot = 0;
  118: 
  119:         /* if an unexpected disk block size is seen, raise an error */
  120:         if ( dcb->blksz != sizeof(buf) ) return E_NOSPT;
  121: 
  122:         /* read master boot record */
  123:         err = (*dcb->rwdisk)(dcb, 0, 1, &buf, FALSE);
  124:         if ( err < E_OK ) return err;
  125: 
  126:         /* check the signature in the boot block */
  127:         if ( GMH(&buf.signature) != 0xaa55 ) return E_OK; /* no partition */
  128: 
  129:         /* obtain partition information */
  130:         for ( i = 0; i < MAX_PARTITION; i++ ) {
  131:                 pno = i + 1;
  132:                 dcb->part[pno].sblk = GMW(buf.part[i].StartBlock);
  133:                 dcb->part[pno].nblk = GMW(buf.part[i].BlockCnt);
  134: 
  135:                 if ( buf.part[i].BootInd == 0x80
  136:                   && dcb->part[pno].nblk > 0
  137:                   && dcb->boot == 0 ) dcb->boot = pno;
  138:         }
  139: 
  140:         return E_OK;
  141: }
  142: 
  143: /*
  144:  * open disk (obtain disk drive control block)
  145:  *       open a device indicated by `devnm', and return the disk information in `dcb'.
  146:  *       devnm can specify a device name with partition number.
  147:  *       return the partition number specified by devnm.
  148:  *       return value     0   : entire disks
  149:  *               1 - : partition number
  150:  *               < 0 : error
  151:  */
  152: EXPORT W openDisk( const UB *devnm, DISKCB **dcb_p )
  153: {
  154:         const CFGDISK  *cfg;
  155:         DISKCB         *dcb;
  156:         W              pno;
  157:         ER             err;
  158: 
  159:         /* search for a device */
  160:         pno = searchDevice(devnm, &cfg);
  161:         if ( pno < E_OK ) return pno;
  162: 
  163:         /* allocating a disk control block */
  164:         dcb = getDISKCB(cfg);
  165: 
  166:         /* initialize disk */
  167:         err = (*cfg->initdisk)(dcb, cfg);
  168:         if ( err < E_OK ) return err;
  169:         if ( dcb->blksz == 0 ) return E_NOMDA;
  170: 
  171:         if ( dcb->boot == 0xff ) {
  172:                 /* read the partition information */
  173:                 err = readPart(dcb);
  174:                 if ( err < E_OK ) return err;
  175:         }
  176: 
  177:         *dcb_p = dcb;
  178:         return pno;
  179: }
  180: 
  181: /*
  182:  * disk access
  183:  *       devnm   device name (possibly with the partition number)
  184:  *       blk     start block number
  185:  *               if device name has a partition number, then the block number in that partition
  186:  *               if there is no partition number in the disk anme, the block number in the entire disk
  187:  *       nblk    number of blocks
  188:  *       buf     buffer (* )
  189:  *       wrt     FALSE : read
  190:  *               TRUE  : write
  191:  *       return value error code
  192:  *       argument marked with (* ) may be an address specified from external sources.
  193:  */
  194: EXPORT ER rwDisk( const UB *devnm, W blk, W nblk, void *buf, BOOL wrt )
  195: {
  196:         DISKCB *dcb;
  197:         W      pno, nb;
  198:         ER     err;
  199: 
  200:         /* initialize disk */
  201:         pno = openDisk(devnm, &dcb);
  202:         if ( pno < E_OK ) return pno;
  203: 
  204:         nb = dcb->part[pno].nblk;
  205: 
  206:         /* range check of the block number */
  207:         if ( blk < 0 || blk >= nb
  208:           || nblk <= 0 || nblk > nb - blk ) return E_PAR;
  209: 
  210:         /* convert the relative block number in a partiton to a block number in the entire disk */
  211:         blk += dcb->part[pno].sblk;
  212: 
  213:         /* read from, or write to disk */
  214:         err = (*dcb->rwdisk)(dcb, blk, nblk, buf, wrt);
  215:         if ( err < E_OK ) return err;
  216: 
  217:         return E_OK;
  218: }
  219: 
  220: /*
  221:  * obtain disk information
  222:  *       devnm   device name (possibly with the partition number)
  223:  *       blksz   return block size (* )
  224:  *       tblks   return the number of all blocks (* )
  225:  *       return value error code
  226:  *       if there is a partition number to the device name, return the specific information to that partition.
  227:  *       argument marked with (* ) may be an address specified from external sources.
  228:  */
  229: EXPORT ER infoDisk( const UB *devnm, W *blksz, W *tblks )
  230: {
  231:         DISKCB *dcb;
  232:         W      pno, buf, n;
  233: 
  234:         /* initialize disk */
  235:         pno = openDisk(devnm, &dcb);
  236:         if ( pno < E_OK ) return pno;
  237: 
  238:         /* obtain disk information
  239:          *       since there are addresses specified from external source, use writeMem()
  240:          */
  241:         buf = dcb->part[pno].nblk;
  242:         n = writeMem((UW)tblks, &buf, sizeof(W), sizeof(W));
  243:         if ( n < sizeof(W) ) return E_MACV;
  244: 
  245:         buf = dcb->blksz;
  246:         n = writeMem((UW)blksz, &buf, sizeof(W), sizeof(W));
  247:         if ( n < sizeof(W) ) return E_MACV;
  248: 
  249:         return E_OK;
  250: }