drivers/ec_module.c
branchkernel2.6
changeset 33 f4171b8aadf8
parent 27 d75ef6b46e33
child 34 c1e8d61fa395
--- a/drivers/ec_module.c	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/ec_module.c	Fri Dec 16 12:04:59 2005 +0000
@@ -30,6 +30,7 @@
 
 int ecat_master_count = 1;
 EtherCAT_master_t *ecat_masters = NULL;
+int *ecat_masters_reserved = NULL;
 
 /******************************************************************************/
 
@@ -44,7 +45,10 @@
 module_init(ecat_init_module);
 module_exit(ecat_cleanup_module);
 
-EXPORT_SYMBOL(EtherCAT_master);
+EXPORT_SYMBOL(EtherCAT_register_device);
+EXPORT_SYMBOL(EtherCAT_unregister_device);
+EXPORT_SYMBOL(EtherCAT_request);
+EXPORT_SYMBOL(EtherCAT_release);
 
 /******************************************************************************/
 
@@ -82,9 +86,18 @@
     return -1;
   }
 
+  if ((ecat_masters_reserved = (int *) kmalloc(sizeof(int) * ecat_master_count,
+                                               GFP_KERNEL)) == NULL)
+  {
+    printk(KERN_ERR "EtherCAT: Could not allocate memory for reservation flags!\n");
+    kfree(ecat_masters);
+    return -1;
+  }
+
   for (i = 0; i < ecat_master_count; i++)
   {
     EtherCAT_master_init(&ecat_masters[i]);
+    ecat_masters_reserved[i] = 0;
   }
 
   printk(KERN_ERR "EtherCAT: Master driver initialized.\n");
@@ -110,6 +123,10 @@
   {
     for (i = 0; i < ecat_master_count; i++)
     {
+      if (ecat_masters_reserved[i]) {
+        printk(KERN_WARNING "EtherCAT: Warning - Master %i is still in use!\n", i);
+      }
+
       EtherCAT_master_clear(&ecat_masters[i]);
     }
 
@@ -119,24 +136,129 @@
   printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n");
 }
 
-/******************************************************************************/
-
-/**
-   Gibt einen Zeiger auf einen bestimmten EtherCAT-Master zurueck.
+/***************************************************************/
+
+/**
+   Setzt das EtherCAT-Geraet, auf dem der Master arbeitet.
+
+   Registriert das Geraet beim Master, der es daraufhin oeffnet.
+
+   @param master Der EtherCAT-Master
+   @param device Das EtherCAT-Geraet
+   @return 0, wenn alles o.k.,
+           < 0, wenn bereits ein Geraet registriert
+           oder das Geraet nicht geoeffnet werden konnte.
+*/
+
+int EtherCAT_register_device(int index, EtherCAT_device_t *device)
+{
+  if (index < 0 || index >= ecat_master_count)
+  {
+    printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
+    return -1;
+  }
+
+  return EtherCAT_master_open(&ecat_masters[index], device);
+}
+
+/***************************************************************/
+
+/**
+   Loescht das EtherCAT-Geraet, auf dem der Master arbeitet.
+
+   @param master Der EtherCAT-Master
+   @param device Das EtherCAT-Geraet
+*/
+
+void EtherCAT_unregister_device(int index, EtherCAT_device_t *device)
+{
+  if (index < 0 || index >= ecat_master_count)
+  {
+    printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", index);
+    return;
+  }
+
+  EtherCAT_master_close(&ecat_masters[index], device);
+}
+
+/******************************************************************************/
+
+/**
+   Reserviert einen bestimmten EtherCAT-Master und das zugehörige Gerät.
+
+   Gibt einen Zeiger auf den reservierten EtherCAT-Master zurueck.
 
    @param index Index des gewuenschten Masters
    @returns Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig.
 */
 
-EtherCAT_master_t *EtherCAT_master(int index)
-{
-  if (index < 0 || index >= ecat_master_count)
-  {
+EtherCAT_master_t *EtherCAT_request(int index)
+{
+  if (index < 0 || index >= ecat_master_count) {
     printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
     return NULL;
   }
 
+  if (ecat_masters_reserved[index]) {
+    printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index);
+    return NULL;
+  }
+
+  if (!ecat_masters[index].dev) {
+    printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n", index);
+    return NULL;
+  }
+
+  if (!ecat_masters[index].dev->module) {
+    printk(KERN_ERR "EtherCAT: Master %i device module is not set!\n", index);
+    return NULL;
+  }
+
+  if (!try_module_get(ecat_masters[index].dev->module)) {
+    printk(KERN_ERR "EtherCAT: Could not reserve device module!\n");
+    return NULL;
+  }
+
+  ecat_masters_reserved[index] = 1;
+
+  printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index);
+
   return &ecat_masters[index];
 }
 
 /******************************************************************************/
+
+/**
+   Gibt einen zuvor reservierten EtherCAT-Master wieder frei.
+
+   @param master Zeiger auf den freizugebenden EtherCAT-Master.
+*/
+
+void EtherCAT_release(EtherCAT_master_t *master)
+{
+  unsigned int i;
+
+  for (i = 0; i < ecat_master_count; i++)
+  {
+    if (&ecat_masters[i] == master)
+    {
+      if (!ecat_masters[i].dev) {
+        printk(KERN_WARNING "EtherCAT: Could not release device"
+               "module because of no device!\n");
+        return;
+      }
+
+      module_put(ecat_masters[i].dev->module);
+      ecat_masters_reserved[i] = 0;
+
+      printk(KERN_INFO "EtherCAT: Released master %i.\n", i);
+
+      return;
+    }
+  }
+
+  printk(KERN_WARNING "EtherCAT: Master %X was never reserved!\n",
+         (unsigned int) master);
+}
+
+/******************************************************************************/