37#include <sys/kernel.h>
38#include <sys/kthread.h>
40#include <sys/malloc.h>
46#include <sys/sysent.h>
48#include <sys/sysctl.h>
51#include <machine/stdarg.h>
81SYSCTL_NODE(_kern_cam, OID_AUTO, enc, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
82 "CAM Enclosure Services driver");
84#if defined(DEBUG) || defined(ENC_DEBUG)
89SYSCTL_INT(_kern_cam_enc, OID_AUTO, verbose, CTLFLAG_RWTUN,
97 TAILQ_HEAD_INITIALIZER(
encdriver.units), 0
103 .d_version = D_VERSION,
108 .d_flags = D_TRACKCLOSE,
123 printf(
"enc: Failed to attach master async callback "
124 "due to status 0x%x!\n", status);
239 TAILQ_FOREACH(periph, &
encdriver.units, unit_links) {
267 printf(
"enc_async: Unable to probe new device due to "
268 "status 0x%x\n", status);
279enc_open(
struct cdev *dev,
int flags,
int fmt,
struct thread *td)
313enc_close(
struct cdev *dev,
int flag,
int fmt,
struct thread *td)
353enc_ioctl(
struct cdev *dev, u_long cmd, caddr_t arg_addr,
int flag,
362#ifdef COMPAT_FREEBSD32
363 if (SV_PROC_FLAG(td->td_proc, SV_ILP32))
368 addr = *((caddr_t *) arg_addr);
394 (
"trying to do ioctl %#lx\n", cmd));
417 if ((flag & FWRITE) == 0) {
430 error = copyout(&cache->
nelms, addr, sizeof (cache->
nelms));
436 for (uelm = addr, i = 0; i != cache->
nelms; i++) {
441 error = copyout(&kelm, &uelm[i],
sizeof(kelm));
455 error = copyin(addr, &tmp,
sizeof(tmp));
473 error = copyin(addr, &sstr,
sizeof(sstr));
479 if (error == 0 || error == ENOMEM)
480 (void)copyout(&sstr.
bufsiz,
488 error = copyin(addr, &elms,
sizeof(elms));
500 error = copyout(&elms, addr,
sizeof(elms));
506 error = copyin(addr, &elmd,
sizeof(elmd));
519 error = copyout(&elmd, addr,
sizeof(elmd));
529 error = copyin(addr, &elmdn,
sizeof(elmdn));
541 error = copyout(&elmdn, addr,
sizeof(elmdn));
547 error = copyin(addr, &elms,
sizeof(elms));
581 int error, dlen, tdlen;
586 (
"entering enc_runcmd\n"));
588 if ((dlen = *dlenp) < 0) {
605 tdlen = min(dlen, 1020);
606 tdlen = (tdlen + 3) & ~3;
611 ATA_SEP_ATTN, cdb[2], 0x02, tdlen / 4);
614 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
618 ATA_SEP_ATTN, cdb[2], 0x00, tdlen / 4);
621 ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
642 *dlenp += tdlen - dlen;
647 (
"exiting enc_runcmd: *dlenp = %d\n", *dlenp));
675#define SAFTE_START 44
677#define SAFTE_LEN SAFTE_END-SAFTE_START
687 if (
STRNCMP(iqd + 43,
"S-E-S", 5) == 0)
689 else if (
STRNCMP(iqd + 43,
"SAF-TE", 6) == 0)
703#ifdef SES_ENABLE_PASSTHROUGH
704 if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) {
739 ENC_DLOG(enc,
"%s: queing requested action %d\n",
744 ENC_DLOG(enc,
"%s: ignoring requested action %d - "
745 "Already queued\n", __func__, action);
764 ENC_DLOG(enc,
"%s enter %p\n", __func__, enc);
774 buf = malloc(cur_state->
buf_size, M_SCSIENC, M_WAITOK|M_ZERO);
780 if (cur_state->
fill != NULL) {
801 cur_state->
done(enc, cur_state,
ccb, &buf,
error, xfer_len);
893 struct make_dev_args args;
898 printf(
"enc_ctor: no getdev CCB, can't register device\n");
904 printf(
"enc_ctor: Unable to probe new device. "
905 "Unable to allocate enc\n");
956 "error %d starting enc_daemon\n", err);
968 "registration!\n", __func__);
974 make_dev_args_init(&args);
977 args.mda_uid = UID_ROOT;
978 args.mda_gid = GID_OPERATOR;
979 args.mda_mode = 0600;
980 args.mda_si_drv1 = periph;
1000 tname =
"No ENC device";
1003 tname =
"SES Device";
1006 tname =
"SES Passthrough Device";
1009 tname =
"SAF-TE Device";
1012 tname =
"SEMB SES Device";
1015 tname =
"SEMB SAF-TE Device";
void ata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features, uint32_t lba, uint8_t sector_count)
#define CAM_PRIORITY_NORMAL
static __inline void cam_fill_ataio(struct ccb_ataio *ataio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int tag_action __unused, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t timeout)
static __BEGIN_DECLS __inline void cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int8_t tag_action, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int8_t cdb_len, u_int32_t timeout)
#define CAM_DEBUG(path, flag, printfargs)
void cam_periph_release_locked(struct cam_periph *periph)
int cam_periph_acquire(struct cam_periph *periph)
void cam_periph_async(struct cam_periph *periph, u_int32_t code, struct cam_path *path, void *arg)
void cam_periph_release(struct cam_periph *periph)
int cam_periph_runccb(union ccb *ccb, int(*error_routine)(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags), cam_flags camflags, u_int32_t sense_flags, struct devstat *ds)
int cam_periph_error(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags)
int cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr, int(*error_routine)(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags))
cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, periph_oninv_t *periph_oninvalidate, periph_dtor_t *periph_dtor, periph_start_t *periph_start, char *name, cam_periph_type type, struct cam_path *path, ac_callback_t *ac_callback, ac_code code, void *arg)
cam_status periph_ctor_t(struct cam_periph *periph, void *arg)
void periph_oninv_t(struct cam_periph *periph)
#define cam_periph_lock(periph)
union ccb * cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
#define cam_periph_unlock(periph)
static __inline struct mtx * cam_periph_mtx(struct cam_periph *periph)
void periph_dtor_t(struct cam_periph *periph)
#define cam_periph_sleep(periph, chan, priority, wmesg, timo)
void() periph_init_t(void)
void xpt_unlock_buses(void)
void xpt_print(struct cam_path *path, const char *fmt,...)
path_id_t xpt_path_path_id(struct cam_path *path)
void xpt_lock_buses(void)
cam_status xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg, struct cam_path *path)
void xpt_release_ccb(union ccb *free_ccb)
void xpt_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb, char *announce_string)
#define SID_ADDITIONAL_LENGTH(iqd)
#define RECEIVE_DIAGNOSTIC
int enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp)
static int enc_kproc_init(enc_softc_t *enc)
static d_ioctl_t enc_ioctl
static void enc_async(void *, uint32_t, struct cam_path *, void *)
static periph_oninv_t enc_oninvalidate
static void enc_daemon(void *arg)
static enctyp enc_type(struct ccb_getdev *)
static void enc_status_updater(void *arg)
static void enc_fsm_step(enc_softc_t *enc)
Invoke the handler of the highest priority pending state in the SES state machine.
static void enc_devgonecb(void *arg)
SYSCTL_NODE(_kern_cam, OID_AUTO, enc, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "CAM Enclosure Services driver")
static d_close_t enc_close
static struct cdevsw enc_cdevsw
const char * elm_type_names[]
CTASSERT(nitems(elm_type_names) - 1==ELMTYP_LAST)
void enc_update_request(enc_softc_t *enc, uint32_t action)
Queue an update request for a given action, if needed.
PERIPHDRIVER_DECLARE(enc, encdriver)
void enc_log(struct enc_softc *enc, const char *fmt,...)
SYSCTL_INT(_kern_cam_enc, OID_AUTO, verbose, CTLFLAG_RWTUN, &enc_verbose, 0, "Enable verbose logging")
int enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags)
static struct periph_driver encdriver
MALLOC_DEFINE(M_SCSIENC, "SCSI ENC", "SCSI ENC buffers")
static periph_init_t enc_init
static periph_ctor_t enc_ctor
static periph_dtor_t enc_dtor
#define ENCIOC_SETENCSTAT
#define ENCIOC_GETELMDESC
unsigned char encioc_enc_status_t
#define ENCIOC_GETENCNAME
#define ENCIOC_GETENCSTAT
#define ENCIOC_GETELMSTAT
#define ENCIOC_SETELMSTAT
#define ENCIOC_GETELMDEVNAMES
#define ENC_FLAG_SHUTDOWN
enc_softc_init_t ses_softc_init
#define ENC_FLAG_INITIALIZED
enc_softc_init_t safte_softc_init
#define ENC_UPDATE_INVALID
#define ENC_FREE_AND_NULL(ptr)
struct ata_params ident_data
struct scsi_inquiry_data inq_data
encioc_enc_status_t enc_status
fsm_fill_handler_t * fill
fsm_error_handler_t * error
fsm_done_handler_t * done
struct root_hold_token enc_rootmount
struct callout status_updater
struct cam_periph * periph
char announce_buf[ENC_ANNOUNCE_SZ]
struct enc_fsm_state * enc_fsm_states
enc_softc_invalidate_t * softc_invalidate
enc_handle_string_t * handle_string
enc_init_enc_t * init_enc
enc_poll_status_t * poll_status
enc_get_elm_devnames_t * get_elm_devnames
enc_get_elm_desc_t * get_elm_desc
enc_get_elm_status_t * get_elm_status
enc_softc_cleanup_t * softc_cleanup
enc_set_elm_status_t * set_elm_status
enc_set_enc_status_t * set_enc_status
enc_device_found_t * device_found
unsigned int elm_subenc_id
u_int8_t cdb_bytes[IOCDBLEN]