drivers/ec_module.c
changeset 54 7506e67dd122
parent 53 6b3b8acb71b5
child 55 059a9e712aa7
equal deleted inserted replaced
53:6b3b8acb71b5 54:7506e67dd122
     1 /******************************************************************************
       
     2  *
       
     3  *  ec_module.c
       
     4  *
       
     5  *  EtherCAT-Master-Treiber
       
     6  *
       
     7  *  Autoren: Wilhelm Hagemeister, Florian Pose
       
     8  *
       
     9  *  $Id$
       
    10  *
       
    11  *  (C) Copyright IgH 2005
       
    12  *  Ingenieurgemeinschaft IgH
       
    13  *  Heinz-Bäcker Str. 34
       
    14  *  D-45356 Essen
       
    15  *  Tel.: +49 201/61 99 31
       
    16  *  Fax.: +49 201/61 98 36
       
    17  *  E-mail: sp@igh-essen.com
       
    18  *
       
    19  *****************************************************************************/
       
    20 
       
    21 #include <linux/module.h>
       
    22 #include <linux/kernel.h>
       
    23 #include <linux/init.h>
       
    24 
       
    25 #include "ec_module.h"
       
    26 
       
    27 int __init ecat_init_module(void);
       
    28 void __exit ecat_cleanup_module(void);
       
    29 
       
    30 /*****************************************************************************/
       
    31 
       
    32 #define LIT(X) #X
       
    33 #define STR(X) LIT(X)
       
    34 
       
    35 #define COMPILE_INFO "Revision " STR(EC_REV) \
       
    36                      ", compiled by " STR(EC_USER) \
       
    37                      " at " STR(EC_DATE)
       
    38 
       
    39 /*****************************************************************************/
       
    40 
       
    41 int ecat_master_count = 1;
       
    42 EtherCAT_master_t *ecat_masters = NULL;
       
    43 int *ecat_masters_reserved = NULL;
       
    44 
       
    45 /*****************************************************************************/
       
    46 
       
    47 MODULE_AUTHOR ("Wilhelm Hagemeister <hm@igh-essen.com>,"
       
    48                "Florian Pose <fp@igh-essen.com>");
       
    49 MODULE_DESCRIPTION ("EtherCAT master driver module");
       
    50 MODULE_LICENSE("GPL");
       
    51 MODULE_VERSION(COMPILE_INFO);
       
    52 
       
    53 module_param(ecat_master_count, int, 1);
       
    54 MODULE_PARM_DESC(ecat_master_count,
       
    55                  "Number of EtherCAT master to initialize.");
       
    56 
       
    57 module_init(ecat_init_module);
       
    58 module_exit(ecat_cleanup_module);
       
    59 
       
    60 EXPORT_SYMBOL(EtherCAT_register_device);
       
    61 EXPORT_SYMBOL(EtherCAT_unregister_device);
       
    62 EXPORT_SYMBOL(EtherCAT_request);
       
    63 EXPORT_SYMBOL(EtherCAT_release);
       
    64 
       
    65 /*****************************************************************************/
       
    66 
       
    67 /**
       
    68    Init-Funktion des EtherCAT-Master-Treibermodules
       
    69 
       
    70    Initialisiert soviele Master, wie im Parameter ecat_master_count
       
    71    angegeben wurde (Default ist 1).
       
    72 
       
    73    @returns 0, wenn alles o.k., -1 bei ungueltiger Anzahl Master
       
    74             oder zu wenig Speicher.
       
    75 */
       
    76 
       
    77 int __init ecat_init_module(void)
       
    78 {
       
    79   unsigned int i;
       
    80 
       
    81   printk(KERN_ERR "EtherCAT: Master driver, %s\n", COMPILE_INFO);
       
    82 
       
    83   if (ecat_master_count < 1) {
       
    84     printk(KERN_ERR "EtherCAT: Error - Illegal"
       
    85            " ecat_master_count: %i\n", ecat_master_count);
       
    86     return -1;
       
    87   }
       
    88 
       
    89   printk(KERN_ERR "EtherCAT: Initializing %i EtherCAT master(s)...\n",
       
    90          ecat_master_count);
       
    91 
       
    92   if ((ecat_masters =
       
    93        (EtherCAT_master_t *) kmalloc(sizeof(EtherCAT_master_t)
       
    94                                      * ecat_master_count,
       
    95                                      GFP_KERNEL)) == NULL) {
       
    96     printk(KERN_ERR "EtherCAT: Could not allocate"
       
    97            " memory for EtherCAT master(s)!\n");
       
    98     return -1;
       
    99   }
       
   100 
       
   101   if ((ecat_masters_reserved =
       
   102        (int *) kmalloc(sizeof(int) * ecat_master_count,
       
   103                        GFP_KERNEL)) == NULL) {
       
   104     printk(KERN_ERR "EtherCAT: Could not allocate"
       
   105            " memory for reservation flags!\n");
       
   106     kfree(ecat_masters);
       
   107     return -1;
       
   108   }
       
   109 
       
   110   for (i = 0; i < ecat_master_count; i++)
       
   111   {
       
   112     EtherCAT_master_init(&ecat_masters[i]);
       
   113     ecat_masters_reserved[i] = 0;
       
   114   }
       
   115 
       
   116   printk(KERN_ERR "EtherCAT: Master driver initialized.\n");
       
   117 
       
   118   return 0;
       
   119 }
       
   120 
       
   121 /*****************************************************************************/
       
   122 
       
   123 /**
       
   124    Cleanup-Funktion des EtherCAT-Master-Treibermoduls
       
   125 
       
   126    Entfernt alle Master-Instanzen.
       
   127 */
       
   128 
       
   129 void __exit ecat_cleanup_module(void)
       
   130 {
       
   131   unsigned int i;
       
   132 
       
   133   printk(KERN_ERR "EtherCAT: Cleaning up master driver...\n");
       
   134 
       
   135   if (ecat_masters)
       
   136   {
       
   137     for (i = 0; i < ecat_master_count; i++)
       
   138     {
       
   139       if (ecat_masters_reserved[i]) {
       
   140         printk(KERN_WARNING "EtherCAT: Warning -"
       
   141                " Master %i is still in use!\n", i);
       
   142       }
       
   143 
       
   144       EtherCAT_master_clear(&ecat_masters[i]);
       
   145     }
       
   146 
       
   147     kfree(ecat_masters);
       
   148   }
       
   149 
       
   150   printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n");
       
   151 }
       
   152 
       
   153 /*****************************************************************************/
       
   154 
       
   155 /**
       
   156    Setzt das EtherCAT-Geraet, auf dem der Master arbeitet.
       
   157 
       
   158    Registriert das Geraet beim Master, der es daraufhin oeffnet.
       
   159 
       
   160    @param master Der EtherCAT-Master
       
   161    @param device Das EtherCAT-Geraet
       
   162    @return 0, wenn alles o.k.,
       
   163            < 0, wenn bereits ein Geraet registriert
       
   164            oder das Geraet nicht geoeffnet werden konnte.
       
   165 */
       
   166 
       
   167 int EtherCAT_register_device(int index, EtherCAT_device_t *device)
       
   168 {
       
   169   if (index < 0 || index >= ecat_master_count) {
       
   170     printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
       
   171     return -1;
       
   172   }
       
   173 
       
   174   return EtherCAT_master_open(&ecat_masters[index], device);
       
   175 }
       
   176 
       
   177 /*****************************************************************************/
       
   178 
       
   179 /**
       
   180    Loescht das EtherCAT-Geraet, auf dem der Master arbeitet.
       
   181 
       
   182    @param master Der EtherCAT-Master
       
   183    @param device Das EtherCAT-Geraet
       
   184 */
       
   185 
       
   186 void EtherCAT_unregister_device(int index, EtherCAT_device_t *device)
       
   187 {
       
   188   if (index < 0 || index >= ecat_master_count) {
       
   189     printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", index);
       
   190     return;
       
   191   }
       
   192 
       
   193   EtherCAT_master_close(&ecat_masters[index], device);
       
   194 }
       
   195 
       
   196 /*****************************************************************************/
       
   197 
       
   198 /**
       
   199    Reserviert einen bestimmten EtherCAT-Master und das zugehörige Gerät.
       
   200 
       
   201    Gibt einen Zeiger auf den reservierten EtherCAT-Master zurueck.
       
   202 
       
   203    @param index Index des gewuenschten Masters
       
   204    @returns Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig.
       
   205 */
       
   206 
       
   207 EtherCAT_master_t *EtherCAT_request(int index)
       
   208 {
       
   209   if (index < 0 || index >= ecat_master_count) {
       
   210     printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
       
   211     return NULL;
       
   212   }
       
   213 
       
   214   if (ecat_masters_reserved[index]) {
       
   215     printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index);
       
   216     return NULL;
       
   217   }
       
   218 
       
   219   if (!ecat_masters[index].dev) {
       
   220     printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n",
       
   221            index);
       
   222     return NULL;
       
   223   }
       
   224 
       
   225   if (!ecat_masters[index].dev->module) {
       
   226     printk(KERN_ERR "EtherCAT: Master %i device module is not set!\n", index);
       
   227     return NULL;
       
   228   }
       
   229 
       
   230   if (!try_module_get(ecat_masters[index].dev->module)) {
       
   231     printk(KERN_ERR "EtherCAT: Could not reserve device module!\n");
       
   232     return NULL;
       
   233   }
       
   234 
       
   235   if (EtherCAT_scan_for_slaves(&ecat_masters[index]) != 0) {
       
   236       printk(KERN_ERR "EtherCAT: Could not scan for slaves!\n");
       
   237       return NULL;
       
   238   }
       
   239 
       
   240   ecat_masters_reserved[index] = 1;
       
   241 
       
   242   printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index);
       
   243 
       
   244   return &ecat_masters[index];
       
   245 }
       
   246 
       
   247 /*****************************************************************************/
       
   248 
       
   249 /**
       
   250    Gibt einen zuvor angeforderten EtherCAT-Master wieder frei.
       
   251 
       
   252    @param master Zeiger auf den freizugebenden EtherCAT-Master.
       
   253 */
       
   254 
       
   255 void EtherCAT_release(EtherCAT_master_t *master)
       
   256 {
       
   257   unsigned int i;
       
   258 
       
   259   for (i = 0; i < ecat_master_count; i++)
       
   260   {
       
   261     if (&ecat_masters[i] == master)
       
   262     {
       
   263       if (!ecat_masters[i].dev) {
       
   264         printk(KERN_WARNING "EtherCAT: Could not release device"
       
   265                "module because of no device!\n");
       
   266         return;
       
   267       }
       
   268 
       
   269       module_put(ecat_masters[i].dev->module);
       
   270       ecat_masters_reserved[i] = 0;
       
   271 
       
   272       printk(KERN_INFO "EtherCAT: Released master %i.\n", i);
       
   273 
       
   274       return;
       
   275     }
       
   276   }
       
   277 
       
   278   printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n",
       
   279          (unsigned int) master);
       
   280 }
       
   281 
       
   282 /*****************************************************************************/