1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM *
4*7836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM *
8*7836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM * and limitations under the License.
12*7836SJohn.Forte@Sun.COM *
13*7836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM *
19*7836SJohn.Forte@Sun.COM * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23*7836SJohn.Forte@Sun.COM * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM */
25*7836SJohn.Forte@Sun.COM
26*7836SJohn.Forte@Sun.COM
27*7836SJohn.Forte@Sun.COM /*LINTLIBRARY*/
28*7836SJohn.Forte@Sun.COM
29*7836SJohn.Forte@Sun.COM
30*7836SJohn.Forte@Sun.COM /*
31*7836SJohn.Forte@Sun.COM * This module is part of the photon library
32*7836SJohn.Forte@Sun.COM */
33*7836SJohn.Forte@Sun.COM
34*7836SJohn.Forte@Sun.COM /*
35*7836SJohn.Forte@Sun.COM * I18N message number ranges
36*7836SJohn.Forte@Sun.COM * This file: 8500 - 8999
37*7836SJohn.Forte@Sun.COM * Shared common messages: 1 - 1999
38*7836SJohn.Forte@Sun.COM */
39*7836SJohn.Forte@Sun.COM
40*7836SJohn.Forte@Sun.COM /* #define _POSIX_SOURCE 1 */
41*7836SJohn.Forte@Sun.COM
42*7836SJohn.Forte@Sun.COM /* Includes */
43*7836SJohn.Forte@Sun.COM #include <stdlib.h>
44*7836SJohn.Forte@Sun.COM #include <stdio.h>
45*7836SJohn.Forte@Sun.COM #include <sys/file.h>
46*7836SJohn.Forte@Sun.COM #include <sys/types.h>
47*7836SJohn.Forte@Sun.COM #include <sys/stat.h>
48*7836SJohn.Forte@Sun.COM #include <sys/param.h>
49*7836SJohn.Forte@Sun.COM #include <fcntl.h>
50*7836SJohn.Forte@Sun.COM #include <unistd.h>
51*7836SJohn.Forte@Sun.COM #include <errno.h>
52*7836SJohn.Forte@Sun.COM #include <string.h>
53*7836SJohn.Forte@Sun.COM #include <time.h>
54*7836SJohn.Forte@Sun.COM #include <sys/scsi/scsi.h>
55*7836SJohn.Forte@Sun.COM #include <sys/vtoc.h>
56*7836SJohn.Forte@Sun.COM #include <nl_types.h>
57*7836SJohn.Forte@Sun.COM #include <strings.h>
58*7836SJohn.Forte@Sun.COM #include <sys/ddi.h> /* for max */
59*7836SJohn.Forte@Sun.COM #include <l_common.h>
60*7836SJohn.Forte@Sun.COM #include <stgcom.h>
61*7836SJohn.Forte@Sun.COM #include <l_error.h>
62*7836SJohn.Forte@Sun.COM #include <rom.h>
63*7836SJohn.Forte@Sun.COM #include <a_state.h>
64*7836SJohn.Forte@Sun.COM #include <a5k.h>
65*7836SJohn.Forte@Sun.COM
66*7836SJohn.Forte@Sun.COM
67*7836SJohn.Forte@Sun.COM /* Global variables */
68*7836SJohn.Forte@Sun.COM extern uchar_t g_switch_to_alpa[];
69*7836SJohn.Forte@Sun.COM extern uchar_t g_sf_alpa_to_switch[];
70*7836SJohn.Forte@Sun.COM
71*7836SJohn.Forte@Sun.COM
72*7836SJohn.Forte@Sun.COM /*
73*7836SJohn.Forte@Sun.COM * This function checks if the passed char pointer has WWN_SIZE nulls (zeroes).
74*7836SJohn.Forte@Sun.COM *
75*7836SJohn.Forte@Sun.COM * This is only a convenience function.
76*7836SJohn.Forte@Sun.COM *
77*7836SJohn.Forte@Sun.COM * INPUT:
78*7836SJohn.Forte@Sun.COM * wwn_ptr - pointer to a character string of length WWN_SIZE
79*7836SJohn.Forte@Sun.COM * It is expected to be holding the WWN
80*7836SJohn.Forte@Sun.COM * Ex: A WWN like 508002000000ddc1 is expected to be stored as
81*7836SJohn.Forte@Sun.COM * the following 8 bytes -
82*7836SJohn.Forte@Sun.COM * 0x50, 0x80, 0x00, 0x20, ... etc
83*7836SJohn.Forte@Sun.COM *
84*7836SJohn.Forte@Sun.COM * RETURNS:
85*7836SJohn.Forte@Sun.COM * 0 - if there is atleast one of WWN_SIZE bytes is != '\0'
86*7836SJohn.Forte@Sun.COM * non-zero - if all WWN_SIZE bytes are '\0'
87*7836SJohn.Forte@Sun.COM */
88*7836SJohn.Forte@Sun.COM int
is_null_wwn(uchar_t * wwn_ptr)89*7836SJohn.Forte@Sun.COM is_null_wwn(uchar_t *wwn_ptr)
90*7836SJohn.Forte@Sun.COM {
91*7836SJohn.Forte@Sun.COM int i;
92*7836SJohn.Forte@Sun.COM
93*7836SJohn.Forte@Sun.COM for (i = 0; i < WWN_SIZE; i++) {
94*7836SJohn.Forte@Sun.COM if (wwn_ptr[i] != '\0' || wwn_ptr[i] != '0')
95*7836SJohn.Forte@Sun.COM return (0);
96*7836SJohn.Forte@Sun.COM }
97*7836SJohn.Forte@Sun.COM return (1);
98*7836SJohn.Forte@Sun.COM }
99*7836SJohn.Forte@Sun.COM
100*7836SJohn.Forte@Sun.COM
101*7836SJohn.Forte@Sun.COM /*
102*7836SJohn.Forte@Sun.COM * This functions constructs a device path of the device/enclosure with the
103*7836SJohn.Forte@Sun.COM * given tid and, for public/fabric cases, on the same area and domain as
104*7836SJohn.Forte@Sun.COM * the given ses_path.
105*7836SJohn.Forte@Sun.COM *
106*7836SJohn.Forte@Sun.COM * INPUT:
107*7836SJohn.Forte@Sun.COM * ses_path - pointer to the ses_path
108*7836SJohn.Forte@Sun.COM * tid - tid of the device/enclosure whose path is to be constructed
109*7836SJohn.Forte@Sun.COM * map - pointer to the map
110*7836SJohn.Forte@Sun.COM * dtype - dtype of the device whose path is to be constructed
111*7836SJohn.Forte@Sun.COM *
112*7836SJohn.Forte@Sun.COM * OUTPUT:
113*7836SJohn.Forte@Sun.COM * dev_path - pointer to the device path of type dtype and with tid
114*7836SJohn.Forte@Sun.COM * - Caller has to free this after use
115*7836SJohn.Forte@Sun.COM *
116*7836SJohn.Forte@Sun.COM * RETURNS:
117*7836SJohn.Forte@Sun.COM * 0 - on success
118*7836SJohn.Forte@Sun.COM * non-zero - otherwise
119*7836SJohn.Forte@Sun.COM */
120*7836SJohn.Forte@Sun.COM int
l_make_node(char * ses_path,int tid,char * dev_path,gfc_map_t * map,int dtype)121*7836SJohn.Forte@Sun.COM l_make_node(char *ses_path, int tid, char *dev_path,
122*7836SJohn.Forte@Sun.COM gfc_map_t *map, int dtype)
123*7836SJohn.Forte@Sun.COM {
124*7836SJohn.Forte@Sun.COM int len, i, err;
125*7836SJohn.Forte@Sun.COM int this_pid, ses_pid;
126*7836SJohn.Forte@Sun.COM char ssd[40], wwn[20];
127*7836SJohn.Forte@Sun.COM gfc_port_dev_info_t *dev_addr_ptr;
128*7836SJohn.Forte@Sun.COM struct stat stat_buf;
129*7836SJohn.Forte@Sun.COM WWN_list *wwnlp, *wwn_list;
130*7836SJohn.Forte@Sun.COM int found = 0;
131*7836SJohn.Forte@Sun.COM
132*7836SJohn.Forte@Sun.COM if ((ses_path == NULL) || (dev_path == NULL) || (map == NULL)) {
133*7836SJohn.Forte@Sun.COM return (L_INVALID_PATH_FORMAT);
134*7836SJohn.Forte@Sun.COM }
135*7836SJohn.Forte@Sun.COM
136*7836SJohn.Forte@Sun.COM switch (map->hba_addr.port_topology) {
137*7836SJohn.Forte@Sun.COM case FC_TOP_PRIVATE_LOOP:
138*7836SJohn.Forte@Sun.COM for (i = 0, dev_addr_ptr = map->dev_addr;
139*7836SJohn.Forte@Sun.COM i < map->count; i++, dev_addr_ptr++) {
140*7836SJohn.Forte@Sun.COM if (dev_addr_ptr->gfc_port_dev.priv_port.
141*7836SJohn.Forte@Sun.COM sf_al_pa == g_switch_to_alpa[tid])
142*7836SJohn.Forte@Sun.COM break;
143*7836SJohn.Forte@Sun.COM }
144*7836SJohn.Forte@Sun.COM if (i >= map->count) {
145*7836SJohn.Forte@Sun.COM *dev_path = '\0';
146*7836SJohn.Forte@Sun.COM return (L_INVALID_LOOP_MAP);
147*7836SJohn.Forte@Sun.COM }
148*7836SJohn.Forte@Sun.COM
149*7836SJohn.Forte@Sun.COM /* Make sure that the port WWN is valid */
150*7836SJohn.Forte@Sun.COM if (is_null_wwn(dev_addr_ptr->gfc_port_dev.
151*7836SJohn.Forte@Sun.COM priv_port.sf_port_wwn)) {
152*7836SJohn.Forte@Sun.COM *dev_path = '\0';
153*7836SJohn.Forte@Sun.COM return (L_INVLD_WWN_FORMAT);
154*7836SJohn.Forte@Sun.COM }
155*7836SJohn.Forte@Sun.COM
156*7836SJohn.Forte@Sun.COM (void) g_ll_to_str(dev_addr_ptr->gfc_port_dev.
157*7836SJohn.Forte@Sun.COM priv_port.sf_port_wwn, wwn);
158*7836SJohn.Forte@Sun.COM
159*7836SJohn.Forte@Sun.COM if (strstr(ses_path, SCSI_VHCI) != NULL) {
160*7836SJohn.Forte@Sun.COM if (err = g_get_wwn_list(&wwn_list, 0)) {
161*7836SJohn.Forte@Sun.COM return (err);
162*7836SJohn.Forte@Sun.COM }
163*7836SJohn.Forte@Sun.COM for (wwnlp = wwn_list, found = 0;
164*7836SJohn.Forte@Sun.COM wwnlp != NULL;
165*7836SJohn.Forte@Sun.COM wwnlp = wwnlp->wwn_next) {
166*7836SJohn.Forte@Sun.COM if (strcmp(wwnlp->port_wwn_s,
167*7836SJohn.Forte@Sun.COM wwn) == 0) {
168*7836SJohn.Forte@Sun.COM found = 1;
169*7836SJohn.Forte@Sun.COM break;
170*7836SJohn.Forte@Sun.COM }
171*7836SJohn.Forte@Sun.COM }
172*7836SJohn.Forte@Sun.COM if (found) {
173*7836SJohn.Forte@Sun.COM (void) strcpy(dev_path,
174*7836SJohn.Forte@Sun.COM wwnlp->physical_path);
175*7836SJohn.Forte@Sun.COM } else {
176*7836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
177*7836SJohn.Forte@Sun.COM }
178*7836SJohn.Forte@Sun.COM } else {
179*7836SJohn.Forte@Sun.COM
180*7836SJohn.Forte@Sun.COM len = strlen(ses_path) -
181*7836SJohn.Forte@Sun.COM strlen(strrchr(ses_path, '/'));
182*7836SJohn.Forte@Sun.COM
183*7836SJohn.Forte@Sun.COM if (dtype != DTYPE_ESI) {
184*7836SJohn.Forte@Sun.COM (void) sprintf(ssd,
185*7836SJohn.Forte@Sun.COM "/ssd@w%s,0:c", wwn);
186*7836SJohn.Forte@Sun.COM } else {
187*7836SJohn.Forte@Sun.COM (void) sprintf(ssd,
188*7836SJohn.Forte@Sun.COM "/ses@w%s,0:c", wwn);
189*7836SJohn.Forte@Sun.COM }
190*7836SJohn.Forte@Sun.COM
191*7836SJohn.Forte@Sun.COM /* TBD: Must find path, not just use :c */
192*7836SJohn.Forte@Sun.COM (void) strncpy(dev_path, ses_path, len);
193*7836SJohn.Forte@Sun.COM dev_path[len] = '\0';
194*7836SJohn.Forte@Sun.COM (void) strcat(dev_path, ssd);
195*7836SJohn.Forte@Sun.COM }
196*7836SJohn.Forte@Sun.COM break;
197*7836SJohn.Forte@Sun.COM case FC_TOP_FABRIC:
198*7836SJohn.Forte@Sun.COM case FC_TOP_PUBLIC_LOOP:
199*7836SJohn.Forte@Sun.COM /* First lets get the PA from the ses path passed in */
200*7836SJohn.Forte@Sun.COM if (err = l_get_pid_from_path(ses_path, map, &ses_pid)) {
201*7836SJohn.Forte@Sun.COM return (err);
202*7836SJohn.Forte@Sun.COM }
203*7836SJohn.Forte@Sun.COM
204*7836SJohn.Forte@Sun.COM /*
205*7836SJohn.Forte@Sun.COM * Now we go through every entry in the map and match the
206*7836SJohn.Forte@Sun.COM * area and domain ids with the PA of the passed ses path.
207*7836SJohn.Forte@Sun.COM * If we find a match, we then match the low order byte
208*7836SJohn.Forte@Sun.COM */
209*7836SJohn.Forte@Sun.COM for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count;
210*7836SJohn.Forte@Sun.COM i++, dev_addr_ptr++) {
211*7836SJohn.Forte@Sun.COM this_pid = dev_addr_ptr->gfc_port_dev.pub_port.
212*7836SJohn.Forte@Sun.COM dev_did.port_id;
213*7836SJohn.Forte@Sun.COM if ((this_pid & AREA_DOMAIN_ID) ==
214*7836SJohn.Forte@Sun.COM (ses_pid & AREA_DOMAIN_ID)) {
215*7836SJohn.Forte@Sun.COM if ((uchar_t)(this_pid & 0xFF) ==
216*7836SJohn.Forte@Sun.COM g_switch_to_alpa[tid])
217*7836SJohn.Forte@Sun.COM break;
218*7836SJohn.Forte@Sun.COM }
219*7836SJohn.Forte@Sun.COM }
220*7836SJohn.Forte@Sun.COM if (i >= map->count) {
221*7836SJohn.Forte@Sun.COM *dev_path = '\0';
222*7836SJohn.Forte@Sun.COM return (L_INVALID_LOOP_MAP);
223*7836SJohn.Forte@Sun.COM }
224*7836SJohn.Forte@Sun.COM /* Make sure that the port WWN is valid */
225*7836SJohn.Forte@Sun.COM if (is_null_wwn(dev_addr_ptr->gfc_port_dev.pub_port.
226*7836SJohn.Forte@Sun.COM dev_pwwn.raw_wwn)) {
227*7836SJohn.Forte@Sun.COM *dev_path = '\0';
228*7836SJohn.Forte@Sun.COM return (L_INVLD_WWN_FORMAT);
229*7836SJohn.Forte@Sun.COM }
230*7836SJohn.Forte@Sun.COM (void) g_ll_to_str(dev_addr_ptr->gfc_port_dev.
231*7836SJohn.Forte@Sun.COM pub_port.dev_pwwn.raw_wwn, wwn);
232*7836SJohn.Forte@Sun.COM
233*7836SJohn.Forte@Sun.COM
234*7836SJohn.Forte@Sun.COM
235*7836SJohn.Forte@Sun.COM if (strstr(ses_path, SCSI_VHCI) != NULL) {
236*7836SJohn.Forte@Sun.COM if (err = g_get_wwn_list(&wwn_list, 0)) {
237*7836SJohn.Forte@Sun.COM return (err);
238*7836SJohn.Forte@Sun.COM }
239*7836SJohn.Forte@Sun.COM for (wwnlp = wwn_list, found = 0; wwnlp != NULL;
240*7836SJohn.Forte@Sun.COM wwnlp = wwnlp->wwn_next) {
241*7836SJohn.Forte@Sun.COM if (strcmp(wwnlp->port_wwn_s,
242*7836SJohn.Forte@Sun.COM wwn) == 0) {
243*7836SJohn.Forte@Sun.COM found = 1;
244*7836SJohn.Forte@Sun.COM }
245*7836SJohn.Forte@Sun.COM }
246*7836SJohn.Forte@Sun.COM if (found) {
247*7836SJohn.Forte@Sun.COM (void) strcpy(dev_path,
248*7836SJohn.Forte@Sun.COM wwnlp->physical_path);
249*7836SJohn.Forte@Sun.COM } else {
250*7836SJohn.Forte@Sun.COM return (L_INVALID_PATH);
251*7836SJohn.Forte@Sun.COM }
252*7836SJohn.Forte@Sun.COM } else {
253*7836SJohn.Forte@Sun.COM len = strlen(ses_path) -
254*7836SJohn.Forte@Sun.COM strlen(strrchr(ses_path, '/'));
255*7836SJohn.Forte@Sun.COM
256*7836SJohn.Forte@Sun.COM if (dtype != DTYPE_ESI) {
257*7836SJohn.Forte@Sun.COM (void) sprintf(ssd, "/ssd@w%s,0:c", wwn);
258*7836SJohn.Forte@Sun.COM } else {
259*7836SJohn.Forte@Sun.COM (void) sprintf(ssd, "/ses@w%s,0:c", wwn);
260*7836SJohn.Forte@Sun.COM }
261*7836SJohn.Forte@Sun.COM
262*7836SJohn.Forte@Sun.COM /* TBD: Must find path, not just use :c */
263*7836SJohn.Forte@Sun.COM (void) strncpy(dev_path, ses_path, len);
264*7836SJohn.Forte@Sun.COM dev_path[len] = '\0';
265*7836SJohn.Forte@Sun.COM (void) strcat(dev_path, ssd);
266*7836SJohn.Forte@Sun.COM }
267*7836SJohn.Forte@Sun.COM
268*7836SJohn.Forte@Sun.COM if (stat(dev_path, &stat_buf) == -1) {
269*7836SJohn.Forte@Sun.COM return (errno);
270*7836SJohn.Forte@Sun.COM }
271*7836SJohn.Forte@Sun.COM
272*7836SJohn.Forte@Sun.COM break;
273*7836SJohn.Forte@Sun.COM case FC_TOP_PT_PT:
274*7836SJohn.Forte@Sun.COM return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
275*7836SJohn.Forte@Sun.COM default:
276*7836SJohn.Forte@Sun.COM return (L_UNEXPECTED_FC_TOPOLOGY);
277*7836SJohn.Forte@Sun.COM } /* End of switch on port_topology */
278*7836SJohn.Forte@Sun.COM return (0);
279*7836SJohn.Forte@Sun.COM }
280*7836SJohn.Forte@Sun.COM
281*7836SJohn.Forte@Sun.COM
282*7836SJohn.Forte@Sun.COM
283*7836SJohn.Forte@Sun.COM /*
284*7836SJohn.Forte@Sun.COM * checks for null wwn to a disk.
285*7836SJohn.Forte@Sun.COM * and returns -1 if found, 0
286*7836SJohn.Forte@Sun.COM * otherwise.
287*7836SJohn.Forte@Sun.COM *
288*7836SJohn.Forte@Sun.COM * OUTPUT:
289*7836SJohn.Forte@Sun.COM * char *ses_path
290*7836SJohn.Forte@Sun.COM *
291*7836SJohn.Forte@Sun.COM * RETURNS:
292*7836SJohn.Forte@Sun.COM * 0 if OK
293*7836SJohn.Forte@Sun.COM * non-zero otherwise
294*7836SJohn.Forte@Sun.COM */
295*7836SJohn.Forte@Sun.COM int
l_chk_null_wwn(Path_struct * path_struct,char * ses_path,L_state * l_state,int verbose)296*7836SJohn.Forte@Sun.COM l_chk_null_wwn(Path_struct *path_struct, char *ses_path,
297*7836SJohn.Forte@Sun.COM L_state *l_state, int verbose)
298*7836SJohn.Forte@Sun.COM {
299*7836SJohn.Forte@Sun.COM char *ptr, boxname[MAXPATHLEN];
300*7836SJohn.Forte@Sun.COM char node_wwn_s[WWN_SIZE * 2 + 1];
301*7836SJohn.Forte@Sun.COM Box_list *boxlist;
302*7836SJohn.Forte@Sun.COM
303*7836SJohn.Forte@Sun.COM
304*7836SJohn.Forte@Sun.COM if ((path_struct == NULL) || (ses_path == NULL) ||
305*7836SJohn.Forte@Sun.COM (l_state == NULL)) {
306*7836SJohn.Forte@Sun.COM return (L_INVALID_PATH_FORMAT);
307*7836SJohn.Forte@Sun.COM }
308*7836SJohn.Forte@Sun.COM
309*7836SJohn.Forte@Sun.COM /*
310*7836SJohn.Forte@Sun.COM * verify and continue only if the argv
311*7836SJohn.Forte@Sun.COM * has a format like box,{f/r}<slot #>.
312*7836SJohn.Forte@Sun.COM * Otherwise, return to the caller.
313*7836SJohn.Forte@Sun.COM * The only way to address null wwn disk
314*7836SJohn.Forte@Sun.COM * is using the box,{f/r}<slot#> format.
315*7836SJohn.Forte@Sun.COM */
316*7836SJohn.Forte@Sun.COM /* add support for new {f/r/s}<slot#> support for DPM */
317*7836SJohn.Forte@Sun.COM (void) strcpy(boxname, path_struct->argv);
318*7836SJohn.Forte@Sun.COM if (((ptr = strstr(boxname, ",")) != NULL) &&
319*7836SJohn.Forte@Sun.COM ((*(ptr + 1) == 'f') || (*(ptr + 1) == 'r') ||
320*7836SJohn.Forte@Sun.COM (*(ptr + 1) == 's'))) {
321*7836SJohn.Forte@Sun.COM *ptr = NULL;
322*7836SJohn.Forte@Sun.COM } else {
323*7836SJohn.Forte@Sun.COM return (0);
324*7836SJohn.Forte@Sun.COM }
325*7836SJohn.Forte@Sun.COM
326*7836SJohn.Forte@Sun.COM
327*7836SJohn.Forte@Sun.COM /*
328*7836SJohn.Forte@Sun.COM * Get the list of enclosures
329*7836SJohn.Forte@Sun.COM * connected to the system.
330*7836SJohn.Forte@Sun.COM */
331*7836SJohn.Forte@Sun.COM if (l_get_box_list(&boxlist, verbose) != 0) {
332*7836SJohn.Forte@Sun.COM return (L_NO_ENCL_LIST_FOUND);
333*7836SJohn.Forte@Sun.COM }
334*7836SJohn.Forte@Sun.COM
335*7836SJohn.Forte@Sun.COM *ses_path = NULL;
336*7836SJohn.Forte@Sun.COM
337*7836SJohn.Forte@Sun.COM /*
338*7836SJohn.Forte@Sun.COM * The following method is safer to get an ses path
339*7836SJohn.Forte@Sun.COM * to the enclosure than calling l_get_ses_path(),
340*7836SJohn.Forte@Sun.COM * with physical path to null WWN disk.
341*7836SJohn.Forte@Sun.COM * Because, l_get_ses_path uses the disk's
342*7836SJohn.Forte@Sun.COM * al_pa to get the box id and then ses path
343*7836SJohn.Forte@Sun.COM * to the box. When a disk has null wwn, it may
344*7836SJohn.Forte@Sun.COM * not have a valid al_pa, and hard address.
345*7836SJohn.Forte@Sun.COM * There is a possibility that l_get_ses_path()
346*7836SJohn.Forte@Sun.COM * not returning ses path to the correct enclosure.
347*7836SJohn.Forte@Sun.COM */
348*7836SJohn.Forte@Sun.COM while (boxlist != NULL) {
349*7836SJohn.Forte@Sun.COM if ((strcmp(boxname, (char *)boxlist->b_name) == 0)) {
350*7836SJohn.Forte@Sun.COM (void) strcpy(ses_path, boxlist->b_physical_path);
351*7836SJohn.Forte@Sun.COM break;
352*7836SJohn.Forte@Sun.COM }
353*7836SJohn.Forte@Sun.COM boxlist = boxlist->box_next;
354*7836SJohn.Forte@Sun.COM }
355*7836SJohn.Forte@Sun.COM
356*7836SJohn.Forte@Sun.COM /* free the box list */
357*7836SJohn.Forte@Sun.COM (void) l_free_box_list(&boxlist);
358*7836SJohn.Forte@Sun.COM
359*7836SJohn.Forte@Sun.COM if ((ses_path != NULL) && (strstr(ses_path, "ses") != NULL)) {
360*7836SJohn.Forte@Sun.COM if (l_get_status(ses_path, l_state,
361*7836SJohn.Forte@Sun.COM verbose) != 0) {
362*7836SJohn.Forte@Sun.COM return (L_GET_STATUS_FAILED);
363*7836SJohn.Forte@Sun.COM }
364*7836SJohn.Forte@Sun.COM if (path_struct->f_flag) {
365*7836SJohn.Forte@Sun.COM (void) strcpy(node_wwn_s,
366*7836SJohn.Forte@Sun.COM l_state->drv_front[path_struct->slot].g_disk_state.node_wwn_s);
367*7836SJohn.Forte@Sun.COM } else {
368*7836SJohn.Forte@Sun.COM (void) strcpy(node_wwn_s,
369*7836SJohn.Forte@Sun.COM l_state->drv_rear[path_struct->slot].g_disk_state.node_wwn_s);
370*7836SJohn.Forte@Sun.COM }
371*7836SJohn.Forte@Sun.COM
372*7836SJohn.Forte@Sun.COM W_DPRINTF("Found ses path: %s\n"
373*7836SJohn.Forte@Sun.COM "and Node WWN: %s\n", ses_path, node_wwn_s);
374*7836SJohn.Forte@Sun.COM
375*7836SJohn.Forte@Sun.COM /* check for null WWN */
376*7836SJohn.Forte@Sun.COM if (is_null_wwn((uchar_t *)node_wwn_s) == 0) {
377*7836SJohn.Forte@Sun.COM return (0); /* Non-null wwn */
378*7836SJohn.Forte@Sun.COM }
379*7836SJohn.Forte@Sun.COM W_DPRINTF("Found NULL WWN: %s\n", node_wwn_s);
380*7836SJohn.Forte@Sun.COM return (1);
381*7836SJohn.Forte@Sun.COM }
382*7836SJohn.Forte@Sun.COM
383*7836SJohn.Forte@Sun.COM return (0);
384*7836SJohn.Forte@Sun.COM
385*7836SJohn.Forte@Sun.COM }
386*7836SJohn.Forte@Sun.COM
387*7836SJohn.Forte@Sun.COM
388*7836SJohn.Forte@Sun.COM
389*7836SJohn.Forte@Sun.COM /*
390*7836SJohn.Forte@Sun.COM * If OVERALL_STATUS is sent as the "func",
391*7836SJohn.Forte@Sun.COM * the code pointer must be valid (non NULL).
392*7836SJohn.Forte@Sun.COM * Otherwise NULL is a valid input for the code pointer.
393*7836SJohn.Forte@Sun.COM *
394*7836SJohn.Forte@Sun.COM * RETURNS:
395*7836SJohn.Forte@Sun.COM * 0 if OK
396*7836SJohn.Forte@Sun.COM * non-zero otherwise
397*7836SJohn.Forte@Sun.COM */
398*7836SJohn.Forte@Sun.COM int
l_encl_status_page_funcs(int func,char * code,int todo,char * ses_path,struct l_state_struct * l_state,int f_flag,int slot,int verbose_flag)399*7836SJohn.Forte@Sun.COM l_encl_status_page_funcs(int func, char *code, int todo, char *ses_path,
400*7836SJohn.Forte@Sun.COM struct l_state_struct *l_state,
401*7836SJohn.Forte@Sun.COM int f_flag, int slot, int verbose_flag)
402*7836SJohn.Forte@Sun.COM {
403*7836SJohn.Forte@Sun.COM uchar_t *page_buf;
404*7836SJohn.Forte@Sun.COM int fd, front_index, rear_index, offset, err;
405*7836SJohn.Forte@Sun.COM unsigned short page_len;
406*7836SJohn.Forte@Sun.COM struct device_element *elem;
407*7836SJohn.Forte@Sun.COM
408*7836SJohn.Forte@Sun.COM if ((ses_path == NULL) || (l_state == NULL)) {
409*7836SJohn.Forte@Sun.COM return (L_INVALID_PATH_FORMAT);
410*7836SJohn.Forte@Sun.COM }
411*7836SJohn.Forte@Sun.COM
412*7836SJohn.Forte@Sun.COM if ((page_buf = (uchar_t *)g_zalloc(MAX_REC_DIAG_LENGTH)) == NULL) {
413*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
414*7836SJohn.Forte@Sun.COM }
415*7836SJohn.Forte@Sun.COM
416*7836SJohn.Forte@Sun.COM if ((fd = g_object_open(ses_path, O_NDELAY | O_RDWR)) == -1) {
417*7836SJohn.Forte@Sun.COM (void) g_destroy_data(page_buf);
418*7836SJohn.Forte@Sun.COM return (L_OPEN_PATH_FAIL);
419*7836SJohn.Forte@Sun.COM }
420*7836SJohn.Forte@Sun.COM
421*7836SJohn.Forte@Sun.COM if ((err = l_get_envsen_page(fd, page_buf, MAX_REC_DIAG_LENGTH,
422*7836SJohn.Forte@Sun.COM L_PAGE_2, verbose_flag)) != 0) {
423*7836SJohn.Forte@Sun.COM (void) g_destroy_data(page_buf);
424*7836SJohn.Forte@Sun.COM (void) close(fd);
425*7836SJohn.Forte@Sun.COM return (err);
426*7836SJohn.Forte@Sun.COM }
427*7836SJohn.Forte@Sun.COM
428*7836SJohn.Forte@Sun.COM page_len = (page_buf[2] << 8 | page_buf[3]) + HEADER_LEN;
429*7836SJohn.Forte@Sun.COM
430*7836SJohn.Forte@Sun.COM if ((err = l_get_disk_element_index(l_state, &front_index,
431*7836SJohn.Forte@Sun.COM &rear_index)) != 0) {
432*7836SJohn.Forte@Sun.COM (void) g_destroy_data(page_buf);
433*7836SJohn.Forte@Sun.COM (void) close(fd);
434*7836SJohn.Forte@Sun.COM return (err);
435*7836SJohn.Forte@Sun.COM }
436*7836SJohn.Forte@Sun.COM /* Skip global element */
437*7836SJohn.Forte@Sun.COM front_index++;
438*7836SJohn.Forte@Sun.COM if ((strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_OFF_NAME,
439*7836SJohn.Forte@Sun.COM strlen(DAK_OFF_NAME)) == 0) ||
440*7836SJohn.Forte@Sun.COM (strncmp((char *)l_state->ib_tbl.config.prod_id, DAK_PROD_STR,
441*7836SJohn.Forte@Sun.COM strlen(DAK_OFF_NAME)) == 0)) {
442*7836SJohn.Forte@Sun.COM rear_index += l_state->total_num_drv/2 + 1;
443*7836SJohn.Forte@Sun.COM } else
444*7836SJohn.Forte@Sun.COM rear_index++;
445*7836SJohn.Forte@Sun.COM
446*7836SJohn.Forte@Sun.COM if (f_flag) {
447*7836SJohn.Forte@Sun.COM offset = (8 + (front_index + slot)*4);
448*7836SJohn.Forte@Sun.COM } else {
449*7836SJohn.Forte@Sun.COM offset = (8 + (rear_index + slot)*4);
450*7836SJohn.Forte@Sun.COM }
451*7836SJohn.Forte@Sun.COM
452*7836SJohn.Forte@Sun.COM elem = (struct device_element *)(page_buf + offset);
453*7836SJohn.Forte@Sun.COM
454*7836SJohn.Forte@Sun.COM switch (func) {
455*7836SJohn.Forte@Sun.COM case OVERALL_STATUS:
456*7836SJohn.Forte@Sun.COM if (code == NULL) {
457*7836SJohn.Forte@Sun.COM return (L_INVALID_ARG);
458*7836SJohn.Forte@Sun.COM }
459*7836SJohn.Forte@Sun.COM switch (todo) {
460*7836SJohn.Forte@Sun.COM case INSERT_DEVICE:
461*7836SJohn.Forte@Sun.COM *code = (elem->code != S_OK) ? elem->code : 0;
462*7836SJohn.Forte@Sun.COM (void) g_destroy_data(page_buf);
463*7836SJohn.Forte@Sun.COM (void) close(fd);
464*7836SJohn.Forte@Sun.COM return (0);
465*7836SJohn.Forte@Sun.COM case REMOVE_DEVICE:
466*7836SJohn.Forte@Sun.COM *code = (elem->code != S_NOT_INSTALLED) ?
467*7836SJohn.Forte@Sun.COM elem->code : 0;
468*7836SJohn.Forte@Sun.COM (void) g_destroy_data(page_buf);
469*7836SJohn.Forte@Sun.COM (void) close(fd);
470*7836SJohn.Forte@Sun.COM return (0);
471*7836SJohn.Forte@Sun.COM }
472*7836SJohn.Forte@Sun.COM /* NOTREACHED */
473*7836SJohn.Forte@Sun.COM case SET_RQST_INSRT:
474*7836SJohn.Forte@Sun.COM bzero(elem, sizeof (struct device_element));
475*7836SJohn.Forte@Sun.COM elem->select = 1;
476*7836SJohn.Forte@Sun.COM elem->rdy_to_ins = 1;
477*7836SJohn.Forte@Sun.COM break;
478*7836SJohn.Forte@Sun.COM case SET_RQST_RMV:
479*7836SJohn.Forte@Sun.COM bzero(elem, sizeof (struct device_element));
480*7836SJohn.Forte@Sun.COM elem->select = 1;
481*7836SJohn.Forte@Sun.COM elem->rmv = 1;
482*7836SJohn.Forte@Sun.COM elem->dev_off = 1;
483*7836SJohn.Forte@Sun.COM elem->en_bypass_a = 1;
484*7836SJohn.Forte@Sun.COM elem->en_bypass_b = 1;
485*7836SJohn.Forte@Sun.COM break;
486*7836SJohn.Forte@Sun.COM case SET_FAULT:
487*7836SJohn.Forte@Sun.COM bzero(elem, sizeof (struct device_element));
488*7836SJohn.Forte@Sun.COM elem->select = 1;
489*7836SJohn.Forte@Sun.COM elem->fault_req = 1;
490*7836SJohn.Forte@Sun.COM elem->dev_off = 1;
491*7836SJohn.Forte@Sun.COM elem->en_bypass_a = 1;
492*7836SJohn.Forte@Sun.COM elem->en_bypass_b = 1;
493*7836SJohn.Forte@Sun.COM break;
494*7836SJohn.Forte@Sun.COM case SET_DRV_ON:
495*7836SJohn.Forte@Sun.COM bzero(elem, sizeof (struct device_element));
496*7836SJohn.Forte@Sun.COM elem->select = 1;
497*7836SJohn.Forte@Sun.COM break;
498*7836SJohn.Forte@Sun.COM }
499*7836SJohn.Forte@Sun.COM
500*7836SJohn.Forte@Sun.COM err = g_scsi_send_diag_cmd(fd, (uchar_t *)page_buf, page_len);
501*7836SJohn.Forte@Sun.COM (void) g_destroy_data(page_buf);
502*7836SJohn.Forte@Sun.COM (void) close(fd);
503*7836SJohn.Forte@Sun.COM return (err);
504*7836SJohn.Forte@Sun.COM }
505*7836SJohn.Forte@Sun.COM
506*7836SJohn.Forte@Sun.COM
507*7836SJohn.Forte@Sun.COM
508*7836SJohn.Forte@Sun.COM /*
509*7836SJohn.Forte@Sun.COM * Finds whether device id (tid) exists in the
510*7836SJohn.Forte@Sun.COM * Arbitrated loop map or not.
511*7836SJohn.Forte@Sun.COM *
512*7836SJohn.Forte@Sun.COM * INPUT:
513*7836SJohn.Forte@Sun.COM * ses_path - pointer to a ses path
514*7836SJohn.Forte@Sun.COM * tid - the target id of the device we want to check on
515*7836SJohn.Forte@Sun.COM * - only the low order 8 bits has the tid
516*7836SJohn.Forte@Sun.COM * map - pointer to a map of the system
517*7836SJohn.Forte@Sun.COM * verbose_flag - self explanatory
518*7836SJohn.Forte@Sun.COM *
519*7836SJohn.Forte@Sun.COM * OUTPUT:
520*7836SJohn.Forte@Sun.COM * dev_path - the device path of the device with "tid".
521*7836SJohn.Forte@Sun.COM * Caller is responsible for freeing it
522*7836SJohn.Forte@Sun.COM *
523*7836SJohn.Forte@Sun.COM * RETURNS:
524*7836SJohn.Forte@Sun.COM * 1 if device present
525*7836SJohn.Forte@Sun.COM * 0 otherwise
526*7836SJohn.Forte@Sun.COM */
527*7836SJohn.Forte@Sun.COM int
l_device_present(char * ses_path,int tid,gfc_map_t * map,int verbose_flag,char ** dev_path)528*7836SJohn.Forte@Sun.COM l_device_present(char *ses_path, int tid, gfc_map_t *map,
529*7836SJohn.Forte@Sun.COM int verbose_flag, char **dev_path)
530*7836SJohn.Forte@Sun.COM {
531*7836SJohn.Forte@Sun.COM char sf_path[MAXPATHLEN];
532*7836SJohn.Forte@Sun.COM uchar_t wwn[40], c;
533*7836SJohn.Forte@Sun.COM int len, i, j, k, fnib, snib, this_pid;
534*7836SJohn.Forte@Sun.COM int fd, ses_pid, al_pa, err;
535*7836SJohn.Forte@Sun.COM char ssd[30];
536*7836SJohn.Forte@Sun.COM gfc_port_dev_info_t *dev_addr_ptr;
537*7836SJohn.Forte@Sun.COM WWN_list *wwnlp, *wwn_list;
538*7836SJohn.Forte@Sun.COM
539*7836SJohn.Forte@Sun.COM
540*7836SJohn.Forte@Sun.COM if (dev_path == NULL)
541*7836SJohn.Forte@Sun.COM return (0);
542*7836SJohn.Forte@Sun.COM
543*7836SJohn.Forte@Sun.COM if ((ses_path == NULL) || (map == NULL)) {
544*7836SJohn.Forte@Sun.COM return (L_NO_SES_PATH);
545*7836SJohn.Forte@Sun.COM }
546*7836SJohn.Forte@Sun.COM
547*7836SJohn.Forte@Sun.COM *dev_path = NULL;
548*7836SJohn.Forte@Sun.COM
549*7836SJohn.Forte@Sun.COM switch (map->hba_addr.port_topology) {
550*7836SJohn.Forte@Sun.COM case FC_TOP_PRIVATE_LOOP:
551*7836SJohn.Forte@Sun.COM for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count;
552*7836SJohn.Forte@Sun.COM i++, dev_addr_ptr++) {
553*7836SJohn.Forte@Sun.COM if (dev_addr_ptr->gfc_port_dev.
554*7836SJohn.Forte@Sun.COM priv_port.sf_inq_dtype != DTYPE_ESI) {
555*7836SJohn.Forte@Sun.COM al_pa = dev_addr_ptr->gfc_port_dev.
556*7836SJohn.Forte@Sun.COM priv_port.sf_al_pa;
557*7836SJohn.Forte@Sun.COM if (tid == g_sf_alpa_to_switch[al_pa]) {
558*7836SJohn.Forte@Sun.COM break;
559*7836SJohn.Forte@Sun.COM }
560*7836SJohn.Forte@Sun.COM }
561*7836SJohn.Forte@Sun.COM }
562*7836SJohn.Forte@Sun.COM if (i >= map->count)
563*7836SJohn.Forte@Sun.COM return (0);
564*7836SJohn.Forte@Sun.COM /*
565*7836SJohn.Forte@Sun.COM * Make sure that the port WWN is valid
566*7836SJohn.Forte@Sun.COM */
567*7836SJohn.Forte@Sun.COM if (is_null_wwn(dev_addr_ptr->gfc_port_dev.
568*7836SJohn.Forte@Sun.COM priv_port.sf_port_wwn)) {
569*7836SJohn.Forte@Sun.COM return (0);
570*7836SJohn.Forte@Sun.COM }
571*7836SJohn.Forte@Sun.COM for (j = 0, k = 0; j < WWN_SIZE; j++) {
572*7836SJohn.Forte@Sun.COM c = dev_addr_ptr->gfc_port_dev.priv_port.sf_port_wwn[j];
573*7836SJohn.Forte@Sun.COM fnib = (((int)(c & 0xf0)) >> 4);
574*7836SJohn.Forte@Sun.COM snib = (c & 0x0f);
575*7836SJohn.Forte@Sun.COM if (fnib >= 0 && fnib <= 9)
576*7836SJohn.Forte@Sun.COM wwn[k++] = '0' + fnib;
577*7836SJohn.Forte@Sun.COM else if (fnib >= 10 && fnib <= 15)
578*7836SJohn.Forte@Sun.COM wwn[k++] = 'a' + fnib - 10;
579*7836SJohn.Forte@Sun.COM if (snib >= 0 && snib <= 9)
580*7836SJohn.Forte@Sun.COM wwn[k++] = '0' + snib;
581*7836SJohn.Forte@Sun.COM else if (snib >= 10 && snib <= 15)
582*7836SJohn.Forte@Sun.COM wwn[k++] = 'a' + snib - 10;
583*7836SJohn.Forte@Sun.COM }
584*7836SJohn.Forte@Sun.COM wwn[k] = '\0';
585*7836SJohn.Forte@Sun.COM break;
586*7836SJohn.Forte@Sun.COM case FC_TOP_PUBLIC_LOOP:
587*7836SJohn.Forte@Sun.COM case FC_TOP_FABRIC:
588*7836SJohn.Forte@Sun.COM /*
589*7836SJohn.Forte@Sun.COM * Get the phys address (port id) of this ses device
590*7836SJohn.Forte@Sun.COM */
591*7836SJohn.Forte@Sun.COM if (err = l_get_pid_from_path(ses_path, map, &ses_pid))
592*7836SJohn.Forte@Sun.COM return (err);
593*7836SJohn.Forte@Sun.COM
594*7836SJohn.Forte@Sun.COM for (i = 0, dev_addr_ptr = map->dev_addr; i < map->count;
595*7836SJohn.Forte@Sun.COM i++, dev_addr_ptr++) {
596*7836SJohn.Forte@Sun.COM if (dev_addr_ptr->gfc_port_dev.pub_port.dev_dtype !=
597*7836SJohn.Forte@Sun.COM DTYPE_ESI) {
598*7836SJohn.Forte@Sun.COM /*
599*7836SJohn.Forte@Sun.COM * We have a device. First match the area and
600*7836SJohn.Forte@Sun.COM * domain ids and if they match, then see if
601*7836SJohn.Forte@Sun.COM * the 8bit tid matches the last 8 bits of
602*7836SJohn.Forte@Sun.COM * 'this_pid'
603*7836SJohn.Forte@Sun.COM */
604*7836SJohn.Forte@Sun.COM this_pid = dev_addr_ptr->gfc_port_dev.
605*7836SJohn.Forte@Sun.COM pub_port.dev_did.port_id;
606*7836SJohn.Forte@Sun.COM if ((this_pid & AREA_DOMAIN_ID) ==
607*7836SJohn.Forte@Sun.COM (ses_pid & AREA_DOMAIN_ID)) {
608*7836SJohn.Forte@Sun.COM if (tid == g_sf_alpa_to_switch[
609*7836SJohn.Forte@Sun.COM this_pid & 0xFF])
610*7836SJohn.Forte@Sun.COM break;
611*7836SJohn.Forte@Sun.COM }
612*7836SJohn.Forte@Sun.COM }
613*7836SJohn.Forte@Sun.COM }
614*7836SJohn.Forte@Sun.COM
615*7836SJohn.Forte@Sun.COM if (i >= map->count)
616*7836SJohn.Forte@Sun.COM return (0);
617*7836SJohn.Forte@Sun.COM /*
618*7836SJohn.Forte@Sun.COM * Make sure that the port WWN is valid
619*7836SJohn.Forte@Sun.COM */
620*7836SJohn.Forte@Sun.COM if (is_null_wwn(dev_addr_ptr->gfc_port_dev.
621*7836SJohn.Forte@Sun.COM pub_port.dev_pwwn.raw_wwn)) {
622*7836SJohn.Forte@Sun.COM return (0);
623*7836SJohn.Forte@Sun.COM }
624*7836SJohn.Forte@Sun.COM for (j = 0, k = 0; j < WWN_SIZE; j++) {
625*7836SJohn.Forte@Sun.COM c = dev_addr_ptr->gfc_port_dev.pub_port.
626*7836SJohn.Forte@Sun.COM dev_pwwn.raw_wwn[j];
627*7836SJohn.Forte@Sun.COM fnib = (((int)(c & 0xf0)) >> 4);
628*7836SJohn.Forte@Sun.COM snib = (c & 0x0f);
629*7836SJohn.Forte@Sun.COM if (fnib >= 0 && fnib <= 9)
630*7836SJohn.Forte@Sun.COM wwn[k++] = '0' + fnib;
631*7836SJohn.Forte@Sun.COM else if (fnib >= 10 && fnib <= 15)
632*7836SJohn.Forte@Sun.COM wwn[k++] = 'a' + fnib - 10;
633*7836SJohn.Forte@Sun.COM if (snib >= 0 && snib <= 9)
634*7836SJohn.Forte@Sun.COM wwn[k++] = '0' + snib;
635*7836SJohn.Forte@Sun.COM else if (snib >= 10 && snib <= 15)
636*7836SJohn.Forte@Sun.COM wwn[k++] = 'a' + snib - 10;
637*7836SJohn.Forte@Sun.COM }
638*7836SJohn.Forte@Sun.COM wwn[k] = '\0';
639*7836SJohn.Forte@Sun.COM break;
640*7836SJohn.Forte@Sun.COM case FC_TOP_PT_PT:
641*7836SJohn.Forte@Sun.COM return (L_PT_PT_FC_TOP_NOT_SUPPORTED);
642*7836SJohn.Forte@Sun.COM default:
643*7836SJohn.Forte@Sun.COM return (L_UNEXPECTED_FC_TOPOLOGY);
644*7836SJohn.Forte@Sun.COM } /* End of switch on port_topology */
645*7836SJohn.Forte@Sun.COM
646*7836SJohn.Forte@Sun.COM if (strstr(ses_path, SCSI_VHCI) != NULL) {
647*7836SJohn.Forte@Sun.COM if (err = g_get_wwn_list(&wwn_list, 0)) {
648*7836SJohn.Forte@Sun.COM return (err);
649*7836SJohn.Forte@Sun.COM }
650*7836SJohn.Forte@Sun.COM for (wwnlp = wwn_list; wwnlp != NULL;
651*7836SJohn.Forte@Sun.COM wwnlp = wwnlp->wwn_next) {
652*7836SJohn.Forte@Sun.COM if (memcmp(wwnlp->port_wwn_s, wwn, WWN_S_LEN) == 0) {
653*7836SJohn.Forte@Sun.COM break;
654*7836SJohn.Forte@Sun.COM }
655*7836SJohn.Forte@Sun.COM }
656*7836SJohn.Forte@Sun.COM if (wwnlp != NULL) {
657*7836SJohn.Forte@Sun.COM if ((*dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
658*7836SJohn.Forte@Sun.COM g_free_wwn_list(&wwn_list);
659*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
660*7836SJohn.Forte@Sun.COM }
661*7836SJohn.Forte@Sun.COM (void) strcpy(*dev_path, wwnlp->physical_path);
662*7836SJohn.Forte@Sun.COM } else {
663*7836SJohn.Forte@Sun.COM g_free_wwn_list(&wwn_list);
664*7836SJohn.Forte@Sun.COM return (0);
665*7836SJohn.Forte@Sun.COM }
666*7836SJohn.Forte@Sun.COM } else {
667*7836SJohn.Forte@Sun.COM
668*7836SJohn.Forte@Sun.COM len = strlen(ses_path) - strlen(strrchr(ses_path, '/'));
669*7836SJohn.Forte@Sun.COM
670*7836SJohn.Forte@Sun.COM (void) sprintf(ssd, "ssd@w%s,0", wwn);
671*7836SJohn.Forte@Sun.COM
672*7836SJohn.Forte@Sun.COM (void) strncpy(sf_path, ses_path, len);
673*7836SJohn.Forte@Sun.COM sf_path[len] = '\0';
674*7836SJohn.Forte@Sun.COM P_DPRINTF(" l_device_present: wwn=%s, sf_path=%s\n",
675*7836SJohn.Forte@Sun.COM wwn, sf_path);
676*7836SJohn.Forte@Sun.COM
677*7836SJohn.Forte@Sun.COM if ((*dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
678*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
679*7836SJohn.Forte@Sun.COM }
680*7836SJohn.Forte@Sun.COM (void) sprintf(*dev_path, "%s/%s", sf_path, ssd);
681*7836SJohn.Forte@Sun.COM P_DPRINTF(" l_device_present: dev_path=%s\n", *dev_path);
682*7836SJohn.Forte@Sun.COM
683*7836SJohn.Forte@Sun.COM (void) strcat(*dev_path, ":c");
684*7836SJohn.Forte@Sun.COM }
685*7836SJohn.Forte@Sun.COM if ((fd = open(*dev_path, O_RDONLY)) == -1) {
686*7836SJohn.Forte@Sun.COM free(*dev_path);
687*7836SJohn.Forte@Sun.COM *dev_path = NULL;
688*7836SJohn.Forte@Sun.COM return (0);
689*7836SJohn.Forte@Sun.COM }
690*7836SJohn.Forte@Sun.COM (void) close(fd);
691*7836SJohn.Forte@Sun.COM return (1);
692*7836SJohn.Forte@Sun.COM }
693*7836SJohn.Forte@Sun.COM
694*7836SJohn.Forte@Sun.COM
695*7836SJohn.Forte@Sun.COM
696*7836SJohn.Forte@Sun.COM /*
697*7836SJohn.Forte@Sun.COM * onlines the given list of devices
698*7836SJohn.Forte@Sun.COM * and free up the allocated memory.
699*7836SJohn.Forte@Sun.COM *
700*7836SJohn.Forte@Sun.COM * RETURNS:
701*7836SJohn.Forte@Sun.COM * N/A
702*7836SJohn.Forte@Sun.COM */
703*7836SJohn.Forte@Sun.COM static void
online_dev(struct dlist * dl_head,int force_flag)704*7836SJohn.Forte@Sun.COM online_dev(struct dlist *dl_head, int force_flag)
705*7836SJohn.Forte@Sun.COM {
706*7836SJohn.Forte@Sun.COM struct dlist *dl, *dl1;
707*7836SJohn.Forte@Sun.COM
708*7836SJohn.Forte@Sun.COM for (dl = dl_head; dl != NULL; ) {
709*7836SJohn.Forte@Sun.COM (void) g_online_drive(dl->multipath, force_flag);
710*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dl->multipath);
711*7836SJohn.Forte@Sun.COM dl1 = dl;
712*7836SJohn.Forte@Sun.COM dl = dl->next;
713*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dl1);
714*7836SJohn.Forte@Sun.COM }
715*7836SJohn.Forte@Sun.COM }
716*7836SJohn.Forte@Sun.COM
717*7836SJohn.Forte@Sun.COM
718*7836SJohn.Forte@Sun.COM
719*7836SJohn.Forte@Sun.COM /*
720*7836SJohn.Forte@Sun.COM * offlines all the disks in a
721*7836SJohn.Forte@Sun.COM * SENA enclosure.
722*7836SJohn.Forte@Sun.COM *
723*7836SJohn.Forte@Sun.COM * RETURNS:
724*7836SJohn.Forte@Sun.COM * 0 if O.K.
725*7836SJohn.Forte@Sun.COM * non-zero otherwise
726*7836SJohn.Forte@Sun.COM */
727*7836SJohn.Forte@Sun.COM int
l_offline_photon(struct hotplug_disk_list * hotplug_sena,struct wwn_list_struct * wwn_list,int force_flag,int verbose_flag)728*7836SJohn.Forte@Sun.COM l_offline_photon(struct hotplug_disk_list *hotplug_sena,
729*7836SJohn.Forte@Sun.COM struct wwn_list_struct *wwn_list,
730*7836SJohn.Forte@Sun.COM int force_flag, int verbose_flag)
731*7836SJohn.Forte@Sun.COM {
732*7836SJohn.Forte@Sun.COM int i, err;
733*7836SJohn.Forte@Sun.COM struct dlist *dl_head, *dl_tail, *dl, *dl_ses;
734*7836SJohn.Forte@Sun.COM char *dev_path, ses_path[MAXPATHLEN];
735*7836SJohn.Forte@Sun.COM L_state *l_state = NULL;
736*7836SJohn.Forte@Sun.COM
737*7836SJohn.Forte@Sun.COM if (hotplug_sena == NULL) {
738*7836SJohn.Forte@Sun.COM return (L_INVALID_PATH_FORMAT);
739*7836SJohn.Forte@Sun.COM }
740*7836SJohn.Forte@Sun.COM
741*7836SJohn.Forte@Sun.COM dl_head = dl_tail = NULL;
742*7836SJohn.Forte@Sun.COM if ((l_state = (L_state *)calloc(1, sizeof (L_state))) == NULL) {
743*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
744*7836SJohn.Forte@Sun.COM }
745*7836SJohn.Forte@Sun.COM
746*7836SJohn.Forte@Sun.COM /* Get global status for this Photon */
747*7836SJohn.Forte@Sun.COM dl_ses = hotplug_sena->seslist;
748*7836SJohn.Forte@Sun.COM while (dl_ses) {
749*7836SJohn.Forte@Sun.COM (void) strcpy(ses_path, dl_ses->dev_path);
750*7836SJohn.Forte@Sun.COM if (l_get_status(ses_path, l_state, verbose_flag) == 0)
751*7836SJohn.Forte@Sun.COM break;
752*7836SJohn.Forte@Sun.COM dl_ses = dl_ses->next;
753*7836SJohn.Forte@Sun.COM }
754*7836SJohn.Forte@Sun.COM
755*7836SJohn.Forte@Sun.COM if (dl_ses == NULL) {
756*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
757*7836SJohn.Forte@Sun.COM return (L_ENCL_INVALID_PATH);
758*7836SJohn.Forte@Sun.COM }
759*7836SJohn.Forte@Sun.COM
760*7836SJohn.Forte@Sun.COM for (i = 0; i < l_state->total_num_drv/2; i++) {
761*7836SJohn.Forte@Sun.COM if (*l_state->drv_front[i].g_disk_state.physical_path) {
762*7836SJohn.Forte@Sun.COM if ((dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
763*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
764*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
765*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
766*7836SJohn.Forte@Sun.COM }
767*7836SJohn.Forte@Sun.COM (void) strcpy(dev_path,
768*7836SJohn.Forte@Sun.COM (char *)&l_state->drv_front[i].g_disk_state.physical_path);
769*7836SJohn.Forte@Sun.COM if ((dl = g_zalloc(sizeof (struct dlist))) == NULL) {
770*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
771*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
772*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
773*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
774*7836SJohn.Forte@Sun.COM }
775*7836SJohn.Forte@Sun.COM dl->dev_path = dev_path;
776*7836SJohn.Forte@Sun.COM if ((err = g_get_multipath(dev_path,
777*7836SJohn.Forte@Sun.COM &(dl->multipath), wwn_list, 0)) != 0) {
778*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
779*7836SJohn.Forte@Sun.COM if (dl->multipath != NULL) {
780*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dl->multipath);
781*7836SJohn.Forte@Sun.COM }
782*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dl);
783*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
784*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
785*7836SJohn.Forte@Sun.COM return (err);
786*7836SJohn.Forte@Sun.COM }
787*7836SJohn.Forte@Sun.COM if ((err = g_offline_drive(dl->multipath,
788*7836SJohn.Forte@Sun.COM force_flag)) != 0) {
789*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
790*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dl->multipath);
791*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dl);
792*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
793*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
794*7836SJohn.Forte@Sun.COM return (err);
795*7836SJohn.Forte@Sun.COM }
796*7836SJohn.Forte@Sun.COM if (dl_head == NULL) {
797*7836SJohn.Forte@Sun.COM dl_head = dl_tail = dl;
798*7836SJohn.Forte@Sun.COM } else {
799*7836SJohn.Forte@Sun.COM dl_tail->next = dl;
800*7836SJohn.Forte@Sun.COM dl->prev = dl_tail;
801*7836SJohn.Forte@Sun.COM dl_tail = dl;
802*7836SJohn.Forte@Sun.COM }
803*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
804*7836SJohn.Forte@Sun.COM }
805*7836SJohn.Forte@Sun.COM if (*l_state->drv_rear[i].g_disk_state.physical_path) {
806*7836SJohn.Forte@Sun.COM if ((dev_path = g_zalloc(MAXPATHLEN)) == NULL) {
807*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
808*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
809*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
810*7836SJohn.Forte@Sun.COM }
811*7836SJohn.Forte@Sun.COM (void) strcpy(dev_path,
812*7836SJohn.Forte@Sun.COM (char *)&l_state->drv_rear[i].g_disk_state.physical_path);
813*7836SJohn.Forte@Sun.COM if ((dl = g_zalloc(sizeof (struct dlist))) == NULL) {
814*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
815*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
816*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
817*7836SJohn.Forte@Sun.COM return (L_MALLOC_FAILED);
818*7836SJohn.Forte@Sun.COM }
819*7836SJohn.Forte@Sun.COM dl->dev_path = dev_path;
820*7836SJohn.Forte@Sun.COM if ((err = g_get_multipath(dev_path,
821*7836SJohn.Forte@Sun.COM &(dl->multipath), wwn_list, 0)) != 0) {
822*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
823*7836SJohn.Forte@Sun.COM if (dl->multipath != NULL) {
824*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dl->multipath);
825*7836SJohn.Forte@Sun.COM }
826*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dl);
827*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
828*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
829*7836SJohn.Forte@Sun.COM return (err);
830*7836SJohn.Forte@Sun.COM }
831*7836SJohn.Forte@Sun.COM if ((err = g_offline_drive(dl->multipath,
832*7836SJohn.Forte@Sun.COM force_flag)) != 0) {
833*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
834*7836SJohn.Forte@Sun.COM (void) g_free_multipath(dl->multipath);
835*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dl);
836*7836SJohn.Forte@Sun.COM (void) online_dev(dl_head, force_flag);
837*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
838*7836SJohn.Forte@Sun.COM return (err);
839*7836SJohn.Forte@Sun.COM }
840*7836SJohn.Forte@Sun.COM if (dl_head == NULL) {
841*7836SJohn.Forte@Sun.COM dl_head = dl_tail = dl;
842*7836SJohn.Forte@Sun.COM } else {
843*7836SJohn.Forte@Sun.COM dl_tail->next = dl;
844*7836SJohn.Forte@Sun.COM dl->prev = dl_tail;
845*7836SJohn.Forte@Sun.COM dl_tail = dl;
846*7836SJohn.Forte@Sun.COM }
847*7836SJohn.Forte@Sun.COM (void) g_destroy_data(dev_path);
848*7836SJohn.Forte@Sun.COM }
849*7836SJohn.Forte@Sun.COM }
850*7836SJohn.Forte@Sun.COM hotplug_sena->dlhead = dl_head;
851*7836SJohn.Forte@Sun.COM (void) l_free_lstate(&l_state);
852*7836SJohn.Forte@Sun.COM return (0);
853*7836SJohn.Forte@Sun.COM
854*7836SJohn.Forte@Sun.COM }
855*7836SJohn.Forte@Sun.COM
856*7836SJohn.Forte@Sun.COM
857*7836SJohn.Forte@Sun.COM
858*7836SJohn.Forte@Sun.COM /*
859*7836SJohn.Forte@Sun.COM * prepares a char string
860*7836SJohn.Forte@Sun.COM * containing the name of the
861*7836SJohn.Forte@Sun.COM * device which will be hotplugged.
862*7836SJohn.Forte@Sun.COM *
863*7836SJohn.Forte@Sun.COM * RETURNS:
864*7836SJohn.Forte@Sun.COM * N/A
865*7836SJohn.Forte@Sun.COM */
866*7836SJohn.Forte@Sun.COM void
l_get_drive_name(char * drive_name,int slot,int f_flag,char * box_name)867*7836SJohn.Forte@Sun.COM l_get_drive_name(char *drive_name, int slot, int f_flag, char *box_name)
868*7836SJohn.Forte@Sun.COM {
869*7836SJohn.Forte@Sun.COM int enc_type = 0;
870*7836SJohn.Forte@Sun.COM L_inquiry inq;
871*7836SJohn.Forte@Sun.COM char *physpath;
872*7836SJohn.Forte@Sun.COM Path_struct *p_pathstruct;
873*7836SJohn.Forte@Sun.COM
874*7836SJohn.Forte@Sun.COM if ((drive_name == NULL) || (box_name == NULL)) {
875*7836SJohn.Forte@Sun.COM return;
876*7836SJohn.Forte@Sun.COM }
877*7836SJohn.Forte@Sun.COM
878*7836SJohn.Forte@Sun.COM if (!l_convert_name(box_name, &physpath, &p_pathstruct, 0)) {
879*7836SJohn.Forte@Sun.COM if (!g_get_inquiry(physpath, &inq)) {
880*7836SJohn.Forte@Sun.COM enc_type = l_get_enc_type(inq);
881*7836SJohn.Forte@Sun.COM }
882*7836SJohn.Forte@Sun.COM }
883*7836SJohn.Forte@Sun.COM /* If either of the above fail, we use the default value of 0 */
884*7836SJohn.Forte@Sun.COM free(physpath);
885*7836SJohn.Forte@Sun.COM free(p_pathstruct);
886*7836SJohn.Forte@Sun.COM switch (enc_type) {
887*7836SJohn.Forte@Sun.COM case DAK_ENC_TYPE:
888*7836SJohn.Forte@Sun.COM if (f_flag != NULL) {
889*7836SJohn.Forte@Sun.COM (void) sprintf(drive_name, MSGSTR(8502,
890*7836SJohn.Forte@Sun.COM "Drive in \"%s\" slot %d"), box_name, slot);
891*7836SJohn.Forte@Sun.COM } else {
892*7836SJohn.Forte@Sun.COM (void) sprintf(drive_name, MSGSTR(8502,
893*7836SJohn.Forte@Sun.COM "Drive in \"%s\" slot %d"), box_name,
894*7836SJohn.Forte@Sun.COM slot + (MAX_DRIVES_DAK/2));
895*7836SJohn.Forte@Sun.COM }
896*7836SJohn.Forte@Sun.COM break;
897*7836SJohn.Forte@Sun.COM default:
898*7836SJohn.Forte@Sun.COM if (f_flag != NULL) {
899*7836SJohn.Forte@Sun.COM (void) sprintf(drive_name, MSGSTR(8500,
900*7836SJohn.Forte@Sun.COM "Drive in \"%s\" front slot %d"), box_name, slot);
901*7836SJohn.Forte@Sun.COM } else {
902*7836SJohn.Forte@Sun.COM (void) sprintf(drive_name, MSGSTR(8501,
903*7836SJohn.Forte@Sun.COM "Drive in \"%s\" rear slot %d"), box_name, slot);
904*7836SJohn.Forte@Sun.COM }
905*7836SJohn.Forte@Sun.COM break;
906*7836SJohn.Forte@Sun.COM }
907*7836SJohn.Forte@Sun.COM }
908