]> rtime.felk.cvut.cz Git - can-usb1.git/blob - ulan/host/ul_drv/ul_drv/ul_inlib.c
Initializing repo
[can-usb1.git] / ulan / host / ul_drv / ul_drv / ul_inlib.c
1 /*******************************************************************
2   uLan Communication - uL_DRV - multiplatform uLan driver
3
4   ul_inlib.c    - interface for driver compiled into library
5                   linked directly with application
6
7   (C) Copyright 1996-2004 by Pavel Pisa - project originator
8         http://cmp.felk.cvut.cz/~pisa
9   (C) Copyright 1996-2004 PiKRON Ltd.
10         http://www.pikron.com
11   (C) Copyright 2002-2004 Petr Smolik
12   
13
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
21
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  *******************************************************************/
28
29 /*******************************************************************/
30 /* Interface for driver in library */
31
32 /* needs for UL_DEV_NAME */
33 #include <ul_lib/ul_fddir.h> 
34
35 #define UL_MINORS 4
36 ul_drv *ul_drv_arr[UL_MINORS]={[0 ... UL_MINORS-1]=NULL};
37
38 void uld_check_timeout(void);
39 ul_drv *uld_try_open_new(const char *dev_name,
40                          const char *options, int minor);
41
42 ul_opdata *ul_open(const char *dev_name, const char *options)
43 {
44   ul_drv *udrv;
45   ul_opdata *opdata;
46   unsigned int minor;
47   const char *p;
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 */
51     p=dev_name+3;
52     if(*p<'1') { errno=ENODEV; return NULL;}
53     minor=*p-'1';
54   }else{ if(!strncmp(dev_name,"/dev/ulan",9)){
55       p=dev_name+9;
56     }else {
57       p=dev_name;
58     }
59     if(!*p||(*p==' ')||(*p==':')) minor=0;
60     else{
61       if(*p<'0') { errno=ENODEV; return NULL;}
62       minor=*p-'0';
63     }
64   }
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);
69   }
70  #endif /* CONFIG_OC_UL_DRV_SYSLESS */
71   if (!ul_drv_arr[minor]){
72     errno=ENODEV; return NULL;
73   }
74   udrv=ul_drv_arr[minor];
75
76   if(!(opdata=MALLOC(sizeof(ul_opdata))))
77   { errno=ENOMEM;
78     return NULL;
79   };
80   memset(opdata,0,sizeof(ul_opdata));
81   /* opdata->file=file; */
82   opdata->magic=ULOP_MAGIC;
83   opdata->message=NULL;
84   opdata->udrv=udrv;
85   /* init_waitqueue_head(&opdata->wqrec); */
86   opdata->opprew=NULL;
87   opdata->opnext=NULL;
88   opdata->recchain=NULL;
89   opdata->filtchain=NULL;
90   { /* add us onto list of clients of udrv */
91     ul_opdata *opptr;
92     UL_DRV_LOCK_FINI
93     UL_DRV_LOCK;
94     opptr=udrv->operators;
95     if(opptr) {opptr->opprew=opdata;opdata->opnext=opptr;};
96     UL_MB();
97     udrv->operators=opdata;
98     UL_DRV_UNLOCK;
99   };
100   uld_printk_flush();
101   return opdata;
102 }
103
104 int ul_close(ul_opdata* opdata)
105 {
106   ul_opchain *opmember;
107
108   if (opdata->message) ulan_freemsg(opdata);
109   { /* delete us from list of clients of udrv */
110     ul_drv *udrv=opdata->udrv;
111     ul_opdata *opptr;
112     UL_DRV_LOCK_FINI
113     UL_DRV_LOCK;
114     if((opptr=opdata->opnext)) opptr->opprew=opdata->opprew;
115     if((opptr=opdata->opprew)) opptr->opnext=opdata->opnext;
116     else udrv->operators=opdata->opnext;
117     UL_DRV_UNLOCK;
118     if(udrv->irq>0) ul_synchronize_irq(udrv->irq);
119   };
120   schedule();
121   while((opmember=opdata->recchain))
122   {
123     del_from_opchain(&opdata->recchain,opmember);
124     if(opmember->message) ul_dec_ref_cnt(opmember->message);
125     FREE(opmember);
126   };
127   while((opmember=opdata->filtchain))
128   {
129     del_from_opchain(&opdata->filtchain,opmember);
130     FREE(opmember);
131   };
132   FREE(opdata);
133
134   /* UL_PRINTF("uLan : printudrvbll\n"); */
135   /* printudrvbll(opdata->udrv); */
136   
137   uld_printk_flush();
138   return 0;
139 }
140
141 ssize_t ul_read(ul_opdata* opdata, void *buf, size_t count)
142 {
143   int cn;
144   int len;
145
146   if(!opdata->message)
147   {
148     errno=ENOMSG;
149     return -1;
150   }
151
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;
154
155   cn=count;
156   while(cn>0)
157   {
158     if(!ul_di_adjust(&opdata->data))
159     {
160       memset(buf,0,cn);
161       cn=0;
162       break;
163     };
164     len=ul_di_atonce(&opdata->data);
165     if(len>cn) len=cn;
166     memcpy(buf,ul_di_byte(&opdata->data),len);
167     ul_di_add(&opdata->data,len);
168     buf+=len;
169     cn-=len;
170   };
171
172   return count-cn;
173 };
174
175 ssize_t ul_write(ul_opdata* opdata, const void *buf, size_t count)
176 {
177   int cn;
178   int len;
179   ul_mem_blk *blk;
180
181   if(!opdata->message)
182   {
183     errno=ENOMSG;
184     return -1;
185   }
186
187   cn=count;
188   while(cn>0)
189   {
190     while(!ul_di_adjust(&opdata->data))
191     {
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;
196     };
197     len=ul_di_atonce(&opdata->data);
198     if(len>cn) len=cn;
199     memcpy(ul_di_byte(&opdata->data),buf,len);
200     ul_di_add(&opdata->data,len);
201     buf+=len;
202     cn-=len;
203   };
204
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;
207
208   return count-cn;
209 };
210
211 int ul_newmsg(ul_opdata* opdata,const ul_msginfo *msginfo)
212 { int ret;
213   ret=ulan_newmsg(opdata,msginfo);
214   if(ret<0) {errno=-ret;ret=-1;}
215   return ret;
216 }
217
218 int ul_tailmsg(ul_opdata* opdata,const ul_msginfo *msginfo)
219 { int ret;
220   ret=ulan_tailmsg(opdata,msginfo);
221   if(ret<0) {errno=-ret;ret=-1;}
222   return ret;
223 }
224
225 int ul_freemsg(ul_opdata* opdata)
226 { int ret;
227   ret=ulan_freemsg(opdata);
228   if(ret<0) {errno=-ret;ret=-1;}
229   return ret;
230 }
231
232 int ul_acceptmsg(ul_opdata* opdata,ul_msginfo *msginfo)
233 { int ret;
234   ret=ulan_acceptmsg(opdata,msginfo);
235   if(ret<0) {errno=-ret;ret=-1;}
236   return ret;
237 }
238
239 int ul_actailmsg(ul_opdata* opdata,ul_msginfo *msginfo)
240 { int ret;
241   ret=ulan_actailmsg(opdata,msginfo);
242   if(ret<0) {errno=-ret;ret=-1;}
243   return ret;
244 }
245
246 int ul_addfilt(ul_opdata* opdata,const ul_msginfo *msginfo)
247 { int ret;
248   ret=ulan_addfilt(opdata,msginfo);
249   if(ret<0) {errno=-ret;ret=-1;}
250   return ret;
251 }
252
253 int ul_abortmsg(ul_opdata* opdata)
254 { int ret;
255   ret=ulan_abortmsg(opdata);
256   if(ret<0) {errno=-ret;ret=-1;}
257   return ret;
258 }
259
260 int ul_rewmsg(ul_opdata* opdata)
261 { int ret;
262   ret=ulan_rewmsg(opdata);
263   if(ret<0) {errno=-ret;ret=-1;}
264   return ret;
265 }
266
267 int ul_inepoll(ul_opdata* opdata)
268 { int ret;
269  #if 1 /* Processing of arrived or processed messages */
270   uld_check_timeout();
271   if(uld_test_dfl(opdata->udrv,ASK_BOTTOM))
272   {
273     ulan_do_bh(opdata->udrv);
274   }
275  #endif
276   ret=ulan_inepoll(opdata);
277   uld_printk_flush();
278   if(ret<0) {errno=-ret;ret=-1;}
279   return ret;
280 }
281
282 int ul_stroke(ul_opdata* opdata)
283 {
284   ul_drv *udrv;
285   if(!opdata->udrv) return -ENODEV;
286   udrv=opdata->udrv;
287   ulan_stroke(udrv, 1);
288   return 0;
289 }
290
291 int ul_hwtest(ul_opdata* opdata, unsigned int fnc)
292 { int ret;
293   ret=ulan_hwtest(opdata,fnc);
294   if(ret<0) {errno=EINVAL;ret=-1;}
295   return ret;
296 }
297
298 int ul_setmyadr(ul_opdata* opdata, int newadr)
299 {
300   int ret;
301   ret=ulan_setmyadr(opdata, newadr);
302   if(ret<0) {errno=-ret;ret=-1;}
303   return ret;
304 }
305
306 int ul_setidstr(ul_opdata* opdata, const char *idstr)
307 {
308   int ret;
309   ret=ulan_setidstr(opdata, idstr);
310   if(ret<0) {errno=-ret;ret=-1;}
311   return ret;
312 }
313
314 int ul_setbaudrate(ul_opdata* opdata, int baudrate)
315 {
316   int ret;
317   ret=ulan_setbaudrate(opdata, baudrate);
318   if(ret<0) {errno=-ret;ret=-1;}
319   return ret;
320 }
321
322 int ul_drv_debflg(ul_opdata* opdata,int debug_msk)
323   {uld_debug_flg=debug_msk;return uld_debug_flg;};
324
325 #ifdef UL_LOG_ENABLE
326
327 #include <stdarg.h>
328
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;
333
334 int uld_printk(const char *format, ...)
335 {
336   int len,rest,ret;
337   char buf[255];
338   va_list va=0;
339   UL_IRQ_LOCK_FINI
340   if(uld_debug_flg&LOG_MSK_DISABLE) return 0;
341   va_start(va,format);
342   ret=vsprintf(buf,format,va);
343   va_end(va);
344   len=strlen(buf);
345   UL_IRQ_LOCK;
346   rest=uld_printk_buf+ULD_PRINTK_BUF_LEN-uld_printk_pin;
347   if(len>=rest){
348     memcpy(uld_printk_pin,buf,rest); len-=rest;
349     memcpy(uld_printk_buf,buf,len);
350     uld_printk_pin=uld_printk_buf+len;
351   }else{
352     memcpy(uld_printk_pin,buf,len); uld_printk_pin+=len;
353   }
354   UL_IRQ_UNLOCK;
355   return ret;
356 }
357
358 void uld_printk_flush(void)
359 {
360   char *pout,*pin;
361   UL_IRQ_LOCK_FINI
362   UL_IRQ_LOCK;
363   pin=uld_printk_pin;
364   pout=uld_printk_pout;
365   UL_IRQ_UNLOCK;
366   if(pin==pout) return;
367   if(pin>pout){
368     fwrite(pout,pin-pout,1,stderr); uld_printk_pout=pin;
369   }else{
370     fwrite(pout,uld_printk_buf+ULD_PRINTK_BUF_LEN-pout,1,stderr);
371     fwrite(uld_printk_buf,pin-uld_printk_buf,1,stderr);
372     uld_printk_pout=pin;
373   }
374   fflush(stderr);
375 }
376
377 #endif /* UL_LOG_ENABLE */
378
379 void uld_check_timeout(void)
380 {
381   int i;
382   ul_drv *udrv;
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 */
388  #ifdef __DJGPP__
389   UL_DRV_LOCK_FINI
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++)
396   {
397     if((udrv=ul_drv_arr[i])!=NULL)
398     {
399       if(uld_test_dfl(udrv,WDSCHED))
400       { 
401        #ifdef JIFFIES_FROM_GETTIMEOFDAY
402         if(old_expires!=udrv->wd_timer_expires)
403         { UL_DRV_LOCK;
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;
408           UL_DRV_UNLOCK;
409           LOG_IRQ("sched timeout %ld at time %ld\n",new_expires,uld_jiffies);
410         }
411        #elif 1
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);
416         }
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) */
423         }
424       }
425       /* Call bottom halves as needed */
426       if(uld_test_dfl(udrv,ASK_BOTTOM))
427       {
428         uld_clear_dfl(udrv,ASK_BOTTOM);
429         ulan_do_bh(udrv);
430       }
431     }
432   }
433  #ifdef __DJGPP__
434   #if 1
435   __save_flags(ul_irq_lock_flags);
436   if(!(ul_irq_lock_flags&0x0200))
437   { LOG_FATAL(KERN_CRIT "Somebody disables IRQ !!!!!\n");
438     __sti();
439   }
440   #endif
441   __dpmi_yield();
442  #endif
443 }
444
445 #ifndef CONFIG_OC_UL_DRV_SYSLESS
446
447 typedef struct uld_dev_params{
448   int  port;
449   int  irq;
450   int  baud;
451   int  my_adr;
452   long baudbase;
453 }uld_dev_params_t;
454
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}
461   };
462
463 ul_drv *uld_try_open_new(const char *dev_name,
464                          const char *options, int minor)
465 {
466   uld_dev_params_t params;
467   const char *p,*r;
468   char *s;
469   char chip_name[16];
470   if(minor<4) params=uld_dev_params_defaults[minor];
471   else  params=uld_dev_params_defaults[0];
472   chip_name[0]=0;
473   p=dev_name;
474   while(*p){
475     while(*p&&(*p!=' ')&&(*p!=':')) p++;
476     while(*p&&((*p==' ')||(*p==':'))) p++;
477     r=p;
478     while(*r&&(*r!=' ')&&(*r!=':')&&((*r<'0')||(*r>'9'))) r++;
479     switch (*p) {
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++)
485                    *s=*p;
486                 *s=0;
487                 break;
488     }
489   }
490   /* printf("port %d irq %d baud %d my_adr %d\n",
491     params.port,params.irq,params.baud,params.my_adr);
492   return NULL; */
493   return ul_drv_new(params.port,params.irq,params.baud,params.my_adr,
494                     chip_name[0]?chip_name:NULL,params.baudbase);
495 }
496
497 #else /* CONFIG_OC_UL_DRV_SYSLESS */
498
499 int ul_drv_add_dev(ul_drv *udrv) 
500 {
501   int minor;
502   for(minor=0;minor<UL_MINORS;minor++) {
503     if (ul_drv_arr[minor]==NULL) {
504       ul_drv_arr[minor]=udrv;
505       return 0;
506     }
507   }
508   return -1;
509 }
510
511 #endif /* CONFIG_OC_UL_DRV_SYSLESS */