ec_enum.c 8.9 KB
Newer Older
Jeroen Vreeken's avatar
Jeroen Vreeken committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
	Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2009
	Copyright Stichting C.A. Muller Radioastronomiestation, 2009

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */
19
20
21
/*
	Simple tool to enumerate all Ethercat devices on the bus.
 */
Jeroen Vreeken's avatar
Jeroen Vreeken committed
22
23
24
25

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
26
#include <stdarg.h>
Jeroen Vreeken's avatar
Jeroen Vreeken committed
27
28
29

#include "ec.h"
#include "esc.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
30
31
#include "esc_esi.h"
#include "esc_registers.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
32
#include "esc_id.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "log.h"

/* Local override, we don't want a complete log implementation */
void log_send(enum log_type type, char *fmt, ...)
{
	va_list ap;
	
	va_start(ap, fmt);
	
	vprintf(fmt, ap);
	printf("\n");

	va_end(ap);
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
47
48
49
50
51
52

void describe_esc(struct ec_dgram_addr *ec_addr)
{
	int r, r2;
	uint8_t val8;
	uint16_t val16;
53
	uint8_t eeprom[1024/8];
Jeroen Vreeken's avatar
Jeroen Vreeken committed
54
55
56
	uint32_t vendorid, productcode;
	char *vendorid_str, *productcode_str;
	int i;
57
58
59
60
	size_t eeprom_size;
	uint16_t eeprom_version;
	struct esc_device *dev;
	struct esc_esi_category *cat;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
61
	
62
63
	dev = esc_device_create2(ec_addr, "ec_enum");

Jeroen Vreeken's avatar
Jeroen Vreeken committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
	ec_addr->addr.position.off = ESC_ADDR_MAP_TYPE;
	r = ec_datagram_read(ec_addr, &val8, 1);
	if (r == 1) {
		char *type;
		switch (val8) {
			case ESC_TYPE_ESC:
				type = "ESC";
				break;
			case ESC_TYPE_IPCORE:
				type = "IP core";
				break;
			case ESC_TYPE_ET1100:
				type = "ET1100";
				break;
			case ESC_TYPE_ET1200:
				type = "ET1200";
				break;
			default:
				type = "unknown";
		}
		printf("\tType: 0x%02x = %s\n", val8, type);
	}

	ec_addr->addr.position.off = ESC_ADDR_MAP_REVISION;
	r = ec_datagram_read(ec_addr, &val8, 1);

	ec_addr->addr.position.off = ESC_ADDR_MAP_BUILD;
	r2 = ec_datagram_read(ec_addr, &val16, 2);
	
	if (r == 1 && r2 == 2) {
		printf("\tRevision & Build: 0x%02x 0x%04x\n", val8, le16toh(val16));
	}

	ec_addr->addr.position.off = ESC_ADDR_MAP_FMMUS_SUPPORTED;
	r = ec_datagram_read(ec_addr, &val8, 1);
	
	if (r == 1) {
		printf("\tFMMUs supported: %d\n", val8);
	}
	
	ec_addr->addr.position.off = ESC_ADDR_MAP_SYNCMANAGERS_SUPPORTED;
	r = ec_datagram_read(ec_addr, &val8, 1);
	
	if (r == 1) {
		printf("\tSyncmanagers supported: %d\n", val8);
	}

	ec_addr->addr.position.off = ESC_ADDR_MAP_RAM_SIZE;
	r = ec_datagram_read(ec_addr, &val8, 1);
	
	if (r == 1) {
		printf("\tRAM size: %d Kb\n", val8);
	}
	
	ec_addr->addr.position.off = ESC_ADDR_MAP_FEATURES;
	r = ec_datagram_read(ec_addr, &val16, 2);
	
	if (r == 2) {
		val16 = le16toh(val16);
		printf("\tFeatures: 0x%02x\n", val16);
		if (val16 & ESC_FEATURE_FMMU_BYTE_ORIENTED)
			printf("\t\tFMMU is byte oriented\n");
		if (val16 & ESC_FEATURE_DISTRIBUTED_CLOCKS)
			printf("\t\tDistributed clocks\n");
		if (val16 & ESC_FEATURE_64BIT_DISTRIBUTED_CLOCKS)
			printf("\t\t64bit wide distributed clocks\n");
		if (val16 & ESC_FEATURE_LOW_JITTER_EBUS)
			printf("\t\tLow jitter EBUS\n");
		if (val16 & ESC_FEATURE_ENHANCED_LINK_DETECTION_EBUS)
			printf("\t\tEnhanced link detection EBUS\n");
		if (val16 & ESC_FEATURE_ENHANCED_LINK_DETECTION_MII)
			printf("\t\tEnhanced link detection MII\n");
		if (val16 & ESC_FEATURE_SEPERATE_FCS_HANDLING)
			printf("\t\tSeperate FCS handling\n");
		if (val16 & ESC_FEATURE_ENHANCED_DC_SYNC_ACTIVATION)
			printf("\t\tEnhanced DC sync activation\n");
	}

Jeroen Vreeken's avatar
Jeroen Vreeken committed
142
143
144
145
146
147
148
	ec_addr->addr.position.off = ESC_ADDR_MAP_SYNC_LATCH_PDI_CONFIG;
	r = ec_datagram_read(ec_addr, &val8, 1);
	
	if (r == 1) {
		printf("\tSync/Latch PDI config: 0x%02x\n", val8);
	}

149
150
	vendorid = esc_esi_vendorid_get(dev);
	productcode = esc_esi_productcode_get(dev);
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
	
	vendorid_str = "unknown vendorid";
	productcode_str = "unkown productcode";
	for (i = 0; i < esc_vendor_list_len; i++)
		if (esc_vendor_list[i].vendorid == vendorid)
			vendorid_str = esc_vendor_list[i].name;
	for (i = 0; i < esc_device_list_len; i++)
		if (esc_device_list[i].vendorid == vendorid &&
		    esc_device_list[i].productcode == productcode)
			productcode_str = esc_device_list[i].name;
	
	printf("\tESI VendorId: 0x%04x\n", vendorid);
	printf("\t\tVendor: %s\n", vendorid_str);
	printf("\tESI ProductCode: 0x%04x\n", productcode);
	printf("\t\tProduct: %s\n", productcode_str);
166
167
	printf("\tESI RevisionNo: 0x%04x\n", esc_esi_revisionno_get(dev));
	printf("\tESI SerialNo: 0x%04x\n", esc_esi_serialno_get(dev));
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
	
	eeprom_size = esc_esi_read16(ec_addr, ESC_ESI_ADDR_SIZE);
	printf("\tESI Size: 0x%08zx\n", eeprom_size);
	eeprom_version = esc_esi_read16(ec_addr, ESC_ESI_ADDR_VERSION);
	printf("\tESI Version: 0x%08x\n", eeprom_version);

	val16 = esc_esi_read16(ec_addr, ESC_ESI_BOOTSTRAP_RX_MAILBOX_OFFSET);
	printf("\tESI Bootstrap RX mailbox offset: 0x%04x\n", val16);
	val16 = esc_esi_read16(ec_addr, ESC_ESI_BOOTSTRAP_RX_MAILBOX_SIZE);
	printf("\tESI Bootstrap RX mailbox size:   0x%04x\n", val16);
	val16 = esc_esi_read16(ec_addr, ESC_ESI_BOOTSTRAP_TX_MAILBOX_OFFSET);
	printf("\tESI Bootstrap TX mailbox offset: 0x%04x\n", val16);
	val16 = esc_esi_read16(ec_addr, ESC_ESI_BOOTSTRAP_TX_MAILBOX_SIZE);
	printf("\tESI Bootstrap TX mailbox size:   0x%04x\n", val16);

	printf("\tESI Standard RX mailbox offset:  0x%04zx\n", 
	    esc_esi_standard_rx_mailbox_offset_get(ec_addr));
	printf("\tESI Standard RX mailbox size:    0x%04zx\n", 
	    esc_esi_standard_rx_mailbox_size_get(ec_addr));
	printf("\tESI Standard TX mailbox offset:  0x%04zx\n", 
	    esc_esi_standard_tx_mailbox_offset_get(ec_addr));
	printf("\tESI Standard TX mailbox size:    0x%04zx\n", 
	    esc_esi_standard_rx_mailbox_size_get(ec_addr));

	val16 = esc_esi_read16(ec_addr, ESC_ESI_MAILBOX_PROTOCOL);
	printf("\tESI Mailbox Protocol: 0x%04x\n", val16);
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
195
196
197
198
199
200
201
	r = esc_esi_eeprom_read(ec_addr, &eeprom, 0, sizeof(eeprom));
	if (r == sizeof(eeprom)) {
		printf("\tESI EEPROM:\n");
		for (i = 0; i < sizeof(eeprom)/sizeof(*eeprom); i += 16) {
			char *c;
			int j;
			
202
			printf("\t\t0x%04x (0x%04x): "
Jeroen Vreeken's avatar
Jeroen Vreeken committed
203
204
			    "%02x%02x %02x%02x %02x%02x %02x%02x "
			    "%02x%02x %02x%02x %02x%02x %02x%02x ",
205
			    i, i/2,
Jeroen Vreeken's avatar
Jeroen Vreeken committed
206
207
208
209
210
211
			    eeprom[i+0], eeprom[i+1], eeprom[i+2], eeprom[i+3],
			    eeprom[i+4], eeprom[i+5], eeprom[i+6], eeprom[i+7],
			    eeprom[i+8], eeprom[i+9], eeprom[i+10], eeprom[i+11],
			    eeprom[i+12], eeprom[i+13], eeprom[i+14], eeprom[i+15]);
			c = (char*)&eeprom[i];
			for (j = 0; j < 16; j++) {
212
				if (isprint(c[j])) {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
213
214
215
216
217
218
219
220
221
222
223
					printf("%c", c[j]);
				} else {
					printf(".");
				}
			}
			printf("\n");
		}
	} else {
		printf("\tESI EEPROM read returned: %d expected: %zd.\n",
		    r, sizeof(eeprom));
	}
224

Jeroen Vreeken's avatar
Jeroen Vreeken committed
225
	esc_esi_device_fill(dev);
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288

	for (cat = dev->categories; cat; cat = cat->next) {
		printf("\tcategory type:   0x%04x\n", cat->type);
		printf("\tcategory length: 0x%04zx\n", cat->length);

		for (i = 0; i < cat->length; i += 16) {
			char *c;
			int j;
			
			printf("\t\t0x%04x (0x%04x): ", i, i/2);
			if (cat->length - i >= 2)
				printf("%02x%02x ", cat->data[i+0], cat->data[i+1]);
			else
				printf("     ");
			if (cat->length - i >= 4)
				printf("%02x%02x ", cat->data[i+2], cat->data[i+3]);
			else
				printf("     ");
			if (cat->length - i >= 6)
				printf("%02x%02x ", cat->data[i+4], cat->data[i+5]);
			else
				printf("     ");
			if (cat->length - i >= 8)
				printf("%02x%02x ", cat->data[i+6], cat->data[i+7]);
			else
				printf("     ");
			if (cat->length - i >= 10)
				printf("%02x%02x ", cat->data[i+8], cat->data[i+9]);
			else
				printf("     ");
			if (cat->length - i >= 12)
				printf("%02x%02x ", cat->data[i+10], cat->data[i+11]);
			else
				printf("     ");
			if (cat->length - i >= 14)
				printf("%02x%02x ", cat->data[i+12], cat->data[i+13]);
			else
				printf("     ");
			if (cat->length - i >= 16)
				printf("%02x%02x ", cat->data[i+14], cat->data[i+15]);
			else
				printf("     ");

			c = (char*)&cat->data[i];
			for (j = 0; j < 16; j++) {
				if (cat->length - i < j) {
					printf(" ");
				} else if (isprint(c[j])) {
					printf("%c", c[j]);
				} else {
					printf(".");
				}
			}
			printf("\n");
		}
	}

	for (i = 0; i < ESC_SYNCMANAGER_MAX; i++) {
		printf("\tsm%d: %zd bytes @ 0x%zx, enabled: %d\n",
		    i, dev->sm[i].len, dev->sm[i].start, dev->sm[i].enabled);
	}

	esc_device_destroy(dev);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
	
	printf("\n");
}

int main(int argc, char **argv)
{
	int slaves;
	int i;
	
	if (argc < 2) {
		printf("Usage: %s [ethernet device]\n", argv[0]);
		return -1;
	}
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
303
	if (ec_init(argv[1], 0, 0)) {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
		printf("EtherCat init failed\n");
		return -1;
	}
	
	slaves = ec_slave_count();
	
	printf("Number of slaves found: %d\n", slaves);
	
	for (i = 0; i < slaves; i++) {
		struct ec_dgram_addr ec_addr;
		
		printf("EtherCat slave controller %d:\n", i);
		
		ec_addr_set_auto_inc_nr(&ec_addr, i);
		
		describe_esc(&ec_addr);
	}
	
	return 0;
}