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