MERGE trunk -r564:568 -> branches/stable-1.1 (doc, master output, atomic flag) stable-1.1
authorFlorian Pose <fp@igh-essen.com>
Tue, 26 Sep 2006 16:38:38 +0000
branchstable-1.1
changeset 1728 4cf9c3e9f0bd
parent 1727 861f4715ed6f
child 1729 bcc41c8986bc
MERGE trunk -r564:568 -> branches/stable-1.1 (doc, master output, atomic flag)
Makefile.am
documentation/ethercat_doc.tex
master/domain.c
master/master.c
master/master.h
master/module.c
--- a/Makefile.am	Mon Sep 25 17:28:31 2006 +0000
+++ b/Makefile.am	Tue Sep 26 16:38:38 2006 +0000
@@ -70,7 +70,8 @@
 	$(MINI_FILES) $(RTAI_FILES) $(MSR_FILES)
 
 mydist:
-	$(MAKE) dist distdir=$(PACKAGE)-$(VERSION)-r`svnversion $(srcdir)`
+	@SVNREV=`svnversion $(srcdir)` && \
+		$(MAKE) dist-bzip2 distdir=$(PACKAGE)-$(VERSION)-r$${SVNREV}
 
 dist-hook:
 	if which svnversion >/dev/null 2>&1; then \
--- a/documentation/ethercat_doc.tex	Mon Sep 25 17:28:31 2006 +0000
+++ b/documentation/ethercat_doc.tex	Tue Sep 26 16:38:38 2006 +0000
@@ -4300,9 +4300,10 @@
 \label{sec:make}
 \index{Master!Compilation}
 
-The current EtherCAT master code is available at~\cite{etherlab}.
-After downloading the \textit{tar.bz2} file, it has to be unpacked
-with the command below (or similar):
+The current EtherCAT master code is available at~\cite{etherlab} or
+can be obtained from the EtherLab\textsuperscript{\textregistered} CD.
+The \textit{tar.bz2} file has to be unpacked with the command below
+(or similar):
 
 \begin{lstlisting}
   host> `\textbf{tar xjf ethercat-1.1-rXXX.tar.bz2}`
@@ -4340,10 +4341,12 @@
   host# `\textbf{make install}`
 \end{lstlisting}
 
-If the EtherCAT master shall be run as a service (recommended), the
-init script and the sysconfig file have to be copied to the
-appropriate locations. The below example is suitable for SUSE Linux.
-It may vary for other distributions.
+If the EtherCAT master shall be run as a service
+(recommended\footnote{Even if the EtherCAT master shall not be loaded
+  on system startup, the use of the init script is recommended for
+  manual (un-)loading.}), the init script and the sysconfig file have
+to be copied to the appropriate locations. The below example is
+suitable for SUSE Linux.  It may vary for other distributions.
 
 \begin{lstlisting}
   host# `\textbf{cd /opt/etherlab}`
@@ -4352,14 +4355,33 @@
   host# `\textbf{insserv ethercat}`
 \end{lstlisting}
 
-Now the sysconfig file has to be customized. For the contents of the
-file, see section~\ref{sec:sysconfig}. To give a short summary: The
-most important thing is to adjust the \textit{DEVICE\_INDEX} variable.
-It has to be set to the index of the compatible network device to use
+Now the sysconfig file \texttt{/etc/sysconfig/ethercat} (see
+section~\ref{sec:sysconfig}) has to be customized: This is mainly done
+by uncommenting and adjusting the \textit{DEVICE\_INDEX} variable. It
+has to be set to the index of the compatible network device to use
 with EtherCAT, where the order of devices is dependent on their
