1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _CFGA_FP_H
27 #define	_CFGA_FP_H
28 
29 
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #include <sys/types.h>
36 #include <sys/mkdev.h>
37 #include <stddef.h>
38 #include <locale.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <errno.h>
46 #include <locale.h>
47 #include <langinfo.h>
48 #include <time.h>
49 #include <stdarg.h>
50 #include <sys/mman.h>
51 #include <sys/ioctl.h>
52 #include <sys/dditypes.h>
53 #include <sys/modctl.h>
54 #include <libdevinfo.h>
55 #include <libdevice.h>
56 #include <librcm.h>
57 #include <dirent.h>
58 #include <strings.h>
59 
60 
61 #include <sys/ioctl.h>
62 #include <sys/byteorder.h>
63 #include <sys/scsi/scsi.h>
64 #include <strings.h>
65 #include <sys/vfstab.h>
66 #include <sys/stat.h>
67 #include <setjmp.h>
68 #include <signal.h>
69 #include <hbaapi.h>
70 #include <sys/fibre-channel/fcio.h>
71 #include <sys/fibre-channel/ulp/fcp_util.h>
72 
73 #include <sys/uio.h>
74 #include <sys/param.h>
75 
76 #include <synch.h>
77 #include <thread.h>
78 
79 #include <limits.h>
80 #include <ftw.h>
81 
82 #define	CFGA_PLUGIN_LIB
83 #include <config_admin.h>
84 
85 #if	!defined(DEBUG)
86 #define	NDEBUG	1
87 #else
88 #undef	NDEBUG
89 #endif
90 
91 #include <assert.h>
92 
93 /* Return/error codes */
94 typedef enum {
95 	FPCFGA_ERR = -2,
96 	FPCFGA_LIB_ERR = -1,
97 	FPCFGA_OK = 0,
98 	FPCFGA_ACCESS_OK,
99 	FPCFGA_NACK,
100 	FPCFGA_BUSY,
101 	FPCFGA_SYSTEM_BUSY,
102 	FPCFGA_APID_NOCONFIGURE,
103 	FPCFGA_APID_NOACCESS,
104 	FPCFGA_APID_NOEXIST,
105 	FPCFGA_OPNOTSUPP,
106 	FPCFGA_PRIV,
107 	FPCFGA_UNLOCKED,
108 	FPCFGA_NO_REC,
109 	FPCFGA_OP_INTR,
110 	FPCFGA_DB_INVAL,
111 	FPCFGA_CONF_OK_UPD_REP_FAILED,
112 	FPCFGA_UNCONF_OK_UPD_REP_FAILED,
113 	FPCFGA_INVALID_PATH,
114 	FPCFGA_VHCI_GET_PATHLIST_FAILED,
115 	FPCFGA_XPORT_NOT_IN_PHCI_LIST,
116 	FPCFGA_UNKNOWN_ERR,
117 	FPCFGA_FCP_TGT_SEND_SCSI_FAILED,
118 	FPCFGA_FCP_SEND_SCSI_DEV_NOT_TGT
119 } fpcfga_ret_t;
120 
121 /* Commands used internally */
122 typedef enum {
123 	FPCFGA_INVAL_CMD = -1,
124 	FPCFGA_DEV_OP = 0,
125 	FPCFGA_BUS_OP,
126 	FPCFGA_STAT_FC_DEV,
127 	FPCFGA_STAT_FCA_PORT,
128 	FPCFGA_STAT_ALL,
129 	FPCFGA_GET_DEVPATH,
130 	FPCFGA_INSERT_DEV,
131 	FPCFGA_REMOVE_DEV,
132 	FPCFGA_REPLACE_DEV,
133 	FPCFGA_WALK_NODE,
134 	FPCFGA_WALK_MINOR,
135 	FPCFGA_BUS_QUIESCE,
136 	FPCFGA_BUS_UNQUIESCE,
137 	FPCFGA_BUS_GETSTATE,
138 	FPCFGA_DEV_GETSTATE,
139 	FPCFGA_BUS_CONFIGURE,
140 	FPCFGA_BUS_UNCONFIGURE,
141 	FPCFGA_DEV_CONFIGURE,
142 	FPCFGA_DEV_UNCONFIGURE,
143 	FPCFGA_DEV_REMOVE,
144 	FPCFGA_RESET_DEV,
145 	FPCFGA_RESET_BUS,
146 	FPCFGA_RESET_ALL,
147 	FPCFGA_READ,
148 	FPCFGA_WRITE
149 } fpcfga_cmd_t;
150 
151 typedef enum {
152 	FPCFGA_TERMINATE = 0,
153 	FPCFGA_CONTINUE
154 } fpcfga_recur_t;
155 
156 
157 /* Structures for tree walking code */
158 
159 typedef struct {
160 	uint_t flags;
161 	int (*fcn)(di_node_t node, void *argp);
162 } walk_node_t;
163 
164 typedef struct {
165 	const char *nodetype;
166 	int (*fcn)(di_node_t node, di_minor_t minor, void *argp);
167 } walk_minor_t;
168 
169 typedef union {
170 	walk_node_t	node_args;
171 	walk_minor_t	minor_args;
172 } walkmode_t;
173 
174 typedef struct {
175 	uint_t flags;
176 	walkmode_t walkmode;
177 } walkarg_t;
178 
179 typedef struct {
180 	char *phys;
181 	char *log;
182 	fpcfga_ret_t ret;
183 	int match_minor;
184 	int l_errno;
185 } pathm_t;
186 
187 typedef struct ldata_list {
188 	cfga_list_data_t ldata;
189 	struct ldata_list *next;
190 } ldata_list_t;
191 
192 typedef struct {
193 	struct cfga_confirm	*confp;
194 	struct cfga_msg		*msgp;
195 } prompt_t;
196 
197 typedef struct luninfo_list {
198 	int 	lunnum;
199 	uint_t	node_state;
200 	uint_t	lun_flag;
201 	char	*path;
202 	struct luninfo_list *next;
203 } luninfo_list_t;
204 
205 typedef struct {
206 	char		*xport_phys;
207 	char		*dyncomp;
208 	uint_t		flags;
209 	luninfo_list_t	*lunlist;	/* Singly linked list */
210 } apid_t;
211 
212 /* Report luns names */
213 #define	FP_SCMD_REPORT_LUN	0xA0
214 #define	DEFAULT_NUM_LUN		1024
215 #define	REPORT_LUN_HDR_SIZE	8
216 #define	SAM_LUN_SIZE		8
217 
218 #ifdef _BIG_ENDIAN
219 #define	htonll(x)	(x)
220 #define	ntohll(x)	(x)
221 #else
222 #define	htonll(x)   ((((unsigned long long)htonl(x)) << 32) + htonl(x >> 32))
223 #define	ntohll(x)   ((((unsigned long long)ntohl(x)) << 32) + ntohl(x >> 32))
224 #endif
225 
226 typedef struct report_lun_resp {
227 	uint32_t	num_lun;
228 	uint32_t	reserved;
229 	longlong_t	lun_string[DEFAULT_NUM_LUN];
230 } report_lun_resp_t;
231 
232 /*
233  * Hardware options acceptable for fp plugin.
234  * list related options are handled by getsupopts() and set to
235  * index of array.
236  */
237 #define	OPT_DEVINFO_FORCE	0
238 #define	OPT_SHOW_SCSI_LUN	1
239 #define	OPT_FCP_DEV		2
240 #define	OPT_DISABLE_RCM		0
241 #define	OPT_FORCE_UPDATE_REP	1
242 #define	OPT_NO_UPDATE_REP	2
243 #define	OPT_REMOVE_UNUSABLE_SCSI_LUN	3
244 #define	OPT_REMOVE_UNUSABLE_FCP_DEV	4
245 
246 /* walk tree flag */
247 #define	FLAG_PATH_INFO_WALK	0x00000001
248 
249 /* apid_t flags */
250 #define	FLAG_DISABLE_RCM	0x00000001
251 #define	FLAG_FORCE_UPDATE_REP	0x00000010
252 #define	FLAG_NO_UPDATE_REP	0x00000100
253 #define	FLAG_DYN_AP_CONFIGURED	0x00001000
254 #define	FLAG_DEVINFO_FORCE	0x00010000
255 #define	FLAG_FCP_DEV		0x00100000
256 #define	FLAG_REMOVE_UNUSABLE_FCP_DEV	0x01000000
257 
258 /* apid_t lun flags */
259 #define	FLAG_SKIP_RCMOFFLINE	0x00000001
260 #define	FLAG_SKIP_RCMREMOVE	0x00000010
261 #define	FLAG_SKIP_ONLINEOTHERS	0x00000100
262 
263 /* define for peripheral qualifier mask */
264 #define	FP_PERI_QUAL_MASK	0xE0
265 
266 /* Message ids */
267 typedef enum {
268 
269 /* ERRORS */
270 ERR_UNKNOWN = -1,
271 ERR_OP_FAILED,
272 ERR_CMD_INVAL,
273 ERR_NOT_BUSAPID,
274 ERR_APID_INVAL,
275 ERR_NOT_BUSOP,
276 ERR_NOT_DEVOP,
277 ERR_UNAVAILABLE,
278 ERR_CTRLR_CRIT,
279 ERR_BUS_GETSTATE,
280 ERR_BUS_NOTCONNECTED,
281 ERR_BUS_CONNECTED,
282 ERR_BUS_QUIESCE,
283 ERR_BUS_UNQUIESCE,
284 ERR_BUS_CONFIGURE,
285 ERR_BUS_UNCONFIGURE,
286 ERR_DEV_CONFIGURE,
287 ERR_DEV_UNCONFIGURE,
288 ERR_FCA_CONFIGURE,
289 ERR_FCA_UNCONFIGURE,
290 ERR_DEV_REPLACE,
291 ERR_DEV_INSERT,
292 ERR_DEV_GETSTATE,
293 ERR_RESET,
294 ERR_LIST,
295 ERR_FC,
296 ERR_FC_GET_DEVLIST,
297 ERR_FC_GET_FIRST_DEV,
298 ERR_FC_GET_NEXT_DEV,
299 ERRARG_FC_DEV_MAP_INIT,
300 ERRARG_FC_PROP_LOOKUP_BYTES,
301 ERRARG_FC_INQUIRY,
302 ERRARG_FC_REP_LUNS,
303 ERRARG_FC_TOPOLOGY,
304 ERRARG_PATH_TOO_LONG,
305 ERRARG_INVALID_PATH,
306 ERRARG_OPENDIR,
307 ERRARG_VHCI_GET_PATHLIST,
308 ERRARG_XPORT_NOT_IN_PHCI_LIST,
309 ERR_SIG_STATE,
310 ERR_MAYBE_BUSY,
311 ERR_BUS_DEV_MISMATCH,
312 ERR_GET_DEVLIST,
313 ERR_MEM_ALLOC,
314 ERR_DEVCTL_OFFLINE,
315 ERR_UPD_REP,
316 ERR_CONF_OK_UPD_REP,
317 ERR_UNCONF_OK_UPD_REP,
318 ERR_PARTIAL_SUCCESS,
319 ERR_HBA_LOAD_LIBRARY,
320 ERR_MATCHING_HBA_PORT,
321 ERR_NO_ADAPTER_FOUND,
322 
323 /* Errors with arguments */
324 ERRARG_OPT_INVAL,
325 ERRARG_HWCMD_INVAL,
326 ERRARG_DEVINFO,
327 ERRARG_NOT_IN_DEVLIST,
328 ERRARG_NOT_IN_DEVINFO,
329 ERRARG_DI_GET_PROP,
330 ERRARG_DC_DDEF_ALLOC,
331 ERRARG_DC_BYTE_ARRAY,
332 ERRARG_DC_BUS_ACQUIRE,
333 ERRARG_BUS_DEV_CREATE,
334 ERRARG_BUS_DEV_CREATE_UNKNOWN,
335 ERRARG_DEV_ACQUIRE,
336 ERRARG_DEV_REMOVE,
337 
338 /* RCM Errors */
339 ERR_RCM_HANDLE,
340 ERRARG_RCM_SUSPEND,
341 ERRARG_RCM_RESUME,
342 ERRARG_RCM_OFFLINE,
343 ERRARG_RCM_ONLINE,
344 ERRARG_RCM_REMOVE,
345 ERRARG_RCM_INFO,
346 
347 /* Commands */
348 CMD_INSERT_DEV,
349 CMD_REMOVE_DEV,
350 CMD_REPLACE_DEV,
351 CMD_RESET_DEV,
352 CMD_RESET_BUS,
353 CMD_RESET_ALL,
354 
355 /* help messages */
356 MSG_HELP_HDR,
357 MSG_HELP_USAGE,
358 
359 /* Hotplug messages */
360 MSG_INSDEV,
361 MSG_RMDEV,
362 MSG_REPLDEV,
363 
364 /* Hotplugging confirmation prompts */
365 CONF_QUIESCE_1,
366 CONF_QUIESCE_2,
367 CONF_UNQUIESCE,
368 
369 /* Misc. */
370 WARN_DISCONNECT
371 } msgid_t;
372 
373 typedef struct {
374 	msgid_t str_id;
375 	fpcfga_cmd_t cmd;
376 	fpcfga_ret_t (*fcn)(fpcfga_cmd_t, apid_t *, prompt_t *, char **);
377 } hw_cmd_t;
378 
379 typedef struct {
380 	msgid_t msgid;
381 	int nargs;		/* Number of arguments following msgid */
382 	int intl;		/* Flag: if 1, internationalize */
383 	const char *msgstr;
384 } msgcvt_t;
385 
386 
387 #define	SLASH			"/"
388 #define	CFGA_DEV_DIR		"/dev/cfg"
389 #define	DEV_DIR			"/dev"
390 #define	DEVICES_DIR		"/devices"
391 #define	DEV_DSK			"/dev/dsk"
392 #define	DEV_RDSK		"/dev/rdsk"
393 #define	DEV_RMT			"/dev/rmt"
394 #define	DSK_DIR			"dsk"
395 #define	RDSK_DIR		"rdsk"
396 #define	RMT_DIR			"rmt"
397 
398 
399 #define	DYN_SEP			"::"
400 #define	LUN_COMP_SEP		","
401 #define	MINOR_SEP		":"
402 
403 #define	S_FREE(x)	(((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
404 #define	S_STR(x)	(((x) == NULL) ? "" : (x))
405 
406 
407 #define	IS_STUB_NODE(s)	(di_instance(s) == -1 &&	\
408 			    di_nodeid(s) == (DI_PROM_NODEID))
409 
410 #define	GET_MSG_STR(i)		(str_tbl[msg_idx(i)].msgstr)
411 
412 #define	GET_DYN(a)	(((a) != NULL) ? strstr((a), DYN_SEP) : (void *)0)
413 #define	GET_LUN_DYN(a)	(((a) != NULL) ? strstr((a), LUN_COMP_SEP) : (void *)0)
414 
415 /*
416  * The following macro removes the separator from the dynamic component.
417  */
418 #define	DYN_TO_DYNCOMP(a)	((a) + strlen(DYN_SEP))
419 #define	LUN_DYN_TO_LUNCOMP(a)	((a) + strlen(LUN_COMP_SEP))
420 
421 /*
422  * Property names
423  */
424 #define	PORT_WWN_PROP	"port-wwn"
425 #define	LUN_GUID_PROP	"client-guid"
426 #define	LUN_PROP	"lun"
427 
428 #define	WWN_S_LEN	17	/* NULL terminated string */
429 #define	WWN_SIZE	8
430 /* Constants used for repository updates */
431 #define	ADD_ENTRY	0
432 #define	REMOVE_ENTRY	1
433 
434 #define	FAB_REPOSITORY_DIR	"/etc/cfg/fp"
435 #define	FAB_REPOSITORY		"/etc/cfg/fp/fabric_WWN_map"
436 #define	TMP_FAB_REPOSITORY	"/etc/cfg/fp/fabric_WWN_map.tmp"
437 #define	OLD_FAB_REPOSITORY	"/etc/cfg/fp/fabric_WWN_map.old"
438 
439 /* MPXIO VHCI root dir */
440 #define	SCSI_VHCI_ROOT		"/devices/scsi_vhci/"
441 #define	SCSI_VHCI_DRVR		"scsi_vhci"
442 #define	HBA_MAX_RETRIES		10
443 
444 /* Function prototypes */
445 
446 fpcfga_ret_t get_report_lun_data(const char *xport_phys,
447 	const char *dyncomp, int *num_luns, report_lun_resp_t **resp_buf,
448 	struct scsi_extended_sense *sense, int *l_errnop);
449 /* Functions in cfga_cs.c */
450 fpcfga_ret_t
451 dev_change_state(cfga_cmd_t, apid_t *, la_wwn_t *, cfga_flags_t, char **,
452     HBA_HANDLE handle, HBA_PORTATTRIBUTES portAttrs);
453 fpcfga_ret_t
454 fca_change_state(cfga_cmd_t, apid_t *, cfga_flags_t, char **);
455 
456 /* Functions in cfga_rep.c */
457 int update_fabric_wwn_list(int, const char *, char **);
458 
459 fpcfga_ret_t dev_insert(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
460     char **errstring);
461 fpcfga_ret_t dev_replace(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
462     char **errstring);
463 fpcfga_ret_t dev_remove(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
464     char **errstring);
465 fpcfga_ret_t reset_common(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
466     char **errstring);
467 
468 
469 /* List related routines */
470 fpcfga_ret_t do_list(apid_t *apidp, fpcfga_cmd_t cmd,
471     ldata_list_t **ldatalistp, int *nelem, char **errstring);
472 fpcfga_ret_t do_list_FCP_dev(const char *ap_id, uint_t flags, fpcfga_cmd_t cmd,
473 	ldata_list_t **llpp, int *nelemp, char **errstring);
474 fpcfga_ret_t list_ext_postprocess(ldata_list_t **ldatalistp, int nelem,
475     cfga_list_data_t **ap_id_list, int *nlistp, char **errstring);
476 int stat_path_info_node(di_node_t root, void *arg, int *l_errnop);
477 
478 /* Conversion routines */
479 fpcfga_ret_t make_xport_logid(const char *xport_phys, char **xport_logpp,
480     int *l_errnop);
481 fpcfga_ret_t dyn_apid_to_path(const char *xport_phys, const char *dyncomp,
482 	struct luninfo_list **lunlistpp, int *l_errnop);
483 void cvt_lawwn_to_dyncomp(const la_wwn_t *pwwn, char **dyncomp, int *l_errnop);
484 int cvt_dyncomp_to_lawwn(const char *dyncomp, la_wwn_t *port_wwn);
485 fpcfga_ret_t make_dyncomp_from_dinode(const di_node_t node, char **dyncompp,
486 	int *l_errnop);
487 fpcfga_ret_t make_portwwn_luncomp_from_dinode(const di_node_t node,
488 	char **dyncompp, int **luncompp, int *l_errnop);
489 fpcfga_ret_t make_portwwn_luncomp_from_pinode(const di_path_t pinode,
490 	char **dyncompp, int **luncompp, int *l_errnop);
491 fpcfga_ret_t construct_nodepath_from_dinode(const di_node_t node,
492 	char **node_pathp, int *l_errnop);
493 u_longlong_t wwnConversion(uchar_t *wwn);
494 
495 
496 /* Functions in cfga_rcm.c */
497 fpcfga_ret_t fp_rcm_offline(char *, char **, cfga_flags_t);
498 fpcfga_ret_t fp_rcm_online(char *, char **, cfga_flags_t);
499 fpcfga_ret_t fp_rcm_remove(char *, char **, cfga_flags_t);
500 fpcfga_ret_t fp_rcm_suspend(char *, char *, char **, cfga_flags_t);
501 fpcfga_ret_t fp_rcm_resume(char *, char *, char **, cfga_flags_t);
502 fpcfga_ret_t fp_rcm_info(char *, char **, char **);
503 
504 /* Utility routines */
505 fpcfga_ret_t physpath_to_devlink(const char *basedir, char *xport_phys,
506     char **xport_logpp, int *l_errnop, int match_minor);
507 fpcfga_ret_t recurse_dev(const char *basedir, void *arg,
508     fpcfga_recur_t (*fcn)(const char *lpath, void *arg));
509 fpcfga_ret_t apidt_create(const char *ap_id, apid_t *apidp,
510     char **errstring);
511 void apidt_free(apid_t *apidp);
512 cfga_err_t err_cvt(fpcfga_ret_t err);
513 void list_free(ldata_list_t **llpp);
514 int known_state(di_node_t node);
515 
516 fpcfga_ret_t devctl_cmd(const char *ap_id, fpcfga_cmd_t cmd,
517     uint_t *statep, int *l_errnop);
518 fpcfga_ret_t invoke_cmd(const char *func, apid_t *apidt, prompt_t *prp,
519     char **errstring);
520 
521 void cfga_err(char **errstring, int use_errno, ...);
522 void cfga_msg(struct cfga_msg *msgp, ...);
523 char *cfga_str(int append_newline, ...);
524 int msg_idx(msgid_t msgid);
525 fpcfga_ret_t walk_tree(const char *physpath, void *arg, uint_t init_flags,
526     walkarg_t *up, fpcfga_cmd_t cmd, int *l_errnop);
527 int hba_dev_cmp(const char *hba, const char *dev);
528 int dev_cmp(const char *dev1, const char *dev2, int match_minor);
529 char *pathdup(const char *path, int *l_errnop);
530 int getPortAttrsByWWN(HBA_HANDLE handle, HBA_WWN wwn,
531 	HBA_PORTATTRIBUTES *attrs);
532 int getDiscPortAttrs(HBA_HANDLE handle, int portIndex,
533 	int discIndex, HBA_PORTATTRIBUTES *attrs);
534 int getAdapterPortAttrs(HBA_HANDLE handle, int portIndex,
535 	HBA_PORTATTRIBUTES *attrs);
536 int getAdapterAttrs(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES *attrs);
537 fpcfga_ret_t findMatchingAdapterPort(char *portPath,
538 	HBA_HANDLE *matchingHandle, int *matchingPortIndex,
539 	HBA_PORTATTRIBUTES *matchingPortAttrs, char **errstring);
540 
541 extern msgcvt_t str_tbl[];
542 
543 #ifdef __cplusplus
544 }
545 #endif
546 
547 #endif /* _CFGA_FP_H */
548