FreeBSD kernel CAM code
scsi_enc_safte.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2000 Matthew Jacob
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification, immediately at the beginning of the file.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33
34#include <sys/conf.h>
35#include <sys/errno.h>
36#include <sys/kernel.h>
37#include <sys/malloc.h>
38#include <sys/mutex.h>
39#include <sys/queue.h>
40#include <sys/sx.h>
41#include <sys/systm.h>
42#include <sys/sysctl.h>
43#include <sys/types.h>
44
45#include <cam/cam.h>
46#include <cam/cam_ccb.h>
47#include <cam/cam_periph.h>
48
49#include <cam/scsi/scsi_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 {
94
102
104{
105 { "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
106 {
107 "SAFTE_UPDATE_READCONFIG",
110 60 * 1000,
114 },
115 {
116 "SAFTE_UPDATE_READGFLAGS",
118 16,
119 60 * 1000,
123 },
124 {
125 "SAFTE_UPDATE_READENCSTATUS",
127 SCSZ,
128 60 * 1000,
132 },
133 {
134 "SAFTE_UPDATE_READSLOTSTATUS",
136 SCSZ,
137 60 * 1000,
141 },
142 {
143 "SAFTE_PROCESS_CONTROL_REQS",
144 0,
145 SCSZ,
146 60 * 1000,
150 }
151};
152
153typedef struct safte_control_request {
155 uint8_t elm_stat[4];
157 TAILQ_ENTRY(safte_control_request) links;
159TAILQ_HEAD(safte_control_reqlist, safte_control_request);
160typedef struct safte_control_reqlist safte_control_reqlist_t;
161enum {
164
165static void
167{
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
203
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_VLOG(enc, safte_2little, x, __LINE__);\
226 return (EIO); \
227 }
228
230SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN,
231 &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
232
233static int
235 union ccb *ccb, uint8_t *buf)
236{
237
238 if (state->page_code != SAFTE_RD_RDCFG &&
239 enc->enc_cache.nelms == 0) {
241 return (-1);
242 }
243
244 if (enc->enc_type == ENC_SEMB_SAFT) {
245 semb_read_buffer(&ccb->ataio, /*retries*/5,
246 NULL, MSG_SIMPLE_Q_TAG,
247 state->page_code, buf, state->buf_size,
248 state->timeout);
249 } else {
250 scsi_read_buffer(&ccb->csio, /*retries*/5,
251 NULL, MSG_SIMPLE_Q_TAG, 1,
252 state->page_code, 0, buf, state->buf_size,
253 SSD_FULL_SIZE, state->timeout);
254 }
255 return (0);
256}
257
258static int
260 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
261{
262 struct scfg *cfg;
263 uint8_t *buf = *bufp;
264 int i, r;
265
266 cfg = enc->enc_private;
267 if (cfg == NULL)
268 return (ENXIO);
269 if (error != 0)
270 return (error);
271 if (xfer_len < 6) {
272 ENC_VLOG(enc, "too little data (%d) for configuration\n",
273 xfer_len);
274 return (EIO);
275 }
276 cfg->Nfans = buf[0];
277 cfg->Npwr = buf[1];
278 cfg->Nslots = buf[2];
279 cfg->DoorLock = buf[3];
280 cfg->Ntherm = buf[4];
281 cfg->Nspkrs = buf[5];
282 if (xfer_len >= 7)
283 cfg->Ntstats = buf[6] & 0x0f;
284 else
285 cfg->Ntstats = 0;
286 ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
287 "Ntstats %d\n",
288 cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
289 cfg->Nspkrs, cfg->Ntstats);
290
291 enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots +
292 cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1;
294 enc->enc_cache.elm_map =
295 malloc(enc->enc_cache.nelms * sizeof(enc_element_t),
296 M_SCSIENC, M_WAITOK|M_ZERO);
297
298 r = 0;
299 /*
300 * Note that this is all arranged for the convenience
301 * in later fetches of status.
302 */
303 for (i = 0; i < cfg->Nfans; i++)
305 cfg->pwroff = (uint8_t) r;
306 for (i = 0; i < cfg->Npwr; i++)
308 for (i = 0; i < cfg->DoorLock; i++)
310 if (cfg->Nspkrs > 0)
312 for (i = 0; i < cfg->Ntherm; i++)
314 for (i = 0; i <= cfg->Ntstats; i++)
316 cfg->slotoff = (uint8_t) r;
317 for (i = 0; i < cfg->Nslots; i++)
318 enc->enc_cache.elm_map[r++].elm_type =
321
325
326 return (0);
327}
328
329static int
331 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
332{
333 struct scfg *cfg;
334 uint8_t *buf = *bufp;
335
336 cfg = enc->enc_private;
337 if (cfg == NULL)
338 return (ENXIO);
339 if (error != 0)
340 return (error);
341 SAFT_BAIL(3, xfer_len);
342 cfg->flag1 = buf[1];
343 cfg->flag2 = buf[2];
344
345 cfg->adm_status = 0;
346 if (cfg->flag1 & SAFT_FLG1_GLOBFAIL)
348 else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
350
351 return (0);
352}
353
354static int
356 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
357{
358 struct scfg *cfg;
359 uint8_t *buf = *bufp;
360 int oid, r, i, nitems;
361 uint16_t tempflags;
362 enc_cache_t *cache = &enc->enc_cache;
363
364 cfg = enc->enc_private;
365 if (cfg == NULL)
366 return (ENXIO);
367 if (error != 0)
368 return (error);
369
370 oid = r = 0;
371 cfg->enc_status = 0;
372
373 for (nitems = i = 0; i < cfg->Nfans; i++) {
374 SAFT_BAIL(r, xfer_len);
375 /*
376 * 0 = Fan Operational
377 * 1 = Fan is malfunctioning
378 * 2 = Fan is not present
379 * 0x80 = Unknown or Not Reportable Status
380 */
381 cache->elm_map[oid].encstat[1] = 0; /* resvd */
382 cache->elm_map[oid].encstat[2] = 0; /* resvd */
383 if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL)
384 cache->elm_map[oid].encstat[3] |= 0x40;
385 else
386 cache->elm_map[oid].encstat[3] &= ~0x40;
387 switch ((int)buf[r]) {
388 case 0:
389 nitems++;
390 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
391 if ((cache->elm_map[oid].encstat[3] & 0x37) == 0)
392 cache->elm_map[oid].encstat[3] |= 0x27;
393 break;
394
395 case 1:
396 cache->elm_map[oid].encstat[0] =
398 /*
399 * FAIL and FAN STOPPED synthesized
400 */
401 cache->elm_map[oid].encstat[3] |= 0x10;
402 cache->elm_map[oid].encstat[3] &= ~0x07;
403 /*
404 * Enclosure marked with CRITICAL error
405 * if only one fan or no thermometers,
406 * else the NONCRITICAL error is set.
407 */
408 if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
410 else
412 break;
413 case 2:
414 cache->elm_map[oid].encstat[0] =
416 cache->elm_map[oid].encstat[3] |= 0x10;
417 cache->elm_map[oid].encstat[3] &= ~0x07;
418 /*
419 * Enclosure marked with CRITICAL error
420 * if only one fan or no thermometers,
421 * else the NONCRITICAL error is set.
422 */
423 if (cfg->Nfans == 1)
425 else
427 break;
428 case 0x80:
429 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
430 cache->elm_map[oid].encstat[3] = 0;
432 break;
433 default:
434 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
435 ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
436 buf[r] & 0xff);
437 break;
438 }
439 cache->elm_map[oid++].svalid = 1;
440 r++;
441 }
442
443 /*
444 * No matter how you cut it, no cooling elements when there
445 * should be some there is critical.
446 */
447 if (cfg->Nfans && nitems == 0)
449
450 for (i = 0; i < cfg->Npwr; i++) {
451 SAFT_BAIL(r, xfer_len);
452 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
453 cache->elm_map[oid].encstat[1] = 0; /* resvd */
454 cache->elm_map[oid].encstat[2] = 0; /* resvd */
455 cache->elm_map[oid].encstat[3] = 0x20; /* requested on */
456 switch (buf[r]) {
457 case 0x00: /* pws operational and on */
458 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
459 break;
460 case 0x01: /* pws operational and off */
461 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
462 cache->elm_map[oid].encstat[3] = 0x10;
464 break;
465 case 0x10: /* pws is malfunctioning and commanded on */
466 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
467 cache->elm_map[oid].encstat[3] = 0x61;
469 break;
470
471 case 0x11: /* pws is malfunctioning and commanded off */
472 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
473 cache->elm_map[oid].encstat[3] = 0x51;
475 break;
476 case 0x20: /* pws is not present */
477 cache->elm_map[oid].encstat[0] =
479 cache->elm_map[oid].encstat[3] = 0;
481 break;
482 case 0x21: /* pws is present */
483 /*
484 * This is for enclosures that cannot tell whether the
485 * device is on or malfunctioning, but know that it is
486 * present. Just fall through.
487 */
488 /* FALLTHROUGH */
489 case 0x80: /* Unknown or Not Reportable Status */
490 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
491 cache->elm_map[oid].encstat[3] = 0;
493 break;
494 default:
495 ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
496 i, buf[r] & 0xff);
497 break;
498 }
499 enc->enc_cache.elm_map[oid++].svalid = 1;
500 r++;
501 }
502
503 /*
504 * Copy Slot SCSI IDs
505 */
506 for (i = 0; i < cfg->Nslots; i++) {
507 SAFT_BAIL(r, xfer_len);
508 if (cache->elm_map[cfg->slotoff + i].elm_type == ELMTYP_DEVICE)
509 cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
510 r++;
511 }
512
513 /*
514 * We always have doorlock status, no matter what,
515 * but we only save the status if we have one.
516 */
517 SAFT_BAIL(r, xfer_len);
518 if (cfg->DoorLock) {
519 /*
520 * 0 = Door Locked
521 * 1 = Door Unlocked, or no Lock Installed
522 * 0x80 = Unknown or Not Reportable Status
523 */
524 cache->elm_map[oid].encstat[1] = 0;
525 cache->elm_map[oid].encstat[2] = 0;
526 switch (buf[r]) {
527 case 0:
528 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
529 cache->elm_map[oid].encstat[3] = 0;
530 break;
531 case 1:
532 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
533 cache->elm_map[oid].encstat[3] = 1;
534 break;
535 case 0x80:
536 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
537 cache->elm_map[oid].encstat[3] = 0;
539 break;
540 default:
541 cache->elm_map[oid].encstat[0] =
543 ENC_VLOG(enc, "unknown lock status 0x%x\n",
544 buf[r] & 0xff);
545 break;
546 }
547 cache->elm_map[oid++].svalid = 1;
548 }
549 r++;
550
551 /*
552 * We always have speaker status, no matter what,
553 * but we only save the status if we have one.
554 */
555 SAFT_BAIL(r, xfer_len);
556 if (cfg->Nspkrs) {
557 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
558 cache->elm_map[oid].encstat[1] = 0;
559 cache->elm_map[oid].encstat[2] = 0;
560 if (buf[r] == 0) {
561 cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
562 cache->elm_map[oid].encstat[3] |= 0x40;
563 }
564 cache->elm_map[oid++].svalid = 1;
565 }
566 r++;
567
568 /*
569 * Now, for "pseudo" thermometers, we have two bytes
570 * of information in enclosure status- 16 bits. Actually,
571 * the MSB is a single TEMP ALERT flag indicating whether
572 * any other bits are set, but, thanks to fuzzy thinking,
573 * in the SAF-TE spec, this can also be set even if no
574 * other bits are set, thus making this really another
575 * binary temperature sensor.
576 */
577
578 SAFT_BAIL(r + cfg->Ntherm, xfer_len);
579 tempflags = buf[r + cfg->Ntherm];
580 SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len);
581 tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1];
582
583 for (i = 0; i < cfg->Ntherm; i++) {
584 SAFT_BAIL(r, xfer_len);
585 /*
586 * Status is a range from -10 to 245 deg Celsius,
587 * which we need to normalize to -20 to -245 according
588 * to the latest SCSI spec, which makes little
589 * sense since this would overflow an 8bit value.
590 * Well, still, the base normalization is -20,
591 * not -10, so we have to adjust.
592 *
593 * So what's over and under temperature?
594 * Hmm- we'll state that 'normal' operating
595 * is 10 to 40 deg Celsius.
596 */
597
598 /*
599 * Actually.... All of the units that people out in the world
600 * seem to have do not come even close to setting a value that
601 * complies with this spec.
602 *
603 * The closest explanation I could find was in an
604 * LSI-Logic manual, which seemed to indicate that
605 * this value would be set by whatever the I2C code
606 * would interpolate from the output of an LM75
607 * temperature sensor.
608 *
609 * This means that it is impossible to use the actual
610 * numeric value to predict anything. But we don't want
611 * to lose the value. So, we'll propagate the *uncorrected*
612 * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
613 * temperature flags for warnings.
614 */
615 if (tempflags & (1 << i)) {
616 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
618 } else
619 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
620 cache->elm_map[oid].encstat[1] = 0;
621 cache->elm_map[oid].encstat[2] = buf[r];
622 cache->elm_map[oid].encstat[3] = 0;
623 cache->elm_map[oid++].svalid = 1;
624 r++;
625 }
626
627 for (i = 0; i <= cfg->Ntstats; i++) {
628 cache->elm_map[oid].encstat[1] = 0;
629 if (tempflags & (1 <<
630 ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) {
631 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
632 cache->elm_map[4].encstat[2] = 0xff;
633 /*
634 * Set 'over temperature' failure.
635 */
636 cache->elm_map[oid].encstat[3] = 8;
638 } else {
639 /*
640 * We used to say 'not available' and synthesize a
641 * nominal 30 deg (C)- that was wrong. Actually,
642 * Just say 'OK', and use the reserved value of
643 * zero.
644 */
645 if ((cfg->Ntherm + cfg->Ntstats) == 0)
646 cache->elm_map[oid].encstat[0] =
648 else
649 cache->elm_map[oid].encstat[0] =
651 cache->elm_map[oid].encstat[2] = 0;
652 cache->elm_map[oid].encstat[3] = 0;
653 }
654 cache->elm_map[oid++].svalid = 1;
655 }
656 r += 2;
657
658 cache->enc_status =
659 cfg->enc_status | cfg->slot_status | cfg->adm_status;
660 return (0);
661}
662
663static int
665 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
666{
667 struct scfg *cfg;
668 uint8_t *buf = *bufp;
669 enc_cache_t *cache = &enc->enc_cache;
670 int oid, r, i;
671
672 cfg = enc->enc_private;
673 if (cfg == NULL)
674 return (ENXIO);
675 if (error != 0)
676 return (error);
677 cfg->slot_status = 0;
678 oid = cfg->slotoff;
679 for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
680 SAFT_BAIL(r+3, xfer_len);
681 if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV)
682 cache->elm_map[oid].encstat[1] = 0;
683 cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
684 cache->elm_map[oid].encstat[3] = 0;
685 if ((buf[r+3] & 0x01) == 0) { /* no device */
687 } else if (buf[r+0] & 0x02) {
688 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
690 } else if (buf[r+0] & 0x40) {
691 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
693 } else {
694 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
695 }
696 if (buf[r+3] & 0x2) {
697 if (buf[r+3] & 0x01)
698 cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
699 else
700 cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
701 }
702 if ((buf[r+3] & 0x04) == 0)
703 cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
704 if (buf[r+0] & 0x02)
705 cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
706 if (buf[r+0] & 0x40)
707 cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
708 if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV) {
709 if (buf[r+0] & 0x01)
710 cache->elm_map[oid].encstat[1] |= 0x80;
711 if (buf[r+0] & 0x04)
712 cache->elm_map[oid].encstat[1] |= 0x02;
713 if (buf[r+0] & 0x08)
714 cache->elm_map[oid].encstat[1] |= 0x04;
715 if (buf[r+0] & 0x10)
716 cache->elm_map[oid].encstat[1] |= 0x08;
717 if (buf[r+0] & 0x20)
718 cache->elm_map[oid].encstat[1] |= 0x10;
719 if (buf[r+1] & 0x01)
720 cache->elm_map[oid].encstat[1] |= 0x20;
721 if (buf[r+1] & 0x02)
722 cache->elm_map[oid].encstat[1] |= 0x01;
723 }
724 cache->elm_map[oid++].svalid = 1;
725 }
726
727 cache->enc_status =
728 cfg->enc_status | cfg->slot_status | cfg->adm_status;
729 return (0);
730}
731
732static int
734 union ccb *ccb, uint8_t *buf)
735{
736 struct scfg *cfg;
737 enc_element_t *ep, *ep1;
739 int i, idx, xfer_len;
740
741 cfg = enc->enc_private;
742 if (cfg == NULL)
743 return (ENXIO);
744
745 if (enc->enc_cache.nelms == 0) {
747 return (-1);
748 }
749
750 if (cfg->current_request == NULL) {
751 cfg->current_request = TAILQ_FIRST(&cfg->requests);
752 TAILQ_REMOVE(&cfg->requests, cfg->current_request, links);
753 cfg->current_request_stage = 0;
754 cfg->current_request_stages = 1;
755 }
756 req = cfg->current_request;
757
758 idx = (int)req->elm_idx;
759 if (req->elm_idx == SES_SETSTATUS_ENC_IDX) {
760 cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT;
764 else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
766 buf[0] = SAFTE_WT_GLOBAL;
767 buf[1] = cfg->flag1;
768 buf[2] = cfg->flag2;
769 buf[3] = 0;
770 xfer_len = 16;
771 } else {
772 ep = &enc->enc_cache.elm_map[idx];
773
774 switch (ep->elm_type) {
775 case ELMTYP_DEVICE:
776 case ELMTYP_ARRAY_DEV:
777 switch (cfg->current_request_stage) {
778 case 0:
779 ep->priv = 0;
780 if (req->elm_stat[0] & SESCTL_PRDFAIL)
781 ep->priv |= 0x40;
782 if (req->elm_stat[3] & SESCTL_RQSFLT)
783 ep->priv |= 0x02;
784 if (ep->elm_type == ELMTYP_ARRAY_DEV) {
785 if (req->elm_stat[1] & 0x01)
786 ep->priv |= 0x200;
787 if (req->elm_stat[1] & 0x02)
788 ep->priv |= 0x04;
789 if (req->elm_stat[1] & 0x04)
790 ep->priv |= 0x08;
791 if (req->elm_stat[1] & 0x08)
792 ep->priv |= 0x10;
793 if (req->elm_stat[1] & 0x10)
794 ep->priv |= 0x20;
795 if (req->elm_stat[1] & 0x20)
796 ep->priv |= 0x100;
797 if (req->elm_stat[1] & 0x80)
798 ep->priv |= 0x01;
799 }
800 if (ep->priv == 0)
801 ep->priv |= 0x01; /* no errors */
802
803 buf[0] = SAFTE_WT_DSTAT;
804 for (i = 0; i < cfg->Nslots; i++) {
805 ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i];
806 buf[1 + (3 * i)] = ep1->priv;
807 buf[2 + (3 * i)] = ep1->priv >> 8;
808 }
809 xfer_len = cfg->Nslots * 3 + 1;
810#define DEVON(x) (!(((x)[2] & SESCTL_RQSINS) | \
811 ((x)[2] & SESCTL_RQSRMV) | \
812 ((x)[3] & SESCTL_DEVOFF)))
813 if (DEVON(req->elm_stat) != DEVON(ep->encstat))
815#define IDON(x) (!!((x)[2] & SESCTL_RQSID))
816 if (IDON(req->elm_stat) != IDON(ep->encstat))
818 break;
819 case 1:
820 case 2:
821 buf[0] = SAFTE_WT_SLTOP;
822 buf[1] = idx - cfg->slotoff;
823 if (cfg->current_request_stage == 1 &&
824 DEVON(req->elm_stat) != DEVON(ep->encstat)) {
825 if (DEVON(req->elm_stat))
826 buf[2] = 0x01;
827 else
828 buf[2] = 0x02;
829 } else {
830 if (IDON(req->elm_stat))
831 buf[2] = 0x04;
832 else
833 buf[2] = 0x00;
834 ep->encstat[2] &= ~SESCTL_RQSID;
835 ep->encstat[2] |= req->elm_stat[2] &
837 }
838 xfer_len = 64;
839 break;
840 default:
841 return (EINVAL);
842 }
843 break;
844 case ELMTYP_POWER:
845 cfg->current_request_stages = 2;
846 switch (cfg->current_request_stage) {
847 case 0:
848 if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
850 } else {
851 cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
852 }
853 buf[0] = SAFTE_WT_GLOBAL;
854 buf[1] = cfg->flag1;
855 buf[2] = cfg->flag2;
856 buf[3] = 0;
857 xfer_len = 16;
858 break;
859 case 1:
860 buf[0] = SAFTE_WT_ACTPWS;
861 buf[1] = idx - cfg->pwroff;
862 if (req->elm_stat[3] & SESCTL_RQSTON)
863 buf[2] = 0x01;
864 else
865 buf[2] = 0x00;
866 buf[3] = 0;
867 xfer_len = 16;
868 default:
869 return (EINVAL);
870 }
871 break;
872 case ELMTYP_FAN:
873 if ((req->elm_stat[3] & 0x7) != 0)
874 cfg->current_request_stages = 2;
875 switch (cfg->current_request_stage) {
876 case 0:
877 if (req->elm_stat[3] & SESCTL_RQSTFAIL)
879 else
880 cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
881 buf[0] = SAFTE_WT_GLOBAL;
882 buf[1] = cfg->flag1;
883 buf[2] = cfg->flag2;
884 buf[3] = 0;
885 xfer_len = 16;
886 break;
887 case 1:
888 buf[0] = SAFTE_WT_FANSPD;
889 buf[1] = idx;
890 if (req->elm_stat[3] & SESCTL_RQSTON) {
891 if ((req->elm_stat[3] & 0x7) == 7)
892 buf[2] = 4;
893 else if ((req->elm_stat[3] & 0x7) >= 5)
894 buf[2] = 3;
895 else if ((req->elm_stat[3] & 0x7) >= 3)
896 buf[2] = 2;
897 else
898 buf[2] = 1;
899 } else
900 buf[2] = 0;
901 buf[3] = 0;
902 xfer_len = 16;
903 ep->encstat[3] = req->elm_stat[3] & 0x67;
904 default:
905 return (EINVAL);
906 }
907 break;
908 case ELMTYP_DOORLOCK:
909 if (req->elm_stat[3] & 0x1)
910 cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
911 else
913 buf[0] = SAFTE_WT_GLOBAL;
914 buf[1] = cfg->flag1;
915 buf[2] = cfg->flag2;
916 buf[3] = 0;
917 xfer_len = 16;
918 break;
919 case ELMTYP_ALARM:
920 if ((req->elm_stat[0] & SESCTL_DISABLE) ||
921 (req->elm_stat[3] & 0x40)) {
922 cfg->flag2 &= ~SAFT_FLG1_ALARM;
923 } else if ((req->elm_stat[3] & 0x0f) != 0) {
924 cfg->flag2 |= SAFT_FLG1_ALARM;
925 } else {
926 cfg->flag2 &= ~SAFT_FLG1_ALARM;
927 }
928 buf[0] = SAFTE_WT_GLOBAL;
929 buf[1] = cfg->flag1;
930 buf[2] = cfg->flag2;
931 buf[3] = 0;
932 xfer_len = 16;
933 ep->encstat[3] = req->elm_stat[3];
934 break;
935 default:
936 return (EINVAL);
937 }
938 }
939
940 if (enc->enc_type == ENC_SEMB_SAFT) {
941 semb_write_buffer(&ccb->ataio, /*retries*/5,
942 NULL, MSG_SIMPLE_Q_TAG,
943 buf, xfer_len, state->timeout);
944 } else {
945 scsi_write_buffer(&ccb->csio, /*retries*/5,
946 NULL, MSG_SIMPLE_Q_TAG, 1,
947 0, 0, buf, xfer_len,
948 SSD_FULL_SIZE, state->timeout);
949 }
950 return (0);
951}
952
953static int
955 union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
956{
957 struct scfg *cfg;
959 int idx, type;
960
961 cfg = enc->enc_private;
962 if (cfg == NULL)
963 return (ENXIO);
964
965 req = cfg->current_request;
966 if (req->result == 0)
967 req->result = error;
969 idx = req->elm_idx;
970 if (idx == SES_SETSTATUS_ENC_IDX)
971 type = -1;
972 else
973 type = enc->enc_cache.elm_map[idx].elm_type;
974 if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
976 else
978 cfg->current_request = NULL;
979 wakeup(req);
980 } else {
982 }
983 return (0);
984}
985
986static void
988{
989 struct scfg *cfg;
990
991 cfg = enc->enc_private;
993}
994
995static void
997{
998
1001 enc->enc_cache.nelms = 0;
1002}
1003
1004static int
1006{
1007 struct scfg *cfg;
1008 int err;
1009 static char cdb0[6] = { SEND_DIAGNOSTIC };
1010
1011 cfg = enc->enc_private;
1012 if (cfg == NULL)
1013 return (ENXIO);
1014
1015 err = enc_runcmd(enc, cdb0, 6, NULL, 0);
1016 if (err) {
1017 return (err);
1018 }
1019 DELAY(5000);
1020 cfg->flag1 = 0;
1021 cfg->flag2 = 0;
1022 err = safte_set_enc_status(enc, 0, 1);
1023 return (err);
1024}
1025
1026static int
1027safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
1028{
1029 struct scfg *cfg;
1031
1032 cfg = enc->enc_private;
1033 if (cfg == NULL)
1034 return (ENXIO);
1035
1037 req.elm_stat[0] = encstat & 0xf;
1038 req.result = 0;
1039
1040 TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1042 cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1043
1044 return (req.result);
1045}
1046
1047static int
1049{
1050 int i = (int)elms->elm_idx;
1051
1052 elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
1053 elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
1054 elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
1055 elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
1056 return (0);
1057}
1058
1059static int
1061{
1062 struct scfg *cfg;
1064
1065 cfg = enc->enc_private;
1066 if (cfg == NULL)
1067 return (ENXIO);
1068
1069 /* If this is clear, we don't do diddly. */
1070 if ((elms->cstat[0] & SESCTL_CSEL) == 0)
1071 return (0);
1072
1073 req.elm_idx = elms->elm_idx;
1074 memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
1075 req.result = 0;
1076
1077 TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1079 cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1080
1081 return (req.result);
1082}
1083
1084static void
1086{
1087
1090}
1091
1092static struct enc_vec safte_enc_vec =
1093{
1095 .softc_cleanup = safte_softc_cleanup,
1096 .init_enc = safte_init_enc,
1097 .set_enc_status = safte_set_enc_status,
1098 .get_elm_status = safte_get_elm_status,
1099 .set_elm_status = safte_set_elm_status,
1100 .poll_status = safte_poll_status
1101};
1102
1103int
1105{
1106 struct scfg *cfg;
1107
1108 enc->enc_vec = safte_enc_vec;
1110
1111 if (enc->enc_private == NULL) {
1113 if (enc->enc_private == NULL)
1114 return (ENOMEM);
1115 }
1116 cfg = enc->enc_private;
1117
1118 enc->enc_cache.nelms = 0;
1119 enc->enc_cache.enc_status = 0;
1120
1121 TAILQ_INIT(&cfg->requests);
1122 return (0);
1123}
void semb_write_buffer(struct ccb_ataio *ataio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
Definition: ata_all.c:1101
void semb_read_buffer(struct ccb_ataio *ataio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, uint8_t page_code, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
Definition: ata_all.c:1080
#define cam_periph_sleep(periph, chan, priority, wmesg, timo)
Definition: cam_periph.h:233
void scsi_read_buffer(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int mode, uint8_t buffer_id, u_int32_t offset, uint8_t *data_ptr, uint32_t allocation_length, uint8_t sense_len, uint32_t timeout)
Definition: scsi_all.c:8841
void scsi_write_buffer(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int mode, uint8_t buffer_id, u_int32_t offset, uint8_t *data_ptr, uint32_t param_list_length, uint8_t sense_len, uint32_t timeout)
Definition: scsi_all.c:8871
#define SEND_DIAGNOSTIC
Definition: scsi_all.h:2093
#define SSD_FULL_SIZE
Definition: scsi_all.h:3251
int enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp)
Definition: scsi_enc.c:579
void enc_update_request(enc_softc_t *enc, uint32_t action)
Queue an update request for a given action, if needed.
Definition: scsi_enc.c:735
int enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags)
Definition: scsi_enc.c:346
unsigned char encioc_enc_status_t
Definition: scsi_enc.h:175
@ ELMTYP_FAN
Definition: scsi_enc.h:102
@ ELMTYP_POWER
Definition: scsi_enc.h:101
@ ELMTYP_ARRAY_DEV
Definition: scsi_enc.h:122
@ ELMTYP_DOORLOCK
Definition: scsi_enc.h:104
@ ELMTYP_ALARM
Definition: scsi_enc.h:105
@ ELMTYP_THERM
Definition: scsi_enc.h:103
@ ELMTYP_DEVICE
Definition: scsi_enc.h:100
int fsm_fill_handler_t(enc_softc_t *ssc, struct enc_fsm_state *state, union ccb *ccb, uint8_t *buf)
@ ENC_SEMB_SAFT
int fsm_done_handler_t(enc_softc_t *ssc, struct enc_fsm_state *state, union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
#define ENC_VLOG
#define ENC_FREE_AND_NULL(ptr)
#define ENC_MALLOCZ(amt)
#define SAFTE_RD_RDGFLG
#define SAFTE_RD_RDDSTS
static int safte_init_enc(enc_softc_t *enc)
safte_update_action
@ SAFTE_NUM_UPDATE_STATES
@ SAFTE_UPDATE_READENCSTATUS
@ SAFTE_UPDATE_READSLOTSTATUS
@ SAFTE_UPDATE_READCONFIG
@ SAFTE_UPDATE_READGFLAGS
@ SAFTE_UPDATE_NONE
@ SAFTE_PROCESS_CONTROL_REQS
#define SAFTE_WT_FANSPD
static struct enc_vec safte_enc_vec
int safte_softc_init(enc_softc_t *enc)
static fsm_done_handler_t safte_process_config
@ SES_SETSTATUS_ENC_IDX
static fsm_fill_handler_t safte_fill_read_buf_io
struct safte_control_request safte_control_request_t
#define IDON(x)
#define SAFTE_RD_RDESTS
static fsm_done_handler_t safte_process_control_request
static int safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
#define SAFT_FLG1_GLOBWARN
static int safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
static fsm_fill_handler_t safte_fill_control_request
static fsm_done_handler_t safte_process_status
static void safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
#define SAFT_PRIVATE
static int safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
static void safte_softc_invalidate(enc_softc_t *enc)
__FBSDID("$FreeBSD$")
#define SAFT_FLG2_LOCKDOOR
SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN, &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE")
#define SAFT_FLG1_ALARM
static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES]
#define SAFT_FLG1_ENCPWRFAIL
static void safte_poll_status(enc_softc_t *enc)
#define ALL_ENC_STAT
struct safte_control_reqlist safte_control_reqlist_t
static fsm_done_handler_t safte_process_slotstatus
#define DEVON(x)
#define SCSZ
#define SAFTE_WT_ACTPWS
#define SAFTE_RD_RDCFG
static fsm_done_handler_t safte_process_gflags
#define SAFT_BAIL(r, x)
int emulate_array_devices
#define SAFTE_WT_SLTOP
TAILQ_HEAD(safte_control_reqlist, safte_control_request)
static char * safte_2little
#define SAFT_FLG1_ENCFANFAIL
#define SAFT_FLG1_GLOBFAIL
static void safte_softc_cleanup(enc_softc_t *enc)
#define SAFT_SCRATCH
#define SAFTE_WT_DSTAT
#define SAFTE_WT_GLOBAL
#define MSG_SIMPLE_Q_TAG
Definition: scsi_message.h:35
#define SESCTL_RQSID
Definition: scsi_ses.h:2240
#define SES_ENCSTAT_UNRECOV
Definition: scsi_ses.h:2190
#define SES_ENCSTAT_CRITICAL
Definition: scsi_ses.h:2191
#define SES_OBJSTAT_UNKNOWN
Definition: scsi_ses.h:2208
#define SESCTL_DEVOFF
Definition: scsi_ses.h:2243
#define SESCTL_DISABLE
Definition: scsi_ses.h:2222
#define SESCTL_RQSRMV
Definition: scsi_ses.h:2239
#define SES_OBJSTAT_UNSUPPORTED
Definition: scsi_ses.h:2202
#define SES_OBJSTAT_NONCRIT
Definition: scsi_ses.h:2205
#define SESCTL_RQSTON
Definition: scsi_ses.h:2249
#define SES_OBJSTAT_OK
Definition: scsi_ses.h:2203
#define SESCTL_RQSFLT
Definition: scsi_ses.h:2242
#define SESCTL_RQSTFAIL
Definition: scsi_ses.h:2248
#define SES_ENCSTAT_INFO
Definition: scsi_ses.h:2193
#define SESCTL_PRDFAIL
Definition: scsi_ses.h:2221
#define SESCTL_CSEL
Definition: scsi_ses.h:2220
#define SES_OBJSTAT_NOTINSTALLED
Definition: scsi_ses.h:2207
#define SESCTL_RQSINS
Definition: scsi_ses.h:2238
#define SES_ENCSTAT_NONCRITICAL
Definition: scsi_ses.h:2192
#define SES_OBJSTAT_CRIT
Definition: scsi_ses.h:2204
#define SES_OBJSTAT_NOTAVAIL
Definition: scsi_ses.h:2209
enc_element_t * elm_map
encioc_enc_status_t enc_status
uint8_t encstat[4]
void * enc_private
struct enc_vec enc_vec
struct cam_periph * periph
struct enc_fsm_state * enc_fsm_states
enc_cache_t enc_cache
enc_softc_invalidate_t * softc_invalidate
unsigned char cstat[4]
Definition: scsi_enc.h:182
unsigned int elm_idx
Definition: scsi_enc.h:181
uint8_t Nslots
uint8_t DoorLock
safte_control_reqlist_t requests
safte_control_request_t * current_request
encioc_enc_status_t adm_status
int current_request_stages
uint8_t Nfans
uint8_t flag1
encioc_enc_status_t enc_status
int current_request_stage
uint8_t Nspkrs
uint8_t Ntherm
uint8_t Ntstats
uint8_t flag2
uint8_t pwroff
uint8_t Npwr
encioc_enc_status_t slot_status
uint8_t slotoff
Definition: cam_ccb.h:1345
struct ccb_scsiio csio
Definition: cam_ccb.h:1347
struct ccb_ataio ataio
Definition: cam_ccb.h:1376