📄 deviceio.c
字号:
devcb = opncb->devcb; execfn = (EXCFN)devcb->ddev.execfn; exinf = devcb->ddev.exinf;#if TA_GP gp = devcb->ddev.gp;#endif /* Get request management block */ reqcb = newReqCB(opncb); if ( reqcb == NULL ) { ercd = E_LIMIT; goto err_ret1; } /* Set request packet */ reqcb->req.next = NULL; reqcb->req.exinf = NULL; reqcb->req.devid = DEVID(devcb, opncb->unitno); reqcb->req.cmd = cmd; reqcb->req.abort = FALSE; reqcb->req.start = start; reqcb->req.size = size; reqcb->req.buf = buf; reqcb->req.asize = 0; reqcb->req.error = 0; /* Indicate that it is during processing */ reqcb->tskid = tk_get_tid_impl(); UnlockDM(); /* Device driver call */ DISABLE_INTERRUPT; knl_ctxtsk->sysmode++; ENABLE_INTERRUPT;#if TA_GP ercd = CallDeviceDriver(&reqcb->req, tmout, exinf, 0, (FP)execfn, gp);#else ercd = (*execfn)(&reqcb->req, tmout, exinf);#endif DISABLE_INTERRUPT; knl_ctxtsk->sysmode--; ENABLE_INTERRUPT; LockDM(); /* Indicate that it is not during processing */ reqcb->tskid = 0; /* If there is an abort completion wait task, notify abort completion */ if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) { tk_sig_sem_impl(opncb->abort_semid, 1); } if ( ercd < E_OK ) { goto err_ret2; } UnlockDM(); return REQID(reqcb);err_ret2: knl_delReqCB(reqcb);err_ret1: UnlockDM(); DEBUG_PRINT(("knl_request ercd = %d\n", ercd)); return ercd;}#endif /* USE_FUNC_REQUEST */#ifdef USE_FUNC_TK_REA_DEV/* * Start reading from device */SYSCALL ID tk_rea_dev_impl( ID dd, W start, VP buf, W size, TMO tmout ){ ER ercd; ercd = knl_request(dd, start, buf, size, tmout, TDC_READ);#ifdef DEBUG if ( ercd < E_OK ) { DEBUG_PRINT(("tk_rea_dev_impl ercd = %d\n", ercd)); }#endif return ercd;}#endif /* USE_FUNC_TK_REA_DEV */#ifdef USE_FUNC_TK_SREA_DEV/* * Synchronous reading from device */SYSCALL ER tk_srea_dev_impl( ID dd, W start, VP buf, W size, W *asize ){ ER ercd, ioercd; ercd = tk_rea_dev_impl(dd, start, buf, size, TMO_FEVR); if ( ercd < E_OK ) { goto err_ret; } ercd = tk_wai_dev_impl(dd, ercd, asize, &ioercd, TMO_FEVR); if ( ercd < E_OK ) { goto err_ret; } return ioercd;err_ret: DEBUG_PRINT(("tk_srea_dev_impl ercd = %d\n", ercd)); return ercd;}#endif /* USE_FUNC_TK_SREA_DEV */#ifdef USE_FUNC_TK_WRI_DEV/* * Start writing to device */SYSCALL ID tk_wri_dev_impl( ID dd, W start, VP buf, W size, TMO tmout ){ ER ercd; ercd = knl_request(dd, start, buf, size, tmout, TDC_WRITE);#ifdef DEBUG if ( ercd < E_OK ) { DEBUG_PRINT(("tk_wri_dev_impl ercd = %d\n", ercd)); }#endif return ercd;}#endif /* USE_FUNC_TK_WRI_DEV */#ifdef USE_FUNC_TK_SWRI_DEV/* * Synchronous writing to device */SYSCALL ER tk_swri_dev_impl( ID dd, W start, VP buf, W size, W *asize ){ ER ercd, ioercd; ercd = tk_wri_dev_impl(dd, start, buf, size, TMO_FEVR); if ( ercd < E_OK ) { goto err_ret; } ercd = tk_wai_dev_impl(dd, ercd, asize, &ioercd, TMO_FEVR); if ( ercd < E_OK ) { goto err_ret; } return ioercd;err_ret: DEBUG_PRINT(("tk_swri_dev_impl ercd = %d\n", ercd)); return ercd;}#endif /* USE_FUNC_TK_SWRI_DEV */#ifdef USE_FUNC_TK_WAI_DEV/* * Verify validity of request ID */LOCAL ReqCB* knl_check_reqid( ID reqid, OpnCB *opncb ){ ReqCB *reqcb; if ( reqid < 1 || reqid > CFN_MAX_REQDEV ) { return NULL; } reqcb = REQCB(reqid); if ( reqcb->opncb != opncb ) { return NULL; } return reqcb;}/* * Request completion wait */SYSCALL ID tk_wai_dev_impl( ID dd, ID reqid, W *asize, ER *ioer, TMO tmout ){ WAIFN waitfn; VP exinf;#if TA_GP VP gp;#endif OpnCB *opncb; DevCB *devcb; ReqCB *reqcb; T_DEVREQ *devreq; INT reqno, nreq; ID tskid; ER ercd; tskid = tk_get_tid_impl(); LockDM(); ercd = knl_check_devdesc(dd, 0, &opncb); if ( ercd < E_OK ) { goto err_ret2; } devcb = opncb->devcb; waitfn = (WAIFN)devcb->ddev.waitfn; exinf = devcb->ddev.exinf;#if TA_GP gp = devcb->ddev.gp;#endif if ( reqid == 0 ) { /* When waiting for completion of any of requests for 'dd' */ if ( opncb->nwaireq > 0 || opncb->waitone > 0 ) { ercd = E_OBJ; goto err_ret2; } if ( isQueEmpty(&opncb->requestq) ) { ercd = E_NOEXS; goto err_ret2; } /* Create wait request list */ reqcb = (ReqCB*)opncb->requestq.next; for ( nreq = 1;; nreq++ ) { reqcb->tskid = tskid; devreq = &reqcb->req; reqcb = (ReqCB*)reqcb->q.next; if ( reqcb == (ReqCB*)&opncb->requestq ) { break; } devreq->next = &reqcb->req; } devreq->next = NULL; devreq = &((ReqCB*)opncb->requestq.next)->req; opncb->waireqlst = devreq; opncb->nwaireq = nreq; } else { /* Wait for completion of abort request processing */ reqcb = knl_check_reqid(reqid, opncb); if ( reqcb == NULL ) { ercd = E_ID; goto err_ret2; } if ( opncb->nwaireq > 0 || reqcb->tskid > 0 ) { ercd = E_OBJ; goto err_ret2; } /* Create waiting request list */ reqcb->tskid = tskid; devreq = &reqcb->req; devreq->next = NULL; nreq = 1; opncb->waitone++; } UnlockDM(); /* Device driver call */ DISABLE_INTERRUPT; knl_ctxtsk->sysmode++; ENABLE_INTERRUPT;#if TA_GP reqno = CallDeviceDriver(devreq, nreq, tmout, exinf, (FP)waitfn, gp);#else reqno = (*waitfn)(devreq, nreq, tmout, exinf);#endif DISABLE_INTERRUPT; knl_ctxtsk->sysmode--; ENABLE_INTERRUPT; if ( reqno < E_OK ) { ercd = reqno; } if ( reqno >= nreq ) { ercd = E_SYS; } LockDM(); /* Free wait processing */ if ( reqid == 0 ) { opncb->nwaireq = 0; } else { opncb->waitone--; } /* If there is an abort completion wait task, notify abort completion */ if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) { tk_sig_sem_impl(opncb->abort_semid, 1); } /* Get processing result */ while ( devreq != NULL ) { reqcb = DEVREQ_REQCB(devreq); if ( reqno-- == 0 ) { reqid = REQID(reqcb); *asize = devreq->asize; *ioer = devreq->error; } reqcb->tskid = 0; devreq = devreq->next; } if ( ercd < E_OK ) { goto err_ret2; } /* Unregister completed request */ knl_delReqCB(REQCB(reqid)); UnlockDM(); return reqid;err_ret2: UnlockDM(); DEBUG_PRINT(("tk_wai_dev_impl ercd = %d\n", ercd)); return ercd;}#endif /* USE_FUNC_TK_WAI_DEV *//* ------------------------------------------------------------------------ */#ifdef USE_FUNC_DISSUSCNT/* Suspend disable request count */EXPORT INT knl_DisSusCnt = 0;#endif /* USE_FUNC_DISSUSCNT */#ifdef USE_FUNC_TK_SUS_DEV/* * Send driver request event to each device */LOCAL ER sendevt_alldevice( INT evttyp, BOOL disk ){ EVTFN eventfn; QUEUE *q; DevCB *devcb; BOOL d; ER ercd = E_OK; for ( q = knl_UsedDevCB.next; q != &knl_UsedDevCB; q = q->next ) { devcb = (DevCB*)q; d = ( (devcb->ddev.devatr & TD_DEVTYPE) == TDK_DISK )? TRUE: FALSE; if ( disk != d ) { continue; } /* Device driver call */ eventfn = (EVTFN)devcb->ddev.eventfn; DISABLE_INTERRUPT; knl_ctxtsk->sysmode++; ENABLE_INTERRUPT;#if TA_GP ercd = CallDeviceDriver(evttyp, NULL, devcb->ddev.exinf, 0, (FP)eventfn, devcb->ddev.gp);#else ercd = (*eventfn)(evttyp, NULL, devcb->ddev.exinf);#endif DISABLE_INTERRUPT; knl_ctxtsk->sysmode--; ENABLE_INTERRUPT; }#ifdef DEBUG if ( ercd < E_OK ) { DEBUG_PRINT(("sendevt_alldevice ercd = %d\n", ercd)); }#endif return ercd;}/* * Suspend */LOCAL ER do_suspend( void ){ ER ercd; /* Stop accepting device registration/unregistration */ LockREG(); /* Suspend processing of device except for disks */ ercd = sendevt_alldevice(TDV_SUSPEND, FALSE);#ifdef DEBUG if ( ercd < E_OK ) { DEBUG_PRINT(("2. do_suspend -> sendevt_alldevice ercd = %d\n", ercd)); }#endif /* Suspend processing of disk device */ ercd = sendevt_alldevice(TDV_SUSPEND, TRUE);#ifdef DEBUG if ( ercd < E_OK ) { DEBUG_PRINT(("3. do_suspend -> sendevt_alldevice ercd = %d\n", ercd)); }#endif /* Stop accepting new requests */ LockDM(); /* * Insert code to transit to suspend state here */ /* * Insert code executed on returning from suspend state */ /* Resume accepting requests */ UnlockDM(); /* Resume processing of disk device */ ercd = sendevt_alldevice(TDV_RESUME, TRUE);#ifdef DEBUG if ( ercd < E_OK ) { DEBUG_PRINT(("7. do_suspend -> sendevt_alldevice ercd = %d\n", ercd)); }#endif /* Resume processing of device except for disks */ ercd = sendevt_alldevice(TDV_RESUME, FALSE);#ifdef DEBUG if ( ercd < E_OK ) { DEBUG_PRINT(("8. do_suspend -> sendevt_alldevice ercd = %d\n", ercd)); }#endif /* Resume accepting device registration/unregistration */ UnlockREG(); return ercd;}/* * Suspend processing */SYSCALL INT tk_sus_dev_impl( UINT mode ){ ResCB *rescb; BOOL suspend = FALSE; ER ercd; /* Get resource management information */ rescb = knl_GetResCB(); if ( rescb == NULL ) { ercd = E_CTX; goto err_ret1; } LockDM(); switch ( mode & 0xf ) { case TD_SUSPEND: /* Suspend */ if ( knl_DisSusCnt > 0 && (mode & TD_FORCE) == 0 ) { ercd = E_BUSY; goto err_ret2; } suspend = TRUE; break; case TD_DISSUS: /* Disable suspend */ if ( knl_DisSusCnt >= MAX_DISSUS ) { ercd = E_QOVR; goto err_ret2; } knl_DisSusCnt++; rescb->dissus++; break; case TD_ENASUS: /* Enable suspend */ if ( rescb->dissus > 0 ) { rescb->dissus--; knl_DisSusCnt--; } break; case TD_CHECK: /* Get suspend disable request count */ break; default: ercd = E_PAR; goto err_ret2; } UnlockDM(); if ( suspend ) { /* Suspend */ ercd = do_suspend(); if ( ercd < E_OK ) { goto err_ret1; } } return knl_DisSusCnt;err_ret2: UnlockDM();err_ret1: DEBUG_PRINT(("tk_sus_dev_impl ercd = %d\n", ercd)); return ercd;}#endif /* USE_FUNC_TK_SUS_DEV *//* ------------------------------------------------------------------------ */#ifdef USE_FUNC_DEVMGR_STARTUP/* * Device management startup function */EXPORT void knl_devmgr_startup( void ){ LockDM(); /* Initialization of open device management queue */ QueInit(&(knl_resource_control_block.openq)); UnlockDM(); return;}#endif /* USE_FUNC_DEVMGR_STARTUP */#ifdef USE_FUNC_DEVMGR_CLEANUP/* * Device management cleanup function */EXPORT void knl_devmgr_cleanup( void ){ OpnCB *opncb; /* Do nothing if it is not used even once */ if ( knl_resource_control_block.openq.next == NULL ) { return; } LockDM(); /* Free suspend disable request */ knl_DisSusCnt -= knl_resource_control_block.dissus; knl_resource_control_block.dissus = 0; /* Close all open devices */ while ( !isQueEmpty(&(knl_resource_control_block.openq)) ) { opncb = RESQ_OPNCB(knl_resource_control_block.openq.next); /* Indicate that it is during close processing */ opncb->resid = 0; UnlockDM(); /* Device close processing */ knl_close_device(opncb, 0); LockDM(); } UnlockDM(); return;}#endif /* USE_FUNC_DEVMGR_CLEANUP */#ifdef USE_FUNC_INITDEVIO/* * Initialization sequence of device input/output-related */EXPORT ER knl_initDevIO( void ){ INT i; QueInit(&knl_FreeOpnCB); for ( i = 0; i < CFN_MAX_OPNDEV; ++i ) { knl_OpnCBtbl[i].resid = 0; QueInsert(&knl_OpnCBtbl[i].q, &knl_FreeOpnCB); } QueInit(&knl_FreeReqCB); for ( i = 0; i < CFN_MAX_REQDEV; ++i ) { knl_ReqCBtbl[i].opncb = NULL; QueInsert(&knl_ReqCBtbl[i].q, &knl_FreeReqCB); } return E_OK;}#endif /* USE_FUNC_INITDEVIO */#ifdef USE_FUNC_FINISHDEVIO/* * Finalization sequence of device input/output-related */EXPORT ER knl_finishDevIO( void ){ return E_OK;}#endif /* USE_FUNC_FINISHDEVIO */#endif /* CFN_MAX_REGDEV */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -