--- a/master/slave.c Tue Mar 28 13:42:50 2006 +0000
+++ b/master/slave.c Tue Mar 28 15:45:19 2006 +0000
@@ -48,6 +48,10 @@
slave->sii_product_code = 0;
slave->sii_revision_number = 0;
slave->sii_serial_number = 0;
+ slave->sii_rx_mailbox_offset = 0;
+ slave->sii_rx_mailbox_size = 0;
+ slave->sii_tx_mailbox_offset = 0;
+ slave->sii_tx_mailbox_size = 0;
slave->sii_mailbox_protocols = 0;
slave->type = NULL;
slave->registered = 0;
@@ -143,44 +147,29 @@
if (slave->base_fmmu_count > EC_MAX_FMMUS)
slave->base_fmmu_count = EC_MAX_FMMUS;
- // Read identification from "Slave Information Interface" (SII)
-
- if (unlikely(ec_slave_sii_read(slave, 0x0004,
- (uint32_t *) &slave->sii_alias))) {
- EC_ERR("Could not read SII alias!\n");
- return -1;
- }
-
- if (unlikely(ec_slave_sii_read(slave, 0x0008, &slave->sii_vendor_id))) {
- EC_ERR("Could not read SII vendor id!\n");
- return -1;
- }
-
- if (unlikely(ec_slave_sii_read(slave, 0x000A, &slave->sii_product_code))) {
- EC_ERR("Could not read SII product code!\n");
- return -1;
- }
-
- if (unlikely(ec_slave_sii_read(slave, 0x000C,
- &slave->sii_revision_number))) {
- EC_ERR("Could not read SII revision number!\n");
- return -1;
- }
-
- if (unlikely(ec_slave_sii_read(slave, 0x000E,
- &slave->sii_serial_number))) {
- EC_ERR("Could not read SII serial number!\n");
- return -1;
- }
-
- if (unlikely(ec_slave_sii_read(slave, 0x001C,
- &slave->sii_mailbox_protocols))) {
- EC_ERR("Could not read SII supported mailbox protocols!\n");
- return -1;
- }
+ if (ec_slave_sii_read16(slave, 0x0004, &slave->sii_alias))
+ return -1;
+ if (ec_slave_sii_read32(slave, 0x0008, &slave->sii_vendor_id))
+ return -1;
+ if (ec_slave_sii_read32(slave, 0x000A, &slave->sii_product_code))
+ return -1;
+ if (ec_slave_sii_read32(slave, 0x000C, &slave->sii_revision_number))
+ return -1;
+ if (ec_slave_sii_read32(slave, 0x000E, &slave->sii_serial_number))
+ return -1;
+ if (ec_slave_sii_read16(slave, 0x0018, &slave->sii_rx_mailbox_offset))
+ return -1;
+ if (ec_slave_sii_read16(slave, 0x0019, &slave->sii_rx_mailbox_size))
+ return -1;
+ if (ec_slave_sii_read16(slave, 0x001A, &slave->sii_tx_mailbox_offset))
+ return -1;
+ if (ec_slave_sii_read16(slave, 0x001B, &slave->sii_tx_mailbox_size))
+ return -1;
+ if (ec_slave_sii_read16(slave, 0x001C, &slave->sii_mailbox_protocols))
+ return -1;
if (unlikely(ec_slave_fetch_categories(slave))) {
- EC_ERR("Could not fetch category data!\n");
+ EC_ERR("Failed to fetch category data!\n");
return -1;
}
@@ -190,20 +179,19 @@
/*****************************************************************************/
/**
- Liest Daten aus dem Slave-Information-Interface
+ Liest 16 Bit aus dem Slave-Information-Interface
eines EtherCAT-Slaves.
\return 0 bei Erfolg, sonst < 0
*/
-int ec_slave_sii_read(ec_slave_t *slave,
- /**< EtherCAT-Slave */
- uint16_t offset,
- /**< Adresse des zu lesenden SII-Registers */
- uint32_t *target
- /**< Zeiger auf einen 4 Byte großen Speicher zum Ablegen
- der Daten */
- )
+int ec_slave_sii_read16(ec_slave_t *slave,
+ /**< EtherCAT-Slave */
+ uint16_t offset,
+ /**< Adresse des zu lesenden SII-Registers */
+ uint16_t *target
+ /**< Speicher für Wert (16-Bit) */
+ )
{
ec_command_t command;
uint8_t data[10];
@@ -242,6 +230,71 @@
end = get_cycles();
if (likely((EC_READ_U8(command.data + 1) & 0x81) == 0)) {
+ *target = EC_READ_U16(command.data + 6);
+ return 0;
+ }
+
+ if (unlikely((end - start) >= timeout)) {
+ EC_ERR("SII-read. Slave %i timed out!\n", slave->ring_position);
+ return -1;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/**
+ Liest 32 Bit aus dem Slave-Information-Interface
+ eines EtherCAT-Slaves.
+
+ \return 0 bei Erfolg, sonst < 0
+*/
+
+int ec_slave_sii_read32(ec_slave_t *slave,
+ /**< EtherCAT-Slave */
+ uint16_t offset,
+ /**< Adresse des zu lesenden SII-Registers */
+ uint32_t *target
+ /**< Speicher für Wert (32-Bit) */
+ )
+{
+ ec_command_t command;
+ uint8_t data[10];
+ cycles_t start, end, timeout;
+
+ // Initiate read operation
+
+ EC_WRITE_U8 (data, 0x00); // read-only access
+ EC_WRITE_U8 (data + 1, 0x01); // request read operation
+ EC_WRITE_U32(data + 2, offset);
+
+ ec_command_init_npwr(&command, slave->station_address, 0x502, 6, data);
+ if (unlikely(ec_master_simple_io(slave->master, &command))) {
+ EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
+ return -1;
+ }
+
+ // Der Slave legt die Informationen des Slave-Information-Interface
+ // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
+ // den Status auslesen, bis das Bit weg ist.
+
+ start = get_cycles();
+ timeout = (cycles_t) 100 * cpu_khz; // 100ms
+
+ while (1)
+ {
+ udelay(10);
+
+ ec_command_init_nprd(&command, slave->station_address, 0x502, 10);
+ if (unlikely(ec_master_simple_io(slave->master, &command))) {
+ EC_ERR("Getting SII-read status failed on slave %i!\n",
+ slave->ring_position);
+ return -1;
+ }
+
+ end = get_cycles();
+
+ if (likely((EC_READ_U8(command.data + 1) & 0x81) == 0)) {
*target = EC_READ_U32(command.data + 6);
return 0;
}
@@ -256,19 +309,19 @@
/*****************************************************************************/
/**
- Schreibt Daten in das Slave-Information-Interface
+ Schreibt 16 Bit Daten in das Slave-Information-Interface
eines EtherCAT-Slaves.
\return 0 bei Erfolg, sonst < 0
*/
-int ec_slave_sii_write(ec_slave_t *slave,
- /**< EtherCAT-Slave */
- uint16_t offset,
- /**< Adresse des zu lesenden SII-Registers */
- uint16_t value
- /**< Zu schreibender Wert */
- )
+int ec_slave_sii_write16(ec_slave_t *slave,
+ /**< EtherCAT-Slave */
+ uint16_t offset,
+ /**< Adresse des zu lesenden SII-Registers */
+ uint16_t value
+ /**< Zu schreibender Wert */
+ )
{
ec_command_t command;
uint8_t data[8];
@@ -352,7 +405,7 @@
while (1) {
// read category type
- if (ec_slave_sii_read(slave, word_offset, &value)) {
+ if (ec_slave_sii_read32(slave, word_offset, &value)) {
EC_ERR("Unable to read category header.\n");
goto out_free;
}
@@ -365,7 +418,7 @@
// Fetch category data
for (i = 0; i < word_count; i++) {
- if (ec_slave_sii_read(slave, word_offset + 2 + i, &value)) {
+ if (ec_slave_sii_read32(slave, word_offset + 2 + i, &value)) {
EC_ERR("Unable to read category data word %i.\n", i);
goto out_free;
}
@@ -824,11 +877,13 @@
EC_INFO("| Supported FMMUs: %i, Sync managers: %i\n",
slave->base_fmmu_count, slave->base_sync_count);
- EC_INFO("| Supported mailbox protocols: ");
- if (!slave->sii_mailbox_protocols) {
- printk("(none)");
- }
- else {
+ if (slave->sii_mailbox_protocols) {
+ EC_INFO("| Mailbox communication:\n");
+ EC_INFO("| RX mailbox: 0x%04X/%i, TX mailbox: 0x%04X/%i\n",
+ slave->sii_rx_mailbox_offset, slave->sii_rx_mailbox_size,
+ slave->sii_tx_mailbox_offset, slave->sii_tx_mailbox_size);
+ EC_INFO("| Supported protocols: ");
+
first = 1;
if (slave->sii_mailbox_protocols & EC_MBOX_AOE) {
printk("AoE");
@@ -858,8 +913,8 @@
if (!first) printk(", ");
printk("VoE");
}
- }
- printk("\n");
+ printk("\n");
+ }
EC_INFO("| EEPROM data:\n");
@@ -983,29 +1038,45 @@
size_t size /**< Datengröße */
)
{
- uint8_t data[0xF6];
+ size_t total_size;
+ uint8_t *data;
ec_command_t command;
- if (unlikely(size + 6 > 0xF6)) {
+ if (unlikely(!slave->sii_mailbox_protocols)) {
+ EC_ERR("Slave %i does not support mailbox communication!\n",
+ slave->ring_position);
+ return -1;
+ }
+
+ total_size = size + 6;
+ if (unlikely(total_size > slave->sii_rx_mailbox_size)) {
EC_ERR("Data size does not fit in mailbox!\n");
return -1;
}
- memset(data, 0x00, 0xF6);
-
+ if (!(data = kmalloc(slave->sii_rx_mailbox_size, GFP_KERNEL))) {
+ EC_ERR("Failed to allocate %i bytes of memory for mailbox data!\n",
+ slave->sii_rx_mailbox_size);
+ return -1;
+ }
+
+ memset(data, 0x00, slave->sii_rx_mailbox_size);
EC_WRITE_U16(data, size); // Length of the Mailbox service data
EC_WRITE_U16(data + 2, slave->station_address); // Station address
EC_WRITE_U8 (data + 4, 0x00); // Channel & priority
EC_WRITE_U8 (data + 5, type); // Underlying protocol type
-
memcpy(data + 6, prot_data, size);
- ec_command_init_npwr(&command, slave->station_address, 0x1800, 0xF6, data);
+ ec_command_init_npwr(&command, slave->station_address,
+ slave->sii_rx_mailbox_offset,
+ slave->sii_rx_mailbox_size, data);
if (unlikely(ec_master_simple_io(slave->master, &command))) {
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
- return -1;
- }
-
+ kfree(data);
+ return -1;
+ }
+
+ kfree(data);
return 0;
}
@@ -1032,6 +1103,7 @@
while (1)
{
+ // FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox?
ec_command_init_nprd(&command, slave->station_address, 0x808, 8);
if (unlikely(ec_master_simple_io(slave->master, &command))) {
EC_ERR("Mailbox checking failed on slave %i!\n",
@@ -1041,7 +1113,8 @@
end = get_cycles();
- if (EC_READ_U8(command.data + 5) & 8) break; // Written bit is high
+ if (EC_READ_U8(command.data + 5) & 8)
+ break; // Proceed with received data
if ((end - start) >= timeout) {
EC_ERR("Mailbox check - Slave %i timed out.\n",
@@ -1052,29 +1125,37 @@
udelay(100);
}
- if (unlikely(slave->master->debug_level) > 1)
- EC_DBG("SDO download took %ius.\n", ((u32) (end - start) * 1000
- / cpu_khz));
-
- ec_command_init_nprd(&command, slave->station_address, 0x18F6, 0xF6);
+ ec_command_init_nprd(&command, slave->station_address,
+ slave->sii_tx_mailbox_offset,
+ slave->sii_tx_mailbox_size);
if (unlikely(ec_master_simple_io(slave->master, &command))) {
EC_ERR("Mailbox receiving failed on slave %i!\n",
slave->ring_position);
return -1;
}
- if (EC_READ_U8(command.data + 5) != type) { // nicht CoE
- EC_ERR("Invalid mailbox response (non-CoE) at slave %i!\n",
+ if ((EC_READ_U8(command.data + 5) & 0x0F) != type) {
+ EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at"
+ " slave %i!\n", EC_READ_U8(command.data + 5), type,
slave->ring_position);
return -1;
}
+ if (unlikely(slave->master->debug_level) > 1)
+ EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000
+ / cpu_khz));
+
if ((data_size = EC_READ_U16(command.data)) > *size) {
- EC_ERR("CoE data does not fit in buffer (%i > %i).\n",
+ EC_ERR("Mailbox service data does not fit into buffer (%i > %i).\n",
data_size, *size);
return -1;
}
+ if (data_size > slave->sii_tx_mailbox_size - 6) {
+ EC_ERR("Currupt mailbox response detected!\n");
+ return -1;
+ }
+
memcpy(prot_data, command.data + 6, data_size);
*size = data_size;
return 0;