Neues Interface.
authorFlorian Pose <fp@igh-essen.com>
Fri, 13 Jan 2006 15:39:38 +0000
changeset 52 c0405659a74a
parent 51 b3beaa00640f
child 53 6b3b8acb71b5
Neues Interface.
drivers/ec_domain.c
drivers/ec_domain.h
drivers/ec_master.c
drivers/ec_master.h
drivers/ec_module.c
drivers/ec_module.h
drivers/ec_slave.c
drivers/ec_slave.h
--- a/drivers/ec_domain.c	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_domain.c	Fri Jan 13 15:39:38 2006 +0000
@@ -24,28 +24,11 @@
 void EtherCAT_domain_init(EtherCAT_domain_t *dom)
 {
   dom->number = 0;
-  dom->data = NULL;
   dom->data_size = 0;
   dom->logical_offset = 0;
   dom->response_count = 0;
-}
 
-/*****************************************************************************/
-
-/**
-   Destruktor eines Prozessdatenobjekts.
-
-   @param dom Zeiger auf die zu löschenden Prozessdaten
-*/
-
-void EtherCAT_domain_clear(EtherCAT_domain_t *dom)
-{
-  if (dom->data) {
-    kfree(dom->data);
-    dom->data = NULL;
-  }
-
-  dom->data_size = 0;
+  memset(dom->data, 0x00, ECAT_FRAME_BUFFER_SIZE);
 }
 
 /*****************************************************************************/
--- a/drivers/ec_domain.h	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_domain.h	Fri Jan 13 15:39:38 2006 +0000
@@ -29,8 +29,8 @@
   unsigned int number; /*<< Domänen-Identifikation */
   EtherCAT_command_t command; /**< Kommando zum Senden und Empfangen der
                                  Prozessdaten */
-  unsigned char *data; /**< Zeiger auf Speicher mit Prozessdaten */
-  unsigned int data_size; /**< Größe des Prozessdatenspeichers */
+  unsigned char data[ECAT_FRAME_BUFFER_SIZE]; /**< Prozessdaten-Array */
+  unsigned int data_size; /**< Größe der Prozessdaten */
   unsigned int logical_offset; /**< Logische Basisaddresse */
   unsigned int response_count; /**< Anzahl antwortender Slaves */
 }
@@ -39,7 +39,6 @@
 /*****************************************************************************/
 
 void EtherCAT_domain_init(EtherCAT_domain_t *);
-void EtherCAT_domain_clear(EtherCAT_domain_t *);
 
 /*****************************************************************************/
 
