xref: /titanic_44/usr/src/cmd/dlutil/dltraninfo.c (revision 48a4016cae8aa2b8b3d8b258eb22e0c781912bed)
1*48a4016cSRobert Mustacchi /*
2*48a4016cSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*48a4016cSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*48a4016cSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*48a4016cSRobert Mustacchi  * 1.0 of the CDDL.
6*48a4016cSRobert Mustacchi  *
7*48a4016cSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*48a4016cSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*48a4016cSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*48a4016cSRobert Mustacchi  */
11*48a4016cSRobert Mustacchi 
12*48a4016cSRobert Mustacchi /*
13*48a4016cSRobert Mustacchi  * Copyright (c) 2017, Joyent, Inc.
14*48a4016cSRobert Mustacchi  */
15*48a4016cSRobert Mustacchi 
16*48a4016cSRobert Mustacchi /*
17*48a4016cSRobert Mustacchi  * Private utility to dump transceiver information for each physical datalink.
18*48a4016cSRobert Mustacchi  * Something like this should eventually be a part of dladm or similar.
19*48a4016cSRobert Mustacchi  */
20*48a4016cSRobert Mustacchi 
21*48a4016cSRobert Mustacchi #include <stdio.h>
22*48a4016cSRobert Mustacchi #include <sys/types.h>
23*48a4016cSRobert Mustacchi #include <sys/stat.h>
24*48a4016cSRobert Mustacchi #include <fcntl.h>
25*48a4016cSRobert Mustacchi #include <strings.h>
26*48a4016cSRobert Mustacchi #include <errno.h>
27*48a4016cSRobert Mustacchi #include <ctype.h>
28*48a4016cSRobert Mustacchi #include <unistd.h>
29*48a4016cSRobert Mustacchi #include <limits.h>
30*48a4016cSRobert Mustacchi #include <stdarg.h>
31*48a4016cSRobert Mustacchi #include <libgen.h>
32*48a4016cSRobert Mustacchi 
33*48a4016cSRobert Mustacchi #include <libdladm.h>
34*48a4016cSRobert Mustacchi #include <libdllink.h>
35*48a4016cSRobert Mustacchi #include <sys/dld.h>
36*48a4016cSRobert Mustacchi #include <sys/dld_ioc.h>
37*48a4016cSRobert Mustacchi #include <sys/dls_mgmt.h>
38*48a4016cSRobert Mustacchi #include <libsff.h>
39*48a4016cSRobert Mustacchi 
40*48a4016cSRobert Mustacchi #define	DLTRAN_KIND_LEN	64
41*48a4016cSRobert Mustacchi 
42*48a4016cSRobert Mustacchi static dladm_handle_t dltran_hdl;
43*48a4016cSRobert Mustacchi static char dltran_dlerrmsg[DLADM_STRSIZE];
44*48a4016cSRobert Mustacchi static const char *dltran_progname;
45*48a4016cSRobert Mustacchi static boolean_t dltran_verbose;
46*48a4016cSRobert Mustacchi static boolean_t dltran_hex;
47*48a4016cSRobert Mustacchi static boolean_t dltran_write;
48*48a4016cSRobert Mustacchi static int dltran_outfd;
49*48a4016cSRobert Mustacchi static int dltran_errors;
50*48a4016cSRobert Mustacchi 
51*48a4016cSRobert Mustacchi /*
52*48a4016cSRobert Mustacchi  * This routine basically assumes that we'll have 16 byte aligned output to
53*48a4016cSRobert Mustacchi  * print out the human readable output.
54*48a4016cSRobert Mustacchi  */
55*48a4016cSRobert Mustacchi static void
dltran_dump_page(uint8_t * buf,size_t nbytes,uint_t page)56*48a4016cSRobert Mustacchi dltran_dump_page(uint8_t *buf, size_t nbytes, uint_t page)
57*48a4016cSRobert Mustacchi {
58*48a4016cSRobert Mustacchi 	size_t i;
59*48a4016cSRobert Mustacchi 	static boolean_t first = B_TRUE;
60*48a4016cSRobert Mustacchi 
61*48a4016cSRobert Mustacchi 	if (first) {
62*48a4016cSRobert Mustacchi 		(void) printf("page  %*s    0", 4, "");
63*48a4016cSRobert Mustacchi 		for (i = 1; i < 16; i++) {
64*48a4016cSRobert Mustacchi 			if (i % 4 == 0 && i % 16 != 0) {
65*48a4016cSRobert Mustacchi 				(void) printf(" ");
66*48a4016cSRobert Mustacchi 			}
67*48a4016cSRobert Mustacchi 
68*48a4016cSRobert Mustacchi 			(void) printf("%2x", i);
69*48a4016cSRobert Mustacchi 		}
70*48a4016cSRobert Mustacchi 		(void) printf("  v123456789abcdef\n");
71*48a4016cSRobert Mustacchi 		first = B_FALSE;
72*48a4016cSRobert Mustacchi 	}
73*48a4016cSRobert Mustacchi 	for (i = 0; i < nbytes; i++) {
74*48a4016cSRobert Mustacchi 
75*48a4016cSRobert Mustacchi 		if (i % 16 == 0) {
76*48a4016cSRobert Mustacchi 			(void) printf("0x%02x  %04x:  ", page, i);
77*48a4016cSRobert Mustacchi 		}
78*48a4016cSRobert Mustacchi 
79*48a4016cSRobert Mustacchi 		if (i % 4 == 0 && i % 16 != 0) {
80*48a4016cSRobert Mustacchi 			(void) printf(" ");
81*48a4016cSRobert Mustacchi 		}
82*48a4016cSRobert Mustacchi 
83*48a4016cSRobert Mustacchi 
84*48a4016cSRobert Mustacchi 		(void) printf("%02x", buf[i]);
85*48a4016cSRobert Mustacchi 
86*48a4016cSRobert Mustacchi 		if (i % 16 == 15) {
87*48a4016cSRobert Mustacchi 			int j;
88*48a4016cSRobert Mustacchi 			(void) printf("  ");
89*48a4016cSRobert Mustacchi 			for (j = i - (i % 16); j <= i; j++) {
90*48a4016cSRobert Mustacchi 				if (!isprint(buf[j])) {
91*48a4016cSRobert Mustacchi 					(void) printf(".");
92*48a4016cSRobert Mustacchi 				} else {
93*48a4016cSRobert Mustacchi 					(void) printf("%c", buf[j]);
94*48a4016cSRobert Mustacchi 				}
95*48a4016cSRobert Mustacchi 			}
96*48a4016cSRobert Mustacchi 			(void) printf("\n");
97*48a4016cSRobert Mustacchi 		}
98*48a4016cSRobert Mustacchi 	}
99*48a4016cSRobert Mustacchi }
100*48a4016cSRobert Mustacchi 
101*48a4016cSRobert Mustacchi static int
dltran_read_page(datalink_id_t link,uint_t tranid,uint_t page,uint8_t * bufp,size_t * buflen)102*48a4016cSRobert Mustacchi dltran_read_page(datalink_id_t link, uint_t tranid, uint_t page, uint8_t *bufp,
103*48a4016cSRobert Mustacchi     size_t *buflen)
104*48a4016cSRobert Mustacchi {
105*48a4016cSRobert Mustacchi 	dld_ioc_tranio_t dti;
106*48a4016cSRobert Mustacchi 
107*48a4016cSRobert Mustacchi 	bzero(bufp, *buflen);
108*48a4016cSRobert Mustacchi 	bzero(&dti, sizeof (dti));
109*48a4016cSRobert Mustacchi 
110*48a4016cSRobert Mustacchi 	dti.dti_linkid = link;
111*48a4016cSRobert Mustacchi 	dti.dti_tran_id = tranid;
112*48a4016cSRobert Mustacchi 	dti.dti_page = page;
113*48a4016cSRobert Mustacchi 	dti.dti_nbytes = *buflen;
114*48a4016cSRobert Mustacchi 	dti.dti_off = 0;
115*48a4016cSRobert Mustacchi 	dti.dti_buf = (uintptr_t)(void *)bufp;
116*48a4016cSRobert Mustacchi 
117*48a4016cSRobert Mustacchi 	if (ioctl(dladm_dld_fd(dltran_hdl), DLDIOC_READTRAN, &dti) != 0) {
118*48a4016cSRobert Mustacchi 		(void) fprintf(stderr, "failed to read transceiver page "
119*48a4016cSRobert Mustacchi 		    "0x%2x: %s\n", page, strerror(errno));
120*48a4016cSRobert Mustacchi 		return (1);
121*48a4016cSRobert Mustacchi 	}
122*48a4016cSRobert Mustacchi 
123*48a4016cSRobert Mustacchi 	*buflen = dti.dti_nbytes;
124*48a4016cSRobert Mustacchi 	return (0);
125*48a4016cSRobert Mustacchi }
126*48a4016cSRobert Mustacchi 
127*48a4016cSRobert Mustacchi static boolean_t
dltran_is_8472(uint8_t * buf)128*48a4016cSRobert Mustacchi dltran_is_8472(uint8_t *buf)
129*48a4016cSRobert Mustacchi {
130*48a4016cSRobert Mustacchi 	switch (buf[0]) {
131*48a4016cSRobert Mustacchi 	case 0xc:
132*48a4016cSRobert Mustacchi 	case 0xd:
133*48a4016cSRobert Mustacchi 	case 0x11:
134*48a4016cSRobert Mustacchi 		/*
135*48a4016cSRobert Mustacchi 		 * Catch cases that refer explicitly to QSFP and newer.
136*48a4016cSRobert Mustacchi 		 */
137*48a4016cSRobert Mustacchi 		return (B_FALSE);
138*48a4016cSRobert Mustacchi 	default:
139*48a4016cSRobert Mustacchi 		break;
140*48a4016cSRobert Mustacchi 	}
141*48a4016cSRobert Mustacchi 
142*48a4016cSRobert Mustacchi 	/*
143*48a4016cSRobert Mustacchi 	 * Check the byte that indicates compliance with SFF 8472. Use this to
144*48a4016cSRobert Mustacchi 	 * know if we can read page 0xa2 or not.
145*48a4016cSRobert Mustacchi 	 */
146*48a4016cSRobert Mustacchi 	if (buf[94] == 0)
147*48a4016cSRobert Mustacchi 		return (B_FALSE);
148*48a4016cSRobert Mustacchi 
149*48a4016cSRobert Mustacchi 	return (B_TRUE);
150*48a4016cSRobert Mustacchi }
151*48a4016cSRobert Mustacchi 
152*48a4016cSRobert Mustacchi static void
dltran_hex_dump(datalink_id_t linkid,uint_t tranid)153*48a4016cSRobert Mustacchi dltran_hex_dump(datalink_id_t linkid, uint_t tranid)
154*48a4016cSRobert Mustacchi {
155*48a4016cSRobert Mustacchi 	uint8_t buf[256];
156*48a4016cSRobert Mustacchi 	size_t buflen = sizeof (buf);
157*48a4016cSRobert Mustacchi 
158*48a4016cSRobert Mustacchi 	if (dltran_read_page(linkid, tranid, 0xa0, buf, &buflen) != 0) {
159*48a4016cSRobert Mustacchi 		dltran_errors++;
160*48a4016cSRobert Mustacchi 		return;
161*48a4016cSRobert Mustacchi 	}
162*48a4016cSRobert Mustacchi 
163*48a4016cSRobert Mustacchi 	dltran_dump_page(buf, buflen, 0xa0);
164*48a4016cSRobert Mustacchi 
165*48a4016cSRobert Mustacchi 	if (!dltran_is_8472(buf)) {
166*48a4016cSRobert Mustacchi 		return;
167*48a4016cSRobert Mustacchi 	}
168*48a4016cSRobert Mustacchi 
169*48a4016cSRobert Mustacchi 	buflen = sizeof (buf);
170*48a4016cSRobert Mustacchi 	if (dltran_read_page(linkid, tranid, 0xa2, buf, &buflen) != 0) {
171*48a4016cSRobert Mustacchi 		dltran_errors++;
172*48a4016cSRobert Mustacchi 		return;
173*48a4016cSRobert Mustacchi 	}
174*48a4016cSRobert Mustacchi 
175*48a4016cSRobert Mustacchi 	dltran_dump_page(buf, buflen, 0xa2);
176*48a4016cSRobert Mustacchi }
177*48a4016cSRobert Mustacchi 
178*48a4016cSRobert Mustacchi static void
dltran_write_page(datalink_id_t linkid,uint_t tranid)179*48a4016cSRobert Mustacchi dltran_write_page(datalink_id_t linkid, uint_t tranid)
180*48a4016cSRobert Mustacchi {
181*48a4016cSRobert Mustacchi 	uint8_t buf[256];
182*48a4016cSRobert Mustacchi 	size_t buflen = sizeof (buf);
183*48a4016cSRobert Mustacchi 	off_t off;
184*48a4016cSRobert Mustacchi 
185*48a4016cSRobert Mustacchi 	if (dltran_read_page(linkid, tranid, 0xa0, buf, &buflen) != 0) {
186*48a4016cSRobert Mustacchi 		dltran_errors++;
187*48a4016cSRobert Mustacchi 		return;
188*48a4016cSRobert Mustacchi 	}
189*48a4016cSRobert Mustacchi 
190*48a4016cSRobert Mustacchi 	off = 0;
191*48a4016cSRobert Mustacchi 	while (buflen > 0) {
192*48a4016cSRobert Mustacchi 		ssize_t ret;
193*48a4016cSRobert Mustacchi 
194*48a4016cSRobert Mustacchi 		ret = write(dltran_outfd, buf + off, buflen);
195*48a4016cSRobert Mustacchi 		if (ret == -1) {
196*48a4016cSRobert Mustacchi 			(void) fprintf(stderr, "failed to write data "
197*48a4016cSRobert Mustacchi 			    "to output file: %s\n", strerror(errno));
198*48a4016cSRobert Mustacchi 			dltran_errors++;
199*48a4016cSRobert Mustacchi 			return;
200*48a4016cSRobert Mustacchi 		}
201*48a4016cSRobert Mustacchi 
202*48a4016cSRobert Mustacchi 		off += ret;
203*48a4016cSRobert Mustacchi 		buflen -= ret;
204*48a4016cSRobert Mustacchi 	}
205*48a4016cSRobert Mustacchi }
206*48a4016cSRobert Mustacchi 
207*48a4016cSRobert Mustacchi static void
dltran_verbose_dump(datalink_id_t linkid,uint_t tranid)208*48a4016cSRobert Mustacchi dltran_verbose_dump(datalink_id_t linkid, uint_t tranid)
209*48a4016cSRobert Mustacchi {
210*48a4016cSRobert Mustacchi 	uint8_t buf[256];
211*48a4016cSRobert Mustacchi 	size_t buflen = sizeof (buf);
212*48a4016cSRobert Mustacchi 	int ret;
213*48a4016cSRobert Mustacchi 	nvlist_t *nvl;
214*48a4016cSRobert Mustacchi 
215*48a4016cSRobert Mustacchi 	if (dltran_read_page(linkid, tranid, 0xa0, buf, &buflen) != 0) {
216*48a4016cSRobert Mustacchi 		dltran_errors++;
217*48a4016cSRobert Mustacchi 		return;
218*48a4016cSRobert Mustacchi 	}
219*48a4016cSRobert Mustacchi 
220*48a4016cSRobert Mustacchi 	ret = libsff_parse(buf, buflen, 0xa0, &nvl);
221*48a4016cSRobert Mustacchi 	if (ret == 0) {
222*48a4016cSRobert Mustacchi 		dump_nvlist(nvl, 8);
223*48a4016cSRobert Mustacchi 		nvlist_free(nvl);
224*48a4016cSRobert Mustacchi 	} else {
225*48a4016cSRobert Mustacchi 		fprintf(stderr, "failed to parse sfp data: %s\n",
226*48a4016cSRobert Mustacchi 		    strerror(ret));
227*48a4016cSRobert Mustacchi 		dltran_errors++;
228*48a4016cSRobert Mustacchi 	}
229*48a4016cSRobert Mustacchi }
230*48a4016cSRobert Mustacchi 
231*48a4016cSRobert Mustacchi static int
dltran_dump_transceivers(dladm_handle_t hdl,datalink_id_t linkid,void * arg)232*48a4016cSRobert Mustacchi dltran_dump_transceivers(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
233*48a4016cSRobert Mustacchi {
234*48a4016cSRobert Mustacchi 	dladm_status_t status;
235*48a4016cSRobert Mustacchi 	char name[MAXLINKNAMELEN];
236*48a4016cSRobert Mustacchi 	dld_ioc_gettran_t gt;
237*48a4016cSRobert Mustacchi 	uint_t count, i, tranid = UINT_MAX;
238*48a4016cSRobert Mustacchi 	boolean_t tran_found = B_FALSE;
239*48a4016cSRobert Mustacchi 	uint_t *tranidp = arg;
240*48a4016cSRobert Mustacchi 
241*48a4016cSRobert Mustacchi 	if (tranidp != NULL)
242*48a4016cSRobert Mustacchi 		tranid = *tranidp;
243*48a4016cSRobert Mustacchi 
244*48a4016cSRobert Mustacchi 	if ((status = dladm_datalink_id2info(hdl, linkid, NULL, NULL, NULL,
245*48a4016cSRobert Mustacchi 	    name, sizeof (name))) != DLADM_STATUS_OK) {
246*48a4016cSRobert Mustacchi 		(void) fprintf(stderr, "failed to get datalink name for link "
247*48a4016cSRobert Mustacchi 		    "%d: %s", linkid, dladm_status2str(status,
248*48a4016cSRobert Mustacchi 		    dltran_dlerrmsg));
249*48a4016cSRobert Mustacchi 		dltran_errors++;
250*48a4016cSRobert Mustacchi 		return (DLADM_WALK_CONTINUE);
251*48a4016cSRobert Mustacchi 	}
252*48a4016cSRobert Mustacchi 
253*48a4016cSRobert Mustacchi 	bzero(&gt, sizeof (gt));
254*48a4016cSRobert Mustacchi 	gt.dgt_linkid = linkid;
255*48a4016cSRobert Mustacchi 	gt.dgt_tran_id = DLDIOC_GETTRAN_GETNTRAN;
256*48a4016cSRobert Mustacchi 
257*48a4016cSRobert Mustacchi 	if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETTRAN, &gt) != 0) {
258*48a4016cSRobert Mustacchi 		if (errno != ENOTSUP) {
259*48a4016cSRobert Mustacchi 			(void) fprintf(stderr, "failed to get transceiver "
260*48a4016cSRobert Mustacchi 			    "count for device %s: %s\n",
261*48a4016cSRobert Mustacchi 			    name, strerror(errno));
262*48a4016cSRobert Mustacchi 			dltran_errors++;
263*48a4016cSRobert Mustacchi 		}
264*48a4016cSRobert Mustacchi 		return (DLADM_WALK_CONTINUE);
265*48a4016cSRobert Mustacchi 	}
266*48a4016cSRobert Mustacchi 
267*48a4016cSRobert Mustacchi 	count = gt.dgt_tran_id;
268*48a4016cSRobert Mustacchi 	(void) printf("%s: discovered %d transceiver%s\n", name, count,
269*48a4016cSRobert Mustacchi 	    count > 1 ? "s" : "");
270*48a4016cSRobert Mustacchi 	for (i = 0; i < count; i++) {
271*48a4016cSRobert Mustacchi 		if (tranid != UINT_MAX && i != tranid)
272*48a4016cSRobert Mustacchi 			continue;
273*48a4016cSRobert Mustacchi 		if (tranid != UINT_MAX)
274*48a4016cSRobert Mustacchi 			tran_found = B_TRUE;
275*48a4016cSRobert Mustacchi 		bzero(&gt, sizeof (gt));
276*48a4016cSRobert Mustacchi 		gt.dgt_linkid = linkid;
277*48a4016cSRobert Mustacchi 		gt.dgt_tran_id = i;
278*48a4016cSRobert Mustacchi 
279*48a4016cSRobert Mustacchi 		if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETTRAN, &gt) != 0) {
280*48a4016cSRobert Mustacchi 			(void) fprintf(stderr, "failed to get tran info for "
281*48a4016cSRobert Mustacchi 			    "%s: %s\n", name, strerror(errno));
282*48a4016cSRobert Mustacchi 			dltran_errors++;
283*48a4016cSRobert Mustacchi 			return (DLADM_WALK_CONTINUE);
284*48a4016cSRobert Mustacchi 		}
285*48a4016cSRobert Mustacchi 
286*48a4016cSRobert Mustacchi 		if (dltran_hex && !gt.dgt_present)
287*48a4016cSRobert Mustacchi 			continue;
288*48a4016cSRobert Mustacchi 		if (!dltran_hex && !dltran_write) {
289*48a4016cSRobert Mustacchi 			(void) printf("\ttransceiver %d present: %s\n", i,
290*48a4016cSRobert Mustacchi 			    gt.dgt_present ? "yes" : "no");
291*48a4016cSRobert Mustacchi 			if (!gt.dgt_present)
292*48a4016cSRobert Mustacchi 				continue;
293*48a4016cSRobert Mustacchi 			(void) printf("\ttransceiver %d usable: %s\n", i,
294*48a4016cSRobert Mustacchi 			    gt.dgt_usable ? "yes" : "no");
295*48a4016cSRobert Mustacchi 		}
296*48a4016cSRobert Mustacchi 
297*48a4016cSRobert Mustacchi 		if (dltran_verbose) {
298*48a4016cSRobert Mustacchi 			dltran_verbose_dump(linkid, i);
299*48a4016cSRobert Mustacchi 		}
300*48a4016cSRobert Mustacchi 
301*48a4016cSRobert Mustacchi 		if (dltran_write) {
302*48a4016cSRobert Mustacchi 			if (!gt.dgt_present) {
303*48a4016cSRobert Mustacchi 				(void) fprintf(stderr, "warning: no "
304*48a4016cSRobert Mustacchi 				    "transceiver present in port %d, not "
305*48a4016cSRobert Mustacchi 				    "writing\n", i);
306*48a4016cSRobert Mustacchi 				dltran_errors++;
307*48a4016cSRobert Mustacchi 				continue;
308*48a4016cSRobert Mustacchi 			}
309*48a4016cSRobert Mustacchi 			dltran_write_page(linkid, i);
310*48a4016cSRobert Mustacchi 		}
311*48a4016cSRobert Mustacchi 
312*48a4016cSRobert Mustacchi 		if (dltran_hex) {
313*48a4016cSRobert Mustacchi 			printf("transceiver %d data:\n", i);
314*48a4016cSRobert Mustacchi 			dltran_hex_dump(linkid, i);
315*48a4016cSRobert Mustacchi 		}
316*48a4016cSRobert Mustacchi 	}
317*48a4016cSRobert Mustacchi 
318*48a4016cSRobert Mustacchi 	if (tranid != UINT_MAX && !tran_found) {
319*48a4016cSRobert Mustacchi 		dltran_errors++;
320*48a4016cSRobert Mustacchi 		(void) fprintf(stderr, "failed to find transceiver %d on "
321*48a4016cSRobert Mustacchi 		    "link %s\n", tranid, name);
322*48a4016cSRobert Mustacchi 	}
323*48a4016cSRobert Mustacchi 
324*48a4016cSRobert Mustacchi 	return (DLADM_WALK_CONTINUE);
325*48a4016cSRobert Mustacchi }
326*48a4016cSRobert Mustacchi 
327*48a4016cSRobert Mustacchi 
328*48a4016cSRobert Mustacchi static void
dltran_usage(const char * fmt,...)329*48a4016cSRobert Mustacchi dltran_usage(const char *fmt, ...)
330*48a4016cSRobert Mustacchi {
331*48a4016cSRobert Mustacchi 	if (fmt != NULL) {
332*48a4016cSRobert Mustacchi 		va_list ap;
333*48a4016cSRobert Mustacchi 
334*48a4016cSRobert Mustacchi 		(void) fprintf(stderr, "%s: ", dltran_progname);
335*48a4016cSRobert Mustacchi 		va_start(ap, fmt);
336*48a4016cSRobert Mustacchi 		(void) vfprintf(stderr, fmt, ap);
337*48a4016cSRobert Mustacchi 		va_end(ap);
338*48a4016cSRobert Mustacchi 	}
339*48a4016cSRobert Mustacchi 
340*48a4016cSRobert Mustacchi 	(void) fprintf(stderr, "Usage: %s [-x | -v | -w file] [tran]...\n"
341*48a4016cSRobert Mustacchi 	    "\n"
342*48a4016cSRobert Mustacchi 	    "\t-v	display all transceiver information\n"
343*48a4016cSRobert Mustacchi 	    "\t-w	write transceiver data page 0xa0 to file\n"
344*48a4016cSRobert Mustacchi 	    "\t-x	dump raw hexadecimal for transceiver\n",
345*48a4016cSRobert Mustacchi 	    dltran_progname);
346*48a4016cSRobert Mustacchi }
347*48a4016cSRobert Mustacchi 
348*48a4016cSRobert Mustacchi int
main(int argc,char * argv[])349*48a4016cSRobert Mustacchi main(int argc, char *argv[])
350*48a4016cSRobert Mustacchi {
351*48a4016cSRobert Mustacchi 	int c;
352*48a4016cSRobert Mustacchi 	dladm_status_t status;
353*48a4016cSRobert Mustacchi 	const char *outfile = NULL;
354*48a4016cSRobert Mustacchi 	uint_t count = 0;
355*48a4016cSRobert Mustacchi 
356*48a4016cSRobert Mustacchi 	dltran_progname = basename(argv[0]);
357*48a4016cSRobert Mustacchi 
358*48a4016cSRobert Mustacchi 	while ((c = getopt(argc, argv, ":xvw:")) != -1) {
359*48a4016cSRobert Mustacchi 		switch (c) {
360*48a4016cSRobert Mustacchi 		case 'v':
361*48a4016cSRobert Mustacchi 			dltran_verbose = B_TRUE;
362*48a4016cSRobert Mustacchi 			break;
363*48a4016cSRobert Mustacchi 		case 'x':
364*48a4016cSRobert Mustacchi 			dltran_hex = B_TRUE;
365*48a4016cSRobert Mustacchi 			break;
366*48a4016cSRobert Mustacchi 		case 'w':
367*48a4016cSRobert Mustacchi 			dltran_write = B_TRUE;
368*48a4016cSRobert Mustacchi 			outfile = optarg;
369*48a4016cSRobert Mustacchi 			break;
370*48a4016cSRobert Mustacchi 		case ':':
371*48a4016cSRobert Mustacchi 			dltran_usage("option -%c requires an "
372*48a4016cSRobert Mustacchi 			    "operand\n", optopt);
373*48a4016cSRobert Mustacchi 			return (2);
374*48a4016cSRobert Mustacchi 		case '?':
375*48a4016cSRobert Mustacchi 		default:
376*48a4016cSRobert Mustacchi 			dltran_usage("unknown option: -%c\n", optopt);
377*48a4016cSRobert Mustacchi 			return (2);
378*48a4016cSRobert Mustacchi 		}
379*48a4016cSRobert Mustacchi 	}
380*48a4016cSRobert Mustacchi 
381*48a4016cSRobert Mustacchi 	argc -= optind;
382*48a4016cSRobert Mustacchi 	argv += optind;
383*48a4016cSRobert Mustacchi 
384*48a4016cSRobert Mustacchi 	if (dltran_verbose)
385*48a4016cSRobert Mustacchi 		count++;
386*48a4016cSRobert Mustacchi 	if (dltran_hex)
387*48a4016cSRobert Mustacchi 		count++;
388*48a4016cSRobert Mustacchi 	if (dltran_write)
389*48a4016cSRobert Mustacchi 		count++;
390*48a4016cSRobert Mustacchi 	if (count > 1) {
391*48a4016cSRobert Mustacchi 		(void) fprintf(stderr, "only one of -v, -w, and -x may be "
392*48a4016cSRobert Mustacchi 		    "specified\n");
393*48a4016cSRobert Mustacchi 		return (2);
394*48a4016cSRobert Mustacchi 	}
395*48a4016cSRobert Mustacchi 
396*48a4016cSRobert Mustacchi 	if (dltran_write) {
397*48a4016cSRobert Mustacchi 		if ((dltran_outfd = open(outfile, O_RDWR | O_TRUNC | O_CREAT,
398*48a4016cSRobert Mustacchi 		    0644)) < 0) {
399*48a4016cSRobert Mustacchi 			(void) fprintf(stderr, "failed to open output file "
400*48a4016cSRobert Mustacchi 			    "%s: %s\n", outfile, strerror(errno));
401*48a4016cSRobert Mustacchi 			return (1);
402*48a4016cSRobert Mustacchi 		}
403*48a4016cSRobert Mustacchi 	}
404*48a4016cSRobert Mustacchi 
405*48a4016cSRobert Mustacchi 	if ((status = dladm_open(&dltran_hdl)) != DLADM_STATUS_OK) {
406*48a4016cSRobert Mustacchi 		(void) fprintf(stderr, "failed to open /dev/dld: %s\n",
407*48a4016cSRobert Mustacchi 		    dladm_status2str(status, dltran_dlerrmsg));
408*48a4016cSRobert Mustacchi 		return (1);
409*48a4016cSRobert Mustacchi 	}
410*48a4016cSRobert Mustacchi 
411*48a4016cSRobert Mustacchi 	if (argc == 0) {
412*48a4016cSRobert Mustacchi 		(void) dladm_walk_datalink_id(dltran_dump_transceivers,
413*48a4016cSRobert Mustacchi 		    dltran_hdl, NULL, DATALINK_CLASS_PHYS,
414*48a4016cSRobert Mustacchi 		    DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
415*48a4016cSRobert Mustacchi 	} else {
416*48a4016cSRobert Mustacchi 		int i;
417*48a4016cSRobert Mustacchi 		char *c;
418*48a4016cSRobert Mustacchi 
419*48a4016cSRobert Mustacchi 		for (i = 0; i < argc; i++) {
420*48a4016cSRobert Mustacchi 			uint_t tran;
421*48a4016cSRobert Mustacchi 			uint_t *tranidp = NULL;
422*48a4016cSRobert Mustacchi 			datalink_id_t linkid;
423*48a4016cSRobert Mustacchi 
424*48a4016cSRobert Mustacchi 			if ((c = strrchr(argv[i], '/')) != NULL) {
425*48a4016cSRobert Mustacchi 				unsigned long u;
426*48a4016cSRobert Mustacchi 				char *eptr;
427*48a4016cSRobert Mustacchi 
428*48a4016cSRobert Mustacchi 				c++;
429*48a4016cSRobert Mustacchi 				errno = 0;
430*48a4016cSRobert Mustacchi 				u = strtoul(c, &eptr, 10);
431*48a4016cSRobert Mustacchi 				if (errno != 0 || *eptr != '\0' ||
432*48a4016cSRobert Mustacchi 				    u >= UINT_MAX) {
433*48a4016cSRobert Mustacchi 					(void) fprintf(stderr, "failed to "
434*48a4016cSRobert Mustacchi 					    "parse link/transceiver: %s\n",
435*48a4016cSRobert Mustacchi 					    argv[i]);
436*48a4016cSRobert Mustacchi 					return (1);
437*48a4016cSRobert Mustacchi 				}
438*48a4016cSRobert Mustacchi 				c--;
439*48a4016cSRobert Mustacchi 				*c = '\0';
440*48a4016cSRobert Mustacchi 				tran = (uint_t)u;
441*48a4016cSRobert Mustacchi 				tranidp = &tran;
442*48a4016cSRobert Mustacchi 			}
443*48a4016cSRobert Mustacchi 
444*48a4016cSRobert Mustacchi 			if ((status = dladm_name2info(dltran_hdl, argv[i],
445*48a4016cSRobert Mustacchi 			    &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
446*48a4016cSRobert Mustacchi 				(void) fprintf(stderr, "failed to get link "
447*48a4016cSRobert Mustacchi 				    "id for link %s: %s\n", argv[i],
448*48a4016cSRobert Mustacchi 				    dladm_status2str(status, dltran_dlerrmsg));
449*48a4016cSRobert Mustacchi 				return (1);
450*48a4016cSRobert Mustacchi 			}
451*48a4016cSRobert Mustacchi 
452*48a4016cSRobert Mustacchi 			(void) dltran_dump_transceivers(dltran_hdl, linkid,
453*48a4016cSRobert Mustacchi 			    tranidp);
454*48a4016cSRobert Mustacchi 		}
455*48a4016cSRobert Mustacchi 	}
456*48a4016cSRobert Mustacchi 
457*48a4016cSRobert Mustacchi 	return (dltran_errors != 0 ? 1 : 0);
458*48a4016cSRobert Mustacchi }
459