module.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: module.c 514 2006-08-09 14:38:44Z fp $
00004  *
00005  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
00006  *
00007  *  This file is part of the IgH EtherCAT Master.
00008  *
00009  *  The IgH EtherCAT Master is free software; you can redistribute it
00010  *  and/or modify it under the terms of the GNU General Public License
00011  *  as published by the Free Software Foundation; either version 2 of the
00012  *  License, or (at your option) any later version.
00013  *
00014  *  The IgH EtherCAT Master is distributed in the hope that it will be
00015  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with the IgH EtherCAT Master; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  *  The right to use EtherCAT Technology is granted and comes free of
00024  *  charge under condition of compatibility of product made by
00025  *  Licensee. People intending to distribute/sell products based on the
00026  *  code, have to sign an agreement to guarantee that products using
00027  *  software based on IgH EtherCAT master stay compatible with the actual
00028  *  EtherCAT specification (which are released themselves as an open
00029  *  standard) as the (only) precondition to have the right to use EtherCAT
00030  *  Technology, IP and trade marks.
00031  *
00032  *****************************************************************************/
00033 
00039 /*****************************************************************************/
00040 
00041 #include <linux/module.h>
00042 #include <linux/kernel.h>
00043 #include <linux/init.h>
00044 
00045 #include "globals.h"
00046 #include "master.h"
00047 #include "device.h"
00048 
00049 /*****************************************************************************/
00050 
00051 int __init ec_init_module(void);
00052 void __exit ec_cleanup_module(void);
00053 
00054 /*****************************************************************************/
00055 
00060 #define COMPILE_INFO EC_STR(EC_MASTER_VERSION_MAIN) \
00061                      "." EC_STR(EC_MASTER_VERSION_SUB) \
00062                      " (" EC_MASTER_VERSION_EXTRA ")" \
00063                      " - rev. " EC_STR(SVNREV) \
00064                      ", compiled by " EC_STR(USER) \
00065                      " at " __DATE__ " " __TIME__
00066 
00067 /*****************************************************************************/
00068 
00069 static int ec_master_count = 1; 
00070 static int ec_eoeif_count = 0; 
00071 static struct list_head ec_masters; 
00073 /*****************************************************************************/
00074 
00077 module_param(ec_master_count, int, S_IRUGO);
00078 module_param(ec_eoeif_count, int, S_IRUGO);
00079 
00080 MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
00081 MODULE_DESCRIPTION("EtherCAT master driver module");
00082 MODULE_LICENSE("GPL");
00083 MODULE_VERSION(COMPILE_INFO);
00084 MODULE_PARM_DESC(ec_master_count, "number of EtherCAT masters to initialize");
00085 MODULE_PARM_DESC(ec_eoeif_count, "number of EoE interfaces per master");
00086 
00089 /*****************************************************************************/
00090 
00097 int __init ec_init_module(void)
00098 {
00099     unsigned int i;
00100     ec_master_t *master, *next;
00101 
00102     EC_INFO("Master driver, %s\n", COMPILE_INFO);
00103 
00104     if (ec_master_count < 1) {
00105         EC_ERR("Error - Invalid ec_master_count: %i\n", ec_master_count);
00106         goto out_return;
00107     }
00108 
00109     EC_INFO("Initializing %i EtherCAT master(s)...\n", ec_master_count);
00110 
00111     INIT_LIST_HEAD(&ec_masters);
00112 
00113     for (i = 0; i < ec_master_count; i++) {
00114         if (!(master =
00115               (ec_master_t *) kmalloc(sizeof(ec_master_t), GFP_KERNEL))) {
00116             EC_ERR("Failed to allocate memory for EtherCAT master %i.\n", i);
00117             goto out_free;
00118         }
00119 
00120         if (ec_master_init(master, i, ec_eoeif_count))
00121             goto out_free;
00122 
00123         if (kobject_add(&master->kobj)) {
00124             EC_ERR("Failed to add kobj.\n");
00125             kobject_put(&master->kobj); // free master
00126             goto out_free;
00127         }
00128 
00129         list_add_tail(&master->list, &ec_masters);
00130     }
00131 
00132     EC_INFO("Master driver initialized.\n");
00133     return 0;
00134 
00135  out_free:
00136     list_for_each_entry_safe(master, next, &ec_masters, list) {
00137         list_del(&master->list);
00138         kobject_del(&master->kobj);
00139         kobject_put(&master->kobj);
00140     }
00141  out_return:
00142     return -1;
00143 }
00144 
00145 /*****************************************************************************/
00146 
00152 void __exit ec_cleanup_module(void)
00153 {
00154     ec_master_t *master, *next;
00155 
00156     EC_INFO("Cleaning up master driver...\n");
00157 
00158     list_for_each_entry_safe(master, next, &ec_masters, list) {
00159         list_del(&master->list);
00160         kobject_del(&master->kobj);
00161         kobject_put(&master->kobj); // free master
00162     }
00163 
00164     EC_INFO("Master driver cleaned up.\n");
00165 }
00166 
00167 /*****************************************************************************/
00168 
00174 ec_master_t *ec_find_master(unsigned int master_index )
00175 {
00176     ec_master_t *master;
00177 
00178     list_for_each_entry(master, &ec_masters, list) {
00179         if (master->index == master_index) return master;
00180     }
00181 
00182     EC_ERR("Master %i does not exist!\n", master_index);
00183     return NULL;
00184 }
00185 
00186 /*****************************************************************************/
00187 
00192 void ec_print_data(const uint8_t *data, 
00193                    size_t size 
00194                    )
00195 {
00196     unsigned int i;
00197 
00198     EC_DBG("");
00199     for (i = 0; i < size; i++) {
00200         printk("%02X ", data[i]);
00201         if ((i + 1) % 16 == 0) {
00202             printk("\n");
00203             EC_DBG("");
00204         }
00205     }
00206     printk("\n");
00207 }
00208 
00209 /*****************************************************************************/
00210 
00215 void ec_print_data_diff(const uint8_t *d1, 
00216                         const uint8_t *d2, 
00217                         size_t size 
00218                         )
00219 {
00220     unsigned int i;
00221 
00222     EC_DBG("");
00223     for (i = 0; i < size; i++) {
00224         if (d1[i] == d2[i]) printk(".. ");
00225         else printk("%02X ", d2[i]);
00226         if ((i + 1) % 16 == 0) {
00227             printk("\n");
00228             EC_DBG("");
00229         }
00230     }
00231     printk("\n");
00232 }
00233 
00234 /*****************************************************************************/
00235 
00240 size_t ec_state_string(uint8_t states, 
00241                        char *buffer 
00242                        )
00243 {
00244     off_t off = 0;
00245     unsigned int first = 1;
00246 
00247     if (!states) {
00248         off += sprintf(buffer + off, "(unknown)");
00249         return off;
00250     }
00251 
00252     if (states & EC_SLAVE_STATE_INIT) {
00253         off += sprintf(buffer + off, "INIT");
00254         first = 0;
00255     }
00256     if (states & EC_SLAVE_STATE_PREOP) {
00257         if (!first) off += sprintf(buffer + off, ", ");
00258         off += sprintf(buffer + off, "PREOP");
00259         first = 0;
00260     }
00261     if (states & EC_SLAVE_STATE_SAVEOP) {
00262         if (!first) off += sprintf(buffer + off, ", ");
00263         off += sprintf(buffer + off, "SAVEOP");
00264         first = 0;
00265     }
00266     if (states & EC_SLAVE_STATE_OP) {
00267         if (!first) off += sprintf(buffer + off, ", ");
00268         off += sprintf(buffer + off, "OP");
00269     }
00270 
00271     return off;
00272 }
00273 
00274 /******************************************************************************
00275  *  Device interface
00276  *****************************************************************************/
00277 
00287 ec_device_t *ecdev_register(unsigned int master_index, 
00288                             struct net_device *net_dev, 
00290                             ec_isr_t isr, 
00291                             struct module *module 
00292                             )
00293 {
00294     ec_master_t *master;
00295 
00296     if (!(master = ec_find_master(master_index))) return NULL;
00297 
00298     if (master->device) {
00299         EC_ERR("Master %i already has a device!\n", master_index);
00300         goto out_return;
00301     }
00302 
00303     if (!(master->device =
00304           (ec_device_t *) kmalloc(sizeof(ec_device_t), GFP_KERNEL))) {
00305         EC_ERR("Failed to allocate device!\n");
00306         goto out_return;
00307     }
00308 
00309     if (ec_device_init(master->device, master, net_dev, isr, module)) {
00310         EC_ERR("Failed to init device!\n");
00311         goto out_free;
00312     }
00313 
00314     return master->device;
00315 
00316  out_free:
00317     kfree(master->device);
00318     master->device = NULL;
00319  out_return:
00320     return NULL;
00321 }
00322 
00323 /*****************************************************************************/
00324 
00334 void ecdev_unregister(unsigned int master_index, 
00335                       ec_device_t *device 
00336                       )
00337 {
00338     ec_master_t *master;
00339 
00340     if (!(master = ec_find_master(master_index))) return;
00341 
00342     if (!master->device || master->device != device) {
00343         EC_WARN("Unable to unregister device!\n");
00344         return;
00345     }
00346 
00347     ec_device_clear(master->device);
00348     kfree(master->device);
00349     master->device = NULL;
00350 }
00351 
00352 /*****************************************************************************/
00353 
00362 int ecdev_start(unsigned int master_index )
00363 {
00364     ec_master_t *master;
00365     if (!(master = ec_find_master(master_index))) return -1;
00366 
00367     if (ec_device_open(master->device)) {
00368         EC_ERR("Failed to open device!\n");
00369         return -1;
00370     }
00371 
00372     ec_master_measure_bus_time(master);
00373     ec_master_idle_start(master);
00374     return 0;
00375 }
00376 
00377 /*****************************************************************************/
00378 
00386 void ecdev_stop(unsigned int master_index )
00387 {
00388     ec_master_t *master;
00389     if (!(master = ec_find_master(master_index))) return;
00390 
00391     ec_master_idle_stop(master);
00392 
00393     if (ec_device_close(master->device))
00394         EC_WARN("Failed to close device!\n");
00395 }
00396 
00397 /******************************************************************************
00398  *  Realtime interface
00399  *****************************************************************************/
00400 
00407 ec_master_t *ecrt_request_master(unsigned int master_index
00409                                  )
00410 {
00411     ec_master_t *master;
00412 
00413     EC_INFO("Requesting master %i...\n", master_index);
00414 
00415     if (!(master = ec_find_master(master_index))) goto out_return;
00416 
00417     if (master->reserved) {
00418         EC_ERR("Master %i is already in use!\n", master_index);
00419         goto out_return;
00420     }
00421     master->reserved = 1;
00422 
00423     if (!master->device) {
00424         EC_ERR("Master %i has no assigned device!\n", master_index);
00425         goto out_release;
00426     }
00427 
00428     if (!try_module_get(master->device->module)) {
00429         EC_ERR("Failed to reserve device module!\n");
00430         goto out_release;
00431     }
00432 
00433     ec_master_measure_bus_time(master);
00434     ec_master_idle_stop(master);
00435     ec_master_reset(master);
00436     master->mode = EC_MASTER_MODE_OPERATION;
00437 
00438     if (!master->device->link_state) EC_WARN("Link is DOWN.\n");
00439 
00440     if (ec_master_bus_scan(master)) {
00441         EC_ERR("Bus scan failed!\n");
00442         goto out_module_put;
00443     }
00444 
00445     EC_INFO("Master %i is ready.\n", master_index);
00446     return master;
00447 
00448  out_module_put:
00449     module_put(master->device->module);
00450     ec_master_reset(master);
00451     ec_master_idle_start(master);
00452  out_release:
00453     master->reserved = 0;
00454  out_return:
00455     EC_ERR("Failed requesting master %i.\n", master_index);
00456     return NULL;
00457 }
00458 
00459 /*****************************************************************************/
00460 
00466 void ecrt_release_master(ec_master_t *master )
00467 {
00468     EC_INFO("Releasing master %i...\n", master->index);
00469 
00470     if (!master->reserved) {
00471         EC_ERR("Master %i was never requested!\n", master->index);
00472         return;
00473     }
00474 
00475     ec_master_reset(master);
00476     ec_master_idle_start(master);
00477 
00478     module_put(master->device->module);
00479     master->reserved = 0;
00480 
00481     EC_INFO("Released master %i.\n", master->index);
00482     return;
00483 }
00484 
00485 /*****************************************************************************/
00486 
00489 module_init(ec_init_module);
00490 module_exit(ec_cleanup_module);
00491 
00492 EXPORT_SYMBOL(ecdev_register);
00493 EXPORT_SYMBOL(ecdev_unregister);
00494 EXPORT_SYMBOL(ecdev_start);
00495 EXPORT_SYMBOL(ecdev_stop);
00496 EXPORT_SYMBOL(ecrt_request_master);
00497 EXPORT_SYMBOL(ecrt_release_master);
00498 
00501 /*****************************************************************************/

Generated on Fri Sep 1 14:56:56 2006 for IgH EtherCAT master by  doxygen 1.4.6