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