xref: /illumos-gate/usr/src/cmd/luxadm/qlgcupdate.c (revision e9175934)
1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22c1911baeSReed  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24fcf3ce44SJohn Forte  */
25fcf3ce44SJohn Forte 
26fcf3ce44SJohn Forte /*
27fcf3ce44SJohn Forte  * I18N message number ranges
28fcf3ce44SJohn Forte  *  This file: 21000 - 21499
29fcf3ce44SJohn Forte  *  Shared common messages: 1 - 1999
30fcf3ce44SJohn Forte  */
31fcf3ce44SJohn Forte 
32fcf3ce44SJohn Forte /*
33fcf3ce44SJohn Forte  * Functions to support the download of FCode to PCI HBAs
34fcf3ce44SJohn Forte  * Qlogic ISP21XX/22XX boards: FC100/P single port, ISP2200 dual port
35fcf3ce44SJohn Forte  * and Emulex cards
36fcf3ce44SJohn Forte  */
37fcf3ce44SJohn Forte #include <errno.h>
38fcf3ce44SJohn Forte #include <ctype.h>
39fcf3ce44SJohn Forte #include <fcntl.h>
40fcf3ce44SJohn Forte #include <stdio.h>
41fcf3ce44SJohn Forte #include <string.h>
42fcf3ce44SJohn Forte #include <strings.h>
43fcf3ce44SJohn Forte #include <unistd.h>
44fcf3ce44SJohn Forte #include <stdlib.h>
45fcf3ce44SJohn Forte #include <sys/stat.h>
46fcf3ce44SJohn Forte #include <limits.h>
47fcf3ce44SJohn Forte #include <signal.h>
48fcf3ce44SJohn Forte #include <dirent.h>
49fcf3ce44SJohn Forte #include <nl_types.h>
50fcf3ce44SJohn Forte #include <utmpx.h>
51fcf3ce44SJohn Forte #include <sys/mnttab.h>
52fcf3ce44SJohn Forte #include <sys/file.h>
53fcf3ce44SJohn Forte #include <sys/mtio.h>
54fcf3ce44SJohn Forte #include <sys/scsi/impl/uscsi.h>
55fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h>
56fcf3ce44SJohn Forte #include <stgcom.h>
57fcf3ce44SJohn Forte #include <sys/scsi/adapters/ifpio.h>
58fcf3ce44SJohn Forte #include <libdevinfo.h>
59fcf3ce44SJohn Forte #include "luxadm.h"
60fcf3ce44SJohn Forte 
61fcf3ce44SJohn Forte /* Error codes - used by the fcode_load_file routine */
62fcf3ce44SJohn Forte #define	FCODE_SUCCESS	    0	/* successful completion */
63fcf3ce44SJohn Forte #define	FCODE_LOAD_FAILURE  1	/* general failure */
64fcf3ce44SJohn Forte #define	FCODE_IOCTL_FAILURE 2	/* FCODE ioctl download failure */
65fcf3ce44SJohn Forte 
66fcf3ce44SJohn Forte #define	HBA_MAX	128
67fcf3ce44SJohn Forte #define	FCODE_HDR 200
68fcf3ce44SJohn Forte #define	MAX_RETRIES	3
69fcf3ce44SJohn Forte #define	MAX_WAIT_TIME	30
70fcf3ce44SJohn Forte 
71fcf3ce44SJohn Forte /*
72fcf3ce44SJohn Forte  * EMULEX Fcode attributes
73fcf3ce44SJohn Forte  */
74fcf3ce44SJohn Forte #define	EMULEX_FCODE_VERSION_LENGTH	16
75fcf3ce44SJohn Forte #define	EMULEX_READ_BUFFER_SIZE		128
76fcf3ce44SJohn Forte 
77fcf3ce44SJohn Forte /* Emulex specific error codes */
78fcf3ce44SJohn Forte #define	EMLX_ERRNO_START	0x100
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte /* Diagnostic error codes */
81fcf3ce44SJohn Forte #define	EMLX_TEST_FAILED	(EMLX_ERRNO_START + 0)
82fcf3ce44SJohn Forte 
83fcf3ce44SJohn Forte /* Download image contains bad data */
84fcf3ce44SJohn Forte #define	EMLX_IMAGE_BAD		(EMLX_ERRNO_START + 1)
85fcf3ce44SJohn Forte /* Download image not compatible with current hardware */
86fcf3ce44SJohn Forte #define	EMLX_IMAGE_INCOMPATIBLE	(EMLX_ERRNO_START + 2)
87fcf3ce44SJohn Forte /* Unable to take adapter offline */
88fcf3ce44SJohn Forte #define	EMLX_IMAGE_FAILED	(EMLX_ERRNO_START + 3)
89fcf3ce44SJohn Forte /* Image download failed */
90fcf3ce44SJohn Forte #define	EMLX_OFFLINE_FAILED	(EMLX_ERRNO_START + 4)
91fcf3ce44SJohn Forte 
92fcf3ce44SJohn Forte 
93fcf3ce44SJohn Forte 
94fcf3ce44SJohn Forte 
95fcf3ce44SJohn Forte /*
96fcf3ce44SJohn Forte  * This is just a random value chosen to identify Sbus Fcodes. Sbus FCode
97fcf3ce44SJohn Forte  * for Ivory is based on a 2200 chip but this value does not reflect that.
98fcf3ce44SJohn Forte  */
99fcf3ce44SJohn Forte #define	SBUS_CHIP_ID	0x1969
100fcf3ce44SJohn Forte #define	IVORY_BUS	"/sbus@"
101fcf3ce44SJohn Forte #define	IVORY_DRVR	"/SUNW,qlc@"
102fcf3ce44SJohn Forte 
103fcf3ce44SJohn Forte /*	Global variables	*/
104fcf3ce44SJohn Forte static char	fc_trans[] = "SUNW,ifp";	/* fibre channel transport */
105fcf3ce44SJohn Forte static char	fp_trans[] = "SUNW,qlc";	/* fca layer driver	   */
106fcf3ce44SJohn Forte static char	fp_trans_id[] = "fp@";		/* transport layer id	   */
107fcf3ce44SJohn Forte static char	qlgc2100[] = "FC100/P";		/* product name for 2100   */
108fcf3ce44SJohn Forte static char	qlgc2200[] = "ISP2200";		/* product name for 2200   */
109fcf3ce44SJohn Forte static char	qlgc2300[] = "ISP2300";		/* product name for 2300   */
110fcf3ce44SJohn Forte static char	qlgc2312[] = "ISP2312";		/* product name for 2312   */
111fcf3ce44SJohn Forte /*
112fcf3ce44SJohn Forte  * The variable qlgc2200Sbus represents the string which is always the
113fcf3ce44SJohn Forte  * starting string of the version information in an ISP2200 Sbus Fcode.
114fcf3ce44SJohn Forte  */
115fcf3ce44SJohn Forte static char	qlgc2200Sbus[] = "ISP2200 Sbus FC-AL Host Adapter Driver";
116fcf3ce44SJohn Forte static char	pcibus_list[HBA_MAX][PATH_MAX];
117fcf3ce44SJohn Forte /*	Internal functions	*/
118fcf3ce44SJohn Forte static int	q_load_file(int, char *);
119fcf3ce44SJohn Forte static int	q_getbootdev(uchar_t *);
120fcf3ce44SJohn Forte static int	q_getdevctlpath(char *, int *);
121fcf3ce44SJohn Forte static int	q_warn(int);
122fcf3ce44SJohn Forte static int	q_findversion(int, int, uchar_t *, uint16_t *);
123c1911baeSReed static int	q_findfileversion(char *, uchar_t *, uint16_t *, int, int *);
124c1911baeSReed static int	q_findSbusfile(int, int *);
125fcf3ce44SJohn Forte static int	memstrstr(char *, char *, int, int);
126fcf3ce44SJohn Forte static int	fcode_load_file(int, char *, int *);
127fcf3ce44SJohn Forte 
128fcf3ce44SJohn Forte /*
129fcf3ce44SJohn Forte  * Functions to support Fcode download for Emulex HBAs
130fcf3ce44SJohn Forte  */
131fcf3ce44SJohn Forte static int	emulex_fcodeversion(di_node_t, uchar_t *);
132fcf3ce44SJohn Forte static void	handle_emulex_error(int, char *);
133fcf3ce44SJohn Forte 
134fcf3ce44SJohn Forte /*
135c1911baeSReed  * Searches for and updates the cards.	This is the "main" function
136fcf3ce44SJohn Forte  * and will give the output to the user by calling the subfunctions.
137fcf3ce44SJohn Forte  * args: FCode file; if NULL only the current FCode version is printed
138fcf3ce44SJohn Forte  */
139fcf3ce44SJohn Forte int
q_qlgc_update(unsigned int verbose,char * file)140fcf3ce44SJohn Forte q_qlgc_update(unsigned int verbose, char *file)
141fcf3ce44SJohn Forte /*ARGSUSED*/
142fcf3ce44SJohn Forte {
143fcf3ce44SJohn Forte 	int fd, fcode_fd = -1, errnum = 0, devcnt = 0, retval = 0, isSbus = 0;
144fcf3ce44SJohn Forte 	int sbus_off;
145fcf3ce44SJohn Forte 	uint_t i, fflag = 0;
146fcf3ce44SJohn Forte 	uint16_t chip_id = 0, file_id = 0;
147fcf3ce44SJohn Forte 	uchar_t fcode_buf[FCODE_HDR];
148fcf3ce44SJohn Forte 	static uchar_t	bootpath[PATH_MAX];
149fcf3ce44SJohn Forte 	static uchar_t	version[MAXNAMELEN], version_file[MAXNAMELEN];
150fcf3ce44SJohn Forte 	char devpath[PATH_MAX], tmppath[PATH_MAX];
151fcf3ce44SJohn Forte 	void	(*sigint)(); /* to store default SIGTERM setting */
152fcf3ce44SJohn Forte 	static struct	utmpx *utmpp = NULL; /* pointer for getutxent() */
153fcf3ce44SJohn Forte 	char *ptr1, *ptr2;
154fcf3ce44SJohn Forte 	char phys_path[PATH_MAX];
155fcf3ce44SJohn Forte 	/*
156fcf3ce44SJohn Forte 	 * The variables port1 and port2 are used to store the bus id
157fcf3ce44SJohn Forte 	 * e.g. the bus id for this path:
158fcf3ce44SJohn Forte 	 * /devices/sbus@12,0/SUNW,qlc@2,30000/fp@0,0:devctl
159fcf3ce44SJohn Forte 	 * is "sbus@12". They are initialized to a random value and are
160fcf3ce44SJohn Forte 	 * set such that they are not equal initially.
161fcf3ce44SJohn Forte 	 */
162525fef19SToomas Soome 	static char port1[MAXNAMELEN] = { 0 };
163525fef19SToomas Soome 	static char port2[MAXNAMELEN] = { 0 };
164fcf3ce44SJohn Forte 
165fcf3ce44SJohn Forte 	if (file) {
166fcf3ce44SJohn Forte 		fflag++;
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte 		/* check for a valid file */
169fcf3ce44SJohn Forte 		if ((fcode_fd = open(file, O_RDONLY)) < 0) {
170fcf3ce44SJohn Forte 			(void) fprintf(stderr,
171fcf3ce44SJohn Forte 			    MSGSTR(21000, "Error: Could not open %s\n"), file);
172fcf3ce44SJohn Forte 			return (1);
173fcf3ce44SJohn Forte 		}
174fcf3ce44SJohn Forte 		if (read(fcode_fd, fcode_buf, FCODE_HDR) != FCODE_HDR) {
175fcf3ce44SJohn Forte 			perror(MSGSTR(21001, "read"));
176fcf3ce44SJohn Forte 			(void) close(fcode_fd);
177fcf3ce44SJohn Forte 			return (1);
178fcf3ce44SJohn Forte 		}
179fcf3ce44SJohn Forte 
180fcf3ce44SJohn Forte 		/*
181fcf3ce44SJohn Forte 		 * Check if it's SBUS FCode by calling q_findSbusfile
182fcf3ce44SJohn Forte 		 * if it is then isSbus will be 1, if not it will be 0
183fcf3ce44SJohn Forte 		 * in case of an error, it will be -1
184fcf3ce44SJohn Forte 		 */
185fcf3ce44SJohn Forte 		isSbus = q_findSbusfile(fcode_fd, &sbus_off);
186fcf3ce44SJohn Forte 		if (isSbus == -1) {
187fcf3ce44SJohn Forte 			(void) close(fcode_fd);
188fcf3ce44SJohn Forte 			return (1);
189fcf3ce44SJohn Forte 		}
190fcf3ce44SJohn Forte 
191fcf3ce44SJohn Forte 		/*
192fcf3ce44SJohn Forte 		 * FCode header check - make sure it's PCI FCode
193fcf3ce44SJohn Forte 		 * Structure of FCode header (byte# refers to byte numbering
194fcf3ce44SJohn Forte 		 * in FCode spec, not the byte# of our fcode_buf buffer):
195c1911baeSReed 		 * header	byte 00	   0x55	 prom signature byte one
196c1911baeSReed 		 *		byte 01	   0xaa	 prom signature byte two
197fcf3ce44SJohn Forte 		 * data		byte 00-03 P C I R
198fcf3ce44SJohn Forte 		 * OR
199c1911baeSReed 		 * header	byte 32	   0x55
200c1911baeSReed 		 *		byte 33	   0xaa
201fcf3ce44SJohn Forte 		 * data		byte 60-63 P C I R
202fcf3ce44SJohn Forte 		 * The second format with an offset of 32 is used for ifp prom
203fcf3ce44SJohn Forte 		 */
204fcf3ce44SJohn Forte 		if (!(((fcode_buf[0x00] == 0x55) &&
205fcf3ce44SJohn Forte 		    (fcode_buf[0x01] == 0xaa) &&
206fcf3ce44SJohn Forte 		    (fcode_buf[0x1c] == 'P') &&
207fcf3ce44SJohn Forte 		    (fcode_buf[0x1d] == 'C') &&
208fcf3ce44SJohn Forte 		    (fcode_buf[0x1e] == 'I') &&
209fcf3ce44SJohn Forte 		    (fcode_buf[0x1f] == 'R')) ||
210fcf3ce44SJohn Forte 
211fcf3ce44SJohn Forte 		    ((fcode_buf[0x20] == 0x55) &&
212fcf3ce44SJohn Forte 		    (fcode_buf[0x21] == 0xaa) &&
213fcf3ce44SJohn Forte 		    (fcode_buf[0x3c] == 'P') &&
214fcf3ce44SJohn Forte 		    (fcode_buf[0x3d] == 'C') &&
215fcf3ce44SJohn Forte 		    (fcode_buf[0x3e] == 'I') &&
216fcf3ce44SJohn Forte 		    (fcode_buf[0x3f] == 'R')) ||
217fcf3ce44SJohn Forte 
218fcf3ce44SJohn Forte 		    (isSbus))) {
219fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(21002,
220fcf3ce44SJohn Forte 			    "Error: %s is not a valid FC100/P, "
221fcf3ce44SJohn Forte 			    "ISP2200, ISP23xx FCode file.\n"),
222fcf3ce44SJohn Forte 			    file);
223fcf3ce44SJohn Forte 			(void) close(fcode_fd);
224fcf3ce44SJohn Forte 			return (1);
225fcf3ce44SJohn Forte 		}
226fcf3ce44SJohn Forte 
227fcf3ce44SJohn Forte 		/* check for single user mode */
228fcf3ce44SJohn Forte 		while ((utmpp = getutxent()) != NULL) {
229fcf3ce44SJohn Forte 			if (strstr(utmpp->ut_line, "run-level") &&
230fcf3ce44SJohn Forte 			    (strcmp(utmpp->ut_line, "run-level S") &&
231fcf3ce44SJohn Forte 				strcmp(utmpp->ut_line, "run-level 1"))) {
232fcf3ce44SJohn Forte 				if (q_warn(1)) {
233fcf3ce44SJohn Forte 					(void) endutxent();
234fcf3ce44SJohn Forte 					(void) close(fcode_fd);
235fcf3ce44SJohn Forte 					return (1);
236fcf3ce44SJohn Forte 				}
237fcf3ce44SJohn Forte 				break;
238fcf3ce44SJohn Forte 			}
239fcf3ce44SJohn Forte 		}
240fcf3ce44SJohn Forte 		(void) endutxent();
241fcf3ce44SJohn Forte 
242fcf3ce44SJohn Forte 		/* get bootpath */
243fcf3ce44SJohn Forte 		if (!q_getbootdev((uchar_t *)&bootpath[0]) &&
244fcf3ce44SJohn Forte 		    getenv("_LUX_D_DEBUG") != NULL) {
245fcf3ce44SJohn Forte 			(void) fprintf(stdout, "  Bootpath: %s\n", bootpath);
246fcf3ce44SJohn Forte 		}
247fcf3ce44SJohn Forte 	}
248fcf3ce44SJohn Forte 	/*
249fcf3ce44SJohn Forte 	 * Get count of, and names of PCI slots with ifp device control
250fcf3ce44SJohn Forte 	 * (devctl) nodes.  Search /devices.
251fcf3ce44SJohn Forte 	 */
252fcf3ce44SJohn Forte 	(void) strcpy(devpath, "/devices");
253fcf3ce44SJohn Forte 	if (q_getdevctlpath(devpath, (int *)&devcnt) == 0) {
254fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(21003,
255fcf3ce44SJohn Forte 		"\n  Found Path to %d FC100/P, ISP2200, ISP23xx Devices\n"),
256fcf3ce44SJohn Forte 			devcnt);
257fcf3ce44SJohn Forte 	} else {
258fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21004,
259fcf3ce44SJohn Forte 		"Error: Could not get /devices path to FC100/P,"
260fcf3ce44SJohn Forte 		"ISP2200, ISP23xx Cards.\n"));
261fcf3ce44SJohn Forte 		retval++;
262fcf3ce44SJohn Forte 	}
263fcf3ce44SJohn Forte 
264fcf3ce44SJohn Forte 	for (i = 0; i < devcnt; i++) {
265fcf3ce44SJohn Forte 
266fcf3ce44SJohn Forte 		(void) strncpy((char *)phys_path, &pcibus_list[i][0],
267fcf3ce44SJohn Forte 				strlen(&pcibus_list[i][0]));
268fcf3ce44SJohn Forte 		if (fflag && (strstr((char *)bootpath,
269fcf3ce44SJohn Forte 		    strtok((char *)phys_path, ":")) != NULL)) {
270fcf3ce44SJohn Forte 			(void) fprintf(stderr,
271fcf3ce44SJohn Forte 			    MSGSTR(21005, "Ignoring %s (bootpath)\n"),
272fcf3ce44SJohn Forte 			    &pcibus_list[i][0]);
273fcf3ce44SJohn Forte 			continue;
274fcf3ce44SJohn Forte 		}
275fcf3ce44SJohn Forte 
276fcf3ce44SJohn Forte 		(void) fprintf(stdout,
277fcf3ce44SJohn Forte 		MSGSTR(21006, "\n  Opening Device: %s\n"), &pcibus_list[i][0]);
278fcf3ce44SJohn Forte 		/* Check if the device is valid */
279fcf3ce44SJohn Forte 		if ((fd = open(&pcibus_list[i][0], O_RDWR)) < 0) {
280fcf3ce44SJohn Forte 			(void) fprintf(stderr,
281fcf3ce44SJohn Forte 			    MSGSTR(21000, "Error: Could not open %s\n"),
282fcf3ce44SJohn Forte 			    &pcibus_list[i][0]);
283fcf3ce44SJohn Forte 			retval++;
284fcf3ce44SJohn Forte 			continue;
285fcf3ce44SJohn Forte 		}
286fcf3ce44SJohn Forte 		(void) close(fd);
287fcf3ce44SJohn Forte 		/*
288fcf3ce44SJohn Forte 		 * Check FCode version present on the adapter (at last boot)
289fcf3ce44SJohn Forte 		 */
290fcf3ce44SJohn Forte 		if (q_findversion(verbose, i, (uchar_t *)&version[0],
291fcf3ce44SJohn Forte 		    &chip_id) == 0) {
292fcf3ce44SJohn Forte 			if (strlen((char *)version) == 0) {
293fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(21007,
294fcf3ce44SJohn Forte 	"  Detected FCode Version:\tNo version available for this FCode\n"));
295fcf3ce44SJohn Forte 			} else {
296fcf3ce44SJohn Forte 			(void) fprintf(stdout, MSGSTR(21008,
297fcf3ce44SJohn Forte 			    "  Detected FCode Version:\t%s\n"), version);
298fcf3ce44SJohn Forte 			}
299fcf3ce44SJohn Forte 		} else {
300fcf3ce44SJohn Forte 			chip_id = 0x0;
301fcf3ce44SJohn Forte 		}
302fcf3ce44SJohn Forte 
303fcf3ce44SJohn Forte 		if (fflag) {
304fcf3ce44SJohn Forte 			/*
305fcf3ce44SJohn Forte 			 * For ISP2200, Sbus HBA, do just 1 download
306fcf3ce44SJohn Forte 			 * for both the ports (dual port HBA)
307fcf3ce44SJohn Forte 			 * Here it is assumed that readdir() always
308fcf3ce44SJohn Forte 			 * returns the paths in pcibus_list[] in the
309fcf3ce44SJohn Forte 			 * sorted order.
310fcf3ce44SJohn Forte 			 */
311fcf3ce44SJohn Forte 			(void) strcpy(tmppath, pcibus_list[i]);
312fcf3ce44SJohn Forte 			if (ptr1 = strstr(tmppath, IVORY_BUS)) {
313fcf3ce44SJohn Forte 				if (ptr2 = strstr(ptr1, IVORY_DRVR)) {
314fcf3ce44SJohn Forte 					ptr2 = strchr(ptr2, ',');
315fcf3ce44SJohn Forte 					if (ptr2 = strchr(++ptr2, ',')) {
316fcf3ce44SJohn Forte 						*ptr2 = '\0';
317fcf3ce44SJohn Forte 					}
318fcf3ce44SJohn Forte 				}
319fcf3ce44SJohn Forte 				(void) strcpy(port2, ptr1);
320fcf3ce44SJohn Forte 				if (strcmp(port1, port2) == 0) {
321fcf3ce44SJohn Forte 				    (void) fprintf(stdout, MSGSTR(21037,
322fcf3ce44SJohn Forte 				    "/n New FCode has already been downloaded "
323fcf3ce44SJohn Forte 				    "to this ISP2200 SBus HBA Card.\n"
324fcf3ce44SJohn Forte 				    "It is sufficient to download to one "
325fcf3ce44SJohn Forte 				    "port of the ISP2200 SBus HBA Card. "
326fcf3ce44SJohn Forte 				    "Moving on...\n"));
327fcf3ce44SJohn Forte 					continue;
328fcf3ce44SJohn Forte 				}
329fcf3ce44SJohn Forte 			}
330fcf3ce44SJohn Forte 			/*
331fcf3ce44SJohn Forte 			 * Check version of the supplied FCode file (once)
332fcf3ce44SJohn Forte 			 */
333fcf3ce44SJohn Forte 			if ((file_id != 0 && version_file != NULL) ||
334fcf3ce44SJohn Forte 			    (q_findfileversion((char *)
335fcf3ce44SJohn Forte 			    &fcode_buf[0], (uchar_t *)&version_file[0],
336fcf3ce44SJohn Forte 			    &file_id, isSbus, &sbus_off) == 0)) {
337fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(21009,
338fcf3ce44SJohn Forte 				    "  New FCode Version:\t\t%s\n"),
339fcf3ce44SJohn Forte 				    version_file);
340fcf3ce44SJohn Forte 			} else {
341fcf3ce44SJohn Forte 				(void) close(fcode_fd);
342fcf3ce44SJohn Forte 				return (1);
343fcf3ce44SJohn Forte 			}
344fcf3ce44SJohn Forte 
345fcf3ce44SJohn Forte 			/*
346fcf3ce44SJohn Forte 			 * Load the New FCode
347fcf3ce44SJohn Forte 			 * Give warning if file doesn't appear to be correct
348fcf3ce44SJohn Forte 			 *
349fcf3ce44SJohn Forte 			 */
350fcf3ce44SJohn Forte 			if (chip_id == 0) {
351fcf3ce44SJohn Forte 				errnum = 2; /* can't get chip_id */
352fcf3ce44SJohn Forte 				retval++;
353fcf3ce44SJohn Forte 			} else if (chip_id - file_id != 0) {
354fcf3ce44SJohn Forte 				errnum = 3; /* file/card mismatch */
355fcf3ce44SJohn Forte 				retval++;
356fcf3ce44SJohn Forte 			} else {
357fcf3ce44SJohn Forte 				errnum = 0; /* everything is ok */
358fcf3ce44SJohn Forte 			}
359fcf3ce44SJohn Forte 
360fcf3ce44SJohn Forte 			if (!q_warn(errnum)) {
361fcf3ce44SJohn Forte 				/* Disable user-interrupt Control-C */
362fcf3ce44SJohn Forte 				sigint =
363fcf3ce44SJohn Forte 				    (void (*)(int)) signal(SIGINT, SIG_IGN);
364fcf3ce44SJohn Forte 
365fcf3ce44SJohn Forte 				/* Load FCode */
366fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(21010,
367fcf3ce44SJohn Forte 				    "  Loading FCode: %s\n"), file);
368fcf3ce44SJohn Forte 
369fcf3ce44SJohn Forte 				if (q_load_file(fcode_fd,
370fcf3ce44SJohn Forte 				    &pcibus_list[i][0]) == 0) {
371fcf3ce44SJohn Forte 					(void) fprintf(stdout, MSGSTR(21011,
372fcf3ce44SJohn Forte 					"  Successful FCode download: %s\n"),
373fcf3ce44SJohn Forte 					    &pcibus_list[i][0]);
374fcf3ce44SJohn Forte 					(void) strcpy(port1, port2);
375fcf3ce44SJohn Forte 				} else {
376fcf3ce44SJohn Forte 					(void) fprintf(stderr, MSGSTR(21012,
377fcf3ce44SJohn Forte 					"Error: FCode download failed: %s\n"),
378fcf3ce44SJohn Forte 							&pcibus_list[i][0]);
379fcf3ce44SJohn Forte 					retval++;
380fcf3ce44SJohn Forte 				}
381fcf3ce44SJohn Forte 				/* Restore SIGINT (user interrupt) setting */
382fcf3ce44SJohn Forte 				(void) signal(SIGINT, sigint);
383fcf3ce44SJohn Forte 			}
384fcf3ce44SJohn Forte 		}
385fcf3ce44SJohn Forte 	}
386fcf3ce44SJohn Forte 	(void) fprintf(stdout, "  ");
387fcf3ce44SJohn Forte 	(void) fprintf(stdout, MSGSTR(125, "Complete\n"));
388fcf3ce44SJohn Forte 	if (fcode_fd != -1)
389fcf3ce44SJohn Forte 		(void) close(fcode_fd);
390fcf3ce44SJohn Forte 	return (retval);
391fcf3ce44SJohn Forte }
392fcf3ce44SJohn Forte 
393fcf3ce44SJohn Forte 
394fcf3ce44SJohn Forte /*
395fcf3ce44SJohn Forte  * Retrieve the version banner from the card
396c1911baeSReed  *    uses ioctl: FCIO_FCODE_MCODE_VERSION	FCode revision
397fcf3ce44SJohn Forte  */
398fcf3ce44SJohn Forte static int
q_findversion(int verbose,int index,uchar_t * version,uint16_t * chip_id)399fcf3ce44SJohn Forte q_findversion(int verbose, int index, uchar_t *version, uint16_t *chip_id)
400fcf3ce44SJohn Forte /*ARGSUSED*/
401fcf3ce44SJohn Forte {
402*e9175934SKlaus Ziegler 	int fd = -1, ntries;
403c1911baeSReed 	struct	ifp_fm_version *version_buffer = NULL;
404525fef19SToomas Soome 	char	prom_ver[100] = { 0 };
405525fef19SToomas Soome 	char	mcode_ver[100] = { 0 };
406fcf3ce44SJohn Forte 	fcio_t	fcio;
407fcf3ce44SJohn Forte 
408fcf3ce44SJohn Forte 	if (strstr(&pcibus_list[index][0], fc_trans)) {
409fcf3ce44SJohn Forte 
410fcf3ce44SJohn Forte 	if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) {
411fcf3ce44SJohn Forte 		(void) fprintf(stderr,
412fcf3ce44SJohn Forte 		    MSGSTR(21000, "Error: Could not open %s\n"),
413fcf3ce44SJohn Forte 		    &pcibus_list[index][0]);
414fcf3ce44SJohn Forte 		return (1);
415fcf3ce44SJohn Forte 	}
416fcf3ce44SJohn Forte 
417fcf3ce44SJohn Forte 	if ((version_buffer = (struct ifp_fm_version *)malloc(
418fcf3ce44SJohn Forte 		sizeof (struct ifp_fm_version))) == NULL) {
419fcf3ce44SJohn Forte 		(void) fprintf(stderr,
420fcf3ce44SJohn Forte 		    MSGSTR(21013, "Error: Memory allocation failed\n"));
421fcf3ce44SJohn Forte 		(void) close(fd);
422fcf3ce44SJohn Forte 		return (1);
423fcf3ce44SJohn Forte 	}
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte 	version_buffer->fcode_ver = (char *)version;
426fcf3ce44SJohn Forte 	version_buffer->mcode_ver = mcode_ver;
427fcf3ce44SJohn Forte 	version_buffer->prom_ver = prom_ver;
428fcf3ce44SJohn Forte 	version_buffer->fcode_ver_len = MAXNAMELEN - 1;
429fcf3ce44SJohn Forte 	version_buffer->mcode_ver_len = 100;
430fcf3ce44SJohn Forte 	version_buffer->prom_ver_len = 100;
431fcf3ce44SJohn Forte 
432fcf3ce44SJohn Forte 	if (ioctl(fd, FCIO_FCODE_MCODE_VERSION, version_buffer) < 0) {
433fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21014,
434fcf3ce44SJohn Forte 		"Error: Driver interface FCIO_FCODE_MCODE_VERSION failed\n"));
435fcf3ce44SJohn Forte 		free(version_buffer);
436fcf3ce44SJohn Forte 		(void) close(fd);
437fcf3ce44SJohn Forte 		return (1);
438fcf3ce44SJohn Forte 	}
439fcf3ce44SJohn Forte 	version[version_buffer->fcode_ver_len] = '\0';
440fcf3ce44SJohn Forte 
441fcf3ce44SJohn Forte 	/* Need a way to get card MCODE (firmware) to track certain HW bugs */
442fcf3ce44SJohn Forte 	if (getenv("_LUX_D_DEBUG") != NULL) {
443fcf3ce44SJohn Forte 		(void) fprintf(stdout, "  Device %i: QLGC chip_id %x\n",
444fcf3ce44SJohn Forte 		    index+1, *chip_id);
445fcf3ce44SJohn Forte 		(void) fprintf(stdout, "  FCode:%s\n  MCODE:%s\n  PROM:%s\n",
446fcf3ce44SJohn Forte 		    (char *)version, mcode_ver, prom_ver);
447fcf3ce44SJohn Forte 	}
448fcf3ce44SJohn Forte 	free(version_buffer);
449fcf3ce44SJohn Forte 
450fcf3ce44SJohn Forte 	} else if (strstr(&pcibus_list[index][0], fp_trans)) {
451fcf3ce44SJohn Forte 		/*
452fcf3ce44SJohn Forte 		 * Get the fcode and prom's fw version
453fcf3ce44SJohn Forte 		 * using the fp ioctls. Currently, we pass
454fcf3ce44SJohn Forte 		 * only the fcode version to the calling function
455fcf3ce44SJohn Forte 		 * and ignore the FW version (using the existing
456fcf3ce44SJohn Forte 		 * implementation).
457fcf3ce44SJohn Forte 		 */
458fcf3ce44SJohn Forte 
459fcf3ce44SJohn Forte 		if ((fd = open(&pcibus_list[index][0], O_RDWR)) < 0) {
460fcf3ce44SJohn Forte 			(void) fprintf(stderr,
461fcf3ce44SJohn Forte 			    MSGSTR(4511, "Could not open %s\n"),
462fcf3ce44SJohn Forte 			    &pcibus_list[index][0]);
463fcf3ce44SJohn Forte 			(void) close(fd);
464fcf3ce44SJohn Forte 			return (1);
465fcf3ce44SJohn Forte 		}
466fcf3ce44SJohn Forte 		/* Get the fcode version */
467fcf3ce44SJohn Forte 		bzero(version, sizeof (version));
468fcf3ce44SJohn Forte 		fcio.fcio_cmd = FCIO_GET_FCODE_REV;
469fcf3ce44SJohn Forte 		/* Information read operation */
470fcf3ce44SJohn Forte 		fcio.fcio_xfer = FCIO_XFER_READ;
471fcf3ce44SJohn Forte 		fcio.fcio_obuf = (caddr_t)version;
472fcf3ce44SJohn Forte 		fcio.fcio_olen = MAXNAMELEN;
473fcf3ce44SJohn Forte 
474fcf3ce44SJohn Forte 		for (ntries = 0; ntries < MAX_RETRIES; ntries++) {
475fcf3ce44SJohn Forte 			if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
476fcf3ce44SJohn Forte 				if ((errno == EAGAIN) &&
477fcf3ce44SJohn Forte 				    (ntries+1 < MAX_RETRIES)) {
478fcf3ce44SJohn Forte 					/* wait 30 secs */
479fcf3ce44SJohn Forte 					(void) sleep(MAX_WAIT_TIME);
480fcf3ce44SJohn Forte 					continue;
481fcf3ce44SJohn Forte 				}
482fcf3ce44SJohn Forte 				(void) close(fd);
483fcf3ce44SJohn Forte 				return (L_FCIO_GET_FCODE_REV_FAIL);
484fcf3ce44SJohn Forte 			}
485fcf3ce44SJohn Forte 			break;
486fcf3ce44SJohn Forte 		}
487fcf3ce44SJohn Forte 		version[MAXNAMELEN-1] = '\0';
488fcf3ce44SJohn Forte 	}
489fcf3ce44SJohn Forte 
490fcf3ce44SJohn Forte 	/* Get type of card from product name in FCode version banner */
491fcf3ce44SJohn Forte 	if (strstr((char *)version, qlgc2100)) {
492fcf3ce44SJohn Forte 		*chip_id = 0x2100;
493fcf3ce44SJohn Forte 	} else if (strstr((char *)version, qlgc2200)) {
494fcf3ce44SJohn Forte 		*chip_id = 0x2200;
495fcf3ce44SJohn Forte 		if (strstr((char *)version, "Sbus")) {
496fcf3ce44SJohn Forte 			*chip_id = SBUS_CHIP_ID;
497fcf3ce44SJohn Forte 		}
498fcf3ce44SJohn Forte 	} else if (strstr((char *)version, qlgc2300)) {
499fcf3ce44SJohn Forte 		*chip_id = 0x2300;
500fcf3ce44SJohn Forte 	} else if (strstr((char *)version, qlgc2312)) {
501fcf3ce44SJohn Forte 		*chip_id = 0x2312;
502fcf3ce44SJohn Forte 	} else {
503fcf3ce44SJohn Forte 		*chip_id = 0x0;
504fcf3ce44SJohn Forte 	}
505fcf3ce44SJohn Forte 
506fcf3ce44SJohn Forte 	(void) close(fd);
507fcf3ce44SJohn Forte 	return (0);
508fcf3ce44SJohn Forte }
509fcf3ce44SJohn Forte 
510fcf3ce44SJohn Forte /*
511fcf3ce44SJohn Forte  * Retrieve the version banner and file type (2100 or 2200) from the file
512fcf3ce44SJohn Forte  */
513fcf3ce44SJohn Forte static int
q_findfileversion(char * dl_fcode,uchar_t * version_file,uint16_t * file_id,int isSbus,int * sbus_offset)514fcf3ce44SJohn Forte q_findfileversion(char *dl_fcode, uchar_t *version_file, uint16_t *file_id,
515fcf3ce44SJohn Forte 		    int isSbus, int *sbus_offset)
516fcf3ce44SJohn Forte {
517fcf3ce44SJohn Forte 	int mark;
518fcf3ce44SJohn Forte 	int qlc_offset = 0;
519525fef19SToomas Soome 	char temp[4] = { 0 };
520fcf3ce44SJohn Forte 
521fcf3ce44SJohn Forte 
522fcf3ce44SJohn Forte 	/*
523fcf3ce44SJohn Forte 	 * Get file version from FCode for 2100 or 2202
524fcf3ce44SJohn Forte 	 */
525fcf3ce44SJohn Forte 	if (isSbus) {
526fcf3ce44SJohn Forte 		*file_id = SBUS_CHIP_ID;
527fcf3ce44SJohn Forte 	} else {
528fcf3ce44SJohn Forte 		if ((dl_fcode[0x23] == 0x22) ||
529fcf3ce44SJohn Forte 		    (dl_fcode[0x23] == 0x23)) {
530fcf3ce44SJohn Forte 			*file_id = dl_fcode[0x22] & 0xff;
531fcf3ce44SJohn Forte 			*file_id |= (dl_fcode[0x23] << 8) & 0xff00;
532fcf3ce44SJohn Forte 		} else {
533fcf3ce44SJohn Forte 			*file_id = dl_fcode[0x42] & 0xff;
534fcf3ce44SJohn Forte 			*file_id |= (dl_fcode[0x43] << 8) & 0xff00;
535fcf3ce44SJohn Forte 		}
536fcf3ce44SJohn Forte 	}
537fcf3ce44SJohn Forte 
538fcf3ce44SJohn Forte 	/*
539fcf3ce44SJohn Forte 	 * Ok, we're just checking for 2200 here. If it is we need
540fcf3ce44SJohn Forte 	 * to offset to find the banner.
541fcf3ce44SJohn Forte 	 */
542fcf3ce44SJohn Forte 	if ((*file_id == 0x2200) ||
543fcf3ce44SJohn Forte 	    (*file_id == 0x2300) ||
544fcf3ce44SJohn Forte 	    (*file_id == 0x2312)) {
545fcf3ce44SJohn Forte 		qlc_offset = -32;
546fcf3ce44SJohn Forte 	}
547fcf3ce44SJohn Forte 
548fcf3ce44SJohn Forte 	/*
549fcf3ce44SJohn Forte 	 * If this is an ISP2200 Sbus Fcode file, then search for the string
550fcf3ce44SJohn Forte 	 * "ISP2200 FC-AL Host Adapter Driver" in the whole fcode file
551fcf3ce44SJohn Forte 	 */
552fcf3ce44SJohn Forte 	if (isSbus) {
553fcf3ce44SJohn Forte 		*file_id = SBUS_CHIP_ID;
554fcf3ce44SJohn Forte 		qlc_offset = *sbus_offset;
555fcf3ce44SJohn Forte 		/* Subtract 111 from the offset we add below for PCI Fcodes */
556fcf3ce44SJohn Forte 		qlc_offset -= 111;
557fcf3ce44SJohn Forte 	}
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte 	/* Banner length varies; grab banner to end of date marker yr/mo/da */
560fcf3ce44SJohn Forte 	version_file[0] = '\0';
561fcf3ce44SJohn Forte 	for (mark = (111 + qlc_offset); mark < (191 + qlc_offset); mark++) {
562fcf3ce44SJohn Forte 		(void) strncpy(temp, (char *)&dl_fcode[mark], 4);
563fcf3ce44SJohn Forte 		if ((strncmp(&temp[0], "/", 1) == 0) &&
564fcf3ce44SJohn Forte 		    (strncmp(&temp[3], "/", 1) == 0)) {
565fcf3ce44SJohn Forte 			(void) strncat((char *)version_file,
566fcf3ce44SJohn Forte 			    (char *)&dl_fcode[mark], 6);
567fcf3ce44SJohn Forte 			break;
568fcf3ce44SJohn Forte 		}
569fcf3ce44SJohn Forte 		(void) strncat((char *)version_file, temp, 1);
570fcf3ce44SJohn Forte 	}
571fcf3ce44SJohn Forte 	return (0);
572fcf3ce44SJohn Forte }
573fcf3ce44SJohn Forte 
574fcf3ce44SJohn Forte /*
575fcf3ce44SJohn Forte  * Find if the FCode file is a ISP2200 SBUS Fcode file
576fcf3ce44SJohn Forte  */
577fcf3ce44SJohn Forte static int
q_findSbusfile(int fd,int * sbus_offset)578fcf3ce44SJohn Forte q_findSbusfile(int fd, int *sbus_offset)
579fcf3ce44SJohn Forte {
580fcf3ce44SJohn Forte 	static int file_size;
581fcf3ce44SJohn Forte 	char *sbus_info;
582fcf3ce44SJohn Forte 	struct stat statinfo;
583fcf3ce44SJohn Forte 
584fcf3ce44SJohn Forte 	if (lseek(fd, 0, SEEK_SET) == -1) {
585fcf3ce44SJohn Forte 		perror(MSGSTR(21022, "seek"));
586fcf3ce44SJohn Forte 		return (-1);
587fcf3ce44SJohn Forte 	}
588fcf3ce44SJohn Forte 	if (fstat(fd, &statinfo)) {
589fcf3ce44SJohn Forte 		perror(MSGSTR(21023, "fstat"));
590fcf3ce44SJohn Forte 		return (-1);
591fcf3ce44SJohn Forte 	}
592fcf3ce44SJohn Forte 	file_size = statinfo.st_size;
593fcf3ce44SJohn Forte 
594fcf3ce44SJohn Forte 	if ((sbus_info = (char *)malloc(file_size)) == NULL) {
595fcf3ce44SJohn Forte 		(void) fprintf(stderr,
596fcf3ce44SJohn Forte 		    MSGSTR(21013, "Error: Memory allocation failed\n"));
597fcf3ce44SJohn Forte 		return (-1);
598fcf3ce44SJohn Forte 	}
599fcf3ce44SJohn Forte 
600fcf3ce44SJohn Forte 	if (read(fd, sbus_info, file_size) < 0) {
601fcf3ce44SJohn Forte 		perror(MSGSTR(21001, "read"));
602fcf3ce44SJohn Forte 		free(sbus_info);
603fcf3ce44SJohn Forte 		return (-1);
604fcf3ce44SJohn Forte 	}
605fcf3ce44SJohn Forte 
606fcf3ce44SJohn Forte 	/*
607fcf3ce44SJohn Forte 	 * Search for the version string in the whole file
608fcf3ce44SJohn Forte 	 */
609fcf3ce44SJohn Forte 	if ((*sbus_offset = memstrstr((char *)sbus_info, qlgc2200Sbus,
610fcf3ce44SJohn Forte 			    file_size, strlen(qlgc2200Sbus))) != -1) {
611fcf3ce44SJohn Forte 		free(sbus_info);
612fcf3ce44SJohn Forte 		return (1);
613fcf3ce44SJohn Forte 	} else {
614fcf3ce44SJohn Forte 		free(sbus_info);
615fcf3ce44SJohn Forte 		return (0);
616fcf3ce44SJohn Forte 	}
617fcf3ce44SJohn Forte }
618fcf3ce44SJohn Forte 
619fcf3ce44SJohn Forte 
620fcf3ce44SJohn Forte /*
621fcf3ce44SJohn Forte  * Build a list of all the devctl entries for all the 2100/2200 based adapters
622fcf3ce44SJohn Forte  */
623fcf3ce44SJohn Forte static int
q_getdevctlpath(char * devpath,int * devcnt)624fcf3ce44SJohn Forte q_getdevctlpath(char *devpath, int *devcnt)
625fcf3ce44SJohn Forte {
626fcf3ce44SJohn Forte 	struct stat	statbuf;
627fcf3ce44SJohn Forte 	struct dirent	*dirp = NULL;
628fcf3ce44SJohn Forte 	DIR		*dp = NULL;
629fcf3ce44SJohn Forte 	char		*ptr = NULL;
6300373a3dfSbing hu - Sun Microsystems - Beijing China 	int		err = 0;
631fcf3ce44SJohn Forte 	int		testopen;
632fcf3ce44SJohn Forte 
633fcf3ce44SJohn Forte 	if (lstat(devpath, &statbuf) < 0) {
634fcf3ce44SJohn Forte 		(void) fprintf(stderr,
635fcf3ce44SJohn Forte 		    MSGSTR(21016, "Error: %s lstat() error\n"), devpath);
636fcf3ce44SJohn Forte 		return (1);
637fcf3ce44SJohn Forte 	}
638fcf3ce44SJohn Forte 
639fcf3ce44SJohn Forte 	if ((strstr(devpath, fc_trans) ||
640fcf3ce44SJohn Forte 	    (strstr(devpath, fp_trans_id) && strstr(devpath, fp_trans))) &&
641fcf3ce44SJohn Forte 	    strstr(devpath, "devctl")) {
642fcf3ce44SJohn Forte 		/* Verify the path is valid */
643fcf3ce44SJohn Forte 		if ((testopen = open(devpath, O_RDONLY)) >= 0) {
644fcf3ce44SJohn Forte 			(void) close(testopen);
645fcf3ce44SJohn Forte 			(void) strcpy(pcibus_list[*devcnt], devpath);
646fcf3ce44SJohn Forte 			*devcnt += 1;
647fcf3ce44SJohn Forte 			return (0);
648fcf3ce44SJohn Forte 		}
649fcf3ce44SJohn Forte 	}
650fcf3ce44SJohn Forte 
651fcf3ce44SJohn Forte 	if (S_ISDIR(statbuf.st_mode) == 0) {
652fcf3ce44SJohn Forte 		/*
653fcf3ce44SJohn Forte 		 * not a directory so
654fcf3ce44SJohn Forte 		 * we don't care about it - return
655fcf3ce44SJohn Forte 		 */
656fcf3ce44SJohn Forte 		return (0);
657fcf3ce44SJohn Forte 	}
658fcf3ce44SJohn Forte 
659fcf3ce44SJohn Forte 	/*
660fcf3ce44SJohn Forte 	 * It's a directory. Call ourself to
661fcf3ce44SJohn Forte 	 * traverse the path(s)
662fcf3ce44SJohn Forte 	 */
663fcf3ce44SJohn Forte 	ptr = devpath + strlen(devpath);
664fcf3ce44SJohn Forte 	*ptr++ = '/';
665fcf3ce44SJohn Forte 	*ptr = 0;
666fcf3ce44SJohn Forte 
667fcf3ce44SJohn Forte 	/* Forget the /devices/pseudo/ directory */
668fcf3ce44SJohn Forte 	if (strcmp(devpath, "/devices/pseudo/") == 0) {
669fcf3ce44SJohn Forte 		return (0);
670fcf3ce44SJohn Forte 	}
671fcf3ce44SJohn Forte 
672fcf3ce44SJohn Forte 	if ((dp = opendir(devpath)) == NULL) {
673fcf3ce44SJohn Forte 		(void) fprintf(stderr,
674fcf3ce44SJohn Forte 		    MSGSTR(21017, "Error: %s Can't read directory\n"), devpath);
675fcf3ce44SJohn Forte 		return (1);
676fcf3ce44SJohn Forte 	}
677fcf3ce44SJohn Forte 
678fcf3ce44SJohn Forte 	while ((dirp = readdir(dp)) != NULL) {
679fcf3ce44SJohn Forte 
680fcf3ce44SJohn Forte 		if (strcmp(dirp->d_name, ".") == 0 ||
681fcf3ce44SJohn Forte 		    strcmp(dirp->d_name, "..") == 0) {
682fcf3ce44SJohn Forte 			continue;
683fcf3ce44SJohn Forte 		}
684fcf3ce44SJohn Forte 		(void) strcpy(ptr, dirp->d_name); /* append name */
685fcf3ce44SJohn Forte 		err = q_getdevctlpath(devpath, devcnt);
686fcf3ce44SJohn Forte 	}
687fcf3ce44SJohn Forte 
688fcf3ce44SJohn Forte 	if (closedir(dp) < 0) {
689fcf3ce44SJohn Forte 		(void) fprintf(stderr,
690fcf3ce44SJohn Forte 		MSGSTR(21018, "Error: Can't close directory %s\n"), devpath);
691fcf3ce44SJohn Forte 		return (1);
692fcf3ce44SJohn Forte 	}
693fcf3ce44SJohn Forte 	return (err);
694fcf3ce44SJohn Forte }
695fcf3ce44SJohn Forte 
696fcf3ce44SJohn Forte /*
697c1911baeSReed  * Get the boot device.	 Cannot load FCode to current boot device.
698fcf3ce44SJohn Forte  * Boot devices under volume management will prompt a warning.
699fcf3ce44SJohn Forte  */
700fcf3ce44SJohn Forte static int
q_getbootdev(uchar_t * bootpath)701fcf3ce44SJohn Forte q_getbootdev(uchar_t *bootpath)
702fcf3ce44SJohn Forte {
703fcf3ce44SJohn Forte 	struct mnttab mp;
704fcf3ce44SJohn Forte 	struct mnttab mpref;
705fcf3ce44SJohn Forte 	FILE *fp = NULL;
706fcf3ce44SJohn Forte 	static char buf[BUFSIZ];
707fcf3ce44SJohn Forte 	char *p = NULL, *p1 = NULL;  /* p = full device, p1 = chunk to rm */
708fcf3ce44SJohn Forte 	char *slot = ":devctl";
709fcf3ce44SJohn Forte 	char *root = "/";
710fcf3ce44SJohn Forte 
711fcf3ce44SJohn Forte 	if ((fp = fopen(MNTTAB, "r")) == NULL) {
712fcf3ce44SJohn Forte 		(void) fprintf(stderr,
713fcf3ce44SJohn Forte 		    MSGSTR(21000, "Error: Could not open %s\n"), MNTTAB);
714fcf3ce44SJohn Forte 		return (1);
715fcf3ce44SJohn Forte 	}
716fcf3ce44SJohn Forte 
717fcf3ce44SJohn Forte 	mntnull(&mpref);
718fcf3ce44SJohn Forte 	mpref.mnt_mountp = (char *)root;
719fcf3ce44SJohn Forte 
720fcf3ce44SJohn Forte 	if (getmntany(fp, &mp, &mpref) != 0 ||
721fcf3ce44SJohn Forte 	    mpref.mnt_mountp == NULL) {
722fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21019,
723fcf3ce44SJohn Forte 		    "Error: Cannot get boot device, check %s.\n"), MNTTAB);
724fcf3ce44SJohn Forte 		(void) fclose(fp);
725fcf3ce44SJohn Forte 		return (1);
726fcf3ce44SJohn Forte 	}
727fcf3ce44SJohn Forte 	(void) fclose(fp);
728fcf3ce44SJohn Forte 
729fcf3ce44SJohn Forte 	/*
730fcf3ce44SJohn Forte 	 * If we can't get a link, we may be dealing with a volume mgr
731fcf3ce44SJohn Forte 	 * so give a warning.  If a colon is present, we likely have a
732fcf3ce44SJohn Forte 	 * non-local disk or cd-rom, so no warning is necessary.
733fcf3ce44SJohn Forte 	 * e.g. /devices/pci@1f,4000/scsi@3/sd@6,0:b (cdrom, no link) or
734c1911baeSReed 	 *	storage-e4:/blah/blah remote boot server
735fcf3ce44SJohn Forte 	 */
736fcf3ce44SJohn Forte 	if (readlink(mp.mnt_special, buf, BUFSIZ) < 0) {
737fcf3ce44SJohn Forte 		if (strstr(mp.mnt_special, ":") == NULL) {
738fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(21020,
739fcf3ce44SJohn Forte 	"\nWarning: Cannot read boot device link, check %s.\n"), MNTTAB);
740fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(21021,
741fcf3ce44SJohn Forte 	"Do not upgrade FCode on adapters controlling the boot device.\n"));
742fcf3ce44SJohn Forte 		}
743fcf3ce44SJohn Forte 		return (1);
744fcf3ce44SJohn Forte 	}
745fcf3ce44SJohn Forte 	/*
746fcf3ce44SJohn Forte 	 * Copy boot device path to bootpath.  First remove leading
747fcf3ce44SJohn Forte 	 * path junk (../../..) then if it's an ifp device, chop off
748fcf3ce44SJohn Forte 	 * the disk and add the devctl to the end of the path.
749fcf3ce44SJohn Forte 	 */
750fcf3ce44SJohn Forte 	if (p = strstr(buf, "/devices")) {
751fcf3ce44SJohn Forte 		if (strstr(buf, fc_trans) != NULL) {
752fcf3ce44SJohn Forte 			p1 = strrchr(p, '/');
753fcf3ce44SJohn Forte 			*p1 = '\0';
754fcf3ce44SJohn Forte 		}
755fcf3ce44SJohn Forte 	}
756fcf3ce44SJohn Forte 	(void) strcpy((char *)bootpath, (char *)p);
757fcf3ce44SJohn Forte 	if (p1) {
758fcf3ce44SJohn Forte 		(void) strcat((char *)bootpath, slot);
759fcf3ce44SJohn Forte 	}
760fcf3ce44SJohn Forte 	return (0);
761fcf3ce44SJohn Forte }
762fcf3ce44SJohn Forte 
763fcf3ce44SJohn Forte /*
764fcf3ce44SJohn Forte  * Load FCode to card.
765fcf3ce44SJohn Forte  *    uses ioctl: IFPIO_FCODE_DOWNLOAD
766fcf3ce44SJohn Forte  */
767fcf3ce44SJohn Forte static int
q_load_file(int fcode_fd,char * device)768fcf3ce44SJohn Forte q_load_file(int fcode_fd, char *device)
769fcf3ce44SJohn Forte {
770fcf3ce44SJohn Forte 	static int	dev_fd, fcode_size;
771fcf3ce44SJohn Forte 	struct stat	stat;
772fcf3ce44SJohn Forte 	ifp_download_t	*download_p = NULL;
773fcf3ce44SJohn Forte 	fcio_t		fcio;
774fcf3ce44SJohn Forte 	uint16_t	file_id = 0;
775*e9175934SKlaus Ziegler 	uchar_t		*bin = NULL;
776fcf3ce44SJohn Forte 
777fcf3ce44SJohn Forte 	if (lseek(fcode_fd, 0, SEEK_SET) == -1) {
778fcf3ce44SJohn Forte 		perror(MSGSTR(21022, "seek"));
779fcf3ce44SJohn Forte 		(void) close(fcode_fd);
780fcf3ce44SJohn Forte 		return (1);
781fcf3ce44SJohn Forte 	}
782fcf3ce44SJohn Forte 	if (fstat(fcode_fd, &stat) == -1) {
783fcf3ce44SJohn Forte 		perror(MSGSTR(21023, "fstat"));
784fcf3ce44SJohn Forte 		(void) close(fcode_fd);
785fcf3ce44SJohn Forte 		return (1);
786fcf3ce44SJohn Forte 	}
787fcf3ce44SJohn Forte 
788fcf3ce44SJohn Forte 	fcode_size = stat.st_size;
789fcf3ce44SJohn Forte 
790fcf3ce44SJohn Forte 	if (strstr(device, fc_trans)) {
791fcf3ce44SJohn Forte 		if ((download_p = (ifp_download_t *)malloc(
792fcf3ce44SJohn Forte 			sizeof (ifp_download_t) + fcode_size)) == NULL) {
793fcf3ce44SJohn Forte 			(void) fprintf(stderr,
794fcf3ce44SJohn Forte 			    MSGSTR(21013, "Error: Memory allocation failed\n"));
795fcf3ce44SJohn Forte 			(void) close(fcode_fd);
796fcf3ce44SJohn Forte 			return (1);
797fcf3ce44SJohn Forte 		}
798fcf3ce44SJohn Forte 	} else {
799fcf3ce44SJohn Forte 		if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) {
800fcf3ce44SJohn Forte 			(void) fprintf(stderr,
801fcf3ce44SJohn Forte 			    MSGSTR(21013, "Error: Memory allocation failed\n"));
802fcf3ce44SJohn Forte 			(void) close(fcode_fd);
803fcf3ce44SJohn Forte 			return (1);
804fcf3ce44SJohn Forte 		}
805fcf3ce44SJohn Forte 	}
806fcf3ce44SJohn Forte 
807fcf3ce44SJohn Forte 	if (strstr(device, fc_trans)) {
808fcf3ce44SJohn Forte 		if (read(fcode_fd, download_p->dl_fcode, fcode_size)
809fcf3ce44SJohn Forte 		    != fcode_size) {
810fcf3ce44SJohn Forte 			perror(MSGSTR(21001, "read"));
811fcf3ce44SJohn Forte 			free(download_p);
812fcf3ce44SJohn Forte 			(void) close(fcode_fd);
813fcf3ce44SJohn Forte 			return (1);
814fcf3ce44SJohn Forte 		}
815fcf3ce44SJohn Forte 	} else {
816fcf3ce44SJohn Forte 		if (read(fcode_fd, bin, fcode_size)
817fcf3ce44SJohn Forte 		    != fcode_size) {
818fcf3ce44SJohn Forte 			perror(MSGSTR(21001, "read"));
819fcf3ce44SJohn Forte 			free(bin);
820fcf3ce44SJohn Forte 			(void) close(fcode_fd);
821fcf3ce44SJohn Forte 			return (1);
822fcf3ce44SJohn Forte 		}
823fcf3ce44SJohn Forte 	}
824fcf3ce44SJohn Forte 
825fcf3ce44SJohn Forte 
826fcf3ce44SJohn Forte 	if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) {
827fcf3ce44SJohn Forte 		(void) fprintf(stderr,
828fcf3ce44SJohn Forte 		    MSGSTR(21000, "Error: Could not open %s\n"), device);
829fcf3ce44SJohn Forte 		free(download_p);
830fcf3ce44SJohn Forte 		return (1);
831fcf3ce44SJohn Forte 	}
832fcf3ce44SJohn Forte 	if (strstr(device, fc_trans)) {
833fcf3ce44SJohn Forte 		download_p->dl_fcode_len = fcode_size;
834fcf3ce44SJohn Forte 		file_id = download_p->dl_fcode[0x42] & 0xff;
835fcf3ce44SJohn Forte 		file_id |= (download_p->dl_fcode[0x43] << 8) & 0xff00;
836fcf3ce44SJohn Forte 		download_p->dl_chip_id = file_id;
837fcf3ce44SJohn Forte 		if (ioctl(dev_fd, IFPIO_FCODE_DOWNLOAD, download_p) < 0) {
838fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(21024,
839fcf3ce44SJohn Forte 		    "Error: Driver interface IFPIO_FCODE_DOWNLOAD failed\n"));
840fcf3ce44SJohn Forte 			free(download_p);
841fcf3ce44SJohn Forte 			(void) close(dev_fd);
842fcf3ce44SJohn Forte 			return (1);
843fcf3ce44SJohn Forte 		}
844fcf3ce44SJohn Forte 		free(download_p);
845fcf3ce44SJohn Forte 	} else if (strstr(device, fp_trans)) {
846fcf3ce44SJohn Forte 		fcio.fcio_cmd = FCIO_DOWNLOAD_FCODE;
847fcf3ce44SJohn Forte 		/* Information read operation */
848fcf3ce44SJohn Forte 		fcio.fcio_xfer = FCIO_XFER_WRITE;
849fcf3ce44SJohn Forte 		fcio.fcio_ibuf = (caddr_t)bin;
850fcf3ce44SJohn Forte 		fcio.fcio_ilen = fcode_size;
851fcf3ce44SJohn Forte 
852fcf3ce44SJohn Forte 		if (ioctl(dev_fd, FCIO_CMD, &fcio) != 0) {
853fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(21036,
854fcf3ce44SJohn Forte 		    "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n"));
855fcf3ce44SJohn Forte 			free(download_p);
856fcf3ce44SJohn Forte 			(void) close(dev_fd);
857fcf3ce44SJohn Forte 			return (1);
858fcf3ce44SJohn Forte 		}
859fcf3ce44SJohn Forte 		free(bin);
860fcf3ce44SJohn Forte 	}
861fcf3ce44SJohn Forte 	(void) close(dev_fd);
862fcf3ce44SJohn Forte 	return (0);
863fcf3ce44SJohn Forte }
864fcf3ce44SJohn Forte 
865fcf3ce44SJohn Forte /*
866fcf3ce44SJohn Forte  * Issue warning strings and loop for Yes/No user interaction
867fcf3ce44SJohn Forte  *    err# 0 -- we're ok, warn for pending FCode load
868c1911baeSReed  *	   1 -- not in single user mode
869c1911baeSReed  *	   2 -- can't get chip_id
870c1911baeSReed  *	   3 -- card and file do not have same type (2100/2200)
871fcf3ce44SJohn Forte  */
872fcf3ce44SJohn Forte static int
q_warn(int errnum)873fcf3ce44SJohn Forte q_warn(int errnum)
874fcf3ce44SJohn Forte {
875fcf3ce44SJohn Forte 	char input[1024];
876fcf3ce44SJohn Forte 	input[0] = '\0';
877fcf3ce44SJohn Forte 
878fcf3ce44SJohn Forte 	if (errnum == 1) {
879fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21025,
880fcf3ce44SJohn Forte 		    "\nWarning: System is not in single-user mode.\n"));
881fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21026,
882fcf3ce44SJohn Forte 	"Loading FCode will reset the adapter and terminate I/O activity\n"));
883fcf3ce44SJohn Forte 	} else {
884fcf3ce44SJohn Forte 		if (errnum == 2) {
885fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(21027,
886fcf3ce44SJohn Forte 			"  Warning: FCode is missing or existing FCode has"
887fcf3ce44SJohn Forte 			" unrecognized version.\n"));
888fcf3ce44SJohn Forte 			return (1);
889fcf3ce44SJohn Forte 		} else if (errnum == 3) {
890fcf3ce44SJohn Forte 			(void) fprintf(stderr, MSGSTR(21028,
891fcf3ce44SJohn Forte 			"  Warning: New FCode file version does not match this"
892fcf3ce44SJohn Forte 			" board type. Skipping...\n"));
893fcf3ce44SJohn Forte 			return (1);
894fcf3ce44SJohn Forte 		}
895fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21029,
896fcf3ce44SJohn Forte 		"\nWARNING!! This program will update the FCode in this"
897fcf3ce44SJohn Forte 		" FC100/PCI, ISP2200/PCI, ISP23xx/PCI "
898fcf3ce44SJohn Forte 		" and Emulex devices.\n"));
899fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21030,
900fcf3ce44SJohn Forte 		"This may take a few (5) minutes. Please be patient.\n"));
901fcf3ce44SJohn Forte 	}
902fcf3ce44SJohn Forte 
903fcf3ce44SJohn Forte loop1:
904fcf3ce44SJohn Forte 	(void) fprintf(stderr, MSGSTR(21031,
905fcf3ce44SJohn Forte 		"Do you wish to continue ? (y/n) "));
906fcf3ce44SJohn Forte 
907fcf3ce44SJohn Forte 	(void) gets(input);
908fcf3ce44SJohn Forte 
909fcf3ce44SJohn Forte 	if ((strcmp(input, MSGSTR(21032, "y")) == 0) ||
910fcf3ce44SJohn Forte 			(strcmp(input, MSGSTR(40, "yes")) == 0)) {
911fcf3ce44SJohn Forte 		return (0);
912fcf3ce44SJohn Forte 	} else if ((strcmp(input, MSGSTR(21033, "n")) == 0) ||
913fcf3ce44SJohn Forte 			(strcmp(input, MSGSTR(45, "no")) == 0)) {
914fcf3ce44SJohn Forte 		(void) fprintf(stderr,
915fcf3ce44SJohn Forte 		    MSGSTR(21034, "Not Downloading FCode\n"));
916fcf3ce44SJohn Forte 		return (1);
917fcf3ce44SJohn Forte 	} else {
918fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21035, "Invalid input\n"));
919fcf3ce44SJohn Forte 		goto loop1;
920fcf3ce44SJohn Forte 	}
921fcf3ce44SJohn Forte }
922fcf3ce44SJohn Forte 
923fcf3ce44SJohn Forte /*
924c1911baeSReed  * Name	   : memstrstr
925fcf3ce44SJohn Forte  * Input   : pointer to buf1, pointer to buf2, size of buf1, size of buf2
926fcf3ce44SJohn Forte  * Returns :
927c1911baeSReed  *	Offset of the start of contents-of-buf2 in buf1 if it is found
928c1911baeSReed  *	-1 if buf1 does not contain contents of buf2
929fcf3ce44SJohn Forte  * Synopsis:
930fcf3ce44SJohn Forte  * This function works similar to strstr(). The difference is that null
931fcf3ce44SJohn Forte  * characters in the buffer are treated like any other character. So, buf1
932fcf3ce44SJohn Forte  * and buf2 can have embedded null characters in them.
933fcf3ce44SJohn Forte  */
934fcf3ce44SJohn Forte static int
memstrstr(char * s1,char * s2,int size1,int size2)935fcf3ce44SJohn Forte memstrstr(char *s1, char *s2, int size1, int size2)
936fcf3ce44SJohn Forte {
937fcf3ce44SJohn Forte 	int count1, count2;
938fcf3ce44SJohn Forte 	char *s1_ptr, *s2_ptr;
939fcf3ce44SJohn Forte 
940fcf3ce44SJohn Forte 	count1 = size1; count2 = size2;
941fcf3ce44SJohn Forte 	s1_ptr = s1; s2_ptr = s2;
942fcf3ce44SJohn Forte 
943fcf3ce44SJohn Forte 	if ((size2 == 0)||(size1 == 0))
944fcf3ce44SJohn Forte 		return (-1);
945fcf3ce44SJohn Forte 
946fcf3ce44SJohn Forte 	for (count1 = 0; count1 < (size1 - size2 + 1); count1++) {
947fcf3ce44SJohn Forte 		if (*s1_ptr++ == *s2_ptr++) {
948fcf3ce44SJohn Forte 			if (--count2 == 0) {
949fcf3ce44SJohn Forte 				return (count1 - size2 + 1);
950fcf3ce44SJohn Forte 			}
951fcf3ce44SJohn Forte 			continue;
952fcf3ce44SJohn Forte 		}
953fcf3ce44SJohn Forte 		count2 = size2;
954fcf3ce44SJohn Forte 		s2_ptr = s2;
955fcf3ce44SJohn Forte 	}
956fcf3ce44SJohn Forte 
957fcf3ce44SJohn Forte 	return (-1);
958fcf3ce44SJohn Forte }
959fcf3ce44SJohn Forte 
960fcf3ce44SJohn Forte /*
961fcf3ce44SJohn Forte  * generic fcode load file routine.  given a file descriptor to a fcode file
962fcf3ce44SJohn Forte  * this routine will issue the FCIO_DOWNLOAD_FCODE ioctl to the given
963fcf3ce44SJohn Forte  * device.  Any ioctl errors will be returned in fcio_errno
964fcf3ce44SJohn Forte  *
965fcf3ce44SJohn Forte  * Arguments:
966fcf3ce44SJohn Forte  *	fcode_fd    file descriptor to a fcode file
967fcf3ce44SJohn Forte  *	device	    path to the device we will be downloading the fcode onto
968fcf3ce44SJohn Forte  *	fcio_errno  pointer to an int that will be used to return any errors
969fcf3ce44SJohn Forte  *			back to the caller
970fcf3ce44SJohn Forte  * Retrurn Values:
971fcf3ce44SJohn Forte  *	0	    successful download
972fcf3ce44SJohn Forte  *	>0	    otherwise
973fcf3ce44SJohn Forte  */
974fcf3ce44SJohn Forte static int
fcode_load_file(int fcode_fd,char * device,int * fcio_errno)975fcf3ce44SJohn Forte fcode_load_file(int fcode_fd, char *device, int *fcio_errno)
976fcf3ce44SJohn Forte {
977fcf3ce44SJohn Forte 
978fcf3ce44SJohn Forte 	fcio_t		fcio;
979fcf3ce44SJohn Forte 	static int	dev_fd, fcode_size;
980fcf3ce44SJohn Forte 	uchar_t		*bin;
981fcf3ce44SJohn Forte 	struct stat	stat;
982fcf3ce44SJohn Forte 
983fcf3ce44SJohn Forte 	if (device == NULL || fcio_errno == NULL) {
984fcf3ce44SJohn Forte 		return (FCODE_LOAD_FAILURE);
985fcf3ce44SJohn Forte 	}
986fcf3ce44SJohn Forte 
987fcf3ce44SJohn Forte 	*fcio_errno = 0;
988fcf3ce44SJohn Forte 	if (lseek(fcode_fd, 0, SEEK_SET) == -1) {
989fcf3ce44SJohn Forte 		perror(MSGSTR(21022, "seek"));
990fcf3ce44SJohn Forte 		return (FCODE_LOAD_FAILURE);
991fcf3ce44SJohn Forte 	}
992fcf3ce44SJohn Forte 
993fcf3ce44SJohn Forte 	if (fstat(fcode_fd, &stat) == -1) {
994fcf3ce44SJohn Forte 		perror(MSGSTR(21023, "fstat"));
995fcf3ce44SJohn Forte 		return (FCODE_LOAD_FAILURE);
996fcf3ce44SJohn Forte 	}
997fcf3ce44SJohn Forte 
998fcf3ce44SJohn Forte 	fcode_size = stat.st_size;
999fcf3ce44SJohn Forte 
1000fcf3ce44SJohn Forte 	if ((bin = (uchar_t *)malloc(fcode_size)) == NULL) {
1001fcf3ce44SJohn Forte 		(void) fprintf(stderr,
1002fcf3ce44SJohn Forte 		    MSGSTR(21013, "Error: Memory allocation failed\n"));
1003fcf3ce44SJohn Forte 		return (FCODE_LOAD_FAILURE);
1004fcf3ce44SJohn Forte 	}
1005fcf3ce44SJohn Forte 
1006fcf3ce44SJohn Forte 	if (read(fcode_fd, bin, fcode_size)
1007fcf3ce44SJohn Forte 	    != fcode_size) {
1008fcf3ce44SJohn Forte 		perror(MSGSTR(21001, "read"));
1009fcf3ce44SJohn Forte 		free(bin);
1010fcf3ce44SJohn Forte 		return (FCODE_LOAD_FAILURE);
1011fcf3ce44SJohn Forte 	}
1012fcf3ce44SJohn Forte 
1013fcf3ce44SJohn Forte 	if ((dev_fd = open(device, O_RDWR|O_EXCL)) < 0) {
1014fcf3ce44SJohn Forte 		(void) fprintf(stderr,
1015fcf3ce44SJohn Forte 		    MSGSTR(21122, "Error: Could not open %s, failed "
1016fcf3ce44SJohn Forte 			    "with errno %d\n"), device, errno);
1017fcf3ce44SJohn Forte 		free(bin);
1018fcf3ce44SJohn Forte 		return (FCODE_LOAD_FAILURE);
1019fcf3ce44SJohn Forte 	}
1020fcf3ce44SJohn Forte 
1021fcf3ce44SJohn Forte 	fcio.fcio_cmd = FCIO_DOWNLOAD_FCODE;
1022fcf3ce44SJohn Forte 	fcio.fcio_xfer = FCIO_XFER_WRITE;
1023fcf3ce44SJohn Forte 	fcio.fcio_ibuf = (caddr_t)bin;
1024fcf3ce44SJohn Forte 	fcio.fcio_ilen = fcode_size;
1025fcf3ce44SJohn Forte 
1026fcf3ce44SJohn Forte 	if (ioctl(dev_fd, FCIO_CMD, &fcio) != 0) {
1027fcf3ce44SJohn Forte 		(void) close(dev_fd);
1028fcf3ce44SJohn Forte 		*fcio_errno = fcio.fcio_errno;
1029fcf3ce44SJohn Forte 		free(bin);
1030fcf3ce44SJohn Forte 		return (FCODE_IOCTL_FAILURE);
1031fcf3ce44SJohn Forte 	}
1032fcf3ce44SJohn Forte 
1033fcf3ce44SJohn Forte 	free(bin);
1034fcf3ce44SJohn Forte 	(void) close(dev_fd);
1035fcf3ce44SJohn Forte 	return (FCODE_SUCCESS);
1036fcf3ce44SJohn Forte }
1037fcf3ce44SJohn Forte 
1038fcf3ce44SJohn Forte /*
1039fcf3ce44SJohn Forte  * Searches for and updates the fcode for Emulex HBA cards
1040fcf3ce44SJohn Forte  * args: FCode file; if NULL only the current FCode
1041fcf3ce44SJohn Forte  * version is printed
1042fcf3ce44SJohn Forte  */
1043fcf3ce44SJohn Forte 
1044fcf3ce44SJohn Forte int
emulex_update(char * file)1045fcf3ce44SJohn Forte emulex_update(char *file)
1046fcf3ce44SJohn Forte {
1047fcf3ce44SJohn Forte 
1048c1911baeSReed 	int		fd, retval = 0;
1049c1911baeSReed 	int		devcnt = 0;
1050c1911baeSReed 	uint_t		state = 0, fflag = 0;
1051c1911baeSReed 	static uchar_t	bootpath[PATH_MAX];
1052c1911baeSReed 	int		fcode_fd = -1;
1053fcf3ce44SJohn Forte 	static struct	utmpx *utmpp = NULL;
1054c1911baeSReed 	di_node_t	root;
1055c1911baeSReed 	di_node_t	node, sib_node, count_node;
1056c1911baeSReed 	di_minor_t	minor_node;
1057c1911baeSReed 	char		phys_path[PATH_MAX], *path;
1058c1911baeSReed 	int		errnum = 0, fcio_errno = 0;
1059fcf3ce44SJohn Forte 	static uchar_t	prom_ver_data[MAXNAMELEN];
1060fcf3ce44SJohn Forte 	static char	ver_file[EMULEX_FCODE_VERSION_LENGTH];
1061fcf3ce44SJohn Forte 	void		(*sigint)();
1062fcf3ce44SJohn Forte 	int		prop_entries = -1;
1063c1911baeSReed 	int		*port_data = NULL;
1064fcf3ce44SJohn Forte 
1065fcf3ce44SJohn Forte 	if (file) {
1066fcf3ce44SJohn Forte 		/* set the fcode download flag */
1067fcf3ce44SJohn Forte 		fflag++;
1068fcf3ce44SJohn Forte 
1069fcf3ce44SJohn Forte 		/* check for a valid file */
1070fcf3ce44SJohn Forte 		if ((fcode_fd = open(file, O_RDONLY)) < 0) {
1071fcf3ce44SJohn Forte 			(void) fprintf(stderr,
1072fcf3ce44SJohn Forte 			    MSGSTR(21118, "Error: Could not open %s, failed "
1073fcf3ce44SJohn Forte 				    "with errno %d\n"), file, errno);
1074fcf3ce44SJohn Forte 			return (1);
1075fcf3ce44SJohn Forte 		}
1076fcf3ce44SJohn Forte 
1077fcf3ce44SJohn Forte 		/* check for single user mode */
1078fcf3ce44SJohn Forte 		while ((utmpp = getutxent()) != NULL) {
1079fcf3ce44SJohn Forte 			if (strstr(utmpp->ut_line, "run-level") &&
1080fcf3ce44SJohn Forte 				(strcmp(utmpp->ut_line, "run-level S") &&
1081fcf3ce44SJohn Forte 				strcmp(utmpp->ut_line, "run-level 1"))) {
1082fcf3ce44SJohn Forte 				if (q_warn(1)) {
1083fcf3ce44SJohn Forte 					(void) endutxent();
1084fcf3ce44SJohn Forte 					(void) close(fcode_fd);
1085fcf3ce44SJohn Forte 					return (1);
1086fcf3ce44SJohn Forte 				}
1087fcf3ce44SJohn Forte 				break;
1088fcf3ce44SJohn Forte 			}
1089fcf3ce44SJohn Forte 		}
1090fcf3ce44SJohn Forte 		(void) endutxent();
1091fcf3ce44SJohn Forte 
1092fcf3ce44SJohn Forte 		/* get bootpath */
1093fcf3ce44SJohn Forte 		if (!q_getbootdev((uchar_t *)&bootpath[0]) &&
1094fcf3ce44SJohn Forte 		    getenv("_LUX_D_DEBUG") != NULL) {
1095fcf3ce44SJohn Forte 			(void) fprintf(stdout, "  Bootpath: %s\n", bootpath);
1096fcf3ce44SJohn Forte 		}
1097fcf3ce44SJohn Forte 	}
1098fcf3ce44SJohn Forte 
1099fcf3ce44SJohn Forte 	/*
1100fcf3ce44SJohn Forte 	 * Download the Fcode to all the emulex cards found
1101fcf3ce44SJohn Forte 	 */
1102fcf3ce44SJohn Forte 
1103fcf3ce44SJohn Forte 	/* Create a snapshot of the kernel device tree */
1104fcf3ce44SJohn Forte 	if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
1105fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21114,
1106fcf3ce44SJohn Forte 		"Error: Could not get /devices path to "
1107fcf3ce44SJohn Forte 		"Emulex Devices.\n"));
1108fcf3ce44SJohn Forte 		retval++;
1109fcf3ce44SJohn Forte 	}
1110fcf3ce44SJohn Forte 
1111fcf3ce44SJohn Forte 	/* point to first node which matches emulex driver */
1112fcf3ce44SJohn Forte 	node = di_drv_first_node("emlxs", root);
1113fcf3ce44SJohn Forte 
1114fcf3ce44SJohn Forte 	if (node == DI_NODE_NIL) {
1115fcf3ce44SJohn Forte 		/*
1116fcf3ce44SJohn Forte 		 * Could not find any emulex cards
1117fcf3ce44SJohn Forte 		 */
1118fcf3ce44SJohn Forte 		(void) di_fini(root);
1119fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21115,
1120fcf3ce44SJohn Forte 		"\n  Found Path to %d Emulex Devices.\n"), devcnt);
1121fcf3ce44SJohn Forte 		retval++;
1122fcf3ce44SJohn Forte 	} else {
1123fcf3ce44SJohn Forte 		count_node = node;
1124fcf3ce44SJohn Forte 		while (count_node != DI_NODE_NIL) {
1125fcf3ce44SJohn Forte 			state = di_state(count_node);
1126fcf3ce44SJohn Forte 			if ((state & DI_DRIVER_DETACHED)
1127fcf3ce44SJohn Forte 			    != DI_DRIVER_DETACHED) {
1128c1911baeSReed 				sib_node = di_child_node(count_node);
1129c1911baeSReed 				while (sib_node != DI_NODE_NIL) {
1130c1911baeSReed 					state = di_state(sib_node);
1131c1911baeSReed 					if ((state & DI_DRIVER_DETACHED) !=
1132c1911baeSReed 					    DI_DRIVER_DETACHED) {
1133c1911baeSReed 						/* Found an attached node */
1134c1911baeSReed 						prop_entries =
1135c1911baeSReed 						    di_prop_lookup_ints(
1136c1911baeSReed 						    DDI_DEV_T_ANY, sib_node,
1137c1911baeSReed 						    "port", &port_data);
1138c1911baeSReed 						if (prop_entries != -1) {
1139c1911baeSReed 							devcnt++;
1140c1911baeSReed 							break;
1141c1911baeSReed 						}
1142c1911baeSReed 					}
1143c1911baeSReed 
1144c1911baeSReed 					sib_node = di_sibling_node(sib_node);
1145c1911baeSReed 				}
1146fcf3ce44SJohn Forte 			}
1147fcf3ce44SJohn Forte 			count_node = di_drv_next_node(count_node);
1148fcf3ce44SJohn Forte 		}
1149fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(21116,
1150fcf3ce44SJohn Forte 		"\n  Found Path to %d Emulex Devices.\n"), devcnt);
1151fcf3ce44SJohn Forte 	}
1152fcf3ce44SJohn Forte 
1153fcf3ce44SJohn Forte 
1154fcf3ce44SJohn Forte 	/*
1155fcf3ce44SJohn Forte 	 * Traverse device tree to find all emulex cards
1156fcf3ce44SJohn Forte 	 */
1157fcf3ce44SJohn Forte 	while (node != DI_NODE_NIL) {
1158fcf3ce44SJohn Forte 
1159fcf3ce44SJohn Forte 		state = di_state(node);
1160fcf3ce44SJohn Forte 		if ((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) {
1161fcf3ce44SJohn Forte 			node = di_drv_next_node(node);
1162fcf3ce44SJohn Forte 			continue;
1163fcf3ce44SJohn Forte 		}
1164fcf3ce44SJohn Forte 
1165fcf3ce44SJohn Forte 		sib_node = di_child_node(node);
1166fcf3ce44SJohn Forte 		while (sib_node != DI_NODE_NIL) {
1167fcf3ce44SJohn Forte 			state = di_state(sib_node);
1168fcf3ce44SJohn Forte 			if ((state & DI_DRIVER_DETACHED) !=
1169fcf3ce44SJohn Forte 			    DI_DRIVER_DETACHED) {
1170fcf3ce44SJohn Forte 
1171fcf3ce44SJohn Forte 				/* Found an attached node */
1172fcf3ce44SJohn Forte 				prop_entries = di_prop_lookup_ints(
1173fcf3ce44SJohn Forte 				    DDI_DEV_T_ANY, sib_node,
1174fcf3ce44SJohn Forte 				    "port", &port_data);
1175fcf3ce44SJohn Forte 				if (prop_entries != -1) {
1176fcf3ce44SJohn Forte 
1177fcf3ce44SJohn Forte 					/* Found a node with "port" property */
1178fcf3ce44SJohn Forte 					minor_node = di_minor_next(sib_node,
1179fcf3ce44SJohn Forte 					    DI_MINOR_NIL);
1180fcf3ce44SJohn Forte 					break;
1181fcf3ce44SJohn Forte 				}
1182fcf3ce44SJohn Forte 			}
1183fcf3ce44SJohn Forte 			sib_node = di_sibling_node(sib_node);
1184fcf3ce44SJohn Forte 		}
1185fcf3ce44SJohn Forte 
1186fcf3ce44SJohn Forte 		if (sib_node == DI_NODE_NIL) {
1187c1911baeSReed 			goto try_next;
1188fcf3ce44SJohn Forte 		}
1189c1911baeSReed 
1190fcf3ce44SJohn Forte 		path = di_devfs_path(sib_node);
1191fcf3ce44SJohn Forte 		(void) strcpy(phys_path, "/devices");
1192fcf3ce44SJohn Forte 		(void) strncat(phys_path, path, strlen(path));
1193fcf3ce44SJohn Forte 		di_devfs_path_free(path);
1194fcf3ce44SJohn Forte 
1195fcf3ce44SJohn Forte 		if (fflag && (strstr((char *)bootpath,
1196fcf3ce44SJohn Forte 		    (char *)phys_path) != NULL)) {
1197fcf3ce44SJohn Forte 			(void) fprintf(stderr,
1198fcf3ce44SJohn Forte 			    MSGSTR(21117, "Ignoring %s (bootpath)\n"),
1199fcf3ce44SJohn Forte 			    phys_path);
1200fcf3ce44SJohn Forte 			node = di_drv_next_node(node);
1201fcf3ce44SJohn Forte 			continue;
1202fcf3ce44SJohn Forte 		}
1203fcf3ce44SJohn Forte 
1204fcf3ce44SJohn Forte 		if (minor_node) {
1205fcf3ce44SJohn Forte 			(void) strncat(phys_path, ":", 1);
1206fcf3ce44SJohn Forte 			(void) strncat(phys_path,
1207fcf3ce44SJohn Forte 				di_minor_name(minor_node),
1208fcf3ce44SJohn Forte 				strlen(di_minor_name(minor_node)));
1209fcf3ce44SJohn Forte 		}
1210fcf3ce44SJohn Forte 
1211fcf3ce44SJohn Forte 		(void) fprintf(stdout,
1212fcf3ce44SJohn Forte 				MSGSTR(21107, "\n  Opening Device: %s\n"),
1213fcf3ce44SJohn Forte 				phys_path);
1214fcf3ce44SJohn Forte 
1215fcf3ce44SJohn Forte 		/* Check if the device is valid */
1216fcf3ce44SJohn Forte 		if ((fd = open(phys_path, O_RDWR)) < 0) {
1217fcf3ce44SJohn Forte 			(void) fprintf(stderr,
1218fcf3ce44SJohn Forte 			    MSGSTR(21121, "Error: Could not open %s, failed "
1219fcf3ce44SJohn Forte 				    "with errno %d\n"), phys_path, errno);
1220fcf3ce44SJohn Forte 			retval++;
1221fcf3ce44SJohn Forte 			node = di_drv_next_node(node);
1222fcf3ce44SJohn Forte 			continue;
1223fcf3ce44SJohn Forte 		}
1224fcf3ce44SJohn Forte 
1225fcf3ce44SJohn Forte 		(void) close(fd);
1226fcf3ce44SJohn Forte 
1227fcf3ce44SJohn Forte 		/*
1228fcf3ce44SJohn Forte 		 * Check FCode version present on the adapter
1229fcf3ce44SJohn Forte 		 * (at last boot)
1230fcf3ce44SJohn Forte 		 */
1231fcf3ce44SJohn Forte 		memset(prom_ver_data, 0, sizeof (prom_ver_data));
1232fcf3ce44SJohn Forte 		if (emulex_fcodeversion(node, (uchar_t *)&prom_ver_data[0])
1233fcf3ce44SJohn Forte 		    == 0) {
1234fcf3ce44SJohn Forte 			errnum = 0;
1235fcf3ce44SJohn Forte 			if (strlen((char *)prom_ver_data) == 0) {
1236fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(21108,
1237fcf3ce44SJohn Forte 	"  Detected FCode Version:\tNo version available for this FCode\n"));
1238fcf3ce44SJohn Forte 			} else {
1239fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(21109,
1240fcf3ce44SJohn Forte 				    "  Detected FCode Version:\t%s\n"),
1241fcf3ce44SJohn Forte 				    prom_ver_data);
1242fcf3ce44SJohn Forte 			}
1243fcf3ce44SJohn Forte 		} else {
1244fcf3ce44SJohn Forte 			errnum = 2; /* can't get prom properties */
1245fcf3ce44SJohn Forte 			retval++;
1246fcf3ce44SJohn Forte 		}
1247fcf3ce44SJohn Forte 
1248fcf3ce44SJohn Forte 		if (fflag) {
1249fcf3ce44SJohn Forte 
1250fcf3ce44SJohn Forte 			memset(ver_file, 0, sizeof (ver_file));
1251fcf3ce44SJohn Forte 			if (emulex_fcode_reader(fcode_fd, "fcode-version",
1252fcf3ce44SJohn Forte 				    ver_file, sizeof (ver_file)) == 0) {
1253fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(21110,
1254fcf3ce44SJohn Forte 					    "  New FCode Version:\t\t%s\n"),
1255fcf3ce44SJohn Forte 					    ver_file);
1256fcf3ce44SJohn Forte 			} else {
1257fcf3ce44SJohn Forte 				di_fini(root);
1258fcf3ce44SJohn Forte 				(void) close(fcode_fd);
1259fcf3ce44SJohn Forte 				return (1);
1260fcf3ce44SJohn Forte 			}
1261fcf3ce44SJohn Forte 
1262fcf3ce44SJohn Forte 			/*
1263fcf3ce44SJohn Forte 			 * Load the New FCode
1264fcf3ce44SJohn Forte 			 * Give warning if file doesn't appear to be correct
1265fcf3ce44SJohn Forte 			 */
1266fcf3ce44SJohn Forte 			if (!q_warn(errnum)) {
1267fcf3ce44SJohn Forte 				/* Disable user-interrupt Control-C */
1268fcf3ce44SJohn Forte 				sigint =
1269fcf3ce44SJohn Forte 				    (void (*)(int)) signal(SIGINT, SIG_IGN);
1270fcf3ce44SJohn Forte 				/* Load FCode */
1271fcf3ce44SJohn Forte 				(void) fprintf(stdout, MSGSTR(21111,
1272fcf3ce44SJohn Forte 					"  Loading FCode: %s\n"), file);
1273fcf3ce44SJohn Forte 				if (fcode_load_file(fcode_fd, phys_path,
1274fcf3ce44SJohn Forte 					    &fcio_errno) == FCODE_SUCCESS) {
1275fcf3ce44SJohn Forte 					(void) fprintf(stdout, MSGSTR(21112,
1276fcf3ce44SJohn Forte 					"  Successful FCode download: %s\n"),
1277fcf3ce44SJohn Forte 					phys_path);
1278fcf3ce44SJohn Forte 				} else {
1279fcf3ce44SJohn Forte 					handle_emulex_error(fcio_errno,
1280fcf3ce44SJohn Forte 					    phys_path);
1281fcf3ce44SJohn Forte 					retval++;
1282fcf3ce44SJohn Forte 				}
1283fcf3ce44SJohn Forte 
1284fcf3ce44SJohn Forte 				/* Restore SIGINT (user interrupt) setting */
1285fcf3ce44SJohn Forte 				(void) signal(SIGINT, sigint);
1286fcf3ce44SJohn Forte 			}
1287fcf3ce44SJohn Forte 		}
1288fcf3ce44SJohn Forte 
1289c1911baeSReed 	try_next:
1290fcf3ce44SJohn Forte 		node = di_drv_next_node(node);
1291fcf3ce44SJohn Forte 	}
1292fcf3ce44SJohn Forte 
1293fcf3ce44SJohn Forte 	di_fini(root);
1294fcf3ce44SJohn Forte 	(void) fprintf(stdout, "  ");
1295fcf3ce44SJohn Forte 	(void) fprintf(stdout, MSGSTR(125, "Complete\n"));
1296fcf3ce44SJohn Forte 	if (fcode_fd != -1)
1297fcf3ce44SJohn Forte 		(void) close(fcode_fd);
1298fcf3ce44SJohn Forte 	return (retval);
1299fcf3ce44SJohn Forte 
1300fcf3ce44SJohn Forte }
1301fcf3ce44SJohn Forte 
1302fcf3ce44SJohn Forte /*
1303fcf3ce44SJohn Forte  * Retrieve the version from the card.
1304fcf3ce44SJohn Forte  *    uses PROM properties
1305fcf3ce44SJohn Forte  */
1306fcf3ce44SJohn Forte static int
emulex_fcodeversion(di_node_t node,uchar_t * ver)1307fcf3ce44SJohn Forte emulex_fcodeversion(di_node_t node, uchar_t *ver) {
1308fcf3ce44SJohn Forte 	di_prom_prop_t	    promprop;
1309fcf3ce44SJohn Forte 	di_prom_handle_t    ph;
1310fcf3ce44SJohn Forte 	char		    *promname;
1311fcf3ce44SJohn Forte 	uchar_t		    *ver_data = NULL;
1312fcf3ce44SJohn Forte 	int		    size, found = 0;
1313fcf3ce44SJohn Forte 
1314fcf3ce44SJohn Forte 	/* check to make sure ver is not NULL */
1315fcf3ce44SJohn Forte 	if (ver == NULL) {
1316fcf3ce44SJohn Forte 		return (1);
1317fcf3ce44SJohn Forte 	}
1318fcf3ce44SJohn Forte 
1319fcf3ce44SJohn Forte 	if ((ph = di_prom_init()) == DI_PROM_HANDLE_NIL) {
1320fcf3ce44SJohn Forte 		return (1);
1321fcf3ce44SJohn Forte 	}
1322fcf3ce44SJohn Forte 
1323fcf3ce44SJohn Forte 	for (promprop = di_prom_prop_next(ph, node,
1324fcf3ce44SJohn Forte 		DI_PROM_PROP_NIL);
1325fcf3ce44SJohn Forte 		promprop != DI_PROM_PROP_NIL;
1326fcf3ce44SJohn Forte 		promprop = di_prom_prop_next(ph, node, promprop)) {
1327fcf3ce44SJohn Forte 		if (((promname = di_prom_prop_name(
1328fcf3ce44SJohn Forte 			promprop)) != NULL) &&
1329fcf3ce44SJohn Forte 			(strcmp(promname, "fcode-version") == 0)) {
1330fcf3ce44SJohn Forte 			size = di_prom_prop_data(promprop, &ver_data);
1331525fef19SToomas Soome 			(void) memset(ver, 0, size);
1332fcf3ce44SJohn Forte 			(void) memcpy(ver, ver_data, size);
1333fcf3ce44SJohn Forte 			found = 1;
1334fcf3ce44SJohn Forte 		}
1335fcf3ce44SJohn Forte 	}
1336fcf3ce44SJohn Forte 
1337fcf3ce44SJohn Forte 	if (found) {
1338fcf3ce44SJohn Forte 		return (0);
1339fcf3ce44SJohn Forte 	} else {
1340fcf3ce44SJohn Forte 		return (1);
1341fcf3ce44SJohn Forte 	}
1342fcf3ce44SJohn Forte }
1343fcf3ce44SJohn Forte 
1344fcf3ce44SJohn Forte /*
1345fcf3ce44SJohn Forte  * Retrieves information from the Emulex fcode
1346fcf3ce44SJohn Forte  *
1347fcf3ce44SJohn Forte  * Given a pattern, this routine will look for this pattern in the fcode
1348fcf3ce44SJohn Forte  * file and if found will return the pattern value
1349fcf3ce44SJohn Forte  *
1350fcf3ce44SJohn Forte  * possible patterns are manufacturer and fcode-version
1351fcf3ce44SJohn Forte  */
1352fcf3ce44SJohn Forte int
emulex_fcode_reader(int fcode_fd,char * pattern,char * pattern_value,uint32_t pattern_value_size)1353fcf3ce44SJohn Forte emulex_fcode_reader(int fcode_fd, char *pattern, char *pattern_value,
1354fcf3ce44SJohn Forte     uint32_t pattern_value_size) {
1355fcf3ce44SJohn Forte 	int32_t i = 0;
1356fcf3ce44SJohn Forte 	uint32_t n = 0;
1357fcf3ce44SJohn Forte 	uint32_t b = 0;
1358fcf3ce44SJohn Forte 	char byte1;
1359fcf3ce44SJohn Forte 	char byte2;
1360fcf3ce44SJohn Forte 	char byte3;
1361fcf3ce44SJohn Forte 	char byte4;
1362fcf3ce44SJohn Forte 	char buffer1[EMULEX_READ_BUFFER_SIZE];
1363fcf3ce44SJohn Forte 	char buffer2[EMULEX_READ_BUFFER_SIZE];
1364fcf3ce44SJohn Forte 	uint32_t plen, image_size;
1365fcf3ce44SJohn Forte 	struct stat	stat;
1366fcf3ce44SJohn Forte 	uchar_t		*image;
1367fcf3ce44SJohn Forte 
1368fcf3ce44SJohn Forte 	/* Check the arguments */
1369fcf3ce44SJohn Forte 	if (!fcode_fd || !pattern_value || pattern_value_size < 8) {
1370fcf3ce44SJohn Forte 		return (1);
1371fcf3ce44SJohn Forte 	}
1372fcf3ce44SJohn Forte 
1373fcf3ce44SJohn Forte 	if (fstat(fcode_fd, &stat) == -1) {
1374fcf3ce44SJohn Forte 		perror(MSGSTR(21023, "fstat"));
1375fcf3ce44SJohn Forte 		return (1);
1376fcf3ce44SJohn Forte 	}
1377fcf3ce44SJohn Forte 	image_size = stat.st_size;
1378fcf3ce44SJohn Forte 	if (image_size < 2) {
1379fcf3ce44SJohn Forte 		return (1);
1380fcf3ce44SJohn Forte 	}
1381fcf3ce44SJohn Forte 	if ((image = (uchar_t *)calloc(image_size, 1)) == NULL) {
1382fcf3ce44SJohn Forte 		(void) fprintf(stderr,
1383fcf3ce44SJohn Forte 		    MSGSTR(21013, "Error: Memory allocation failed\n"));
1384fcf3ce44SJohn Forte 		return (1);
1385fcf3ce44SJohn Forte 	}
1386fcf3ce44SJohn Forte 
1387fcf3ce44SJohn Forte 	/* Read the fcode image file */
1388fcf3ce44SJohn Forte 	lseek(fcode_fd, 0, SEEK_SET);
1389fcf3ce44SJohn Forte 	read(fcode_fd, image, image_size);
1390fcf3ce44SJohn Forte 
1391fcf3ce44SJohn Forte 	/* Initialize */
1392fcf3ce44SJohn Forte 	bzero(buffer1, sizeof (buffer1));
1393fcf3ce44SJohn Forte 	bzero(buffer2, sizeof (buffer2));
1394fcf3ce44SJohn Forte 	/* Default pattern_value string */
1395fcf3ce44SJohn Forte 	strcpy((char *)pattern_value, "<unknown>");
1396fcf3ce44SJohn Forte 	plen = strlen(pattern);
1397fcf3ce44SJohn Forte 	n = 0;
1398fcf3ce44SJohn Forte 	b = 0;
1399fcf3ce44SJohn Forte 	i = 0;
1400fcf3ce44SJohn Forte 
1401fcf3ce44SJohn Forte 	/* Search entire image for pattern string */
1402fcf3ce44SJohn Forte 	while (i <= (image_size - 2)) {
1403fcf3ce44SJohn Forte 		/* Read next two bytes */
1404fcf3ce44SJohn Forte 		byte1 = image[i++];
1405fcf3ce44SJohn Forte 		byte2 = image[i++];
1406fcf3ce44SJohn Forte 
1407fcf3ce44SJohn Forte 		/* Check second byte first due to endianness */
1408fcf3ce44SJohn Forte 
1409fcf3ce44SJohn Forte 		/* Save byte in circular buffer */
1410fcf3ce44SJohn Forte 		buffer1[b++] = byte2;
1411fcf3ce44SJohn Forte 		if (b == sizeof (buffer1)) {
1412fcf3ce44SJohn Forte 			b = 0;
1413fcf3ce44SJohn Forte 		}
1414fcf3ce44SJohn Forte 
1415fcf3ce44SJohn Forte 		/* Check byte for pattern match */
1416fcf3ce44SJohn Forte 		if (pattern[n++] != byte2) {
1417fcf3ce44SJohn Forte 			/* If no match, then reset pattern */
1418fcf3ce44SJohn Forte 			n = 0;
1419fcf3ce44SJohn Forte 		} else {
1420fcf3ce44SJohn Forte 			/*
1421fcf3ce44SJohn Forte 			 * If complete pattern has been matched then
1422fcf3ce44SJohn Forte 			 * exit loop
1423fcf3ce44SJohn Forte 			 */
1424fcf3ce44SJohn Forte 			if (n == plen) {
1425fcf3ce44SJohn Forte 				goto found;
1426fcf3ce44SJohn Forte 			}
1427fcf3ce44SJohn Forte 		}
1428fcf3ce44SJohn Forte 
1429fcf3ce44SJohn Forte 
1430fcf3ce44SJohn Forte 		/* Check first byte second due to endianness */
1431fcf3ce44SJohn Forte 		/* Save byte in circular buffer */
1432fcf3ce44SJohn Forte 		buffer1[b++] = byte1;
1433fcf3ce44SJohn Forte 		if (b == sizeof (buffer1)) {
1434fcf3ce44SJohn Forte 			b = 0;
1435fcf3ce44SJohn Forte 		}
1436fcf3ce44SJohn Forte 		/* Check byte for pattern match */
1437fcf3ce44SJohn Forte 		if (pattern[n++] != byte1) {
1438fcf3ce44SJohn Forte 			/* If no match, then reset pattern */
1439fcf3ce44SJohn Forte 			n = 0;
1440fcf3ce44SJohn Forte 		} else {
1441fcf3ce44SJohn Forte 			/*
1442fcf3ce44SJohn Forte 			 * If complete pattern has been matched
1443fcf3ce44SJohn Forte 			 * then exit loop
1444fcf3ce44SJohn Forte 			 */
1445fcf3ce44SJohn Forte 			if (n == plen) {
1446fcf3ce44SJohn Forte 				goto found;
1447fcf3ce44SJohn Forte 			}
1448fcf3ce44SJohn Forte 		}
1449fcf3ce44SJohn Forte 	}
1450fcf3ce44SJohn Forte 
1451fcf3ce44SJohn Forte 	/* Not found.  Try again with different endianess */
1452fcf3ce44SJohn Forte 
1453fcf3ce44SJohn Forte 	/* Initialize */
1454fcf3ce44SJohn Forte 	bzero(buffer1, sizeof (buffer1));
1455fcf3ce44SJohn Forte 	bzero(buffer2, sizeof (buffer2));
1456fcf3ce44SJohn Forte 	n = 0;
1457fcf3ce44SJohn Forte 	b = 0;
1458fcf3ce44SJohn Forte 	i = 0;
1459fcf3ce44SJohn Forte 
1460fcf3ce44SJohn Forte 	/* Search entire 32bit endian image for pattern string */
1461fcf3ce44SJohn Forte 	while (i <= (image_size - 4)) {
1462fcf3ce44SJohn Forte 		/* Read next four bytes */
1463fcf3ce44SJohn Forte 		byte1 = image[i++];
1464fcf3ce44SJohn Forte 		byte2 = image[i++];
1465fcf3ce44SJohn Forte 		byte3 = image[i++];
1466fcf3ce44SJohn Forte 		byte4 = image[i++];
1467fcf3ce44SJohn Forte 
1468fcf3ce44SJohn Forte 		/* Save byte in circular buffer */
1469fcf3ce44SJohn Forte 		buffer1[b++] = byte4;
1470fcf3ce44SJohn Forte 		if (b == sizeof (buffer1)) {
1471fcf3ce44SJohn Forte 			b = 0;
1472fcf3ce44SJohn Forte 		}
1473fcf3ce44SJohn Forte 
1474fcf3ce44SJohn Forte 		/* Check byte for pattern match */
1475fcf3ce44SJohn Forte 		if (pattern[n++] != byte4) {
1476fcf3ce44SJohn Forte 			/* If no match, then reset pattern */
1477fcf3ce44SJohn Forte 			n = 0;
1478fcf3ce44SJohn Forte 		} else {
1479fcf3ce44SJohn Forte 			/*
1480fcf3ce44SJohn Forte 			 * If complete pattern has been matched then exit loop
1481fcf3ce44SJohn Forte 			 */
1482fcf3ce44SJohn Forte 			if (n == plen) {
1483fcf3ce44SJohn Forte 				goto found;
1484fcf3ce44SJohn Forte 			}
1485fcf3ce44SJohn Forte 		}
1486fcf3ce44SJohn Forte 
1487fcf3ce44SJohn Forte 		/* Save byte in circular buffer */
1488fcf3ce44SJohn Forte 		buffer1[b++] = byte3;
1489fcf3ce44SJohn Forte 		if (b == sizeof (buffer1)) {
1490fcf3ce44SJohn Forte 			b = 0;
1491fcf3ce44SJohn Forte 		}
1492fcf3ce44SJohn Forte 
1493fcf3ce44SJohn Forte 		/* Check byte for pattern match */
1494fcf3ce44SJohn Forte 		if (pattern[n++] != byte3) {
1495fcf3ce44SJohn Forte 			/* If no match, then reset pattern */
1496fcf3ce44SJohn Forte 			n = 0;
1497fcf3ce44SJohn Forte 		} else {
1498fcf3ce44SJohn Forte 			/*
1499fcf3ce44SJohn Forte 			 * If complete pattern has been matched then exit loop
1500fcf3ce44SJohn Forte 			 */
1501fcf3ce44SJohn Forte 			if (n == plen) {
1502fcf3ce44SJohn Forte 				goto found;
1503fcf3ce44SJohn Forte 			}
1504fcf3ce44SJohn Forte 		}
1505fcf3ce44SJohn Forte 
1506fcf3ce44SJohn Forte 		/* Save byte in circular buffer */
1507fcf3ce44SJohn Forte 		buffer1[b++] = byte2;
1508fcf3ce44SJohn Forte 		if (b == sizeof (buffer1)) {
1509fcf3ce44SJohn Forte 			b = 0;
1510fcf3ce44SJohn Forte 		}
1511fcf3ce44SJohn Forte 
1512fcf3ce44SJohn Forte 		/* Check byte for pattern match */
1513fcf3ce44SJohn Forte 		if (pattern[n++] != byte2) {
1514fcf3ce44SJohn Forte 			/* If no match, then reset pattern */
1515fcf3ce44SJohn Forte 			n = 0;
1516fcf3ce44SJohn Forte 		} else {
1517fcf3ce44SJohn Forte 			/*
1518fcf3ce44SJohn Forte 			 * If complete pattern has been matched then exit loop
1519fcf3ce44SJohn Forte 			 */
1520fcf3ce44SJohn Forte 			if (n == plen) {
1521fcf3ce44SJohn Forte 				goto found;
1522fcf3ce44SJohn Forte 			}
1523fcf3ce44SJohn Forte 		}
1524fcf3ce44SJohn Forte 
1525fcf3ce44SJohn Forte 		/* Save byte in circular buffer */
1526fcf3ce44SJohn Forte 		buffer1[b++] = byte1;
1527fcf3ce44SJohn Forte 		if (b == sizeof (buffer1)) {
1528fcf3ce44SJohn Forte 			b = 0;
1529fcf3ce44SJohn Forte 		}
1530fcf3ce44SJohn Forte 
1531fcf3ce44SJohn Forte 		/* Check byte for pattern match */
1532fcf3ce44SJohn Forte 		if (pattern[n++] != byte1) {
1533fcf3ce44SJohn Forte 			/* If no match, then reset pattern */
1534fcf3ce44SJohn Forte 			n = 0;
1535fcf3ce44SJohn Forte 		} else {
1536fcf3ce44SJohn Forte 			/*
1537fcf3ce44SJohn Forte 			 * If complete pattern has been matched then exit loop
1538fcf3ce44SJohn Forte 			 */
1539fcf3ce44SJohn Forte 			if (n == plen) {
1540fcf3ce44SJohn Forte 				goto found;
1541fcf3ce44SJohn Forte 			}
1542fcf3ce44SJohn Forte 		}
1543fcf3ce44SJohn Forte 	}
1544fcf3ce44SJohn Forte 
1545fcf3ce44SJohn Forte 	free(image);
1546fcf3ce44SJohn Forte 	return (1);
1547fcf3ce44SJohn Forte 
1548fcf3ce44SJohn Forte found:
1549fcf3ce44SJohn Forte 	free(image);
1550fcf3ce44SJohn Forte 
1551fcf3ce44SJohn Forte 	/* Align buffer and eliminate non-printable characters */
1552fcf3ce44SJohn Forte 	for (i = 0; i < (sizeof (buffer1)-plen); i++) {
1553fcf3ce44SJohn Forte 		byte1 = buffer1[b++];
1554fcf3ce44SJohn Forte 		if (b == sizeof (buffer1)) {
1555fcf3ce44SJohn Forte 			b = 0;
1556fcf3ce44SJohn Forte 		}
1557fcf3ce44SJohn Forte 		/* Zero any non-printable characters */
1558fcf3ce44SJohn Forte 		if (byte1 >= 33 && byte1 <= 126) {
1559fcf3ce44SJohn Forte 			buffer2[i] = byte1;
1560fcf3ce44SJohn Forte 		} else {
1561fcf3ce44SJohn Forte 			buffer2[i] = 0;
1562fcf3ce44SJohn Forte 		}
1563fcf3ce44SJohn Forte 	}
1564fcf3ce44SJohn Forte 
1565fcf3ce44SJohn Forte 	/*
1566fcf3ce44SJohn Forte 	 *  Scan backwards for first non-zero string. This will be the
1567fcf3ce44SJohn Forte 	 *  version string
1568fcf3ce44SJohn Forte 	 */
1569fcf3ce44SJohn Forte 	for (i = sizeof (buffer1)-plen-1; i >= 0; i--) {
1570fcf3ce44SJohn Forte 		if (buffer2[i] != 0) {
1571fcf3ce44SJohn Forte 			for (; i >= 0; i--) {
1572fcf3ce44SJohn Forte 				if (buffer2[i] == 0) {
1573fcf3ce44SJohn Forte 					i++;
1574fcf3ce44SJohn Forte 					strncpy((char *)pattern_value,
1575fcf3ce44SJohn Forte 					    &buffer2[i], pattern_value_size);
1576fcf3ce44SJohn Forte 					break;
1577fcf3ce44SJohn Forte 				}
1578fcf3ce44SJohn Forte 			}
1579fcf3ce44SJohn Forte 			break;
1580fcf3ce44SJohn Forte 		}
1581fcf3ce44SJohn Forte 	}
1582fcf3ce44SJohn Forte 	return (0);
1583fcf3ce44SJohn Forte }
1584fcf3ce44SJohn Forte 
1585fcf3ce44SJohn Forte /*
1586fcf3ce44SJohn Forte  * error handling routine to handle emulex error conditions
1587fcf3ce44SJohn Forte  */
1588fcf3ce44SJohn Forte static void
handle_emulex_error(int fcio_errno,char * phys_path)1589fcf3ce44SJohn Forte handle_emulex_error(int fcio_errno, char *phys_path) {
1590fcf3ce44SJohn Forte 	if (fcio_errno == EMLX_IMAGE_BAD) {
1591fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(21119,
1592fcf3ce44SJohn Forte 			    "Error: Fcode download failed.  "
1593fcf3ce44SJohn Forte 			    "Bad fcode image.\n"));
1594fcf3ce44SJohn Forte 	} else if (fcio_errno == EMLX_IMAGE_INCOMPATIBLE) {
1595fcf3ce44SJohn Forte 		fprintf(stderr, MSGSTR(21120,
1596fcf3ce44SJohn Forte 			    "Error: Fcode download failed.  Fcode is not "
1597fcf3ce44SJohn Forte 			    "compatible with card.\n"));
1598fcf3ce44SJohn Forte 	} else {
1599fcf3ce44SJohn Forte 		(void) fprintf(stderr, MSGSTR(21036,
1600fcf3ce44SJohn Forte 		    "Error: Driver interface FCIO_DOWNLOAD_FCODE failed\n"));
1601fcf3ce44SJohn Forte 		(void) fprintf(stderr,
1602fcf3ce44SJohn Forte 			MSGSTR(21113,
1603fcf3ce44SJohn Forte 				"Error: FCode download failed: %s\n"),
1604fcf3ce44SJohn Forte 				phys_path);
1605fcf3ce44SJohn Forte 	}
1606fcf3ce44SJohn Forte }
1607