Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/cam/scsi/scsi_enc_safte.c
39482 views
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
}
1121
1122