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