⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ul_base.c

📁 linux下的RS485的驱动 值得一看
💻 C
字号:
/*******************************************************************  uLan Communication - uL_DRV - multiplatform uLan driver  ul_base.c	- functions common for all kinds of the driver  (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. *******************************************************************/void ulan_stroke(ul_drv *udrv, int force){  UL_DRV_LOCK_FINI  if(!uld_test_dfl(udrv,CHIPOK)) return;  if(force)    uld_set_dfl(udrv,WDFORCED);  else    if(udrv->prep_bll.first==NULL) return;  if(udrv->fnc_stroke)  { udrv->fnc_stroke(udrv);    return;  }  UL_DRV_LOCK;  #ifndef _WIN32  { int delay;    delay=udrv->last_ctrl&0x80?0:ULD_HZ/100+2;    SCHEDULE_UDRV_WDTIM(udrv,jiffies+delay);  }  #else /* _WIN32 */  { LARGE_INTEGER delay;    delay=udrv->last_ctrl&0x80?RtlConvertLongToLargeInteger(-1):		 	      RtlConvertLongToLargeInteger(-40*10000);    KeSetTimer(&udrv->wd_timer,delay,&udrv->wd_timer_dpc);  }   #endif /* _WIN32 */  UL_DRV_UNLOCK;};static void add_to_opchain(ul_opchain **chain,ul_opchain *member){  UL_DRV_LOCK_FINI  UL_DRV_LOCK;  if(!*chain) *chain=member->next=member->prev=member;  else {    ((volatile ul_opchain*)member)->next=*chain;    ((volatile ul_opchain*)member)->prev=(*chain)->prev;    UL_MB();    ((volatile ul_opchain*)(*chain))->prev->next=member;    ((volatile ul_opchain*)(*chain))->prev=member;  };  UL_DRV_UNLOCK;};static void add_to_opchain_front(ul_opchain **chain,ul_opchain *member){  UL_DRV_LOCK_FINI  UL_DRV_LOCK;  if(!*chain) *chain=member->next=member->prev=member;  else {    ((volatile ul_opchain*)member)->next=*chain;    ((volatile ul_opchain*)member)->prev=(*chain)->prev;    UL_MB();    ((volatile ul_opchain*)(*chain))->prev->next=member;    ((volatile ul_opchain*)(*chain))->prev=member;    *(volatile ul_opchain**)chain=member;  };  UL_DRV_UNLOCK;};static void del_from_opchain(ul_opchain **chain,ul_opchain *member){  UL_DRV_LOCK_FINI  UL_DRV_LOCK;  member->next->prev=member->prev;  member->prev->next=member->next;  if(*chain==member)   { if(member->next==member) *chain=NULL;    else *chain=member->next;  };  UL_DRV_UNLOCK;};/* free message form ulan operator */static int ulan_freemsg(ul_opdata* opdata){  int stamp;  ul_mem_blk *mes;  ul_opchain *opmember;  if(!opdata->udrv) return -ENODEV;  if(!(mes=opdata->message)) return -ENOMSG;  if(!UL_BLK_HEAD(mes).stamp)  {    opdata->message=NULL;    stamp=ul_gen_stamp();    UL_BLK_HEAD(mes).stamp=stamp;    if(UL_BLK_HEAD(mes).flg&UL_BFL_M2IN)    {      opmember=(ul_opchain*)MALLOC(sizeof(ul_opchain));      if(opmember)      {	memset(opmember,0,sizeof(ul_opchain));	opmember->stamp=stamp;	opmember->state=UL_OPST_ONCE;	add_to_opchain_front(&opdata->filtchain,opmember);      };    };    ul_bll_move_mes(&opdata->udrv->prep_bll,mes);    ulan_stroke(opdata->udrv, 0);    return stamp;  }else{    ul_dec_ref_cnt(mes);    opdata->message=NULL;    return 0;  };};/* abort preparation of message */static int ulan_abortmsg(ul_opdata* opdata){  ul_mem_blk *mes;  if(!opdata->udrv) return -ENODEV;  if(!(mes=opdata->message)) return -ENOMSG;  opdata->message=NULL;  if(!UL_BLK_HEAD(mes).stamp)  {    ul_free_mes(opdata->udrv,mes);    return 1;  }else{    ul_dec_ref_cnt(mes);    return 0;  };};/* rewind of message */static int ulan_rewmsg(ul_opdata* opdata){  ul_mem_blk *mes;  if(!opdata->udrv) return -ENODEV;  if(!(mes=opdata->message)) return -ENOMSG;  opdata->message=NULL;  ul_di_init(&opdata->data,opdata->message);  return 0;};/* create new outgoing message */static int ulan_newmsg(ul_opdata* opdata,const ul_msginfo *msginfo){  int flg=msginfo->flg;  flg &= ~(UL_BFL_LOCK | UL_BFL_FAIL | UL_BFL_TAIL | UL_BFL_REC);  flg |= UL_BFL_SND;  if(!opdata->udrv) return -ENODEV;  if (opdata->message) ulan_freemsg(opdata);  opdata->message=ul_new_frame_head(opdata->udrv, msginfo->dadr,                     opdata->udrv->my_adr, msginfo->cmd,flg);  if(!opdata->message) return -ENOMEM;  memset(UL_BLK_FDATA(opdata->message),0,UL_BLK_FSIZE);  ul_di_init(&opdata->data,opdata->message);  return 0;}static int ulan_tailmsg(ul_opdata* opdata,const ul_msginfo *msginfo){  ul_mem_blk *mes;  ul_mem_blk *tail;  int flg=msginfo->flg;  if(!opdata->udrv) return -ENODEV;  if(!(mes=opdata->message)) return -ENOMSG;  if(UL_BLK_HEAD(mes).stamp) return -EPERM;  flg &= ~(UL_BFL_LOCK | UL_BFL_FAIL | UL_BFL_TAIL);  if(!flg&UL_BFL_REC) flg|=UL_BFL_SND;  tail=ul_new_frame_head(opdata->udrv, msginfo->dadr,	opdata->udrv->my_adr, msginfo->cmd,flg);  if(!tail) return -ENOMEM;  memset(UL_BLK_FDATA(tail),0,UL_BLK_FSIZE);  UL_BLK_HEAD(tail).len=msginfo->len;  ul_tail_frame_head(mes,tail);  ul_di_init(&opdata->data,tail);  return 0;}static int ulan_acceptmsg(ul_opdata* opdata,ul_msginfo *msginfo){  ul_mem_blk *mes;  ul_opchain *opmember;  if(!opdata->udrv) return -ENODEV;  if (opdata->message) ulan_freemsg(opdata);  memset(msginfo,0,sizeof(ul_msginfo));  if(!(opmember=opdata->recchain)) return -ENOMSG;  del_from_opchain(&opdata->recchain,opmember);  mes=opmember->message;  if(opmember->state==UL_OPST_MES) FREE(opmember);  opdata->message=mes;  ul_di_init(&opdata->data,mes);  msginfo->flg=UL_BLK_HEAD(mes).flg;  msginfo->dadr=UL_BLK_HEAD(mes).dadr;  msginfo->sadr=UL_BLK_HEAD(mes).sadr;  msginfo->cmd=UL_BLK_HEAD(mes).cmd;  msginfo->len=UL_BLK_HEAD(mes).len;  msginfo->stamp=UL_BLK_HEAD(mes).stamp;  return 0;}static int ulan_actailmsg(ul_opdata* opdata,ul_msginfo *msginfo){  ul_mem_blk *mes;  ul_mem_blk *tail;  if(!opdata->udrv) return -ENODEV;  memset(msginfo,0,sizeof(ul_msginfo));  if(!(mes=opdata->message)) return -ENOMSG;  if(!UL_BLK_HEAD(mes).stamp) return -EPERM;  tail=UL_BLK_HEAD(opdata->data.head_blk).next;  if(!tail) return -ENOMSG;  ul_di_init(&opdata->data,tail);  msginfo->flg=UL_BLK_HEAD(tail).flg;  msginfo->dadr=UL_BLK_HEAD(tail).dadr;  msginfo->sadr=UL_BLK_HEAD(tail).sadr;  msginfo->cmd=UL_BLK_HEAD(tail).cmd;  msginfo->len=UL_BLK_HEAD(tail).len;  msginfo->stamp=UL_BLK_HEAD(tail).stamp;  return 0;}/* create new outgoing message */static int ulan_addfilt(ul_opdata* opdata,const ul_msginfo *msginfo){  ul_drv *udrv;  ul_opchain *opmember;  int filtonce;  if(!opdata->udrv) return -ENODEV;  opmember=(ul_opchain*)MALLOC(sizeof(ul_opchain));  udrv=opdata->udrv;  if(!opmember) return -ENOMEM;  memset(opmember,0,sizeof(ul_opchain));  opmember->dadr=msginfo->dadr;  opmember->sadr=msginfo->sadr;  opmember->cmd=msginfo->cmd;  filtonce=msginfo->flg&UL_BFL_NORE;  opmember->state=filtonce?UL_OPST_FILTNEW:UL_OPST_FILT;  add_to_opchain(&opdata->filtchain,opmember);  if(filtonce){    uld_set_dfl(udrv,CHECK_FILT);    SCHEDULE_BH(udrv);  }  LOG_FILTS("ulan_addfilt : filter %d %d %d %s\n",	 opmember->dadr,opmember->sadr,opmember->cmd,filtonce?"once":"");  return 0;}static int ulan_inepoll(ul_opdata* opdata){  return opdata->recchain!=NULL?1:0;}static int ulan_hwtest(ul_opdata* opdata,unsigned long fnc){  int ret;  ul_drv *udrv;  UL_DRV_LOCK_FINI  if(!opdata->udrv) return -ENODEV;  udrv=opdata->udrv;  UL_DRV_LOCK;  ret=udrv->fnc_cctrl(udrv,UL_CC_HWTEST,fnc);  if(ret<0) ret=-EINVAL;  UL_DRV_UNLOCK;  return ret;}static int ulan_setmyadr(ul_opdata* opdata, int newadr){  int ret;  ul_drv *udrv;  if(!opdata->udrv) return -ENODEV;  udrv=opdata->udrv;  ret=udrv->fnc_cctrl(udrv,UL_CC_SETMYADR,newadr);  if(ret==UL_RC_ENOFNC){    if(newadr)      udrv->my_adr=newadr;    ret=udrv->my_adr;  }else if(ret<0) ret=-EINVAL;  return ret;}static int ulan_setidstr(ul_opdata* opdata, const char *idstr){#ifdef UL_WITH_IAC  #define UL_CMD_SID	0xF0	/* Send identification */  ul_drv *udrv;  char *cidstr;  int len;  if(!opdata->udrv) return -ENODEV;  udrv=opdata->udrv;  len=strlen(idstr);  if(!(cidstr=MALLOC(len))) return ENOMEM;  memcpy(cidstr,idstr,len);     ul_drv_del_iac(udrv,UL_CMD_SID);  ul_drv_add_iac(udrv,UL_CMD_SID,UL_IAC_OP_SNDBUFF,NULL,cidstr,len,UL_IAC_BFL_FREEBUFF,NULL);  return 0;#else /*UL_WITH_IAC*/  return -EINVAL;#endif /*UL_WITH_IAC*/}/* this function is responsible to inform all ulan client operators   about message of waited type -- !!!!! it is not SMP clean still */static int ulan_proc_arrived(ul_drv *udrv, ul_mem_blk *message){  ul_opdata *opdata;  ul_opchain **opchain;  ul_opchain *opmember;  ul_opchain *opmember2;  UL_DRV_LOCK_FINI  ul_inc_ref_cnt(message);  UL_DRV_LOCK;  opdata=udrv->operators;  UL_DRV_UNLOCK;  while(opdata)  {    opchain=&opdata->filtchain;    opmember=*opchain;    if(opmember) do    {      if((!opmember->stamp||opmember->stamp==UL_BLK_HEAD(message).stamp)&&	 (!opmember->cmd||opmember->cmd==UL_BLK_HEAD(message).cmd)&&	 (!opmember->dadr||opmember->dadr==UL_BLK_HEAD(message).dadr)&&	 (!opmember->sadr||opmember->sadr==UL_BLK_HEAD(message).sadr))      {	if(opmember->state==UL_OPST_ONCE)	{	  del_from_opchain(opchain,opmember);	  opmember->state=UL_OPST_MES;	  ul_inc_ref_cnt(message);	  opmember->message=message;	  add_to_opchain(&opdata->recchain,opmember);	}else if(opmember->state==UL_OPST_FILT){	 #ifdef FOR_LINUX_KERNEL	  #ifdef ENABLE_UL_MEM_CHECK	  atomic_inc(&ul_mem_check_counter);	  #endif	  opmember2=(ul_opchain*)kmalloc(sizeof(ul_opchain),GFP_ATOMIC);	 #else /* FOR_LINUX_KERNEL */	  opmember2=(ul_opchain*)MALLOC(sizeof(ul_opchain));	 #endif /* FOR_LINUX_KERNEL */	  if(opmember2)	  { 	    memset(opmember2,0,sizeof(ul_opchain));	    opmember2->state=UL_OPST_MES;	    ul_inc_ref_cnt(message);	    opmember2->message=message;	    add_to_opchain(&opdata->recchain,opmember2);	  } else  UL_PRINTF(KERN_CRIT "ulan_proc_arrived : no kernel memory : FIXME handling\n");	};       #ifdef FOR_LINUX_KERNEL	wake_up_interruptible(&opdata->wqrec);       #elif defined(_WIN32)	    wake_and_xch_pending_irp(&opdata->wait_irp,NULL,STATUS_SUCCESS);       #endif /* FOR_LINUX_KERNEL */	break;      };    } while((opmember=opmember->next)!=*opchain);    opdata=opdata->opnext;  };  /* if no one interested in message, it is discarded */  return  ul_dec_ref_cnt(message);};/* check for UL_OPST_FILTNEW and change them to single instance   of UL_OPST_FILT */void check_for_filtnew(ul_drv *udrv){  ul_opdata *opdata;  ul_opchain **opchain;  ul_opchain *opmember;  ul_opchain *opmember2;  ul_opchain *opnext;  UL_DRV_LOCK_FINI  LOG_FILTS("check_for_filtnew : called\n");  UL_DRV_LOCK;  opdata=udrv->operators;  UL_DRV_UNLOCK;  for(;opdata;opdata=opdata->opnext)  {    opchain=&opdata->filtchain;    opmember=*opchain;    if(opmember) do    { opnext=opmember->next;      if(opnext==*opchain) opnext=NULL;      if(opmember->state==UL_OPST_FILTNEW){	LOG_FILTS("check_for_filtnew : processing UL_OPST_FILTNEW\n");	opmember2=*opchain;	while(opmember2){	  if((opmember->cmd==opmember2->cmd)&&             (opmember->sadr==opmember2->sadr)&&	     (opmember->dadr==opmember2->dadr)&&	     (opmember->stamp==opmember2->stamp)&&	     (opmember2->state==UL_OPST_FILT)) break;	  opmember2=opmember2->next;	  if(opmember2==*opchain){	    opmember2=NULL;	  }        };	if(opmember2){	  LOG_FILTS("check_for_filtnew : deletting UL_OPST_FILTNEW\n");	  del_from_opchain(opchain,opmember);	  FREE(opmember);	}else{	  LOG_FILTS("check_for_filtnew : changing to UL_OPST_FILT\n");	  opmember->state=UL_OPST_FILT;	}      }    } while((opmember=opnext)!=NULL);  };};#ifndef _WIN32/* notice about new message in udrv->proc_bll */void ulan_do_bh(ulan_do_bh_data_type data){  ul_mem_blk *message;  ul_drv *udrv=(ul_drv *)data;  #ifdef ENABLE_UL_IRQ_STALE_WDG  ul_irq_stale_wdg_cnt=0;  #endif /* ENABLE_UL_IRQ_STALE_WDG */  if(udrv->magic!=UL_DRV_MAGIC)  {    #ifdef FOR_LINUX_KERNEL     panic("ulan_do_bh : BAD udrv magic !!!");    #else /* FOR_LINUX_KERNEL */     return;    #endif /* FOR_LINUX_KERNEL */  }  LOG_MESSAGES("ulan_do_bh : announcing messages\n");  while(udrv->proc_bll.first||uld_test_dfl(udrv,ASK_BOTTOM))  {    if(uld_test_and_set_dfl(udrv,IN_BOTTOM))    { LOG_MESSAGES("ulan_do_bh : else is already in");	  return;    }    uld_clear_dfl(udrv,ASK_BOTTOM);    if(uld_test_dfl(udrv,CHECK_FILT)){      uld_clear_dfl(udrv,CHECK_FILT);      check_for_filtnew(udrv);    }    while((message=udrv->proc_bll.first))    {      int i;      ul_bll_move_mes(&udrv->opan_bll,message);      i=ulan_proc_arrived(udrv,message);      LOG_MESSAGES("ulan_do_bh : message sent to %d recchains\n",i);    };    uld_atomic_clear_dfl(udrv,IN_BOTTOM);  };};#endif /* _WIN32 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -