rtdm/module.c
changeset 2054 3417bbc4ad2f
child 2055 d246ab6b50d2
equal deleted inserted replaced
2053:cceb9aacf4a6 2054:3417bbc4ad2f
       
     1 /******************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  ec_rtdm.c	Copyright (C) 2009-2010  Moehwald GmbH B.Benner
       
     6  *                            2011       IgH Andreas Stewering-Bone
       
     7  *								  
       
     8  *  This file is used for Prisma RT to interface to EtherCAT devices
       
     9  *								  
       
    10  *  This file is part of ethercatrtdm interface to IgH EtherCAT master 
       
    11  *  
       
    12  *  The Moehwald ec_rtdm interface is free software; you can
       
    13  *  redistribute it and/or modify it under the terms of the GNU Lesser General
       
    14  *  Public License as published by the Free Software Foundation; version 2.1
       
    15  *  of the License.
       
    16  *
       
    17  *  The IgH EtherCAT master userspace library is distributed in the hope that
       
    18  *  it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    19  *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    20  *  GNU Lesser General Public License for more details.
       
    21  *
       
    22  *  You should have received a copy of the GNU Lesser General Public License
       
    23  *  along with the IgH EtherCAT master userspace library. If not, see
       
    24  *  <http://www.gnu.org/licenses/>.
       
    25  *  
       
    26  *  The license mentioned above concerns the source code only. Using the
       
    27  *  EtherCAT technology and brand is only permitted in compliance with the
       
    28  *  industrial property and similar rights of Beckhoff Automation GmbH.
       
    29  *
       
    30  *****************************************************************************/
       
    31 
       
    32 #include <linux/module.h>
       
    33 #include <linux/mman.h>
       
    34 #include <rtdm/rtdm_driver.h>
       
    35 #include <native/task.h>
       
    36 #include <native/sem.h>
       
    37 #include <native/mutex.h>
       
    38 #include <native/timer.h>
       
    39 
       
    40 #include "../include/ecrt.h"
       
    41 #include "../include/ec_rtdm.h"
       
    42 
       
    43 #define EC_RTDM_MAX_MASTERS 5 /**< Maximum number of masters. */
       
    44 
       
    45 #define EC_RTDM_GINFO(fmt, args...) \
       
    46     printk(KERN_INFO "EtherCATrtdm: " fmt,  ##args)
       
    47 
       
    48 #define EC_RTDM_GERR(fmt, args...) \
       
    49     printk(KERN_ERR "EtherCATrtdm ERROR: " fmt, ##args)
       
    50 
       
    51 #define EC_RTDM_GWARN(fmt, args...) \
       
    52     printk(KERN_WARNING "EtherCATrtdm WARNING: " fmt, ##args)
       
    53 
       
    54 
       
    55 #define EC_RTDM_INFO(devno, fmt, args...) \
       
    56     printk(KERN_INFO "EtherCATrtdm %u: " fmt, devno, ##args)
       
    57 
       
    58 #define EC_RTDM_ERR(devno, fmt, args...) \
       
    59     printk(KERN_ERR "EtherCATrtdm %u ERROR: " fmt, devno, ##args)
       
    60 
       
    61 #define EC_RTDM_WARN(devno, fmt, args...) \
       
    62     printk(KERN_WARNING "EtherCATrtdm %u WARNING: " fmt, devno, ##args)
       
    63 
       
    64 
       
    65 
       
    66 
       
    67 typedef struct _EC_RTDM_DRV_STRUCT {
       
    68     unsigned int	    isattached;
       
    69     ec_master_t *	    master;
       
    70     ec_domain_t *	    domain;				   
       
    71     RT_MUTEX                masterlock;
       
    72     unsigned int	    sendcnt;
       
    73     unsigned int	    reccnt;
       
    74     unsigned int	    sendcntlv;
       
    75     unsigned int	    reccntlv;
       
    76     char                    mutexname[64];
       
    77     unsigned int            masterno;
       
    78 } EC_RTDM_DRV_STRUCT;
       
    79 
       
    80 
       
    81 static EC_RTDM_DRV_STRUCT ec_rtdm_masterintf[EC_RTDM_MAX_MASTERS];
       
    82 
       
    83 
       
    84 /* import from ethercat */
       
    85 ec_master_t *ecrt_attach_master(unsigned int master_index /**< Index of the master to request. */
       
    86         );
       
    87 
       
    88 // driver context struct: used for storing various information
       
    89 typedef struct _EC_RTDM_DRV_CONTEXT {
       
    90     int                       dev_id;
       
    91     EC_RTDM_DRV_STRUCT*  pdrvstruc;
       
    92 } EC_RTDM_DRV_CONTEXT;
       
    93 
       
    94 
       
    95 
       
    96 /**********************************************************/
       
    97 /*            Utilities                                   */
       
    98 /**********************************************************/
       
    99 
       
   100 static int _atoi(const char* text)
       
   101 {
       
   102   char  b;
       
   103   int wd=-1;
       
   104   int nfak=1;
       
   105 
       
   106   wd=0;
       
   107 
       
   108   while ((*text==' ') || (*text=='\t')) text++;
       
   109   if (*text=='-') 
       
   110     {
       
   111       nfak=-1;
       
   112 	  text++;
       
   113     }
       
   114   if (*text=='+') 
       
   115     {
       
   116       text++;
       
   117     }
       
   118   while (*text!=0)
       
   119     {
       
   120  	  b = *text;
       
   121 
       
   122 	  if ( (b>='0') && (b<='9') )
       
   123 		{
       
   124 		   b=b-'0';
       
   125 		   wd=wd*10+b;
       
   126 		}
       
   127 	  text++;
       
   128 	}
       
   129   return (nfak*wd);
       
   130 }
       
   131 
       
   132 
       
   133 /**********************************************************/
       
   134 /*            DRIVER sendcallback                         */
       
   135 /**********************************************************/
       
   136 void send_callback(void *cb_data)
       
   137 {
       
   138     EC_RTDM_DRV_STRUCT * pdrvstruc;
       
   139     
       
   140     pdrvstruc = (EC_RTDM_DRV_STRUCT*)cb_data;
       
   141     if (pdrvstruc->master)
       
   142         {
       
   143             rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   144             ecrt_master_send_ext(pdrvstruc->master);
       
   145             rt_mutex_release(&pdrvstruc->masterlock);
       
   146       }
       
   147 }
       
   148 
       
   149 /*****************************************************************************/
       
   150 
       
   151 void receive_callback(void *cb_data)
       
   152 {
       
   153     EC_RTDM_DRV_STRUCT * pdrvstruc;
       
   154 
       
   155     pdrvstruc = (EC_RTDM_DRV_STRUCT*)cb_data;
       
   156     if (pdrvstruc->master)
       
   157       {
       
   158           rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   159           ecrt_master_receive(pdrvstruc->master);
       
   160           rt_mutex_release(&pdrvstruc->masterlock);      
       
   161     }
       
   162 }
       
   163 
       
   164 void receive_process(EC_RTDM_DRV_STRUCT * pdrvstruc)
       
   165 {
       
   166     if (pdrvstruc->master)
       
   167         {
       
   168             rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   169             ecrt_master_receive(pdrvstruc->master);
       
   170             ecrt_domain_process(pdrvstruc->domain);
       
   171             pdrvstruc->reccnt++;
       
   172             rt_mutex_release(&pdrvstruc->masterlock);
       
   173       }
       
   174 }
       
   175 
       
   176 void send_process(EC_RTDM_DRV_STRUCT * pdrvstruc)
       
   177 {
       
   178   if (pdrvstruc->master)
       
   179       {
       
   180          rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   181          ecrt_domain_queue(pdrvstruc->domain);
       
   182          ecrt_master_send(pdrvstruc->master);
       
   183          pdrvstruc->sendcnt++;
       
   184          rt_mutex_release(&pdrvstruc->masterlock);
       
   185       }
       
   186 }  
       
   187 
       
   188 void detach_master(EC_RTDM_DRV_STRUCT * pdrvstruc)
       
   189 {
       
   190 
       
   191   if (pdrvstruc->isattached)
       
   192       {
       
   193           EC_RTDM_INFO(pdrvstruc->masterno,"reseting callbacks!\n");
       
   194           ecrt_master_callbacks(pdrvstruc->master,NULL,NULL,NULL);
       
   195           EC_RTDM_INFO(pdrvstruc->masterno,"deleting mutex!\n");
       
   196           rt_mutex_delete(&pdrvstruc->masterlock);
       
   197           pdrvstruc->master = NULL;
       
   198           pdrvstruc->isattached=0;
       
   199           EC_RTDM_INFO(pdrvstruc->masterno,"master detach done!\n");
       
   200       }
       
   201 }
       
   202 
       
   203 
       
   204 
       
   205 
       
   206 /**********************************************************/
       
   207 /*            DRIVER OPEN                                 */
       
   208 /**********************************************************/
       
   209 int ec_rtdm_open_rt(struct rtdm_dev_context    *context,
       
   210                  rtdm_user_info_t           *user_info,
       
   211                  int                        oflags)
       
   212 {
       
   213     EC_RTDM_DRV_CONTEXT* my_context;
       
   214     EC_RTDM_DRV_STRUCT * pdrvstruc;
       
   215     const char * p;
       
   216     int dev_no;
       
   217     unsigned int namelen;
       
   218 
       
   219     //int ret;
       
   220     int dev_id;
       
   221 
       
   222     // get the context for our driver - used to store driver info
       
   223     my_context = (EC_RTDM_DRV_CONTEXT*)context->dev_private;
       
   224 
       
   225     dev_no = -1;
       
   226     namelen   = strlen(context->device->driver_name);
       
   227     p = &context->device->driver_name[namelen-1];
       
   228     if (p!=&context->device->driver_name[0])
       
   229       {
       
   230 	  while ((*p>='0') && (*p<='9')) 
       
   231 	    {
       
   232 	       p--;
       
   233 	       if (p==&context->device->driver_name[0]) break;
       
   234    	    }
       
   235 	  dev_no=_atoi(p);
       
   236 	  if  ((dev_no!=-1) && (dev_no<EC_RTDM_MAX_MASTERS))
       
   237 	    { 
       
   238 		dev_id    = context->device->device_id;
       
   239     		pdrvstruc = (EC_RTDM_DRV_STRUCT*)&ec_rtdm_masterintf[dev_no];
       
   240 
       
   241     		my_context->dev_id         = dev_id;
       
   242     		my_context->pdrvstruc      = pdrvstruc;
       
   243 		 
       
   244     		// enable interrupt in RTDM
       
   245     		return 0;	
       
   246 	    }	
       
   247       }
       
   248    EC_RTDM_GERR("open - Cannot detect master device no\n");
       
   249    return -EFAULT;
       
   250 }
       
   251 
       
   252 /**********************************************************/
       
   253 /*            DRIVER CLOSE                                */
       
   254 /**********************************************************/
       
   255 int ec_rtdm_close_rt(struct rtdm_dev_context   *context,
       
   256                   rtdm_user_info_t          *user_info)
       
   257 {
       
   258     EC_RTDM_DRV_CONTEXT* my_context;
       
   259     EC_RTDM_DRV_STRUCT * pdrvstruc;
       
   260 
       
   261     // get the context
       
   262     my_context = (EC_RTDM_DRV_CONTEXT*)context->dev_private;
       
   263 
       
   264     pdrvstruc =  my_context->pdrvstruc;
       
   265     EC_RTDM_INFO(pdrvstruc->masterno,"close called!\n");
       
   266     detach_master(pdrvstruc);
       
   267     return 0;
       
   268 	
       
   269 }
       
   270 
       
   271 /**********************************************************/
       
   272 /*            DRIVER IOCTL                                */
       
   273 /**********************************************************/
       
   274 int ec_rtdm_ioctl_rt(struct rtdm_dev_context   *context,
       
   275                   rtdm_user_info_t          *user_info,
       
   276                   int                       request,
       
   277                   void                      *arg)
       
   278 {
       
   279     EC_RTDM_DRV_CONTEXT* my_context;
       
   280     EC_RTDM_DRV_STRUCT * pdrvstruc;
       
   281     int ret;
       
   282     unsigned int l_ioctlvalue[]={0,0,0,0,0,0,0,0};
       
   283     ec_domain_state_t ds;
       
   284     ec_master_state_t ms;
       
   285     uint64_t app_time;
       
   286 
       
   287 
       
   288     ret = 0;
       
   289 
       
   290     // get the context
       
   291     my_context = (EC_RTDM_DRV_CONTEXT*)context->dev_private;
       
   292     pdrvstruc =  my_context->pdrvstruc;
       
   293     
       
   294     switch (request) {
       
   295     case EC_RTDM_MASTERSTATE:
       
   296     {
       
   297 		if (!pdrvstruc->isattached)
       
   298             {
       
   299                 return -EFAULT;
       
   300             }
       
   301 		if (pdrvstruc->master)
       
   302             {
       
   303                 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   304                 
       
   305                 ecrt_master_state(pdrvstruc->master, &ms);
       
   306                 
       
   307                 rt_mutex_release(&pdrvstruc->masterlock);
       
   308                 
       
   309             }
       
   310         if  (rtdm_rw_user_ok(user_info, arg, sizeof(ms)))
       
   311             {
       
   312                 // copy data to user
       
   313                 if (rtdm_copy_to_user(user_info, arg, &ms,sizeof(ms)))
       
   314                     {
       
   315                         return -EFAULT;
       
   316                     }
       
   317             }
       
   318         
       
   319     }
       
   320     break;
       
   321     case EC_RTDM_DOMAINSTATE:
       
   322     {
       
   323 		if (!pdrvstruc->isattached)
       
   324             {
       
   325                 return -EFAULT;
       
   326             }
       
   327 	   	if (pdrvstruc->domain)
       
   328             {
       
   329                 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   330                 
       
   331                 ecrt_domain_state(pdrvstruc->domain, &ds);
       
   332                 
       
   333                 rt_mutex_release(&pdrvstruc->masterlock);
       
   334             }
       
   335         if  (rtdm_rw_user_ok(user_info, arg, sizeof(ds)))
       
   336             {
       
   337                 // copy data to user
       
   338                 if (rtdm_copy_to_user(user_info, arg, &ds,sizeof(ds)))
       
   339                     {
       
   340                         return -EFAULT;
       
   341                     }
       
   342             }
       
   343     }
       
   344     break;
       
   345     
       
   346     case EC_RTDM_MSTRRECEIVE:
       
   347     {	       
       
   348         if (pdrvstruc->isattached)
       
   349             {
       
   350                 receive_process(pdrvstruc);
       
   351             }
       
   352     }
       
   353     break;
       
   354     case EC_RTDM_MSTRSEND:
       
   355     {
       
   356         
       
   357         if (pdrvstruc->isattached)
       
   358             {
       
   359                 send_process(pdrvstruc);
       
   360             }
       
   361     }
       
   362     break;
       
   363     case EC_RTDM_MASTER_APP_TIME:
       
   364     {
       
   365 		if (!pdrvstruc->isattached)
       
   366             {
       
   367                 return -EFAULT;
       
   368             }
       
   369         if  (rtdm_rw_user_ok(user_info, arg, sizeof(app_time)))
       
   370             {
       
   371                 // copy data from user
       
   372                 if (rtdm_copy_from_user(user_info, &app_time, arg, sizeof(app_time)))
       
   373                     {
       
   374                         return -EFAULT;
       
   375                     }
       
   376                 if (pdrvstruc->master)
       
   377                     {
       
   378                         rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   379                         
       
   380                         ecrt_master_application_time(pdrvstruc->master, app_time);
       
   381                         
       
   382                         rt_mutex_release(&pdrvstruc->masterlock);
       
   383                         
       
   384                     }
       
   385             }
       
   386     }
       
   387     break;
       
   388     case EC_RTDM_SYNC_REF_CLOCK:
       
   389     {
       
   390 		if (!pdrvstruc->isattached)
       
   391             {
       
   392                 return -EFAULT;
       
   393             }
       
   394         if (pdrvstruc->master)
       
   395             {
       
   396                 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   397                 
       
   398                 ecrt_master_sync_reference_clock(pdrvstruc->master);
       
   399                 
       
   400                 rt_mutex_release(&pdrvstruc->masterlock);
       
   401                 
       
   402             }
       
   403     }
       
   404     break;
       
   405     case EC_RTDM_SYNC_SLAVE_CLOCK:
       
   406     {
       
   407 		if (!pdrvstruc->isattached)
       
   408             {
       
   409                 return -EFAULT;
       
   410             }
       
   411         if (pdrvstruc->master)
       
   412             {
       
   413                 rt_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
       
   414                 
       
   415                 ecrt_master_sync_slave_clocks(pdrvstruc->master);
       
   416                 
       
   417                 rt_mutex_release(&pdrvstruc->masterlock);
       
   418                 
       
   419             }
       
   420     }
       
   421     break;
       
   422     case EC_RTDM_MSTRATTACH:
       
   423     {
       
   424         unsigned int mstridx;
       
   425         
       
   426         mstridx = 0;
       
   427         ret = 0;
       
   428         
       
   429         EC_RTDM_INFO(pdrvstruc->masterno,"Master attach start!\n");
       
   430         if (user_info) 
       
   431             {
       
   432                 if (rtdm_read_user_ok(user_info, arg, sizeof(unsigned int)))
       
   433                     {
       
   434                         if (rtdm_copy_from_user(user_info, &l_ioctlvalue[0], arg,sizeof(unsigned int))==0)
       
   435                             {
       
   436                                 pdrvstruc->domain = (ec_domain_t*)l_ioctlvalue[0];
       
   437                             }
       
   438                         else
       
   439                             {
       
   440                                 EC_RTDM_ERR(pdrvstruc->masterno,"copy user param failed!\n");
       
   441                                 ret=-EFAULT;
       
   442                             }		
       
   443                     }
       
   444                 else
       
   445                     { 
       
   446                         EC_RTDM_ERR(pdrvstruc->masterno,"user parameter domain missing!\n");
       
   447                         ret=-EFAULT;
       
   448                     }	
       
   449             }
       
   450 		if (ret!=0) 
       
   451             {
       
   452                 return ret;
       
   453             }
       
   454         
       
   455 		if ( (pdrvstruc->master) && (pdrvstruc->isattached))
       
   456             // master is allready attached
       
   457             {
       
   458                 // master is allready attached
       
   459                 EC_RTDM_ERR(pdrvstruc->masterno,"Master is allready attached!\n");
       
   460                 ret = -EFAULT;
       
   461             }
       
   462 	    else
       
   463             {
       
   464                 //mstr=ecrt_request_master(0);
       
   465                 mstridx = pdrvstruc->masterno;
       
   466 	        	
       
   467                 pdrvstruc->master=ecrt_attach_master(mstridx);
       
   468                 
       
   469                 if (pdrvstruc->master)
       
   470                     {
       
   471                         // Ok
       
   472                         EC_RTDM_INFO(pdrvstruc->masterno,"Master searching for domain!\n");
       
   473                         pdrvstruc->domain = ecrt_master_find_domain(pdrvstruc->master,l_ioctlvalue[0]);
       
   474                         if (!pdrvstruc->domain)
       
   475                             {
       
   476                                 //
       
   477                                 EC_RTDM_ERR(pdrvstruc->masterno,"Cannot find domain from index %u!\n",l_ioctlvalue[0]);
       
   478                                 ret = -EFAULT;
       
   479                             }
       
   480                         else
       
   481                             {
       
   482                                 
       
   483                                 // set device name
       
   484                                 snprintf(&pdrvstruc->mutexname[0],sizeof(pdrvstruc->mutexname)-1,"ETHrtdmLOCK%d",pdrvstruc->masterno);
       
   485                                 EC_RTDM_INFO(pdrvstruc->masterno,"Creating Master mutex %s!\n",&pdrvstruc->mutexname[0]);
       
   486                                 rt_mutex_create(&pdrvstruc->masterlock,&pdrvstruc->mutexname[0]);
       
   487                                 //ecrt_release_master(mstr);
       
   488                                 ecrt_master_callbacks(pdrvstruc->master, send_callback, receive_callback, pdrvstruc);
       
   489                                 EC_RTDM_INFO(pdrvstruc->masterno,"MSTR ATTACH done domain=%u!\n",(unsigned int)pdrvstruc->domain);
       
   490                                 pdrvstruc->isattached=1;
       
   491                                 ret = 0;
       
   492                             }
       
   493                         
       
   494                     }
       
   495                 else
       
   496                     {
       
   497                         EC_RTDM_ERR(pdrvstruc->masterno,"Master attach failed!\n");
       
   498                         pdrvstruc->master = NULL;
       
   499                         ret = -EFAULT;
       
   500                     }
       
   501             }
       
   502     }
       
   503     break;
       
   504     default:
       
   505         ret = -ENOTTY;
       
   506     }
       
   507     return ret;
       
   508 }
       
   509 
       
   510 
       
   511 /**********************************************************/
       
   512 /*            DRIVER READ                                 */
       
   513 /**********************************************************/
       
   514 int ec_rtdm_read_rt(struct rtdm_dev_context *context,
       
   515                     rtdm_user_info_t *user_info, void *buf, size_t nbyte)
       
   516 {
       
   517     int                     ret;
       
   518 #if defined(USE_THIS)
       
   519     EC_RTDM_DRV_CONTEXT* my_context;
       
   520     char                    *out_pos;
       
   521     int                     dev_id;
       
   522     rtdm_toseq_t            timeout_seq;
       
   523     int                     ret;
       
   524 
       
   525     out_pos = (char *)buf;
       
   526     
       
   527     my_context = (EC_RTDM_DRV_CONTEXT*)context->dev_private;
       
   528     
       
   529     // zero bytes requested ? return!
       
   530     if (nbyte == 0)
       
   531         return 0;
       
   532 
       
   533     // check if R/W actions to user-space are allowed
       
   534     if (user_info && !rtdm_rw_user_ok(user_info, buf, nbyte))
       
   535         return -EFAULT;
       
   536 
       
   537     dev_id = my_context->dev_id;
       
   538 
       
   539     // in case we need to check if reading is allowed (locking)
       
   540 /*    if (test_and_set_bit(0, &ctx->in_lock))
       
   541         return -EBUSY;
       
   542 */
       
   543 /*  // if we need to do some stuff with preemption disabled:
       
   544     rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);
       
   545     // stuff here
       
   546     rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx);
       
   547 */
       
   548 
       
   549     // wait: if ctx->timeout = 0, it will block infintely until
       
   550     //       rtdm_event_signal(&ctx->irq_event); is called from our
       
   551     //       interrupt routine
       
   552     //ret = rtdm_event_timedwait(&ctx->irq_event, ctx->timeout, &timeout_seq);
       
   553 
       
   554     // now write the requested stuff to user-space
       
   555     if (rtdm_copy_to_user(user_info, out_pos,
       
   556                           dummy_buffer, BUFSIZE) != 0) {
       
   557         ret = -EFAULT;
       
   558     } else {
       
   559         ret = BUFSIZE;
       
   560     }
       
   561 #else
       
   562     ret = -EFAULT;
       
   563 #endif
       
   564     return ret;
       
   565 }
       
   566 
       
   567 /**********************************************************/
       
   568 /*            DRIVER WRITE                                */
       
   569 /**********************************************************/
       
   570 int ec_rtdm_write_rt(struct rtdm_dev_context *context,
       
   571                    rtdm_user_info_t *user_info,
       
   572                    const void *buf, size_t nbyte)
       
   573 {
       
   574     int                     ret;
       
   575 
       
   576 #if defined(USE_THIS)
       
   577     int                     dev_id;
       
   578     char                    *in_pos = (char *)buf;
       
   579 
       
   580     EC_RTDM_DRV_CONTEXT* my_context;
       
   581     
       
   582 
       
   583     my_context = (EC_RTDM_DRV_CONTEXT*)context->dev_private;
       
   584     
       
   585 
       
   586     if (nbyte == 0)
       
   587         return 0;
       
   588     if (user_info && !rtdm_read_user_ok(user_info, buf, nbyte))
       
   589         return -EFAULT;
       
   590 
       
   591     dev_id = my_context->dev_id;
       
   592 
       
   593     if (rtdm_copy_from_user(user_info, dummy_buffer,
       
   594                              in_pos, BUFSIZE) != 0) {
       
   595         ret = -EFAULT;
       
   596     } else {
       
   597        ret = BUFSIZE;
       
   598     }
       
   599 #else
       
   600     ret = -EFAULT;
       
   601 #endif
       
   602     // used when it is atomic
       
   603 //   rtdm_mutex_unlock(&ctx->out_lock);
       
   604     return ret;
       
   605 }
       
   606 
       
   607 /**********************************************************/
       
   608 /*            DRIVER OPERATIONS                           */
       
   609 /**********************************************************/
       
   610 
       
   611 // Template
       
   612 
       
   613 static struct rtdm_device ec_rtdm_device_t = {
       
   614     struct_version:     RTDM_DEVICE_STRUCT_VER,
       
   615 
       
   616     device_flags:       RTDM_NAMED_DEVICE,
       
   617     context_size:   	sizeof(EC_RTDM_DRV_CONTEXT),
       
   618     device_name:        EC_RTDM_DEV_FILE_NAME,
       
   619 
       
   620 /* open and close functions are not real-time safe due kmalloc
       
   621    and kfree. If you do not use kmalloc and kfree, and you made
       
   622    sure that there is no syscall in the open/close handler, you
       
   623    can declare the open_rt and close_rt handler.
       
   624 */
       
   625     open_rt:            NULL,
       
   626     open_nrt:           ec_rtdm_open_rt,
       
   627 
       
   628     ops: {
       
   629         close_rt:       NULL,
       
   630         close_nrt:      ec_rtdm_close_rt,
       
   631 
       
   632         ioctl_rt:       ec_rtdm_ioctl_rt,
       
   633         ioctl_nrt:      ec_rtdm_ioctl_rt, // rtdm_mmap_to_user is not RT safe
       
   634 
       
   635         read_rt:        ec_rtdm_read_rt,
       
   636         read_nrt:       NULL,
       
   637 
       
   638         write_rt:       ec_rtdm_write_rt,
       
   639         write_nrt:      NULL,
       
   640 
       
   641         recvmsg_rt:     NULL,
       
   642         recvmsg_nrt:    NULL,
       
   643 
       
   644         sendmsg_rt:     NULL,
       
   645         sendmsg_nrt:    NULL,
       
   646     },
       
   647 
       
   648     device_class:       RTDM_CLASS_EXPERIMENTAL,
       
   649     device_sub_class:   222,
       
   650     driver_name:        EC_RTDM_DEV_FILE_NAME,
       
   651     driver_version:     RTDM_DRIVER_VER(1,0,1),
       
   652     peripheral_name:    EC_RTDM_DEV_FILE_NAME,
       
   653     provider_name:      "Moehwald GmbH - Bosch Group",
       
   654 //    proc_name:          ethcatrtdm_device.device_name,
       
   655 };
       
   656 
       
   657 
       
   658 static struct rtdm_device ec_rtdm_devices[EC_RTDM_MAX_MASTERS];
       
   659 
       
   660 
       
   661 /**********************************************************/
       
   662 /*            INIT DRIVER                                 */
       
   663 /**********************************************************/
       
   664 int init_module(void)
       
   665 {
       
   666 	unsigned int i;
       
   667     int ret;
       
   668 
       
   669     ret = 0; 	
       
   670     
       
   671     EC_RTDM_GINFO("Initlializing EtherCAT RTDM Interface to Igh EtherCAT Master\n");
       
   672     memset(&ec_rtdm_masterintf[0],0,sizeof(ec_rtdm_masterintf));
       
   673     for (i=0;( (i<EC_RTDM_MAX_MASTERS) && (ret==0) ) ;i++)
       
   674       {	 
       
   675     	// master no to struct
       
   676     	ec_rtdm_masterintf[i].masterno = i;
       
   677         // copy from template
       
   678         memcpy(&ec_rtdm_devices[i],&ec_rtdm_device_t,sizeof(ec_rtdm_devices[0]));
       
   679 
       
   680         // set device name
       
   681         snprintf(&ec_rtdm_devices[i].device_name[0],RTDM_MAX_DEVNAME_LEN,"%s%d",EC_RTDM_DEV_FILE_NAME,i);
       
   682         // set proc_name
       
   683 	    ec_rtdm_devices[i].proc_name = &ec_rtdm_devices[i].device_name[0];
       
   684 	    ec_rtdm_devices[i].driver_name = &ec_rtdm_devices[i].device_name[0];
       
   685 		ec_rtdm_devices[i].peripheral_name = &ec_rtdm_devices[i].device_name[0];
       
   686 	
       
   687 		EC_RTDM_GINFO("Registering device %s!\n",ec_rtdm_devices[i].driver_name);
       
   688 		ret = rtdm_dev_register(&ec_rtdm_devices[i]);
       
   689 
       
   690       }	
       
   691     if (ret!=0)
       
   692       {	
       
   693     	// register m
       
   694         EC_RTDM_GERR("Initialization of EtherCAT RTDM Interface failed\n");
       
   695       }		
       
   696     return ret;
       
   697 }
       
   698 
       
   699 /**********************************************************/
       
   700 /*            CLEANUP DRIVER                              */
       
   701 /**********************************************************/
       
   702 void cleanup_module(void)
       
   703 {
       
   704     unsigned int i;
       
   705 
       
   706     EC_RTDM_GINFO("Cleanup EtherCAT RTDM Interface to Igh EtherCAT Master - Moehwald GmbH\n");
       
   707     for (i=0;i<EC_RTDM_MAX_MASTERS;i++)
       
   708       {
       
   709          if (ec_rtdm_masterintf[i].isattached)
       
   710            {
       
   711 	          detach_master(&ec_rtdm_masterintf[i]);
       
   712 	       }
       
   713  		 EC_RTDM_GINFO("Unregistering device %s!\n",ec_rtdm_devices[i].driver_name);
       
   714          rtdm_dev_unregister(&ec_rtdm_devices[i],1000);
       
   715     }
       
   716 }
       
   717 
       
   718 MODULE_LICENSE("GPL");
       
   719 MODULE_DESCRIPTION("EtherCAT RTDM Interface to Igh EtherCAT Master");