master/master.c
changeset 1500 ed1a733efbc5
parent 1489 f77a1182b6f4
child 1507 68e89abadd19
--- a/master/master.c	Fri Jul 10 10:40:05 2009 +0000
+++ b/master/master.c	Mon Jul 13 15:18:28 2009 +0000
@@ -146,6 +146,9 @@
     INIT_LIST_HEAD(&master->datagram_queue);
     master->datagram_index = 0;
 
+    INIT_LIST_HEAD(&master->ext_datagram_queue);
+    init_MUTEX(&master->ext_queue_sem);
+
     INIT_LIST_HEAD(&master->domains);
 
     master->debug_level = debug_level;
@@ -163,9 +166,10 @@
 #endif
 
     init_MUTEX(&master->io_sem);
-    master->request_cb = NULL;
-    master->release_cb = NULL;
-    master->cb_data = NULL;
+    master->send_cb = NULL;
+    master->receive_cb = NULL;
+    master->app_send_cb = NULL;
+    master->app_receive_cb = NULL;
 
     INIT_LIST_HEAD(&master->sii_requests);
     init_waitqueue_head(&master->sii_queue);
@@ -375,22 +379,27 @@
 
 /*****************************************************************************/
 
-/** Internal locking callback.
- */
-int ec_master_request_cb(void *data /**< callback data */)
-{
-    ec_master_t *master = (ec_master_t *) data;
+/** Internal sending callback.
+ */
+void ec_master_internal_send_cb(
+        ec_master_t *master /**< EtherCAT master. */
+        )
+{
     down(&master->io_sem);
-    return 0;
-}
-
-/*****************************************************************************/
-
-/** Internal unlocking callback.
- */
-void ec_master_release_cb(void *data /**< callback data */)
-{
-    ec_master_t *master = (ec_master_t *) data;
+    ecrt_master_send_ext(master);
+    up(&master->io_sem);
+}
+
+/*****************************************************************************/
+
+/** Internal receiving callback.
+ */
+void ec_master_internal_receive_cb(
+        ec_master_t *master /**< EtherCAT master. */
+        )
+{
+    down(&master->io_sem);
+    ecrt_master_receive(master);
     up(&master->io_sem);
 }
 
@@ -462,9 +471,8 @@
     if (master->debug_level)
         EC_DBG("ORPHANED -> IDLE.\n");
 
-    master->request_cb = ec_master_request_cb;
-    master->release_cb = ec_master_release_cb;
-    master->cb_data = master;
+    master->send_cb = ec_master_internal_send_cb;
+    master->receive_cb = ec_master_internal_receive_cb;
 
     master->phase = EC_IDLE;
     ret = ec_master_thread_start(master, ec_master_idle_thread,
@@ -564,9 +572,8 @@
 #endif
 
     master->phase = EC_OPERATION;
-    master->ext_request_cb = NULL;
-    master->ext_release_cb = NULL;
-    master->ext_cb_data = NULL;
+    master->app_send_cb = NULL;
+    master->app_receive_cb = NULL;
     return ret;
     
 out_allow:
@@ -597,9 +604,8 @@
 #endif
     ec_master_thread_stop(master);
     
-    master->request_cb = ec_master_request_cb;
-    master->release_cb = ec_master_release_cb;
-    master->cb_data = master;
+    master->send_cb = ec_master_internal_send_cb;
+    master->receive_cb = ec_master_internal_receive_cb;
     
     down(&master->master_sem);
     ec_master_clear_domains(master);
@@ -646,9 +652,10 @@
 
 /** Places a datagram in the datagram queue.
  */
-void ec_master_queue_datagram(ec_master_t *master, /**< EtherCAT master */
-                              ec_datagram_t *datagram /**< datagram */
-                              )
+void ec_master_queue_datagram(
+        ec_master_t *master, /**< EtherCAT master */
+        ec_datagram_t *datagram /**< datagram */
+        )
 {
     ec_datagram_t *queued_datagram;
 
@@ -669,6 +676,20 @@
 
 /*****************************************************************************/
 
+/** Places a datagram in the non-application datagram queue.
+ */
+void ec_master_queue_datagram_ext(
+        ec_master_t *master, /**< EtherCAT master */
+        ec_datagram_t *datagram /**< datagram */
+        )
+{
+    down(&master->ext_queue_sem);
+    list_add_tail(&datagram->queue, &master->ext_datagram_queue);
+    up(&master->ext_queue_sem);
+}
+
+/*****************************************************************************/
+
 /** Sends the datagrams in the queue.
  *
  * \return 0 in case of success, else < 0
@@ -1048,8 +1069,8 @@
     if (list_empty(&master->eoe_handlers))
         return;
 
-    if (!master->request_cb || !master->release_cb) {
-        EC_WARN("No EoE processing because of missing locking callbacks!\n");
+    if (!master->send_cb || !master->receive_cb) {
+        EC_WARN("No EoE processing because of missing callbacks!\n");
         return;
     }
 
@@ -1109,11 +1130,7 @@
             goto schedule;
 
         // receive datagrams
-        if (master->request_cb(master->cb_data))
-            goto schedule;
-        
-        ecrt_master_receive(master);
-        master->release_cb(master->cb_data);
+        master->receive_cb(master);
 
         // actual EoE processing
         sth_to_send = 0;
@@ -1128,15 +1145,13 @@
         }
 
         if (sth_to_send) {
-            // send datagrams
-            if (master->request_cb(master->cb_data)) {
-                goto schedule;
-            }
             list_for_each_entry(eoe, &master->eoe_handlers, list) {
                 ec_eoe_queue(eoe);
             }
-            ecrt_master_send(master);
-            master->release_cb(master->cb_data);
+            // (try to) send datagrams
+            down(&master->ext_queue_sem);
+            master->send_cb(master);
+            up(&master->ext_queue_sem);
         }
 
 schedule:
@@ -1641,9 +1656,9 @@
 
     master->injection_seq_fsm = 0;
     master->injection_seq_rt = 0;
-    master->request_cb = master->ext_request_cb;
-    master->release_cb = master->ext_release_cb;
-    master->cb_data = master->ext_cb_data;
+
+    master->send_cb = master->app_send_cb;
+    master->receive_cb = master->app_receive_cb;
     
     ret = ec_master_thread_start(master, ec_master_operation_thread,
                 "EtherCAT-OP");
@@ -1735,6 +1750,21 @@
 
 /*****************************************************************************/
 
+void ecrt_master_send_ext(ec_master_t *master)
+{
+    ec_datagram_t *datagram, *next;
+
+    list_for_each_entry_safe(datagram, next, &master->ext_datagram_queue,
+            queue) {
+        list_del(&datagram->queue);
+        ec_master_queue_datagram(master, datagram);
+    }
+
+    ecrt_master_send(master);
+}
+
+/*****************************************************************************/
+
 /** Same as ecrt_master_slave_config(), but with ERR_PTR() return value.
  */
 ec_slave_config_t *ecrt_master_slave_config_err(ec_master_t *master,
@@ -1805,17 +1835,16 @@
 
 /*****************************************************************************/
 
-void ecrt_master_callbacks(ec_master_t *master, int (*request_cb)(void *),
-        void (*release_cb)(void *), void *cb_data)
+void ecrt_master_callbacks(ec_master_t *master,
+        void (*send_cb)(ec_master_t *), void (*receive_cb)(ec_master_t *))
 {
     if (master->debug_level)
-        EC_DBG("ecrt_master_callbacks(master = 0x%x, request_cb = 0x%x, "
-                " release_cb = 0x%x, cb_data = 0x%x)\n", (u32) master,
-                (u32) request_cb, (u32) release_cb, (u32) cb_data);
-
-    master->ext_request_cb = request_cb;
-    master->ext_release_cb = release_cb;
-    master->ext_cb_data = cb_data;
+        EC_DBG("ecrt_master_callbacks(master = 0x%x, send_cb = 0x%x, "
+                " receive_cb = 0x%x)\n", (u32) master, (u32) send_cb,
+                (u32) receive_cb);
+
+    master->app_send_cb = send_cb;
+    master->app_receive_cb = receive_cb;
 }
 
 /*****************************************************************************/
@@ -1862,6 +1891,7 @@
 EXPORT_SYMBOL(ecrt_master_create_domain);
 EXPORT_SYMBOL(ecrt_master_activate);
 EXPORT_SYMBOL(ecrt_master_send);
+EXPORT_SYMBOL(ecrt_master_send_ext);
 EXPORT_SYMBOL(ecrt_master_receive);
 EXPORT_SYMBOL(ecrt_master_callbacks);
 EXPORT_SYMBOL(ecrt_master_slave_config);