📄 deviceio.c
字号:
} if ( err < E_OK ) goto err_ret2; UnlockDM(); return REQID(reqcb);err_ret2: delReqCB(reqcb);err_ret1: UnlockDM(); DEBUG_PRINT(("request err = %d\n", err)); return err;}/* * Start reading from device */EXPORT ID _tk_rea_dev( ID dd, INT start, VP buf, INT size, TMO tmout ){ ER err; err = request(dd, start, buf, size, tmout, TDC_READ);#ifdef DEBUG if ( err < E_OK ) DEBUG_PRINT(("_tk_rea_dev err = %d\n", err));#endif return err;}/* * Synchronous reading from device */EXPORT ER _tk_srea_dev( ID dd, INT start, VP buf, INT size, INT *asize ){ ER err, ioerr; /* Precheck to avoid errors by 'tk_wai_dev' */ err = ChkSpaceRW(asize, sizeof(INT)); if ( err < E_OK ) goto err_ret; err = _tk_rea_dev(dd, start, buf, size, TMO_FEVR); if ( err < E_OK ) goto err_ret; err = _tk_wai_dev(dd, err, asize, &ioerr, TMO_FEVR); if ( err < E_OK ) goto err_ret; return ioerr;err_ret: DEBUG_PRINT(("_tk_srea_dev err = %d\n", err)); return err;}/* * Start writing to device */EXPORT ID _tk_wri_dev( ID dd, INT start, VP buf, INT size, TMO tmout ){ ER err; err = request(dd, start, buf, size, tmout, TDC_WRITE);#ifdef DEBUG if ( err < E_OK ) DEBUG_PRINT(("_tk_wri_dev err = %d\n", err));#endif return err;}/* * Synchronous writing to device */EXPORT ER _tk_swri_dev( ID dd, INT start, VP buf, INT size, INT *asize ){ ER err, ioerr; /* Precheck to avoid errors by 'tk_wai_dev' */ err = ChkSpaceRW(asize, sizeof(INT)); if ( err < E_OK ) goto err_ret; err = _tk_wri_dev(dd, start, buf, size, TMO_FEVR); if ( err < E_OK ) goto err_ret; err = _tk_wai_dev(dd, err, asize, &ioerr, TMO_FEVR); if ( err < E_OK ) goto err_ret; return ioerr;err_ret: DEBUG_PRINT(("_tk_swri_dev err = %d\n", err)); return err;}/* * Request completion wait */EXPORT ID _tk_wai_dev( ID dd, ID reqid, INT *asize, ER *ioer, TMO tmout ){ INT (*waitfn)( T_DEVREQ *devreq, INT nreq, TMO tmout, VP exinf ); VP exinf;#if TA_GP VP gp;#endif OpnCB *opncb; DevCB *devcb; ReqCB *reqcb; T_DEVREQ *devreq; INT reqno, nreq; ID tskid; ER err; err = ChkSpaceRW(asize, sizeof(INT)); if ( err < E_OK ) goto err_ret1; err = ChkSpaceRW(ioer, sizeof(ER)); if ( err < E_OK ) goto err_ret1; tskid = tk_get_tid(); LockDM(); /* Check whether there is a break request */ err = check_break(); if ( err < E_OK ) goto err_ret2; err = check_devdesc(dd, 0, &opncb); if ( err < E_OK ) goto err_ret2; devcb = opncb->devcb; waitfn = (VP)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 ) { err = E_OBJ; goto err_ret2; } if ( isQueEmpty(&opncb->requestq) ) { err = 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 = check_reqid(reqid, opncb); if ( reqcb == NULL ) { err = E_ID; goto err_ret2; } if ( opncb->nwaireq > 0 || reqcb->tskid > 0 ) { err = 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 */#if TA_GP reqno = CallDeviceDriver(devreq, nreq, tmout, exinf, waitfn, gp);#else reqno = (*waitfn)(devreq, nreq, tmout, exinf);#endif if ( reqno < E_OK ) err = reqno; if ( reqno >= nreq ) err = 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 ) { SyncSignalDM(opncb->abort_tskid); } /* 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 ( err < E_OK ) goto err_ret2; /* Unregister completed request */ delReqCB(REQCB(reqid)); UnlockDM(); return reqid;err_ret2: UnlockDM();err_ret1: DEBUG_PRINT(("_tk_wai_dev err = %d\n", err)); return err;}/* ------------------------------------------------------------------------ *//* Suspend disable request count */LOCAL INT DisSusCnt;/* Maximum number of suspend disable request counts */#define MAX_DISSUS 0x7fff/* * Send driver request event to each device */LOCAL ER sendevt_alldevice( INT evttyp, BOOL disk ){ INT (*eventfn)( INT evttyp, VP evtinf, VP exinf ); QUEUE *q; DevCB *devcb; BOOL d; ER err, error = E_OK; for ( q = UsedDevCB.next; q != &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 = (VP)devcb->ddev.eventfn;#if TA_GP err = CallDeviceDriver(evttyp, NULL, devcb->ddev.exinf, 0, eventfn, devcb->ddev.gp);#else err = (*eventfn)(evttyp, NULL, devcb->ddev.exinf);#endif if ( err < E_OK ) error = err; }#ifdef DEBUG if ( error < E_OK ) DEBUG_PRINT(("sendevt_alldevice err = %d\n", error));#endif return error;}/* * Suspend */LOCAL ER do_suspend( void ){ ER err, error = E_OK; /* Stop accepting device registration/unregistration */ LockREG(); /* Processing before starting subsystem suspend */ err = tk_evt_ssy(0, TSEVT_SUSPEND_BEGIN, 0, 0); if ( err < E_OK ) error = err; /* Suspend processing of device except for disks */ err = sendevt_alldevice(TDV_SUSPEND, FALSE); if ( err < E_OK ) error = err; /* Suspend processing of disk device */ err = sendevt_alldevice(TDV_SUSPEND, TRUE); if ( err < E_OK ) error = err; /* Stop accepting new requests */ LockDM(); /* Processing after completion of subsystem suspend */ err = tk_evt_ssy(0, TSEVT_SUSPEND_DONE, 0, 0); if ( err < E_OK ) error = err; /* Transit to suspend state */ err = tk_set_pow(TPW_DOSUSPEND); if ( err < E_OK ) error = err; /* Return from suspend state */ /* Processing before starting subsystem resume */ err = tk_evt_ssy(0, TSEVT_RESUME_BEGIN, 0, 0); if ( err < E_OK ) error = err; /* Resume accepting requests */ UnlockDM(); /* Resume processing of disk device */ err = sendevt_alldevice(TDV_RESUME, TRUE); if ( err < E_OK ) error = err; /* Resume processing of device except for disks */ err = sendevt_alldevice(TDV_RESUME, FALSE); if ( err < E_OK ) error = err; /* Processing after completion of subsystem resume */ err = tk_evt_ssy(0, TSEVT_RESUME_DONE, 0, 0); if ( err < E_OK ) error = err; /* Resume accepting device registration/unregistration */ UnlockREG();#ifdef DEBUG if ( error < E_OK ) DEBUG_PRINT(("do_suspend err = %d\n", error));#endif return error;}/* * Suspend processing */EXPORT INT _tk_sus_dev( UINT mode ){ ResCB *rescb; BOOL suspend = FALSE; ER err; /* Get resource management information */ rescb = GetResCB(DEVICE_SVC, TSK_SELF); if ( rescb == NULL ) { err = E_CTX; goto err_ret1; } LockDM(); switch ( mode & 0xf ) { case TD_SUSPEND: /* Suspend */ if ( DisSusCnt > 0 && (mode & TD_FORCE) == 0 ) { err = E_BUSY; goto err_ret2; } suspend = TRUE; break; case TD_DISSUS: /* Disable suspend */ if ( DisSusCnt >= MAX_DISSUS ) { err = E_QOVR; goto err_ret2; } DisSusCnt++; rescb->dissus++; break; case TD_ENASUS: /* Enable suspend */ if ( rescb->dissus > 0 ) { rescb->dissus--; DisSusCnt--; } break; case TD_CHECK: /* Get suspend disable request count */ break; default: err = E_PAR; goto err_ret2; } UnlockDM(); if ( suspend ) { /* Suspend */ err = do_suspend(); if ( err < E_OK ) goto err_ret1; } return DisSusCnt;err_ret2: UnlockDM();err_ret1: DEBUG_PRINT(("_tk_sus_dev err = %d\n", err)); return err;}/* ------------------------------------------------------------------------ *//* * Device driver abort function call */Inline ER call_abortfn( DevCB *devcb, ID tskid, T_DEVREQ *devreq, INT nreq ){ ER (*abortfn)( ID tskid, T_DEVREQ *devreq, INT nreq, VP exinf ); abortfn = (VP)devcb->ddev.abortfn;#if TA_GP return CallDeviceDriver(tskid, devreq, nreq, devcb->ddev.exinf, abortfn, devcb->ddev.gp);#else return (*abortfn)(tskid, devreq, nreq, devcb->ddev.exinf);#endif}/* * Device management break function */EXPORT void devmgr_break( ID tskid ){ ResCB *rescb; OpnCB *opncb; ReqCB *reqcb; QUEUE *q, *r; T_DEVREQ *devreq; /* Get resource management block */ rescb = GetResCB(DEVICE_SVC, tskid); if ( rescb == NULL ) return; LockDM(); /* Search the request if 'tskid' task is executing and request abort */ for ( q = rescb->openq.next; q != &rescb->openq; q = q->next ) { opncb = RESQ_OPNCB(q); if ( opncb->nwaireq > 0 ) { /* Multiple requests wait */ reqcb = DEVREQ_REQCB(opncb->waireqlst); if ( reqcb->tskid == tskid ) { /* Abort request: Device driver call */ call_abortfn(opncb->devcb, tskid, opncb->waireqlst, opncb->nwaireq); goto exit; } } else { /* Start request or single request wait */ for ( r = opncb->requestq.next; r != &opncb->requestq; r = r->next ) { reqcb = (ReqCB*)r; if ( reqcb->tskid != tskid ) continue; /* Abort request: Device driver call */ devreq = &reqcb->req; devreq->abort = TRUE; call_abortfn(opncb->devcb, tskid, devreq, 1); goto exit; } } }exit: UnlockDM();}/* * Device management startup function */EXPORT void devmgr_startup( ID resid, INT info ){ ResCB *rescb; ER err; err = tk_get_res(resid, DEVICE_SVC, (VP*)&rescb); if ( err < E_OK ) goto err_ret; LockDM(); /* Initialization of open device management queue */ QueInit(&rescb->openq); UnlockDM(); return;err_ret: DEBUG_PRINT(("devmgr_cleanup err = %d\n", err)); return;}/* * Device management cleanup function */EXPORT void devmgr_cleanup( ID resid, INT info ){ ResCB *rescb; OpnCB *opncb; ER err; err = tk_get_res(resid, DEVICE_SVC, (VP*)&rescb); if ( err < E_OK ) goto err_ret; /* Do nothing if it is not used even once */ if ( rescb->openq.next == NULL ) return; LockDM(); /* Free suspend disable request */ DisSusCnt -= rescb->dissus; rescb->dissus = 0; /* Close all open devices */ while ( !isQueEmpty(&rescb->openq) ) { opncb = RESQ_OPNCB(rescb->openq.next); /* Indicate that it is during close processing */ opncb->resid = 0; UnlockDM(); /* Device close processing */ close_device(opncb, 0); LockDM(); } UnlockDM(); return;err_ret: DEBUG_PRINT(("devmgr_cleanup err = %d\n", err)); return;}/* * Initialization sequence of device input/output-related */EXPORT ER initDevIO( void ){ INT i; ER err; i = _tk_get_cfn("TMaxOpnDev", &MaxOpnDev, 1); if ( i < 1 ) { err = E_SYS; goto err_ret; } i = _tk_get_cfn("TMaxReqDev", &MaxReqDev, 1); if ( i < 1 ) { err = E_SYS; goto err_ret; } /* Generate open management information table */ OpnCBtbl = Imalloc(MaxOpnDev * sizeof(OpnCB)); if ( OpnCBtbl == NULL ) { err = E_NOMEM; goto err_ret; } QueInit(&FreeOpnCB); for ( i = 0; i < MaxOpnDev; ++i ) { OpnCBtbl[i].resid = 0; QueInsert(&OpnCBtbl[i].q, &FreeOpnCB); } /* Generate request management information table */ ReqCBtbl = Imalloc(MaxReqDev * sizeof(ReqCB)); if ( ReqCBtbl == NULL ) { err = E_NOMEM; goto err_ret; } QueInit(&FreeReqCB); for ( i = 0; i < MaxReqDev; ++i ) { ReqCBtbl[i].opncb = NULL; QueInsert(&ReqCBtbl[i].q, &FreeReqCB); } return E_OK;err_ret: DEBUG_PRINT(("initDevIO err = %d\n", err)); return err;}/* * Finalization sequence of device input/output-related */EXPORT ER finishDevIO( void ){ /* Delete each table */ if ( OpnCBtbl != NULL ) { Ifree(OpnCBtbl); OpnCBtbl = NULL; } if ( ReqCBtbl != NULL ) { Ifree(ReqCBtbl); ReqCBtbl = NULL; } return E_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -