drivers/ec_device.c
changeset 0 05c992bf5847
child 2 b0a7a4745bf9
equal deleted inserted replaced
-1:000000000000 0:05c992bf5847
       
     1 /****************************************************************
       
     2  *
       
     3  *  e c _ d e v i c e . c
       
     4  *
       
     5  *  Methoden für ein EtherCAT-Gerät.
       
     6  *
       
     7  *  $Date$
       
     8  *  $Author$
       
     9  *
       
    10  ***************************************************************/
       
    11 
       
    12 #include <linux/skbuff.h>
       
    13 #include <linux/if_ether.h>
       
    14 #include <linux/netdevice.h>
       
    15 #include <rtai.h>
       
    16 
       
    17 #include "ec_device.h"
       
    18 #include "ec_dbg.h"
       
    19 
       
    20 /***************************************************************/
       
    21 
       
    22 /**
       
    23    EtherCAT-Geräte-Konstuktor.
       
    24    
       
    25    Initialisiert ein EtherCAT-Gerät, indem es die Variablen
       
    26    in der Struktur auf die Default-Werte setzt.
       
    27 
       
    28    @param ecd Zu initialisierendes EtherCAT-Gerät
       
    29 */
       
    30 
       
    31 void EtherCAT_device_init(EtherCAT_device_t *ecd)
       
    32 {
       
    33   ecd->dev = NULL;
       
    34   ecd->tx_skb = NULL;
       
    35   ecd->rx_skb = NULL;
       
    36   ecd->tx_time = 0;
       
    37   ecd->rx_time = 0;
       
    38   ecd->tx_intr_cnt = 0;
       
    39   ecd->rx_intr_cnt = 0;
       
    40   ecd->intr_cnt = 0;
       
    41   ecd->state = ECAT_DS_READY;
       
    42   ecd->rx_data_length = 0;
       
    43   ecd->lock = NULL;
       
    44 }
       
    45 
       
    46 /***************************************************************/
       
    47 
       
    48 /**
       
    49    EtherCAT-Geräte-Destuktor.
       
    50    
       
    51    Gibt den dynamisch allozierten Speicher des
       
    52    EtherCAT-Gerätes (die beiden Socket-Buffer) wieder frei.
       
    53 
       
    54    @param ecd EtherCAT-Gerät
       
    55 */
       
    56 
       
    57 void EtherCAT_device_clear(EtherCAT_device_t *ecd)
       
    58 {
       
    59   ecd->dev = NULL;
       
    60 
       
    61   if (ecd->tx_skb)
       
    62   {
       
    63     dev_kfree_skb(ecd->tx_skb);
       
    64     ecd->tx_skb = NULL;
       
    65   }
       
    66 
       
    67   if (ecd->rx_skb)
       
    68   {
       
    69     dev_kfree_skb(ecd->rx_skb);
       
    70     ecd->rx_skb = NULL;
       
    71   }
       
    72 }
       
    73 
       
    74 /***************************************************************/
       
    75 
       
    76 /**
       
    77    Weist einem EtherCAT-Gerät das entsprechende net_device zu.
       
    78    
       
    79    Prüft das net_device, allokiert Socket-Buffer in Sende- und
       
    80    Empfangsrichtung und weist dem EtherCAT-Gerät und den
       
    81    Socket-Buffern das net_device zu.
       
    82 
       
    83    @param ecd EtherCAT-Device
       
    84    @param dev net_device
       
    85 
       
    86    @return 0: Erfolg, < 0: Konnte Socket-Buffer nicht allozieren.
       
    87 */
       
    88 
       
    89 int EtherCAT_device_assign(EtherCAT_device_t *ecd,
       
    90                            struct net_device *dev)
       
    91 {
       
    92   if (!dev)
       
    93   {
       
    94     EC_DBG("EtherCAT: Device is NULL!\n");
       
    95     return -1;
       
    96   }
       
    97 
       
    98   if ((ecd->tx_skb = dev_alloc_skb(ECAT_FRAME_BUFFER_SIZE)) == NULL)
       
    99   {
       
   100     EC_DBG(KERN_ERR "EtherCAT: Could not allocate device tx socket buffer!\n");
       
   101     return -1;
       
   102   }
       
   103 
       
   104   if ((ecd->rx_skb = dev_alloc_skb(ECAT_FRAME_BUFFER_SIZE)) == NULL)
       
   105   {
       
   106     dev_kfree_skb(ecd->tx_skb);
       
   107     ecd->tx_skb = NULL;
       
   108 
       
   109     EC_DBG(KERN_ERR "EtherCAT: Could not allocate device rx socket buffer!\n");
       
   110     return -1;
       
   111   }
       
   112 
       
   113   ecd->dev = dev;
       
   114   ecd->tx_skb->dev = dev;
       
   115   ecd->rx_skb->dev = dev;
       
   116 
       
   117   EC_DBG("EtherCAT: Assigned Device %X.\n", (unsigned) dev);
       
   118 
       
   119   return 0;
       
   120 }
       
   121 
       
   122 /***************************************************************/
       
   123 
       
   124 /**
       
   125    Führt die open()-Funktion des Netzwerktreibers aus.
       
   126 
       
   127    Dies entspricht einem "ifconfig up". Vorher wird der Zeiger
       
   128    auf das EtherCAT-Gerät auf Gültigkeit geprüft und der
       
   129    Gerätezustand zurückgesetzt.
       
   130 
       
   131    @param ecd EtherCAT-Gerät
       
   132 
       
   133    @return 0 bei Erfolg, < 0: Ungültiger Zeiger, oder open()
       
   134    fehlgeschlagen
       
   135 */
       
   136 
       
   137 int EtherCAT_device_open(EtherCAT_device_t *ecd)
       
   138 {
       
   139   if (!ecd)
       
   140   {
       
   141     EC_DBG(KERN_ERR "EtherCAT: Trying to open a NULL device!\n");
       
   142     return -1;
       
   143   }
       
   144 
       
   145   if (!ecd->dev)
       
   146   {
       
   147     EC_DBG(KERN_ERR "EtherCAT: No device to open!\n");
       
   148     return -1;
       
   149   }
       
   150 
       
   151   // Reset old device state
       
   152   ecd->state = ECAT_DS_READY;
       
   153   ecd->tx_intr_cnt = 0;
       
   154   ecd->rx_intr_cnt = 0;
       
   155 
       
   156   return ecd->dev->open(ecd->dev);
       
   157 }
       
   158 
       
   159 /***************************************************************/
       
   160 
       
   161 /**
       
   162    Führt die stop()-Funktion des net_devices aus.
       
   163 
       
   164    @param ecd EtherCAT-Gerät
       
   165 
       
   166    @return 0 bei Erfolg, < 0: Kein Gerät zum Schliessen
       
   167 */
       
   168 
       
   169 int EtherCAT_device_close(EtherCAT_device_t *ecd)
       
   170 {
       
   171   if (!ecd->dev)
       
   172   {
       
   173     EC_DBG("EtherCAT: No device to close!\n");
       
   174     return -1;
       
   175   }
       
   176 
       
   177   EC_DBG("EtherCAT: txcnt: %u, rxcnt: %u\n",
       
   178          (unsigned int) ecd->tx_intr_cnt,
       
   179          (unsigned int) ecd->rx_intr_cnt);
       
   180 
       
   181   EC_DBG("EtherCAT: Stopping device at 0x%X\n",
       
   182          (unsigned int) ecd->dev);
       
   183 
       
   184   return ecd->dev->stop(ecd->dev);
       
   185 }
       
   186 
       
   187 /***************************************************************/
       
   188 
       
   189 /**
       
   190    Sendet einen Rahmen über das EtherCAT-Gerät.
       
   191 
       
   192    Kopiert die zu sendenden Daten in den statischen Socket-
       
   193    Buffer, fügt den Ethernat-II-Header hinzu und ruft die
       
   194    start_xmit()-Funktion der Netzwerkkarte auf.
       
   195 
       
   196    @param ecd EtherCAT-Gerät
       
   197    @param data Zeiger auf die zu sendenden Daten
       
   198    @param length Länge der zu sendenden Daten
       
   199 
       
   200    @return 0 bei Erfolg, < 0: Vorheriger Rahmen noch
       
   201    nicht empfangen, oder kein Speicher mehr vorhanden
       
   202 */
       
   203 
       
   204 int EtherCAT_device_send(EtherCAT_device_t *ecd,
       
   205                          unsigned char *data,
       
   206                          unsigned int length)
       
   207 {
       
   208   unsigned char *frame_data;
       
   209   struct ethhdr *eth;
       
   210 
       
   211   if (ecd->state == ECAT_DS_SENT)
       
   212   {
       
   213     EC_DBG(KERN_ERR "EtherCAT: Trying to send frame while last was not received!\n");
       
   214     return -1;
       
   215   }
       
   216 
       
   217   skb_trim(ecd->tx_skb, 0); // Clear transmit socket buffer
       
   218   skb_reserve(ecd->tx_skb, ETH_HLEN); // Reserve space for Ethernet-II header
       
   219 
       
   220   // Copy data to socket buffer
       
   221   frame_data = skb_put(ecd->tx_skb, length);
       
   222   memcpy(frame_data, data, length);
       
   223 
       
   224   // Add Ethernet-II-Header
       
   225   if ((eth = (struct ethhdr *) skb_push(ecd->tx_skb, ETH_HLEN)) == NULL)
       
   226   {
       
   227     EC_DBG(KERN_ERR "EtherCAT: device_send - Could not allocate Ethernet-II header!\n");
       
   228     return -1;
       
   229   }
       
   230 
       
   231   eth->h_proto = htons(0x88A4); // Protocol type
       
   232   memcpy(eth->h_source, ecd->dev->dev_addr, ecd->dev->addr_len); // Hardware address
       
   233   memset(eth->h_dest, 0xFF, ecd->dev->addr_len); // Broadcast address
       
   234 
       
   235   rdtscl(ecd->tx_time); // Get CPU cycles
       
   236 
       
   237   // Start sending of frame
       
   238   ecd->state = ECAT_DS_SENT;
       
   239   ecd->dev->hard_start_xmit(ecd->tx_skb, ecd->dev);
       
   240   
       
   241   return 0;
       
   242 }
       
   243 
       
   244 /***************************************************************/
       
   245 
       
   246 /**
       
   247    Holt einen empfangenen Rahmen von der Netzwerkkarte.
       
   248 
       
   249    Zuerst wird geprüft, ob überhaupt ein Rahmen empfangen
       
   250    wurde. Wenn ja, wird diesem mit Hilfe eines Spin-Locks
       
   251    in den angegebenen Speicherbereich kopiert.
       
   252 
       
   253    @param ecd EtherCAT-Gerät
       
   254    @param data Zeiger auf den Speicherbereich, in den die
       
   255    empfangenen Daten kopiert werden sollen
       
   256    @param size Größe des angegebenen Speicherbereichs
       
   257 
       
   258    @return Anzahl der kopierten Bytes bei Erfolg, sonst < 0
       
   259 */
       
   260 
       
   261 int EtherCAT_device_receive(EtherCAT_device_t *ecd, 
       
   262                             unsigned char *data,
       
   263                             unsigned int size)
       
   264 {
       
   265   int cnt;
       
   266 //  unsigned long flags;
       
   267   
       
   268   if (ecd->state != ECAT_DS_RECEIVED)
       
   269   {
       
   270     EC_DBG(KERN_ERR "EtherCAT: receive - Nothing received!\n");
       
   271     return -1;
       
   272   }
       
   273     
       
   274 //  flags = rt_spin_lock_irqsave(ecd->lock);
       
   275 
       
   276   cnt = min(ecd->rx_data_length, size);
       
   277   memcpy(data,ecd->rx_data, cnt);
       
   278 
       
   279 //  rt_spin_unlock_irqrestore(ecd->lock, flags);
       
   280 
       
   281   return cnt;
       
   282 }
       
   283 
       
   284 /***************************************************************/
       
   285 
       
   286 /**
       
   287    Gibt alle Informationen über das Device-Objekt aus.
       
   288 
       
   289    @param ecd EtherCAT-Gerät
       
   290 */
       
   291 
       
   292 void EtherCAT_device_debug(EtherCAT_device_t *ecd)
       
   293 {
       
   294   EC_DBG(KERN_DEBUG "---EtherCAT device information begin---\n");
       
   295 
       
   296   if (ecd)
       
   297   {
       
   298     EC_DBG(KERN_DEBUG "Assigned net_device: %X\n", (unsigned) ecd->dev);
       
   299     EC_DBG(KERN_DEBUG "Transmit socket buffer: %X\n", (unsigned) ecd->tx_skb);
       
   300     EC_DBG(KERN_DEBUG "Receive socket buffer: %X\n", (unsigned) ecd->rx_skb);
       
   301     EC_DBG(KERN_DEBUG "Time of last transmission: %u\n", (unsigned) ecd->tx_time);
       
   302     EC_DBG(KERN_DEBUG "Time of last receive: %u\n", (unsigned) ecd->rx_time);
       
   303     EC_DBG(KERN_DEBUG "Number of transmit interrupts: %u\n", (unsigned) ecd->tx_intr_cnt);
       
   304     EC_DBG(KERN_DEBUG "Number of receive interrupts: %u\n", (unsigned) ecd->rx_intr_cnt);
       
   305     EC_DBG(KERN_DEBUG "Total Number of interrupts: %u\n", (unsigned) ecd->intr_cnt);
       
   306     EC_DBG(KERN_DEBUG "Actual device state: %i\n", (int) ecd->state);
       
   307     EC_DBG(KERN_DEBUG "Receive buffer: %X\n", (unsigned) ecd->rx_data);
       
   308     EC_DBG(KERN_DEBUG "Receive buffer fill state: %u/%u\n",
       
   309            (unsigned) ecd->rx_data_length, ECAT_FRAME_BUFFER_SIZE);
       
   310     EC_DBG(KERN_DEBUG "Lock: %X\n", (unsigned) ecd->lock);
       
   311   }
       
   312   else
       
   313   {
       
   314     EC_DBG(KERN_DEBUG "Device is NULL!\n");
       
   315   }
       
   316 
       
   317   EC_DBG(KERN_DEBUG "---EtherCAT device information end---\n");
       
   318 }
       
   319 
       
   320 /***************************************************************/