master/device.c
changeset 1011 a0759d0dded4
parent 986 a486591ba86b
child 1029 61ffe5f22306
--- a/master/device.c	Tue Jun 17 09:44:46 2008 +0000
+++ b/master/device.c	Tue Jun 17 10:19:52 2008 +0000
@@ -60,12 +60,12 @@
 
 /*****************************************************************************/
 
-/**
-   Device constructor.
-   \return 0 in case of success, else < 0
-*/
-
-int ec_device_init(ec_device_t *device, /**< EtherCAT device */
+/** Constructor.
+ * 
+ * \return 0 in case of success, else < 0
+ */
+int ec_device_init(
+        ec_device_t *device, /**< EtherCAT device */
         ec_master_t *master /**< master owning the device */
         )
 {
@@ -129,11 +129,11 @@
 
 /*****************************************************************************/
 
-/**
-   EtherCAT device destuctor.
-*/
-
-void ec_device_clear(ec_device_t *device /**< EtherCAT device */)
+/** Destuctor.
+ */
+void ec_device_clear(
+        ec_device_t *device /**< EtherCAT device */
+        )
 {
     unsigned int i;
 
@@ -147,11 +147,10 @@
 
 /*****************************************************************************/
 
-/**
-   Associate with net_device.
-*/
-
-void ec_device_attach(ec_device_t *device, /**< EtherCAT device */
+/** Associate with net_device.
+ */
+void ec_device_attach(
+        ec_device_t *device, /**< EtherCAT device */
         struct net_device *net_dev, /**< net_device structure */
         ec_pollfunc_t poll, /**< pointer to device's poll function */
         struct module *module /**< the device's module */
@@ -175,11 +174,11 @@
 
 /*****************************************************************************/
 
-/**
-   Disconnect from net_device.
-*/
-
-void ec_device_detach(ec_device_t *device /**< EtherCAT device */)
+/** Disconnect from net_device.
+ */
+void ec_device_detach(
+        ec_device_t *device /**< EtherCAT device */
+        )
 {
     unsigned int i;
 
@@ -196,12 +195,13 @@
 
 /*****************************************************************************/
 
-/**
-   Opens the EtherCAT device.
-   \return 0 in case of success, else < 0
-*/
-
-int ec_device_open(ec_device_t *device /**< EtherCAT device */)
+/** Opens the EtherCAT device.
+ *
+ * \return 0 in case of success, else < 0
+ */
+int ec_device_open(
+        ec_device_t *device /**< EtherCAT device */
+        )
 {
     if (!device->dev) {
         EC_ERR("No net_device to open!\n");
@@ -224,12 +224,13 @@
 
 /*****************************************************************************/
 
-/**
-   Stops the EtherCAT device.
-   \return 0 in case of success, else < 0
-*/
-
-int ec_device_close(ec_device_t *device /**< EtherCAT device */)
+/** Stops the EtherCAT device.
+ *
+ * \return 0 in case of success, else < 0
+ */
+int ec_device_close(
+        ec_device_t *device /**< EtherCAT device */
+        )
 {
     if (!device->dev) {
         EC_ERR("No device to close!\n");
@@ -248,12 +249,13 @@
 
 /*****************************************************************************/
 
-/**
-   Returns a pointer to the device's transmit memory.
-   \return pointer to the TX socket buffer
-*/
-
-uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT device */)
+/** Returns a pointer to the device's transmit memory.
+ *
+ * \return pointer to the TX socket buffer
+ */
+uint8_t *ec_device_tx_data(
+        ec_device_t *device /**< EtherCAT device */
+        )
 {
     /* cycle through socket buffers, because otherwise there is a race
      * condition, if multiple frames are sent and the DMA is not scheduled in
@@ -265,15 +267,15 @@
 
 /*****************************************************************************/
 
-/**
-   Sends the content of the transmit socket buffer.
-   Cuts the socket buffer content to the (now known) size, and calls the
-   start_xmit() function of the assigned net_device.
-*/
-
-void ec_device_send(ec_device_t *device, /**< EtherCAT device */
-                    size_t size /**< number of bytes to send */
-                    )
+/** Sends the content of the transmit socket buffer.
+ *
+ * Cuts the socket buffer content to the (now known) size, and calls the
+ * start_xmit() function of the assigned net_device.
+ */
+void ec_device_send(
+        ec_device_t *device, /**< EtherCAT device */
+        size_t size /**< number of bytes to send */
+        )
 {
     struct sk_buff *skb = device->tx_skb[device->tx_ring_index];
 
@@ -304,10 +306,8 @@
 /*****************************************************************************/
 
 #ifdef EC_DEBUG_RING
-/**
- * Appends frame data to the debug ring.
- */
-
+/** Appends frame data to the debug ring.
+ */
 void ec_device_debug_ring_append(
         ec_device_t *device, /**< EtherCAT device */
         ec_debug_frame_dir_t dir, /**< direction */
@@ -333,10 +333,8 @@
 
 /*****************************************************************************/
 
-/**
- * Outputs the debug ring.
- */
-
+/** Outputs the debug ring.
+ */
 void ec_device_debug_ring_print(
         const ec_device_t *device /**< EtherCAT device */
         )
@@ -376,14 +374,15 @@
 
 /*****************************************************************************/
 
-/**
-   Calls the poll function of the assigned net_device.
-   The master itself works without using interrupts. Therefore the processing
-   of received data and status changes of the network device has to be
-   done by the master calling the ISR "manually".
-*/
-
-void ec_device_poll(ec_device_t *device /**< EtherCAT device */)
+/** Calls the poll function of the assigned net_device.
+ *
+ * The master itself works without using interrupts. Therefore the processing
+ * of received data and status changes of the network device has to be
+ * done by the master calling the ISR "manually".
+ */
+void ec_device_poll(
+        ec_device_t *device /**< EtherCAT device */
+        )
 {
     device->cycles_poll = get_cycles();
     device->jiffies_poll = jiffies;
@@ -397,17 +396,80 @@
  *  Device interface
  *****************************************************************************/
 
-/**
-   Accepts a received frame.
-   Forwards the received data to the master. The master will analyze the frame
-   and dispatch the received commands to the sending instances.
-   \ingroup DeviceInterface
-*/
-
-void ecdev_receive(ec_device_t *device, /**< EtherCAT device */
-                   const void *data, /**< pointer to received data */
-                   size_t size /**< number of bytes received */
-                   )
+/** Withdraws an EtherCAT device from the master.
+ *
+ * The device is disconnected from the master and all device ressources
+ * are freed.
+ *
+ * \attention Before calling this function, the ecdev_stop() function has
+ *            to be called, to be sure that the master does not use the device
+ *            any more.
+ * \ingroup DeviceInterface
+ */
+void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
+{
+    ec_master_t *master = device->master;
+    char str[20];
+
+    ec_mac_print(device->dev->dev_addr, str);
+    EC_INFO("Master %u releasing main device %s.\n", master->index, str);
+    
+    down(&master->device_sem);
+    ec_device_detach(device);
+    up(&master->device_sem);
+}
+
+/*****************************************************************************/
+
+/** Opens the network device and makes the master enter IDLE mode.
+ *
+ * \return 0 on success, else < 0
+ * \ingroup DeviceInterface
+ */
+int ecdev_open(ec_device_t *device /**< EtherCAT device */)
+{
+    if (ec_device_open(device)) {
+        EC_ERR("Failed to open device!\n");
+        return -1;
+    }
+
+    if (ec_master_enter_idle_mode(device->master)) {
+        EC_ERR("Failed to enter idle mode!\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+/** Makes the master leave IDLE mode and closes the network device.
+ *
+ * \return 0 on success, else < 0
+ * \ingroup DeviceInterface
+ */
+void ecdev_close(ec_device_t *device /**< EtherCAT device */)
+{
+    ec_master_leave_idle_mode(device->master);
+
+    if (ec_device_close(device))
+        EC_WARN("Failed to close device!\n");
+}
+
+/*****************************************************************************/
+
+/** Accepts a received frame.
+ *
+ * Forwards the received data to the master. The master will analyze the frame
+ * and dispatch the received commands to the sending instances.
+ * 
+ * \ingroup DeviceInterface
+ */
+void ecdev_receive(
+        ec_device_t *device, /**< EtherCAT device */
+        const void *data, /**< pointer to received data */
+        size_t size /**< number of bytes received */
+        )
 {
     const void *ec_data = data + ETH_HLEN;
     size_t ec_size = size - ETH_HLEN;
@@ -430,19 +492,20 @@
 
 /*****************************************************************************/
 
-/**
-   Sets a new link state.
-   If the device notifies the master about the link being down, the master
-   will not try to send frames using this device.
-   \ingroup DeviceInterface
-*/
-
-void ecdev_set_link(ec_device_t *device, /**< EtherCAT device */
+/** Sets a new link state.
+ *
+ * If the device notifies the master about the link being down, the master
+ * will not try to send frames using this device.
+ * 
+ * \ingroup DeviceInterface
+ */
+void ecdev_set_link(
+        ec_device_t *device, /**< EtherCAT device */
         uint8_t state /**< new link state */
         )
 {
     if (unlikely(!device)) {
-        EC_WARN("ecdev_link_state: no device!\n");
+        EC_WARN("ecdev_set_link(): No device!\n");
         return;
     }
 
@@ -454,15 +517,16 @@
 
 /*****************************************************************************/
 
-/**
-   Reads the link state.
-   \ingroup DeviceInterface
-*/
-
-uint8_t ecdev_get_link(ec_device_t *device /**< EtherCAT device */)
+/** Reads the link state.
+ *
+ * \ingroup DeviceInterface
+ */
+uint8_t ecdev_get_link(
+        const ec_device_t *device /**< EtherCAT device */
+        )
 {
     if (unlikely(!device)) {
-        EC_WARN("ecdev_link_state: no device!\n");
+        EC_WARN("ecdev_get_link(): No device!\n");
         return 0;
     }
 
@@ -473,6 +537,9 @@
 
 /** \cond */
 
+EXPORT_SYMBOL(ecdev_withdraw);
+EXPORT_SYMBOL(ecdev_open);
+EXPORT_SYMBOL(ecdev_close);
 EXPORT_SYMBOL(ecdev_receive);
 EXPORT_SYMBOL(ecdev_get_link);
 EXPORT_SYMBOL(ecdev_set_link);