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