282 return (0); 283} 284 285static void 286enc_start(struct cam_periph *p, union ccb *sccb) 287{ 288 struct enc_softc *enc; 289 290 enc = p->softc; 291 ENC_DLOG(enc, "%s enter imm=%d prio=%d\n", 292 __func__, p->immediate_priority, p->pinfo.priority); 293 if (p->immediate_priority <= p->pinfo.priority) { 294 SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle); 295 p->immediate_priority = CAM_PRIORITY_NONE; 296 wakeup(&p->ccb_list); 297 } else 298 xpt_release_ccb(sccb); 299 ENC_DLOG(enc, "%s exit\n", __func__); 300} 301 302void 303enc_done(struct cam_periph *periph, union ccb *dccb) 304{ 305 wakeup(&dccb->ccb_h.cbfcnp); 306} 307 308int 309enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags) 310{ 311 struct enc_softc *softc; 312 struct cam_periph *periph; 313 314 periph = xpt_path_periph(ccb->ccb_h.path); 315 softc = (struct enc_softc *)periph->softc; 316 317 return (cam_periph_error(ccb, cflags, sflags, &softc->saved_ccb)); 318} 319 320static int 321enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, 322 struct thread *td) 323{ 324 struct cam_periph *periph; 325 encioc_enc_status_t tmp; 326 encioc_string_t sstr; 327 encioc_elm_status_t elms; 328 encioc_elm_desc_t elmd; 329 encioc_elm_devnames_t elmdn; 330 encioc_element_t *uelm; 331 enc_softc_t *enc; 332 enc_cache_t *cache; 333 void *addr; 334 int error, i; 335 336 337 if (arg_addr) 338 addr = *((caddr_t *) arg_addr); 339 else 340 addr = NULL; 341 342 periph = (struct cam_periph *)dev->si_drv1; 343 if (periph == NULL) 344 return (ENXIO); 345 346 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering encioctl\n")); 347 348 cam_periph_lock(periph); 349 enc = (struct enc_softc *)periph->softc; 350 cache = &enc->enc_cache; 351 352 /* 353 * Now check to see whether we're initialized or not. 354 * This actually should never fail as we're not supposed 355 * to get past enc_open w/o successfully initializing 356 * things. 357 */ 358 if ((enc->enc_flags & ENC_FLAG_INITIALIZED) == 0) { 359 cam_periph_unlock(periph); 360 return (ENXIO); 361 } 362 cam_periph_unlock(periph); 363 364 error = 0; 365 366 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 367 ("trying to do ioctl %#lx\n", cmd)); 368 369 /* 370 * If this command can change the device's state, 371 * we must have the device open for writing. 372 * 373 * For commands that get information about the 374 * device- we don't need to lock the peripheral 375 * if we aren't running a command. The periph 376 * also can't go away while a user process has 377 * it open. 378 */ 379 switch (cmd) { 380 case ENCIOC_GETNELM: 381 case ENCIOC_GETELMMAP: 382 case ENCIOC_GETENCSTAT: 383 case ENCIOC_GETELMSTAT: 384 case ENCIOC_GETELMDESC: 385 case ENCIOC_GETELMDEVNAMES: 386 break; 387 default: 388 if ((flag & FWRITE) == 0) { 389 return (EBADF); 390 } 391 } 392 393 /* 394 * XXX The values read here are only valid for the current 395 * configuration generation. We need these ioctls 396 * to also pass in/out a generation number. 397 */ 398 sx_slock(&enc->enc_cache_lock); 399 switch (cmd) { 400 case ENCIOC_GETNELM: 401 error = copyout(&cache->nelms, addr, sizeof (cache->nelms)); 402 break; 403 404 case ENCIOC_GETELMMAP: 405 for (uelm = addr, i = 0; i != cache->nelms; i++) { 406 encioc_element_t kelm; 407 kelm.elm_idx = i; 408 kelm.elm_subenc_id = cache->elm_map[i].subenclosure; 409 kelm.elm_type = cache->elm_map[i].enctype; 410 error = copyout(&kelm, &uelm[i], sizeof(kelm)); 411 if (error) 412 break; 413 } 414 break; 415 416 case ENCIOC_GETENCSTAT: 417 cam_periph_lock(periph); 418 error = enc->enc_vec.get_enc_status(enc, 1); 419 if (error) { 420 cam_periph_unlock(periph); 421 break; 422 } 423 tmp = cache->enc_status; 424 cam_periph_unlock(periph); 425 error = copyout(&tmp, addr, sizeof(tmp)); 426 cache->enc_status = tmp; 427 break; 428 429 case ENCIOC_SETENCSTAT: 430 error = copyin(addr, &tmp, sizeof(tmp)); 431 if (error) 432 break; 433 cam_periph_lock(periph); 434 error = enc->enc_vec.set_enc_status(enc, tmp, 1); 435 cam_periph_unlock(periph); 436 break; 437 438 case ENCIOC_GETSTRING: 439 case ENCIOC_SETSTRING: 440 if (enc->enc_vec.handle_string == NULL) { 441 error = EINVAL; 442 break; 443 } 444 error = copyin(addr, &sstr, sizeof(sstr)); 445 if (error) 446 break; 447 cam_periph_lock(periph); 448 error = enc->enc_vec.handle_string(enc, &sstr, cmd); 449 cam_periph_unlock(periph); 450 break; 451 452 case ENCIOC_GETELMSTAT: 453 error = copyin(addr, &elms, sizeof(elms)); 454 if (error) 455 break; 456 if (elms.elm_idx >= cache->nelms) { 457 error = EINVAL; 458 break; 459 } 460 cam_periph_lock(periph); 461 error = enc->enc_vec.get_elm_status(enc, &elms, 1); 462 cam_periph_unlock(periph); 463 if (error) 464 break; 465 error = copyout(&elms, addr, sizeof(elms)); 466 break; 467 468 case ENCIOC_GETELMDESC: 469 error = copyin(addr, &elmd, sizeof(elmd)); 470 if (error) 471 break; 472 if (elmd.elm_idx >= cache->nelms) { 473 error = EINVAL; 474 break; 475 } 476 if (enc->enc_vec.get_elm_desc != NULL) { 477 error = enc->enc_vec.get_elm_desc(enc, &elmd); 478 if (error) 479 break; 480 } else 481 elmd.elm_desc_len = 0; 482 error = copyout(&elmd, addr, sizeof(elmd)); 483 break; 484 485 case ENCIOC_GETELMDEVNAMES: 486 if (enc->enc_vec.get_elm_devnames == NULL) { 487 error = EINVAL; 488 break; 489 } 490 error = copyin(addr, &elmdn, sizeof(elmdn)); 491 if (error) 492 break; 493 if (elmdn.elm_idx >= cache->nelms) { 494 error = EINVAL; 495 break; 496 } 497 cam_periph_lock(periph); 498 error = (*enc->enc_vec.get_elm_devnames)(enc, &elmdn); 499 cam_periph_unlock(periph); 500 if (error) 501 break; 502 error = copyout(&elmdn, addr, sizeof(elmdn)); 503 break; 504 505 case ENCIOC_SETELMSTAT: 506 error = copyin(addr, &elms, sizeof(elms)); 507 if (error) 508 break; 509 510 if (elms.elm_idx >= cache->nelms) { 511 error = EINVAL; 512 break; 513 } 514 cam_periph_lock(periph); 515 error = enc->enc_vec.set_elm_status(enc, &elms, 1); 516 cam_periph_unlock(periph); 517 518 break; 519 520 case ENCIOC_INIT: 521 522 cam_periph_lock(periph); 523 error = enc->enc_vec.init_enc(enc); 524 cam_periph_unlock(periph); 525 break; 526 527 default: 528 cam_periph_lock(periph); 529 error = cam_periph_ioctl(periph, cmd, arg_addr, enc_error); 530 cam_periph_unlock(periph); 531 break; 532 } 533 sx_sunlock(&enc->enc_cache_lock); 534 return (error); 535} 536 537int 538enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp) 539{ 540 int error, dlen, tdlen; 541 ccb_flags ddf; 542 union ccb *ccb; 543 544 CAM_DEBUG(enc->periph->path, CAM_DEBUG_TRACE, 545 ("entering enc_runcmd\n")); 546 if (dptr) { 547 if ((dlen = *dlenp) < 0) { 548 dlen = -dlen; 549 ddf = CAM_DIR_OUT; 550 } else { 551 ddf = CAM_DIR_IN; 552 } 553 } else { 554 dlen = 0; 555 ddf = CAM_DIR_NONE; 556 } 557 558 if (cdbl > IOCDBLEN) { 559 cdbl = IOCDBLEN; 560 } 561 562 ccb = cam_periph_getccb(enc->periph, CAM_PRIORITY_NORMAL); 563 if (enc->enc_type == ENC_SEMB_SES || enc->enc_type == ENC_SEMB_SAFT) { 564 tdlen = min(dlen, 1020); 565 tdlen = (tdlen + 3) & ~3; 566 cam_fill_ataio(&ccb->ataio, 0, enc_done, ddf, 0, dptr, tdlen, 567 30 * 1000); 568 if (cdb[0] == RECEIVE_DIAGNOSTIC) 569 ata_28bit_cmd(&ccb->ataio, 570 ATA_SEP_ATTN, cdb[2], 0x02, tdlen / 4); 571 else if (cdb[0] == SEND_DIAGNOSTIC) 572 ata_28bit_cmd(&ccb->ataio, 573 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0, 574 0x82, tdlen / 4); 575 else if (cdb[0] == READ_BUFFER) 576 ata_28bit_cmd(&ccb->ataio, 577 ATA_SEP_ATTN, cdb[2], 0x00, tdlen / 4); 578 else 579 ata_28bit_cmd(&ccb->ataio, 580 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0, 581 0x80, tdlen / 4); 582 } else { 583 tdlen = dlen; 584 cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG, 585 dptr, dlen, sizeof (struct scsi_sense_data), cdbl, 586 60 * 1000); 587 bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl); 588 } 589 590 error = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL); 591 if (error) { 592 if (dptr) { 593 *dlenp = dlen; 594 } 595 } else { 596 if (dptr) { 597 if (ccb->ccb_h.func_code == XPT_ATA_IO) 598 *dlenp = ccb->ataio.resid; 599 else 600 *dlenp = ccb->csio.resid; 601 *dlenp += tdlen - dlen; 602 } 603 } 604 xpt_release_ccb(ccb); 605 CAM_DEBUG(enc->periph->path, CAM_DEBUG_SUBTRACE, 606 ("exiting enc_runcmd: *dlenp = %d\n", *dlenp)); 607 return (error); 608} 609 610void 611enc_log(struct enc_softc *enc, const char *fmt, ...) 612{ 613 va_list ap; 614 615 printf("%s%d: ", enc->periph->periph_name, enc->periph->unit_number); 616 va_start(ap, fmt); 617 vprintf(fmt, ap); 618 va_end(ap); 619} 620 621/* 622 * The code after this point runs on many platforms, 623 * so forgive the slightly awkward and nonconforming 624 * appearance. 625 */ 626 627/* 628 * Is this a device that supports enclosure services? 629 * 630 * It's a pretty simple ruleset- if it is device type 631 * 0x0D (13), it's an ENCLOSURE device. 632 */ 633 634#define SAFTE_START 44 635#define SAFTE_END 50 636#define SAFTE_LEN SAFTE_END-SAFTE_START 637 638static enctyp 639enc_type(struct ccb_getdev *cgd) 640{ 641 int buflen; 642 unsigned char *iqd; 643 644 if (cgd->protocol == PROTO_SEMB) { 645 iqd = (unsigned char *)&cgd->ident_data; 646 if (STRNCMP(iqd + 43, "S-E-S", 5) == 0) 647 return (ENC_SEMB_SES); 648 else if (STRNCMP(iqd + 43, "SAF-TE", 6) == 0) 649 return (ENC_SEMB_SAFT); 650 return (ENC_NONE); 651 652 } else if (cgd->protocol != PROTO_SCSI) 653 return (ENC_NONE); 654 655 iqd = (unsigned char *)&cgd->inq_data; 656 buflen = min(sizeof(cgd->inq_data), 657 SID_ADDITIONAL_LENGTH(&cgd->inq_data)); 658 659 if ((iqd[0] & 0x1f) == T_ENCLOSURE) { 660 if ((iqd[2] & 0x7) > 2) { 661 return (ENC_SES); 662 } else { 663 return (ENC_SES_SCSI2); 664 } 665 return (ENC_NONE); 666 } 667 668#ifdef ENC_ENABLE_PASSTHROUGH 669 if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) { 670 /* 671 * PassThrough Device. 672 */ 673 return (ENC_ENC_PASSTHROUGH); 674 } 675#endif 676 677 /* 678 * The comparison is short for a reason- 679 * some vendors were chopping it short. 680 */ 681 682 if (buflen < SAFTE_END - 2) { 683 return (ENC_NONE); 684 } 685 686 if (STRNCMP((char *)&iqd[SAFTE_START], "SAF-TE", SAFTE_LEN - 2) == 0) { 687 return (ENC_SAFT); 688 } 689 return (ENC_NONE); 690} 691 692/*================== Enclosure Monitoring/Processing Daemon ==================*/ 693/** 694 * \brief Queue an update request for a given action, if needed. 695 * 696 * \param enc SES softc to queue the request for. 697 * \param action Action requested. 698 */ 699void 700enc_update_request(enc_softc_t *enc, uint32_t action) 701{ 702 if ((enc->pending_actions & (0x1 << action)) == 0) { 703 enc->pending_actions |= (0x1 << action); 704 ENC_DLOG(enc, "%s: queing requested action %d\n", 705 __func__, action); 706 if (enc->current_action == ENC_UPDATE_NONE) 707 wakeup(enc->enc_daemon); 708 } else { 709 ENC_DLOG(enc, "%s: ignoring requested action %d - " 710 "Already queued\n", __func__, action); 711 } 712} 713 714/** 715 * \brief Invoke the handler of the highest priority pending 716 * state in the SES state machine. 717 * 718 * \param enc The SES instance invoking the state machine. 719 */ 720static void 721enc_fsm_step(enc_softc_t *enc) 722{ 723 union ccb *ccb; 724 uint8_t *buf; 725 struct enc_fsm_state *cur_state; 726 int error; 727 uint32_t xfer_len; 728 729 ENC_DLOG(enc, "%s enter %p\n", __func__, enc); 730 731 enc->current_action = ffs(enc->pending_actions) - 1; 732 enc->pending_actions &= ~(0x1 << enc->current_action); 733 734 cur_state = &enc->enc_fsm_states[enc->current_action]; 735 736 buf = NULL; 737 if (cur_state->buf_size != 0) { 738 cam_periph_unlock(enc->periph); 739 buf = malloc(cur_state->buf_size, M_SCSIENC, M_WAITOK|M_ZERO); 740 cam_periph_lock(enc->periph); 741 } 742 743 error = 0; 744 ccb = NULL; 745 if (cur_state->fill != NULL) { 746 ccb = cam_periph_getccb(enc->periph, CAM_PRIORITY_NORMAL); 747 748 error = cur_state->fill(enc, cur_state, ccb, buf); 749 if (error != 0) 750 goto done; 751 752 error = cam_periph_runccb(ccb, cur_state->error, 753 ENC_CFLAGS, 754 ENC_FLAGS|SF_QUIET_IR, NULL); 755 } 756 757 if (ccb != NULL) { 758 if (ccb->ccb_h.func_code == XPT_ATA_IO) 759 xfer_len = ccb->ataio.dxfer_len - ccb->ataio.resid; 760 else 761 xfer_len = ccb->csio.dxfer_len - ccb->csio.resid; 762 } else 763 xfer_len = 0; 764 765 cam_periph_unlock(enc->periph); 766 cur_state->done(enc, cur_state, ccb, &buf, error, xfer_len); 767 cam_periph_lock(enc->periph); 768 769done: 770 ENC_DLOG(enc, "%s exit - result %d\n", __func__, error); 771 ENC_FREE_AND_NULL(buf); 772 if (ccb != NULL) 773 xpt_release_ccb(ccb); 774} 775 776/** 777 * \invariant Called with cam_periph mutex held. 778 */ 779static void 780enc_status_updater(void *arg) 781{ 782 enc_softc_t *enc; 783 784 enc = arg; 785 if (enc->enc_vec.poll_status != NULL) 786 enc->enc_vec.poll_status(enc); 787} 788 789static void 790enc_daemon(void *arg) 791{ 792 enc_softc_t *enc; 793 794 enc = arg; 795 796 cam_periph_lock(enc->periph); 797 while ((enc->enc_flags & ENC_FLAG_SHUTDOWN) == 0) { 798 if (enc->pending_actions == 0) { 799 struct intr_config_hook *hook; 800 801 /* 802 * Reset callout and msleep, or 803 * issue timed task completion 804 * status command. 805 */ 806 enc->current_action = ENC_UPDATE_NONE; 807 808 /* 809 * We've been through our state machine at least 810 * once. Allow the transition to userland. 811 */ 812 hook = &enc->enc_boot_hold_ch; 813 if (hook->ich_func != NULL) { 814 config_intrhook_disestablish(hook); 815 hook->ich_func = NULL; 816 } 817 818 callout_reset(&enc->status_updater, 60*hz, 819 enc_status_updater, enc); 820 821 cam_periph_sleep(enc->periph, enc->enc_daemon, 822 PUSER, "idle", 0); 823 } else { 824 enc_fsm_step(enc); 825 } 826 } 827 enc->enc_daemon = NULL; 828 cam_periph_unlock(enc->periph); 829 cam_periph_release(enc->periph); 830 kproc_exit(0); 831} 832 833static int 834enc_kproc_init(enc_softc_t *enc) 835{ 836 int result; 837 838 callout_init_mtx(&enc->status_updater, enc->periph->sim->mtx, 0); 839 840 if (cam_periph_acquire(enc->periph) != CAM_REQ_CMP) 841 return (ENXIO); 842 843 result = kproc_create(enc_daemon, enc, &enc->enc_daemon, /*flags*/0, 844 /*stackpgs*/0, "enc_daemon%d", 845 enc->periph->unit_number); 846 if (result == 0) { 847 /* Do an initial load of all page data. */ 848 cam_periph_lock(enc->periph); 849 enc->enc_vec.poll_status(enc); 850 cam_periph_unlock(enc->periph); 851 } else 852 cam_periph_release(enc->periph); 853 return (result); 854} 855 856/** 857 * \brief Interrupt configuration hook callback associated with 858 * enc_boot_hold_ch. 859 * 860 * Since interrupts are always functional at the time of enclosure 861 * configuration, there is nothing to be done when the callback occurs. 862 * This hook is only registered to hold up boot processing while initial 863 * eclosure processing occurs. 864 * 865 * \param arg The enclosure softc, but currently unused in this callback. 866 */ 867static void 868enc_nop_confighook_cb(void *arg __unused) 869{ 870} 871 872static cam_status 873enc_ctor(struct cam_periph *periph, void *arg) 874{ 875 cam_status status = CAM_REQ_CMP_ERR; 876 int err; 877 enc_softc_t *enc; 878 struct ccb_getdev *cgd; 879 char *tname; 880 881 cgd = (struct ccb_getdev *)arg; 882 if (cgd == NULL) { 883 printf("enc_ctor: no getdev CCB, can't register device\n"); 884 goto out; 885 } 886 887 enc = ENC_MALLOCZ(sizeof(*enc)); 888 if (enc == NULL) { 889 printf("enc_ctor: Unable to probe new device. " 890 "Unable to allocate enc\n"); 891 goto out; 892 } 893 enc->periph = periph; 894 enc->current_action = ENC_UPDATE_INVALID; 895 896 enc->enc_type = enc_type(cgd); 897 sx_init(&enc->enc_cache_lock, "enccache"); 898 899 switch (enc->enc_type) { 900 case ENC_SES: 901 case ENC_SES_SCSI2: 902 case ENC_SES_PASSTHROUGH: 903 case ENC_SEMB_SES: 904 err = ses_softc_init(enc); 905 break; 906 case ENC_SAFT: 907 case ENC_SEMB_SAFT: 908 err = safte_softc_init(enc); 909 break; 910 case ENC_NONE: 911 default: 912 ENC_FREE(enc); 913 return (CAM_REQ_CMP_ERR); 914 } 915 916 if (err) { 917 xpt_print(periph->path, "error %d initializing\n", err); 918 goto out; 919 } 920 921 /* 922 * Hold off userland until we have made at least one pass 923 * through our state machine so that physical path data is 924 * present. 925 */ 926 if (enc->enc_vec.poll_status != NULL) { 927 enc->enc_boot_hold_ch.ich_func = enc_nop_confighook_cb; 928 enc->enc_boot_hold_ch.ich_arg = enc; 929 config_intrhook_establish(&enc->enc_boot_hold_ch); 930 } 931 932 /* 933 * The softc field is set only once the enc is fully initialized 934 * so that we can rely on this field to detect partially 935 * initialized periph objects in the AC_FOUND_DEVICE handler. 936 */ 937 periph->softc = enc; 938 939 cam_periph_unlock(periph); 940 if (enc->enc_vec.poll_status != NULL) { 941 err = enc_kproc_init(enc); 942 if (err) { 943 xpt_print(periph->path, 944 "error %d starting enc_daemon\n", err); 945 goto out; 946 } 947 } 948
| 336 return (0); 337} 338 339static void 340enc_start(struct cam_periph *p, union ccb *sccb) 341{ 342 struct enc_softc *enc; 343 344 enc = p->softc; 345 ENC_DLOG(enc, "%s enter imm=%d prio=%d\n", 346 __func__, p->immediate_priority, p->pinfo.priority); 347 if (p->immediate_priority <= p->pinfo.priority) { 348 SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle); 349 p->immediate_priority = CAM_PRIORITY_NONE; 350 wakeup(&p->ccb_list); 351 } else 352 xpt_release_ccb(sccb); 353 ENC_DLOG(enc, "%s exit\n", __func__); 354} 355 356void 357enc_done(struct cam_periph *periph, union ccb *dccb) 358{ 359 wakeup(&dccb->ccb_h.cbfcnp); 360} 361 362int 363enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags) 364{ 365 struct enc_softc *softc; 366 struct cam_periph *periph; 367 368 periph = xpt_path_periph(ccb->ccb_h.path); 369 softc = (struct enc_softc *)periph->softc; 370 371 return (cam_periph_error(ccb, cflags, sflags, &softc->saved_ccb)); 372} 373 374static int 375enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, 376 struct thread *td) 377{ 378 struct cam_periph *periph; 379 encioc_enc_status_t tmp; 380 encioc_string_t sstr; 381 encioc_elm_status_t elms; 382 encioc_elm_desc_t elmd; 383 encioc_elm_devnames_t elmdn; 384 encioc_element_t *uelm; 385 enc_softc_t *enc; 386 enc_cache_t *cache; 387 void *addr; 388 int error, i; 389 390 391 if (arg_addr) 392 addr = *((caddr_t *) arg_addr); 393 else 394 addr = NULL; 395 396 periph = (struct cam_periph *)dev->si_drv1; 397 if (periph == NULL) 398 return (ENXIO); 399 400 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering encioctl\n")); 401 402 cam_periph_lock(periph); 403 enc = (struct enc_softc *)periph->softc; 404 cache = &enc->enc_cache; 405 406 /* 407 * Now check to see whether we're initialized or not. 408 * This actually should never fail as we're not supposed 409 * to get past enc_open w/o successfully initializing 410 * things. 411 */ 412 if ((enc->enc_flags & ENC_FLAG_INITIALIZED) == 0) { 413 cam_periph_unlock(periph); 414 return (ENXIO); 415 } 416 cam_periph_unlock(periph); 417 418 error = 0; 419 420 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 421 ("trying to do ioctl %#lx\n", cmd)); 422 423 /* 424 * If this command can change the device's state, 425 * we must have the device open for writing. 426 * 427 * For commands that get information about the 428 * device- we don't need to lock the peripheral 429 * if we aren't running a command. The periph 430 * also can't go away while a user process has 431 * it open. 432 */ 433 switch (cmd) { 434 case ENCIOC_GETNELM: 435 case ENCIOC_GETELMMAP: 436 case ENCIOC_GETENCSTAT: 437 case ENCIOC_GETELMSTAT: 438 case ENCIOC_GETELMDESC: 439 case ENCIOC_GETELMDEVNAMES: 440 break; 441 default: 442 if ((flag & FWRITE) == 0) { 443 return (EBADF); 444 } 445 } 446 447 /* 448 * XXX The values read here are only valid for the current 449 * configuration generation. We need these ioctls 450 * to also pass in/out a generation number. 451 */ 452 sx_slock(&enc->enc_cache_lock); 453 switch (cmd) { 454 case ENCIOC_GETNELM: 455 error = copyout(&cache->nelms, addr, sizeof (cache->nelms)); 456 break; 457 458 case ENCIOC_GETELMMAP: 459 for (uelm = addr, i = 0; i != cache->nelms; i++) { 460 encioc_element_t kelm; 461 kelm.elm_idx = i; 462 kelm.elm_subenc_id = cache->elm_map[i].subenclosure; 463 kelm.elm_type = cache->elm_map[i].enctype; 464 error = copyout(&kelm, &uelm[i], sizeof(kelm)); 465 if (error) 466 break; 467 } 468 break; 469 470 case ENCIOC_GETENCSTAT: 471 cam_periph_lock(periph); 472 error = enc->enc_vec.get_enc_status(enc, 1); 473 if (error) { 474 cam_periph_unlock(periph); 475 break; 476 } 477 tmp = cache->enc_status; 478 cam_periph_unlock(periph); 479 error = copyout(&tmp, addr, sizeof(tmp)); 480 cache->enc_status = tmp; 481 break; 482 483 case ENCIOC_SETENCSTAT: 484 error = copyin(addr, &tmp, sizeof(tmp)); 485 if (error) 486 break; 487 cam_periph_lock(periph); 488 error = enc->enc_vec.set_enc_status(enc, tmp, 1); 489 cam_periph_unlock(periph); 490 break; 491 492 case ENCIOC_GETSTRING: 493 case ENCIOC_SETSTRING: 494 if (enc->enc_vec.handle_string == NULL) { 495 error = EINVAL; 496 break; 497 } 498 error = copyin(addr, &sstr, sizeof(sstr)); 499 if (error) 500 break; 501 cam_periph_lock(periph); 502 error = enc->enc_vec.handle_string(enc, &sstr, cmd); 503 cam_periph_unlock(periph); 504 break; 505 506 case ENCIOC_GETELMSTAT: 507 error = copyin(addr, &elms, sizeof(elms)); 508 if (error) 509 break; 510 if (elms.elm_idx >= cache->nelms) { 511 error = EINVAL; 512 break; 513 } 514 cam_periph_lock(periph); 515 error = enc->enc_vec.get_elm_status(enc, &elms, 1); 516 cam_periph_unlock(periph); 517 if (error) 518 break; 519 error = copyout(&elms, addr, sizeof(elms)); 520 break; 521 522 case ENCIOC_GETELMDESC: 523 error = copyin(addr, &elmd, sizeof(elmd)); 524 if (error) 525 break; 526 if (elmd.elm_idx >= cache->nelms) { 527 error = EINVAL; 528 break; 529 } 530 if (enc->enc_vec.get_elm_desc != NULL) { 531 error = enc->enc_vec.get_elm_desc(enc, &elmd); 532 if (error) 533 break; 534 } else 535 elmd.elm_desc_len = 0; 536 error = copyout(&elmd, addr, sizeof(elmd)); 537 break; 538 539 case ENCIOC_GETELMDEVNAMES: 540 if (enc->enc_vec.get_elm_devnames == NULL) { 541 error = EINVAL; 542 break; 543 } 544 error = copyin(addr, &elmdn, sizeof(elmdn)); 545 if (error) 546 break; 547 if (elmdn.elm_idx >= cache->nelms) { 548 error = EINVAL; 549 break; 550 } 551 cam_periph_lock(periph); 552 error = (*enc->enc_vec.get_elm_devnames)(enc, &elmdn); 553 cam_periph_unlock(periph); 554 if (error) 555 break; 556 error = copyout(&elmdn, addr, sizeof(elmdn)); 557 break; 558 559 case ENCIOC_SETELMSTAT: 560 error = copyin(addr, &elms, sizeof(elms)); 561 if (error) 562 break; 563 564 if (elms.elm_idx >= cache->nelms) { 565 error = EINVAL; 566 break; 567 } 568 cam_periph_lock(periph); 569 error = enc->enc_vec.set_elm_status(enc, &elms, 1); 570 cam_periph_unlock(periph); 571 572 break; 573 574 case ENCIOC_INIT: 575 576 cam_periph_lock(periph); 577 error = enc->enc_vec.init_enc(enc); 578 cam_periph_unlock(periph); 579 break; 580 581 default: 582 cam_periph_lock(periph); 583 error = cam_periph_ioctl(periph, cmd, arg_addr, enc_error); 584 cam_periph_unlock(periph); 585 break; 586 } 587 sx_sunlock(&enc->enc_cache_lock); 588 return (error); 589} 590 591int 592enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp) 593{ 594 int error, dlen, tdlen; 595 ccb_flags ddf; 596 union ccb *ccb; 597 598 CAM_DEBUG(enc->periph->path, CAM_DEBUG_TRACE, 599 ("entering enc_runcmd\n")); 600 if (dptr) { 601 if ((dlen = *dlenp) < 0) { 602 dlen = -dlen; 603 ddf = CAM_DIR_OUT; 604 } else { 605 ddf = CAM_DIR_IN; 606 } 607 } else { 608 dlen = 0; 609 ddf = CAM_DIR_NONE; 610 } 611 612 if (cdbl > IOCDBLEN) { 613 cdbl = IOCDBLEN; 614 } 615 616 ccb = cam_periph_getccb(enc->periph, CAM_PRIORITY_NORMAL); 617 if (enc->enc_type == ENC_SEMB_SES || enc->enc_type == ENC_SEMB_SAFT) { 618 tdlen = min(dlen, 1020); 619 tdlen = (tdlen + 3) & ~3; 620 cam_fill_ataio(&ccb->ataio, 0, enc_done, ddf, 0, dptr, tdlen, 621 30 * 1000); 622 if (cdb[0] == RECEIVE_DIAGNOSTIC) 623 ata_28bit_cmd(&ccb->ataio, 624 ATA_SEP_ATTN, cdb[2], 0x02, tdlen / 4); 625 else if (cdb[0] == SEND_DIAGNOSTIC) 626 ata_28bit_cmd(&ccb->ataio, 627 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0, 628 0x82, tdlen / 4); 629 else if (cdb[0] == READ_BUFFER) 630 ata_28bit_cmd(&ccb->ataio, 631 ATA_SEP_ATTN, cdb[2], 0x00, tdlen / 4); 632 else 633 ata_28bit_cmd(&ccb->ataio, 634 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0, 635 0x80, tdlen / 4); 636 } else { 637 tdlen = dlen; 638 cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG, 639 dptr, dlen, sizeof (struct scsi_sense_data), cdbl, 640 60 * 1000); 641 bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl); 642 } 643 644 error = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL); 645 if (error) { 646 if (dptr) { 647 *dlenp = dlen; 648 } 649 } else { 650 if (dptr) { 651 if (ccb->ccb_h.func_code == XPT_ATA_IO) 652 *dlenp = ccb->ataio.resid; 653 else 654 *dlenp = ccb->csio.resid; 655 *dlenp += tdlen - dlen; 656 } 657 } 658 xpt_release_ccb(ccb); 659 CAM_DEBUG(enc->periph->path, CAM_DEBUG_SUBTRACE, 660 ("exiting enc_runcmd: *dlenp = %d\n", *dlenp)); 661 return (error); 662} 663 664void 665enc_log(struct enc_softc *enc, const char *fmt, ...) 666{ 667 va_list ap; 668 669 printf("%s%d: ", enc->periph->periph_name, enc->periph->unit_number); 670 va_start(ap, fmt); 671 vprintf(fmt, ap); 672 va_end(ap); 673} 674 675/* 676 * The code after this point runs on many platforms, 677 * so forgive the slightly awkward and nonconforming 678 * appearance. 679 */ 680 681/* 682 * Is this a device that supports enclosure services? 683 * 684 * It's a pretty simple ruleset- if it is device type 685 * 0x0D (13), it's an ENCLOSURE device. 686 */ 687 688#define SAFTE_START 44 689#define SAFTE_END 50 690#define SAFTE_LEN SAFTE_END-SAFTE_START 691 692static enctyp 693enc_type(struct ccb_getdev *cgd) 694{ 695 int buflen; 696 unsigned char *iqd; 697 698 if (cgd->protocol == PROTO_SEMB) { 699 iqd = (unsigned char *)&cgd->ident_data; 700 if (STRNCMP(iqd + 43, "S-E-S", 5) == 0) 701 return (ENC_SEMB_SES); 702 else if (STRNCMP(iqd + 43, "SAF-TE", 6) == 0) 703 return (ENC_SEMB_SAFT); 704 return (ENC_NONE); 705 706 } else if (cgd->protocol != PROTO_SCSI) 707 return (ENC_NONE); 708 709 iqd = (unsigned char *)&cgd->inq_data; 710 buflen = min(sizeof(cgd->inq_data), 711 SID_ADDITIONAL_LENGTH(&cgd->inq_data)); 712 713 if ((iqd[0] & 0x1f) == T_ENCLOSURE) { 714 if ((iqd[2] & 0x7) > 2) { 715 return (ENC_SES); 716 } else { 717 return (ENC_SES_SCSI2); 718 } 719 return (ENC_NONE); 720 } 721 722#ifdef ENC_ENABLE_PASSTHROUGH 723 if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) { 724 /* 725 * PassThrough Device. 726 */ 727 return (ENC_ENC_PASSTHROUGH); 728 } 729#endif 730 731 /* 732 * The comparison is short for a reason- 733 * some vendors were chopping it short. 734 */ 735 736 if (buflen < SAFTE_END - 2) { 737 return (ENC_NONE); 738 } 739 740 if (STRNCMP((char *)&iqd[SAFTE_START], "SAF-TE", SAFTE_LEN - 2) == 0) { 741 return (ENC_SAFT); 742 } 743 return (ENC_NONE); 744} 745 746/*================== Enclosure Monitoring/Processing Daemon ==================*/ 747/** 748 * \brief Queue an update request for a given action, if needed. 749 * 750 * \param enc SES softc to queue the request for. 751 * \param action Action requested. 752 */ 753void 754enc_update_request(enc_softc_t *enc, uint32_t action) 755{ 756 if ((enc->pending_actions & (0x1 << action)) == 0) { 757 enc->pending_actions |= (0x1 << action); 758 ENC_DLOG(enc, "%s: queing requested action %d\n", 759 __func__, action); 760 if (enc->current_action == ENC_UPDATE_NONE) 761 wakeup(enc->enc_daemon); 762 } else { 763 ENC_DLOG(enc, "%s: ignoring requested action %d - " 764 "Already queued\n", __func__, action); 765 } 766} 767 768/** 769 * \brief Invoke the handler of the highest priority pending 770 * state in the SES state machine. 771 * 772 * \param enc The SES instance invoking the state machine. 773 */ 774static void 775enc_fsm_step(enc_softc_t *enc) 776{ 777 union ccb *ccb; 778 uint8_t *buf; 779 struct enc_fsm_state *cur_state; 780 int error; 781 uint32_t xfer_len; 782 783 ENC_DLOG(enc, "%s enter %p\n", __func__, enc); 784 785 enc->current_action = ffs(enc->pending_actions) - 1; 786 enc->pending_actions &= ~(0x1 << enc->current_action); 787 788 cur_state = &enc->enc_fsm_states[enc->current_action]; 789 790 buf = NULL; 791 if (cur_state->buf_size != 0) { 792 cam_periph_unlock(enc->periph); 793 buf = malloc(cur_state->buf_size, M_SCSIENC, M_WAITOK|M_ZERO); 794 cam_periph_lock(enc->periph); 795 } 796 797 error = 0; 798 ccb = NULL; 799 if (cur_state->fill != NULL) { 800 ccb = cam_periph_getccb(enc->periph, CAM_PRIORITY_NORMAL); 801 802 error = cur_state->fill(enc, cur_state, ccb, buf); 803 if (error != 0) 804 goto done; 805 806 error = cam_periph_runccb(ccb, cur_state->error, 807 ENC_CFLAGS, 808 ENC_FLAGS|SF_QUIET_IR, NULL); 809 } 810 811 if (ccb != NULL) { 812 if (ccb->ccb_h.func_code == XPT_ATA_IO) 813 xfer_len = ccb->ataio.dxfer_len - ccb->ataio.resid; 814 else 815 xfer_len = ccb->csio.dxfer_len - ccb->csio.resid; 816 } else 817 xfer_len = 0; 818 819 cam_periph_unlock(enc->periph); 820 cur_state->done(enc, cur_state, ccb, &buf, error, xfer_len); 821 cam_periph_lock(enc->periph); 822 823done: 824 ENC_DLOG(enc, "%s exit - result %d\n", __func__, error); 825 ENC_FREE_AND_NULL(buf); 826 if (ccb != NULL) 827 xpt_release_ccb(ccb); 828} 829 830/** 831 * \invariant Called with cam_periph mutex held. 832 */ 833static void 834enc_status_updater(void *arg) 835{ 836 enc_softc_t *enc; 837 838 enc = arg; 839 if (enc->enc_vec.poll_status != NULL) 840 enc->enc_vec.poll_status(enc); 841} 842 843static void 844enc_daemon(void *arg) 845{ 846 enc_softc_t *enc; 847 848 enc = arg; 849 850 cam_periph_lock(enc->periph); 851 while ((enc->enc_flags & ENC_FLAG_SHUTDOWN) == 0) { 852 if (enc->pending_actions == 0) { 853 struct intr_config_hook *hook; 854 855 /* 856 * Reset callout and msleep, or 857 * issue timed task completion 858 * status command. 859 */ 860 enc->current_action = ENC_UPDATE_NONE; 861 862 /* 863 * We've been through our state machine at least 864 * once. Allow the transition to userland. 865 */ 866 hook = &enc->enc_boot_hold_ch; 867 if (hook->ich_func != NULL) { 868 config_intrhook_disestablish(hook); 869 hook->ich_func = NULL; 870 } 871 872 callout_reset(&enc->status_updater, 60*hz, 873 enc_status_updater, enc); 874 875 cam_periph_sleep(enc->periph, enc->enc_daemon, 876 PUSER, "idle", 0); 877 } else { 878 enc_fsm_step(enc); 879 } 880 } 881 enc->enc_daemon = NULL; 882 cam_periph_unlock(enc->periph); 883 cam_periph_release(enc->periph); 884 kproc_exit(0); 885} 886 887static int 888enc_kproc_init(enc_softc_t *enc) 889{ 890 int result; 891 892 callout_init_mtx(&enc->status_updater, enc->periph->sim->mtx, 0); 893 894 if (cam_periph_acquire(enc->periph) != CAM_REQ_CMP) 895 return (ENXIO); 896 897 result = kproc_create(enc_daemon, enc, &enc->enc_daemon, /*flags*/0, 898 /*stackpgs*/0, "enc_daemon%d", 899 enc->periph->unit_number); 900 if (result == 0) { 901 /* Do an initial load of all page data. */ 902 cam_periph_lock(enc->periph); 903 enc->enc_vec.poll_status(enc); 904 cam_periph_unlock(enc->periph); 905 } else 906 cam_periph_release(enc->periph); 907 return (result); 908} 909 910/** 911 * \brief Interrupt configuration hook callback associated with 912 * enc_boot_hold_ch. 913 * 914 * Since interrupts are always functional at the time of enclosure 915 * configuration, there is nothing to be done when the callback occurs. 916 * This hook is only registered to hold up boot processing while initial 917 * eclosure processing occurs. 918 * 919 * \param arg The enclosure softc, but currently unused in this callback. 920 */ 921static void 922enc_nop_confighook_cb(void *arg __unused) 923{ 924} 925 926static cam_status 927enc_ctor(struct cam_periph *periph, void *arg) 928{ 929 cam_status status = CAM_REQ_CMP_ERR; 930 int err; 931 enc_softc_t *enc; 932 struct ccb_getdev *cgd; 933 char *tname; 934 935 cgd = (struct ccb_getdev *)arg; 936 if (cgd == NULL) { 937 printf("enc_ctor: no getdev CCB, can't register device\n"); 938 goto out; 939 } 940 941 enc = ENC_MALLOCZ(sizeof(*enc)); 942 if (enc == NULL) { 943 printf("enc_ctor: Unable to probe new device. " 944 "Unable to allocate enc\n"); 945 goto out; 946 } 947 enc->periph = periph; 948 enc->current_action = ENC_UPDATE_INVALID; 949 950 enc->enc_type = enc_type(cgd); 951 sx_init(&enc->enc_cache_lock, "enccache"); 952 953 switch (enc->enc_type) { 954 case ENC_SES: 955 case ENC_SES_SCSI2: 956 case ENC_SES_PASSTHROUGH: 957 case ENC_SEMB_SES: 958 err = ses_softc_init(enc); 959 break; 960 case ENC_SAFT: 961 case ENC_SEMB_SAFT: 962 err = safte_softc_init(enc); 963 break; 964 case ENC_NONE: 965 default: 966 ENC_FREE(enc); 967 return (CAM_REQ_CMP_ERR); 968 } 969 970 if (err) { 971 xpt_print(periph->path, "error %d initializing\n", err); 972 goto out; 973 } 974 975 /* 976 * Hold off userland until we have made at least one pass 977 * through our state machine so that physical path data is 978 * present. 979 */ 980 if (enc->enc_vec.poll_status != NULL) { 981 enc->enc_boot_hold_ch.ich_func = enc_nop_confighook_cb; 982 enc->enc_boot_hold_ch.ich_arg = enc; 983 config_intrhook_establish(&enc->enc_boot_hold_ch); 984 } 985 986 /* 987 * The softc field is set only once the enc is fully initialized 988 * so that we can rely on this field to detect partially 989 * initialized periph objects in the AC_FOUND_DEVICE handler. 990 */ 991 periph->softc = enc; 992 993 cam_periph_unlock(periph); 994 if (enc->enc_vec.poll_status != NULL) { 995 err = enc_kproc_init(enc); 996 if (err) { 997 xpt_print(periph->path, 998 "error %d starting enc_daemon\n", err); 999 goto out; 1000 } 1001 } 1002
|