-position in the PCI bus. If this is not known, the index can be
-determinded with trial and error, but it has to be considered that a
-wrong value can cause a loss of network connection.
+position in the PCI bus:
+
+\begin{lstlisting}[numbers=left,basicstyle=\ttfamily\scriptsize]
+  host# `\textbf{lspci}`
+  00:00.0 Host bridge: VIA Technologies, Inc. VT8363/8365 [KT133/KM133] (rev 03)
+  00:01.0 PCI bridge: VIA Technologies, Inc. VT8363/8365 [KT133/KM133 AGP]
+  00:04.0 ISA bridge: VIA Technologies, Inc. VT82C686 [Apollo Super South] (rev 40)
+  00:04.1 IDE interface: VIA Technologies, Inc. VT82C586A/B/VT82C686/A/B/VT823x/A/C...
+  00:04.2 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller...
+  00:04.3 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller...
+  00:04.4 Bridge: VIA Technologies, Inc. VT82C686 [Apollo Super ACPI] (rev 40)
+  00:09.0 Ethernet controller: D-Link System Inc RTL8139 Ethernet (rev 10)
+  00:0a.0 Ethernet controller: Intel Corporation 82557/8/9 [Ethernet Pro 100] (rev 08)
+  00:0b.0 Ethernet controller: D-Link System Inc RTL8139 Ethernet (rev 10)
+  00:0c.0 VGA compatible controller: ATI Technologies Inc Rage XL (rev 27)
+  00:11.0 Unknown mass storage controller: Promise Technology, Inc. PDC20265...
+\end{lstlisting}
+
+In the above output of the \textit{lspci} command, two compatible
+network devices can be found in lines~\textcircled{\tiny 9} and
+\textcircled{\tiny 11}. The \textit{DEVICE\_INDEX} variable should be
+set to $0$ or $1$, respectively.
 
 After the basic configuration is done, the master can be started with
 the below command:
--- a/master/domain.c	Mon Sep 25 17:28:31 2006 +0000
+++ b/master/domain.c	Tue Sep 26 16:38:38 2006 +0000
@@ -357,7 +357,7 @@
         }
     }
 
-    EC_INFO("Domain %i - Allocated %i bytes in %i datagram%s\n",
+    EC_INFO("Domain %i - Allocated %i bytes in %i datagram%s.\n",
             domain->index, domain->data_size, datagram_count,
             datagram_count == 1 ? "" : "s");
 
--- a/master/master.c	Mon Sep 25 17:28:31 2006 +0000
+++ b/master/master.c	Tue Sep 26 16:38:38 2006 +0000
@@ -108,7 +108,7 @@
 
     master->index = index;
     master->device = NULL;
-    master->reserved = 0;
+    atomic_set(&master->available, 1);
     INIT_LIST_HEAD(&master->slaves);
     INIT_LIST_HEAD(&master->datagram_queue);
     INIT_LIST_HEAD(&master->domains);
@@ -1041,9 +1041,10 @@
 
 /**
    Measures the time, a frame is on the bus.
-*/
-
-void ec_master_measure_bus_time(ec_master_t *master)
+   \return 0 in case of success, else < 0
+*/
+
+int ec_master_measure_bus_time(ec_master_t *master)
 {
     ec_datagram_t datagram;
     cycles_t cycles_start, cycles_end, cycles_timeout;
@@ -1054,7 +1055,7 @@
     if (ec_datagram_brd(&datagram, 0x130, 2)) {
         EC_ERR("Failed to allocate datagram for bus time measuring.\n");
         ec_datagram_clear(&datagram);
-        return;
+        return -1;
     }
 
     cycles_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000);
@@ -1093,11 +1094,13 @@
 
     EC_INFO("Bus time is (min/avg/max) %u/%u.%u/%u us.\n",
             min, sum / 100, sum % 100, max);
+    return 0;
 
   error:
     // Dequeue and free datagram
     list_del(&datagram.queue);
     ec_datagram_clear(&datagram);
+    return -1;
 }
 
 /******************************************************************************
--- a/master/master.h	Mon Sep 25 17:28:31 2006 +0000
+++ b/master/master.h	Tue Sep 26 16:38:38 2006 +0000
@@ -44,6 +44,7 @@
 #include <linux/list.h>
 #include <linux/sysfs.h>
 #include <linux/timer.h>
+#include <asm/atomic.h>
 
 #include "device.h"
 #include "domain.h"
@@ -91,7 +92,7 @@
 struct ec_master
 {
     struct list_head list; /**< list item for module's master list */
