drivers/ec_master.c
changeset 17 1b5aea4d5147
parent 15 72d95aa70c1d
child 19 a51289e6cb2d
equal deleted inserted replaced
16:f04e93b8af0f 17:1b5aea4d5147
    32 */
    32 */
    33 
    33 
    34 int EtherCAT_master_init(EtherCAT_master_t *master,
    34 int EtherCAT_master_init(EtherCAT_master_t *master,
    35                          EtherCAT_device_t *dev)
    35                          EtherCAT_device_t *dev)
    36 {
    36 {
    37   unsigned int i;
       
    38 
       
    39   if (!dev)
    37   if (!dev)
    40   {
    38   {
    41     EC_DBG(KERN_ERR "EtherCAT: Master init without device!\n");
    39     EC_DBG(KERN_ERR "EtherCAT: Master init without device!\n");
    42     return -1;
    40     return -1;
    43   }
    41   }
    44 
    42 
    45   master->slaves = NULL;
    43   master->slaves = NULL;
    46   master->slave_count = 0;
    44   master->slave_count = 0;
    47   //master->first_command = NULL;
       
    48   //master->process_data_command = NULL;
       
    49   master->dev = dev;
    45   master->dev = dev;
    50   master->command_index = 0x00;
    46   master->command_index = 0x00;
    51   master->tx_data_length = 0;
    47   master->tx_data_length = 0;
    52   master->process_data = NULL;
    48   master->process_data = NULL;
    53   master->process_data_length = 0;
    49   master->process_data_length = 0;
    54   //master->cmd_ring_index = 0;
       
    55   master->debug_level = 0;
    50   master->debug_level = 0;
    56 
       
    57 #if 0
       
    58   for (i = 0; i < ECAT_COMMAND_RING_SIZE; i++)
       
    59   {
       
    60     EtherCAT_command_init(&master->cmd_ring[i]);
       
    61     master->cmd_reserved[i] = 0;
       
    62   }
       
    63 #endif
       
    64 
    51 
    65   return 0;
    52   return 0;
    66 }
    53 }
    67 
    54 
    68 /***************************************************************/
    55 /***************************************************************/
    76    @param master Zeiger auf den zu löschenden Master
    63    @param master Zeiger auf den zu löschenden Master
    77 */
    64 */
    78 
    65 
    79 void EtherCAT_master_clear(EtherCAT_master_t *master)
    66 void EtherCAT_master_clear(EtherCAT_master_t *master)
    80 {
    67 {
    81 #if 0
       
    82   // Remove all pending commands
       
    83   while (master->first_command)
       
    84   {
       
    85     EtherCAT_remove_command(master, master->first_command);
       
    86   }
       
    87 #endif
       
    88 
       
    89   // Remove all slaves
    68   // Remove all slaves
    90   EtherCAT_clear_slaves(master);
    69   EtherCAT_clear_slaves(master);
    91 
    70 
    92   if (master->process_data)
    71   if (master->process_data)
    93   {
    72   {
    95     master->process_data = NULL;
    74     master->process_data = NULL;
    96   }
    75   }
    97 
    76 
    98   master->process_data_length = 0;
    77   master->process_data_length = 0;
    99 }
    78 }
   100 
       
   101 /***************************************************************/
       
   102 
       
   103 /**
       
   104    Überprüft die angeschlossenen Slaves.
       
   105 
       
   106    Vergleicht die an den Bus angeschlossenen Slaves mit
       
   107    den im statischen-Slave-Array vorgegebenen Konfigurationen.
       
   108    Stimmen Anzahl oder Typen nicht überein, gibt diese
       
   109    Methode einen Fehler aus.
       
   110 
       
   111    @param master Der EtherCAT-Master
       
   112    @param slaves Zeiger auf ein statisches Slave-Array
       
   113    @param slave_count Anzahl der Slaves im Array
       
   114 
       
   115    @return 0 bei Erfolg, sonst < 0
       
   116 */
       
   117 
       
   118 int EtherCAT_check_slaves(EtherCAT_master_t *master,
       
   119                           EtherCAT_slave_t *slaves,
       
   120                           unsigned int slave_count)
       
   121 {
       
   122   EtherCAT_command_t cmd;
       
   123   EtherCAT_slave_t *cur;
       
   124   unsigned int i, j, found, length, pos;
       
   125   unsigned char data[2];
       
   126 
       
   127   // EtherCAT_clear_slaves() must be called before!
       
   128   if (master->slaves || master->slave_count)
       
   129   {
       
   130     EC_DBG(KERN_ERR "EtherCAT duplicate slave check!");
       
   131     return -1;
       
   132   }
       
   133 
       
   134   // No slaves.
       
   135   if (slave_count == 0)
       
   136   {
       
   137     EC_DBG(KERN_ERR "EtherCAT: No slaves in list!");
       
   138     return -1;
       
   139   }
       
   140 
       
   141   // Determine number of slaves on bus
       
   142 
       
   143   EtherCAT_command_broadcast_read(&cmd, 0x0000, 4);
       
   144 
       
   145   if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -1;
       
   146 
       
   147   if (cmd.working_counter != slave_count)
       
   148   {
       
   149     EC_DBG(KERN_ERR "EtherCAT: Wrong number of slaves on bus: %i / %i\n",
       
   150            cmd.working_counter, slave_count);
       
   151     return -1;
       
   152   }
       
   153   else
       
   154   {
       
   155     EC_DBG("EtherCAT: Found all %i slaves.\n", slave_count);
       
   156   }
       
   157 
       
   158   // For every slave in the list
       
   159   for (i = 0; i < slave_count; i++)
       
   160   {
       
   161     cur = &slaves[i];
       
   162 
       
   163     if (!cur->desc)
       
   164     {
       
   165       EC_DBG(KERN_ERR "EtherCAT: Slave %i has no description.\n", i);
       
   166       return -1;
       
   167     }
       
   168 
       
   169     // Set ring position
       
   170     cur->ring_position = -i;
       
   171     cur->station_address = i + 1;
       
   172 
       
   173     // Write station address
       
   174 
       
   175     data[0] = cur->station_address & 0x00FF;
       
   176     data[1] = (cur->station_address & 0xFF00) >> 8;
       
   177 
       
   178     EtherCAT_command_position_write(&cmd, cur->ring_position, 0x0010, 2, data);
       
   179     if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -1;
       
   180 
       
   181     if (cmd.working_counter != 1)
       
   182     {
       
   183       EC_DBG(KERN_ERR "EtherCAT: Slave %i did not repond while writing station address!\n", i);
       
   184       return -1;
       
   185     }
       
   186 
       
   187     // Read base data
       
   188 
       
   189     EtherCAT_command_read(&cmd, cur->station_address, 0x0000, 4);
       
   190     if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -1;
       
   191 
       
   192     if (cmd.working_counter != 1)
       
   193     {
       
   194       EC_DBG(KERN_ERR "EtherCAT: Slave %i did not respond while reading base data!\n", i);
       
   195       return -1;
       
   196     }
       
   197 
       
   198     // Get base data
       
   199     cur->type = cmd.data[0];
       
   200     cur->revision = cmd.data[1];
       
   201     cur->build = cmd.data[2] | (cmd.data[3] << 8);
       
   202 
       
   203     // Read identification from "Slave Information Interface" (SII)
       
   204 
       
   205     if (EtherCAT_read_slave_information(master, cur->station_address,
       
   206                                         0x0008, &cur->vendor_id) != 0)
       
   207     {
       
   208       EC_DBG(KERN_ERR "EtherCAT: Could not read SII vendor id!\n");
       
   209       return -1;
       
   210     }
       
   211 
       
   212     if (EtherCAT_read_slave_information(master, cur->station_address,
       
   213                                         0x000A, &cur->product_code) != 0)
       
   214     {
       
   215       EC_DBG(KERN_ERR "EtherCAT: Could not read SII product code!\n");
       
   216       return -1;
       
   217     }
       
   218 
       
   219     if (EtherCAT_read_slave_information(master, cur->station_address,
       
   220                                         0x000C, &cur->revision_number) != 0)
       
   221     {
       
   222       EC_DBG(KERN_ERR "EtherCAT: Could not read SII revision number!\n");
       
   223       return -1;
       
   224     }
       
   225 
       
   226     if (EtherCAT_read_slave_information(master, cur->station_address,
       
   227                                         0x000E, &cur->serial_number) != 0)
       
   228     {
       
   229       EC_DBG(KERN_ERR "EtherCAT: Could not read SII serial number!\n");
       
   230       return -1;
       
   231     }
       
   232 
       
   233     // Search for identification in "database"
       
   234 
       
   235     found = 0;
       
   236 
       
   237     for (j = 0; j < slave_idents_count; j++)
       
   238     {
       
   239       if (slave_idents[j].vendor_id == cur->vendor_id
       
   240           && slave_idents[j].product_code == cur->product_code)
       
   241       {
       
   242         found = 1;
       
   243 
       
   244         if (cur->desc != slave_idents[j].desc)
       
   245         {
       
   246           EC_DBG(KERN_ERR "EtherCAT: Unexpected slave device \"%s %s\""
       
   247                  " at position %i. Expected: \"%s %s\"\n",
       
   248                  slave_idents[j].desc->vendor_name,
       
   249                  slave_idents[j].desc->product_name, i,
       
   250                  cur->desc->vendor_name, cur->desc->product_name);
       
   251           return -1;
       
   252         }
       
   253 
       
   254         break;
       
   255       }
       
   256     }
       
   257 
       
   258     if (!found)
       
   259     {
       
   260       EC_DBG(KERN_ERR "EtherCAT: Unknown slave device"
       
   261              " (vendor %X, code %X) at position %i.\n",
       
   262              i, cur->vendor_id, cur->product_code);
       
   263       return -1;
       
   264     }
       
   265   }
       
   266 
       
   267   length = 0;
       
   268   for (i = 0; i < slave_count; i++)
       
   269   {
       
   270     length += slaves[i].desc->data_length;
       
   271   }
       
   272 
       
   273   if ((master->process_data = (unsigned char *)
       
   274        kmalloc(sizeof(unsigned char) * length, GFP_KERNEL)) == NULL)
       
   275   {
       
   276     EC_DBG(KERN_ERR "EtherCAT: Could not allocate %i bytes for process data.\n", length);
       
   277     return -1;
       
   278   }
       
   279 
       
   280   master->process_data_length = length;
       
   281   memset(master->process_data, 0x00, length);
       
   282 
       
   283   pos = 0;
       
   284   for (i = 0; i < slave_count; i++)
       
   285   {
       
   286     slaves[i].process_data = master->process_data + pos;
       
   287     slaves[i].logical_address0 = pos;
       
   288 
       
   289     EC_DBG(KERN_DEBUG "EtherCAT: Slave %i - Address 0x%X, \"%s %s\", s/n %u\n",
       
   290            i, pos, slaves[i].desc->vendor_name, slaves[i].desc->product_name,
       
   291            slaves[i].serial_number);
       
   292 
       
   293     pos += slaves[i].desc->data_length;
       
   294   }
       
   295 
       
   296   master->slaves = slaves;
       
   297   master->slave_count = slave_count;
       
   298 
       
   299   return 0;
       
   300 }
       
   301 
       
   302 /***************************************************************/
       
   303 
       
   304 /**
       
   305    Entfernt den Zeiger auf das Slave-Array.
       
   306 
       
   307    @param master EtherCAT-Master
       
   308 */
       
   309 
       
   310 void EtherCAT_clear_slaves(EtherCAT_master_t *master)
       
   311 {
       
   312   master->slaves = NULL;
       
   313   master->slave_count = 0;
       
   314 }
       
   315 
       
   316 /***************************************************************/
       
   317 
       
   318 /**
       
   319    Liest Daten aus dem Slave-Information-Interface
       
   320    eines EtherCAT-Slaves.
       
   321 
       
   322    @param master EtherCAT-Master
       
   323    @param node_address Knotenadresse des Slaves
       
   324    @param offset Adresse des zu lesenden SII-Registers
       
   325    @param target Zeiger auf einen 4 Byte großen Speicher
       
   326    zum Ablegen der Daten
       
   327 
       
   328    @return 0 bei Erfolg, sonst < 0
       
   329 */
       
   330 
       
   331 int EtherCAT_read_slave_information(EtherCAT_master_t *master,
       
   332                                     unsigned short int node_address,
       
   333                                     unsigned short int offset,
       
   334                                     unsigned int *target)
       
   335 {
       
   336   EtherCAT_command_t cmd;
       
   337   unsigned char data[10];
       
   338   unsigned int tries_left;
       
   339 
       
   340   // Initiate read operation
       
   341 
       
   342   data[0] = 0x00;
       
   343   data[1] = 0x01;
       
   344   data[2] = offset & 0xFF;
       
   345   data[3] = (offset & 0xFF00) >> 8;
       
   346   data[4] = 0x00;
       
   347   data[5] = 0x00;
       
   348 
       
   349   EtherCAT_command_write(&cmd, node_address, 0x502, 6, data);
       
   350   if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -3;
       
   351 
       
   352   if (cmd.working_counter != 1)
       
   353   {
       
   354     EC_DBG(KERN_ERR "EtherCAT: SII-read - Slave %04X did not respond!\n",
       
   355            node_address);
       
   356     return -4;
       
   357   }
       
   358 
       
   359   // Der Slave legt die Informationen des Slave-Information-Interface
       
   360   // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
       
   361   // den Status auslesen, bis das Bit weg ist.
       
   362 
       
   363   tries_left = 100;
       
   364   while (tries_left)
       
   365   {
       
   366     udelay(10);
       
   367 
       
   368     EtherCAT_command_read(&cmd, node_address, 0x502, 10);
       
   369     if (EtherCAT_simple_send_receive(master, &cmd) != 0) return -3;
       
   370 
       
   371     if (cmd.working_counter != 1)
       
   372     {
       
   373       EC_DBG(KERN_ERR "EtherCAT: SII-read status - Slave %04X did not respond!\n",
       
   374              node_address);
       
   375       return -4;
       
   376     }
       
   377 
       
   378     if ((cmd.data[1] & 0x81) == 0)
       
   379     {
       
   380       memcpy(target, cmd.data + 6, 4);
       
   381       break;
       
   382     }
       
   383 
       
   384     tries_left--;
       
   385   }
       
   386 
       
   387   if (!tries_left)
       
   388   {
       
   389     EC_DBG(KERN_WARNING "EtherCAT: SSI-read. Slave %04X timed out!\n",
       
   390            node_address);
       
   391     return -1;
       
   392   }
       
   393 
       
   394   return 0;
       
   395 }
       
   396 
       
   397 #if 0
       
   398 /***************************************************************/
       
   399 
       
   400 /**
       
   401    Führt ein asynchrones Senden und Empfangen aus.
       
   402 
       
   403    Sendet alle wartenden Kommandos und wartet auf die
       
   404    entsprechenden Antworten.
       
   405 
       
   406    @param master EtherCAT-Master
       
   407 
       
   408    @return 0 bei Erfolg, sonst < 0
       
   409 */
       
   410 
       
   411 int EtherCAT_async_send_receive(EtherCAT_master_t *master)
       
   412 {
       
   413   unsigned int wait_cycles;
       
   414   int i;
       
   415 
       
   416   // Send all commands
       
   417 
       
   418   for (i = 0; i < ECAT_NUM_RETRIES; i++)
       
   419   {
       
   420     if (EtherCAT_send(master) < 0)
       
   421     {
       
   422       return -1;
       
   423     }
       
   424 
       
   425     // Wait until something is received or an error has occurred
       
   426 
       
   427     wait_cycles = 10;
       
   428     EtherCAT_device_call_isr(master->dev);
       
   429 
       
   430     while (master->dev->state == ECAT_DS_SENT && wait_cycles)
       
   431     {
       
   432       udelay(1000);
       
   433       wait_cycles--;
       
   434       EtherCAT_device_call_isr(master->dev);
       
   435     }
       
   436 
       
   437     //EC_DBG("Master async send: tries %d",tries_left);
       
   438 
       
   439     if (!wait_cycles)
       
   440     {
       
   441       EC_DBG(KERN_ERR "EtherCAT: Asynchronous receive timeout.\n");
       
   442       continue;
       
   443     }
       
   444 
       
   445     if (master->dev->state != ECAT_DS_RECEIVED)
       
   446     {
       
   447       EC_DBG(KERN_ERR "EtherCAT: Asyncronous send error. State %i\n", master->dev->state);
       
   448       continue;
       
   449     }
       
   450 
       
   451     // Receive all commands
       
   452     if (EtherCAT_receive(master) < 0)
       
   453     {
       
   454       // Noch mal versuchen
       
   455       master->dev->state = ECAT_DS_READY;
       
   456       EC_DBG("Retry Asynchronous send/recieve: %d", i);
       
   457       continue;
       
   458     }
       
   459 
       
   460     return 0; // Erfolgreich
       
   461   }
       
   462 
       
   463   return -1;
       
   464 }
       
   465 
       
   466 /***************************************************************/
       
   467 
       
   468 /**
       
   469    Sendet alle wartenden Kommandos.
       
   470 
       
   471    Errechnet erst die benötigte Gesamt-Rahmenlänge, und erstellt
       
   472    dann alle Kommando-Bytefolgen im statischen Sendespeicher.
       
   473    Danach wird die Sendefunktion des EtherCAT-Gerätes aufgerufen.
       
   474 
       
   475    @param master EtherCAT-Master
       
   476 
       
   477    @return 0 bei Erfolg, sonst < 0
       
   478 */
       
   479 
       
   480 int EtherCAT_send(EtherCAT_master_t *master)
       
   481 {
       
   482   unsigned int i, length, framelength, pos;
       
   483   EtherCAT_command_t *cmd;
       
   484   int cmdcnt = 0;
       
   485 
       
   486   if (master->debug_level > 0)
       
   487   {
       
   488     EC_DBG(KERN_DEBUG "EtherCAT_send, first_command = %X\n", (int) master->first_command);
       
   489   }
       
   490 
       
   491   length = 0;
       
   492   for (cmd = master->first_command; cmd != NULL; cmd = cmd->next)
       
   493   {
       
   494     if (cmd->state != ECAT_CS_READY) continue;
       
   495     length += cmd->data_length + 12;
       
   496     cmdcnt++;
       
   497   }
       
   498 
       
   499   if (master->debug_level > 0)
       
   500   {
       
   501     EC_DBG(KERN_DEBUG "%i commands to send.\n", cmdcnt);
       
   502   }
       
   503 
       
   504   if (length == 0)
       
   505   {
       
   506     EC_DBG(KERN_WARNING "EtherCAT: Nothing to send...\n");
       
   507     return 0;
       
   508   }
       
   509 
       
   510   framelength = length + 2;
       
   511   if (framelength < 46) framelength = 46;
       
   512 
       
   513   if (master->debug_level > 0)
       
   514   {
       
   515     EC_DBG(KERN_DEBUG "framelength: %i\n", framelength);
       
   516   }
       
   517 
       
   518   master->tx_data[0] = length & 0xFF;
       
   519   master->tx_data[1] = ((length & 0x700) >> 8) | 0x10;
       
   520   pos = 2;
       
   521 
       
   522   for (cmd = master->first_command; cmd != NULL; cmd = cmd->next)
       
   523   {
       
   524     if (cmd->state != ECAT_CS_READY) continue;
       
   525 
       
   526     cmd->index = master->command_index;
       
   527     master->command_index = (master->command_index + 1) % 0x0100;
       
   528 
       
   529     if (master->debug_level > 0)
       
   530     {
       
   531       EC_DBG(KERN_DEBUG "Sending command index %i\n", cmd->index);
       
   532     }
       
   533 
       
   534     cmd->state = ECAT_CS_SENT;
       
   535 
       
   536     master->tx_data[pos + 0] = cmd->type;
       
   537     master->tx_data[pos + 1] = cmd->index;
       
   538 
       
   539     master->tx_data[pos + 2] = cmd->address.raw[0];
       
   540     master->tx_data[pos + 3] = cmd->address.raw[1];
       
   541     master->tx_data[pos + 4] = cmd->address.raw[2];
       
   542     master->tx_data[pos + 5] = cmd->address.raw[3];
       
   543 
       
   544     master->tx_data[pos + 6] = cmd->data_length & 0xFF;
       
   545     master->tx_data[pos + 7] = (cmd->data_length & 0x700) >> 8;
       
   546 
       
   547     if (cmd->next) master->tx_data[pos + 7] |= 0x80;
       
   548 
       
   549     master->tx_data[pos + 8] = 0x00;
       
   550     master->tx_data[pos + 9] = 0x00;
       
   551 
       
   552     if (cmd->type == ECAT_CMD_APWR
       
   553         || cmd->type == ECAT_CMD_NPWR
       
   554         || cmd->type == ECAT_CMD_BWR
       
   555         || cmd->type == ECAT_CMD_LRW) // Write
       
   556     {
       
   557       for (i = 0; i < cmd->data_length; i++) master->tx_data[pos + 10 + i] = cmd->data[i];
       
   558     }
       
   559     else // Read
       
   560     {
       
   561       for (i = 0; i < cmd->data_length; i++) master->tx_data[pos + 10 + i] = 0x00;
       
   562     }
       
   563 
       
   564     master->tx_data[pos + 10 + cmd->data_length] = 0x00;
       
   565     master->tx_data[pos + 11 + cmd->data_length] = 0x00;
       
   566 
       
   567     pos += 12 + cmd->data_length;
       
   568   }
       
   569 
       
   570   // Pad with zeros
       
   571   while (pos < 46) master->tx_data[pos++] = 0x00;
       
   572 
       
   573   master->tx_data_length = framelength;
       
   574 
       
   575 #ifdef DEBUG_SEND_RECEIVE
       
   576   EC_DBG(KERN_DEBUG "\n");
       
   577   EC_DBG(KERN_DEBUG ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
       
   578   EC_DBG(KERN_DEBUG);
       
   579   for (i = 0; i < framelength; i++)
       
   580   {
       
   581     EC_DBG("%02X ", master->tx_data[i]);
       
   582 
       
   583     if ((i + 1) % 16 == 0) EC_DBG("\n" KERN_DEBUG);
       
   584   }
       
   585   EC_DBG("\n");
       
   586   EC_DBG(KERN_DEBUG "-----------------------------------------------\n");
       
   587 #endif
       
   588 
       
   589   if (master->debug_level > 0)
       
   590   {
       
   591     EC_DBG(KERN_DEBUG "device send...\n");
       
   592   }
       
   593 
       
   594   // Send frame
       
   595   if (EtherCAT_device_send(master->dev, master->tx_data, framelength) != 0)
       
   596   {
       
   597     EC_DBG(KERN_ERR "EtherCAT: Could not send!\n");
       
   598     EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n");
       
   599     output_debug_data(master->tx_data, framelength);
       
   600     return -1;
       
   601   }
       
   602 
       
   603   if (master->debug_level > 0)
       
   604   {
       
   605     EC_DBG(KERN_DEBUG "EtherCAT_send done.\n");
       
   606   }
       
   607 
       
   608   return 0;
       
   609 }
       
   610 
       
   611 /***************************************************************/
       
   612 
       
   613 /**
       
   614    Holt alle empfangenen Kommandos vom EtherCAT-Gerät.
       
   615 
       
   616    Kopiert einen empfangenen Rahmen vom EtherCAT-Gerät
       
   617    in den Statischen Empfangsspeicher und ordnet dann
       
   618    allen gesendeten Kommandos ihre Antworten zu.
       
   619 
       
   620    @param master EtherCAT-Master
       
   621 
       
   622    @return 0 bei Erfolg, sonst < 0
       
   623 */
       
   624 
       
   625 int EtherCAT_receive(EtherCAT_master_t *master)
       
   626 {
       
   627   EtherCAT_command_t *cmd;
       
   628   unsigned int length, pos, found, rx_data_length;
       
   629   unsigned int command_follows, command_type, command_index;
       
   630 
       
   631   // Copy received data into master buffer (with locking)
       
   632   rx_data_length = EtherCAT_device_receive(master->dev, master->rx_data,
       
   633                                            ECAT_FRAME_BUFFER_SIZE);
       
   634 
       
   635 #ifdef DEBUG_SEND_RECEIVE
       
   636   for (i = 0; i < rx_data_length; i++)
       
   637   {
       
   638     if (master->rx_data[i] == master->tx_data[i]) EC_DBG("   ");
       
   639     else EC_DBG("%02X ", master->rx_data[i]);
       
   640     if ((i + 1) % 16 == 0) EC_DBG("\n" KERN_DEBUG);
       
   641   }
       
   642   EC_DBG("\n");
       
   643   EC_DBG(KERN_DEBUG "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
       
   644   EC_DBG(KERN_DEBUG "\n");
       
   645 #endif
       
   646 
       
   647   if (rx_data_length < 2)
       
   648   {
       
   649     EC_DBG(KERN_ERR "EtherCAT: Received corrupted frame (illegal length)!\n");
       
   650     EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n");
       
   651     output_debug_data(master->tx_data, master->tx_data_length);
       
   652     EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n");
       
   653     output_debug_data(master->rx_data, rx_data_length);
       
   654     return -1;
       
   655   }
       
   656 
       
   657   // Länge des gesamten Frames prüfen
       
   658   length = ((master->rx_data[1] & 0x07) << 8) | (master->rx_data[0] & 0xFF);
       
   659 
       
   660   if (length > rx_data_length)
       
   661   {
       
   662     EC_DBG(KERN_ERR "EtherCAT: Received corrupted frame (length does not match)!\n");
       
   663     EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n");
       
   664     output_debug_data(master->tx_data, master->tx_data_length);
       
   665     EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n");
       
   666     output_debug_data(master->rx_data, rx_data_length);
       
   667     return -1;
       
   668   }
       
   669 
       
   670   pos = 2; // LibPCAP: 16
       
   671   command_follows = 1;
       
   672   while (command_follows)
       
   673   {
       
   674     if (pos + 10 > rx_data_length)
       
   675     {
       
   676       EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete command header!\n");
       
   677       EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n");
       
   678       output_debug_data(master->tx_data, master->tx_data_length);
       
   679       EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n");
       
   680       output_debug_data(master->rx_data, rx_data_length);
       
   681       return -1;
       
   682     }
       
   683 
       
   684     command_type = master->rx_data[pos];
       
   685     command_index = master->rx_data[pos + 1];
       
   686     length = (master->rx_data[pos + 6] & 0xFF)
       
   687       | ((master->rx_data[pos + 7] & 0x07) << 8);
       
   688     command_follows = master->rx_data[pos + 7] & 0x80;
       
   689 
       
   690     if (pos + length + 12 > rx_data_length)
       
   691     {
       
   692       EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete command data!\n");
       
   693       EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n");
       
   694       output_debug_data(master->tx_data, master->tx_data_length);
       
   695       EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n");
       
   696       output_debug_data(master->rx_data, rx_data_length);
       
   697       return -1;
       
   698     }
       
   699 
       
   700     found = 0;
       
   701 
       
   702     for (cmd = master->first_command; cmd != NULL; cmd = cmd->next)
       
   703     {
       
   704       if (cmd->state == ECAT_CS_SENT
       
   705           && cmd->type == command_type
       
   706           && cmd->index == command_index
       
   707           && cmd->data_length == length)
       
   708       {
       
   709         found = 1;
       
   710         cmd->state = ECAT_CS_RECEIVED;
       
   711 
       
   712         // Empfangene Daten in Kommandodatenspeicher kopieren
       
   713         memcpy(cmd->data, master->rx_data + pos + 10, length);
       
   714 
       
   715         // Working-Counter setzen
       
   716         cmd->working_counter = (master->rx_data[pos + length + 10] & 0xFF)
       
   717           | ((master->rx_data[pos + length + 11] & 0xFF) << 8);
       
   718       }
       
   719     }
       
   720 
       
   721     if (!found)
       
   722     {
       
   723       EC_DBG(KERN_WARNING "EtherCAT: WARNING - Command not assigned!\n");
       
   724     }
       
   725 
       
   726     pos += length + 12;
       
   727   }
       
   728 
       
   729   for (cmd = master->first_command; cmd != NULL; cmd = cmd->next)
       
   730   {
       
   731     if (cmd->state == ECAT_CS_SENT)
       
   732     {
       
   733       EC_DBG(KERN_WARNING "EtherCAT: WARNING - One command received no response!\n");
       
   734     }
       
   735   }
       
   736 
       
   737   master->dev->state = ECAT_DS_READY;
       
   738 
       
   739   return 0;
       
   740 }
       
   741 #endif
       
   742 
    79 
   743 /***************************************************************/
    80 /***************************************************************/
   744 
    81 
   745 /**
    82 /**
   746    Sendet ein einzelnes Kommando in einem Frame und
    83    Sendet ein einzelnes Kommando in einem Frame und
   957   return 0;
   294   return 0;
   958 }
   295 }
   959 
   296 
   960 /***************************************************************/
   297 /***************************************************************/
   961 
   298 
   962 #if 0
   299 /**
   963 
   300    Überprüft die angeschlossenen Slaves.
   964 #define ECAT_FUNC_HEADER \
   301 
   965   EtherCAT_command_t *cmd; \
   302    Vergleicht die an den Bus angeschlossenen Slaves mit
   966   if ((cmd = alloc_cmd(master)) == NULL) \
   303    den im statischen-Slave-Array vorgegebenen Konfigurationen.
   967   { \
   304    Stimmen Anzahl oder Typen nicht überein, gibt diese
   968     EC_DBG(KERN_ERR "EtherCAT: Out of memory while creating command!\n"); \
   305    Methode einen Fehler aus.
   969     return NULL; \
   306 
   970   } \
   307    @param master Der EtherCAT-Master
   971   EtherCAT_command_init(cmd)
   308    @param slaves Zeiger auf ein statisches Slave-Array
   972 
   309    @param slave_count Anzahl der Slaves im Array
   973 #define ECAT_FUNC_WRITE_FOOTER \
   310 
   974   cmd->data_length = length; \
   311    @return 0 bei Erfolg, sonst < 0
   975   memcpy(cmd->data, data, length); \
   312 */
   976   if (add_command(master, cmd) < 0) return NULL; \
   313 
   977   return cmd
   314 int EtherCAT_check_slaves(EtherCAT_master_t *master,
   978 
   315                           EtherCAT_slave_t *slaves,
   979 #define ECAT_FUNC_READ_FOOTER \
   316                           unsigned int slave_count)
   980   cmd->data_length = length; \
   317 {
   981   if (add_command(master, cmd) < 0) return NULL; \
   318   EtherCAT_command_t cmd;
   982   return cmd
   319   EtherCAT_slave_t *cur;
   983 
   320   unsigned int i, j, found, length, pos;
   984 /***************************************************************/
   321   unsigned char data[2];
   985 
   322 
   986 /**
   323   // EtherCAT_clear_slaves() must be called before!
   987    Erstellt ein EtherCAT-NPRD-Kommando.
   324   if (master->slaves || master->slave_count)
   988 
   325   {
   989    Alloziert ein "node-adressed physical read"-Kommando
   326     EC_DBG(KERN_ERR "EtherCAT duplicate slave check!");
   990    und fügt es in die Liste des Masters ein.
   327     return -1;
   991 
   328   }
   992    @param master EtherCAT-Master
   329 
   993    @param node_address Adresse des Knotens (Slaves)
   330   // No slaves.
   994    @param offset Physikalische Speicheradresse im Slave
   331   if (slave_count == 0)
   995    @param length Länge der zu lesenden Daten
   332   {
   996 
   333     EC_DBG(KERN_ERR "EtherCAT: No slaves in list!");
   997    @return Adresse des Kommandos bei Erfolg, sonst NULL
   334     return -1;
   998 */
   335   }
   999 
   336 
  1000 EtherCAT_command_t *EtherCAT_read(EtherCAT_master_t *master,
   337   // Determine number of slaves on bus
  1001                                   unsigned short node_address,
   338 
  1002                                   unsigned short offset,
   339   EtherCAT_command_broadcast_read(&cmd, 0x0000, 4);
  1003                                   unsigned int length)
   340 
  1004 {
   341   if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -1;
  1005   if (node_address == 0x0000)
   342 
  1006     EC_DBG(KERN_WARNING "EtherCAT: Using node address 0x0000!\n");
   343   if (cmd.working_counter != slave_count)
  1007 
   344   {
  1008   ECAT_FUNC_HEADER;
   345     EC_DBG(KERN_ERR "EtherCAT: Wrong number of slaves on bus: %i / %i\n",
  1009 
   346            cmd.working_counter, slave_count);
  1010   cmd->type = ECAT_CMD_NPRD;
   347     return -1;
  1011   cmd->address.phy.dev.node = node_address;
   348   }
  1012   cmd->address.phy.mem = offset;
   349   else
  1013 
   350   {
  1014   ECAT_FUNC_READ_FOOTER;
   351     EC_DBG("EtherCAT: Found all %i slaves.\n", slave_count);
  1015 }
   352   }
  1016 
   353 
  1017 /***************************************************************/
   354   // For every slave in the list
  1018 
   355   for (i = 0; i < slave_count; i++)
  1019 /**
   356   {
  1020    Erstellt ein EtherCAT-NPWR-Kommando.
   357     cur = &slaves[i];
  1021 
   358 
  1022    Alloziert ein "node-adressed physical write"-Kommando
   359     if (!cur->desc)
  1023    und fügt es in die Liste des Masters ein.
   360     {
  1024 
   361       EC_DBG(KERN_ERR "EtherCAT: Slave %i has no description.\n", i);
  1025    @param master EtherCAT-Master
   362       return -1;
  1026    @param node_address Adresse des Knotens (Slaves)
   363     }
  1027    @param offset Physikalische Speicheradresse im Slave
   364 
  1028    @param length Länge der zu schreibenden Daten
   365     // Set ring position
  1029    @param data Zeiger auf Speicher mit zu schreibenden Daten
   366     cur->ring_position = -i;
  1030 
   367     cur->station_address = i + 1;
  1031    @return Adresse des Kommandos bei Erfolg, sonst NULL
   368 
  1032 */
   369     // Write station address
  1033 
   370 
  1034 EtherCAT_command_t *EtherCAT_write(EtherCAT_master_t *master,
   371     data[0] = cur->station_address & 0x00FF;
  1035                                    unsigned short node_address,
   372     data[1] = (cur->station_address & 0xFF00) >> 8;
  1036                                    unsigned short offset,
   373 
  1037                                    unsigned int length,
   374     EtherCAT_command_position_write(&cmd, cur->ring_position, 0x0010, 2, data);
  1038                                    const unsigned char *data)
   375     if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -1;
  1039 {
   376 
  1040   if (node_address == 0x0000)
   377     if (cmd.working_counter != 1)
  1041     EC_DBG(KERN_WARNING "WARNING: Using node address 0x0000!\n");
   378     {
  1042 
   379       EC_DBG(KERN_ERR "EtherCAT: Slave %i did not repond while writing station address!\n", i);
  1043   ECAT_FUNC_HEADER;
   380       return -1;
  1044 
   381     }
  1045   cmd->type = ECAT_CMD_NPWR;
   382 
  1046   cmd->address.phy.dev.node = node_address;
   383     // Read base data
  1047   cmd->address.phy.mem = offset;
   384 
  1048 
   385     EtherCAT_command_read(&cmd, cur->station_address, 0x0000, 4);
  1049   ECAT_FUNC_WRITE_FOOTER;
   386     if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -1;
  1050 }
   387 
  1051 
   388     if (cmd.working_counter != 1)
  1052 /***************************************************************/
   389     {
  1053 
   390       EC_DBG(KERN_ERR "EtherCAT: Slave %i did not respond while reading base data!\n", i);
  1054 /**
   391       return -1;
  1055    Erstellt ein EtherCAT-APRD-Kommando.
   392     }
  1056 
   393 
  1057    Alloziert ein "autoincerement physical read"-Kommando
   394     // Get base data
  1058    und fügt es in die Liste des Masters ein.
   395     cur->type = cmd.data[0];
  1059 
   396     cur->revision = cmd.data[1];
  1060    @param master EtherCAT-Master
   397     cur->build = cmd.data[2] | (cmd.data[3] << 8);
  1061    @param ring_position (Negative) Position des Slaves im Bus
   398 
  1062    @param offset Physikalische Speicheradresse im Slave
   399     // Read identification from "Slave Information Interface" (SII)
  1063    @param length Länge der zu lesenden Daten
   400 
  1064 
   401     if (EtherCAT_read_slave_information(master, cur->station_address,
  1065    @return Adresse des Kommandos bei Erfolg, sonst NULL
   402                                         0x0008, &cur->vendor_id) != 0)
  1066 */
   403     {
  1067 
   404       EC_DBG(KERN_ERR "EtherCAT: Could not read SII vendor id!\n");
  1068 EtherCAT_command_t *EtherCAT_position_read(EtherCAT_master_t *master,
   405       return -1;
  1069                                            short ring_position,
   406     }
  1070                                            unsigned short offset,
   407 
  1071                                            unsigned int length)
   408     if (EtherCAT_read_slave_information(master, cur->station_address,
  1072 {
   409                                         0x000A, &cur->product_code) != 0)
  1073   ECAT_FUNC_HEADER;
   410     {
  1074 
   411       EC_DBG(KERN_ERR "EtherCAT: Could not read SII product code!\n");
  1075   cmd->type = ECAT_CMD_APRD;
   412       return -1;
  1076   cmd->address.phy.dev.pos = ring_position;
   413     }
  1077   cmd->address.phy.mem = offset;
   414 
  1078 
   415     if (EtherCAT_read_slave_information(master, cur->station_address,
  1079   ECAT_FUNC_READ_FOOTER;
   416                                         0x000C, &cur->revision_number) != 0)
  1080 }
   417     {
  1081 
   418       EC_DBG(KERN_ERR "EtherCAT: Could not read SII revision number!\n");
  1082 /***************************************************************/
   419       return -1;
  1083 
   420     }
  1084 /**
   421 
  1085    Erstellt ein EtherCAT-APWR-Kommando.
   422     if (EtherCAT_read_slave_information(master, cur->station_address,
  1086 
   423                                         0x000E, &cur->serial_number) != 0)
  1087    Alloziert ein "autoincrement physical write"-Kommando
   424     {
  1088    und fügt es in die Liste des Masters ein.
   425       EC_DBG(KERN_ERR "EtherCAT: Could not read SII serial number!\n");
  1089 
   426       return -1;
  1090    @param master EtherCAT-Master
   427     }
  1091    @param ring_position (Negative) Position des Slaves im Bus
   428 
  1092    @param offset Physikalische Speicheradresse im Slave
   429     // Search for identification in "database"
  1093    @param length Länge der zu schreibenden Daten
   430 
  1094    @param data Zeiger auf Speicher mit zu schreibenden Daten
   431     found = 0;
  1095 
   432 
  1096    @return Adresse des Kommandos bei Erfolg, sonst NULL
   433     for (j = 0; j < slave_idents_count; j++)
  1097 */
   434     {
  1098 
   435       if (slave_idents[j].vendor_id == cur->vendor_id
  1099 EtherCAT_command_t *EtherCAT_position_write(EtherCAT_master_t *master,
   436           && slave_idents[j].product_code == cur->product_code)
  1100                                             short ring_position,
       
  1101                                             unsigned short offset,
       
  1102                                             unsigned int length,
       
  1103                                             const unsigned char *data)
       
  1104 {
       
  1105   ECAT_FUNC_HEADER;
       
  1106 
       
  1107   cmd->type = ECAT_CMD_APWR;
       
  1108   cmd->address.phy.dev.pos = ring_position;
       
  1109   cmd->address.phy.mem = offset;
       
  1110 
       
  1111   ECAT_FUNC_WRITE_FOOTER;
       
  1112 }
       
  1113 
       
  1114 /***************************************************************/
       
  1115 
       
  1116 /**
       
  1117    Erstellt ein EtherCAT-BRD-Kommando.
       
  1118 
       
  1119    Alloziert ein "broadcast read"-Kommando
       
  1120    und fügt es in die Liste des Masters ein.
       
  1121 
       
  1122    @param master EtherCAT-Master
       
  1123    @param offset Physikalische Speicheradresse im Slave
       
  1124    @param length Länge der zu lesenden Daten
       
  1125 
       
  1126    @return Adresse des Kommandos bei Erfolg, sonst NULL
       
  1127 */
       
  1128 
       
  1129 EtherCAT_command_t *EtherCAT_broadcast_read(EtherCAT_master_t *master,
       
  1130                                             unsigned short offset,
       
  1131                                             unsigned int length)
       
  1132 {
       
  1133   ECAT_FUNC_HEADER;
       
  1134 
       
  1135   cmd->type = ECAT_CMD_BRD;
       
  1136   cmd->address.phy.dev.node = 0x0000;
       
  1137   cmd->address.phy.mem = offset;
       
  1138 
       
  1139   ECAT_FUNC_READ_FOOTER;
       
  1140 }
       
  1141 
       
  1142 /***************************************************************/
       
  1143 
       
  1144 /**
       
  1145    Erstellt ein EtherCAT-BWR-Kommando.
       
  1146 
       
  1147    Alloziert ein "broadcast write"-Kommando
       
  1148    und fügt es in die Liste des Masters ein.
       
  1149 
       
  1150    @param master EtherCAT-Master
       
  1151    @param offset Physikalische Speicheradresse im Slave
       
  1152    @param length Länge der zu schreibenden Daten
       
  1153    @param data Zeiger auf Speicher mit zu schreibenden Daten
       
  1154 
       
  1155    @return Adresse des Kommandos bei Erfolg, sonst NULL
       
  1156 */
       
  1157 
       
  1158 EtherCAT_command_t *EtherCAT_broadcast_write(EtherCAT_master_t *master,
       
  1159                                              unsigned short offset,
       
  1160                                              unsigned int length,
       
  1161                                              const unsigned char *data)
       
  1162 {
       
  1163   ECAT_FUNC_HEADER;
       
  1164 
       
  1165   cmd->type = ECAT_CMD_BWR;
       
  1166   cmd->address.phy.dev.node = 0x0000;
       
  1167   cmd->address.phy.mem = offset;
       
  1168 
       
  1169   ECAT_FUNC_WRITE_FOOTER;
       
  1170 }
       
  1171 
       
  1172 /***************************************************************/
       
  1173 
       
  1174 /**
       
  1175    Erstellt ein EtherCAT-LRW-Kommando.
       
  1176 
       
  1177    Alloziert ein "logical read write"-Kommando
       
  1178    und fügt es in die Liste des Masters ein.
       
  1179 
       
  1180    @param master EtherCAT-Master
       
  1181    @param offset Logische Speicheradresse
       
  1182    @param length Länge der zu lesenden/schreibenden Daten
       
  1183    @param data Zeiger auf Speicher mit zu lesenden/schreibenden Daten
       
  1184 
       
  1185    @return Adresse des Kommandos bei Erfolg, sonst NULL
       
  1186 */
       
  1187 
       
  1188 EtherCAT_command_t *EtherCAT_logical_read_write(EtherCAT_master_t *master,
       
  1189                                                 unsigned int offset,
       
  1190                                                 unsigned int length,
       
  1191                                                 unsigned char *data)
       
  1192 {
       
  1193   ECAT_FUNC_HEADER;
       
  1194 
       
  1195   cmd->type = ECAT_CMD_LRW;
       
  1196   cmd->address.logical = offset;
       
  1197 
       
  1198   ECAT_FUNC_WRITE_FOOTER;
       
  1199 }
       
  1200 
       
  1201 /***************************************************************/
       
  1202 
       
  1203 /**
       
  1204    Alloziert ein neues Kommando aus dem Kommandoring.
       
  1205 
       
  1206    Durchsucht den Kommandoring nach einem freien Kommando,
       
  1207    reserviert es und gibt dessen Adresse zurück.
       
  1208 
       
  1209    @param master EtherCAT-Master
       
  1210 
       
  1211    @return Adresse des Kommandos bei Erfolg, sonst NULL
       
  1212 */
       
  1213 
       
  1214 EtherCAT_command_t *alloc_cmd(EtherCAT_master_t *master)
       
  1215 {
       
  1216   int j;
       
  1217 
       
  1218   for (j = 0; j < ECAT_COMMAND_RING_SIZE; j++) // Einmal rum suchen
       
  1219   {
       
  1220     // Solange suchen, bis freies Kommando gefunden
       
  1221     if (master->cmd_reserved[master->cmd_ring_index] == 0)
       
  1222     {
       
  1223       master->cmd_reserved[master->cmd_ring_index] = 1; // Belegen
       
  1224 
       
  1225       if (master->debug_level)
       
  1226       {
   437       {
  1227         EC_DBG(KERN_DEBUG "Allocating command %i (addr %X).\n",
   438         found = 1;
  1228                master->cmd_ring_index,
   439 
  1229                (int) &master->cmd_ring[master->cmd_ring_index]);
   440         if (cur->desc != slave_idents[j].desc)
       
   441         {
       
   442           EC_DBG(KERN_ERR "EtherCAT: Unexpected slave device \"%s %s\""
       
   443                  " at position %i. Expected: \"%s %s\"\n",
       
   444                  slave_idents[j].desc->vendor_name,
       
   445                  slave_idents[j].desc->product_name, i,
       
   446                  cur->desc->vendor_name, cur->desc->product_name);
       
   447           return -1;
       
   448         }
       
   449 
       
   450         break;
  1230       }
   451       }
  1231 
   452     }
  1232       return &master->cmd_ring[master->cmd_ring_index];
   453 
  1233     }
   454     if (!found)
  1234 
   455     {
  1235     if (master->debug_level)
   456       EC_DBG(KERN_ERR "EtherCAT: Unknown slave device"
  1236     {
   457              " (vendor %X, code %X) at position %i.\n",
  1237       EC_DBG(KERN_DEBUG "Command %i (addr %X) is reserved...\n",
   458              i, cur->vendor_id, cur->product_code);
  1238              master->cmd_ring_index,
       
  1239              (int) &master->cmd_ring[master->cmd_ring_index]);
       
  1240     }
       
  1241 
       
  1242     master->cmd_ring_index++;
       
  1243     master->cmd_ring_index %= ECAT_COMMAND_RING_SIZE;
       
  1244   }
       
  1245 
       
  1246   EC_DBG(KERN_WARNING "EtherCAT: Command ring full!\n");
       
  1247 
       
  1248   return NULL; // Nix gefunden
       
  1249 }
       
  1250 
       
  1251 /***************************************************************/
       
  1252 
       
  1253 /**
       
  1254    Fügt ein Kommando in die Liste des Masters ein.
       
  1255 
       
  1256    @param master EtherCAT-Master
       
  1257    @param cmd Zeiger auf das einzufügende Kommando
       
  1258 */
       
  1259 
       
  1260 int add_command(EtherCAT_master_t *master,
       
  1261                 EtherCAT_command_t *new_cmd)
       
  1262 {
       
  1263   EtherCAT_command_t *cmd, **last_cmd;
       
  1264 
       
  1265   for (cmd = master->first_command; cmd != NULL; cmd = cmd->next)
       
  1266   {
       
  1267     if (cmd == new_cmd)
       
  1268     {
       
  1269       EC_DBG(KERN_WARNING "EtherCAT: Trying to add a command"
       
  1270              " that is already in the list!\n");
       
  1271       return -1;
   459       return -1;
  1272     }
   460     }
  1273   }
   461   }
  1274 
   462 
  1275   // Find the address of the last pointer in the list
   463   length = 0;
  1276   last_cmd = &(master->first_command);
   464   for (i = 0; i < slave_count; i++)
  1277   while (*last_cmd) last_cmd = &(*last_cmd)->next;
   465   {
  1278 
   466     length += slaves[i].desc->data_length;
  1279   // Let this pointer point to the new command
   467   }
  1280   *last_cmd = new_cmd;
   468 
  1281 
   469   if ((master->process_data = (unsigned char *)
  1282   return 0;
   470        kmalloc(sizeof(unsigned char) * length, GFP_KERNEL)) == NULL)
  1283 }
   471   {
  1284 
   472     EC_DBG(KERN_ERR "EtherCAT: Could not allocate %i bytes for process data.\n", length);
  1285 /***************************************************************/
   473     return -1;
  1286 
   474   }
  1287 /**
   475 
  1288    Entfernt ein Kommando aus der Liste und gibt es frei.
   476   master->process_data_length = length;
  1289 
   477   memset(master->process_data, 0x00, length);
  1290    Prüft erst, ob das Kommando in der Liste des Masters
   478 
  1291    ist. Wenn ja, wird es entfernt und die Reservierung wird
   479   pos = 0;
  1292    aufgehoben.
   480   for (i = 0; i < slave_count; i++)
  1293 
   481   {
  1294    @param master EtherCAT-Master
   482     slaves[i].process_data = master->process_data + pos;
  1295    @param rem_cmd Zeiger auf das zu entfernende Kommando
   483     slaves[i].logical_address0 = pos;
  1296 
   484 
  1297    @return 0 bei Erfolg, sonst < 0
   485     EC_DBG(KERN_DEBUG "EtherCAT: Slave %i - Address 0x%X, \"%s %s\", s/n %u\n",
  1298 */
   486            i, pos, slaves[i].desc->vendor_name, slaves[i].desc->product_name,
  1299 
   487            slaves[i].serial_number);
  1300 void EtherCAT_remove_command(EtherCAT_master_t *master,
   488 
  1301                              EtherCAT_command_t *rem_cmd)
   489     pos += slaves[i].desc->data_length;
  1302 {
   490   }
  1303   EtherCAT_command_t **last_cmd;
   491 
  1304   int i;
   492   master->slaves = slaves;
  1305 
   493   master->slave_count = slave_count;
  1306   last_cmd = &master->first_command;
   494 
  1307   while (*last_cmd)
   495   return 0;
  1308   {
   496 }
  1309     if (*last_cmd == rem_cmd)
   497 
  1310     {
   498 /***************************************************************/
  1311       *last_cmd = rem_cmd->next;
   499 
  1312       EtherCAT_command_clear(rem_cmd);
   500 /**
  1313 
   501    Entfernt den Zeiger auf das Slave-Array.
  1314       // Reservierung des Kommandos aufheben
   502 
  1315       for (i = 0; i < ECAT_COMMAND_RING_SIZE; i++)
   503    @param master EtherCAT-Master
  1316       {
   504 */
  1317         if (&master->cmd_ring[i] == rem_cmd)
   505 
  1318         {
   506 void EtherCAT_clear_slaves(EtherCAT_master_t *master)
  1319           master->cmd_reserved[i] = 0;
   507 {
  1320           return;
   508   master->slaves = NULL;
  1321         }
   509   master->slave_count = 0;
  1322       }
   510 }
  1323 
   511 
  1324       EC_DBG(KERN_WARNING "EtherCAT: Could not remove command reservation!\n");
   512 /***************************************************************/
  1325       return;
   513 
  1326     }
   514 /**
  1327 
   515    Liest Daten aus dem Slave-Information-Interface
  1328     last_cmd = &(*last_cmd)->next;
   516    eines EtherCAT-Slaves.
  1329   }
   517 
  1330 
   518    @param master EtherCAT-Master
  1331   EC_DBG(KERN_WARNING "EtherCAT: Trying to remove non-existent command!\n");
   519    @param node_address Knotenadresse des Slaves
  1332 }
   520    @param offset Adresse des zu lesenden SII-Registers
  1333 #endif
   521    @param target Zeiger auf einen 4 Byte großen Speicher
       
   522    zum Ablegen der Daten
       
   523 
       
   524    @return 0 bei Erfolg, sonst < 0
       
   525 */
       
   526 
       
   527 int EtherCAT_read_slave_information(EtherCAT_master_t *master,
       
   528                                     unsigned short int node_address,
       
   529                                     unsigned short int offset,
       
   530                                     unsigned int *target)
       
   531 {
       
   532   EtherCAT_command_t cmd;
       
   533   unsigned char data[10];
       
   534   unsigned int tries_left;
       
   535 
       
   536   // Initiate read operation
       
   537 
       
   538   data[0] = 0x00;
       
   539   data[1] = 0x01;
       
   540   data[2] = offset & 0xFF;
       
   541   data[3] = (offset & 0xFF00) >> 8;
       
   542   data[4] = 0x00;
       
   543   data[5] = 0x00;
       
   544 
       
   545   EtherCAT_command_write(&cmd, node_address, 0x502, 6, data);
       
   546   if (EtherCAT_simple_send_receive(master, &cmd) < 0) return -3;
       
   547 
       
   548   if (cmd.working_counter != 1)
       
   549   {
       
   550     EC_DBG(KERN_ERR "EtherCAT: SII-read - Slave %04X did not respond!\n",
       
   551            node_address);
       
   552     return -4;
       
   553   }
       
   554 
       
   555   // Der Slave legt die Informationen des Slave-Information-Interface
       
   556   // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
       
   557   // den Status auslesen, bis das Bit weg ist.
       
   558 
       
   559   tries_left = 100;
       
   560   while (tries_left)
       
   561   {
       
   562     udelay(10);
       
   563 
       
   564     EtherCAT_command_read(&cmd, node_address, 0x502, 10);
       
   565     if (EtherCAT_simple_send_receive(master, &cmd) != 0) return -3;
       
   566 
       
   567     if (cmd.working_counter != 1)
       
   568     {
       
   569       EC_DBG(KERN_ERR "EtherCAT: SII-read status - Slave %04X did not respond!\n",
       
   570              node_address);
       
   571       return -4;
       
   572     }
       
   573 
       
   574     if ((cmd.data[1] & 0x81) == 0)
       
   575     {
       
   576       memcpy(target, cmd.data + 6, 4);
       
   577       break;
       
   578     }
       
   579 
       
   580     tries_left--;
       
   581   }
       
   582 
       
   583   if (!tries_left)
       
   584   {
       
   585     EC_DBG(KERN_WARNING "EtherCAT: SSI-read. Slave %04X timed out!\n",
       
   586            node_address);
       
   587     return -1;
       
   588   }
       
   589 
       
   590   return 0;
       
   591 }
  1334 
   592 
  1335 /***************************************************************/
   593 /***************************************************************/
  1336 
   594 
  1337 /**
   595 /**
  1338    Ändert den Zustand eines Slaves (asynchron).
   596    Ändert den Zustand eines Slaves (asynchron).