gonzui


Format: Advanced Search

mtkernel_3/kernel/tkernel/device.cbare sourcepermlink (0.04 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    micro T-Kernel 3.00.02
    4:  *
    5:  *    Copyright (C) 2006-2020 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.2.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2020/10/21.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: /*
   15:  *      device.c
   16:  *      Device Management Function
   17:  */
   18: 
   19: #include "kernel.h"
   20: #include "sysmgr.h"
   21: #include "device.h"
   22: 
   23: #if USE_DEVICE
   24: 
   25: /* Lock for device management exclusive control */
   26: Noinit(EXPORT   FastMLock knl_DevMgrLock);
   27: 
   28: /* Device initial setting information */
   29: Noinit(EXPORT   T_IDEV            knl_DefaultIDev);
   30: 
   31: /* ------------------------------------------------------------------------ */
   32: /*
   33:  *      Device registration management
   34:  */
   35: 
   36: Noinit(EXPORT   DevCB             knl_DevCBtbl[MAX_REGDEV]); /* Device registration information table */
   37: Noinit(EXPORT   QUEUE             knl_UsedDevCB);    /* In-use queue */
   38: Noinit(EXPORT   QUEUE             knl_FreeDevCB);    /* Unused queue */
   39: 
   40: 
   41: /*
   42:  * Search registration device
   43:  */
   44: EXPORT DevCB* knl_searchDevCB( CONST UB *devnm )
   45: {
   46:         QUEUE  *q;
   47:         DevCB  *devcb;
   48: 
   49:         for ( q = knl_UsedDevCB.next; q != &knl_UsedDevCB; q = q->next ) {
   50:                 devcb = (DevCB*)q;
   51: 
   52:                 if ( devcb->devnm[0] == devnm[0] && knl_strcmp((char*)devcb->devnm, (char*)devnm) == 0 ) {
   53:                         return devcb; /* Found */
   54:                 }
   55:         }
   56: 
   57:         return NULL;
   58: }
   59: 
   60: /*
   61:  * Get DevCB for new registration
   62:  */
   63: LOCAL DevCB* newDevCB( CONST UB *devnm )
   64: {
   65:         DevCB  *devcb;
   66: 
   67:         devcb = (DevCB*)QueRemoveNext(&knl_FreeDevCB);
   68:         if ( devcb == NULL ) {
   69:                 return NULL; /* No space */
   70:         }
   71: 
   72:         knl_strncpy((char*)devcb->devnm, (char*)devnm, L_DEVNM+1);
   73:         QueInit(&devcb->openq);
   74: 
   75:         QueInsert(&devcb->q, &knl_UsedDevCB);
   76: 
   77:         return devcb;
   78: }
   79: 
   80: /*
   81:  * Free DevCB
   82:  */
   83: LOCAL void delDevCB( DevCB *devcb )
   84: {
   85:         QueRemove(&devcb->q);
   86:         QueInsert(&devcb->q, &knl_FreeDevCB);
   87:         devcb->devnm[0] = '\0';
   88: }
   89: 
   90: /*
   91:  * Device registration
   92:  */
   93: SYSCALL ID tk_def_dev( CONST UB *devnm, CONST T_DDEV *pk_ddev, T_IDEV *pk_idev )
   94: {
   95:         DevCB  *devcb;
   96:         INT    len;
   97:         ER     ercd;
   98: 
   99:         LockREG();
  100: 
  101:         len = knl_strlen((char*)devnm);
  102:         if ( len == 0 || len > L_DEVNM ) {
  103:                 ercd = E_PAR;
  104:                 goto err_ret1;
  105:         }
  106: 
  107:         if ( pk_ddev != NULL ) {
  108:                 if ( pk_ddev->nsub < 0 || pk_ddev->nsub > MAX_UNIT ) {
  109:                         ercd = E_PAR;
  110:                         goto err_ret1;
  111:                 }
  112: 
  113:                 /* Make sure that the length of the logical device name
  114:                    does not exceed the character limit */
  115:                 if ( pk_ddev->nsub > 0   ) {
  116:                         ++len;
  117:                 }
  118:                 if ( pk_ddev->nsub > 10  ) {
  119:                         ++len;
  120:                 }
  121:                 if ( pk_ddev->nsub > 100 ) {
  122:                         ++len;
  123:                 }
  124:                 if ( len > L_DEVNM ) {
  125:                         ercd = E_PAR;
  126:                         goto err_ret1;
  127:                 }
  128:         }
  129: 
  130:         LockDM();
  131: 
  132:         /* Search whether 'devnm' device is registered */
  133:         devcb = knl_searchDevCB(devnm);
  134:         if ( devcb == NULL ) {
  135:                 if ( pk_ddev == NULL ) {
  136:                         ercd = E_NOEXS;
  137:                         goto err_ret2;
  138:                 }
  139: 
  140:                 /* Get 'devcb' for new registration because it is not
  141:                    registered */
  142:                 devcb = newDevCB(devnm);
  143:                 if ( devcb == NULL ) {
  144:                         ercd = E_LIMIT;
  145:                         goto err_ret2;
  146:                 }
  147:         }
  148: 
  149:         if ( pk_ddev != NULL ) {
  150:                 /* Set/update device registration information */
  151:                 devcb->ddev = *pk_ddev;
  152: 
  153:                 if ( pk_idev != NULL ) {
  154:                         /* Device initial setting information */
  155:                         *pk_idev = knl_DefaultIDev;
  156:                 }
  157:         } else {
  158:                 if ( !isQueEmpty(&devcb->openq) ) {
  159:                         /* In use (open) */
  160:                         ercd = E_BUSY;
  161:                         goto err_ret2;
  162:                 }
  163: 
  164:                 /* Device unregistration */
  165:                 delDevCB(devcb);
  166:         }
  167: 
  168:         UnlockDM();
  169:         UnlockREG();
  170: 
  171:         return DID(devcb);
  172: 
  173: err_ret2:
  174:         UnlockDM();
  175: err_ret1:
  176:         UnlockREG();
  177:         return ercd;
  178: }
  179: 
  180: /*
  181:  * Check device initial information
  182:  */
  183: SYSCALL ER tk_ref_idv( T_IDEV *pk_idev )
  184: {
  185:         LockDM();
  186:         *pk_idev = knl_DefaultIDev;
  187:         UnlockDM();
  188: 
  189:         return E_OK;
  190: }
  191: 
  192: /* ------------------------------------------------------------------------ */
  193: 
  194: /*
  195:  * Get physical device name
  196:  *      Get the subunit number (return value) 
  197:  *      from the logical device name (ldevnm) and the physical
  198:  *      device name (pdevnm).
  199:  */
  200: EXPORT INT knl_phydevnm( UB *pdevnm, CONST UB *ldevnm )
  201: {
  202:         UB     c;
  203:         INT    unitno;
  204: 
  205:         while ( (c = *ldevnm) != '\0' ) {
  206:                 if ( c >= '0' && c <= '9' ) {
  207:                         break;
  208:                 }
  209:                 *pdevnm++ = c;
  210:                 ldevnm++;
  211:         }
  212:         *pdevnm = '\0';
  213: 
  214:         unitno = 0;
  215:         if (c != '\0') {
  216:                 while ( (c = *ldevnm) != '\0' ) {
  217:                         unitno = unitno * 10 + (c - '0');
  218:                         ldevnm++;
  219:                 }
  220:                 ++unitno;
  221:         }
  222: 
  223:         return unitno;
  224: }
  225: 
  226: /*
  227:  * Get logical device name
  228:  *      Get the logical device name from
  229:  *      the physical device name (pdevnm) and the subunit number (unitno).
  230:  */
  231: LOCAL void logdevnm( UB *ldevnm, UB *pdevnm, INT unitno )
  232: {
  233:         UB     unostr[12], *cp;
  234: 
  235:         knl_strcpy((char*)ldevnm, (char*)pdevnm);
  236:         if ( unitno > 0 ) {
  237:                 cp = &unostr[11];
  238:                 *cp = '\0';
  239:                 while (*ldevnm != '\0') {
  240:                         ++ldevnm;
  241:                 }
  242:                 --unitno;
  243:                 do {
  244:                         *(--cp) = (UB)('0' + (unitno % 10));
  245:                         unitno /= 10;
  246:                 } while (unitno);
  247:                 knl_strcat((char*)ldevnm, (char*)cp);
  248:         }
  249: }
  250: 
  251: /*
  252:  * Get device name
  253:  */
  254: SYSCALL ID tk_get_dev( ID devid, UB *devnm )
  255: {
  256:         DevCB  *devcb;
  257:         ER     ercd;
  258: 
  259:         ercd = knl_check_devid(devid);
  260:         if ( ercd < E_OK ) {
  261:                 goto err_ret1;
  262:         }
  263: 
  264:         LockDM();
  265: 
  266:         devcb = DEVCB(devid);
  267:         if ( (devcb->devnm[0] == '\0')||(UNITNO(devid) > devcb->ddev.nsub) ) {
  268:                 ercd = E_NOEXS;
  269:                 goto err_ret2;
  270:         }
  271: 
  272:         logdevnm(devnm, devcb->devnm, UNITNO(devid));
  273: 
  274:         UnlockDM();
  275: 
  276:         return DID(devcb);
  277: 
  278: err_ret2:
  279:         UnlockDM();
  280: err_ret1:
  281:         return ercd;
  282: }
  283: 
  284: /*
  285:  * Get device information
  286:  */
  287: SYSCALL ID tk_ref_dev( CONST UB *devnm, T_RDEV *pk_rdev )
  288: {
  289:         UB     pdevnm[L_DEVNM + 1];
  290:         DevCB  *devcb;
  291:         INT    unitno;
  292:         ER     ercd;
  293: 
  294:         unitno = knl_phydevnm(pdevnm, devnm);
  295: 
  296:         LockDM();
  297: 
  298:         devcb = knl_searchDevCB(pdevnm);
  299:         if ( devcb == NULL || unitno > devcb->ddev.nsub ) {
  300:                 ercd = E_NOEXS;
  301:                 goto err_ret2;
  302:         }
  303: 
  304:         if ( pk_rdev != NULL ) {
  305:                 pk_rdev->devatr = devcb->ddev.devatr;
  306:                 pk_rdev->blksz  = devcb->ddev.blksz;
  307:                 pk_rdev->nsub   = devcb->ddev.nsub;
  308:                 pk_rdev->subno  = unitno;
  309:         }
  310: 
  311:         UnlockDM();
  312: 
  313:         return DEVID(devcb, unitno);
  314: 
  315: err_ret2:
  316:         UnlockDM();
  317:         return ercd;
  318: }
  319: 
  320: /*
  321:  * Get device information
  322:  */
  323: SYSCALL ID tk_oref_dev( ID dd, T_RDEV *pk_rdev )
  324: {
  325:         OpnCB  *opncb;
  326:         DevCB  *devcb;
  327:         INT    unitno;
  328:         ER     ercd;
  329: 
  330:         LockDM();
  331: 
  332:         ercd = knl_check_devdesc(dd, 0, &opncb);
  333:         if ( ercd < E_OK ) {
  334:                 goto err_ret2;
  335:         }
  336: 
  337:         devcb  = opncb->devcb;
  338:         unitno = opncb->unitno;
  339: 
  340:         if ( pk_rdev != NULL ) {
  341:                 pk_rdev->devatr = devcb->ddev.devatr;
  342:                 pk_rdev->blksz  = devcb->ddev.blksz;
  343:                 pk_rdev->nsub   = devcb->ddev.nsub;
  344:                 pk_rdev->subno  = unitno;
  345:         }
  346: 
  347:         UnlockDM();
  348: 
  349:         return DEVID(devcb, unitno);
  350: 
  351: err_ret2:
  352:         UnlockDM();
  353:         return ercd;
  354: }
  355: 
  356: /*
  357:  * Get registration device list
  358:  */
  359: SYSCALL INT tk_lst_dev( T_LDEV *pk_ldev, INT start, INT ndev )
  360: {
  361:         DevCB  *devcb;
  362:         QUEUE  *q;
  363:         INT    n, end;
  364:         ER     ercd;
  365: 
  366:         if ( start < 0 || ndev < 0 ) {
  367:                 ercd = E_PAR;
  368:                 goto err_ret;
  369:         }
  370:         LockDM();
  371: 
  372:         end = start + ndev;
  373:         n = 0;
  374:         for ( q = knl_UsedDevCB.next; q != &knl_UsedDevCB; q = q->next ) {
  375:                 if ( n >= start && n < end ) {
  376:                         devcb = (DevCB*)q;
  377:                         pk_ldev->devatr = devcb->ddev.devatr;
  378:                         pk_ldev->blksz  = devcb->ddev.blksz;
  379:                         pk_ldev->nsub   = devcb->ddev.nsub;
  380:                         knl_strncpy((char*)pk_ldev->devnm, (char*)devcb->devnm, L_DEVNM);
  381:                         pk_ldev++;
  382:                 }
  383:                 n++;
  384:         }
  385: 
  386:         UnlockDM();
  387: 
  388:         if ( start >= n ) {
  389:                 ercd = E_NOEXS;
  390:                 goto err_ret;
  391:         }
  392: 
  393:         return n - start;
  394: 
  395: err_ret:
  396:         return ercd;
  397: }
  398: 
  399: /* ------------------------------------------------------------------------ */
  400: 
  401: /*
  402:  * Send driver request event
  403:  */
  404: SYSCALL INT tk_evt_dev( ID devid, INT evttyp, void *evtinf )
  405: {
  406:         DevCB  *devcb;
  407:         EVTFN  eventfn;
  408:         void   *exinf;
  409:         ER     ercd;
  410: 
  411:         ercd = knl_check_devid(devid);
  412:         if ( ercd < E_OK ) {
  413:                 goto err_ret1;
  414:         }
  415:         if ( evttyp < 0 ) {
  416:                 ercd = E_PAR;
  417:                 goto err_ret1;
  418:         }
  419: 
  420:         LockDM();
  421: 
  422:         devcb = DEVCB(devid);
  423:         if ( (devcb->devnm[0] == '\0')||(UNITNO(devid) > devcb->ddev.nsub) ) {
  424:                 ercd = E_NOEXS;
  425:                 goto err_ret2;
  426:         }
  427: 
  428:         eventfn = (EVTFN)devcb->ddev.eventfn;
  429:         exinf = devcb->ddev.exinf;
  430: 
  431:         UnlockDM();
  432: 
  433:         /* Device driver call */
  434:         DISABLE_INTERRUPT;
  435:         knl_ctxtsk->sysmode++;
  436:         ENABLE_INTERRUPT;
  437:         ercd = (*eventfn)(evttyp, evtinf, exinf);
  438:         DISABLE_INTERRUPT;
  439:         knl_ctxtsk->sysmode--;
  440:         ENABLE_INTERRUPT;
  441: 
  442:         return ercd;
  443: 
  444: err_ret2:
  445:         UnlockDM();
  446: err_ret1:
  447:         return ercd;
  448: }
  449: 
  450: /* ------------------------------------------------------------------------ */
  451: 
  452: /*
  453:  * Initialization of device registration information table
  454:  */
  455: LOCAL ER initDevCB( void )
  456: {
  457:         DevCB  *devcb;
  458:         INT    num = MAX_REGDEV;
  459: 
  460:         QueInit(&knl_UsedDevCB);
  461:         QueInit(&knl_FreeDevCB);
  462: 
  463:         devcb = knl_DevCBtbl;
  464:         while ( num-- > 0 ) {
  465:                 QueInsert(&devcb->q, &knl_FreeDevCB);
  466:                 devcb->devnm[0] = '\0';
  467:                 devcb++;
  468:         }
  469: 
  470:         return E_OK;
  471: }
  472: 
  473: /*
  474:  * Initialization of device initial setting information
  475:  */
  476: LOCAL ER initIDev( void )
  477: {
  478:         ER     ercd;
  479: 
  480: #if DEVT_MBFSZ0 >= 0
  481:         T_CMBF cmbf;
  482: 
  483:         /* Generate message buffer for event notification */
  484:         knl_strncpy((char*)&cmbf.exinf, (char*)OBJNAME_DMMBF, sizeof(cmbf.exinf));
  485:         cmbf.mbfatr = TA_TFIFO;
  486:         cmbf.bufsz  = DEVT_MBFSZ0;
  487:         cmbf.maxmsz = DEVT_MBFSZ1;
  488:         ercd = tk_cre_mbf(&cmbf);
  489:         if ( ercd < E_OK ) {
  490:                 knl_DefaultIDev.evtmbfid = 0;
  491:                 goto err_ret;
  492:         }
  493: #else   /* Do not use message buffer for event notification */
  494:         ercd = E_OK;
  495: #endif
  496:         knl_DefaultIDev.evtmbfid = ercd;
  497: 
  498: #if DEVT_MBFSZ0 >= 0
  499: err_ret:
  500: #endif
  501:         return ercd;
  502: }
  503: 
  504: /*
  505:  * Initialization of Devive management
  506:  */
  507: EXPORT ER knl_initialize_devmgr( void )
  508: {
  509:         ER     ercd;
  510: 
  511:         /* Generate lock for device management exclusive control */
  512:         ercd = CreateMLock(&knl_DevMgrLock, (UB*)OBJNAME_DMLOCK);
  513:         if ( ercd < E_OK ) {
  514:                 goto err_ret;
  515:         }
  516: 
  517:         /* Generate device registration information table */
  518:         ercd = initDevCB();
  519:         if ( ercd < E_OK ) {
  520:                 goto err_ret;
  521:         }
  522: 
  523:         /* Initialization of device input/output-related */
  524:         ercd = knl_initDevIO();
  525:         if ( ercd < E_OK ) {
  526:                 goto err_ret;
  527:         }
  528: 
  529:         /* Initialization of device initial setting information */
  530:         ercd = initIDev();
  531:         if ( ercd < E_OK ) {
  532:                 goto err_ret;
  533:         }
  534: 
  535:         knl_devmgr_startup();
  536: 
  537:         return E_OK;
  538: 
  539: err_ret:
  540:         knl_finish_devmgr();
  541:         return ercd;
  542: }
  543: 
  544: /*
  545:  * Unregister device initial setting information
  546:  */
  547: LOCAL ER delIDev( void )
  548: {
  549:         ER     ercd = E_OK;
  550: 
  551: #if DEVT_MBFSZ0 >= 0
  552:         /* Delete message buffer for event notification */
  553:         if ( knl_DefaultIDev.evtmbfid > 0 ) {
  554:                 ercd = tk_del_mbf(knl_DefaultIDev.evtmbfid);
  555:                 knl_DefaultIDev.evtmbfid = 0;
  556:         }
  557: 
  558: 
  559: #endif /* DEVT_MBFSZ0 >= 0 */
  560: 
  561:         return ercd;
  562: }
  563: 
  564: /*
  565:  * Finalization sequence of system management 
  566:  */
  567: EXPORT ER knl_finish_devmgr( void )
  568: {
  569:         ER     ercd;
  570: 
  571:         knl_devmgr_cleanup();
  572: 
  573:         /* Unregister device initial setting information */
  574:         ercd = delIDev();
  575: 
  576:         /* Finalization sequence of device input/output-related */
  577:         ercd = knl_finishDevIO();
  578: 
  579:         /* Delete lock for device management exclusive control */
  580:         DeleteMLock(&knl_DevMgrLock);
  581: 
  582:         return ercd;
  583: }
  584: 
  585: #endif /* USE_DEVICE */