| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2000 Matthew Jacob |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions, and the following disclaimer, |
| 12 | * without modification, immediately at the beginning of the file. |
| 13 | * 2. The name of the author may not be used to endorse or promote products |
| 14 | * derived from this software without specific prior written permission. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR |
| 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 26 | * SUCH DAMAGE. |
| 27 | */ |
| 28 | |
| 29 | /* |
| 30 | * This file contains definitions only intended for use within |
| 31 | * sys/cam/scsi/scsi_enc*.c, and not in other kernel components. |
| 32 | */ |
| 33 | |
| 34 | #ifndef	__SCSI_ENC_INTERNAL_H__ |
| 35 | #define	__SCSI_ENC_INTERNAL_H__ |
| 36 | |
| 37 | #include <sys/sysctl.h> |
| 38 | |
| 39 | typedef struct enc_element { |
| 40 | 	u_int	 elm_idx;		/* index of element */ |
| 41 | 	uint8_t	 elm_type;		/* element type */ |
| 42 | 	uint8_t	 subenclosure;		/* subenclosure id */ |
| 43 | 	uint8_t	 type_elm_idx;		/* index of element within type */ |
| 44 | 	uint8_t	 svalid;		/* enclosure information valid */ |
| 45 | 	uint8_t	 encstat[4];		/* state && stats */ |
| 46 | 	u_int	 physical_path_len;	/* Length of device path data. */ |
| 47 | 	uint8_t *physical_path;		/* Device physical path data. */ |
| 48 | 	void *elm_private;		/* per-type object data */ |
| 49 | 	uint16_t priv; |
| 50 | } enc_element_t; |
| 51 | |
| 52 | typedef enum { |
| 53 | 	ENC_NONE, |
| 54 | 	ENC_SES, |
| 55 | 	ENC_SES_PASSTHROUGH, |
| 56 | 	ENC_SAFT, |
| 57 | 	ENC_SEMB_SES, |
| 58 | 	ENC_SEMB_SAFT |
| 59 | } enctyp; |
| 60 | |
| 61 | /* Platform Independent Driver Internal Definitions for enclosure devices. */ |
| 62 | typedef struct enc_softc enc_softc_t; |
| 63 | |
| 64 | struct enc_fsm_state; |
| 65 | typedef int fsm_fill_handler_t(enc_softc_t *ssc, |
| 66 | 				struct enc_fsm_state *state, |
| 67 | 				union ccb *ccb, |
| 68 | 				uint8_t *buf); |
| 69 | typedef int fsm_error_handler_t(union ccb *ccb, uint32_t cflags, |
| 70 | 				uint32_t sflags); |
| 71 | typedef int fsm_done_handler_t(enc_softc_t *ssc, |
| 72 | 			 struct enc_fsm_state *state, union ccb *ccb, |
| 73 | 			 uint8_t **bufp, int error, int xfer_len); |
| 74 | |
| 75 | struct enc_fsm_state { |
| 76 | 	const char	 *name; |
| 77 | 	int		 page_code; |
| 78 | 	size_t		 buf_size; |
| 79 | 	uint32_t	 timeout; |
| 80 | 	fsm_fill_handler_t *fill; |
| 81 | 	fsm_done_handler_t *done; |
| 82 | 	fsm_error_handler_t *error; |
| 83 | }; |
| 84 | |
| 85 | typedef int (enc_softc_init_t)(enc_softc_t *); |
| 86 | typedef void (enc_softc_invalidate_t)(enc_softc_t *); |
| 87 | typedef void (enc_softc_cleanup_t)(enc_softc_t *); |
| 88 | typedef int (enc_init_enc_t)(enc_softc_t *); |
| 89 | typedef int (enc_set_enc_status_t)(enc_softc_t *, encioc_enc_status_t, int); |
| 90 | typedef int (enc_get_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int); |
| 91 | typedef int (enc_set_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int); |
| 92 | typedef int (enc_get_elm_desc_t)(enc_softc_t *, encioc_elm_desc_t *); |
| 93 | typedef int (enc_get_elm_devnames_t)(enc_softc_t *, encioc_elm_devnames_t *); |
| 94 | typedef int (enc_handle_string_t)(enc_softc_t *, encioc_string_t *, |
| 95 | 				 unsigned long); |
| 96 | typedef void (enc_device_found_t)(enc_softc_t *); |
| 97 | typedef void (enc_poll_status_t)(enc_softc_t *); |
| 98 | |
| 99 | struct enc_vec { |
| 100 | 	enc_softc_invalidate_t	*softc_invalidate; |
| 101 | 	enc_softc_cleanup_t	*softc_cleanup; |
| 102 | 	enc_init_enc_t		*init_enc; |
| 103 | 	enc_set_enc_status_t	*set_enc_status; |
| 104 | 	enc_get_elm_status_t	*get_elm_status; |
| 105 | 	enc_set_elm_status_t	*set_elm_status; |
| 106 | 	enc_get_elm_desc_t	*get_elm_desc; |
| 107 | 	enc_get_elm_devnames_t	*get_elm_devnames; |
| 108 | 	enc_handle_string_t	*handle_string; |
| 109 | 	enc_device_found_t	*device_found; |
| 110 | 	enc_poll_status_t	*poll_status; |
| 111 | }; |
| 112 | |
| 113 | typedef struct enc_cache { |
| 114 | 	enc_element_t		*elm_map;	/* objects */ |
| 115 | 	int			 nelms;		/* number of objects */ |
| 116 | 	encioc_enc_status_t	 enc_status;	/* overall status */ |
| 117 | 	void			*private;	/* per-type private data */ |
| 118 | } enc_cache_t; |
| 119 | |
| 120 | /* Enclosure instance toplevel structure */ |
| 121 | struct enc_softc { |
| 122 | 	enctyp			 enc_type;	/* type of enclosure */ |
| 123 | 	struct enc_vec		 enc_vec;	/* vector to handlers */ |
| 124 | 	void			*enc_private;	/* per-type private data */ |
| 125 | |
| 126 | 	/** |
| 127 | 	 * "Published" configuration and state data available to |
| 128 | 	 * external consumers. |
| 129 | 	 */ |
| 130 | 	enc_cache_t		 enc_cache; |
| 131 | |
| 132 | 	/** |
| 133 | 	 * Configuration and state data being actively updated |
| 134 | 	 * by the enclosure daemon. |
| 135 | 	 */ |
| 136 | 	enc_cache_t		 enc_daemon_cache; |
| 137 | |
| 138 | 	struct sx		 enc_cache_lock; |
| 139 | 	uint8_t			 enc_flags; |
| 140 | #define	ENC_FLAG_INVALID	0x01 |
| 141 | #define	ENC_FLAG_INITIALIZED	0x02 |
| 142 | #define	ENC_FLAG_SHUTDOWN	0x04 |
| 143 | 	struct cdev		*enc_dev; |
| 144 | 	struct cam_periph	*periph; |
| 145 | 	int			 open_count; |
| 146 | |
| 147 | 	/* Bitmap of pending operations. */ |
| 148 | 	uint32_t		 pending_actions; |
| 149 | |
| 150 | 	/* The action on which the state machine is currently working. */ |
| 151 | 	uint32_t		 current_action; |
| 152 | #define	ENC_UPDATE_NONE		0x00 |
| 153 | #define	ENC_UPDATE_INVALID	0xff |
| 154 | |
| 155 | 	/* Callout for auto-updating enclosure status */ |
| 156 | 	struct callout		 status_updater; |
| 157 | |
| 158 | 	struct proc		*enc_daemon; |
| 159 | |
| 160 | 	struct enc_fsm_state 	*enc_fsm_states; |
| 161 | |
| 162 | #define 	ENC_ANNOUNCE_SZ		400 |
| 163 | 	char			announce_buf[ENC_ANNOUNCE_SZ]; |
| 164 | }; |
| 165 | |
| 166 | static inline enc_cache_t * |
| 167 | enc_other_cache(enc_softc_t *enc, enc_cache_t *primary) |
| 168 | { |
| 169 | 	return (primary == &enc->enc_cache |
| 170 | 	 ? &enc->enc_daemon_cache : &enc->enc_cache); |
| 171 | } |
| 172 | |
| 173 | /* SES Management mode page - SES2r20 Table 59 */ |
| 174 | struct ses_mgmt_mode_page { |
| 175 | 	struct scsi_mode_header_6 header; |
| 176 | 	struct scsi_mode_blk_desc blk_desc; |
| 177 | 	uint8_t byte0; /* ps : 1, spf : 1, page_code : 6 */ |
| 178 | #define SES_MGMT_MODE_PAGE_CODE 0x14 |
| 179 | 	uint8_t length; |
| 180 | #define SES_MGMT_MODE_PAGE_LEN 6 |
| 181 | 	uint8_t reserved[3]; |
| 182 | 	uint8_t byte5; /* reserved : 7, enbltc : 1 */ |
| 183 | #define SES_MGMT_TIMED_COMP_EN 0x1 |
| 184 | 	uint8_t max_comp_time[2]; |
| 185 | }; |
| 186 | |
| 187 | /* Enclosure core interface for sub-drivers */ |
| 188 | int enc_runcmd(struct enc_softc *, char *, int, char *, int *); |
| 189 | void enc_log(struct enc_softc *, const char *, ...); |
| 190 | int enc_error(union ccb *, uint32_t, uint32_t); |
| 191 | void enc_update_request(enc_softc_t *, uint32_t); |
| 192 | |
| 193 | /* SES Native interface */ |
| 194 | enc_softc_init_t	ses_softc_init; |
| 195 | |
| 196 | /* SAF-TE interface */ |
| 197 | enc_softc_init_t	safte_softc_init; |
| 198 | |
| 199 | SYSCTL_DECL(_kern_cam_enc); |
| 200 | extern int enc_verbose; |
| 201 | |
| 202 | /* Helper macros */ |
| 203 | MALLOC_DECLARE(M_SCSIENC); |
| 204 | #define	ENC_CFLAGS		CAM_RETRY_SELTO |
| 205 | #define	ENC_FLAGS		SF_NO_PRINT | SF_RETRY_UA |
| 206 | #define	STRNCMP			strncmp |
| 207 | #define	PRINTF			printf |
| 208 | #define	ENC_LOG			enc_log |
| 209 | #if defined(DEBUG) || defined(ENC_DEBUG) |
| 210 | #define	ENC_DLOG		enc_log |
| 211 | #else |
| 212 | #define	ENC_DLOG		if (0) enc_log |
| 213 | #endif |
| 214 | #define	ENC_VLOG		if (enc_verbose) enc_log |
| 215 | #define	ENC_MALLOC(amt)		malloc(amt, M_SCSIENC, M_NOWAIT) |
| 216 | #define	ENC_MALLOCZ(amt)	malloc(amt, M_SCSIENC, M_ZERO|M_NOWAIT) |
| 217 | /* Cast away const avoiding GCC warnings. */ |
| 218 | #define	ENC_FREE(ptr)		free((void *)((uintptr_t)ptr), M_SCSIENC) |
| 219 | #define	ENC_FREE_AND_NULL(ptr)	do {	\ |
| 220 | 	if (ptr != NULL) {		\ |
| 221 | 		ENC_FREE(ptr);		\ |
| 222 | 		ptr = NULL;		\ |
| 223 | 	}				\ |
| 224 | } while(0) |
| 225 | #define	MEMZERO			bzero |
| 226 | #define	MEMCPY(dest, src, amt)	bcopy(src, dest, amt) |
| 227 | |
| 228 | #endif	/* __SCSI_ENC_INTERNAL_H__ */ |