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