2 * Copyright (c) 2000 Matthew Jacob
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.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>
39 #include <sys/systm.h>
40 #include <sys/sysctl.h>
41 #include <sys/types.h>
44 #include <cam/cam_ccb.h>
45 #include <cam/cam_periph.h>
47 #include <cam/scsi/scsi_enc.h>
48 #include <cam/scsi/scsi_enc_internal.h>
49 #include <cam/scsi/scsi_message.h>
52 * SAF-TE Type Device Emulation
55 static int safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag);
57 #define ALL_ENC_STAT (SES_ENCSTAT_CRITICAL | SES_ENCSTAT_UNRECOV | \
58 SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
60 * SAF-TE specific defines- Mandatory ones only...
64 * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
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 */
72 * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
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 */
80 #define SAFT_SCRATCH 64
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;
93 static fsm_fill_handler_t safte_fill_read_buf_io;
94 static fsm_fill_handler_t safte_fill_control_request;
95 static fsm_done_handler_t safte_process_config;
96 static fsm_done_handler_t safte_process_gflags;
97 static fsm_done_handler_t safte_process_status;
98 static fsm_done_handler_t safte_process_slotstatus;
99 static fsm_done_handler_t safte_process_control_request;
101 static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES] =
103 { "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
105 "SAFTE_UPDATE_READCONFIG",
109 safte_fill_read_buf_io,
110 safte_process_config,
114 "SAFTE_UPDATE_READGFLAGS",
118 safte_fill_read_buf_io,
119 safte_process_gflags,
123 "SAFTE_UPDATE_READENCSTATUS",
127 safte_fill_read_buf_io,
128 safte_process_status,
132 "SAFTE_UPDATE_READSLOTSTATUS",
136 safte_fill_read_buf_io,
137 safte_process_slotstatus,
141 "SAFTE_PROCESS_CONTROL_REQS",
145 safte_fill_control_request,
146 safte_process_control_request,
151 typedef struct safte_control_request {
155 TAILQ_ENTRY(safte_control_request) links;
156 } safte_control_request_t;
157 TAILQ_HEAD(safte_control_reqlist, safte_control_request);
158 typedef struct safte_control_reqlist safte_control_reqlist_t;
160 SES_SETSTATUS_ENC_IDX = -1
164 safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
166 safte_control_request_t *req;
168 while ((req = TAILQ_FIRST(reqlist)) != NULL) {
169 TAILQ_REMOVE(reqlist, req, links);
170 req->result = result;
177 * Cached Configuration
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 */
187 * Cached Flag Bytes for Global Status
192 * What object index ID is where various slots start.
196 #define SAFT_ALARM_OFFSET(cc) (cc)->slotoff - 1
198 encioc_enc_status_t adm_status;
199 encioc_enc_status_t enc_status;
200 encioc_enc_status_t slot_status;
202 safte_control_reqlist_t requests;
203 safte_control_request_t *current_request;
204 int current_request_stage;
205 int current_request_stages;
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
217 #define SAFT_FLG2_LOCKDOOR 0x4
218 #define SAFT_PRIVATE sizeof (struct scfg)
220 static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
221 #define SAFT_BAIL(r, x) \
223 ENC_VLOG(enc, safte_2little, x, __LINE__);\
227 int emulate_array_devices = 1;
228 SYSCTL_DECL(_kern_cam_enc);
229 SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN,
230 &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
233 safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
234 union ccb *ccb, uint8_t *buf)
237 if (state->page_code != SAFTE_RD_RDCFG &&
238 enc->enc_cache.nelms == 0) {
239 enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
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,
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);
258 safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
259 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
262 uint8_t *buf = *bufp;
265 cfg = enc->enc_private;
271 ENC_VLOG(enc, "too little data (%d) for configuration\n",
277 cfg->Nslots = buf[2];
278 cfg->DoorLock = buf[3];
279 cfg->Ntherm = buf[4];
280 cfg->Nspkrs = buf[5];
282 cfg->Ntstats = buf[6] & 0x0f;
285 ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
287 cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
288 cfg->Nspkrs, cfg->Ntstats);
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;
302 * Note that this is all arranged for the convenience
303 * in later fetches of status.
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;
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 :
324 enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
325 enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
326 enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
332 safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
333 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
336 uint8_t *buf = *bufp;
338 cfg = enc->enc_private;
343 SAFT_BAIL(3, xfer_len);
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;
357 safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
358 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
361 uint8_t *buf = *bufp;
362 int oid, r, i, nitems;
364 enc_cache_t *cache = &enc->enc_cache;
366 cfg = enc->enc_private;
375 for (nitems = i = 0; i < cfg->Nfans; i++) {
376 SAFT_BAIL(r, xfer_len);
378 * 0 = Fan Operational
379 * 1 = Fan is malfunctioning
380 * 2 = Fan is not present
381 * 0x80 = Unknown or Not Reportable Status
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;
388 cache->elm_map[oid].encstat[3] &= ~0x40;
389 switch ((int)buf[r]) {
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;
398 cache->elm_map[oid].encstat[0] =
401 * FAIL and FAN STOPPED synthesized
403 cache->elm_map[oid].encstat[3] |= 0x10;
404 cache->elm_map[oid].encstat[3] &= ~0x07;
406 * Enclosure marked with CRITICAL error
407 * if only one fan or no thermometers,
408 * else the NONCRITICAL error is set.
410 if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
411 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
413 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
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;
421 * Enclosure marked with CRITICAL error
422 * if only one fan or no thermometers,
423 * else the NONCRITICAL error is set.
426 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
428 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
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;
436 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
437 ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
441 cache->elm_map[oid++].svalid = 1;
446 * No matter how you cut it, no cooling elements when there
447 * should be some there is critical.
449 if (cfg->Nfans && nitems == 0)
450 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
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 */
459 case 0x00: /* pws operational and on */
460 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
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;
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;
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;
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;
484 case 0x21: /* pws is present */
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.
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;
497 ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
501 enc->enc_cache.elm_map[oid++].svalid = 1;
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];
516 * We always have doorlock status, no matter what,
517 * but we only save the status if we have one.
519 SAFT_BAIL(r, xfer_len);
523 * 1 = Door Unlocked, or no Lock Installed
524 * 0x80 = Unknown or Not Reportable Status
526 cache->elm_map[oid].encstat[1] = 0;
527 cache->elm_map[oid].encstat[2] = 0;
530 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
531 cache->elm_map[oid].encstat[3] = 0;
534 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
535 cache->elm_map[oid].encstat[3] = 1;
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;
543 cache->elm_map[oid].encstat[0] =
544 SES_OBJSTAT_UNSUPPORTED;
545 ENC_VLOG(enc, "unknown lock status 0x%x\n",
549 cache->elm_map[oid++].svalid = 1;
554 * We always have speaker status, no matter what,
555 * but we only save the status if we have one.
557 SAFT_BAIL(r, xfer_len);
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;
563 cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
564 cache->elm_map[oid].encstat[3] |= 0x40;
566 cache->elm_map[oid++].svalid = 1;
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.
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];
585 for (i = 0; i < cfg->Ntherm; i++) {
586 SAFT_BAIL(r, xfer_len);
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.
595 * So what's over and under temperature?
596 * Hmm- we'll state that 'normal' operating
597 * is 10 to 40 deg Celsius.
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.
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.
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.
617 if (tempflags & (1 << i)) {
618 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
619 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
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;
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;
636 * Set 'over temperature' failure.
638 cache->elm_map[oid].encstat[3] = 8;
639 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
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
647 if ((cfg->Ntherm + cfg->Ntstats) == 0)
648 cache->elm_map[oid].encstat[0] =
649 SES_OBJSTAT_NOTAVAIL;
651 cache->elm_map[oid].encstat[0] =
653 cache->elm_map[oid].encstat[2] = 0;
654 cache->elm_map[oid].encstat[3] = 0;
656 cache->elm_map[oid++].svalid = 1;
661 cfg->enc_status | cfg->slot_status | cfg->adm_status;
666 safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
667 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
670 uint8_t *buf = *bufp;
671 enc_cache_t *cache = &enc->enc_cache;
674 cfg = enc->enc_private;
679 cfg->slot_status = 0;
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;
696 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
698 if (buf[r+3] & 0x2) {
700 cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
702 cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
704 if ((buf[r+3] & 0x04) == 0)
705 cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
707 cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
709 cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
710 if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
712 cache->elm_map[oid].encstat[1] |= 0x80;
714 cache->elm_map[oid].encstat[1] |= 0x02;
716 cache->elm_map[oid].encstat[1] |= 0x04;
718 cache->elm_map[oid].encstat[1] |= 0x08;
720 cache->elm_map[oid].encstat[1] |= 0x10;
722 cache->elm_map[oid].encstat[1] |= 0x20;
724 cache->elm_map[oid].encstat[1] |= 0x01;
726 cache->elm_map[oid++].svalid = 1;
730 cfg->enc_status | cfg->slot_status | cfg->adm_status;
735 safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
736 union ccb *ccb, uint8_t *buf)
739 enc_element_t *ep, *ep1;
740 safte_control_request_t *req;
741 int i, idx, xfer_len;
743 cfg = enc->enc_private;
747 if (enc->enc_cache.nelms == 0) {
748 enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
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;
758 req = cfg->current_request;
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;
774 ep = &enc->enc_cache.elm_map[idx];
776 switch (ep->enctype) {
778 case ELMTYP_ARRAY_DEV:
779 switch (cfg->current_request_stage) {
782 if (req->elm_stat[0] & SESCTL_PRDFAIL)
784 if (req->elm_stat[3] & SESCTL_RQSFLT)
786 if (ep->enctype == ELMTYP_ARRAY_DEV) {
787 if (req->elm_stat[1] & 0x01)
789 if (req->elm_stat[1] & 0x02)
791 if (req->elm_stat[1] & 0x04)
793 if (req->elm_stat[1] & 0x08)
795 if (req->elm_stat[1] & 0x10)
797 if (req->elm_stat[1] & 0x20)
799 if (req->elm_stat[1] & 0x80)
803 ep->priv |= 0x01; /* no errors */
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;
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++;
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))
832 if (IDON(req->elm_stat))
836 ep->encstat[2] &= ~SESCTL_RQSID;
837 ep->encstat[2] |= req->elm_stat[2] &
847 cfg->current_request_stages = 2;
848 switch (cfg->current_request_stage) {
850 if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
851 cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
853 cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
855 buf[0] = SAFTE_WT_GLOBAL;
862 buf[0] = SAFTE_WT_ACTPWS;
863 buf[1] = idx - cfg->pwroff;
864 if (req->elm_stat[3] & SESCTL_RQSTON)
875 if ((req->elm_stat[3] & 0x7) != 0)
876 cfg->current_request_stages = 2;
877 switch (cfg->current_request_stage) {
879 if (req->elm_stat[3] & SESCTL_RQSTFAIL)
880 cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
882 cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
883 buf[0] = SAFTE_WT_GLOBAL;
890 buf[0] = SAFTE_WT_FANSPD;
892 if (req->elm_stat[3] & SESCTL_RQSTON) {
893 if ((req->elm_stat[3] & 0x7) == 7)
895 else if ((req->elm_stat[3] & 0x7) >= 5)
897 else if ((req->elm_stat[3] & 0x7) >= 3)
905 ep->encstat[3] = req->elm_stat[3] & 0x67;
910 case ELMTYP_DOORLOCK:
911 if (req->elm_stat[3] & 0x1)
912 cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
914 cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
915 buf[0] = SAFTE_WT_GLOBAL;
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;
928 cfg->flag2 &= ~SAFT_FLG1_ALARM;
930 buf[0] = SAFTE_WT_GLOBAL;
935 ep->encstat[3] = req->elm_stat[3];
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);
947 scsi_write_buffer(&ccb->csio, /*retries*/5,
948 NULL, MSG_SIMPLE_Q_TAG, 1,
950 SSD_FULL_SIZE, state->timeout);
956 safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
957 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
960 safte_control_request_t *req;
963 cfg = enc->enc_private;
967 req = cfg->current_request;
968 if (req->result == 0)
970 if (++cfg->current_request_stage >= cfg->current_request_stages) {
972 if (idx == SES_SETSTATUS_ENC_IDX)
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);
979 enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
980 cfg->current_request = NULL;
983 enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
989 safte_softc_invalidate(enc_softc_t *enc)
993 cfg = enc->enc_private;
994 safte_terminate_control_requests(&cfg->requests, ENXIO);
998 safte_softc_cleanup(enc_softc_t *enc)
1001 ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
1002 ENC_FREE_AND_NULL(enc->enc_private);
1003 enc->enc_cache.nelms = 0;
1007 safte_init_enc(enc_softc_t *enc)
1011 static char cdb0[6] = { SEND_DIAGNOSTIC };
1013 cfg = enc->enc_private;
1017 err = enc_runcmd(enc, cdb0, 6, NULL, 0);
1024 err = safte_set_enc_status(enc, 0, 1);
1029 safte_get_enc_status(enc_softc_t *enc, int slpflg)
1036 safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
1039 safte_control_request_t req;
1041 cfg = enc->enc_private;
1045 req.elm_idx = SES_SETSTATUS_ENC_IDX;
1046 req.elm_stat[0] = encstat & 0xf;
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);
1053 return (req.result);
1057 safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
1059 int i = (int)elms->elm_idx;
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];
1069 safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
1072 safte_control_request_t req;
1074 cfg = enc->enc_private;
1078 /* If this is clear, we don't do diddly. */
1079 if ((elms->cstat[0] & SESCTL_CSEL) == 0)
1082 req.elm_idx = elms->elm_idx;
1083 memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
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);
1090 return (req.result);
1094 safte_poll_status(enc_softc_t *enc)
1097 enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
1098 enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
1101 static struct enc_vec safte_enc_vec =
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
1114 safte_softc_init(enc_softc_t *enc)
1118 enc->enc_vec = safte_enc_vec;
1119 enc->enc_fsm_states = enc_fsm_states;
1121 if (enc->enc_private == NULL) {
1122 enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
1123 if (enc->enc_private == NULL)
1126 cfg = enc->enc_private;
1128 enc->enc_cache.nelms = 0;
1129 enc->enc_cache.enc_status = 0;
1131 TAILQ_INIT(&cfg->requests);