?? ul_ufsm.c
字號:
/******************************************************************* uLan Communication - uL_DRV - multiplatform uLan driver ul_ufsm.c - finite state machine for building and receiving message frames on UART devices (C) Copyright 1996-2004 by Pavel Pisa - project originator http://cmp.felk.cvut.cz/~pisa (C) Copyright 1996-2004 PiKRON Ltd. http://www.pikron.com (C) Copyright 2002-2004 Petr Smolik The uLan driver project can be used and distributed in compliance with any of next licenses - GPL - GNU Public License See file COPYING for details. - LGPL - Lesser GNU Public License - MPL - Mozilla Public License - and other licenses added by project originator Code can be modified and re-distributed under any combination of the above listed licenses. If contributor does not agree with some of the licenses, he/she can delete appropriate line. WARNING: if you delete all lines, you are not allowed to distribute code or sources in any form. *******************************************************************//*******************************************************************//* uLan main driver automata loop */ul_call_fnc uld_drvloop_proc_1, uld_drvloop_proc_2;ul_call_fnc uld_drvloop_rec_1, uld_drvloop_rec_2, uld_drvloop_rec_3, uld_drvloop_rec_4;int uld_drvloop(ul_drv *udrv, int ret_code){ if(((udrv->char_buff==(udrv->my_adr|0x100))|| (udrv->char_buff==0x100))&& (udrv->char_buff==udrv->last_ctrl)) { /* it seems, that somebody wants us */ udrv->con_flg=0; udrv->xor_sum=udrv->char_buff+1; UL_FCALL2(uld_recbeg_1,uld_drvloop_rec_1); return UL_RC_PROC; }; if(udrv->prep_bll.first!=NULL) /* we have something to proccess */ { LOG_CHIO(" call connect "); UL_FCALL2(*udrv->fnc_connect,uld_drvloop_proc_1); return UL_RC_PROC; }; udrv->char_buff=0; UL_FCALL(*udrv->fnc_recch); return UL_RC_PROC;};int uld_drvloop_proc_error(ul_drv *udrv){ ul_mem_blk *mes; udrv->fnc_timeout=NULL; LOG_MESSAGES("uLan : send message ERROR\n"); if((mes=udrv->con_message)!=NULL) {udrv->con_message=NULL; if((UL_BLK_HEAD(mes).flg&UL_BFL_NORE)|| (++UL_BLK_HEAD(mes).retry_cnt>=UL_RETRY_CNT)) { UL_BLK_HEAD(mes).flg|=UL_BFL_FAIL; ul_bll_move_mes(&udrv->proc_bll,mes); LOG_FAILS(KERN_ERR "uLan : send message (d:%d,s:%d,c:%X,f:%X,l:%d) FAILED after %d attempts\n", UL_BLK_HEAD(mes).dadr,UL_BLK_HEAD(mes).sadr, UL_BLK_HEAD(mes).cmd,UL_BLK_HEAD(mes).flg, UL_BLK_HEAD(mes).len,UL_BLK_HEAD(mes).retry_cnt); SCHEDULE_BH(udrv); }else if(UL_BLK_HEAD(mes).flg&UL_BFL_REWA) ul_bll_move_mes(&udrv->prep_bll,mes); }; udrv->char_buff=0x1FF; return 0;};int uld_drvloop_proc_1(ul_drv *udrv, int ret_code){ if(ret_code<0) {UL_FNEXT(uld_drvloop); return UL_RC_PROC;}; LOG_MESSAGES("uLan : begin of send message\n"); udrv->fnc_timeout=&uld_drvloop_proc_error; udrv->con_message=udrv->prep_bll.first; UL_FCALL2(uld_prmess,uld_drvloop_proc_2); return UL_RC_PROC;};int uld_drvloop_proc_2(ul_drv *udrv, int ret_code){ ul_mem_blk *mes; udrv->fnc_timeout=NULL; udrv->char_buff=udrv->my_adr|0x180; UL_FCALL2(*udrv->fnc_sndch,uld_drvloop); if(udrv->con_message==NULL) return UL_RC_PROC; if(ret_code<0) {uld_drvloop_proc_error(udrv); }else{ LOG_MESSAGES("uLan : send message finished OK\n"); mes=udrv->con_message; udrv->con_message=NULL; if(UL_BLK_HEAD(mes).flg&UL_BFL_M2IN || UL_BLK_HEAD(mes).dadr==udrv->my_adr) { ul_bll_move_mes(&udrv->proc_bll,mes); SCHEDULE_BH(udrv); } else ul_bll_free_mes(mes); }; return UL_RC_PROC;};int uld_drvloop_rec_error(ul_drv *udrv){ ul_mem_blk *mes; udrv->fnc_timeout=NULL; LOG_MESSAGES("uLan : receive message ERROR\n"); if((mes=udrv->con_message)!=NULL) { udrv->con_message=NULL; ul_bll_free_mes(mes); }; udrv->char_buff=0x1FF; return 0;};int uld_drvloop_rec_1(ul_drv *udrv, int ret_code){ ul_mem_blk *mes; if(ret_code<0) {UL_FNEXT(uld_drvloop); return UL_RC_PROC;}; LOG_MESSAGES("uLan : begin of receive message\n"); mes=ul_new_frame_head(udrv,udrv->con_dadr,udrv->con_sadr, udrv->con_cmd,0); if(mes==NULL) { LOG_FAILS(KERN_ERR "uLan : NO memory for receive\n"); UL_FNEXT(uld_drvloop); return UL_RC_PROC; }; ul_bll_ins(&udrv->work_bll,mes); udrv->con_message=mes; udrv->fnc_timeout=&uld_drvloop_rec_error; udrv->con_frame=mes; UL_FCALL2(uld_recdata,uld_drvloop_rec_2); return UL_RC_PROC;};int uld_drvloop_rec_2(ul_drv *udrv, int ret_code){ if(ret_code<0) { uld_drvloop_rec_error(udrv); UL_FNEXT(uld_drvloop); return UL_RC_PROC; }; #ifdef UL_WITH_IAC UL_FCALL2(uld_recend,uld_drvloop_rec_3); #else UL_FCALL2(uld_recend,uld_drvloop_rec_4); #endif /* UL_WITH_IAC */ return UL_RC_PROC;};#ifdef UL_WITH_IACint uld_drvloop_rec_3(ul_drv *udrv, int ret_code){ if(ret_code<0) { uld_drvloop_rec_error(udrv); UL_FNEXT(uld_drvloop); return UL_RC_PROC; }; UL_FCALL2(uld_prmess_iac,uld_drvloop_rec_4); return UL_RC_PROC; }#endif /* UL_WITH_IAC */int uld_drvloop_rec_4(ul_drv *udrv, int ret_code){ ul_mem_blk *mes; if(ret_code<0) { uld_drvloop_rec_error(udrv); UL_FNEXT(uld_drvloop); return UL_RC_PROC; }; mes=udrv->con_message; udrv->fnc_timeout=NULL; udrv->con_message=NULL; if (ret_code==UL_RC_FREEMSG) { ul_bll_free_mes(mes); UL_FNEXT(uld_drvloop); LOG_MESSAGES("uLan : receive message was freed\n"); return UL_RC_PROC; } UL_BLK_HEAD(mes).stamp=ul_gen_stamp(); ul_bll_move_mes(&udrv->proc_bll,mes); SCHEDULE_BH(udrv); UL_FNEXT(uld_drvloop); LOG_MESSAGES("uLan : end of receive message\n"); return UL_RC_PROC;};int ul_max_cycle_cnt=0;int ul_max_cycle_time=0;int ul_irq_seq_num=0;#ifdef ENABLE_UL_IRQ_STALE_WDG int ul_irq_stale_wdg_cnt=0;#endif /* ENABLE_UL_IRQ_STALE_WDG *//*** Interrupt entry point ***/ul_irqreturn_t uld_irq_handler(UL_IRQ_HANDLER_ARGS(intno, dev_id)){ #ifdef UL_GLOBAL_IRQ_LOCK_FINI UL_GLOBAL_IRQ_LOCK_FINI #endif int irq_loop_cnt=0; int cycle_cnt=0; int cycle_time; int ret_code; #ifdef UL_LOG_ENABLE int seq_num=++ul_irq_seq_num; #endif ul_drv* udrv=(ul_drv*)dev_id; if(udrv->magic!=UL_DRV_MAGIC) { #ifdef FOR_LINUX_KERNEL panic("uld_irq_handler : BAD udrv magic !!!"); #elif defined(_WIN32) UL_PRINTF("uld_irq_handler : BAD udrv magic !!!\n"); return FALSE; #elif defined(__DJGPP__)||defined(CONFIG_OC_UL_DRV_SYSLESS) UL_PRINTF("uld_irq_handler : BAD udrv magic !!!\n"); return; #else error("uld_irq_handler : BAD udrv magic !!!"); #endif } #ifdef UL_GLOBAL_IRQ_LOCK UL_GLOBAL_IRQ_LOCK; #endif if(uld_test_dfl(udrv,CHIPOK)) do { #ifdef ENABLE_UL_IRQ_STALE_WDG /* last rescue code for stale IRQ !!!!!! */ if(ul_irq_stale_wdg_cnt++>10000) { SCHEDULE_BH(udrv); /* Test activation of BH */ if(ul_irq_stale_wdg_cnt>20000) { LOG_FATAL(KERN_CRIT "Stale IRQ uLan IRQ signal !!!\n"); udrv->fnc_cctrl(udrv,UL_CC_GENIRQ,0); if(ul_irq_stale_wdg_cnt<25000) break; #ifdef FOR_LINUX_KERNEL LOG_FATAL(KERN_CRIT "Disabling IRQ %d forever !!!\n",intno); disable_irq_nosync(intno); #endif break; } } #endif /* ENABLE_UL_IRQ_STALE_WDG */ do /* IRQ fully SMP and re-entrant processing */ { uld_set_dfl(udrv,ASK_ISR); if(uld_test_and_set_dfl(udrv,IN_ISR)) { LOG_IRQ("uLan IRQ %d arrived, but else is in ISR\n",intno); break; }; /* only one CPU in no nested levels at time */ uld_clear_dfl(udrv,ASK_ISR); while((ret_code=udrv->fnc_pool(udrv))!=0) { LOG_SEQNUM("\n<<< seq %d ",seq_num); LOG_IRQ("uLan IRQ %d arrived, code = %d\n",intno,ret_code); cycle_time=RDTSC; while((ret_code=udrv->fnc_act(udrv,ret_code))!=0) if(cycle_cnt++>100) {LOG_FATAL(KERN_CRIT "Infinite loop in uLan IRQ handler !!!\n");break;}; cycle_time=RDTSC-cycle_time; if(cycle_cnt>ul_max_cycle_cnt) ul_max_cycle_cnt=cycle_cnt; if(cycle_time>ul_max_cycle_time) ul_max_cycle_time=cycle_time; LOG_SEQNUM(" seq %d >>>",seq_num); if(irq_loop_cnt++>10) { LOG_FATAL(KERN_CRIT "Stale IRQ - uLan state handlers !!!\n"); udrv->fnc_cctrl(udrv,UL_CC_GENIRQ,0); break; }; uld_atomic_clear_dfl(udrv,NACTIV); }; uld_atomic_clear_dfl(udrv,IN_ISR); } while(uld_atomic_test_dfl(udrv,ASK_ISR)); }while(0); #ifdef UL_GLOBAL_IRQ_UNLOCK UL_GLOBAL_IRQ_UNLOCK; #endif return UL_IRQ_RETVAL(irq_loop_cnt);};/*** Timeout entry point ***/void uld_timeout(ul_drv *udrv){ #ifdef UL_GLOBAL_IRQ_LOCK_FINI UL_GLOBAL_IRQ_LOCK_FINI #endif #if defined(_WIN32)&&defined(UL_WITH_PCI) KIRQL old_irql; #endif int cycle_cnt=0; int cycle_time; int ret_code=0; #ifdef UL_GLOBAL_IRQ_LOCK UL_GLOBAL_IRQ_LOCK; #endif LOG_IRQ("uLan timeout activated\n"); if(uld_test_dfl(udrv,CHIPOK)) { #ifdef FOR_LINUX_KERNEL if(udrv->irq) disable_irq_nosync(udrv->irq); #elif defined(_WIN32)&&defined(UL_WITH_PCI) KeRaiseIrql(uL_SpinLock_Irql,&old_irql); #endif do { if(uld_test_and_set_dfl(udrv,IN_ISR)) { LOG_IRQ("uLan timeout, but else is in ISR\n"); break; }; /* only one CPU with no nested levels goes there */ uld_clear_dfl(udrv,ASK_ISR); if((ret_code=udrv->fnc_pool(udrv))==0) {/* if first pass check for timeout conditions */ if(!cycle_cnt&&(uld_atomic_test_dfl(udrv,NACTIV)|| (udrv->last_ctrl&0x80))) { cycle_cnt++; uld_clear_dfl(udrv,WDFORCED); if(udrv->fnc_timeout) ret_code=udrv->fnc_timeout(udrv); if(ret_code==0) {udrv->fnc_sp=&udrv->fnc_stack[0]; udrv->fnc_act=&uld_drvloop; ret_code=UL_RC_ACTIVATE; }; }; }; cycle_time=RDTSC; while(ret_code) { ret_code=udrv->fnc_act(udrv,ret_code); if(cycle_cnt++>100) {LOG_FATAL(KERN_CRIT "Infinite loop in uLan Timeout handler !!!\n");break;}; }; cycle_time=RDTSC-cycle_time; if(cycle_cnt>ul_max_cycle_cnt) ul_max_cycle_cnt=cycle_cnt; if(cycle_time>ul_max_cycle_time) ul_max_cycle_time=cycle_time; uld_clear_dfl(udrv,NACTIV); uld_atomic_clear_dfl(udrv,IN_ISR); } while(uld_atomic_test_dfl(udrv,ASK_ISR)); #ifdef FOR_LINUX_KERNEL if(udrv->irq) enable_irq(udrv->irq); #elif defined(_WIN32)&&defined(UL_WITH_PCI) KeLowerIrql(old_irql); #endif }; #ifdef UL_GLOBAL_IRQ_UNLOCK UL_GLOBAL_IRQ_UNLOCK; #endif};/* link watchdog timer function */#ifdef _WIN32VOID ulan_wd_dpc(IN PKDPC Dpc,IN PVOID data, IN PVOID arg1,IN PVOID arg2)#else /* _WIN32 */ void ulan_do_wd_timer(unsigned long data)#endif /* _WIN32 */{ ul_drv* udrv=(ul_drv*)data; if(udrv->magic!=UL_DRV_MAGIC) { #ifdef FOR_LINUX_KERNEL panic("ulan_do_wd_timer : BAD udrv magic !!!"); #elif defined(_WIN32)||defined(__DJGPP__)||defined(CONFIG_OC_UL_DRV_SYSLESS) UL_PRINTF("ulan_do_wd_timer : BAD udrv magic !!!\n"); return; #else error("ulan_do_wd_timer : BAD udrv magic !!!"); #endif } if(!uld_test_dfl(udrv,CHIPOK)) return; if((udrv->prep_bll.first!=NULL)||uld_test_dfl(udrv,WDFORCED)) { if(uld_test_and_set_dfl(udrv,NACTIV)|| (udrv->last_ctrl&0x80)) uld_timeout(udrv); #ifndef _WIN32 SCHEDULE_UDRV_WDTIM(udrv,jiffies+ULD_HZ/25+1); #else /* _WIN32 */ { LARGE_INTEGER delay; delay=RtlConvertLongToLargeInteger(-40*10000); KeSetTimer(&udrv->wd_timer,delay,&udrv->wd_timer_dpc); } #endif /* _WIN32 */ };};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -