2 * Copyright (c) 2000 Matthew Jacob
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
33 #include <sys/errno.h>
34 #include <sys/fcntl.h>
35 #include <sys/kernel.h>
36 #include <sys/kthread.h>
38 #include <sys/malloc.h>
39 #include <sys/mutex.h>
40 #include <sys/queue.h>
42 #include <sys/systm.h>
43 #include <sys/sysctl.h>
44 #include <sys/types.h>
46 #include <machine/stdarg.h>
49 #include <cam/cam_ccb.h>
50 #include <cam/cam_debug.h>
51 #include <cam/cam_periph.h>
52 #include <cam/cam_xpt_periph.h>
54 #include <cam/scsi/scsi_all.h>
55 #include <cam/scsi/scsi_message.h>
56 #include <cam/scsi/scsi_enc.h>
57 #include <cam/scsi/scsi_enc_internal.h>
61 MALLOC_DEFINE(M_SCSIENC, "SCSI ENC", "SCSI ENC buffers");
63 /* Enclosure type independent driver */
65 static d_open_t enc_open;
66 static d_close_t enc_close;
67 static d_ioctl_t enc_ioctl;
68 static periph_init_t enc_init;
69 static periph_ctor_t enc_ctor;
70 static periph_oninv_t enc_oninvalidate;
71 static periph_dtor_t enc_dtor;
72 static periph_start_t enc_start;
74 static void enc_async(void *, uint32_t, struct cam_path *, void *);
75 static enctyp enc_type(struct ccb_getdev *);
77 SYSCTL_NODE(_kern_cam, OID_AUTO, enc, CTLFLAG_RD, 0,
78 "CAM Enclosure Services driver");
80 static struct periph_driver encdriver = {
82 TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
85 PERIPHDRIVER_DECLARE(enc, encdriver);
87 static struct cdevsw enc_cdevsw = {
88 .d_version = D_VERSION,
93 .d_flags = D_TRACKCLOSE,
102 * Install a global async callback. This callback will
103 * receive async callbacks like "new device found".
105 status = xpt_register_async(AC_FOUND_DEVICE, enc_async, NULL, NULL);
107 if (status != CAM_REQ_CMP) {
108 printf("enc: Failed to attach master async callback "
109 "due to status 0x%x!\n", status);
114 enc_devgonecb(void *arg)
117 struct cam_periph *periph;
118 struct enc_softc *enc;
121 periph = (struct cam_periph *)arg;
123 enc = (struct enc_softc *)periph->softc;
128 * When we get this callback, we will get no more close calls from
129 * devfs. So if we have any dangling opens, we need to release the
130 * reference held for that particular context.
132 for (i = 0; i < enc->open_count; i++)
133 cam_periph_release_locked(periph);
138 * Release the reference held for the device node, it is gone now.
140 cam_periph_release_locked(periph);
143 * We reference the SIM lock directly here, instead of using
144 * cam_periph_unlock(). The reason is that the final call to
145 * cam_periph_release_locked() above could result in the periph
146 * getting freed. If that is the case, dereferencing the periph
147 * with a cam_periph_unlock() call would cause a page fault.
149 mtx_unlock(sim->mtx);
153 enc_oninvalidate(struct cam_periph *periph)
155 struct enc_softc *enc;
159 enc->enc_flags |= ENC_FLAG_INVALID;
161 /* If the sub-driver has an invalidate routine, call it */
162 if (enc->enc_vec.softc_invalidate != NULL)
163 enc->enc_vec.softc_invalidate(enc);
166 * Unregister any async callbacks.
168 xpt_register_async(0, enc_async, periph, periph->path);
171 * Shutdown our daemon.
173 enc->enc_flags |= ENC_FLAG_SHUTDOWN;
174 if (enc->enc_daemon != NULL) {
175 /* Signal the ses daemon to terminate. */
176 wakeup(enc->enc_daemon);
178 callout_drain(&enc->status_updater);
180 destroy_dev_sched_cb(enc->enc_dev, enc_devgonecb, periph);
184 enc_dtor(struct cam_periph *periph)
186 struct enc_softc *enc;
190 /* If the sub-driver has a cleanup routine, call it */
191 if (enc->enc_vec.softc_cleanup != NULL)
192 enc->enc_vec.softc_cleanup(enc);
194 if (enc->enc_boot_hold_ch.ich_func != NULL) {
195 config_intrhook_disestablish(&enc->enc_boot_hold_ch);
196 enc->enc_boot_hold_ch.ich_func = NULL;
203 enc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
205 struct cam_periph *periph;
207 periph = (struct cam_periph *)callback_arg;
210 case AC_FOUND_DEVICE:
212 struct ccb_getdev *cgd;
216 cgd = (struct ccb_getdev *)arg;
221 if (enc_type(cgd) == ENC_NONE) {
223 * Schedule announcement of the ENC bindings for
224 * this device if it is managed by a SEP.
226 path_id = xpt_path_path_id(path);
228 TAILQ_FOREACH(periph, &encdriver.units, unit_links) {
229 struct enc_softc *softc;
231 softc = (struct enc_softc *)periph->softc;
232 if (xpt_path_path_id(periph->path) != path_id
234 || (softc->enc_flags & ENC_FLAG_INITIALIZED)
236 || softc->enc_vec.device_found == NULL)
239 softc->enc_vec.device_found(softc);
245 status = cam_periph_alloc(enc_ctor, enc_oninvalidate,
246 enc_dtor, enc_start, "ses", CAM_PERIPH_BIO,
247 cgd->ccb_h.path, enc_async, AC_FOUND_DEVICE, cgd);
249 if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) {
250 printf("enc_async: Unable to probe new device due to "
251 "status 0x%x\n", status);
256 cam_periph_async(periph, code, path, arg);
262 enc_open(struct cdev *dev, int flags, int fmt, struct thread *td)
264 struct cam_periph *periph;
265 struct enc_softc *softc;
268 periph = (struct cam_periph *)dev->si_drv1;
269 if (periph == NULL) {
273 if (cam_periph_acquire(periph) != CAM_REQ_CMP)
276 cam_periph_lock(periph);
278 softc = (struct enc_softc *)periph->softc;
280 if ((softc->enc_flags & ENC_FLAG_INITIALIZED) == 0) {
284 if (softc->enc_flags & ENC_FLAG_INVALID) {
290 cam_periph_release_locked(periph);
294 cam_periph_unlock(periph);
300 enc_close(struct cdev *dev, int flag, int fmt, struct thread *td)
303 struct cam_periph *periph;
304 struct enc_softc *enc;
306 periph = (struct cam_periph *)dev->si_drv1;
317 cam_periph_release_locked(periph);
320 * We reference the SIM lock directly here, instead of using
321 * cam_periph_unlock(). The reason is that the call to
322 * cam_periph_release_locked() above could result in the periph
323 * getting freed. If that is the case, dereferencing the periph
324 * with a cam_periph_unlock() call would cause a page fault.
326 * cam_periph_release() avoids this problem using the same method,
327 * but we're manually acquiring and dropping the lock here to
328 * protect the open count and avoid another lock acquisition and
331 mtx_unlock(sim->mtx);
337 enc_start(struct cam_periph *p, union ccb *sccb)
339 struct enc_softc *enc;
342 ENC_DLOG(enc, "%s enter imm=%d prio=%d\n",
343 __func__, p->immediate_priority, p->pinfo.priority);
344 if (p->immediate_priority <= p->pinfo.priority) {
345 SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle);
346 p->immediate_priority = CAM_PRIORITY_NONE;
347 wakeup(&p->ccb_list);
349 xpt_release_ccb(sccb);
350 ENC_DLOG(enc, "%s exit\n", __func__);
354 enc_done(struct cam_periph *periph, union ccb *dccb)
356 wakeup(&dccb->ccb_h.cbfcnp);
360 enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags)
362 struct enc_softc *softc;
363 struct cam_periph *periph;
365 periph = xpt_path_periph(ccb->ccb_h.path);
366 softc = (struct enc_softc *)periph->softc;
368 return (cam_periph_error(ccb, cflags, sflags, &softc->saved_ccb));
372 enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
375 struct cam_periph *periph;
376 encioc_enc_status_t tmp;
377 encioc_string_t sstr;
378 encioc_elm_status_t elms;
379 encioc_elm_desc_t elmd;
380 encioc_elm_devnames_t elmdn;
381 encioc_element_t *uelm;
389 addr = *((caddr_t *) arg_addr);
393 periph = (struct cam_periph *)dev->si_drv1;
397 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering encioctl\n"));
399 cam_periph_lock(periph);
400 enc = (struct enc_softc *)periph->softc;
401 cache = &enc->enc_cache;
404 * Now check to see whether we're initialized or not.
405 * This actually should never fail as we're not supposed
406 * to get past enc_open w/o successfully initializing
409 if ((enc->enc_flags & ENC_FLAG_INITIALIZED) == 0) {
410 cam_periph_unlock(periph);
413 cam_periph_unlock(periph);
417 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
418 ("trying to do ioctl %#lx\n", cmd));
421 * If this command can change the device's state,
422 * we must have the device open for writing.
424 * For commands that get information about the
425 * device- we don't need to lock the peripheral
426 * if we aren't running a command. The periph
427 * also can't go away while a user process has
432 case ENCIOC_GETELMMAP:
433 case ENCIOC_GETENCSTAT:
434 case ENCIOC_GETELMSTAT:
435 case ENCIOC_GETELMDESC:
436 case ENCIOC_GETELMDEVNAMES:
439 if ((flag & FWRITE) == 0) {
445 * XXX The values read here are only valid for the current
446 * configuration generation. We need these ioctls
447 * to also pass in/out a generation number.
449 sx_slock(&enc->enc_cache_lock);
452 error = copyout(&cache->nelms, addr, sizeof (cache->nelms));
455 case ENCIOC_GETELMMAP:
456 for (uelm = addr, i = 0; i != cache->nelms; i++) {
457 encioc_element_t kelm;
459 kelm.elm_subenc_id = cache->elm_map[i].subenclosure;
460 kelm.elm_type = cache->elm_map[i].enctype;
461 error = copyout(&kelm, &uelm[i], sizeof(kelm));
467 case ENCIOC_GETENCSTAT:
468 cam_periph_lock(periph);
469 error = enc->enc_vec.get_enc_status(enc, 1);
471 cam_periph_unlock(periph);
474 tmp = cache->enc_status;
475 cam_periph_unlock(periph);
476 error = copyout(&tmp, addr, sizeof(tmp));
477 cache->enc_status = tmp;
480 case ENCIOC_SETENCSTAT:
481 error = copyin(addr, &tmp, sizeof(tmp));
484 cam_periph_lock(periph);
485 error = enc->enc_vec.set_enc_status(enc, tmp, 1);
486 cam_periph_unlock(periph);
489 case ENCIOC_GETSTRING:
490 case ENCIOC_SETSTRING:
491 if (enc->enc_vec.handle_string == NULL) {
495 error = copyin(addr, &sstr, sizeof(sstr));
498 cam_periph_lock(periph);
499 error = enc->enc_vec.handle_string(enc, &sstr, cmd);
500 cam_periph_unlock(periph);
503 case ENCIOC_GETELMSTAT:
504 error = copyin(addr, &elms, sizeof(elms));
507 if (elms.elm_idx >= cache->nelms) {
511 cam_periph_lock(periph);
512 error = enc->enc_vec.get_elm_status(enc, &elms, 1);
513 cam_periph_unlock(periph);
516 error = copyout(&elms, addr, sizeof(elms));
519 case ENCIOC_GETELMDESC:
520 error = copyin(addr, &elmd, sizeof(elmd));
523 if (elmd.elm_idx >= cache->nelms) {
527 if (enc->enc_vec.get_elm_desc != NULL) {
528 error = enc->enc_vec.get_elm_desc(enc, &elmd);
532 elmd.elm_desc_len = 0;
533 error = copyout(&elmd, addr, sizeof(elmd));
536 case ENCIOC_GETELMDEVNAMES:
537 if (enc->enc_vec.get_elm_devnames == NULL) {
541 error = copyin(addr, &elmdn, sizeof(elmdn));
544 if (elmdn.elm_idx >= cache->nelms) {
548 cam_periph_lock(periph);
549 error = (*enc->enc_vec.get_elm_devnames)(enc, &elmdn);
550 cam_periph_unlock(periph);
553 error = copyout(&elmdn, addr, sizeof(elmdn));
556 case ENCIOC_SETELMSTAT:
557 error = copyin(addr, &elms, sizeof(elms));
561 if (elms.elm_idx >= cache->nelms) {
565 cam_periph_lock(periph);
566 error = enc->enc_vec.set_elm_status(enc, &elms, 1);
567 cam_periph_unlock(periph);
573 cam_periph_lock(periph);
574 error = enc->enc_vec.init_enc(enc);
575 cam_periph_unlock(periph);
579 cam_periph_lock(periph);
580 error = cam_periph_ioctl(periph, cmd, arg_addr, enc_error);
581 cam_periph_unlock(periph);
584 sx_sunlock(&enc->enc_cache_lock);
589 enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp)
591 int error, dlen, tdlen;
595 CAM_DEBUG(enc->periph->path, CAM_DEBUG_TRACE,
596 ("entering enc_runcmd\n"));
598 if ((dlen = *dlenp) < 0) {
609 if (cdbl > IOCDBLEN) {
613 ccb = cam_periph_getccb(enc->periph, CAM_PRIORITY_NORMAL);
614 if (enc->enc_type == ENC_SEMB_SES || enc->enc_type == ENC_SEMB_SAFT) {
615 tdlen = min(dlen, 1020);
616 tdlen = (tdlen + 3) & ~3;
617 cam_fill_ataio(&ccb->ataio, 0, enc_done, ddf, 0, dptr, tdlen,
619 if (cdb[0] == RECEIVE_DIAGNOSTIC)
620 ata_28bit_cmd(&ccb->ataio,
621 ATA_SEP_ATTN, cdb[2], 0x02, tdlen / 4);
622 else if (cdb[0] == SEND_DIAGNOSTIC)
623 ata_28bit_cmd(&ccb->ataio,
624 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
626 else if (cdb[0] == READ_BUFFER)
627 ata_28bit_cmd(&ccb->ataio,
628 ATA_SEP_ATTN, cdb[2], 0x00, tdlen / 4);
630 ata_28bit_cmd(&ccb->ataio,
631 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
635 cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG,
636 dptr, dlen, sizeof (struct scsi_sense_data), cdbl,
638 bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl);
641 error = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL);
648 if (ccb->ccb_h.func_code == XPT_ATA_IO)
649 *dlenp = ccb->ataio.resid;
651 *dlenp = ccb->csio.resid;
652 *dlenp += tdlen - dlen;
655 xpt_release_ccb(ccb);
656 CAM_DEBUG(enc->periph->path, CAM_DEBUG_SUBTRACE,
657 ("exiting enc_runcmd: *dlenp = %d\n", *dlenp));
662 enc_log(struct enc_softc *enc, const char *fmt, ...)
666 printf("%s%d: ", enc->periph->periph_name, enc->periph->unit_number);
673 * The code after this point runs on many platforms,
674 * so forgive the slightly awkward and nonconforming
679 * Is this a device that supports enclosure services?
681 * It's a pretty simple ruleset- if it is device type
682 * 0x0D (13), it's an ENCLOSURE device.
685 #define SAFTE_START 44
687 #define SAFTE_LEN SAFTE_END-SAFTE_START
690 enc_type(struct ccb_getdev *cgd)
695 if (cgd->protocol == PROTO_SEMB) {
696 iqd = (unsigned char *)&cgd->ident_data;
697 if (STRNCMP(iqd + 43, "S-E-S", 5) == 0)
698 return (ENC_SEMB_SES);
699 else if (STRNCMP(iqd + 43, "SAF-TE", 6) == 0)
700 return (ENC_SEMB_SAFT);
703 } else if (cgd->protocol != PROTO_SCSI)
706 iqd = (unsigned char *)&cgd->inq_data;
707 buflen = min(sizeof(cgd->inq_data),
708 SID_ADDITIONAL_LENGTH(&cgd->inq_data));
710 if ((iqd[0] & 0x1f) == T_ENCLOSURE) {
711 if ((iqd[2] & 0x7) > 2) {
714 return (ENC_SES_SCSI2);
719 #ifdef SES_ENABLE_PASSTHROUGH
720 if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) {
722 * PassThrough Device.
724 return (ENC_SES_PASSTHROUGH);
729 * The comparison is short for a reason-
730 * some vendors were chopping it short.
733 if (buflen < SAFTE_END - 2) {
737 if (STRNCMP((char *)&iqd[SAFTE_START], "SAF-TE", SAFTE_LEN - 2) == 0) {
743 /*================== Enclosure Monitoring/Processing Daemon ==================*/
745 * \brief Queue an update request for a given action, if needed.
747 * \param enc SES softc to queue the request for.
748 * \param action Action requested.
751 enc_update_request(enc_softc_t *enc, uint32_t action)
753 if ((enc->pending_actions & (0x1 << action)) == 0) {
754 enc->pending_actions |= (0x1 << action);
755 ENC_DLOG(enc, "%s: queing requested action %d\n",
757 if (enc->current_action == ENC_UPDATE_NONE)
758 wakeup(enc->enc_daemon);
760 ENC_DLOG(enc, "%s: ignoring requested action %d - "
761 "Already queued\n", __func__, action);
766 * \brief Invoke the handler of the highest priority pending
767 * state in the SES state machine.
769 * \param enc The SES instance invoking the state machine.
772 enc_fsm_step(enc_softc_t *enc)
776 struct enc_fsm_state *cur_state;
780 ENC_DLOG(enc, "%s enter %p\n", __func__, enc);
782 enc->current_action = ffs(enc->pending_actions) - 1;
783 enc->pending_actions &= ~(0x1 << enc->current_action);
785 cur_state = &enc->enc_fsm_states[enc->current_action];
788 if (cur_state->buf_size != 0) {
789 cam_periph_unlock(enc->periph);
790 buf = malloc(cur_state->buf_size, M_SCSIENC, M_WAITOK|M_ZERO);
791 cam_periph_lock(enc->periph);
796 if (cur_state->fill != NULL) {
797 ccb = cam_periph_getccb(enc->periph, CAM_PRIORITY_NORMAL);
799 error = cur_state->fill(enc, cur_state, ccb, buf);
803 error = cam_periph_runccb(ccb, cur_state->error,
805 ENC_FLAGS|SF_QUIET_IR, NULL);
809 if (ccb->ccb_h.func_code == XPT_ATA_IO)
810 xfer_len = ccb->ataio.dxfer_len - ccb->ataio.resid;
812 xfer_len = ccb->csio.dxfer_len - ccb->csio.resid;
816 cam_periph_unlock(enc->periph);
817 cur_state->done(enc, cur_state, ccb, &buf, error, xfer_len);
818 cam_periph_lock(enc->periph);
821 ENC_DLOG(enc, "%s exit - result %d\n", __func__, error);
822 ENC_FREE_AND_NULL(buf);
824 xpt_release_ccb(ccb);
828 * \invariant Called with cam_periph mutex held.
831 enc_status_updater(void *arg)
836 if (enc->enc_vec.poll_status != NULL)
837 enc->enc_vec.poll_status(enc);
841 enc_daemon(void *arg)
847 cam_periph_lock(enc->periph);
848 while ((enc->enc_flags & ENC_FLAG_SHUTDOWN) == 0) {
849 if (enc->pending_actions == 0) {
850 struct intr_config_hook *hook;
853 * Reset callout and msleep, or
854 * issue timed task completion
857 enc->current_action = ENC_UPDATE_NONE;
860 * We've been through our state machine at least
861 * once. Allow the transition to userland.
863 hook = &enc->enc_boot_hold_ch;
864 if (hook->ich_func != NULL) {
865 config_intrhook_disestablish(hook);
866 hook->ich_func = NULL;
869 callout_reset(&enc->status_updater, 60*hz,
870 enc_status_updater, enc);
872 cam_periph_sleep(enc->periph, enc->enc_daemon,
878 enc->enc_daemon = NULL;
879 cam_periph_unlock(enc->periph);
880 cam_periph_release(enc->periph);
885 enc_kproc_init(enc_softc_t *enc)
889 callout_init_mtx(&enc->status_updater, enc->periph->sim->mtx, 0);
891 if (cam_periph_acquire(enc->periph) != CAM_REQ_CMP)
894 result = kproc_create(enc_daemon, enc, &enc->enc_daemon, /*flags*/0,
895 /*stackpgs*/0, "enc_daemon%d",
896 enc->periph->unit_number);
898 /* Do an initial load of all page data. */
899 cam_periph_lock(enc->periph);
900 enc->enc_vec.poll_status(enc);
901 cam_periph_unlock(enc->periph);
903 cam_periph_release(enc->periph);
908 * \brief Interrupt configuration hook callback associated with
911 * Since interrupts are always functional at the time of enclosure
912 * configuration, there is nothing to be done when the callback occurs.
913 * This hook is only registered to hold up boot processing while initial
914 * eclosure processing occurs.
916 * \param arg The enclosure softc, but currently unused in this callback.
919 enc_nop_confighook_cb(void *arg __unused)
924 enc_ctor(struct cam_periph *periph, void *arg)
926 cam_status status = CAM_REQ_CMP_ERR;
929 struct ccb_getdev *cgd;
932 cgd = (struct ccb_getdev *)arg;
934 printf("enc_ctor: no getdev CCB, can't register device\n");
938 enc = ENC_MALLOCZ(sizeof(*enc));
940 printf("enc_ctor: Unable to probe new device. "
941 "Unable to allocate enc\n");
944 enc->periph = periph;
945 enc->current_action = ENC_UPDATE_INVALID;
947 enc->enc_type = enc_type(cgd);
948 sx_init(&enc->enc_cache_lock, "enccache");
950 switch (enc->enc_type) {
953 case ENC_SES_PASSTHROUGH:
955 err = ses_softc_init(enc);
959 err = safte_softc_init(enc);
964 return (CAM_REQ_CMP_ERR);
968 xpt_print(periph->path, "error %d initializing\n", err);
973 * Hold off userland until we have made at least one pass
974 * through our state machine so that physical path data is
977 if (enc->enc_vec.poll_status != NULL) {
978 enc->enc_boot_hold_ch.ich_func = enc_nop_confighook_cb;
979 enc->enc_boot_hold_ch.ich_arg = enc;
980 config_intrhook_establish(&enc->enc_boot_hold_ch);
984 * The softc field is set only once the enc is fully initialized
985 * so that we can rely on this field to detect partially
986 * initialized periph objects in the AC_FOUND_DEVICE handler.
990 cam_periph_unlock(periph);
991 if (enc->enc_vec.poll_status != NULL) {
992 err = enc_kproc_init(enc);
994 xpt_print(periph->path,
995 "error %d starting enc_daemon\n", err);
1001 * Acquire a reference to the periph before we create the devfs
1002 * instance for it. We'll release this reference once the devfs
1003 * instance has been freed.
1005 if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
1006 xpt_print(periph->path, "%s: lost periph during "
1007 "registration!\n", __func__);
1008 cam_periph_lock(periph);
1010 return (CAM_REQ_CMP_ERR);
1013 enc->enc_dev = make_dev(&enc_cdevsw, periph->unit_number,
1014 UID_ROOT, GID_OPERATOR, 0600, "%s%d",
1015 periph->periph_name, periph->unit_number);
1017 cam_periph_lock(periph);
1018 enc->enc_dev->si_drv1 = periph;
1020 enc->enc_flags |= ENC_FLAG_INITIALIZED;
1023 * Add an async callback so that we get notified if this
1026 xpt_register_async(AC_LOST_DEVICE, enc_async, periph, periph->path);
1028 switch (enc->enc_type) {
1031 tname = "No ENC device";
1034 tname = "SCSI-2 ENC Device";
1037 tname = "SCSI-3 ENC Device";
1039 case ENC_SES_PASSTHROUGH:
1040 tname = "ENC Passthrough Device";
1043 tname = "SAF-TE Compliant Device";
1046 tname = "SEMB SES Device";
1049 tname = "SEMB SAF-TE Device";
1052 xpt_announce_periph(periph, tname);
1053 status = CAM_REQ_CMP;
1056 if (status != CAM_REQ_CMP)