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