-    unsigned int reserved; /**< non-zero, if the master is reserved for RT */
+    atomic_t available; /**< zero, if the master is reserved for RT */
     unsigned int index; /**< master index */
 
     struct kobject kobj; /**< kobject */
@@ -158,7 +159,7 @@
 // misc.
 void ec_master_output_stats(ec_master_t *);
 void ec_master_clear_slaves(ec_master_t *);
-void ec_master_measure_bus_time(ec_master_t *);
+int ec_master_measure_bus_time(ec_master_t *);
 
 // other methods
 void ec_sync_config(const ec_sii_sync_t *, const ec_slave_t *, uint8_t *);
--- a/master/module.c	Mon Sep 25 17:28:31 2006 +0000
+++ b/master/module.c	Tue Sep 26 16:38:38 2006 +0000
@@ -401,71 +401,78 @@
 
     if (!(master = ec_find_master(master_index))) goto out_return;
 
-    if (master->reserved) {
+    if (!atomic_dec_and_test(&master->available)) {
+        atomic_inc(&master->available);
         EC_ERR("Master %i is already in use!\n", master_index);
         goto out_return;
     }
-    master->reserved = 1;
 
     if (!master->device) {
         EC_ERR("Master %i has no assigned device!\n", master_index);
         goto out_release;
     }
 
-    if (!try_module_get(master->device->module)) {
+    if (!try_module_get(master->device->module)) { // possible race?
         EC_ERR("Failed to reserve device module!\n");
         goto out_release;
     }
 
-    ec_master_measure_bus_time(master);
-    ec_master_idle_stop(master);
-    ec_master_reset(master);
+    if (!master->device->link_state) {
+        EC_ERR("Link is DOWN.\n");
+        goto out_module_put;
+    }
+
+    ec_master_reset(master); // also stops idle mode
     master->mode = EC_MASTER_MODE_OPERATION;
 
-    if (!master->device->link_state) EC_WARN("Link is DOWN.\n");
+    if (ec_master_measure_bus_time(master)) {
+        EC_ERR("Bus time measuring failed!\n");
+        goto out_reset;
+    }
 
     if (ec_master_bus_scan(master)) {
         EC_ERR("Bus scan failed!\n");
-        goto out_module_put;
-    }
-
-    EC_INFO("Master %i is ready.\n", master_index);
+        goto out_reset;
+    }
+
+    EC_INFO("Successfully requested master %i.\n", master_index);
     return master;
 
+ out_reset:
+    ec_master_reset(master);
+    ec_master_idle_start(master);
  out_module_put:
     module_put(master->device->module);
+ out_release:
+    atomic_inc(&master->available);
+ out_return:
+    EC_ERR("Failed to request master %i.\n", master_index);
+    return NULL;
+}
+
+/*****************************************************************************/
+
+/**
+   Releases a reserved EtherCAT master.
+   \ingroup RealtimeInterface
+*/
+
+void ecrt_release_master(ec_master_t *master /**< EtherCAT master */)
+{
+    EC_INFO("Releasing master %i...\n", master->index);
+
+    if (atomic_read(&master->available)) {
+        EC_ERR("Master %i was never requested!\n", master->index);
+        return;
+    }
+
     ec_master_reset(master);
     ec_master_idle_start(master);
- out_release:
-    master->reserved = 0;
- out_return:
-    EC_ERR("Failed requesting master %i.\n", master_index);
-    return NULL;
-}
-
-/*****************************************************************************/
-
-/**
-   Releases a reserved EtherCAT master.
-   \ingroup RealtimeInterface
-*/
-
-void ecrt_release_master(ec_master_t *master /**< EtherCAT master */)
-{
-    EC_INFO("Releasing master %i...\n", master->index);
-
-    if (!master->reserved) {
-        EC_ERR("Master %i was never requested!\n", master->index);
-        return;
-    }
-
-    ec_master_reset(master);
-    ec_master_idle_start(master);
 
     module_put(master->device->module);
-    master->reserved = 0;
-
-    EC_INFO("Released master %i.\n", master->index);
+    atomic_inc(&master->available);
+
+    EC_INFO("Successfully released master %i.\n", master->index);
     return;
 }