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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _CFGA_SCSI_H
28 #define	_CFGA_SCSI_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #include <stddef.h>
37 #include <locale.h>
38 #include <ctype.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <locale.h>
46 #include <langinfo.h>
47 #include <time.h>
48 #include <stdarg.h>
49 #include <sys/types.h>
50 #include <sys/ioctl.h>
51 #include <sys/dditypes.h>
52 #include <sys/modctl.h>
53 #include <libdevinfo.h>
54 #include <libdevice.h>
55 #include <librcm.h>
56 #include <dirent.h>
57 #include <strings.h>
58 
59 #include <sys/ioctl.h>
60 #include <sys/byteorder.h>
61 #include <sys/scsi/scsi.h>
62 #include <strings.h>
63 #include <sys/vfstab.h>
64 #include <sys/stat.h>
65 #include <sys/mnttab.h>
66 #include <sys/wait.h>
67 #include <signal.h>
68 
69 #include <sys/uio.h>
70 #include <sys/param.h>
71 
72 #include <synch.h>
73 #include <thread.h>
74 
75 #include <limits.h>
76 #include <ftw.h>
77 
78 #define	CFGA_PLUGIN_LIB
79 #include <config_admin.h>
80 
81 #if	!defined(DEBUG)
82 #define	NDEBUG	1
83 #else
84 #undef	NDEBUG
85 #endif
86 
87 #include <assert.h>
88 
89 /* Return/error codes */
90 typedef enum {
91 	SCFGA_ERR = -1,
92 	SCFGA_LIB_ERR = 0,
93 	SCFGA_OK,
94 	SCFGA_NACK,
95 	SCFGA_BUSY,
96 	SCFGA_SYSTEM_BUSY,
97 	SCFGA_APID_NOEXIST,
98 	SCFGA_OPNOTSUPP,
99 	SCFGA_PRIV,
100 	SCFGA_UNLOCKED,
101 	SCFGA_NO_REC,
102 	SCFGA_OP_INTR,
103 	SCFGA_DB_INVAL,
104 	SCFGA_UNKNOWN_ERR
105 } scfga_ret_t;
106 
107 /* Commands used internally */
108 typedef enum {
109 	SCFGA_INVAL_CMD = -1,
110 	SCFGA_DEV_OP = 0,
111 	SCFGA_BUS_OP,
112 	SCFGA_STAT_DEV,
113 	SCFGA_STAT_BUS,
114 	SCFGA_STAT_ALL,
115 	SCFGA_GET_DEVPATH,
116 	SCFGA_INSERT_DEV,
117 	SCFGA_REMOVE_DEV,
118 	SCFGA_REPLACE_DEV,
119 	SCFGA_WALK_NODE,
120 	SCFGA_WALK_MINOR,
121 	SCFGA_BUS_QUIESCE,
122 	SCFGA_BUS_UNQUIESCE,
123 	SCFGA_BUS_GETSTATE,
124 	SCFGA_DEV_GETSTATE,
125 	SCFGA_BUS_CONFIGURE,
126 	SCFGA_BUS_UNCONFIGURE,
127 	SCFGA_DEV_CONFIGURE,
128 	SCFGA_DEV_UNCONFIGURE,
129 	SCFGA_DEV_REMOVE,
130 	SCFGA_RESET_DEV,
131 	SCFGA_RESET_BUS,
132 	SCFGA_RESET_ALL,
133 	SCFGA_READ,
134 	SCFGA_WRITE
135 } scfga_cmd_t;
136 
137 typedef enum {
138 	SCFGA_TERMINATE = 0,
139 	SCFGA_CONTINUE
140 } scfga_recur_t;
141 
142 
143 /* Structures for tree walking code */
144 
145 typedef struct {
146 	uint_t flags;
147 	int (*fcn)(di_node_t node, void *argp);
148 } walk_node_t;
149 
150 typedef struct {
151 	const char *nodetype;
152 	int (*fcn)(di_node_t node, di_minor_t minor, void *argp);
153 } walk_minor_t;
154 
155 typedef union {
156 	walk_node_t	node_args;
157 	walk_minor_t	minor_args;
158 } walkarg_t;
159 
160 typedef struct {
161 	char *phys;
162 	char *log;
163 	scfga_ret_t ret;
164 	int match_minor;
165 	int l_errno;
166 } pathm_t;
167 
168 typedef struct ldata_list {
169 	cfga_list_data_t ldata;
170 	struct ldata_list *next;
171 } ldata_list_t;
172 
173 typedef struct {
174 	struct cfga_confirm	*confp;
175 	struct cfga_msg		*msgp;
176 } prompt_t;
177 
178 typedef struct {
179 	char		*hba_phys;
180 	char		*dyncomp;
181 	char		*path;
182 	uint_t		flags;
183 } apid_t;
184 
185 /* Private hardware options */
186 #define	OPT_DISABLE_RCM	"disable_rcm"
187 #define	OPT_USE_DIFORCE	"use_diforce"
188 
189 /* apid_t flags */
190 #define	FLAG_DISABLE_RCM	0x01
191 #define	FLAG_USE_DIFORCE	0x02
192 
193 /* Message ids */
194 typedef enum {
195 
196 /* ERRORS */
197 ERR_UNKNOWN = -1,
198 ERR_OP_FAILED,
199 ERR_CMD_INVAL,
200 ERR_NOT_BUSAPID,
201 ERR_APID_INVAL,
202 ERR_NOT_BUSOP,
203 ERR_NOT_DEVOP,
204 ERR_UNAVAILABLE,
205 ERR_CTRLR_CRIT,
206 ERR_BUS_GETSTATE,
207 ERR_BUS_NOTCONNECTED,
208 ERR_BUS_CONNECTED,
209 ERR_BUS_QUIESCE,
210 ERR_BUS_UNQUIESCE,
211 ERR_BUS_CONFIGURE,
212 ERR_BUS_UNCONFIGURE,
213 ERR_DEV_CONFIGURE,
214 ERR_DEV_RECONFIGURE,
215 ERR_DEV_UNCONFIGURE,
216 ERR_DEV_REMOVE,
217 ERR_DEV_REPLACE,
218 ERR_DEV_INSERT,
219 ERR_DEV_GETSTATE,
220 ERR_RESET,
221 ERR_LIST,
222 ERR_MAYBE_BUSY,
223 ERR_BUS_DEV_MISMATCH,
224 ERR_VAR_RUN,
225 ERR_FORK,
226 
227 /* Errors with arguments */
228 ERRARG_OPT_INVAL,
229 ERRARG_HWCMD_INVAL,
230 ERRARG_DEVINFO,
231 ERRARG_OPEN,
232 ERRARG_LOCK,
233 ERRARG_QUIESCE_LOCK,
234 
235 /* RCM Errors */
236 ERR_RCM_HANDLE,
237 ERRARG_RCM_SUSPEND,
238 ERRARG_RCM_RESUME,
239 ERRARG_RCM_OFFLINE,
240 ERRARG_RCM_ONLINE,
241 ERRARG_RCM_REMOVE,
242 
243 /* Commands */
244 CMD_INSERT_DEV,
245 CMD_REMOVE_DEV,
246 CMD_REPLACE_DEV,
247 CMD_RESET_DEV,
248 CMD_RESET_BUS,
249 CMD_RESET_ALL,
250 
251 /* help messages */
252 MSG_HELP_HDR,
253 MSG_HELP_USAGE,
254 
255 /* Hotplug messages */
256 MSG_INSDEV,
257 MSG_RMDEV,
258 MSG_REPLDEV,
259 MSG_WAIT_LOCK,
260 
261 /* Hotplugging confirmation prompts */
262 CONF_QUIESCE_1,
263 CONF_QUIESCE_2,
264 CONF_UNQUIESCE,
265 CONF_NO_QUIESCE,
266 
267 /* Misc. */
268 WARN_DISCONNECT
269 } msgid_t;
270 
271 typedef struct {
272 	msgid_t str_id;
273 	scfga_cmd_t cmd;
274 	scfga_ret_t (*fcn)(scfga_cmd_t, apid_t *, prompt_t *, cfga_flags_t,
275 	    char **);
276 } hw_cmd_t;
277 
278 typedef struct {
279 	msgid_t msgid;
280 	int nargs;		/* Number of arguments following msgid */
281 	int intl;		/* Flag: if 1, internationalize */
282 	const char *msgstr;
283 } msgcvt_t;
284 
285 
286 #define	SLASH			"/"
287 #define	CFGA_DEV_DIR		"/dev/cfg"
288 #define	DEV_DIR			"/dev"
289 #define	DEVICES_DIR		"/devices"
290 #define	DEV_DSK			"/dev/dsk"
291 #define	DEV_RDSK		"/dev/rdsk"
292 #define	DEV_RMT			"/dev/rmt"
293 #define	DSK_DIR			"dsk"
294 #define	RDSK_DIR		"rdsk"
295 #define	RMT_DIR			"rmt"
296 
297 
298 #define	DYN_SEP			"::"
299 #define	MINOR_SEP		":"
300 
301 #define	S_FREE(x)	(((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
302 #define	S_STR(x)	(((x) == NULL) ? "" : (x))
303 
304 
305 #define	IS_STUB_NODE(s)	(di_instance(s) == -1 &&	\
306 			    di_nodeid(s) == (DI_PROM_NODEID))
307 
308 #define	GET_MSG_STR(i)		(str_tbl[msg_idx(i)].msgstr)
309 
310 #define	GET_DYN(a)	(((a) != NULL) ? strstr((a), DYN_SEP) : (void *)0)
311 
312 /*
313  * The following macro removes the separator from the dynamic component.
314  */
315 #define	DYN_TO_DYNCOMP(a)	((a) + strlen(DYN_SEP))
316 
317 extern int _scfga_debug;
318 
319 /*
320  * Tracing/debugging macros
321  */
322 #define	CFGA_TRACE1(args)	(void) ((_scfga_debug >= 1) ? fprintf args : 0)
323 #define	CFGA_TRACE2(args)	(void) ((_scfga_debug >= 2) ? fprintf args : 0)
324 #define	CFGA_TRACE3(args)	(void) ((_scfga_debug >= 3) ? fprintf args : 0)
325 
326 /* Function prototypes */
327 
328 /* bus/device ctl routines */
329 scfga_ret_t bus_change_state(cfga_cmd_t state_change_cmd,
330     apid_t *apidp, struct cfga_confirm *confp, cfga_flags_t flags,
331     char **errstring);
332 scfga_ret_t dev_change_state(cfga_cmd_t state_change_cmd,
333     apid_t *apidp, cfga_flags_t flags, char **errstring);
334 scfga_ret_t dev_insert(scfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
335     cfga_flags_t flags, char **errstring);
336 scfga_ret_t dev_replace(scfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
337     cfga_flags_t flags, char **errstring);
338 scfga_ret_t dev_remove(scfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
339     cfga_flags_t flags, char **errstring);
340 scfga_ret_t reset_common(scfga_cmd_t cmd, apid_t *apidp, prompt_t *argsp,
341     cfga_flags_t flags, char **errstring);
342 
343 
344 /* List related routines */
345 scfga_ret_t do_list(apid_t *apidp, scfga_cmd_t cmd,
346     ldata_list_t **llpp, int *nelem, char **errstring);
347 scfga_ret_t list_ext_postprocess(ldata_list_t **llpp, int nelem,
348     cfga_list_data_t **ap_id_list, int *nlistp, char **errstring);
349 
350 
351 /* Conversion routines */
352 scfga_ret_t make_hba_logid(const char *hba_phys, char **hba_logpp,
353     int *l_errnop);
354 scfga_ret_t apid_to_path(const char *hba_phys, const char *dyncomp,
355     char **pathpp, int *l_errnop);
356 scfga_ret_t make_dyncomp(di_node_t node, const char *physpath,
357     char **dyncompp, int *l_errnop);
358 
359 
360 /* RCM routines */
361 scfga_ret_t scsi_rcm_suspend(char **rsrclist, char **errstring,
362     cfga_flags_t flags, int pflag);
363 scfga_ret_t scsi_rcm_resume(char **rsrclist, char **errstring,
364     cfga_flags_t flags, int pflag);
365 scfga_ret_t scsi_rcm_offline(char **rsrclist, char **errstring,
366     cfga_flags_t flags);
367 scfga_ret_t scsi_rcm_online(char **rsrclist, char **errstring,
368     cfga_flags_t flags);
369 scfga_ret_t scsi_rcm_remove(char **rsrclist, char **errstring,
370     cfga_flags_t flags);
371 
372 
373 /* Utility routines */
374 scfga_ret_t physpath_to_devlink(char *physpath, char **linkpp, int *l_errnop,
375     int match_minor);
376 scfga_ret_t apidt_create(const char *ap_id, apid_t *apidp,
377     char **errstring);
378 void apidt_free(apid_t *apidp);
379 cfga_err_t err_cvt(scfga_ret_t err);
380 void list_free(ldata_list_t **llpp);
381 int known_state(di_node_t node);
382 scfga_ret_t devctl_cmd(const char *ap_id, scfga_cmd_t cmd,
383     uint_t *statep, int *l_errnop);
384 scfga_ret_t invoke_cmd(const char *func, apid_t *apidt, prompt_t *prp,
385     cfga_flags_t flags, char **errstring);
386 
387 void cfga_err(char **errstring, int use_errno, ...);
388 void cfga_msg(struct cfga_msg *msgp, ...);
389 char *cfga_str(int append_newline, ...);
390 int msg_idx(msgid_t msgid);
391 scfga_ret_t walk_tree(const char *physpath, void *arg, uint_t init_flags,
392     walkarg_t *up, scfga_cmd_t cmd, int *l_errnop);
393 int hba_dev_cmp(const char *hba, const char *dev);
394 int dev_cmp(const char *dev1, const char *dev2, int match_minor);
395 
396 extern msgcvt_t str_tbl[];
397 
398 #ifdef __cplusplus
399 }
400 #endif
401 
402 #endif /* _CFGA_SCSI_H */
403