]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cam/scsi/scsi_enc_safte.c
powerpc64/mmu: Use a SLIST for the PVO delete list, instead of a RB_TREE
[FreeBSD/FreeBSD.git] / sys / cam / scsi / scsi_enc_safte.c
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>
50 #include <cam/scsi/scsi_enc_internal.h>
51 #include <cam/scsi/scsi_message.h>
52
53 /*
54  * SAF-TE Type Device Emulation
55  */
56
57 static 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
85 typedef enum {
86         SAFTE_UPDATE_NONE,
87         SAFTE_UPDATE_READCONFIG,
88         SAFTE_UPDATE_READGFLAGS,
89         SAFTE_UPDATE_READENCSTATUS,
90         SAFTE_UPDATE_READSLOTSTATUS,
91         SAFTE_PROCESS_CONTROL_REQS,
92         SAFTE_NUM_UPDATE_STATES
93 } safte_update_action;
94
95 static fsm_fill_handler_t safte_fill_read_buf_io;
96 static fsm_fill_handler_t safte_fill_control_request;
97 static fsm_done_handler_t safte_process_config;
98 static fsm_done_handler_t safte_process_gflags;
99 static fsm_done_handler_t safte_process_status;
100 static fsm_done_handler_t safte_process_slotstatus;
101 static fsm_done_handler_t safte_process_control_request;
102
103 static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES] =
104 {
105         { "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
106         {
107                 "SAFTE_UPDATE_READCONFIG",
108                 SAFTE_RD_RDCFG,
109                 SAFT_SCRATCH,
110                 60 * 1000,
111                 safte_fill_read_buf_io,
112                 safte_process_config,
113                 enc_error
114         },
115         {
116                 "SAFTE_UPDATE_READGFLAGS",
117                 SAFTE_RD_RDGFLG,
118                 16,
119                 60 * 1000,
120                 safte_fill_read_buf_io,
121                 safte_process_gflags,
122                 enc_error
123         },
124         {
125                 "SAFTE_UPDATE_READENCSTATUS",
126                 SAFTE_RD_RDESTS,
127                 SCSZ,
128                 60 * 1000,
129                 safte_fill_read_buf_io,
130                 safte_process_status,
131                 enc_error
132         },
133         {
134                 "SAFTE_UPDATE_READSLOTSTATUS",
135                 SAFTE_RD_RDDSTS,
136                 SCSZ,
137                 60 * 1000,
138                 safte_fill_read_buf_io,
139                 safte_process_slotstatus,
140                 enc_error
141         },
142         {
143                 "SAFTE_PROCESS_CONTROL_REQS",
144                 0,
145                 SCSZ,
146                 60 * 1000,
147                 safte_fill_control_request,
148                 safte_process_control_request,
149                 enc_error
150         }
151 };
152
153 typedef struct safte_control_request {
154         int     elm_idx;
155         uint8_t elm_stat[4];
156         int     result;
157         TAILQ_ENTRY(safte_control_request) links;
158 } safte_control_request_t;
159 TAILQ_HEAD(safte_control_reqlist, safte_control_request);
160 typedef struct safte_control_reqlist safte_control_reqlist_t;
161 enum {
162         SES_SETSTATUS_ENC_IDX = -1
163 };
164
165 static void
166 safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
167 {
168         safte_control_request_t *req;
169
170         while ((req = TAILQ_FIRST(reqlist)) != NULL) {
171                 TAILQ_REMOVE(reqlist, req, links);
172                 req->result = result;
173                 wakeup(req);
174         }
175 }
176
177 struct scfg {
178         /*
179          * Cached Configuration
180          */
181         uint8_t Nfans;          /* Number of Fans */
182         uint8_t Npwr;           /* Number of Power Supplies */
183         uint8_t Nslots;         /* Number of Device Slots */
184         uint8_t DoorLock;       /* Door Lock Installed */
185         uint8_t Ntherm;         /* Number of Temperature Sensors */
186         uint8_t Nspkrs;         /* Number of Speakers */
187         uint8_t Ntstats;        /* Number of Thermostats */
188         /*
189          * Cached Flag Bytes for Global Status
190          */
191         uint8_t flag1;
192         uint8_t flag2;
193         /*
194          * What object index ID is where various slots start.
195          */
196         uint8_t pwroff;
197         uint8_t slotoff;
198 #define SAFT_ALARM_OFFSET(cc)   (cc)->slotoff - 1
199
200         encioc_enc_status_t     adm_status;
201         encioc_enc_status_t     enc_status;
202         encioc_enc_status_t     slot_status;
203
204         safte_control_reqlist_t requests;
205         safte_control_request_t *current_request;
206         int                     current_request_stage;
207         int                     current_request_stages;
208 };
209
210 #define SAFT_FLG1_ALARM         0x1
211 #define SAFT_FLG1_GLOBFAIL      0x2
212 #define SAFT_FLG1_GLOBWARN      0x4
213 #define SAFT_FLG1_ENCPWROFF     0x8
214 #define SAFT_FLG1_ENCFANFAIL    0x10
215 #define SAFT_FLG1_ENCPWRFAIL    0x20
216 #define SAFT_FLG1_ENCDRVFAIL    0x40
217 #define SAFT_FLG1_ENCDRVWARN    0x80
218
219 #define SAFT_FLG2_LOCKDOOR      0x4
220 #define SAFT_PRIVATE            sizeof (struct scfg)
221
222 static 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
229 int emulate_array_devices = 1;
230 SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN,
231            &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
232
233 static int
234 safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
235                        union ccb *ccb, uint8_t *buf)
236 {
237
238         if (state->page_code != SAFTE_RD_RDCFG &&
239             enc->enc_cache.nelms == 0) {
240                 enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
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
258 static int
259 safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
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;
293         ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
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++)
304                 enc->enc_cache.elm_map[r++].elm_type = ELMTYP_FAN;
305         cfg->pwroff = (uint8_t) r;
306         for (i = 0; i < cfg->Npwr; i++)
307                 enc->enc_cache.elm_map[r++].elm_type = ELMTYP_POWER;
308         for (i = 0; i < cfg->DoorLock; i++)
309                 enc->enc_cache.elm_map[r++].elm_type = ELMTYP_DOORLOCK;
310         if (cfg->Nspkrs > 0)
311                 enc->enc_cache.elm_map[r++].elm_type = ELMTYP_ALARM;
312         for (i = 0; i < cfg->Ntherm; i++)
313                 enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
314         for (i = 0; i <= cfg->Ntstats; i++)
315                 enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
316         cfg->slotoff = (uint8_t) r;
317         for (i = 0; i < cfg->Nslots; i++)
318                 enc->enc_cache.elm_map[r++].elm_type =
319                     emulate_array_devices ? ELMTYP_ARRAY_DEV :
320                      ELMTYP_DEVICE;
321
322         enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
323         enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
324         enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
325
326         return (0);
327 }
328
329 static int
330 safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
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)
347                 cfg->adm_status |= SES_ENCSTAT_CRITICAL;
348         else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
349                 cfg->adm_status |= SES_ENCSTAT_NONCRITICAL;
350
351         return (0);
352 }
353
354 static int
355 safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
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] =
397                             SES_OBJSTAT_CRIT;
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)
409                                 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
410                         else
411                                 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
412                         break;
413                 case 2:
414                         cache->elm_map[oid].encstat[0] =
415                             SES_OBJSTAT_NOTINSTALLED;
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)
424                                 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
425                         else
426                                 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
427                         break;
428                 case 0x80:
429                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
430                         cache->elm_map[oid].encstat[3] = 0;
431                         cfg->enc_status |= SES_ENCSTAT_INFO;
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)
448                 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
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;
463                         cfg->enc_status |= SES_ENCSTAT_INFO;
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;
468                         cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
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;
474                         cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
475                         break;
476                 case 0x20:      /* pws is not present */
477                         cache->elm_map[oid].encstat[0] =
478                             SES_OBJSTAT_NOTINSTALLED;
479                         cache->elm_map[oid].encstat[3] = 0;
480                         cfg->enc_status |= SES_ENCSTAT_INFO;
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;
492                         cfg->enc_status |= SES_ENCSTAT_INFO;
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;
538                         cfg->enc_status |= SES_ENCSTAT_INFO;
539                         break;
540                 default:
541                         cache->elm_map[oid].encstat[0] =
542                             SES_OBJSTAT_UNSUPPORTED;
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;
617                         cfg->enc_status |= SES_ENCSTAT_CRITICAL;
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;
637                         cfg->enc_status |= SES_ENCSTAT_CRITICAL;
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] =
647                                     SES_OBJSTAT_NOTAVAIL;
648                         else
649                                 cache->elm_map[oid].encstat[0] =
650                                     SES_OBJSTAT_OK;
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
663 static int
664 safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
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 */
686                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED;
687                 } else if (buf[r+0] & 0x02) {
688                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
689                         cfg->slot_status |= SES_ENCSTAT_CRITICAL;
690                 } else if (buf[r+0] & 0x40) {
691                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
692                         cfg->slot_status |= SES_ENCSTAT_NONCRITICAL;
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
732 static int
733 safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
734                        union ccb *ccb, uint8_t *buf)
735 {
736         struct scfg *cfg;
737         enc_element_t *ep, *ep1;
738         safte_control_request_t *req;
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) {
746                 enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
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;
761                 cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
762                 if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV))
763                         cfg->flag1 |= SAFT_FLG1_GLOBFAIL;
764                 else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
765                         cfg->flag1 |= SAFT_FLG1_GLOBWARN;
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))
814                                         cfg->current_request_stages++;
815 #define IDON(x)         (!!((x)[2] & SESCTL_RQSID))
816                                 if (IDON(req->elm_stat) != IDON(ep->encstat))
817                                         cfg->current_request_stages++;
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] &
836                                             SESCTL_RQSID;
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) {
849                                         cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
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)
878                                         cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
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
912                                 cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
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
953 static int
954 safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
955     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
956 {
957         struct scfg *cfg;
958         safte_control_request_t *req;
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;
968         if (++cfg->current_request_stage >= cfg->current_request_stages) {
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)
975                         enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
976                 else
977                         enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
978                 cfg->current_request = NULL;
979                 wakeup(req);
980         } else {
981                 enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
982         }
983         return (0);
984 }
985
986 static void
987 safte_softc_invalidate(enc_softc_t *enc)
988 {
989         struct scfg *cfg;
990
991         cfg = enc->enc_private;
992         safte_terminate_control_requests(&cfg->requests, ENXIO);
993 }
994
995 static void
996 safte_softc_cleanup(enc_softc_t *enc)
997 {
998
999         ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
1000         ENC_FREE_AND_NULL(enc->enc_private);
1001         enc->enc_cache.nelms = 0;
1002 }
1003
1004 static int
1005 safte_init_enc(enc_softc_t *enc)
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
1026 static int
1027 safte_get_enc_status(enc_softc_t *enc, int slpflg)
1028 {
1029
1030         return (0);
1031 }
1032
1033 static int
1034 safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
1035 {
1036         struct scfg *cfg;
1037         safte_control_request_t req;
1038
1039         cfg = enc->enc_private;
1040         if (cfg == NULL)
1041                 return (ENXIO);
1042
1043         req.elm_idx = SES_SETSTATUS_ENC_IDX;
1044         req.elm_stat[0] = encstat & 0xf;
1045         req.result = 0;
1046         
1047         TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1048         enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1049         cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1050
1051         return (req.result);
1052 }
1053
1054 static int
1055 safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
1056 {
1057         int i = (int)elms->elm_idx;
1058
1059         elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
1060         elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
1061         elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
1062         elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
1063         return (0);
1064 }
1065
1066 static int
1067 safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
1068 {
1069         struct scfg *cfg;
1070         safte_control_request_t req;
1071
1072         cfg = enc->enc_private;
1073         if (cfg == NULL)
1074                 return (ENXIO);
1075
1076         /* If this is clear, we don't do diddly.  */
1077         if ((elms->cstat[0] & SESCTL_CSEL) == 0)
1078                 return (0);
1079
1080         req.elm_idx = elms->elm_idx;
1081         memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
1082         req.result = 0;
1083
1084         TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1085         enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1086         cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1087
1088         return (req.result);
1089 }
1090
1091 static void
1092 safte_poll_status(enc_softc_t *enc)
1093 {
1094
1095         enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
1096         enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
1097 }
1098
1099 static struct enc_vec safte_enc_vec =
1100 {
1101         .softc_invalidate       = safte_softc_invalidate,
1102         .softc_cleanup  = safte_softc_cleanup,
1103         .init_enc       = safte_init_enc,
1104         .get_enc_status = safte_get_enc_status,
1105         .set_enc_status = safte_set_enc_status,
1106         .get_elm_status = safte_get_elm_status,
1107         .set_elm_status = safte_set_elm_status,
1108         .poll_status    = safte_poll_status
1109 };
1110
1111 int
1112 safte_softc_init(enc_softc_t *enc)
1113 {
1114         struct scfg *cfg;
1115
1116         enc->enc_vec = safte_enc_vec;
1117         enc->enc_fsm_states = enc_fsm_states;
1118
1119         if (enc->enc_private == NULL) {
1120                 enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
1121                 if (enc->enc_private == NULL)
1122                         return (ENOMEM);
1123         }
1124         cfg = enc->enc_private;
1125
1126         enc->enc_cache.nelms = 0;
1127         enc->enc_cache.enc_status = 0;
1128
1129         TAILQ_INIT(&cfg->requests);
1130         return (0);
1131 }
1132