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_DECL(_kern_cam_enc); 231 SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN, 232 &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE"); 233 234 static int 235 safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state, 236 union ccb *ccb, uint8_t *buf) 237 { 238 239 if (state->page_code != SAFTE_RD_RDCFG && 240 enc->enc_cache.nelms == 0) { 241 enc_update_request(enc, SAFTE_UPDATE_READCONFIG); 242 return (-1); 243 } 244 245 if (enc->enc_type == ENC_SEMB_SAFT) { 246 semb_read_buffer(&ccb->ataio, /*retries*/5, 247 NULL, MSG_SIMPLE_Q_TAG, 248 state->page_code, buf, state->buf_size, 249 state->timeout); 250 } else { 251 scsi_read_buffer(&ccb->csio, /*retries*/5, 252 NULL, MSG_SIMPLE_Q_TAG, 1, 253 state->page_code, 0, buf, state->buf_size, 254 SSD_FULL_SIZE, state->timeout); 255 } 256 return (0); 257 } 258 259 static int 260 safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state, 261 union ccb *ccb, uint8_t **bufp, int error, int xfer_len) 262 { 263 struct scfg *cfg; 264 uint8_t *buf = *bufp; 265 int i, r; 266 267 cfg = enc->enc_private; 268 if (cfg == NULL) 269 return (ENXIO); 270 if (error != 0) 271 return (error); 272 if (xfer_len < 6) { 273 ENC_VLOG(enc, "too little data (%d) for configuration\n", 274 xfer_len); 275 return (EIO); 276 } 277 cfg->Nfans = buf[0]; 278 cfg->Npwr = buf[1]; 279 cfg->Nslots = buf[2]; 280 cfg->DoorLock = buf[3]; 281 cfg->Ntherm = buf[4]; 282 cfg->Nspkrs = buf[5]; 283 if (xfer_len >= 7) 284 cfg->Ntstats = buf[6] & 0x0f; 285 else 286 cfg->Ntstats = 0; 287 ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d " 288 "Ntstats %d\n", 289 cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm, 290 cfg->Nspkrs, cfg->Ntstats); 291 292 enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots + 293 cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1; 294 ENC_FREE_AND_NULL(enc->enc_cache.elm_map); 295 enc->enc_cache.elm_map = 296 malloc(enc->enc_cache.nelms * sizeof(enc_element_t), 297 M_SCSIENC, M_WAITOK|M_ZERO); 298 299 r = 0; 300 /* 301 * Note that this is all arranged for the convenience 302 * in later fetches of status. 303 */ 304 for (i = 0; i < cfg->Nfans; i++) 305 enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN; 306 cfg->pwroff = (uint8_t) r; 307 for (i = 0; i < cfg->Npwr; i++) 308 enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER; 309 for (i = 0; i < cfg->DoorLock; i++) 310 enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK; 311 if (cfg->Nspkrs > 0) 312 enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM; 313 for (i = 0; i < cfg->Ntherm; i++) 314 enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM; 315 for (i = 0; i <= cfg->Ntstats; i++) 316 enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM; 317 cfg->slotoff = (uint8_t) r; 318 for (i = 0; i < cfg->Nslots; i++) 319 enc->enc_cache.elm_map[r++].enctype = 320 emulate_array_devices ? ELMTYP_ARRAY_DEV : 321 ELMTYP_DEVICE; 322 323 enc_update_request(enc, SAFTE_UPDATE_READGFLAGS); 324 enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS); 325 enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS); 326 327 return (0); 328 } 329 330 static int 331 safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state, 332 union ccb *ccb, uint8_t **bufp, int error, int xfer_len) 333 { 334 struct scfg *cfg; 335 uint8_t *buf = *bufp; 336 337 cfg = enc->enc_private; 338 if (cfg == NULL) 339 return (ENXIO); 340 if (error != 0) 341 return (error); 342 SAFT_BAIL(3, xfer_len); 343 cfg->flag1 = buf[1]; 344 cfg->flag2 = buf[2]; 345 346 cfg->adm_status = 0; 347 if (cfg->flag1 & SAFT_FLG1_GLOBFAIL) 348 cfg->adm_status |= SES_ENCSTAT_CRITICAL; 349 else if (cfg->flag1 & SAFT_FLG1_GLOBWARN) 350 cfg->adm_status |= SES_ENCSTAT_NONCRITICAL; 351 352 return (0); 353 } 354 355 static int 356 safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state, 357 union ccb *ccb, uint8_t **bufp, int error, int xfer_len) 358 { 359 struct scfg *cfg; 360 uint8_t *buf = *bufp; 361 int oid, r, i, nitems; 362 uint16_t tempflags; 363 enc_cache_t *cache = &enc->enc_cache; 364 365 cfg = enc->enc_private; 366 if (cfg == NULL) 367 return (ENXIO); 368 if (error != 0) 369 return (error); 370 371 oid = r = 0; 372 cfg->enc_status = 0; 373 374 for (nitems = i = 0; i < cfg->Nfans; i++) { 375 SAFT_BAIL(r, xfer_len); 376 /* 377 * 0 = Fan Operational 378 * 1 = Fan is malfunctioning 379 * 2 = Fan is not present 380 * 0x80 = Unknown or Not Reportable Status 381 */ 382 cache->elm_map[oid].encstat[1] = 0; /* resvd */ 383 cache->elm_map[oid].encstat[2] = 0; /* resvd */ 384 if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL) 385 cache->elm_map[oid].encstat[3] |= 0x40; 386 else 387 cache->elm_map[oid].encstat[3] &= ~0x40; 388 switch ((int)buf[r]) { 389 case 0: 390 nitems++; 391 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 392 if ((cache->elm_map[oid].encstat[3] & 0x37) == 0) 393 cache->elm_map[oid].encstat[3] |= 0x27; 394 break; 395 396 case 1: 397 cache->elm_map[oid].encstat[0] = 398 SES_OBJSTAT_CRIT; 399 /* 400 * FAIL and FAN STOPPED synthesized 401 */ 402 cache->elm_map[oid].encstat[3] |= 0x10; 403 cache->elm_map[oid].encstat[3] &= ~0x07; 404 /* 405 * Enclosure marked with CRITICAL error 406 * if only one fan or no thermometers, 407 * else the NONCRITICAL error is set. 408 */ 409 if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0) 410 cfg->enc_status |= SES_ENCSTAT_CRITICAL; 411 else 412 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL; 413 break; 414 case 2: 415 cache->elm_map[oid].encstat[0] = 416 SES_OBJSTAT_NOTINSTALLED; 417 cache->elm_map[oid].encstat[3] |= 0x10; 418 cache->elm_map[oid].encstat[3] &= ~0x07; 419 /* 420 * Enclosure marked with CRITICAL error 421 * if only one fan or no thermometers, 422 * else the NONCRITICAL error is set. 423 */ 424 if (cfg->Nfans == 1) 425 cfg->enc_status |= SES_ENCSTAT_CRITICAL; 426 else 427 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL; 428 break; 429 case 0x80: 430 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN; 431 cache->elm_map[oid].encstat[3] = 0; 432 cfg->enc_status |= SES_ENCSTAT_INFO; 433 break; 434 default: 435 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED; 436 ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i, 437 buf[r] & 0xff); 438 break; 439 } 440 cache->elm_map[oid++].svalid = 1; 441 r++; 442 } 443 444 /* 445 * No matter how you cut it, no cooling elements when there 446 * should be some there is critical. 447 */ 448 if (cfg->Nfans && nitems == 0) 449 cfg->enc_status |= SES_ENCSTAT_CRITICAL; 450 451 for (i = 0; i < cfg->Npwr; i++) { 452 SAFT_BAIL(r, xfer_len); 453 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN; 454 cache->elm_map[oid].encstat[1] = 0; /* resvd */ 455 cache->elm_map[oid].encstat[2] = 0; /* resvd */ 456 cache->elm_map[oid].encstat[3] = 0x20; /* requested on */ 457 switch (buf[r]) { 458 case 0x00: /* pws operational and on */ 459 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 460 break; 461 case 0x01: /* pws operational and off */ 462 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 463 cache->elm_map[oid].encstat[3] = 0x10; 464 cfg->enc_status |= SES_ENCSTAT_INFO; 465 break; 466 case 0x10: /* pws is malfunctioning and commanded on */ 467 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT; 468 cache->elm_map[oid].encstat[3] = 0x61; 469 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL; 470 break; 471 472 case 0x11: /* pws is malfunctioning and commanded off */ 473 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT; 474 cache->elm_map[oid].encstat[3] = 0x51; 475 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL; 476 break; 477 case 0x20: /* pws is not present */ 478 cache->elm_map[oid].encstat[0] = 479 SES_OBJSTAT_NOTINSTALLED; 480 cache->elm_map[oid].encstat[3] = 0; 481 cfg->enc_status |= SES_ENCSTAT_INFO; 482 break; 483 case 0x21: /* pws is present */ 484 /* 485 * This is for enclosures that cannot tell whether the 486 * device is on or malfunctioning, but know that it is 487 * present. Just fall through. 488 */ 489 /* FALLTHROUGH */ 490 case 0x80: /* Unknown or Not Reportable Status */ 491 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN; 492 cache->elm_map[oid].encstat[3] = 0; 493 cfg->enc_status |= SES_ENCSTAT_INFO; 494 break; 495 default: 496 ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n", 497 i, buf[r] & 0xff); 498 break; 499 } 500 enc->enc_cache.elm_map[oid++].svalid = 1; 501 r++; 502 } 503 504 /* 505 * Copy Slot SCSI IDs 506 */ 507 for (i = 0; i < cfg->Nslots; i++) { 508 SAFT_BAIL(r, xfer_len); 509 if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE) 510 cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r]; 511 r++; 512 } 513 514 /* 515 * We always have doorlock status, no matter what, 516 * but we only save the status if we have one. 517 */ 518 SAFT_BAIL(r, xfer_len); 519 if (cfg->DoorLock) { 520 /* 521 * 0 = Door Locked 522 * 1 = Door Unlocked, or no Lock Installed 523 * 0x80 = Unknown or Not Reportable Status 524 */ 525 cache->elm_map[oid].encstat[1] = 0; 526 cache->elm_map[oid].encstat[2] = 0; 527 switch (buf[r]) { 528 case 0: 529 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 530 cache->elm_map[oid].encstat[3] = 0; 531 break; 532 case 1: 533 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 534 cache->elm_map[oid].encstat[3] = 1; 535 break; 536 case 0x80: 537 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN; 538 cache->elm_map[oid].encstat[3] = 0; 539 cfg->enc_status |= SES_ENCSTAT_INFO; 540 break; 541 default: 542 cache->elm_map[oid].encstat[0] = 543 SES_OBJSTAT_UNSUPPORTED; 544 ENC_VLOG(enc, "unknown lock status 0x%x\n", 545 buf[r] & 0xff); 546 break; 547 } 548 cache->elm_map[oid++].svalid = 1; 549 } 550 r++; 551 552 /* 553 * We always have speaker status, no matter what, 554 * but we only save the status if we have one. 555 */ 556 SAFT_BAIL(r, xfer_len); 557 if (cfg->Nspkrs) { 558 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 559 cache->elm_map[oid].encstat[1] = 0; 560 cache->elm_map[oid].encstat[2] = 0; 561 if (buf[r] == 0) { 562 cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE; 563 cache->elm_map[oid].encstat[3] |= 0x40; 564 } 565 cache->elm_map[oid++].svalid = 1; 566 } 567 r++; 568 569 /* 570 * Now, for "pseudo" thermometers, we have two bytes 571 * of information in enclosure status- 16 bits. Actually, 572 * the MSB is a single TEMP ALERT flag indicating whether 573 * any other bits are set, but, thanks to fuzzy thinking, 574 * in the SAF-TE spec, this can also be set even if no 575 * other bits are set, thus making this really another 576 * binary temperature sensor. 577 */ 578 579 SAFT_BAIL(r + cfg->Ntherm, xfer_len); 580 tempflags = buf[r + cfg->Ntherm]; 581 SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len); 582 tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1]; 583 584 for (i = 0; i < cfg->Ntherm; i++) { 585 SAFT_BAIL(r, xfer_len); 586 /* 587 * Status is a range from -10 to 245 deg Celsius, 588 * which we need to normalize to -20 to -245 according 589 * to the latest SCSI spec, which makes little 590 * sense since this would overflow an 8bit value. 591 * Well, still, the base normalization is -20, 592 * not -10, so we have to adjust. 593 * 594 * So what's over and under temperature? 595 * Hmm- we'll state that 'normal' operating 596 * is 10 to 40 deg Celsius. 597 */ 598 599 /* 600 * Actually.... All of the units that people out in the world 601 * seem to have do not come even close to setting a value that 602 * complies with this spec. 603 * 604 * The closest explanation I could find was in an 605 * LSI-Logic manual, which seemed to indicate that 606 * this value would be set by whatever the I2C code 607 * would interpolate from the output of an LM75 608 * temperature sensor. 609 * 610 * This means that it is impossible to use the actual 611 * numeric value to predict anything. But we don't want 612 * to lose the value. So, we'll propagate the *uncorrected* 613 * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the 614 * temperature flags for warnings. 615 */ 616 if (tempflags & (1 << i)) { 617 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT; 618 cfg->enc_status |= SES_ENCSTAT_CRITICAL; 619 } else 620 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 621 cache->elm_map[oid].encstat[1] = 0; 622 cache->elm_map[oid].encstat[2] = buf[r]; 623 cache->elm_map[oid].encstat[3] = 0; 624 cache->elm_map[oid++].svalid = 1; 625 r++; 626 } 627 628 for (i = 0; i <= cfg->Ntstats; i++) { 629 cache->elm_map[oid].encstat[1] = 0; 630 if (tempflags & (1 << 631 ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) { 632 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT; 633 cache->elm_map[4].encstat[2] = 0xff; 634 /* 635 * Set 'over temperature' failure. 636 */ 637 cache->elm_map[oid].encstat[3] = 8; 638 cfg->enc_status |= SES_ENCSTAT_CRITICAL; 639 } else { 640 /* 641 * We used to say 'not available' and synthesize a 642 * nominal 30 deg (C)- that was wrong. Actually, 643 * Just say 'OK', and use the reserved value of 644 * zero. 645 */ 646 if ((cfg->Ntherm + cfg->Ntstats) == 0) 647 cache->elm_map[oid].encstat[0] = 648 SES_OBJSTAT_NOTAVAIL; 649 else 650 cache->elm_map[oid].encstat[0] = 651 SES_OBJSTAT_OK; 652 cache->elm_map[oid].encstat[2] = 0; 653 cache->elm_map[oid].encstat[3] = 0; 654 } 655 cache->elm_map[oid++].svalid = 1; 656 } 657 r += 2; 658 659 cache->enc_status = 660 cfg->enc_status | cfg->slot_status | cfg->adm_status; 661 return (0); 662 } 663 664 static int 665 safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state, 666 union ccb *ccb, uint8_t **bufp, int error, int xfer_len) 667 { 668 struct scfg *cfg; 669 uint8_t *buf = *bufp; 670 enc_cache_t *cache = &enc->enc_cache; 671 int oid, r, i; 672 673 cfg = enc->enc_private; 674 if (cfg == NULL) 675 return (ENXIO); 676 if (error != 0) 677 return (error); 678 cfg->slot_status = 0; 679 oid = cfg->slotoff; 680 for (r = i = 0; i < cfg->Nslots; i++, r += 4) { 681 SAFT_BAIL(r+3, xfer_len); 682 if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) 683 cache->elm_map[oid].encstat[1] = 0; 684 cache->elm_map[oid].encstat[2] &= SESCTL_RQSID; 685 cache->elm_map[oid].encstat[3] = 0; 686 if ((buf[r+3] & 0x01) == 0) { /* no device */ 687 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED; 688 } else if (buf[r+0] & 0x02) { 689 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT; 690 cfg->slot_status |= SES_ENCSTAT_CRITICAL; 691 } else if (buf[r+0] & 0x40) { 692 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT; 693 cfg->slot_status |= SES_ENCSTAT_NONCRITICAL; 694 } else { 695 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK; 696 } 697 if (buf[r+3] & 0x2) { 698 if (buf[r+3] & 0x01) 699 cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV; 700 else 701 cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS; 702 } 703 if ((buf[r+3] & 0x04) == 0) 704 cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF; 705 if (buf[r+0] & 0x02) 706 cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT; 707 if (buf[r+0] & 0x40) 708 cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL; 709 if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) { 710 if (buf[r+0] & 0x01) 711 cache->elm_map[oid].encstat[1] |= 0x80; 712 if (buf[r+0] & 0x04) 713 cache->elm_map[oid].encstat[1] |= 0x02; 714 if (buf[r+0] & 0x08) 715 cache->elm_map[oid].encstat[1] |= 0x04; 716 if (buf[r+0] & 0x10) 717 cache->elm_map[oid].encstat[1] |= 0x08; 718 if (buf[r+0] & 0x20) 719 cache->elm_map[oid].encstat[1] |= 0x10; 720 if (buf[r+1] & 0x01) 721 cache->elm_map[oid].encstat[1] |= 0x20; 722 if (buf[r+1] & 0x02) 723 cache->elm_map[oid].encstat[1] |= 0x01; 724 } 725 cache->elm_map[oid++].svalid = 1; 726 } 727 728 cache->enc_status = 729 cfg->enc_status | cfg->slot_status | cfg->adm_status; 730 return (0); 731 } 732 733 static int 734 safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state, 735 union ccb *ccb, uint8_t *buf) 736 { 737 struct scfg *cfg; 738 enc_element_t *ep, *ep1; 739 safte_control_request_t *req; 740 int i, idx, xfer_len; 741 742 cfg = enc->enc_private; 743 if (cfg == NULL) 744 return (ENXIO); 745 746 if (enc->enc_cache.nelms == 0) { 747 enc_update_request(enc, SAFTE_UPDATE_READCONFIG); 748 return (-1); 749 } 750 751 if (cfg->current_request == NULL) { 752 cfg->current_request = TAILQ_FIRST(&cfg->requests); 753 TAILQ_REMOVE(&cfg->requests, cfg->current_request, links); 754 cfg->current_request_stage = 0; 755 cfg->current_request_stages = 1; 756 } 757 req = cfg->current_request; 758 759 idx = (int)req->elm_idx; 760 if (req->elm_idx == SES_SETSTATUS_ENC_IDX) { 761 cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT; 762 cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN); 763 if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV)) 764 cfg->flag1 |= SAFT_FLG1_GLOBFAIL; 765 else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL) 766 cfg->flag1 |= SAFT_FLG1_GLOBWARN; 767 buf[0] = SAFTE_WT_GLOBAL; 768 buf[1] = cfg->flag1; 769 buf[2] = cfg->flag2; 770 buf[3] = 0; 771 xfer_len = 16; 772 } else { 773 ep = &enc->enc_cache.elm_map[idx]; 774 775 switch (ep->enctype) { 776 case ELMTYP_DEVICE: 777 case ELMTYP_ARRAY_DEV: 778 switch (cfg->current_request_stage) { 779 case 0: 780 ep->priv = 0; 781 if (req->elm_stat[0] & SESCTL_PRDFAIL) 782 ep->priv |= 0x40; 783 if (req->elm_stat[3] & SESCTL_RQSFLT) 784 ep->priv |= 0x02; 785 if (ep->enctype == ELMTYP_ARRAY_DEV) { 786 if (req->elm_stat[1] & 0x01) 787 ep->priv |= 0x200; 788 if (req->elm_stat[1] & 0x02) 789 ep->priv |= 0x04; 790 if (req->elm_stat[1] & 0x04) 791 ep->priv |= 0x08; 792 if (req->elm_stat[1] & 0x08) 793 ep->priv |= 0x10; 794 if (req->elm_stat[1] & 0x10) 795 ep->priv |= 0x20; 796 if (req->elm_stat[1] & 0x20) 797 ep->priv |= 0x100; 798 if (req->elm_stat[1] & 0x80) 799 ep->priv |= 0x01; 800 } 801 if (ep->priv == 0) 802 ep->priv |= 0x01; /* no errors */ 803 804 buf[0] = SAFTE_WT_DSTAT; 805 for (i = 0; i < cfg->Nslots; i++) { 806 ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i]; 807 buf[1 + (3 * i)] = ep1->priv; 808 buf[2 + (3 * i)] = ep1->priv >> 8; 809 } 810 xfer_len = cfg->Nslots * 3 + 1; 811 #define DEVON(x) (!(((x)[2] & SESCTL_RQSINS) | \ 812 ((x)[2] & SESCTL_RQSRMV) | \ 813 ((x)[3] & SESCTL_DEVOFF))) 814 if (DEVON(req->elm_stat) != DEVON(ep->encstat)) 815 cfg->current_request_stages++; 816 #define IDON(x) (!!((x)[2] & SESCTL_RQSID)) 817 if (IDON(req->elm_stat) != IDON(ep->encstat)) 818 cfg->current_request_stages++; 819 break; 820 case 1: 821 case 2: 822 buf[0] = SAFTE_WT_SLTOP; 823 buf[1] = idx - cfg->slotoff; 824 if (cfg->current_request_stage == 1 && 825 DEVON(req->elm_stat) != DEVON(ep->encstat)) { 826 if (DEVON(req->elm_stat)) 827 buf[2] = 0x01; 828 else 829 buf[2] = 0x02; 830 } else { 831 if (IDON(req->elm_stat)) 832 buf[2] = 0x04; 833 else 834 buf[2] = 0x00; 835 ep->encstat[2] &= ~SESCTL_RQSID; 836 ep->encstat[2] |= req->elm_stat[2] & 837 SESCTL_RQSID; 838 } 839 xfer_len = 64; 840 break; 841 default: 842 return (EINVAL); 843 } 844 break; 845 case ELMTYP_POWER: 846 cfg->current_request_stages = 2; 847 switch (cfg->current_request_stage) { 848 case 0: 849 if (req->elm_stat[3] & SESCTL_RQSTFAIL) { 850 cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL; 851 } else { 852 cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL; 853 } 854 buf[0] = SAFTE_WT_GLOBAL; 855 buf[1] = cfg->flag1; 856 buf[2] = cfg->flag2; 857 buf[3] = 0; 858 xfer_len = 16; 859 break; 860 case 1: 861 buf[0] = SAFTE_WT_ACTPWS; 862 buf[1] = idx - cfg->pwroff; 863 if (req->elm_stat[3] & SESCTL_RQSTON) 864 buf[2] = 0x01; 865 else 866 buf[2] = 0x00; 867 buf[3] = 0; 868 xfer_len = 16; 869 default: 870 return (EINVAL); 871 } 872 break; 873 case ELMTYP_FAN: 874 if ((req->elm_stat[3] & 0x7) != 0) 875 cfg->current_request_stages = 2; 876 switch (cfg->current_request_stage) { 877 case 0: 878 if (req->elm_stat[3] & SESCTL_RQSTFAIL) 879 cfg->flag1 |= SAFT_FLG1_ENCFANFAIL; 880 else 881 cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL; 882 buf[0] = SAFTE_WT_GLOBAL; 883 buf[1] = cfg->flag1; 884 buf[2] = cfg->flag2; 885 buf[3] = 0; 886 xfer_len = 16; 887 break; 888 case 1: 889 buf[0] = SAFTE_WT_FANSPD; 890 buf[1] = idx; 891 if (req->elm_stat[3] & SESCTL_RQSTON) { 892 if ((req->elm_stat[3] & 0x7) == 7) 893 buf[2] = 4; 894 else if ((req->elm_stat[3] & 0x7) >= 5) 895 buf[2] = 3; 896 else if ((req->elm_stat[3] & 0x7) >= 3) 897 buf[2] = 2; 898 else 899 buf[2] = 1; 900 } else 901 buf[2] = 0; 902 buf[3] = 0; 903 xfer_len = 16; 904 ep->encstat[3] = req->elm_stat[3] & 0x67; 905 default: 906 return (EINVAL); 907 } 908 break; 909 case ELMTYP_DOORLOCK: 910 if (req->elm_stat[3] & 0x1) 911 cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR; 912 else 913 cfg->flag2 |= SAFT_FLG2_LOCKDOOR; 914 buf[0] = SAFTE_WT_GLOBAL; 915 buf[1] = cfg->flag1; 916 buf[2] = cfg->flag2; 917 buf[3] = 0; 918 xfer_len = 16; 919 break; 920 case ELMTYP_ALARM: 921 if ((req->elm_stat[0] & SESCTL_DISABLE) || 922 (req->elm_stat[3] & 0x40)) { 923 cfg->flag2 &= ~SAFT_FLG1_ALARM; 924 } else if ((req->elm_stat[3] & 0x0f) != 0) { 925 cfg->flag2 |= SAFT_FLG1_ALARM; 926 } else { 927 cfg->flag2 &= ~SAFT_FLG1_ALARM; 928 } 929 buf[0] = SAFTE_WT_GLOBAL; 930 buf[1] = cfg->flag1; 931 buf[2] = cfg->flag2; 932 buf[3] = 0; 933 xfer_len = 16; 934 ep->encstat[3] = req->elm_stat[3]; 935 break; 936 default: 937 return (EINVAL); 938 } 939 } 940 941 if (enc->enc_type == ENC_SEMB_SAFT) { 942 semb_write_buffer(&ccb->ataio, /*retries*/5, 943 NULL, MSG_SIMPLE_Q_TAG, 944 buf, xfer_len, state->timeout); 945 } else { 946 scsi_write_buffer(&ccb->csio, /*retries*/5, 947 NULL, MSG_SIMPLE_Q_TAG, 1, 948 0, 0, buf, xfer_len, 949 SSD_FULL_SIZE, state->timeout); 950 } 951 return (0); 952 } 953 954 static int 955 safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state, 956 union ccb *ccb, uint8_t **bufp, int error, int xfer_len) 957 { 958 struct scfg *cfg; 959 safte_control_request_t *req; 960 int idx, type; 961 962 cfg = enc->enc_private; 963 if (cfg == NULL) 964 return (ENXIO); 965 966 req = cfg->current_request; 967 if (req->result == 0) 968 req->result = error; 969 if (++cfg->current_request_stage >= cfg->current_request_stages) { 970 idx = req->elm_idx; 971 if (idx == SES_SETSTATUS_ENC_IDX) 972 type = -1; 973 else 974 type = enc->enc_cache.elm_map[idx].enctype; 975 if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV) 976 enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS); 977 else 978 enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS); 979 cfg->current_request = NULL; 980 wakeup(req); 981 } else { 982 enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS); 983 } 984 return (0); 985 } 986 987 static void 988 safte_softc_invalidate(enc_softc_t *enc) 989 { 990 struct scfg *cfg; 991 992 cfg = enc->enc_private; 993 safte_terminate_control_requests(&cfg->requests, ENXIO); 994 } 995 996 static void 997 safte_softc_cleanup(enc_softc_t *enc) 998 { 999 1000 ENC_FREE_AND_NULL(enc->enc_cache.elm_map); 1001 ENC_FREE_AND_NULL(enc->enc_private); 1002 enc->enc_cache.nelms = 0; 1003 } 1004 1005 static int 1006 safte_init_enc(enc_softc_t *enc) 1007 { 1008 struct scfg *cfg; 1009 int err; 1010 static char cdb0[6] = { SEND_DIAGNOSTIC }; 1011 1012 cfg = enc->enc_private; 1013 if (cfg == NULL) 1014 return (ENXIO); 1015 1016 err = enc_runcmd(enc, cdb0, 6, NULL, 0); 1017 if (err) { 1018 return (err); 1019 } 1020 DELAY(5000); 1021 cfg->flag1 = 0; 1022 cfg->flag2 = 0; 1023 err = safte_set_enc_status(enc, 0, 1); 1024 return (err); 1025 } 1026 1027 static int 1028 safte_get_enc_status(enc_softc_t *enc, int slpflg) 1029 { 1030 1031 return (0); 1032 } 1033 1034 static int 1035 safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag) 1036 { 1037 struct scfg *cfg; 1038 safte_control_request_t req; 1039 1040 cfg = enc->enc_private; 1041 if (cfg == NULL) 1042 return (ENXIO); 1043 1044 req.elm_idx = SES_SETSTATUS_ENC_IDX; 1045 req.elm_stat[0] = encstat & 0xf; 1046 req.result = 0; 1047 1048 TAILQ_INSERT_TAIL(&cfg->requests, &req, links); 1049 enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS); 1050 cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0); 1051 1052 return (req.result); 1053 } 1054 1055 static int 1056 safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg) 1057 { 1058 int i = (int)elms->elm_idx; 1059 1060 elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0]; 1061 elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1]; 1062 elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2]; 1063 elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3]; 1064 return (0); 1065 } 1066 1067 static int 1068 safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag) 1069 { 1070 struct scfg *cfg; 1071 safte_control_request_t req; 1072 1073 cfg = enc->enc_private; 1074 if (cfg == NULL) 1075 return (ENXIO); 1076 1077 /* If this is clear, we don't do diddly. */ 1078 if ((elms->cstat[0] & SESCTL_CSEL) == 0) 1079 return (0); 1080 1081 req.elm_idx = elms->elm_idx; 1082 memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat)); 1083 req.result = 0; 1084 1085 TAILQ_INSERT_TAIL(&cfg->requests, &req, links); 1086 enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS); 1087 cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0); 1088 1089 return (req.result); 1090 } 1091 1092 static void 1093 safte_poll_status(enc_softc_t *enc) 1094 { 1095 1096 enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS); 1097 enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS); 1098 } 1099 1100 static struct enc_vec safte_enc_vec = 1101 { 1102 .softc_invalidate = safte_softc_invalidate, 1103 .softc_cleanup = safte_softc_cleanup, 1104 .init_enc = safte_init_enc, 1105 .get_enc_status = safte_get_enc_status, 1106 .set_enc_status = safte_set_enc_status, 1107 .get_elm_status = safte_get_elm_status, 1108 .set_elm_status = safte_set_elm_status, 1109 .poll_status = safte_poll_status 1110 }; 1111 1112 int 1113 safte_softc_init(enc_softc_t *enc) 1114 { 1115 struct scfg *cfg; 1116 1117 enc->enc_vec = safte_enc_vec; 1118 enc->enc_fsm_states = enc_fsm_states; 1119 1120 if (enc->enc_private == NULL) { 1121 enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE); 1122 if (enc->enc_private == NULL) 1123 return (ENOMEM); 1124 } 1125 cfg = enc->enc_private; 1126 1127 enc->enc_cache.nelms = 0; 1128 enc->enc_cache.enc_status = 0; 1129 1130 TAILQ_INIT(&cfg->requests); 1131 return (0); 1132 } 1133 1134