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