/* * Device registration */ RAW_U32 _tk_def_dev( CONST UB *devnm, CONST T_DDEV *ddev, void *caller_gp ) { DevCB *devcb; INT len, evttyp; ER ercd; len = ChkSpaceBstrR(devnm, 0); if ( len <= 0 || len > MaxRegDev ) { RAW_ASSERT(0); } /* Search whether 'devnm' device is registered */ devcb = searchDevCB(devnm); if ( devcb == 0 ) { if ( ddev == 0 ) { 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; 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; } return DID(devcb); }
/* * Device open */ EXPORT ID _tk_opn_dev( CONST UB *devnm, UINT omode ) { UB pdevnm[L_DEVNM + 1]; INT unitno; ResCB *rescb; DevCB *devcb; OpnCB *opncb; WaitQ waiq; ER ercd; ercd = ChkSpaceBstrR(devnm, 0); if ( ercd < E_OK ) { goto err_ret1; } unitno = phydevnm(pdevnm, devnm); /* Get resource management information */ rescb = GetResCB(DEVICE_SVC, TSK_SELF); if ( rescb == NULL ) { ercd = E_CTX; goto err_ret1; } LockDM(); /* Search device to open */ devcb = searchDevCB(pdevnm); if ( devcb == NULL || unitno > devcb->ddev.nsub ) { ercd = E_NOEXS; goto err_ret2; } /* Check open mode */ ercd = chkopenmode(devcb, unitno, omode); if ( ercd < E_OK ) { goto err_ret2; } /* Get open management block */ opncb = newOpnCB(devcb, unitno, omode, rescb); if ( opncb == NULL ) { ercd = E_LIMIT; goto err_ret2; } /* Multiple tasks can initiate open/close processing, so ensure processing only by one task at a time. */ if ( enterSyncWait(&devcb->syncq, &waiq) ) { /* Wait for synchronization for concurrent open/close */ UnlockDM(); SyncWaitDM(); LockDM(); } /* Is device driver call required? */ if ( ! ( chkopen(devcb, unitno, opncb) && (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) ) { /* Device driver call */ UnlockDM(); ercd = call_openfn(devcb, DEVID(devcb, unitno), omode); LockDM(); if ( ercd < E_OK ) { goto err_ret3; } } opncb->resid = tk_get_rid(TSK_SELF); /* Indicate that open processing is completed */ /* Wake up task waiting for synchronization for concurrent open/close */ leaveSyncWait(&devcb->syncq, &waiq); UnlockDM(); return DD(opncb); err_ret3: delOpnCB(opncb); leaveSyncWait(&devcb->syncq, &waiq); err_ret2: UnlockDM(); err_ret1: DEBUG_PRINT(("_tk_opn_dev ercd = %d\n", ercd)); return ercd; }