--- a/drivers/ec_master.c	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_master.c	Fri Jan 13 15:39:38 2006 +0000
@@ -27,6 +27,8 @@
 
 void EtherCAT_master_init(EtherCAT_master_t *master)
 {
+  master->bus_slaves = NULL;
+  master->bus_slaves_count = 0;
   master->dev = NULL;
   master->command_index = 0x00;
   master->tx_data_length = 0;
@@ -51,11 +53,9 @@
 
 void EtherCAT_master_clear(EtherCAT_master_t *master)
 {
-  unsigned int i;
-
-  // Remove domains
-  for (i = 0; i < master->domain_count; i++) {
-    EtherCAT_domain_clear(master->domains + i);
+  if (master->bus_slaves) {
+    kfree(master->bus_slaves);
+    master->bus_slaves = NULL;
   }
 
   master->domain_count = 0;
@@ -353,42 +353,19 @@
 /*****************************************************************************/
 
 /**
-   Überprüft die angeschlossenen Slaves.
-
-   Vergleicht die an den Bus angeschlossenen Slaves mit
-   den im statischen-Slave-Array vorgegebenen Konfigurationen.
-   Stimmen Anzahl oder Typen nicht überein, gibt diese
-   Methode einen Fehler aus.
+   Durchsucht den Bus nach Slaves.
 
    @param master Der EtherCAT-Master
-   @param slaves Zeiger auf ein statisches Slave-Array
-   @param slave_count Anzahl der Slaves im Array
 
    @return 0 bei Erfolg, sonst < 0
 */
 
-int EtherCAT_check_slaves(EtherCAT_master_t *master,
-                          EtherCAT_slave_t *slaves,
-                          unsigned int slave_count)
+int EtherCAT_scan_for_slaves(EtherCAT_master_t *master)
 {
   EtherCAT_command_t cmd;
   EtherCAT_slave_t *cur;
-  unsigned int i, j, found, size, offset;
+  unsigned int i, j;
   unsigned char data[2];
-  EtherCAT_domain_t *dom;
-
-  // Clear domains
-  for (i = 0; i < master->domain_count; i++) {
-    printk(KERN_DEBUG "EtherCAT: Clearing domain %i!\n",
-           master->domains[i].number);
-    EtherCAT_domain_clear(master->domains + i);
-  }
-  master->domain_count = 0;
-
-  if (unlikely(!slave_count)) {
-    printk(KERN_ERR "EtherCAT: No slaves in list!\n");
-    return -1;
-  }
 
   // Determine number of slaves on bus
 
@@ -397,44 +374,24 @@
   if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
     return -1;
 
-  if (unlikely(cmd.working_counter != slave_count)) {
-    printk(KERN_ERR "EtherCAT: Wrong number of slaves on bus: %i / %i\n",
-           cmd.working_counter, slave_count);
-    return -1;
-  }
-
-  printk("EtherCAT: Found all %i slaves.\n", slave_count);
+  master->bus_slaves_count = cmd.working_counter;
+  printk("EtherCAT: Found %i slaves on bus.\n", master->bus_slaves_count);
+
+  if (!master->bus_slaves_count) return 0;
+
+  if (!(master->bus_slaves =
+        (EtherCAT_slave_t *) kmalloc(master->bus_slaves_count *
+                                     sizeof(EtherCAT_slave_t), GFP_KERNEL))) {
+    printk(KERN_ERR "EtherCAT: Could not allocate memory for bus slaves!\n");
+    return -1;
+  }
 
   // For every slave in the list
-  for (i = 0; i < slave_count; i++)
-  {
-    cur = &slaves[i];
-
-    if (unlikely(!cur->desc)) {
-      printk(KERN_ERR "EtherCAT: Slave %i has no description.\n", i);
-      return -1;
-    }
-
-    // Set ring position
-    cur->ring_position = -i;
-    cur->station_address = i + 1;
-
-    // Write station address
-
-    data[0] = cur->station_address & 0x00FF;
-    data[1] = (cur->station_address & 0xFF00) >> 8;
-
-    EtherCAT_command_position_write(&cmd, cur->ring_position,
-                                    0x0010, 2, data);
-
-    if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
-      return -1;
-
-    if (unlikely(cmd.working_counter != 1)) {
-      printk(KERN_ERR "EtherCAT: Slave %i did not repond"
-             " while writing station address!\n", i);
-      return -1;
-    }
+  for (i = 0; i < master->bus_slaves_count; i++)
+  {
+    cur = master->bus_slaves + i;
+
+    EtherCAT_slave_init(cur);
 
     // Read base data
 
@@ -495,107 +452,42 @@
 
     // Search for identification in "database"
 
-    found = 0;
-
     for (j = 0; j < slave_ident_count; j++)
     {
       if (unlikely(slave_idents[j].vendor_id == cur->vendor_id
                    && slave_idents[j].product_code == cur->product_code))
       {
-        found = 1;
-
-        if (unlikely(cur->desc != slave_idents[j].desc)) {
-          printk(KERN_ERR "EtherCAT: Unexpected slave device"
-                 " \"%s %s\" at position %i. Expected: \"%s %s\"\n",
-                 slave_idents[j].desc->vendor_name,
-                 slave_idents[j].desc->product_name, i,
-                 cur->desc->vendor_name, cur->desc->product_name);
-          return -1;
-        }
-
+        cur->desc = slave_idents[j].desc;
         break;
       }
     }
 
-    if (unlikely(!found)) {
-      printk(KERN_ERR "EtherCAT: Unknown slave device"
-             " (vendor %X, code %X) at position %i.\n",
-             cur->vendor_id, cur->product_code, i);
-      return -1;
-    }
-
-    // Check, if process data domain already exists...
-    found = 0;
-    for (j = 0; j < master->domain_count; j++) {
-      if (cur->domain == master->domains[j].number) {
-        found = 1;
-      }
-    }
-
-    // Create process data domain
-    if (!found) {
-      if (master->domain_count + 1 >= ECAT_MAX_DOMAINS) {
-        printk(KERN_ERR "EtherCAT: Too many domains!\n");
-        return -1;
-      }
-
-      EtherCAT_domain_init(&master->domains[master->domain_count]);
-      master->domains[master->domain_count].number = cur->domain;
-      master->domain_count++;
-    }
-  }
-
-  // Calculate domain sizes and addresses
-
-  offset = 0;
-  for (i = 0; i < master->domain_count; i++)
-  {
-    dom = master->domains + i;
-
-    dom->logical_offset = offset;
-
-    // Calculate size of the domain
-    size = 0;
-    for (j = 0; j < slave_count; j++) {
-      if (slaves[j].domain == dom->number) {
-        size += slaves[j].desc->process_data_size;
-      }
-    }
-
-    if (size > ECAT_FRAME_BUFFER_SIZE - 14) {
-      printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n",
-             dom->number, size, ECAT_FRAME_BUFFER_SIZE - 14);
-      return -1;
-    }
-
-    if (!(dom->data = (unsigned char *) kmalloc(sizeof(unsigned char)
-                                               * size, GFP_KERNEL))) {
-      printk(KERN_ERR "EtherCAT: Could not allocate %i bytes of domain"
-             " data.\n", size);
-      return -1;
-    }
-
-    dom->data_size = size;
-    memset(dom->data, 0x00, size);
-
-    printk(KERN_INFO "EtherCAT: Domain %i: Offset 0x%04X, %i Bytes of"
-           " process data.\n", dom->number, dom->logical_offset, size);
-
-    // Set logical addresses and data pointers of domain slaves
-    size = 0;
-    for (j = 0; j < slave_count; j++) {
-      if (slaves[j].domain == dom->number) {
-        slaves[j].process_data = dom->data + size;
-        slaves[j].logical_address = dom->logical_offset + size;
-        size += slaves[j].desc->process_data_size;
-
-        printk(KERN_INFO "EtherCAT:    Slave %i: Logical Address 0x%04X, %i"
-               " bytes of process data.\n", j, slaves[j].logical_address,
-               slaves[j].desc->process_data_size);
-      }
-    }
-
-    offset += size;
+    if (unlikely(!cur->desc)) {
+      printk(KERN_ERR "EtherCAT: Unknown slave device (vendor %X, code %X) at "
+             " position %i.\n", cur->vendor_id, cur->product_code, i);
+      return -1;
+    }
+
+    // Set ring position
+    cur->ring_position = -i;
+    cur->station_address = i + 1;
+
+    // Write station address
+
+    data[0] = cur->station_address & 0x00FF;
+    data[1] = (cur->station_address & 0xFF00) >> 8;
+
+    EtherCAT_command_position_write(&cmd, cur->ring_position,
+                                    0x0010, 2, data);
+
+    if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
+      return -1;
+
+    if (unlikely(cmd.working_counter != 1)) {
+      printk(KERN_ERR "EtherCAT: Slave %i did not repond"
+             " while writing station address!\n", i);
+      return -1;
+    }
   }
 
   return 0;
@@ -604,6 +496,83 @@
 /*****************************************************************************/
 
 /**
+   Registriert einen Slave beim Master.
+
+   @param master Der EtherCAT-Master
+
+   @return 0 bei Erfolg, sonst < 0
+*/
+
+void *EtherCAT_register_slave(EtherCAT_master_t *master,
+                              unsigned int bus_index,
+                              const char *vendor_name,
+                              const char *product_name,
+                              unsigned int domain)
+{
+  EtherCAT_slave_t *slave;
+  EtherCAT_domain_t *dom;
+  unsigned int j;
+
+  if (bus_index >= master->bus_slaves_count) {
+    printk(KERN_ERR "EtherCAT: Illegal bus index! (%i / %i)\n", bus_index,
+           master->bus_slaves_count);
+    return NULL;
+  }
+
+  slave = master->bus_slaves + bus_index;
+
+  if (slave->process_data) {
+    printk(KERN_ERR "EtherCAT: Slave %i is already registered!\n", bus_index);
+    return NULL;
+  }
+
+  if (strcmp(vendor_name, slave->desc->vendor_name) ||
+      strcmp(product_name, slave->desc->product_name)) {
+    printk(KERN_ERR "Invalid Slave Type! Requested: \"%s %s\", present: \"%s"
+           "%s\".\n", vendor_name, product_name, slave->desc->vendor_name,
+           slave->desc->product_name);
+    return NULL;
+  }
+
+  // Check, if process data domain already exists...
+  dom = NULL;
+  for (j = 0; j < master->domain_count; j++) {
+    if (domain == master->domains[j].number) {
+      dom = master->domains + j;
+    }
+  }
+
+  // Create process data domain
+  if (!dom) {
+    if (master->domain_count > ECAT_MAX_DOMAINS - 1) {
+      printk(KERN_ERR "EtherCAT: Too many domains!\n");
+      return NULL;
+    }
+
+    dom = master->domains + master->domain_count;
+    EtherCAT_domain_init(dom);
+    dom->number = domain;
+    dom->logical_offset = master->domain_count * ECAT_FRAME_BUFFER_SIZE;
+    master->domain_count++;
+  }
+
+  if (dom->data_size + slave->desc->process_data_size
+      > ECAT_FRAME_BUFFER_SIZE - 14) {
+    printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n",
+           dom->number, dom->data_size + slave->desc->process_data_size,
+           ECAT_FRAME_BUFFER_SIZE - 14);
+    return NULL;
+  }
+
+  slave->process_data = dom->data + dom->data_size;
+  dom->data_size += slave->desc->process_data_size;
+
+  return slave->process_data;
+}
+
+/*****************************************************************************/
+
+/**
    Liest Daten aus dem Slave-Information-Interface
    eines EtherCAT-Slaves.
 
@@ -1142,11 +1111,8 @@
 
 /*****************************************************************************/
 
-EXPORT_SYMBOL(EtherCAT_master_init);
-EXPORT_SYMBOL(EtherCAT_master_clear);
 EXPORT_SYMBOL(EtherCAT_master_open);
 EXPORT_SYMBOL(EtherCAT_master_close);
-EXPORT_SYMBOL(EtherCAT_check_slaves);
 EXPORT_SYMBOL(EtherCAT_activate_slave);
 EXPORT_SYMBOL(EtherCAT_deactivate_slave);
 EXPORT_SYMBOL(EtherCAT_process_data_cycle);
--- a/drivers/ec_master.h	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_master.h	Fri Jan 13 15:39:38 2006 +0000
@@ -27,6 +27,8 @@
 
 struct EtherCAT_master
 {
+  EtherCAT_slave_t *bus_slaves; /**< Array von Slaves auf dem Bus */
+  unsigned int bus_slaves_count; /**< Anzahl Slaves auf dem Bus */
   EtherCAT_device_t *dev; /**< Zeiger auf das zugewiesene EtherCAT-Gerät */
   unsigned char command_index; /**< Aktueller Kommando-Index */
   unsigned char tx_data[ECAT_FRAME_BUFFER_SIZE]; /**< Statischer Speicher
@@ -47,6 +49,17 @@
 
 /*****************************************************************************/
 
+// Public methods
+
+void *EtherCAT_register_slave(EtherCAT_master_t *, unsigned int,
+                              const char *, const char *, unsigned int);
+int EtherCAT_activate_slave(EtherCAT_master_t *, EtherCAT_slave_t *);
+int EtherCAT_deactivate_slave(EtherCAT_master_t *, EtherCAT_slave_t *);
+int EtherCAT_process_data_cycle(EtherCAT_master_t *, unsigned int,
+                                unsigned int);
+
+// Private Methods
+
 // Master creation and deletion
 void EtherCAT_master_init(EtherCAT_master_t *);
 void EtherCAT_master_clear(EtherCAT_master_t *);
@@ -61,20 +74,14 @@
 int EtherCAT_simple_receive(EtherCAT_master_t *, EtherCAT_command_t *);
 
 // Slave management
-int EtherCAT_check_slaves(EtherCAT_master_t *, EtherCAT_slave_t *,
-                          unsigned int);
+int EtherCAT_scan_for_slaves(EtherCAT_master_t *);
 int EtherCAT_read_slave_information(EtherCAT_master_t *, unsigned short int,
                                     unsigned short int, unsigned int *);
-int EtherCAT_activate_slave(EtherCAT_master_t *, EtherCAT_slave_t *);
-int EtherCAT_deactivate_slave(EtherCAT_master_t *, EtherCAT_slave_t *);
 int EtherCAT_state_change(EtherCAT_master_t *, EtherCAT_slave_t *,
                           unsigned char);
 
-// Process data
-int EtherCAT_process_data_cycle(EtherCAT_master_t *, unsigned int,
-                                unsigned int);
+// Misc.
 
-// Private functions
 void output_debug_data(const EtherCAT_master_t *);
 void ecat_output_lost_frames(EtherCAT_master_t *);
 
--- a/drivers/ec_module.c	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_module.c	Fri Jan 13 15:39:38 2006 +0000
@@ -24,6 +24,9 @@
 
 #include "ec_module.h"
 
+int __init ecat_init_module(void);
+void __exit ecat_cleanup_module(void);
+
 /*****************************************************************************/
 
 #define LIT(X) #X
@@ -229,6 +232,11 @@
     return NULL;
   }
 
+  if (EtherCAT_scan_for_slaves(&ecat_masters[index]) != 0) {
+      printk(KERN_ERR "EtherCAT: Could not scan for slaves!\n");
+      return NULL;
+  }
+
   ecat_masters_reserved[index] = 1;
 
   printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index);
--- a/drivers/ec_module.h	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_module.h	Fri Jan 13 15:39:38 2006 +0000
@@ -26,9 +26,6 @@
 
 /*****************************************************************************/
 
-int __init ecat_init_module(void);
-void __exit ecat_cleanup_module(void);
-
 // Registration of devices
 int EtherCAT_register_device(int, EtherCAT_device_t *);
 void EtherCAT_unregister_device(int, EtherCAT_device_t *);
--- a/drivers/ec_slave.c	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_slave.c	Fri Jan 13 15:39:38 2006 +0000
@@ -49,21 +49,6 @@
 /*****************************************************************************/
 
 /**
-   EtherCAT-Slave-Destruktor.
-
-   Im Moment ohne Funktionalität.
-
-   @param slave Zeiger auf den zu zerstörenden Slave
-*/
-
-void EtherCAT_slave_clear(EtherCAT_slave_t *slave)
-{
-  // Nothing yet...
-}
-
-/*****************************************************************************/
-
-/**
    Liest einen bestimmten Kanal des Slaves als Integer-Wert.
 
    Prüft zuerst, ob der entsprechende Slave eine
--- a/drivers/ec_slave.h	Fri Jan 13 13:44:22 2006 +0000
+++ b/drivers/ec_slave.h	Fri Jan 13 15:39:38 2006 +0000
@@ -62,7 +62,6 @@
 
 // Slave construction and deletion
 void EtherCAT_slave_init(EtherCAT_slave_t *);
-void EtherCAT_slave_clear(EtherCAT_slave_t *);
 
 int EtherCAT_read_value(EtherCAT_slave_t *, unsigned int);
 void EtherCAT_write_value(EtherCAT_slave_t *, unsigned int, int);