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