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