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