xref: /freebsd/sys/cam/scsi/scsi_enc_safte.c (revision 2ffd30f7ee15c87ee092cbac6a4438bcb3af923c)
1f6ad3f23SAlexander Motin /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3bec9534dSPedro F. Giffuni  *
4f6ad3f23SAlexander Motin  * Copyright (c) 2000 Matthew Jacob
5f6ad3f23SAlexander Motin  * All rights reserved.
6f6ad3f23SAlexander Motin  *
7f6ad3f23SAlexander Motin  * Redistribution and use in source and binary forms, with or without
8f6ad3f23SAlexander Motin  * modification, are permitted provided that the following conditions
9f6ad3f23SAlexander Motin  * are met:
10f6ad3f23SAlexander Motin  * 1. Redistributions of source code must retain the above copyright
11f6ad3f23SAlexander Motin  *    notice, this list of conditions, and the following disclaimer,
12f6ad3f23SAlexander Motin  *    without modification, immediately at the beginning of the file.
13f6ad3f23SAlexander Motin  * 2. The name of the author may not be used to endorse or promote products
14f6ad3f23SAlexander Motin  *    derived from this software without specific prior written permission.
15f6ad3f23SAlexander Motin  *
16f6ad3f23SAlexander Motin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17f6ad3f23SAlexander Motin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18f6ad3f23SAlexander Motin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19f6ad3f23SAlexander Motin  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20f6ad3f23SAlexander Motin  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21f6ad3f23SAlexander Motin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22f6ad3f23SAlexander Motin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23f6ad3f23SAlexander Motin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24f6ad3f23SAlexander Motin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25f6ad3f23SAlexander Motin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26f6ad3f23SAlexander Motin  * SUCH DAMAGE.
27f6ad3f23SAlexander Motin  */
28f6ad3f23SAlexander Motin 
29f6ad3f23SAlexander Motin #include <sys/param.h>
30f6ad3f23SAlexander Motin 
31f6ad3f23SAlexander Motin #include <sys/conf.h>
32f6ad3f23SAlexander Motin #include <sys/errno.h>
33f6ad3f23SAlexander Motin #include <sys/kernel.h>
34f6ad3f23SAlexander Motin #include <sys/malloc.h>
35f6ad3f23SAlexander Motin #include <sys/mutex.h>
36f6ad3f23SAlexander Motin #include <sys/queue.h>
37f6ad3f23SAlexander Motin #include <sys/sx.h>
38f6ad3f23SAlexander Motin #include <sys/systm.h>
39f6ad3f23SAlexander Motin #include <sys/sysctl.h>
40f6ad3f23SAlexander Motin #include <sys/types.h>
41f6ad3f23SAlexander Motin 
42f6ad3f23SAlexander Motin #include <cam/cam.h>
43f6ad3f23SAlexander Motin #include <cam/cam_ccb.h>
44f6ad3f23SAlexander Motin #include <cam/cam_periph.h>
45f6ad3f23SAlexander Motin 
46f6ad3f23SAlexander Motin #include <cam/scsi/scsi_enc.h>
47f6ad3f23SAlexander Motin #include <cam/scsi/scsi_enc_internal.h>
48f6ad3f23SAlexander Motin #include <cam/scsi/scsi_message.h>
49f6ad3f23SAlexander Motin 
50f6ad3f23SAlexander Motin /*
51f6ad3f23SAlexander Motin  * SAF-TE Type Device Emulation
52f6ad3f23SAlexander Motin  */
53f6ad3f23SAlexander Motin 
54f6ad3f23SAlexander Motin static int safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag);
55f6ad3f23SAlexander Motin 
56f6ad3f23SAlexander Motin #define	ALL_ENC_STAT (SES_ENCSTAT_CRITICAL | SES_ENCSTAT_UNRECOV | \
57f6ad3f23SAlexander Motin 	SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
58f6ad3f23SAlexander Motin /*
59f6ad3f23SAlexander Motin  * SAF-TE specific defines- Mandatory ones only...
60f6ad3f23SAlexander Motin  */
61f6ad3f23SAlexander Motin 
62f6ad3f23SAlexander Motin /*
63f6ad3f23SAlexander Motin  * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
64f6ad3f23SAlexander Motin  */
65f6ad3f23SAlexander Motin #define	SAFTE_RD_RDCFG	0x00	/* read enclosure configuration */
66f6ad3f23SAlexander Motin #define	SAFTE_RD_RDESTS	0x01	/* read enclosure status */
67f6ad3f23SAlexander Motin #define	SAFTE_RD_RDDSTS	0x04	/* read drive slot status */
68f6ad3f23SAlexander Motin #define	SAFTE_RD_RDGFLG	0x05	/* read global flags */
69f6ad3f23SAlexander Motin 
70f6ad3f23SAlexander Motin /*
71f6ad3f23SAlexander Motin  * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
72f6ad3f23SAlexander Motin  */
73f6ad3f23SAlexander Motin #define	SAFTE_WT_DSTAT	0x10	/* write device slot status */
74f6ad3f23SAlexander Motin #define	SAFTE_WT_SLTOP	0x12	/* perform slot operation */
75f6ad3f23SAlexander Motin #define	SAFTE_WT_FANSPD	0x13	/* set fan speed */
76f6ad3f23SAlexander Motin #define	SAFTE_WT_ACTPWS	0x14	/* turn on/off power supply */
77f6ad3f23SAlexander Motin #define	SAFTE_WT_GLOBAL	0x15	/* send global command */
78f6ad3f23SAlexander Motin 
79f6ad3f23SAlexander Motin #define	SAFT_SCRATCH	64
80f6ad3f23SAlexander Motin #define	SCSZ		0x8000
81f6ad3f23SAlexander Motin 
82f6ad3f23SAlexander Motin typedef enum {
83f6ad3f23SAlexander Motin 	SAFTE_UPDATE_NONE,
84f6ad3f23SAlexander Motin 	SAFTE_UPDATE_READCONFIG,
85f6ad3f23SAlexander Motin 	SAFTE_UPDATE_READGFLAGS,
86f6ad3f23SAlexander Motin 	SAFTE_UPDATE_READENCSTATUS,
87f6ad3f23SAlexander Motin 	SAFTE_UPDATE_READSLOTSTATUS,
88f6ad3f23SAlexander Motin 	SAFTE_PROCESS_CONTROL_REQS,
89f6ad3f23SAlexander Motin 	SAFTE_NUM_UPDATE_STATES
90f6ad3f23SAlexander Motin } safte_update_action;
91f6ad3f23SAlexander Motin 
92f6ad3f23SAlexander Motin static fsm_fill_handler_t safte_fill_read_buf_io;
93f6ad3f23SAlexander Motin static fsm_fill_handler_t safte_fill_control_request;
94f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_config;
95f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_gflags;
96f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_status;
97f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_slotstatus;
98f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_control_request;
99f6ad3f23SAlexander Motin 
100f6ad3f23SAlexander Motin static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES] =
101f6ad3f23SAlexander Motin {
102f6ad3f23SAlexander Motin 	{ "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
103f6ad3f23SAlexander Motin 	{
104f6ad3f23SAlexander Motin 		"SAFTE_UPDATE_READCONFIG",
105f6ad3f23SAlexander Motin 		SAFTE_RD_RDCFG,
106f6ad3f23SAlexander Motin 		SAFT_SCRATCH,
107f6ad3f23SAlexander Motin 		60 * 1000,
108f6ad3f23SAlexander Motin 		safte_fill_read_buf_io,
109f6ad3f23SAlexander Motin 		safte_process_config,
110f6ad3f23SAlexander Motin 		enc_error
111f6ad3f23SAlexander Motin 	},
112f6ad3f23SAlexander Motin 	{
113f6ad3f23SAlexander Motin 		"SAFTE_UPDATE_READGFLAGS",
114f6ad3f23SAlexander Motin 		SAFTE_RD_RDGFLG,
115f6ad3f23SAlexander Motin 		16,
116f6ad3f23SAlexander Motin 		60 * 1000,
117f6ad3f23SAlexander Motin 		safte_fill_read_buf_io,
118f6ad3f23SAlexander Motin 		safte_process_gflags,
119f6ad3f23SAlexander Motin 		enc_error
120f6ad3f23SAlexander Motin 	},
121f6ad3f23SAlexander Motin 	{
122f6ad3f23SAlexander Motin 		"SAFTE_UPDATE_READENCSTATUS",
123f6ad3f23SAlexander Motin 		SAFTE_RD_RDESTS,
124f6ad3f23SAlexander Motin 		SCSZ,
125f6ad3f23SAlexander Motin 		60 * 1000,
126f6ad3f23SAlexander Motin 		safte_fill_read_buf_io,
127f6ad3f23SAlexander Motin 		safte_process_status,
128f6ad3f23SAlexander Motin 		enc_error
129f6ad3f23SAlexander Motin 	},
130f6ad3f23SAlexander Motin 	{
131f6ad3f23SAlexander Motin 		"SAFTE_UPDATE_READSLOTSTATUS",
132f6ad3f23SAlexander Motin 		SAFTE_RD_RDDSTS,
133f6ad3f23SAlexander Motin 		SCSZ,
134f6ad3f23SAlexander Motin 		60 * 1000,
135f6ad3f23SAlexander Motin 		safte_fill_read_buf_io,
136f6ad3f23SAlexander Motin 		safte_process_slotstatus,
137f6ad3f23SAlexander Motin 		enc_error
138f6ad3f23SAlexander Motin 	},
139f6ad3f23SAlexander Motin 	{
140f6ad3f23SAlexander Motin 		"SAFTE_PROCESS_CONTROL_REQS",
141f6ad3f23SAlexander Motin 		0,
142f6ad3f23SAlexander Motin 		SCSZ,
143f6ad3f23SAlexander Motin 		60 * 1000,
144f6ad3f23SAlexander Motin 		safte_fill_control_request,
145f6ad3f23SAlexander Motin 		safte_process_control_request,
146f6ad3f23SAlexander Motin 		enc_error
147f6ad3f23SAlexander Motin 	}
148f6ad3f23SAlexander Motin };
149f6ad3f23SAlexander Motin 
150f6ad3f23SAlexander Motin typedef struct safte_control_request {
151f6ad3f23SAlexander Motin 	int	elm_idx;
152f6ad3f23SAlexander Motin 	uint8_t	elm_stat[4];
153f6ad3f23SAlexander Motin 	int	result;
154f6ad3f23SAlexander Motin 	TAILQ_ENTRY(safte_control_request) links;
155f6ad3f23SAlexander Motin } safte_control_request_t;
156f6ad3f23SAlexander Motin TAILQ_HEAD(safte_control_reqlist, safte_control_request);
157f6ad3f23SAlexander Motin typedef struct safte_control_reqlist safte_control_reqlist_t;
158f6ad3f23SAlexander Motin enum {
159f6ad3f23SAlexander Motin 	SES_SETSTATUS_ENC_IDX = -1
160f6ad3f23SAlexander Motin };
161f6ad3f23SAlexander Motin 
162f6ad3f23SAlexander Motin static void
safte_terminate_control_requests(safte_control_reqlist_t * reqlist,int result)163f6ad3f23SAlexander Motin safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
164f6ad3f23SAlexander Motin {
165f6ad3f23SAlexander Motin 	safte_control_request_t *req;
166f6ad3f23SAlexander Motin 
167f6ad3f23SAlexander Motin 	while ((req = TAILQ_FIRST(reqlist)) != NULL) {
168f6ad3f23SAlexander Motin 		TAILQ_REMOVE(reqlist, req, links);
169f6ad3f23SAlexander Motin 		req->result = result;
170f6ad3f23SAlexander Motin 		wakeup(req);
171f6ad3f23SAlexander Motin 	}
172f6ad3f23SAlexander Motin }
173f6ad3f23SAlexander Motin 
174f6ad3f23SAlexander Motin struct scfg {
175f6ad3f23SAlexander Motin 	/*
176f6ad3f23SAlexander Motin 	 * Cached Configuration
177f6ad3f23SAlexander Motin 	 */
178f6ad3f23SAlexander Motin 	uint8_t	Nfans;		/* Number of Fans */
179f6ad3f23SAlexander Motin 	uint8_t	Npwr;		/* Number of Power Supplies */
180f6ad3f23SAlexander Motin 	uint8_t	Nslots;		/* Number of Device Slots */
181f6ad3f23SAlexander Motin 	uint8_t	DoorLock;	/* Door Lock Installed */
182f6ad3f23SAlexander Motin 	uint8_t	Ntherm;		/* Number of Temperature Sensors */
183f6ad3f23SAlexander Motin 	uint8_t	Nspkrs;		/* Number of Speakers */
184f6ad3f23SAlexander Motin 	uint8_t	Ntstats;	/* Number of Thermostats */
185f6ad3f23SAlexander Motin 	/*
186f6ad3f23SAlexander Motin 	 * Cached Flag Bytes for Global Status
187f6ad3f23SAlexander Motin 	 */
188f6ad3f23SAlexander Motin 	uint8_t	flag1;
189f6ad3f23SAlexander Motin 	uint8_t	flag2;
190f6ad3f23SAlexander Motin 	/*
191f6ad3f23SAlexander Motin 	 * What object index ID is where various slots start.
192f6ad3f23SAlexander Motin 	 */
193f6ad3f23SAlexander Motin 	uint8_t	pwroff;
194f6ad3f23SAlexander Motin 	uint8_t	slotoff;
195f6ad3f23SAlexander Motin #define	SAFT_ALARM_OFFSET(cc)	(cc)->slotoff - 1
196f6ad3f23SAlexander Motin 
197f6ad3f23SAlexander Motin 	encioc_enc_status_t	adm_status;
198f6ad3f23SAlexander Motin 	encioc_enc_status_t	enc_status;
199f6ad3f23SAlexander Motin 	encioc_enc_status_t	slot_status;
200f6ad3f23SAlexander Motin 
201f6ad3f23SAlexander Motin 	safte_control_reqlist_t	requests;
202f6ad3f23SAlexander Motin 	safte_control_request_t	*current_request;
203f6ad3f23SAlexander Motin 	int			current_request_stage;
204f6ad3f23SAlexander Motin 	int			current_request_stages;
205f6ad3f23SAlexander Motin };
206f6ad3f23SAlexander Motin 
207f6ad3f23SAlexander Motin #define	SAFT_FLG1_ALARM		0x1
208f6ad3f23SAlexander Motin #define	SAFT_FLG1_GLOBFAIL	0x2
209f6ad3f23SAlexander Motin #define	SAFT_FLG1_GLOBWARN	0x4
210f6ad3f23SAlexander Motin #define	SAFT_FLG1_ENCPWROFF	0x8
211f6ad3f23SAlexander Motin #define	SAFT_FLG1_ENCFANFAIL	0x10
212f6ad3f23SAlexander Motin #define	SAFT_FLG1_ENCPWRFAIL	0x20
213f6ad3f23SAlexander Motin #define	SAFT_FLG1_ENCDRVFAIL	0x40
214f6ad3f23SAlexander Motin #define	SAFT_FLG1_ENCDRVWARN	0x80
215f6ad3f23SAlexander Motin 
216f6ad3f23SAlexander Motin #define	SAFT_FLG2_LOCKDOOR	0x4
217f6ad3f23SAlexander Motin #define	SAFT_PRIVATE		sizeof (struct scfg)
218f6ad3f23SAlexander Motin 
219f6ad3f23SAlexander Motin static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
220f6ad3f23SAlexander Motin #define	SAFT_BAIL(r, x)	\
221f6ad3f23SAlexander Motin 	if ((r) >= (x)) { \
2225e6609a2SMatt Jacob 		ENC_VLOG(enc, safte_2little, x, __LINE__);\
223f6ad3f23SAlexander Motin 		return (EIO); \
224f6ad3f23SAlexander Motin 	}
225f6ad3f23SAlexander Motin 
226f6ad3f23SAlexander Motin int emulate_array_devices = 1;
227af3b2549SHans Petter Selasky SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN,
228f6ad3f23SAlexander Motin            &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
229f6ad3f23SAlexander Motin 
230f6ad3f23SAlexander Motin static int
safte_fill_read_buf_io(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t * buf)231f6ad3f23SAlexander Motin safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
232f6ad3f23SAlexander Motin 		       union ccb *ccb, uint8_t *buf)
233f6ad3f23SAlexander Motin {
234f6ad3f23SAlexander Motin 
235f6ad3f23SAlexander Motin 	if (state->page_code != SAFTE_RD_RDCFG &&
236f6ad3f23SAlexander Motin 	    enc->enc_cache.nelms == 0) {
237f6ad3f23SAlexander Motin 		enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
238f6ad3f23SAlexander Motin 		return (-1);
239f6ad3f23SAlexander Motin 	}
240f6ad3f23SAlexander Motin 
241f6ad3f23SAlexander Motin 	if (enc->enc_type == ENC_SEMB_SAFT) {
242f6ad3f23SAlexander Motin 		semb_read_buffer(&ccb->ataio, /*retries*/5,
243227d67aaSAlexander Motin 				NULL, MSG_SIMPLE_Q_TAG,
244f6ad3f23SAlexander Motin 				state->page_code, buf, state->buf_size,
245f6ad3f23SAlexander Motin 				state->timeout);
246f6ad3f23SAlexander Motin 	} else {
247f6ad3f23SAlexander Motin 		scsi_read_buffer(&ccb->csio, /*retries*/5,
248227d67aaSAlexander Motin 				NULL, MSG_SIMPLE_Q_TAG, 1,
249f6ad3f23SAlexander Motin 				state->page_code, 0, buf, state->buf_size,
250f6ad3f23SAlexander Motin 				SSD_FULL_SIZE, state->timeout);
251f6ad3f23SAlexander Motin 	}
252f6ad3f23SAlexander Motin 	return (0);
253f6ad3f23SAlexander Motin }
254f6ad3f23SAlexander Motin 
255f6ad3f23SAlexander Motin static int
safte_process_config(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)256f6ad3f23SAlexander Motin safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
257f6ad3f23SAlexander Motin     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
258f6ad3f23SAlexander Motin {
259f6ad3f23SAlexander Motin 	struct scfg *cfg;
260f6ad3f23SAlexander Motin 	uint8_t *buf = *bufp;
261f6ad3f23SAlexander Motin 	int i, r;
262f6ad3f23SAlexander Motin 
263f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
264f6ad3f23SAlexander Motin 	if (cfg == NULL)
265f6ad3f23SAlexander Motin 		return (ENXIO);
266f6ad3f23SAlexander Motin 	if (error != 0)
267f6ad3f23SAlexander Motin 		return (error);
268f6ad3f23SAlexander Motin 	if (xfer_len < 6) {
2695e6609a2SMatt Jacob 		ENC_VLOG(enc, "too little data (%d) for configuration\n",
270f6ad3f23SAlexander Motin 		    xfer_len);
271f6ad3f23SAlexander Motin 		return (EIO);
272f6ad3f23SAlexander Motin 	}
273f6ad3f23SAlexander Motin 	cfg->Nfans = buf[0];
274f6ad3f23SAlexander Motin 	cfg->Npwr = buf[1];
275f6ad3f23SAlexander Motin 	cfg->Nslots = buf[2];
276f6ad3f23SAlexander Motin 	cfg->DoorLock = buf[3];
277f6ad3f23SAlexander Motin 	cfg->Ntherm = buf[4];
278f6ad3f23SAlexander Motin 	cfg->Nspkrs = buf[5];
279f6ad3f23SAlexander Motin 	if (xfer_len >= 7)
280f6ad3f23SAlexander Motin 		cfg->Ntstats = buf[6] & 0x0f;
281f6ad3f23SAlexander Motin 	else
282f6ad3f23SAlexander Motin 		cfg->Ntstats = 0;
283f6ad3f23SAlexander Motin 	ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
284f6ad3f23SAlexander Motin 	    "Ntstats %d\n",
285f6ad3f23SAlexander Motin 	    cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
286f6ad3f23SAlexander Motin 	    cfg->Nspkrs, cfg->Ntstats);
287f6ad3f23SAlexander Motin 
288f6ad3f23SAlexander Motin 	enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots +
289f6ad3f23SAlexander Motin 	    cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1;
290f6ad3f23SAlexander Motin 	ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
291f6ad3f23SAlexander Motin 	enc->enc_cache.elm_map =
292ed246e82SAlexander Motin 	    malloc(enc->enc_cache.nelms * sizeof(enc_element_t),
293ed246e82SAlexander Motin 	    M_SCSIENC, M_WAITOK|M_ZERO);
294f6ad3f23SAlexander Motin 
295f6ad3f23SAlexander Motin 	r = 0;
296f6ad3f23SAlexander Motin 	/*
297f6ad3f23SAlexander Motin 	 * Note that this is all arranged for the convenience
298f6ad3f23SAlexander Motin 	 * in later fetches of status.
299f6ad3f23SAlexander Motin 	 */
300f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->Nfans; i++)
30153f5ac13SAlexander Motin 		enc->enc_cache.elm_map[r++].elm_type = ELMTYP_FAN;
302f6ad3f23SAlexander Motin 	cfg->pwroff = (uint8_t) r;
303f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->Npwr; i++)
30453f5ac13SAlexander Motin 		enc->enc_cache.elm_map[r++].elm_type = ELMTYP_POWER;
305f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->DoorLock; i++)
30653f5ac13SAlexander Motin 		enc->enc_cache.elm_map[r++].elm_type = ELMTYP_DOORLOCK;
307f6ad3f23SAlexander Motin 	if (cfg->Nspkrs > 0)
30853f5ac13SAlexander Motin 		enc->enc_cache.elm_map[r++].elm_type = ELMTYP_ALARM;
309f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->Ntherm; i++)
31053f5ac13SAlexander Motin 		enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
311f6ad3f23SAlexander Motin 	for (i = 0; i <= cfg->Ntstats; i++)
31253f5ac13SAlexander Motin 		enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
313f6ad3f23SAlexander Motin 	cfg->slotoff = (uint8_t) r;
314f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->Nslots; i++)
31553f5ac13SAlexander Motin 		enc->enc_cache.elm_map[r++].elm_type =
316f6ad3f23SAlexander Motin 		    emulate_array_devices ? ELMTYP_ARRAY_DEV :
317f6ad3f23SAlexander Motin 		     ELMTYP_DEVICE;
318f6ad3f23SAlexander Motin 
319f6ad3f23SAlexander Motin 	enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
320f6ad3f23SAlexander Motin 	enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
321f6ad3f23SAlexander Motin 	enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
322f6ad3f23SAlexander Motin 
323f6ad3f23SAlexander Motin 	return (0);
324f6ad3f23SAlexander Motin }
325f6ad3f23SAlexander Motin 
326f6ad3f23SAlexander Motin static int
safte_process_gflags(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)327f6ad3f23SAlexander Motin safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
328f6ad3f23SAlexander Motin     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
329f6ad3f23SAlexander Motin {
330f6ad3f23SAlexander Motin 	struct scfg *cfg;
331f6ad3f23SAlexander Motin 	uint8_t *buf = *bufp;
332f6ad3f23SAlexander Motin 
333f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
334f6ad3f23SAlexander Motin 	if (cfg == NULL)
335f6ad3f23SAlexander Motin 		return (ENXIO);
336f6ad3f23SAlexander Motin 	if (error != 0)
337f6ad3f23SAlexander Motin 		return (error);
338f6ad3f23SAlexander Motin 	SAFT_BAIL(3, xfer_len);
339f6ad3f23SAlexander Motin 	cfg->flag1 = buf[1];
340f6ad3f23SAlexander Motin 	cfg->flag2 = buf[2];
341f6ad3f23SAlexander Motin 
342f6ad3f23SAlexander Motin 	cfg->adm_status = 0;
343f6ad3f23SAlexander Motin 	if (cfg->flag1 & SAFT_FLG1_GLOBFAIL)
344f6ad3f23SAlexander Motin 		cfg->adm_status |= SES_ENCSTAT_CRITICAL;
345f6ad3f23SAlexander Motin 	else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
346f6ad3f23SAlexander Motin 		cfg->adm_status |= SES_ENCSTAT_NONCRITICAL;
347f6ad3f23SAlexander Motin 
348f6ad3f23SAlexander Motin 	return (0);
349f6ad3f23SAlexander Motin }
350f6ad3f23SAlexander Motin 
351f6ad3f23SAlexander Motin static int
safte_process_status(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)352f6ad3f23SAlexander Motin safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
353f6ad3f23SAlexander Motin     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
354f6ad3f23SAlexander Motin {
355f6ad3f23SAlexander Motin 	struct scfg *cfg;
356f6ad3f23SAlexander Motin 	uint8_t *buf = *bufp;
357f6ad3f23SAlexander Motin 	int oid, r, i, nitems;
358f6ad3f23SAlexander Motin 	uint16_t tempflags;
359f6ad3f23SAlexander Motin 	enc_cache_t *cache = &enc->enc_cache;
360f6ad3f23SAlexander Motin 
361f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
362f6ad3f23SAlexander Motin 	if (cfg == NULL)
363f6ad3f23SAlexander Motin 		return (ENXIO);
364f6ad3f23SAlexander Motin 	if (error != 0)
365f6ad3f23SAlexander Motin 		return (error);
366f6ad3f23SAlexander Motin 
367f6ad3f23SAlexander Motin 	oid = r = 0;
368f6ad3f23SAlexander Motin 	cfg->enc_status = 0;
369f6ad3f23SAlexander Motin 
370f6ad3f23SAlexander Motin 	for (nitems = i = 0; i < cfg->Nfans; i++) {
371f6ad3f23SAlexander Motin 		SAFT_BAIL(r, xfer_len);
372f6ad3f23SAlexander Motin 		/*
373f6ad3f23SAlexander Motin 		 * 0 = Fan Operational
374f6ad3f23SAlexander Motin 		 * 1 = Fan is malfunctioning
375f6ad3f23SAlexander Motin 		 * 2 = Fan is not present
376f6ad3f23SAlexander Motin 		 * 0x80 = Unknown or Not Reportable Status
377f6ad3f23SAlexander Motin 		 */
378f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[1] = 0;	/* resvd */
379f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[2] = 0;	/* resvd */
380f6ad3f23SAlexander Motin 		if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL)
381f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] |= 0x40;
382f6ad3f23SAlexander Motin 		else
383f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] &= ~0x40;
384f6ad3f23SAlexander Motin 		switch ((int)buf[r]) {
385f6ad3f23SAlexander Motin 		case 0:
386f6ad3f23SAlexander Motin 			nitems++;
387f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
388f6ad3f23SAlexander Motin 			if ((cache->elm_map[oid].encstat[3] & 0x37) == 0)
389f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[3] |= 0x27;
390f6ad3f23SAlexander Motin 			break;
391f6ad3f23SAlexander Motin 
392f6ad3f23SAlexander Motin 		case 1:
393f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] =
394f6ad3f23SAlexander Motin 			    SES_OBJSTAT_CRIT;
395f6ad3f23SAlexander Motin 			/*
396f6ad3f23SAlexander Motin 			 * FAIL and FAN STOPPED synthesized
397f6ad3f23SAlexander Motin 			 */
398f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] |= 0x10;
399f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] &= ~0x07;
400f6ad3f23SAlexander Motin 			/*
401f6ad3f23SAlexander Motin 			 * Enclosure marked with CRITICAL error
402f6ad3f23SAlexander Motin 			 * if only one fan or no thermometers,
403f6ad3f23SAlexander Motin 			 * else the NONCRITICAL error is set.
404f6ad3f23SAlexander Motin 			 */
405f6ad3f23SAlexander Motin 			if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
406f6ad3f23SAlexander Motin 				cfg->enc_status |= SES_ENCSTAT_CRITICAL;
407f6ad3f23SAlexander Motin 			else
408f6ad3f23SAlexander Motin 				cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
409f6ad3f23SAlexander Motin 			break;
410f6ad3f23SAlexander Motin 		case 2:
411f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] =
412f6ad3f23SAlexander Motin 			    SES_OBJSTAT_NOTINSTALLED;
413f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] |= 0x10;
414f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] &= ~0x07;
415f6ad3f23SAlexander Motin 			/*
416f6ad3f23SAlexander Motin 			 * Enclosure marked with CRITICAL error
417f6ad3f23SAlexander Motin 			 * if only one fan or no thermometers,
418f6ad3f23SAlexander Motin 			 * else the NONCRITICAL error is set.
419f6ad3f23SAlexander Motin 			 */
420f6ad3f23SAlexander Motin 			if (cfg->Nfans == 1)
421f6ad3f23SAlexander Motin 				cfg->enc_status |= SES_ENCSTAT_CRITICAL;
422f6ad3f23SAlexander Motin 			else
423f6ad3f23SAlexander Motin 				cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
424f6ad3f23SAlexander Motin 			break;
425f6ad3f23SAlexander Motin 		case 0x80:
426f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
427f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0;
428f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_INFO;
429f6ad3f23SAlexander Motin 			break;
430f6ad3f23SAlexander Motin 		default:
431f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
4325e6609a2SMatt Jacob 			ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
433f6ad3f23SAlexander Motin 			    buf[r] & 0xff);
434f6ad3f23SAlexander Motin 			break;
435f6ad3f23SAlexander Motin 		}
436f6ad3f23SAlexander Motin 		cache->elm_map[oid++].svalid = 1;
437f6ad3f23SAlexander Motin 		r++;
438f6ad3f23SAlexander Motin 	}
439f6ad3f23SAlexander Motin 
440f6ad3f23SAlexander Motin 	/*
441f6ad3f23SAlexander Motin 	 * No matter how you cut it, no cooling elements when there
442f6ad3f23SAlexander Motin 	 * should be some there is critical.
443f6ad3f23SAlexander Motin 	 */
444f6ad3f23SAlexander Motin 	if (cfg->Nfans && nitems == 0)
445f6ad3f23SAlexander Motin 		cfg->enc_status |= SES_ENCSTAT_CRITICAL;
446f6ad3f23SAlexander Motin 
447f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->Npwr; i++) {
448f6ad3f23SAlexander Motin 		SAFT_BAIL(r, xfer_len);
449f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
450f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[1] = 0;	/* resvd */
451f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[2] = 0;	/* resvd */
452f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[3] = 0x20;	/* requested on */
453f6ad3f23SAlexander Motin 		switch (buf[r]) {
454f6ad3f23SAlexander Motin 		case 0x00:	/* pws operational and on */
455f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
456f6ad3f23SAlexander Motin 			break;
457f6ad3f23SAlexander Motin 		case 0x01:	/* pws operational and off */
458f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
459f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0x10;
460f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_INFO;
461f6ad3f23SAlexander Motin 			break;
462f6ad3f23SAlexander Motin 		case 0x10:	/* pws is malfunctioning and commanded on */
463f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
464f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0x61;
465f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
466f6ad3f23SAlexander Motin 			break;
467f6ad3f23SAlexander Motin 
468f6ad3f23SAlexander Motin 		case 0x11:	/* pws is malfunctioning and commanded off */
469f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
470f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0x51;
471f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
472f6ad3f23SAlexander Motin 			break;
473f6ad3f23SAlexander Motin 		case 0x20:	/* pws is not present */
474f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] =
475f6ad3f23SAlexander Motin 			    SES_OBJSTAT_NOTINSTALLED;
476f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0;
477f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_INFO;
478f6ad3f23SAlexander Motin 			break;
479f6ad3f23SAlexander Motin 		case 0x21:	/* pws is present */
480f6ad3f23SAlexander Motin 			/*
481f6ad3f23SAlexander Motin 			 * This is for enclosures that cannot tell whether the
482f6ad3f23SAlexander Motin 			 * device is on or malfunctioning, but know that it is
483f6ad3f23SAlexander Motin 			 * present. Just fall through.
484f6ad3f23SAlexander Motin 			 */
485f6ad3f23SAlexander Motin 			/* FALLTHROUGH */
486f6ad3f23SAlexander Motin 		case 0x80:	/* Unknown or Not Reportable Status */
487f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
488f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0;
489f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_INFO;
490f6ad3f23SAlexander Motin 			break;
491f6ad3f23SAlexander Motin 		default:
4925e6609a2SMatt Jacob 			ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
493f6ad3f23SAlexander Motin 			    i, buf[r] & 0xff);
494f6ad3f23SAlexander Motin 			break;
495f6ad3f23SAlexander Motin 		}
496f6ad3f23SAlexander Motin 		enc->enc_cache.elm_map[oid++].svalid = 1;
497f6ad3f23SAlexander Motin 		r++;
498f6ad3f23SAlexander Motin 	}
499f6ad3f23SAlexander Motin 
500f6ad3f23SAlexander Motin 	/*
501f6ad3f23SAlexander Motin 	 * Copy Slot SCSI IDs
502f6ad3f23SAlexander Motin 	 */
503f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->Nslots; i++) {
504f6ad3f23SAlexander Motin 		SAFT_BAIL(r, xfer_len);
50553f5ac13SAlexander Motin 		if (cache->elm_map[cfg->slotoff + i].elm_type == ELMTYP_DEVICE)
506f6ad3f23SAlexander Motin 			cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
507f6ad3f23SAlexander Motin 		r++;
508f6ad3f23SAlexander Motin 	}
509f6ad3f23SAlexander Motin 
510f6ad3f23SAlexander Motin 	/*
511f6ad3f23SAlexander Motin 	 * We always have doorlock status, no matter what,
512f6ad3f23SAlexander Motin 	 * but we only save the status if we have one.
513f6ad3f23SAlexander Motin 	 */
514f6ad3f23SAlexander Motin 	SAFT_BAIL(r, xfer_len);
515f6ad3f23SAlexander Motin 	if (cfg->DoorLock) {
516f6ad3f23SAlexander Motin 		/*
517f6ad3f23SAlexander Motin 		 * 0 = Door Locked
518f6ad3f23SAlexander Motin 		 * 1 = Door Unlocked, or no Lock Installed
519f6ad3f23SAlexander Motin 		 * 0x80 = Unknown or Not Reportable Status
520f6ad3f23SAlexander Motin 		 */
521f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[1] = 0;
522f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[2] = 0;
523f6ad3f23SAlexander Motin 		switch (buf[r]) {
524f6ad3f23SAlexander Motin 		case 0:
525f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
526f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0;
527f6ad3f23SAlexander Motin 			break;
528f6ad3f23SAlexander Motin 		case 1:
529f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
530f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 1;
531f6ad3f23SAlexander Motin 			break;
532f6ad3f23SAlexander Motin 		case 0x80:
533f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
534f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0;
535f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_INFO;
536f6ad3f23SAlexander Motin 			break;
537f6ad3f23SAlexander Motin 		default:
538f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] =
539f6ad3f23SAlexander Motin 			    SES_OBJSTAT_UNSUPPORTED;
5405e6609a2SMatt Jacob 			ENC_VLOG(enc, "unknown lock status 0x%x\n",
541f6ad3f23SAlexander Motin 			    buf[r] & 0xff);
542f6ad3f23SAlexander Motin 			break;
543f6ad3f23SAlexander Motin 		}
544f6ad3f23SAlexander Motin 		cache->elm_map[oid++].svalid = 1;
545f6ad3f23SAlexander Motin 	}
546f6ad3f23SAlexander Motin 	r++;
547f6ad3f23SAlexander Motin 
548f6ad3f23SAlexander Motin 	/*
549f6ad3f23SAlexander Motin 	 * We always have speaker status, no matter what,
550f6ad3f23SAlexander Motin 	 * but we only save the status if we have one.
551f6ad3f23SAlexander Motin 	 */
552f6ad3f23SAlexander Motin 	SAFT_BAIL(r, xfer_len);
553f6ad3f23SAlexander Motin 	if (cfg->Nspkrs) {
554f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
555f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[1] = 0;
556f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[2] = 0;
557f6ad3f23SAlexander Motin 		if (buf[r] == 0) {
558f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
559f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] |= 0x40;
560f6ad3f23SAlexander Motin 		}
561f6ad3f23SAlexander Motin 		cache->elm_map[oid++].svalid = 1;
562f6ad3f23SAlexander Motin 	}
563f6ad3f23SAlexander Motin 	r++;
564f6ad3f23SAlexander Motin 
565f6ad3f23SAlexander Motin 	/*
566f6ad3f23SAlexander Motin 	 * Now, for "pseudo" thermometers, we have two bytes
567f6ad3f23SAlexander Motin 	 * of information in enclosure status- 16 bits. Actually,
568f6ad3f23SAlexander Motin 	 * the MSB is a single TEMP ALERT flag indicating whether
569f6ad3f23SAlexander Motin 	 * any other bits are set, but, thanks to fuzzy thinking,
570f6ad3f23SAlexander Motin 	 * in the SAF-TE spec, this can also be set even if no
571f6ad3f23SAlexander Motin 	 * other bits are set, thus making this really another
572f6ad3f23SAlexander Motin 	 * binary temperature sensor.
573f6ad3f23SAlexander Motin 	 */
574f6ad3f23SAlexander Motin 
575f6ad3f23SAlexander Motin 	SAFT_BAIL(r + cfg->Ntherm, xfer_len);
576f6ad3f23SAlexander Motin 	tempflags = buf[r + cfg->Ntherm];
577f6ad3f23SAlexander Motin 	SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len);
578f6ad3f23SAlexander Motin 	tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1];
579f6ad3f23SAlexander Motin 
580f6ad3f23SAlexander Motin 	for (i = 0; i < cfg->Ntherm; i++) {
581f6ad3f23SAlexander Motin 		SAFT_BAIL(r, xfer_len);
582f6ad3f23SAlexander Motin 		/*
583f6ad3f23SAlexander Motin 		 * Status is a range from -10 to 245 deg Celsius,
584f6ad3f23SAlexander Motin 		 * which we need to normalize to -20 to -245 according
585f6ad3f23SAlexander Motin 		 * to the latest SCSI spec, which makes little
586f6ad3f23SAlexander Motin 		 * sense since this would overflow an 8bit value.
587f6ad3f23SAlexander Motin 		 * Well, still, the base normalization is -20,
588f6ad3f23SAlexander Motin 		 * not -10, so we have to adjust.
589f6ad3f23SAlexander Motin 		 *
590f6ad3f23SAlexander Motin 		 * So what's over and under temperature?
591f6ad3f23SAlexander Motin 		 * Hmm- we'll state that 'normal' operating
592f6ad3f23SAlexander Motin 		 * is 10 to 40 deg Celsius.
593f6ad3f23SAlexander Motin 		 */
594f6ad3f23SAlexander Motin 
595f6ad3f23SAlexander Motin 		/*
596f6ad3f23SAlexander Motin 		 * Actually.... All of the units that people out in the world
597f6ad3f23SAlexander Motin 		 * seem to have do not come even close to setting a value that
598f6ad3f23SAlexander Motin 		 * complies with this spec.
599f6ad3f23SAlexander Motin 		 *
600f6ad3f23SAlexander Motin 		 * The closest explanation I could find was in an
601f6ad3f23SAlexander Motin 		 * LSI-Logic manual, which seemed to indicate that
602f6ad3f23SAlexander Motin 		 * this value would be set by whatever the I2C code
603f6ad3f23SAlexander Motin 		 * would interpolate from the output of an LM75
604f6ad3f23SAlexander Motin 		 * temperature sensor.
605f6ad3f23SAlexander Motin 		 *
606f6ad3f23SAlexander Motin 		 * This means that it is impossible to use the actual
607f6ad3f23SAlexander Motin 		 * numeric value to predict anything. But we don't want
608f6ad3f23SAlexander Motin 		 * to lose the value. So, we'll propagate the *uncorrected*
609f6ad3f23SAlexander Motin 		 * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
610f6ad3f23SAlexander Motin 		 * temperature flags for warnings.
611f6ad3f23SAlexander Motin 		 */
612f6ad3f23SAlexander Motin 		if (tempflags & (1 << i)) {
613f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
614f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_CRITICAL;
615f6ad3f23SAlexander Motin 		} else
616f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
617f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[1] = 0;
618f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[2] = buf[r];
619f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[3] = 0;
620f6ad3f23SAlexander Motin 		cache->elm_map[oid++].svalid = 1;
621f6ad3f23SAlexander Motin 		r++;
622f6ad3f23SAlexander Motin 	}
623f6ad3f23SAlexander Motin 
624f6ad3f23SAlexander Motin 	for (i = 0; i <= cfg->Ntstats; i++) {
625f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[1] = 0;
626f6ad3f23SAlexander Motin 		if (tempflags & (1 <<
627f6ad3f23SAlexander Motin 		    ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) {
628f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
629f6ad3f23SAlexander Motin 			cache->elm_map[4].encstat[2] = 0xff;
630f6ad3f23SAlexander Motin 			/*
631f6ad3f23SAlexander Motin 			 * Set 'over temperature' failure.
632f6ad3f23SAlexander Motin 			 */
633f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 8;
634f6ad3f23SAlexander Motin 			cfg->enc_status |= SES_ENCSTAT_CRITICAL;
635f6ad3f23SAlexander Motin 		} else {
636f6ad3f23SAlexander Motin 			/*
637f6ad3f23SAlexander Motin 			 * We used to say 'not available' and synthesize a
638f6ad3f23SAlexander Motin 			 * nominal 30 deg (C)- that was wrong. Actually,
639f6ad3f23SAlexander Motin 			 * Just say 'OK', and use the reserved value of
640f6ad3f23SAlexander Motin 			 * zero.
641f6ad3f23SAlexander Motin 			 */
642f6ad3f23SAlexander Motin 			if ((cfg->Ntherm + cfg->Ntstats) == 0)
643f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[0] =
644f6ad3f23SAlexander Motin 				    SES_OBJSTAT_NOTAVAIL;
645f6ad3f23SAlexander Motin 			else
646f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[0] =
647f6ad3f23SAlexander Motin 				    SES_OBJSTAT_OK;
648f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[2] = 0;
649f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] = 0;
650f6ad3f23SAlexander Motin 		}
651f6ad3f23SAlexander Motin 		cache->elm_map[oid++].svalid = 1;
652f6ad3f23SAlexander Motin 	}
653f6ad3f23SAlexander Motin 	r += 2;
654f6ad3f23SAlexander Motin 
655f6ad3f23SAlexander Motin 	cache->enc_status =
656f6ad3f23SAlexander Motin 	    cfg->enc_status | cfg->slot_status | cfg->adm_status;
657f6ad3f23SAlexander Motin 	return (0);
658f6ad3f23SAlexander Motin }
659f6ad3f23SAlexander Motin 
660f6ad3f23SAlexander Motin static int
safte_process_slotstatus(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)661f6ad3f23SAlexander Motin safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
662f6ad3f23SAlexander Motin     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
663f6ad3f23SAlexander Motin {
664f6ad3f23SAlexander Motin 	struct scfg *cfg;
665f6ad3f23SAlexander Motin 	uint8_t *buf = *bufp;
666f6ad3f23SAlexander Motin 	enc_cache_t *cache = &enc->enc_cache;
667f6ad3f23SAlexander Motin 	int oid, r, i;
668f6ad3f23SAlexander Motin 
669f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
670f6ad3f23SAlexander Motin 	if (cfg == NULL)
671f6ad3f23SAlexander Motin 		return (ENXIO);
672f6ad3f23SAlexander Motin 	if (error != 0)
673f6ad3f23SAlexander Motin 		return (error);
674f6ad3f23SAlexander Motin 	cfg->slot_status = 0;
675f6ad3f23SAlexander Motin 	oid = cfg->slotoff;
676f6ad3f23SAlexander Motin 	for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
677f6ad3f23SAlexander Motin 		SAFT_BAIL(r+3, xfer_len);
67853f5ac13SAlexander Motin 		if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV)
679f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[1] = 0;
680f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
681f6ad3f23SAlexander Motin 		cache->elm_map[oid].encstat[3] = 0;
682f6ad3f23SAlexander Motin 		if ((buf[r+3] & 0x01) == 0) {	/* no device */
683f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED;
684f6ad3f23SAlexander Motin 		} else if (buf[r+0] & 0x02) {
685f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
686f6ad3f23SAlexander Motin 			cfg->slot_status |= SES_ENCSTAT_CRITICAL;
687f6ad3f23SAlexander Motin 		} else if (buf[r+0] & 0x40) {
688f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
689f6ad3f23SAlexander Motin 			cfg->slot_status |= SES_ENCSTAT_NONCRITICAL;
690f6ad3f23SAlexander Motin 		} else {
691f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
692f6ad3f23SAlexander Motin 		}
693f6ad3f23SAlexander Motin 		if (buf[r+3] & 0x2) {
694f6ad3f23SAlexander Motin 			if (buf[r+3] & 0x01)
695f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
696f6ad3f23SAlexander Motin 			else
697f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
698f6ad3f23SAlexander Motin 		}
699f6ad3f23SAlexander Motin 		if ((buf[r+3] & 0x04) == 0)
700f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
701f6ad3f23SAlexander Motin 		if (buf[r+0] & 0x02)
702f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
703f6ad3f23SAlexander Motin 		if (buf[r+0] & 0x40)
704f6ad3f23SAlexander Motin 			cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
70553f5ac13SAlexander Motin 		if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV) {
706f6ad3f23SAlexander Motin 			if (buf[r+0] & 0x01)
707f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[1] |= 0x80;
708f6ad3f23SAlexander Motin 			if (buf[r+0] & 0x04)
709f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[1] |= 0x02;
710f6ad3f23SAlexander Motin 			if (buf[r+0] & 0x08)
711f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[1] |= 0x04;
712f6ad3f23SAlexander Motin 			if (buf[r+0] & 0x10)
713f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[1] |= 0x08;
714f6ad3f23SAlexander Motin 			if (buf[r+0] & 0x20)
715f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[1] |= 0x10;
716f6ad3f23SAlexander Motin 			if (buf[r+1] & 0x01)
717f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[1] |= 0x20;
718f6ad3f23SAlexander Motin 			if (buf[r+1] & 0x02)
719f6ad3f23SAlexander Motin 				cache->elm_map[oid].encstat[1] |= 0x01;
720f6ad3f23SAlexander Motin 		}
721f6ad3f23SAlexander Motin 		cache->elm_map[oid++].svalid = 1;
722f6ad3f23SAlexander Motin 	}
723f6ad3f23SAlexander Motin 
724f6ad3f23SAlexander Motin 	cache->enc_status =
725f6ad3f23SAlexander Motin 	    cfg->enc_status | cfg->slot_status | cfg->adm_status;
726f6ad3f23SAlexander Motin 	return (0);
727f6ad3f23SAlexander Motin }
728f6ad3f23SAlexander Motin 
729f6ad3f23SAlexander Motin static int
safte_fill_control_request(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t * buf)730f6ad3f23SAlexander Motin safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
731f6ad3f23SAlexander Motin 		       union ccb *ccb, uint8_t *buf)
732f6ad3f23SAlexander Motin {
733f6ad3f23SAlexander Motin 	struct scfg *cfg;
734f6ad3f23SAlexander Motin 	enc_element_t *ep, *ep1;
735f6ad3f23SAlexander Motin 	safte_control_request_t *req;
736f6ad3f23SAlexander Motin 	int i, idx, xfer_len;
737f6ad3f23SAlexander Motin 
738f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
739f6ad3f23SAlexander Motin 	if (cfg == NULL)
740f6ad3f23SAlexander Motin 		return (ENXIO);
741f6ad3f23SAlexander Motin 
742f6ad3f23SAlexander Motin 	if (enc->enc_cache.nelms == 0) {
743f6ad3f23SAlexander Motin 		enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
744f6ad3f23SAlexander Motin 		return (-1);
745f6ad3f23SAlexander Motin 	}
746f6ad3f23SAlexander Motin 
747f6ad3f23SAlexander Motin 	if (cfg->current_request == NULL) {
748f6ad3f23SAlexander Motin 		cfg->current_request = TAILQ_FIRST(&cfg->requests);
749f6ad3f23SAlexander Motin 		TAILQ_REMOVE(&cfg->requests, cfg->current_request, links);
750f6ad3f23SAlexander Motin 		cfg->current_request_stage = 0;
751f6ad3f23SAlexander Motin 		cfg->current_request_stages = 1;
752f6ad3f23SAlexander Motin 	}
753f6ad3f23SAlexander Motin 	req = cfg->current_request;
754f6ad3f23SAlexander Motin 
755f6ad3f23SAlexander Motin 	idx = (int)req->elm_idx;
756f6ad3f23SAlexander Motin 	if (req->elm_idx == SES_SETSTATUS_ENC_IDX) {
757f6ad3f23SAlexander Motin 		cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT;
758f6ad3f23SAlexander Motin 		cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
759f6ad3f23SAlexander Motin 		if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV))
760f6ad3f23SAlexander Motin 			cfg->flag1 |= SAFT_FLG1_GLOBFAIL;
761f6ad3f23SAlexander Motin 		else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
762f6ad3f23SAlexander Motin 			cfg->flag1 |= SAFT_FLG1_GLOBWARN;
763f6ad3f23SAlexander Motin 		buf[0] = SAFTE_WT_GLOBAL;
764f6ad3f23SAlexander Motin 		buf[1] = cfg->flag1;
765f6ad3f23SAlexander Motin 		buf[2] = cfg->flag2;
766f6ad3f23SAlexander Motin 		buf[3] = 0;
767f6ad3f23SAlexander Motin 		xfer_len = 16;
768f6ad3f23SAlexander Motin 	} else {
769f6ad3f23SAlexander Motin 		ep = &enc->enc_cache.elm_map[idx];
770f6ad3f23SAlexander Motin 
77153f5ac13SAlexander Motin 		switch (ep->elm_type) {
772f6ad3f23SAlexander Motin 		case ELMTYP_DEVICE:
773f6ad3f23SAlexander Motin 		case ELMTYP_ARRAY_DEV:
774f6ad3f23SAlexander Motin 			switch (cfg->current_request_stage) {
775f6ad3f23SAlexander Motin 			case 0:
776f6ad3f23SAlexander Motin 				ep->priv = 0;
777f6ad3f23SAlexander Motin 				if (req->elm_stat[0] & SESCTL_PRDFAIL)
778f6ad3f23SAlexander Motin 					ep->priv |= 0x40;
779f6ad3f23SAlexander Motin 				if (req->elm_stat[3] & SESCTL_RQSFLT)
780f6ad3f23SAlexander Motin 					ep->priv |= 0x02;
78153f5ac13SAlexander Motin 				if (ep->elm_type == ELMTYP_ARRAY_DEV) {
782f6ad3f23SAlexander Motin 					if (req->elm_stat[1] & 0x01)
783f6ad3f23SAlexander Motin 						ep->priv |= 0x200;
784f6ad3f23SAlexander Motin 					if (req->elm_stat[1] & 0x02)
785f6ad3f23SAlexander Motin 						ep->priv |= 0x04;
786f6ad3f23SAlexander Motin 					if (req->elm_stat[1] & 0x04)
787f6ad3f23SAlexander Motin 						ep->priv |= 0x08;
788f6ad3f23SAlexander Motin 					if (req->elm_stat[1] & 0x08)
789f6ad3f23SAlexander Motin 						ep->priv |= 0x10;
790f6ad3f23SAlexander Motin 					if (req->elm_stat[1] & 0x10)
791f6ad3f23SAlexander Motin 						ep->priv |= 0x20;
792f6ad3f23SAlexander Motin 					if (req->elm_stat[1] & 0x20)
793f6ad3f23SAlexander Motin 						ep->priv |= 0x100;
794f6ad3f23SAlexander Motin 					if (req->elm_stat[1] & 0x80)
795f6ad3f23SAlexander Motin 						ep->priv |= 0x01;
796f6ad3f23SAlexander Motin 				}
797f6ad3f23SAlexander Motin 				if (ep->priv == 0)
798f6ad3f23SAlexander Motin 					ep->priv |= 0x01;	/* no errors */
799f6ad3f23SAlexander Motin 
800f6ad3f23SAlexander Motin 				buf[0] = SAFTE_WT_DSTAT;
801f6ad3f23SAlexander Motin 				for (i = 0; i < cfg->Nslots; i++) {
802f6ad3f23SAlexander Motin 					ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i];
803f6ad3f23SAlexander Motin 					buf[1 + (3 * i)] = ep1->priv;
804f6ad3f23SAlexander Motin 					buf[2 + (3 * i)] = ep1->priv >> 8;
805f6ad3f23SAlexander Motin 				}
806f6ad3f23SAlexander Motin 				xfer_len = cfg->Nslots * 3 + 1;
807f6ad3f23SAlexander Motin #define DEVON(x)	(!(((x)[2] & SESCTL_RQSINS) |	\
808f6ad3f23SAlexander Motin 			   ((x)[2] & SESCTL_RQSRMV) |	\
809f6ad3f23SAlexander Motin 			   ((x)[3] & SESCTL_DEVOFF)))
810f6ad3f23SAlexander Motin 				if (DEVON(req->elm_stat) != DEVON(ep->encstat))
811f6ad3f23SAlexander Motin 					cfg->current_request_stages++;
812f6ad3f23SAlexander Motin #define IDON(x)		(!!((x)[2] & SESCTL_RQSID))
813f6ad3f23SAlexander Motin 				if (IDON(req->elm_stat) != IDON(ep->encstat))
814f6ad3f23SAlexander Motin 					cfg->current_request_stages++;
815f6ad3f23SAlexander Motin 				break;
816f6ad3f23SAlexander Motin 			case 1:
817f6ad3f23SAlexander Motin 			case 2:
818f6ad3f23SAlexander Motin 				buf[0] = SAFTE_WT_SLTOP;
819f6ad3f23SAlexander Motin 				buf[1] = idx - cfg->slotoff;
820f6ad3f23SAlexander Motin 				if (cfg->current_request_stage == 1 &&
821f6ad3f23SAlexander Motin 				    DEVON(req->elm_stat) != DEVON(ep->encstat)) {
822f6ad3f23SAlexander Motin 					if (DEVON(req->elm_stat))
823f6ad3f23SAlexander Motin 						buf[2] = 0x01;
824f6ad3f23SAlexander Motin 					else
825f6ad3f23SAlexander Motin 						buf[2] = 0x02;
826f6ad3f23SAlexander Motin 				} else {
827f6ad3f23SAlexander Motin 					if (IDON(req->elm_stat))
828f6ad3f23SAlexander Motin 						buf[2] = 0x04;
829f6ad3f23SAlexander Motin 					else
830f6ad3f23SAlexander Motin 						buf[2] = 0x00;
831f6ad3f23SAlexander Motin 					ep->encstat[2] &= ~SESCTL_RQSID;
832f6ad3f23SAlexander Motin 					ep->encstat[2] |= req->elm_stat[2] &
833f6ad3f23SAlexander Motin 					    SESCTL_RQSID;
834f6ad3f23SAlexander Motin 				}
835f6ad3f23SAlexander Motin 				xfer_len = 64;
836f6ad3f23SAlexander Motin 				break;
837f6ad3f23SAlexander Motin 			default:
838f6ad3f23SAlexander Motin 				return (EINVAL);
839f6ad3f23SAlexander Motin 			}
840f6ad3f23SAlexander Motin 			break;
841f6ad3f23SAlexander Motin 		case ELMTYP_POWER:
842f6ad3f23SAlexander Motin 			cfg->current_request_stages = 2;
843f6ad3f23SAlexander Motin 			switch (cfg->current_request_stage) {
844f6ad3f23SAlexander Motin 			case 0:
845f6ad3f23SAlexander Motin 				if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
846f6ad3f23SAlexander Motin 					cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
847f6ad3f23SAlexander Motin 				} else {
848f6ad3f23SAlexander Motin 					cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
849f6ad3f23SAlexander Motin 				}
850f6ad3f23SAlexander Motin 				buf[0] = SAFTE_WT_GLOBAL;
851f6ad3f23SAlexander Motin 				buf[1] = cfg->flag1;
852f6ad3f23SAlexander Motin 				buf[2] = cfg->flag2;
853f6ad3f23SAlexander Motin 				buf[3] = 0;
854f6ad3f23SAlexander Motin 				xfer_len = 16;
855f6ad3f23SAlexander Motin 				break;
856f6ad3f23SAlexander Motin 			case 1:
857f6ad3f23SAlexander Motin 				buf[0] = SAFTE_WT_ACTPWS;
858f6ad3f23SAlexander Motin 				buf[1] = idx - cfg->pwroff;
859f6ad3f23SAlexander Motin 				if (req->elm_stat[3] & SESCTL_RQSTON)
860f6ad3f23SAlexander Motin 					buf[2] = 0x01;
861f6ad3f23SAlexander Motin 				else
862f6ad3f23SAlexander Motin 					buf[2] = 0x00;
863f6ad3f23SAlexander Motin 				buf[3] = 0;
864f6ad3f23SAlexander Motin 				xfer_len = 16;
865f6ad3f23SAlexander Motin 			default:
866f6ad3f23SAlexander Motin 				return (EINVAL);
867f6ad3f23SAlexander Motin 			}
868f6ad3f23SAlexander Motin 			break;
869f6ad3f23SAlexander Motin 		case ELMTYP_FAN:
870f6ad3f23SAlexander Motin 			if ((req->elm_stat[3] & 0x7) != 0)
871f6ad3f23SAlexander Motin 				cfg->current_request_stages = 2;
872f6ad3f23SAlexander Motin 			switch (cfg->current_request_stage) {
873f6ad3f23SAlexander Motin 			case 0:
874f6ad3f23SAlexander Motin 				if (req->elm_stat[3] & SESCTL_RQSTFAIL)
875f6ad3f23SAlexander Motin 					cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
876f6ad3f23SAlexander Motin 				else
877f6ad3f23SAlexander Motin 					cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
878f6ad3f23SAlexander Motin 				buf[0] = SAFTE_WT_GLOBAL;
879f6ad3f23SAlexander Motin 				buf[1] = cfg->flag1;
880f6ad3f23SAlexander Motin 				buf[2] = cfg->flag2;
881f6ad3f23SAlexander Motin 				buf[3] = 0;
882f6ad3f23SAlexander Motin 				xfer_len = 16;
883f6ad3f23SAlexander Motin 				break;
884f6ad3f23SAlexander Motin 			case 1:
885f6ad3f23SAlexander Motin 				buf[0] = SAFTE_WT_FANSPD;
886f6ad3f23SAlexander Motin 				buf[1] = idx;
887f6ad3f23SAlexander Motin 				if (req->elm_stat[3] & SESCTL_RQSTON) {
888f6ad3f23SAlexander Motin 					if ((req->elm_stat[3] & 0x7) == 7)
889f6ad3f23SAlexander Motin 						buf[2] = 4;
890f6ad3f23SAlexander Motin 					else if ((req->elm_stat[3] & 0x7) >= 5)
891f6ad3f23SAlexander Motin 						buf[2] = 3;
892f6ad3f23SAlexander Motin 					else if ((req->elm_stat[3] & 0x7) >= 3)
893f6ad3f23SAlexander Motin 						buf[2] = 2;
894f6ad3f23SAlexander Motin 					else
895f6ad3f23SAlexander Motin 						buf[2] = 1;
896f6ad3f23SAlexander Motin 				} else
897f6ad3f23SAlexander Motin 					buf[2] = 0;
898f6ad3f23SAlexander Motin 				buf[3] = 0;
899f6ad3f23SAlexander Motin 				xfer_len = 16;
900f6ad3f23SAlexander Motin 				ep->encstat[3] = req->elm_stat[3] & 0x67;
901f6ad3f23SAlexander Motin 			default:
902f6ad3f23SAlexander Motin 				return (EINVAL);
903f6ad3f23SAlexander Motin 			}
904f6ad3f23SAlexander Motin 			break;
905f6ad3f23SAlexander Motin 		case ELMTYP_DOORLOCK:
906f6ad3f23SAlexander Motin 			if (req->elm_stat[3] & 0x1)
907f6ad3f23SAlexander Motin 				cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
908f6ad3f23SAlexander Motin 			else
909f6ad3f23SAlexander Motin 				cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
910f6ad3f23SAlexander Motin 			buf[0] = SAFTE_WT_GLOBAL;
911f6ad3f23SAlexander Motin 			buf[1] = cfg->flag1;
912f6ad3f23SAlexander Motin 			buf[2] = cfg->flag2;
913f6ad3f23SAlexander Motin 			buf[3] = 0;
914f6ad3f23SAlexander Motin 			xfer_len = 16;
915f6ad3f23SAlexander Motin 			break;
916f6ad3f23SAlexander Motin 		case ELMTYP_ALARM:
917f6ad3f23SAlexander Motin 			if ((req->elm_stat[0] & SESCTL_DISABLE) ||
918f6ad3f23SAlexander Motin 			    (req->elm_stat[3] & 0x40)) {
919f6ad3f23SAlexander Motin 				cfg->flag2 &= ~SAFT_FLG1_ALARM;
920f6ad3f23SAlexander Motin 			} else if ((req->elm_stat[3] & 0x0f) != 0) {
921f6ad3f23SAlexander Motin 				cfg->flag2 |= SAFT_FLG1_ALARM;
922f6ad3f23SAlexander Motin 			} else {
923f6ad3f23SAlexander Motin 				cfg->flag2 &= ~SAFT_FLG1_ALARM;
924f6ad3f23SAlexander Motin 			}
925f6ad3f23SAlexander Motin 			buf[0] = SAFTE_WT_GLOBAL;
926f6ad3f23SAlexander Motin 			buf[1] = cfg->flag1;
927f6ad3f23SAlexander Motin 			buf[2] = cfg->flag2;
928f6ad3f23SAlexander Motin 			buf[3] = 0;
929f6ad3f23SAlexander Motin 			xfer_len = 16;
930f6ad3f23SAlexander Motin 			ep->encstat[3] = req->elm_stat[3];
931f6ad3f23SAlexander Motin 			break;
932f6ad3f23SAlexander Motin 		default:
933f6ad3f23SAlexander Motin 			return (EINVAL);
934f6ad3f23SAlexander Motin 		}
935f6ad3f23SAlexander Motin 	}
936f6ad3f23SAlexander Motin 
937f6ad3f23SAlexander Motin 	if (enc->enc_type == ENC_SEMB_SAFT) {
938f6ad3f23SAlexander Motin 		semb_write_buffer(&ccb->ataio, /*retries*/5,
939227d67aaSAlexander Motin 				NULL, MSG_SIMPLE_Q_TAG,
940f6ad3f23SAlexander Motin 				buf, xfer_len, state->timeout);
941f6ad3f23SAlexander Motin 	} else {
942f6ad3f23SAlexander Motin 		scsi_write_buffer(&ccb->csio, /*retries*/5,
943227d67aaSAlexander Motin 				NULL, MSG_SIMPLE_Q_TAG, 1,
944f6ad3f23SAlexander Motin 				0, 0, buf, xfer_len,
945f6ad3f23SAlexander Motin 				SSD_FULL_SIZE, state->timeout);
946f6ad3f23SAlexander Motin 	}
947f6ad3f23SAlexander Motin 	return (0);
948f6ad3f23SAlexander Motin }
949f6ad3f23SAlexander Motin 
950f6ad3f23SAlexander Motin static int
safte_process_control_request(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)951f6ad3f23SAlexander Motin safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
952f6ad3f23SAlexander Motin     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
953f6ad3f23SAlexander Motin {
954f6ad3f23SAlexander Motin 	struct scfg *cfg;
955f6ad3f23SAlexander Motin 	safte_control_request_t *req;
956f6ad3f23SAlexander Motin 	int idx, type;
957f6ad3f23SAlexander Motin 
958f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
959f6ad3f23SAlexander Motin 	if (cfg == NULL)
960f6ad3f23SAlexander Motin 		return (ENXIO);
961f6ad3f23SAlexander Motin 
962f6ad3f23SAlexander Motin 	req = cfg->current_request;
963f6ad3f23SAlexander Motin 	if (req->result == 0)
964f6ad3f23SAlexander Motin 		req->result = error;
965f6ad3f23SAlexander Motin 	if (++cfg->current_request_stage >= cfg->current_request_stages) {
966f6ad3f23SAlexander Motin 		idx = req->elm_idx;
967f6ad3f23SAlexander Motin 		if (idx == SES_SETSTATUS_ENC_IDX)
968f6ad3f23SAlexander Motin 			type = -1;
969f6ad3f23SAlexander Motin 		else
97053f5ac13SAlexander Motin 			type = enc->enc_cache.elm_map[idx].elm_type;
971f6ad3f23SAlexander Motin 		if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
972f6ad3f23SAlexander Motin 			enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
973f6ad3f23SAlexander Motin 		else
974f6ad3f23SAlexander Motin 			enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
975f6ad3f23SAlexander Motin 		cfg->current_request = NULL;
976f6ad3f23SAlexander Motin 		wakeup(req);
977f6ad3f23SAlexander Motin 	} else {
978f6ad3f23SAlexander Motin 		enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
979f6ad3f23SAlexander Motin 	}
980f6ad3f23SAlexander Motin 	return (0);
981f6ad3f23SAlexander Motin }
982f6ad3f23SAlexander Motin 
983f6ad3f23SAlexander Motin static void
safte_softc_invalidate(enc_softc_t * enc)984f6ad3f23SAlexander Motin safte_softc_invalidate(enc_softc_t *enc)
985f6ad3f23SAlexander Motin {
986f6ad3f23SAlexander Motin 	struct scfg *cfg;
987f6ad3f23SAlexander Motin 
988f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
989f6ad3f23SAlexander Motin 	safte_terminate_control_requests(&cfg->requests, ENXIO);
990f6ad3f23SAlexander Motin }
991f6ad3f23SAlexander Motin 
992f6ad3f23SAlexander Motin static void
safte_softc_cleanup(enc_softc_t * enc)993f6ad3f23SAlexander Motin safte_softc_cleanup(enc_softc_t *enc)
994f6ad3f23SAlexander Motin {
995f6ad3f23SAlexander Motin 
996f6ad3f23SAlexander Motin 	ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
997f6ad3f23SAlexander Motin 	ENC_FREE_AND_NULL(enc->enc_private);
998f6ad3f23SAlexander Motin 	enc->enc_cache.nelms = 0;
999f6ad3f23SAlexander Motin }
1000f6ad3f23SAlexander Motin 
1001f6ad3f23SAlexander Motin static int
safte_init_enc(enc_softc_t * enc)1002f6ad3f23SAlexander Motin safte_init_enc(enc_softc_t *enc)
1003f6ad3f23SAlexander Motin {
1004f6ad3f23SAlexander Motin 	struct scfg *cfg;
1005f6ad3f23SAlexander Motin 	int err;
1006f6ad3f23SAlexander Motin 	static char cdb0[6] = { SEND_DIAGNOSTIC };
1007f6ad3f23SAlexander Motin 
1008f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
1009f6ad3f23SAlexander Motin 	if (cfg == NULL)
1010f6ad3f23SAlexander Motin 		return (ENXIO);
1011f6ad3f23SAlexander Motin 
1012f6ad3f23SAlexander Motin 	err = enc_runcmd(enc, cdb0, 6, NULL, 0);
1013f6ad3f23SAlexander Motin 	if (err) {
1014f6ad3f23SAlexander Motin 		return (err);
1015f6ad3f23SAlexander Motin 	}
1016f6ad3f23SAlexander Motin 	DELAY(5000);
1017f6ad3f23SAlexander Motin 	cfg->flag1 = 0;
1018f6ad3f23SAlexander Motin 	cfg->flag2 = 0;
1019f6ad3f23SAlexander Motin 	err = safte_set_enc_status(enc, 0, 1);
1020f6ad3f23SAlexander Motin 	return (err);
1021f6ad3f23SAlexander Motin }
1022f6ad3f23SAlexander Motin 
1023f6ad3f23SAlexander Motin static int
safte_set_enc_status(enc_softc_t * enc,uint8_t encstat,int slpflag)1024f6ad3f23SAlexander Motin safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
1025f6ad3f23SAlexander Motin {
1026f6ad3f23SAlexander Motin 	struct scfg *cfg;
1027f6ad3f23SAlexander Motin 	safte_control_request_t req;
1028f6ad3f23SAlexander Motin 
1029f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
1030f6ad3f23SAlexander Motin 	if (cfg == NULL)
1031f6ad3f23SAlexander Motin 		return (ENXIO);
1032f6ad3f23SAlexander Motin 
1033f6ad3f23SAlexander Motin 	req.elm_idx = SES_SETSTATUS_ENC_IDX;
1034f6ad3f23SAlexander Motin 	req.elm_stat[0] = encstat & 0xf;
1035f6ad3f23SAlexander Motin 	req.result = 0;
1036f6ad3f23SAlexander Motin 
1037f6ad3f23SAlexander Motin 	TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1038f6ad3f23SAlexander Motin 	enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1039f6ad3f23SAlexander Motin 	cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1040f6ad3f23SAlexander Motin 
1041f6ad3f23SAlexander Motin 	return (req.result);
1042f6ad3f23SAlexander Motin }
1043f6ad3f23SAlexander Motin 
1044f6ad3f23SAlexander Motin static int
safte_get_elm_status(enc_softc_t * enc,encioc_elm_status_t * elms,int slpflg)1045f6ad3f23SAlexander Motin safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
1046f6ad3f23SAlexander Motin {
1047f6ad3f23SAlexander Motin 	int i = (int)elms->elm_idx;
1048f6ad3f23SAlexander Motin 
1049f6ad3f23SAlexander Motin 	elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
1050f6ad3f23SAlexander Motin 	elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
1051f6ad3f23SAlexander Motin 	elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
1052f6ad3f23SAlexander Motin 	elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
1053f6ad3f23SAlexander Motin 	return (0);
1054f6ad3f23SAlexander Motin }
1055f6ad3f23SAlexander Motin 
1056f6ad3f23SAlexander Motin static int
safte_set_elm_status(enc_softc_t * enc,encioc_elm_status_t * elms,int slpflag)1057f6ad3f23SAlexander Motin safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
1058f6ad3f23SAlexander Motin {
1059f6ad3f23SAlexander Motin 	struct scfg *cfg;
1060f6ad3f23SAlexander Motin 	safte_control_request_t req;
1061f6ad3f23SAlexander Motin 
1062f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
1063f6ad3f23SAlexander Motin 	if (cfg == NULL)
1064f6ad3f23SAlexander Motin 		return (ENXIO);
1065f6ad3f23SAlexander Motin 
1066f6ad3f23SAlexander Motin 	/* If this is clear, we don't do diddly.  */
1067f6ad3f23SAlexander Motin 	if ((elms->cstat[0] & SESCTL_CSEL) == 0)
1068f6ad3f23SAlexander Motin 		return (0);
1069f6ad3f23SAlexander Motin 
1070f6ad3f23SAlexander Motin 	req.elm_idx = elms->elm_idx;
1071f6ad3f23SAlexander Motin 	memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
1072f6ad3f23SAlexander Motin 	req.result = 0;
1073f6ad3f23SAlexander Motin 
1074f6ad3f23SAlexander Motin 	TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1075f6ad3f23SAlexander Motin 	enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1076f6ad3f23SAlexander Motin 	cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1077f6ad3f23SAlexander Motin 
1078f6ad3f23SAlexander Motin 	return (req.result);
1079f6ad3f23SAlexander Motin }
1080f6ad3f23SAlexander Motin 
1081f6ad3f23SAlexander Motin static void
safte_poll_status(enc_softc_t * enc)1082f6ad3f23SAlexander Motin safte_poll_status(enc_softc_t *enc)
1083f6ad3f23SAlexander Motin {
1084f6ad3f23SAlexander Motin 
1085f6ad3f23SAlexander Motin 	enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
1086f6ad3f23SAlexander Motin 	enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
1087f6ad3f23SAlexander Motin }
1088f6ad3f23SAlexander Motin 
1089f6ad3f23SAlexander Motin static struct enc_vec safte_enc_vec =
1090f6ad3f23SAlexander Motin {
1091f6ad3f23SAlexander Motin 	.softc_invalidate	= safte_softc_invalidate,
1092f6ad3f23SAlexander Motin 	.softc_cleanup	= safte_softc_cleanup,
1093f6ad3f23SAlexander Motin 	.init_enc	= safte_init_enc,
1094f6ad3f23SAlexander Motin 	.set_enc_status	= safte_set_enc_status,
1095f6ad3f23SAlexander Motin 	.get_elm_status	= safte_get_elm_status,
1096f6ad3f23SAlexander Motin 	.set_elm_status	= safte_set_elm_status,
1097f6ad3f23SAlexander Motin 	.poll_status	= safte_poll_status
1098f6ad3f23SAlexander Motin };
1099f6ad3f23SAlexander Motin 
1100f6ad3f23SAlexander Motin int
safte_softc_init(enc_softc_t * enc)1101f6ad3f23SAlexander Motin safte_softc_init(enc_softc_t *enc)
1102f6ad3f23SAlexander Motin {
1103f6ad3f23SAlexander Motin 	struct scfg *cfg;
1104f6ad3f23SAlexander Motin 
1105f6ad3f23SAlexander Motin 	enc->enc_vec = safte_enc_vec;
1106f6ad3f23SAlexander Motin 	enc->enc_fsm_states = enc_fsm_states;
1107f6ad3f23SAlexander Motin 
1108f6ad3f23SAlexander Motin 	if (enc->enc_private == NULL) {
1109f6ad3f23SAlexander Motin 		enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
1110f6ad3f23SAlexander Motin 		if (enc->enc_private == NULL)
1111f6ad3f23SAlexander Motin 			return (ENOMEM);
1112f6ad3f23SAlexander Motin 	}
1113f6ad3f23SAlexander Motin 	cfg = enc->enc_private;
1114f6ad3f23SAlexander Motin 
1115f6ad3f23SAlexander Motin 	enc->enc_cache.nelms = 0;
1116f6ad3f23SAlexander Motin 	enc->enc_cache.enc_status = 0;
1117f6ad3f23SAlexander Motin 
1118f6ad3f23SAlexander Motin 	TAILQ_INIT(&cfg->requests);
1119f6ad3f23SAlexander Motin 	return (0);
1120f6ad3f23SAlexander Motin }
1121