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