4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
34 #include <sys/fibre-channel/fcio.h>
35 #include <sys/fibre-channel/impl/fc_error.h>
36 #include <sys/scsi/adapters/scsi_vhci.h>
38 #include "errorcodes.h"
41 /* The i18n catalog */
46 static int fileopen
= 0;
48 if (setlocale(LC_ALL
, "") == NULL
) {
49 (void) fprintf(stderr
,
50 "Cannot operate in the locale requested. "
51 "Continuing in the default C locale\n");
54 l_catd
= catopen("a5k_g_fc_i18n_cat", NL_CAT_LOCALE
);
55 if (l_catd
== (nl_catd
)-1) {
65 * Given an error number, this functions
66 * calls the get_errString() to print a
67 * corresponding error message to the stderr.
68 * get_errString() always returns an error
69 * message, even in case of undefined error number.
70 * So, there is no need to check for a NULL pointer
71 * while printing the error message to the stdout.
77 print_errString(int errnum
, char *devpath
)
82 errStr
= get_errString(errnum
);
84 if (devpath
== NULL
) {
85 (void) fprintf(stderr
,
88 (void) fprintf(stderr
,
89 "%s - %s.\n\n", errStr
, devpath
);
92 /* free the allocated memory for error string */
97 static void terminate() {
98 fprintf(stdout
, MSGSTR(2506, "Unsupported"));
99 fprintf(stdout
, "\n");
104 int adm_display_config(char **a
) {
110 void adm_download(char **a
, char *b
) {
115 void up_encl_name(char **a
, int b
) {
119 void adm_failover(char **argv
) {
120 int path_index
= 0, err
= 0, fd
;
121 char path_class
[MAXNAMELEN
];
122 char client_path
[MAXPATHLEN
];
123 char *path_phys
= NULL
, *trailingMinor
;
124 sv_switch_to_cntlr_iocdata_t iocsc
;
126 (void) memset(path_class
, 0, sizeof (path_class
));
127 (void) strcpy(path_class
, argv
[path_index
++]);
128 if ((strcmp(path_class
, "primary") != 0) &&
129 (strcmp(path_class
, "secondary") != 0)) {
130 (void) fprintf(stderr
,
131 MSGSTR(2300, "Incorrect pathclass\n"));
135 if ((fd
= open("/devices/scsi_vhci:devctl", O_RDWR
)) < 0) {
136 print_errString(L_OPEN_PATH_FAIL
, "/devices/scsi_vhci:devctl");
140 iocsc
.client
= client_path
;
141 iocsc
.class = path_class
;
143 while (argv
[path_index
] != NULL
) {
145 get_slash_devices_from_osDevName(argv
[path_index
++],
146 STANDARD_DEVNAME_HANDLING
);
147 if ((path_phys
== NULL
) ||
148 (strstr(path_phys
, "/devices/scsi_vhci") == NULL
)) {
149 (void) fprintf(stderr
,
150 MSGSTR(2301, "Incorrect pathname\n"));
155 strcpy(iocsc
.client
, path_phys
+ strlen("/devices"));
157 /* Now chop off the trailing ":xxx" portion if present */
158 if ((trailingMinor
= strrchr(iocsc
.client
, ':')) != NULL
) {
159 trailingMinor
[0] = '\0';
162 if (ioctl(fd
, SCSI_VHCI_SWITCH_TO_CNTLR
, &iocsc
) != 0) {
165 err
= L_SCSI_VHCI_ALREADY_ACTIVE
;
168 err
= L_INVALID_PATH
;
171 err
= L_SCSI_VHCI_NO_STANDBY
;
174 err
= L_SCSI_VHCI_FAILOVER_NOTSUP
;
177 err
= L_SCSI_VHCI_FAILOVER_BUSY
;
181 err
= L_SCSI_VHCI_ERROR
;
187 print_errString(err
, path_phys
);
196 int adm_inquiry(char **a
) {
207 void non_encl_probe() {
212 void adm_led(char **a
, int b
) {
217 void up_password(char **a
) {
222 int adm_reserve(char *path
) {
228 int adm_release(char *path
) {
234 int adm_start(char **a
) {
240 int adm_stop(char **a
) {
246 int adm_power_off(char **a
, int b
) {
252 adm_forcelip(char **argv
)
254 int path_index
= 0, fd
;
258 HBA_ADAPTERATTRIBUTES hbaAttrs
;
259 HBA_PORTATTRIBUTES portAttrs
;
260 HBA_FCPTARGETMAPPINGV2
*map
;
262 int count
, adapterIndex
, portIndex
, mapIndex
;
264 int matched
, ret
= 0, wwnCompare
= 0, ntries
;
265 char *physical
= NULL
, *slash_OSDeviceName
= NULL
;
267 if ((status
= loadLibrary())) {
268 /* loadLibrary print out error msg */
271 for (path_index
= 0; argv
[path_index
] != NULL
; path_index
++) {
273 if (is_wwn(argv
[path_index
])) {
274 (void) sscanf(argv
[path_index
], "%016llx", &wwn
);
276 } else if (!is_path(argv
[path_index
])) {
277 print_errString(L_INVALID_PATH
, argv
[path_index
]);
282 /* Convert the paths to phsyical paths */
283 physical
= get_slash_devices_from_osDevName(argv
[path_index
],
284 STANDARD_DEVNAME_HANDLING
);
286 print_errString(L_INVALID_PATH
, argv
[path_index
]);
292 count
= getNumberOfAdapters();
295 for (adapterIndex
= 0; adapterIndex
< count
; adapterIndex
++) {
296 status
= HBA_GetAdapterName(adapterIndex
, (char *)&name
);
297 if (status
!= HBA_STATUS_OK
) {
298 /* May have been DR'd */
301 handle
= HBA_OpenAdapter(name
);
303 /* May have been DR'd */
307 if (getAdapterAttrs(handle
, name
, &hbaAttrs
)) {
308 /* Should never happen */
309 HBA_CloseAdapter(handle
);
313 /* Loop over all HBA Ports */
314 for (portIndex
= 0; portIndex
< hbaAttrs
.NumberOfPorts
;
316 if (getAdapterPortAttrs(handle
, name
, portIndex
,
322 if (is_wwn(argv
[path_index
])) {
323 if (wwn
== wwnConversion(
324 portAttrs
.NodeWWN
.wwn
) ||
325 wwn
== wwnConversion(
326 portAttrs
.PortWWN
.wwn
)) {
330 slash_OSDeviceName
= get_slash_devices_from_osDevName(
331 portAttrs
.OSDeviceName
, STANDARD_DEVNAME_HANDLING
);
332 if (!slash_OSDeviceName
) {
335 if (strncmp(physical
, slash_OSDeviceName
,
336 strlen(slash_OSDeviceName
) -
337 strlen(strrchr(slash_OSDeviceName
, ':')))
341 free(slash_OSDeviceName
);
346 if (!fetch_mappings(handle
, portAttrs
.PortWWN
, &map
)) {
348 * matchr_mapping checks the arg
349 * so we pass argv here.
351 mapIndex
= match_mappings(argv
[path_index
], map
);
361 if ((fd
= open(portAttrs
.OSDeviceName
,
362 O_RDONLY
| O_EXCL
)) == -1) {
363 print_errString(L_OPEN_PATH_FAIL
,
364 portAttrs
.OSDeviceName
);
368 fcio
.fcio_cmd
= FCIO_RESET_LINK
;
369 fcio
.fcio_xfer
= FCIO_XFER_WRITE
;
371 * Reset the local loop here (fcio_ibuf = 0).
372 * Reset a remote loop on the Fabric by
373 * passing its node wwn (fcio_len = sizeof(nwwn)
374 * and fcio_ibuf = (caddr_t)&nwwn) to the port driver.
376 (void) memset(&wwn
, 0, sizeof (wwn
));
377 fcio
.fcio_ilen
= sizeof (wwn
);
378 fcio
.fcio_ibuf
= (caddr_t
)&wwn
;
380 for (ntries
= 0; ntries
< RETRY_FCIO_IOCTL
; ntries
++) {
382 if (ioctl(fd
, FCIO_CMD
, &fcio
) != 0) {
384 * When port is offlined, qlc
385 * returns the FC_OFFLINE error and errno
387 * We do want to ignore this error,
388 * especially when an enclosure is
389 * removed from the loop.
391 if (fcio
.fcio_errno
== FC_OFFLINE
)
393 if ((errno
== EAGAIN
) &&
394 (ntries
+1 < RETRY_FCIO_IOCTL
)) {
395 /* wait WAIT_FCIO_IOCTL */
396 (void) usleep(WAIT_FCIO_IOCTL
);
399 I_DPRINTF("FCIO ioctl failed.\n"
400 "Error: %s. fc_error = %d (0x%x)\n",
401 strerror(errno
), fcio
.fcio_errno
,
404 print_errString(L_FCIO_FORCE_LIP_FAIL
,
405 portAttrs
.OSDeviceName
);
408 break; /* ioctl succeeds. */
412 if (ntries
== RETRY_FCIO_IOCTL
) {
413 print_errString(L_FCIO_FORCE_LIP_FAIL
,
414 portAttrs
.OSDeviceName
);
419 break; /* for HBA port for loop */
421 if (matched
) /* HBA adapter for loop */
426 print_errString(L_INVALID_PATH
, argv
[path_index
]);
435 void adm_bypass_enable(char **argv
, int bypass_flag
) {
440 int adm_port_offline_online(char **a
, int b
) {
446 void display_link_status(char **a
) {
451 void dump_map(char **argv
) {
456 int adm_display_port(int a
) {
462 int adm_port_loopback(char *a
, int b
) {
468 int hotplug_e(int todo
, char **argv
, int verbose_flag
, int force_flag
) {
475 setboot(unsigned int yes
, unsigned int verbose
, char *fname
)
482 int hotplug(int todo
, char **argv
, int verbose_flag
, int force_flag
) {
488 int adm_check_file(char **argv
, int flag
) {
494 int sysdump(int verbose
) {
500 int fcal_update(unsigned int verbose
, char *file
) {
506 int q_qlgc_update(unsigned int verbose
, char *file
) {
512 int emulex_update(char *file
) {
518 int emulex_fcode_reader(int fcode_fd
, char *pattern
, char *pattern_value
,
519 uint32_t pattern_value_size
) {
525 void dump(char **argv
) {
530 int h_insertSena_fcdev() {