📄 ul_inlib.c
字号:
/******************************************************************* uLan Communication - uL_DRV - multiplatform uLan driver ul_inlib.c - interface for driver compiled into library linked directly with application (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. *******************************************************************//*******************************************************************//* Interface for driver in library *//* needs for UL_DEV_NAME */#include <ul_lib/ul_fddir.h> #define UL_MINORS 4ul_drv *ul_drv_arr[UL_MINORS]={[0 ... UL_MINORS-1]=NULL};void uld_check_timeout(void);ul_drv *uld_try_open_new(const char *dev_name, const char *options, int minor);ul_opdata *ul_open(const char *dev_name, const char *options){ ul_drv *udrv; ul_opdata *opdata; unsigned int minor; const char *p; /*if(dev_name==NULL) { errno=ENODEV; return NULL;} */ if(dev_name==NULL) dev_name=UL_DEV_NAME; if(!strncasecmp(dev_name,"COM",3)){ /* strnicmp */ p=dev_name+3; if(*p<'1') { errno=ENODEV; return NULL;} minor=*p-'1'; }else{ if(!strncmp(dev_name,"/dev/ulan",9)){ p=dev_name+9; }else { p=dev_name; } if(!*p||(*p==' ')||(*p==':')) minor=0; else{ if(*p<'0') { errno=ENODEV; return NULL;} minor=*p-'0'; } } if (minor >= UL_MINORS) { errno=ENODEV; return NULL;} #ifndef CONFIG_OC_UL_DRV_SYSLESS if (!ul_drv_arr[minor]){ ul_drv_arr[minor]=uld_try_open_new(dev_name,options,minor); } #endif /* CONFIG_OC_UL_DRV_SYSLESS */ if (!ul_drv_arr[minor]){ errno=ENODEV; return NULL; } udrv=ul_drv_arr[minor]; if(!(opdata=MALLOC(sizeof(ul_opdata)))) { errno=ENOMEM; return NULL; }; memset(opdata,0,sizeof(ul_opdata)); /* opdata->file=file; */ opdata->magic=ULOP_MAGIC; opdata->message=NULL; opdata->udrv=udrv; /* init_waitqueue_head(&opdata->wqrec); */ opdata->opprew=NULL; opdata->opnext=NULL; opdata->recchain=NULL; opdata->filtchain=NULL; { /* add us onto list of clients of udrv */ ul_opdata *opptr; UL_DRV_LOCK_FINI UL_DRV_LOCK; opptr=udrv->operators; if(opptr) {opptr->opprew=opdata;opdata->opnext=opptr;}; UL_MB(); udrv->operators=opdata; UL_DRV_UNLOCK; }; uld_printk_flush(); return opdata;}int ul_close(ul_opdata* opdata){ ul_opchain *opmember; if (opdata->message) ulan_freemsg(opdata); { /* delete us from list of clients of udrv */ ul_drv *udrv=opdata->udrv; ul_opdata *opptr; UL_DRV_LOCK_FINI UL_DRV_LOCK; if((opptr=opdata->opnext)) opptr->opprew=opdata->opprew; if((opptr=opdata->opprew)) opptr->opnext=opdata->opnext; else udrv->operators=opdata->opnext; UL_DRV_UNLOCK; if(udrv->irq>0) ul_synchronize_irq(udrv->irq); }; schedule(); while((opmember=opdata->recchain)) { del_from_opchain(&opdata->recchain,opmember); if(opmember->message) ul_dec_ref_cnt(opmember->message); FREE(opmember); }; while((opmember=opdata->filtchain)) { del_from_opchain(&opdata->filtchain,opmember); FREE(opmember); }; FREE(opdata); /* UL_PRINTF("uLan : printudrvbll\n"); */ /* printudrvbll(opdata->udrv); */ uld_printk_flush(); return 0;}ssize_t ul_read(ul_opdata* opdata, void *buf, size_t count){ int cn; int len; if(!opdata->message) { errno=ENOMSG; return -1; } if(opdata->data.pos+count>UL_BLK_HEAD(opdata->data.head_blk).len) count=UL_BLK_HEAD(opdata->data.head_blk).len-opdata->data.pos; cn=count; while(cn>0) { if(!ul_di_adjust(&opdata->data)) { memset(buf,0,cn); cn=0; break; }; len=ul_di_atonce(&opdata->data); if(len>cn) len=cn; memcpy(buf,ul_di_byte(&opdata->data),len); ul_di_add(&opdata->data,len); buf+=len; cn-=len; }; return count-cn;};ssize_t ul_write(ul_opdata* opdata, const void *buf, size_t count){ int cn; int len; ul_mem_blk *blk; if(!opdata->message) { errno=ENOMSG; return -1; } cn=count; while(cn>0) { while(!ul_di_adjust(&opdata->data)) { if(!(blk=ul_alloc_blk(opdata->udrv))) {count-=cn;cn=0;break;}; memset(UL_BLK_NDATA(blk),0,UL_BLK_SIZE); opdata->data.blk->next=blk; }; len=ul_di_atonce(&opdata->data); if(len>cn) len=cn; memcpy(ul_di_byte(&opdata->data),buf,len); ul_di_add(&opdata->data,len); buf+=len; cn-=len; }; if(opdata->data.pos>UL_BLK_HEAD(opdata->data.head_blk).len) UL_BLK_HEAD(opdata->data.head_blk).len=opdata->data.pos; return count-cn;};int ul_newmsg(ul_opdata* opdata,const ul_msginfo *msginfo){ int ret; ret=ulan_newmsg(opdata,msginfo); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_tailmsg(ul_opdata* opdata,const ul_msginfo *msginfo){ int ret; ret=ulan_tailmsg(opdata,msginfo); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_freemsg(ul_opdata* opdata){ int ret; ret=ulan_freemsg(opdata); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_acceptmsg(ul_opdata* opdata,ul_msginfo *msginfo){ int ret; ret=ulan_acceptmsg(opdata,msginfo); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_actailmsg(ul_opdata* opdata,ul_msginfo *msginfo){ int ret; ret=ulan_actailmsg(opdata,msginfo); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_addfilt(ul_opdata* opdata,const ul_msginfo *msginfo){ int ret; ret=ulan_addfilt(opdata,msginfo); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_abortmsg(ul_opdata* opdata){ int ret; ret=ulan_abortmsg(opdata); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_rewmsg(ul_opdata* opdata){ int ret; ret=ulan_rewmsg(opdata); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_inepoll(ul_opdata* opdata){ int ret; #if 1 /* Processing of arrived or processed messages */ uld_check_timeout(); if(uld_test_dfl(opdata->udrv,ASK_BOTTOM)) { ulan_do_bh(opdata->udrv); } #endif ret=ulan_inepoll(opdata); uld_printk_flush(); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_stroke(ul_opdata* opdata){ ul_drv *udrv; if(!opdata->udrv) return -ENODEV; udrv=opdata->udrv; ulan_stroke(udrv, 1); return 0;}int ul_hwtest(ul_opdata* opdata, unsigned int fnc){ int ret; ret=ulan_hwtest(opdata,fnc); if(ret<0) {errno=EINVAL;ret=-1;} return ret;}int ul_setmyadr(ul_opdata* opdata, int newadr){ int ret; ret=ulan_setmyadr(opdata, newadr); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_setidstr(ul_opdata* opdata, const char *idstr){ int ret; ret=ulan_setidstr(opdata, idstr); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_setbaudrate(ul_opdata* opdata, int baudrate){ int ret; ret=ulan_setbaudrate(opdata, baudrate); if(ret<0) {errno=-ret;ret=-1;} return ret;}int ul_drv_debflg(ul_opdata* opdata,int debug_msk) {uld_debug_flg=debug_msk;return uld_debug_flg;};#ifdef UL_LOG_ENABLE#include <stdarg.h>#define ULD_PRINTK_BUF_LEN 4096char uld_printk_buf[ULD_PRINTK_BUF_LEN];char *uld_printk_pin=uld_printk_buf;char *uld_printk_pout=uld_printk_buf;int uld_printk(const char *format, ...){ int len,rest,ret; char buf[255]; va_list va=0; UL_IRQ_LOCK_FINI if(uld_debug_flg&LOG_MSK_DISABLE) return 0; va_start(va,format); ret=vsprintf(buf,format,va); va_end(va); len=strlen(buf); UL_IRQ_LOCK; rest=uld_printk_buf+ULD_PRINTK_BUF_LEN-uld_printk_pin; if(len>=rest){ memcpy(uld_printk_pin,buf,rest); len-=rest; memcpy(uld_printk_buf,buf,len); uld_printk_pin=uld_printk_buf+len; }else{ memcpy(uld_printk_pin,buf,len); uld_printk_pin+=len; } UL_IRQ_UNLOCK; return ret;}void uld_printk_flush(void){ char *pout,*pin; UL_IRQ_LOCK_FINI UL_IRQ_LOCK; pin=uld_printk_pin; pout=uld_printk_pout; UL_IRQ_UNLOCK; if(pin==pout) return; if(pin>pout){ fwrite(pout,pin-pout,1,stderr); uld_printk_pout=pin; }else{ fwrite(pout,uld_printk_buf+ULD_PRINTK_BUF_LEN-pout,1,stderr); fwrite(uld_printk_buf,pin-uld_printk_buf,1,stderr); uld_printk_pout=pin; } fflush(stderr);}#endif /* UL_LOG_ENABLE */void uld_check_timeout(void){ int i; ul_drv *udrv; #ifdef JIFFIES_FROM_GETTIMEOFDAY struct timeval actual; long int new_expires; static long int old_expires; #endif /* JIFFIES_FROM_GETTIMEOFDAY */ #ifdef __DJGPP__ UL_DRV_LOCK_FINI #endif /* __DJGPP__ */ #ifdef JIFFIES_FROM_GETTIMEOFDAY gettimeofday(&actual,NULL); uld_jiffies=actual.tv_usec+actual.tv_sec*ULD_HZ; #endif /* JIFFIES_FROM_GETTIMEOFDAY */ for(i=0;i<UL_MINORS;i++) { if((udrv=ul_drv_arr[i])!=NULL) { if(uld_test_dfl(udrv,WDSCHED)) { #ifdef JIFFIES_FROM_GETTIMEOFDAY if(old_expires!=udrv->wd_timer_expires) { UL_DRV_LOCK; new_expires=uld_jiffies+ULD_HZ/18; if((new_expires-udrv->wd_timer_expires)<0) new_expires=udrv->wd_timer_expires; old_expires=udrv->wd_timer_expires=new_expires; UL_DRV_UNLOCK; LOG_IRQ("sched timeout %ld at time %ld\n",new_expires,uld_jiffies); } #elif 1 { static long int old_expires; if(old_expires!=udrv->wd_timer_expires) LOG_IRQ("sched timeout %ld at time %ld\n", old_expires=udrv->wd_timer_expires,jiffies); } #endif /* JIFFIES_FROM_GETTIMEOFDAY */ if((udrv->wd_timer_expires-jiffies)<0) { uld_clear_dfl(udrv,WDSCHED); ulan_do_wd_timer((unsigned long)udrv); /* uld_timeout(udrv); */ /* printudrvfncstack(udrv) */ } } /* Call bottom halves as needed */ if(uld_test_dfl(udrv,ASK_BOTTOM)) { uld_clear_dfl(udrv,ASK_BOTTOM); ulan_do_bh(udrv); } } } #ifdef __DJGPP__ #if 1 __save_flags(ul_irq_lock_flags); if(!(ul_irq_lock_flags&0x0200)) { LOG_FATAL(KERN_CRIT "Somebody disables IRQ !!!!!\n"); __sti(); } #endif __dpmi_yield(); #endif}#ifndef CONFIG_OC_UL_DRV_SYSLESStypedef struct uld_dev_params{ int port; int irq; int baud; int my_adr; long baudbase;}uld_dev_params_t;static const uld_dev_params_t uld_dev_params_defaults[4]={ {0x3f8,0x4,19200,2,0}, {0x2f8,0x3,19200,2,0}, {0x3e8,0x5,19200,2,0}, {0x2e8,0x5,19200,2,0} };ul_drv *uld_try_open_new(const char *dev_name, const char *options, int minor){ uld_dev_params_t params; const char *p,*r; char *s; char chip_name[16]; if(minor<4) params=uld_dev_params_defaults[minor]; else params=uld_dev_params_defaults[0]; chip_name[0]=0; p=dev_name; while(*p){ while(*p&&(*p!=' ')&&(*p!=':')) p++; while(*p&&((*p==' ')||(*p==':'))) p++; r=p; while(*r&&(*r!=' ')&&(*r!=':')&&((*r<'0')||(*r>'9'))) r++; switch (*p) { case 'p': params.port=strtol(r,NULL,0); break; case 'i': params.irq=strtol(r,NULL,0); break; case 'b': params.baud=strtol(r,NULL,0); break; case 'a': params.my_adr=strtol(r,NULL,0); break; case 'c': for(s=chip_name,p++;*p&&(*p!=':');p++,s++) *s=*p; *s=0; break; } } /* printf("port %d irq %d baud %d my_adr %d\n", params.port,params.irq,params.baud,params.my_adr); return NULL; */ return ul_drv_new(params.port,params.irq,params.baud,params.my_adr, chip_name[0]?chip_name:NULL,params.baudbase);}#else /* CONFIG_OC_UL_DRV_SYSLESS */int ul_drv_add_dev(ul_drv *udrv) { int minor; for(minor=0;minor<UL_MINORS;minor++) { if (ul_drv_arr[minor]==NULL) { ul_drv_arr[minor]=udrv; return 0; } } return -1;}#endif /* CONFIG_OC_UL_DRV_SYSLESS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -