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