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 /*
23  * Copyright 2009 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 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #include <stddef.h>
35 #include <locale.h>
36 #include <ctype.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <locale.h>
44 #include <langinfo.h>
45 #include <time.h>
46 #include <stdarg.h>
47 #include <sys/types.h>
48 #include <sys/ioctl.h>
49 #include <sys/dditypes.h>
50 #include <sys/modctl.h>
51 #include <libdevinfo.h>
52 #include <libdevice.h>
53 #include <librcm.h>
54 #include <dirent.h>
55 #include <strings.h>
56 
57 #include <sys/ioctl.h>
58 #include <sys/byteorder.h>
59 #include <sys/scsi/scsi.h>
60 #include <strings.h>
61 #include <sys/vfstab.h>
62 #include <sys/stat.h>
63 #include <sys/mnttab.h>
64 #include <sys/wait.h>
65 #include <signal.h>
66 
67 #include <sys/uio.h>
68 #include <sys/param.h>
69 
70 #include <synch.h>
71 #include <thread.h>
72 
73 #include <limits.h>
74 #include <ftw.h>
75 
76 #define	CFGA_PLUGIN_LIB
77 #include <config_admin.h>
78 
79 #if	!defined(DEBUG)
80 #define	NDEBUG	1
81 #else
82 #undef	NDEBUG
83 #endif
84 
85 #include <assert.h>
86 
87 /* Return/error codes */
88 typedef enum {
89 	SCFGA_ERR = -1,
90 	SCFGA_LIB_ERR = 0,
91 	SCFGA_OK,
92 	SCFGA_NACK,
93 	SCFGA_BUSY,
94 	SCFGA_SYSTEM_BUSY,
95 	SCFGA_APID_NOEXIST,
96 	SCFGA_OPNOTSUPP,
97 	SCFGA_PRIV,
98 	SCFGA_UNLOCKED,
99 	SCFGA_NO_REC,
100 	SCFGA_OP_INTR,
101 	SCFGA_DB_INVAL,
102 	SCFGA_UNKNOWN_ERR
103 } scfga_ret_t;
104 
105 /* Commands used internally */
106 typedef enum {
107 	SCFGA_INVAL_CMD = -1,
108 	SCFGA_DEV_OP = 0,
109 	SCFGA_BUS_OP,
110 	SCFGA_STAT_DEV,
111 	SCFGA_STAT_BUS,
112 	SCFGA_STAT_ALL,
113 	SCFGA_GET_DEVPATH,
114 	SCFGA_INSERT_DEV,
115 	SCFGA_REMOVE_DEV,
116 	SCFGA_REPLACE_DEV,
117 	SCFGA_WALK_NODE,
118 	SCFGA_WALK_MINOR,
119 	SCFGA_WALK_PATH,
120 	SCFGA_BUS_QUIESCE,
121 	SCFGA_BUS_UNQUIESCE,
122 	SCFGA_BUS_GETSTATE,
123 	SCFGA_DEV_GETSTATE,
124 	SCFGA_BUS_CONFIGURE,
125 	SCFGA_BUS_UNCONFIGURE,
126 	SCFGA_DEV_CONFIGURE,
127 	SCFGA_DEV_UNCONFIGURE,
128 	SCFGA_DEV_REMOVE,
129 	SCFGA_LED_DEV,
130 	SCFGA_LOCATOR_DEV,
131 	SCFGA_RESET_DEV,
132 	SCFGA_RESET_BUS,
133 	SCFGA_RESET_ALL,
134 	SCFGA_READ,
135 	SCFGA_WRITE
136 } scfga_cmd_t;
137 
138 typedef enum {
139 	SCFGA_TERMINATE = 0,
140 	SCFGA_CONTINUE
141 } scfga_recur_t;
142 
143 typedef enum {
144 	NODYNCOMP = 1,
145 	DEV_APID,
146 	PATH_APID
147 } dyncomp_t;
148 
149 
150 /* Structures for tree walking code */
151 
152 typedef struct {
153 	uint_t flags;
154 	int (*fcn)(di_node_t node, void *argp);
155 } walk_node_t;
156 
157 typedef struct {
158 	const char *nodetype;
159 	int (*fcn)(di_node_t node, di_minor_t minor, void *argp);
160 } walk_minor_t;
161 
162 typedef union {
163 	walk_node_t	node_args;
164 	walk_minor_t	minor_args;
165 } walkarg_t;
166 
167 typedef struct {
168 	char *phys;
169 	char *log;
170 	scfga_ret_t ret;
171 	int match_minor;
172 	int l_errno;
173 } pathm_t;
174 
175 typedef struct ldata_list {
176 	cfga_list_data_t ldata;
177 	struct ldata_list *next;
178 } ldata_list_t;
179 
180 typedef struct {
181 	struct cfga_confirm	*confp;
182 	struct cfga_msg		*msgp;
183 } prompt_t;
184 
185 typedef struct {
186 	char		*hba_phys;
187 	char		*dyncomp;
188 	dyncomp_t	dyntype;    /* is pathinfo or dev apid? */
189 	char		*path;	    /* for apid with device dyn comp. */
190 	uint_t		flags;
191 } apid_t;
192 
193 /* Private hardware options */
194 #define	OPT_DISABLE_RCM	"disable_rcm"
195 #define	OPT_USE_DIFORCE	"use_diforce"
196 
197 /* apid_t flags */
198 #define	FLAG_DISABLE_RCM	0x01
199 #define	FLAG_USE_DIFORCE	0x02
200 
201 /* internal use for handling pathinfo */
202 #define	FLAG_CLIENT_DEV		0x04
203 
204 /* Message ids */
205 typedef enum {
206 
207 /* ERRORS */
208 ERR_UNKNOWN = -1,
209 ERR_OP_FAILED,
210 ERR_CMD_INVAL,
211 ERR_NOT_BUSAPID,
212 ERR_APID_INVAL,
213 ERR_NOT_BUSOP,
214 ERR_NOT_DEVOP,
215 ERR_UNAVAILABLE,
216 ERR_CTRLR_CRIT,
217 ERR_BUS_GETSTATE,
218 ERR_BUS_NOTCONNECTED,
219 ERR_BUS_CONNECTED,
220 ERR_BUS_QUIESCE,
221 ERR_BUS_UNQUIESCE,
222 ERR_BUS_CONFIGURE,
223 ERR_BUS_UNCONFIGURE,
224 ERR_DEV_CONFIGURE,
225 ERR_DEV_RECONFIGURE,
226 ERR_DEV_UNCONFIGURE,
227 ERR_DEV_REMOVE,
228 ERR_DEV_REPLACE,
229 ERR_DEV_INSERT,
230 ERR_DEV_GETSTATE,
231 ERR_RESET,
232 ERR_LIST,
233 ERR_MAYBE_BUSY,
234 ERR_BUS_DEV_MISMATCH,
235 ERR_VAR_RUN,
236 ERR_FORK,
237 
238 /* Errors with arguments */
239 ERRARG_OPT_INVAL,
240 ERRARG_HWCMD_INVAL,
241 ERRARG_DEVINFO,
242 ERRARG_OPEN,
243 ERRARG_LOCK,
244 ERRARG_QUIESCE_LOCK,
245 
246 /* RCM Errors */
247 ERR_RCM_HANDLE,
248 ERRARG_RCM_SUSPEND,
249 ERRARG_RCM_RESUME,
250 ERRARG_RCM_OFFLINE,
251 ERRARG_RCM_CLIENT_OFFLINE,
252 ERRARG_RCM_ONLINE,
253 ERRARG_RCM_REMOVE,
254 
255 /* Commands */
256 CMD_INSERT_DEV,
257 CMD_REMOVE_DEV,
258 CMD_REPLACE_DEV,
259 CMD_LED_DEV,
260 CMD_LOCATOR_DEV,
261 CMD_RESET_DEV,
262 CMD_RESET_BUS,
263 CMD_RESET_ALL,
264 
265 /* help messages */
266 MSG_HELP_HDR,
267 MSG_HELP_USAGE,
268 
269 /* Hotplug messages */
270 MSG_INSDEV,
271 MSG_RMDEV,
272 MSG_REPLDEV,
273 MSG_WAIT_LOCK,
274 
275 /* Hotplugging confirmation prompts */
276 CONF_QUIESCE_1,
277 CONF_QUIESCE_2,
278 CONF_UNQUIESCE,
279 CONF_NO_QUIESCE,
280 
281 /* Misc. */
282 WARN_DISCONNECT,
283 
284 /* HDD led/locator messages */
285 MSG_LED_HDR,
286 MSG_MISSING_LED_NAME,
287 MSG_MISSING_LED_MODE
288 } msgid_t;
289 
290 typedef enum {
291 	LED_STR_FAULT,
292 	LED_STR_POWER,
293 	LED_STR_ATTN,
294 	LED_STR_ACTIVE,
295 	LED_STR_LOCATOR
296 } led_strid_t;
297 
298 typedef enum {
299 	LED_MODE_OFF,
300 	LED_MODE_ON,
301 	LED_MODE_BLINK,
302 	LED_MODE_FAULTED,
303 	LED_MODE_UNK
304 } led_modeid_t;
305 
306 
307 typedef struct {
308 	msgid_t str_id;
309 	scfga_cmd_t cmd;
310 	scfga_ret_t (*fcn)(const char *, scfga_cmd_t, apid_t *, prompt_t *,
311 	    cfga_flags_t, char **);
312 } hw_cmd_t;
313 
314 typedef struct {
315 	msgid_t msgid;
316 	int nargs;		/* Number of arguments following msgid */
317 	int intl;		/* Flag: if 1, internationalize */
318 	const char *msgstr;
319 } msgcvt_t;
320 
321 
322 #define	SLASH			"/"
323 #define	CFGA_DEV_DIR		"/dev/cfg"
324 #define	DEV_DIR			"/dev"
325 #define	DEVICES_DIR		"/devices"
326 #define	DEV_DSK			"/dev/dsk"
327 #define	DEV_RDSK		"/dev/rdsk"
328 #define	DEV_RMT			"/dev/rmt"
329 #define	DSK_DIR			"dsk"
330 #define	RDSK_DIR		"rdsk"
331 #define	RMT_DIR			"rmt"
332 
333 
334 #define	DYN_SEP			"::"
335 #define	MINOR_SEP		":"
336 #define	PATH_APID_DYN_SEP	","
337 
338 #define	S_FREE(x)	(((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
339 #define	S_STR(x)	(((x) == NULL) ? "" : (x))
340 
341 
342 #define	IS_STUB_NODE(s)	(di_instance(s) == -1 &&	\
343 			    di_nodeid(s) == (DI_PROM_NODEID))
344 
345 #define	GET_MSG_STR(i)		(str_tbl[msg_idx(i)].msgstr)
346 
347 #define	GET_DYN(a)	(((a) != NULL) ? strstr((a), DYN_SEP) : (void *)0)
348 
349 /*
350  * The following macro removes the separator from the dynamic component.
351  */
352 #define	DYN_TO_DYNCOMP(a)	((a) + strlen(DYN_SEP))
353 
354 extern int _scfga_debug;
355 
356 /*
357  * Tracing/debugging macros
358  */
359 #define	CFGA_TRACE1(args)	(void) ((_scfga_debug >= 1) ? fprintf args : 0)
360 #define	CFGA_TRACE2(args)	(void) ((_scfga_debug >= 2) ? fprintf args : 0)
361 #define	CFGA_TRACE3(args)	(void) ((_scfga_debug >= 3) ? fprintf args : 0)
362 
363 /* Function prototypes */
364 
365 /* bus/device ctl routines */
366 scfga_ret_t bus_change_state(cfga_cmd_t state_change_cmd,
367     apid_t *apidp, struct cfga_confirm *confp, cfga_flags_t flags,
368     char **errstring);
369 scfga_ret_t dev_change_state(cfga_cmd_t state_change_cmd,
370     apid_t *apidp, cfga_flags_t flags, char **errstring);
371 scfga_ret_t dev_insert(const char *func, scfga_cmd_t cmd, apid_t *apidp,
372     prompt_t *argsp, cfga_flags_t flags, char **errstring);
373 scfga_ret_t dev_replace(const char *func, scfga_cmd_t cmd, apid_t *apidp,
374     prompt_t *argsp, cfga_flags_t flags, char **errstring);
375 scfga_ret_t dev_remove(const char *func, scfga_cmd_t cmd, apid_t *apidp,
376     prompt_t *argsp, cfga_flags_t flags, char **errstring);
377 scfga_ret_t reset_common(const char *func, scfga_cmd_t cmd, apid_t *apidp,
378     prompt_t *argsp, cfga_flags_t flags, char **errstring);
379 scfga_ret_t dev_led(const char *func, scfga_cmd_t cmd, apid_t *apidp,
380     prompt_t *argsp, cfga_flags_t flags, char **errstring);
381 scfga_ret_t plat_dev_led(const char *func, scfga_cmd_t cmd, apid_t *apidp,
382     prompt_t *argsp, cfga_flags_t flags, char **errstring);
383 
384 
385 /* List related routines */
386 scfga_ret_t do_list(apid_t *apidp, scfga_cmd_t cmd,
387     ldata_list_t **llpp, int *nelem, char **errstring);
388 scfga_ret_t list_ext_postprocess(ldata_list_t **llpp, int nelem,
389     cfga_list_data_t **ap_id_list, int *nlistp, char **errstring);
390 int stat_path_info(di_node_t root, void *arg, int *l_errnop);
391 
392 
393 /* Conversion routines */
394 scfga_ret_t make_hba_logid(const char *hba_phys, char **hba_logpp,
395     int *l_errnop);
396 scfga_ret_t apid_to_path(const char *hba_phys, const char *dyncomp,
397     char **pathpp, int *l_errnop);
398 scfga_ret_t make_dyncomp(di_node_t node, const char *physpath,
399     char **dyncompp, int *l_errnop);
400 scfga_ret_t make_path_dyncomp(di_path_t path, char **dyncomp, int *l_errnop);
401 
402 
403 /* RCM routines */
404 scfga_ret_t scsi_rcm_suspend(char **rsrclist, char **errstring,
405     cfga_flags_t flags, int pflag);
406 scfga_ret_t scsi_rcm_resume(char **rsrclist, char **errstring,
407     cfga_flags_t flags, int pflag);
408 scfga_ret_t scsi_rcm_offline(char **rsrclist, char **errstring,
409     cfga_flags_t flags);
410 scfga_ret_t scsi_rcm_online(char **rsrclist, char **errstring,
411     cfga_flags_t flags);
412 scfga_ret_t scsi_rcm_remove(char **rsrclist, char **errstring,
413     cfga_flags_t flags);
414 
415 
416 /* Utility routines */
417 scfga_ret_t physpath_to_devlink(char *physpath, char **linkpp, int *l_errnop,
418     int match_minor);
419 scfga_ret_t apidt_create(const char *ap_id, apid_t *apidp,
420     char **errstring);
421 void apidt_free(apid_t *apidp);
422 cfga_err_t err_cvt(scfga_ret_t err);
423 void list_free(ldata_list_t **llpp);
424 int known_state(di_node_t node);
425 scfga_ret_t devctl_cmd(const char *ap_id, scfga_cmd_t cmd,
426     uint_t *statep, int *l_errnop);
427 scfga_ret_t path_apid_state_change(apid_t *apidp, scfga_cmd_t cmd,
428     cfga_flags_t flags, char **errstring, int *l_errnop, msgid_t errid);
429 scfga_ret_t invoke_cmd(const char *func, apid_t *apidt, prompt_t *prp,
430     cfga_flags_t flags, char **errstring);
431 
432 void cfga_err(char **errstring, int use_errno, ...);
433 void cfga_msg(struct cfga_msg *msgp, ...);
434 void cfga_led_msg(struct cfga_msg *msgp, apid_t *apidp, led_strid_t,
435     led_modeid_t);
436 char *cfga_str(int append_newline, ...);
437 int msg_idx(msgid_t msgid);
438 scfga_ret_t walk_tree(const char *physpath, void *arg, uint_t init_flags,
439     walkarg_t *up, scfga_cmd_t cmd, int *l_errnop);
440 int hba_dev_cmp(const char *hba, const char *dev);
441 int dev_cmp(const char *dev1, const char *dev2, int match_minor);
442 
443 extern msgcvt_t str_tbl[];
444 
445 #ifdef __cplusplus
446 }
447 #endif
448 
449 #endif /* _CFGA_SCSI_H */
450