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