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