1 /*******************************************************************
2 uLan Communication - uL_DRV - multiplatform uLan driver
4 ul_inlib.c - interface for driver compiled into library
5 linked directly with application
7 (C) Copyright 1996-2004 by Pavel Pisa - project originator
8 http://cmp.felk.cvut.cz/~pisa
9 (C) Copyright 1996-2004 PiKRON Ltd.
11 (C) Copyright 2002-2004 Petr Smolik
14 The uLan driver project can be used and distributed
15 in compliance with any of next licenses
16 - GPL - GNU Public License
17 See file COPYING for details.
18 - LGPL - Lesser GNU Public License
19 - MPL - Mozilla Public License
20 - and other licenses added by project originator
22 Code can be modified and re-distributed under any combination
23 of the above listed licenses. If contributor does not agree with
24 some of the licenses, he/she can delete appropriate line.
25 WARNING: if you delete all lines, you are not allowed to
26 distribute code or sources in any form.
27 *******************************************************************/
29 /*******************************************************************/
30 /* Interface for driver in library */
32 /* needs for UL_DEV_NAME */
33 #include <ul_lib/ul_fddir.h>
36 ul_drv *ul_drv_arr[UL_MINORS]={[0 ... UL_MINORS-1]=NULL};
38 void uld_check_timeout(void);
39 ul_drv *uld_try_open_new(const char *dev_name,
40 const char *options, int minor);
42 ul_opdata *ul_open(const char *dev_name, const char *options)
48 /*if(dev_name==NULL) { errno=ENODEV; return NULL;} */
49 if(dev_name==NULL) dev_name=UL_DEV_NAME;
50 if(!strncasecmp(dev_name,"COM",3)){ /* strnicmp */
52 if(*p<'1') { errno=ENODEV; return NULL;}
54 }else{ if(!strncmp(dev_name,"/dev/ulan",9)){
59 if(!*p||(*p==' ')||(*p==':')) minor=0;
61 if(*p<'0') { errno=ENODEV; return NULL;}
65 if (minor >= UL_MINORS) { errno=ENODEV; return NULL;}
66 #ifndef CONFIG_OC_UL_DRV_SYSLESS
67 if (!ul_drv_arr[minor]){
68 ul_drv_arr[minor]=uld_try_open_new(dev_name,options,minor);
70 #endif /* CONFIG_OC_UL_DRV_SYSLESS */
71 if (!ul_drv_arr[minor]){
72 errno=ENODEV; return NULL;
74 udrv=ul_drv_arr[minor];
76 if(!(opdata=MALLOC(sizeof(ul_opdata))))
80 memset(opdata,0,sizeof(ul_opdata));
81 /* opdata->file=file; */
82 opdata->magic=ULOP_MAGIC;
85 /* init_waitqueue_head(&opdata->wqrec); */
88 opdata->recchain=NULL;
89 opdata->filtchain=NULL;
90 { /* add us onto list of clients of udrv */
94 opptr=udrv->operators;
95 if(opptr) {opptr->opprew=opdata;opdata->opnext=opptr;};
97 udrv->operators=opdata;
104 int ul_close(ul_opdata* opdata)
106 ul_opchain *opmember;
108 if (opdata->message) ulan_freemsg(opdata);
109 { /* delete us from list of clients of udrv */
110 ul_drv *udrv=opdata->udrv;
114 if((opptr=opdata->opnext)) opptr->opprew=opdata->opprew;
115 if((opptr=opdata->opprew)) opptr->opnext=opdata->opnext;
116 else udrv->operators=opdata->opnext;
118 if(udrv->irq>0) ul_synchronize_irq(udrv->irq);
121 while((opmember=opdata->recchain))
123 del_from_opchain(&opdata->recchain,opmember);
124 if(opmember->message) ul_dec_ref_cnt(opmember->message);
127 while((opmember=opdata->filtchain))
129 del_from_opchain(&opdata->filtchain,opmember);
134 /* UL_PRINTF("uLan : printudrvbll\n"); */
135 /* printudrvbll(opdata->udrv); */
141 ssize_t ul_read(ul_opdata* opdata, void *buf, size_t count)
152 if(opdata->data.pos+count>UL_BLK_HEAD(opdata->data.head_blk).len)
153 count=UL_BLK_HEAD(opdata->data.head_blk).len-opdata->data.pos;
158 if(!ul_di_adjust(&opdata->data))
164 len=ul_di_atonce(&opdata->data);
166 memcpy(buf,ul_di_byte(&opdata->data),len);
167 ul_di_add(&opdata->data,len);
175 ssize_t ul_write(ul_opdata* opdata, const void *buf, size_t count)
190 while(!ul_di_adjust(&opdata->data))
192 if(!(blk=ul_alloc_blk(opdata->udrv)))
193 {count-=cn;cn=0;break;};
194 memset(UL_BLK_NDATA(blk),0,UL_BLK_SIZE);
195 opdata->data.blk->next=blk;
197 len=ul_di_atonce(&opdata->data);
199 memcpy(ul_di_byte(&opdata->data),buf,len);
200 ul_di_add(&opdata->data,len);
205 if(opdata->data.pos>UL_BLK_HEAD(opdata->data.head_blk).len)
206 UL_BLK_HEAD(opdata->data.head_blk).len=opdata->data.pos;
211 int ul_newmsg(ul_opdata* opdata,const ul_msginfo *msginfo)
213 ret=ulan_newmsg(opdata,msginfo);
214 if(ret<0) {errno=-ret;ret=-1;}
218 int ul_tailmsg(ul_opdata* opdata,const ul_msginfo *msginfo)
220 ret=ulan_tailmsg(opdata,msginfo);
221 if(ret<0) {errno=-ret;ret=-1;}
225 int ul_freemsg(ul_opdata* opdata)
227 ret=ulan_freemsg(opdata);
228 if(ret<0) {errno=-ret;ret=-1;}
232 int ul_acceptmsg(ul_opdata* opdata,ul_msginfo *msginfo)
234 ret=ulan_acceptmsg(opdata,msginfo);
235 if(ret<0) {errno=-ret;ret=-1;}
239 int ul_actailmsg(ul_opdata* opdata,ul_msginfo *msginfo)
241 ret=ulan_actailmsg(opdata,msginfo);
242 if(ret<0) {errno=-ret;ret=-1;}
246 int ul_addfilt(ul_opdata* opdata,const ul_msginfo *msginfo)
248 ret=ulan_addfilt(opdata,msginfo);
249 if(ret<0) {errno=-ret;ret=-1;}
253 int ul_abortmsg(ul_opdata* opdata)
255 ret=ulan_abortmsg(opdata);
256 if(ret<0) {errno=-ret;ret=-1;}
260 int ul_rewmsg(ul_opdata* opdata)
262 ret=ulan_rewmsg(opdata);
263 if(ret<0) {errno=-ret;ret=-1;}
267 int ul_inepoll(ul_opdata* opdata)
269 #if 1 /* Processing of arrived or processed messages */
271 if(uld_test_dfl(opdata->udrv,ASK_BOTTOM))
273 ulan_do_bh(opdata->udrv);
276 ret=ulan_inepoll(opdata);
278 if(ret<0) {errno=-ret;ret=-1;}
282 int ul_stroke(ul_opdata* opdata)
285 if(!opdata->udrv) return -ENODEV;
287 ulan_stroke(udrv, 1);
291 int ul_hwtest(ul_opdata* opdata, unsigned int fnc)
293 ret=ulan_hwtest(opdata,fnc);
294 if(ret<0) {errno=EINVAL;ret=-1;}
298 int ul_setmyadr(ul_opdata* opdata, int newadr)
301 ret=ulan_setmyadr(opdata, newadr);
302 if(ret<0) {errno=-ret;ret=-1;}
306 int ul_setidstr(ul_opdata* opdata, const char *idstr)
309 ret=ulan_setidstr(opdata, idstr);
310 if(ret<0) {errno=-ret;ret=-1;}
314 int ul_setbaudrate(ul_opdata* opdata, int baudrate)
317 ret=ulan_setbaudrate(opdata, baudrate);
318 if(ret<0) {errno=-ret;ret=-1;}
322 int ul_drv_debflg(ul_opdata* opdata,int debug_msk)
323 {uld_debug_flg=debug_msk;return uld_debug_flg;};
329 #define ULD_PRINTK_BUF_LEN 4096
330 char uld_printk_buf[ULD_PRINTK_BUF_LEN];
331 char *uld_printk_pin=uld_printk_buf;
332 char *uld_printk_pout=uld_printk_buf;
334 int uld_printk(const char *format, ...)
340 if(uld_debug_flg&LOG_MSK_DISABLE) return 0;
342 ret=vsprintf(buf,format,va);
346 rest=uld_printk_buf+ULD_PRINTK_BUF_LEN-uld_printk_pin;
348 memcpy(uld_printk_pin,buf,rest); len-=rest;
349 memcpy(uld_printk_buf,buf,len);
350 uld_printk_pin=uld_printk_buf+len;
352 memcpy(uld_printk_pin,buf,len); uld_printk_pin+=len;
358 void uld_printk_flush(void)
364 pout=uld_printk_pout;
366 if(pin==pout) return;
368 fwrite(pout,pin-pout,1,stderr); uld_printk_pout=pin;
370 fwrite(pout,uld_printk_buf+ULD_PRINTK_BUF_LEN-pout,1,stderr);
371 fwrite(uld_printk_buf,pin-uld_printk_buf,1,stderr);
377 #endif /* UL_LOG_ENABLE */
379 void uld_check_timeout(void)
383 #ifdef JIFFIES_FROM_GETTIMEOFDAY
384 struct timeval actual;
385 long int new_expires;
386 static long int old_expires;
387 #endif /* JIFFIES_FROM_GETTIMEOFDAY */
390 #endif /* __DJGPP__ */
391 #ifdef JIFFIES_FROM_GETTIMEOFDAY
392 gettimeofday(&actual,NULL);
393 uld_jiffies=actual.tv_usec+actual.tv_sec*ULD_HZ;
394 #endif /* JIFFIES_FROM_GETTIMEOFDAY */
395 for(i=0;i<UL_MINORS;i++)
397 if((udrv=ul_drv_arr[i])!=NULL)
399 if(uld_test_dfl(udrv,WDSCHED))
401 #ifdef JIFFIES_FROM_GETTIMEOFDAY
402 if(old_expires!=udrv->wd_timer_expires)
404 new_expires=uld_jiffies+ULD_HZ/18;
405 if((new_expires-udrv->wd_timer_expires)<0)
406 new_expires=udrv->wd_timer_expires;
407 old_expires=udrv->wd_timer_expires=new_expires;
409 LOG_IRQ("sched timeout %ld at time %ld\n",new_expires,uld_jiffies);
412 { static long int old_expires;
413 if(old_expires!=udrv->wd_timer_expires)
414 LOG_IRQ("sched timeout %ld at time %ld\n",
415 old_expires=udrv->wd_timer_expires,jiffies);
417 #endif /* JIFFIES_FROM_GETTIMEOFDAY */
418 if((udrv->wd_timer_expires-jiffies)<0)
419 { uld_clear_dfl(udrv,WDSCHED);
420 ulan_do_wd_timer((unsigned long)udrv);
421 /* uld_timeout(udrv); */
422 /* printudrvfncstack(udrv) */
425 /* Call bottom halves as needed */
426 if(uld_test_dfl(udrv,ASK_BOTTOM))
428 uld_clear_dfl(udrv,ASK_BOTTOM);
435 __save_flags(ul_irq_lock_flags);
436 if(!(ul_irq_lock_flags&0x0200))
437 { LOG_FATAL(KERN_CRIT "Somebody disables IRQ !!!!!\n");
445 #ifndef CONFIG_OC_UL_DRV_SYSLESS
447 typedef struct uld_dev_params{
455 static const uld_dev_params_t
456 uld_dev_params_defaults[4]={
457 {0x3f8,0x4,19200,2,0},
458 {0x2f8,0x3,19200,2,0},
459 {0x3e8,0x5,19200,2,0},
460 {0x2e8,0x5,19200,2,0}
463 ul_drv *uld_try_open_new(const char *dev_name,
464 const char *options, int minor)
466 uld_dev_params_t params;
470 if(minor<4) params=uld_dev_params_defaults[minor];
471 else params=uld_dev_params_defaults[0];
475 while(*p&&(*p!=' ')&&(*p!=':')) p++;
476 while(*p&&((*p==' ')||(*p==':'))) p++;
478 while(*r&&(*r!=' ')&&(*r!=':')&&((*r<'0')||(*r>'9'))) r++;
480 case 'p': params.port=strtol(r,NULL,0); break;
481 case 'i': params.irq=strtol(r,NULL,0); break;
482 case 'b': params.baud=strtol(r,NULL,0); break;
483 case 'a': params.my_adr=strtol(r,NULL,0); break;
484 case 'c': for(s=chip_name,p++;*p&&(*p!=':');p++,s++)
490 /* printf("port %d irq %d baud %d my_adr %d\n",
491 params.port,params.irq,params.baud,params.my_adr);
493 return ul_drv_new(params.port,params.irq,params.baud,params.my_adr,
494 chip_name[0]?chip_name:NULL,params.baudbase);
497 #else /* CONFIG_OC_UL_DRV_SYSLESS */
499 int ul_drv_add_dev(ul_drv *udrv)
502 for(minor=0;minor<UL_MINORS;minor++) {
503 if (ul_drv_arr[minor]==NULL) {
504 ul_drv_arr[minor]=udrv;
511 #endif /* CONFIG_OC_UL_DRV_SYSLESS */