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
32extern "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 */
94typedef 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 */
122typedef 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
151typedef enum {
152	FPCFGA_TERMINATE = 0,
153	FPCFGA_CONTINUE
154} fpcfga_recur_t;
155
156
157/* Structures for tree walking code */
158
159typedef struct {
160	uint_t flags;
161	int (*fcn)(di_node_t node, void *argp);
162} walk_node_t;
163
164typedef struct {
165	const char *nodetype;
166	int (*fcn)(di_node_t node, di_minor_t minor, void *argp);
167} walk_minor_t;
168
169typedef union {
170	walk_node_t	node_args;
171	walk_minor_t	minor_args;
172} walkmode_t;
173
174typedef struct {
175	uint_t flags;
176	walkmode_t walkmode;
177} walkarg_t;
178
179typedef struct {
180	char *phys;
181	char *log;
182	fpcfga_ret_t ret;
183	int match_minor;
184	int l_errno;
185} pathm_t;
186
187typedef struct ldata_list {
188	cfga_list_data_t ldata;
189	struct ldata_list *next;
190} ldata_list_t;
191
192typedef struct {
193	struct cfga_confirm	*confp;
194	struct cfga_msg		*msgp;
195} prompt_t;
196
197typedef 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
205typedef 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
226typedef 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 */
267typedef enum {
268
269/* ERRORS */
270ERR_UNKNOWN = -1,
271ERR_OP_FAILED,
272ERR_CMD_INVAL,
273ERR_NOT_BUSAPID,
274ERR_APID_INVAL,
275ERR_NOT_BUSOP,
276ERR_NOT_DEVOP,
277ERR_UNAVAILABLE,
278ERR_CTRLR_CRIT,
279ERR_BUS_GETSTATE,
280ERR_BUS_NOTCONNECTED,
281ERR_BUS_CONNECTED,
282ERR_BUS_QUIESCE,
283ERR_BUS_UNQUIESCE,
284ERR_BUS_CONFIGURE,
285ERR_BUS_UNCONFIGURE,
286ERR_DEV_CONFIGURE,
287ERR_DEV_UNCONFIGURE,
288ERR_FCA_CONFIGURE,
289ERR_FCA_UNCONFIGURE,
290ERR_DEV_REPLACE,
291ERR_DEV_INSERT,
292ERR_DEV_GETSTATE,
293ERR_RESET,
294ERR_LIST,
295ERR_FC,
296ERR_FC_GET_DEVLIST,
297ERR_FC_GET_FIRST_DEV,
298ERR_FC_GET_NEXT_DEV,
299ERRARG_FC_DEV_MAP_INIT,
300ERRARG_FC_PROP_LOOKUP_BYTES,
301ERRARG_FC_INQUIRY,
302ERRARG_FC_REP_LUNS,
303ERRARG_FC_TOPOLOGY,
304ERRARG_PATH_TOO_LONG,
305ERRARG_INVALID_PATH,
306ERRARG_OPENDIR,
307ERRARG_VHCI_GET_PATHLIST,
308ERRARG_XPORT_NOT_IN_PHCI_LIST,
309ERR_SIG_STATE,
310ERR_MAYBE_BUSY,
311ERR_BUS_DEV_MISMATCH,
312ERR_GET_DEVLIST,
313ERR_MEM_ALLOC,
314ERR_DEVCTL_OFFLINE,
315ERR_UPD_REP,
316ERR_CONF_OK_UPD_REP,
317ERR_UNCONF_OK_UPD_REP,
318ERR_PARTIAL_SUCCESS,
319ERR_HBA_LOAD_LIBRARY,
320ERR_MATCHING_HBA_PORT,
321ERR_NO_ADAPTER_FOUND,
322
323/* Errors with arguments */
324ERRARG_OPT_INVAL,
325ERRARG_HWCMD_INVAL,
326ERRARG_DEVINFO,
327ERRARG_NOT_IN_DEVLIST,
328ERRARG_NOT_IN_DEVINFO,
329ERRARG_DI_GET_PROP,
330ERRARG_DC_DDEF_ALLOC,
331ERRARG_DC_BYTE_ARRAY,
332ERRARG_DC_BUS_ACQUIRE,
333ERRARG_BUS_DEV_CREATE,
334ERRARG_BUS_DEV_CREATE_UNKNOWN,
335ERRARG_DEV_ACQUIRE,
336ERRARG_DEV_REMOVE,
337
338/* RCM Errors */
339ERR_RCM_HANDLE,
340ERRARG_RCM_SUSPEND,
341ERRARG_RCM_RESUME,
342ERRARG_RCM_OFFLINE,
343ERRARG_RCM_ONLINE,
344ERRARG_RCM_REMOVE,
345ERRARG_RCM_INFO,
346
347/* Commands */
348CMD_INSERT_DEV,
349CMD_REMOVE_DEV,
350CMD_REPLACE_DEV,
351CMD_RESET_DEV,
352CMD_RESET_BUS,
353CMD_RESET_ALL,
354
355/* help messages */
356MSG_HELP_HDR,
357MSG_HELP_USAGE,
358
359/* Hotplug messages */
360MSG_INSDEV,
361MSG_RMDEV,
362MSG_REPLDEV,
363
364/* Hotplugging confirmation prompts */
365CONF_QUIESCE_1,
366CONF_QUIESCE_2,
367CONF_UNQUIESCE,
368
369/* Misc. */
370WARN_DISCONNECT
371} msgid_t;
372
373typedef 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
379typedef 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
446fpcfga_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 */
450fpcfga_ret_t
451dev_change_state(cfga_cmd_t, apid_t *, la_wwn_t *, cfga_flags_t, char **,
452    HBA_HANDLE handle, HBA_PORTATTRIBUTES portAttrs);
453fpcfga_ret_t
454fca_change_state(cfga_cmd_t, apid_t *, cfga_flags_t, char **);
455
456/* Functions in cfga_rep.c */
457int update_fabric_wwn_list(int, const char *, char **);
458
459fpcfga_ret_t dev_insert(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
460    char **errstring);
461fpcfga_ret_t dev_replace(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
462    char **errstring);
463fpcfga_ret_t dev_remove(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
464    char **errstring);
465fpcfga_ret_t reset_common(fpcfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
466    char **errstring);
467
468
469/* List related routines */
470fpcfga_ret_t do_list(apid_t *apidp, fpcfga_cmd_t cmd,
471    ldata_list_t **ldatalistp, int *nelem, char **errstring);
472fpcfga_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);
474fpcfga_ret_t list_ext_postprocess(ldata_list_t **ldatalistp, int nelem,
475    cfga_list_data_t **ap_id_list, int *nlistp, char **errstring);
476int stat_path_info_node(di_node_t root, void *arg, int *l_errnop);
477
478/* Conversion routines */
479fpcfga_ret_t make_xport_logid(const char *xport_phys, char **xport_logpp,
480    int *l_errnop);
481fpcfga_ret_t dyn_apid_to_path(const char *xport_phys, const char *dyncomp,
482	struct luninfo_list **lunlistpp, int *l_errnop);
483void cvt_lawwn_to_dyncomp(const la_wwn_t *pwwn, char **dyncomp, int *l_errnop);
484int cvt_dyncomp_to_lawwn(const char *dyncomp, la_wwn_t *port_wwn);
485fpcfga_ret_t make_dyncomp_from_dinode(const di_node_t node, char **dyncompp,
486	int *l_errnop);
487fpcfga_ret_t make_portwwn_luncomp_from_dinode(const di_node_t node,
488	char **dyncompp, int **luncompp, int *l_errnop);
489fpcfga_ret_t make_portwwn_luncomp_from_pinode(const di_path_t pinode,
490	char **dyncompp, int **luncompp, int *l_errnop);
491fpcfga_ret_t construct_nodepath_from_dinode(const di_node_t node,
492	char **node_pathp, int *l_errnop);
493u_longlong_t wwnConversion(uchar_t *wwn);
494
495
496/* Functions in cfga_rcm.c */
497fpcfga_ret_t fp_rcm_offline(char *, char **, cfga_flags_t);
498fpcfga_ret_t fp_rcm_online(char *, char **, cfga_flags_t);
499fpcfga_ret_t fp_rcm_remove(char *, char **, cfga_flags_t);
500fpcfga_ret_t fp_rcm_suspend(char *, char *, char **, cfga_flags_t);
501fpcfga_ret_t fp_rcm_resume(char *, char *, char **, cfga_flags_t);
502fpcfga_ret_t fp_rcm_info(char *, char **, char **);
503
504/* Utility routines */
505fpcfga_ret_t physpath_to_devlink(const char *basedir, char *xport_phys,
506    char **xport_logpp, int *l_errnop, int match_minor);
507fpcfga_ret_t recurse_dev(const char *basedir, void *arg,
508    fpcfga_recur_t (*fcn)(const char *lpath, void *arg));
509fpcfga_ret_t apidt_create(const char *ap_id, apid_t *apidp,
510    char **errstring);
511void apidt_free(apid_t *apidp);
512cfga_err_t err_cvt(fpcfga_ret_t err);
513void list_free(ldata_list_t **llpp);
514int known_state(di_node_t node);
515
516fpcfga_ret_t devctl_cmd(const char *ap_id, fpcfga_cmd_t cmd,
517    uint_t *statep, int *l_errnop);
518fpcfga_ret_t invoke_cmd(const char *func, apid_t *apidt, prompt_t *prp,
519    char **errstring);
520
521void cfga_err(char **errstring, int use_errno, ...);
522void cfga_msg(struct cfga_msg *msgp, ...);
523char *cfga_str(int append_newline, ...);
524int msg_idx(msgid_t msgid);
525fpcfga_ret_t walk_tree(const char *physpath, void *arg, uint_t init_flags,
526    walkarg_t *up, fpcfga_cmd_t cmd, int *l_errnop);
527int hba_dev_cmp(const char *hba, const char *dev);
528int dev_cmp(const char *dev1, const char *dev2, int match_minor);
529char *pathdup(const char *path, int *l_errnop);
530int getPortAttrsByWWN(HBA_HANDLE handle, HBA_WWN wwn,
531	HBA_PORTATTRIBUTES *attrs);
532int getDiscPortAttrs(HBA_HANDLE handle, int portIndex,
533	int discIndex, HBA_PORTATTRIBUTES *attrs);
534int getAdapterPortAttrs(HBA_HANDLE handle, int portIndex,
535	HBA_PORTATTRIBUTES *attrs);
536int getAdapterAttrs(HBA_HANDLE handle, HBA_ADAPTERATTRIBUTES *attrs);
537fpcfga_ret_t findMatchingAdapterPort(char *portPath,
538	HBA_HANDLE *matchingHandle, int *matchingPortIndex,
539	HBA_PORTATTRIBUTES *matchingPortAttrs, char **errstring);
540
541extern msgcvt_t str_tbl[];
542
543#ifdef __cplusplus
544}
545#endif
546
547#endif /* _CFGA_FP_H */
548