diff options
Diffstat (limited to 'sys/cam/cam_compat.c')
-rw-r--r-- | sys/cam/cam_compat.c | 129 |
1 files changed, 122 insertions, 7 deletions
diff --git a/sys/cam/cam_compat.c b/sys/cam/cam_compat.c index a24debc..f291479 100644 --- a/sys/cam/cam_compat.c +++ b/sys/cam/cam_compat.c @@ -44,23 +44,28 @@ __FBSDID("$FreeBSD$"); #include <cam/cam.h> #include <cam/cam_ccb.h> +#include <cam/cam_xpt.h> #include <cam/cam_compat.h> #include <cam/scsi/scsi_pass.h> #include "opt_cam.h" +static int cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, + int flag, struct thread *td, d_ioctl_t *cbfnp); + int -cam_compat_ioctl(struct cdev *dev, u_long *cmd, caddr_t *addr, int *flag, struct thread *td) +cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, + struct thread *td, d_ioctl_t *cbfnp) { int error; - switch (*cmd) { + switch (cmd) { case CAMIOCOMMAND_0x16: { union ccb *ccb; - ccb = (union ccb *)*addr; + ccb = (union ccb *)addr; if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS_0x16) { ccb->ccb_h.flags &= ~CAM_SG_LIST_PHYS_0x16; ccb->ccb_h.flags |= CAM_DATA_SG_PADDR; @@ -73,13 +78,21 @@ cam_compat_ioctl(struct cdev *dev, u_long *cmd, caddr_t *addr, int *flag, struct ccb->ccb_h.flags &= CAM_SCATTER_VALID_0x16; ccb->ccb_h.flags |= CAM_DATA_SG; } - *cmd = CAMIOCOMMAND; - error = EAGAIN; + cmd = CAMIOCOMMAND; + error = (cbfnp)(dev, cmd, addr, flag, td); break; } case CAMGETPASSTHRU_0x16: - *cmd = CAMGETPASSTHRU; - error = EAGAIN; + cmd = CAMGETPASSTHRU; + error = (cbfnp)(dev, cmd, addr, flag, td); + break; + case CAMIOCOMMAND_0x17: + cmd = CAMIOCOMMAND; + error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); + break; + case CAMGETPASSTHRU_0x17: + cmd = CAMGETPASSTHRU; + error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); break; default: error = ENOTTY; @@ -87,3 +100,105 @@ cam_compat_ioctl(struct cdev *dev, u_long *cmd, caddr_t *addr, int *flag, struct return (error); } + +static int +cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, + struct thread *td, d_ioctl_t *cbfnp) +{ + union ccb *ccb; + struct ccb_hdr *hdr; + struct ccb_hdr_0x17 *hdr17; + uint8_t *ccbb, *ccbb17; + u_int error; + + hdr17 = (struct ccb_hdr_0x17 *)addr; + ccb = xpt_alloc_ccb(); + hdr = &ccb->ccb_h; + + hdr->pinfo = hdr17->pinfo; + hdr->xpt_links = hdr17->xpt_links; + hdr->sim_links = hdr17->sim_links; + hdr->periph_links = hdr17->periph_links; + hdr->retry_count = hdr17->retry_count; + hdr->cbfcnp = hdr17->cbfcnp; + hdr->func_code = hdr17->func_code; + hdr->status = hdr17->status; + hdr->path = hdr17->path; + hdr->path_id = hdr17->path_id; + hdr->target_id = hdr17->target_id; + hdr->target_lun = hdr17->target_lun; + hdr->ext_lun.lun64 = 0; + hdr->flags = hdr17->flags; + hdr->xflags = 0; + hdr->periph_priv = hdr17->periph_priv; + hdr->sim_priv = hdr17->sim_priv; + hdr->timeout = hdr17->timeout; + hdr->softtimeout.tv_sec = 0; + hdr->softtimeout.tv_usec = 0; + + ccbb = (uint8_t *)&hdr[1]; + ccbb17 = (uint8_t *)&hdr17[1]; + bcopy(ccbb17, ccbb, CAM_0X17_DATA_LEN); + + error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td); + + hdr17->pinfo = hdr->pinfo; + hdr17->xpt_links = hdr->xpt_links; + hdr17->sim_links = hdr->sim_links; + hdr17->periph_links = hdr->periph_links; + hdr17->retry_count = hdr->retry_count; + hdr17->cbfcnp = hdr->cbfcnp; + hdr17->func_code = hdr->func_code; + hdr17->status = hdr->status; + hdr17->path = hdr->path; + hdr17->path_id = hdr->path_id; + hdr17->target_id = hdr->target_id; + hdr17->target_lun = hdr->target_lun; + hdr17->flags = hdr->flags; + hdr17->periph_priv = hdr->periph_priv; + hdr17->sim_priv = hdr->sim_priv; + hdr17->timeout = hdr->timeout; + + /* The PATH_INQ only needs special handling on the way out */ + if (ccb->ccb_h.func_code != XPT_PATH_INQ) { + bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN); + } else { + struct ccb_pathinq *cpi; + struct ccb_pathinq_0x17 *cpi17; + + cpi = &ccb->cpi; + cpi17 = (struct ccb_pathinq_0x17 *)hdr17; + cpi17->version_num = cpi->version_num; + cpi17->hba_inquiry = cpi->hba_inquiry; + cpi17->target_sprt = (u_int8_t)cpi->target_sprt; + cpi17->hba_misc = (u_int8_t)cpi->hba_misc; + cpi17->hba_eng_cnt = cpi->hba_eng_cnt; + bcopy(&cpi->vuhba_flags[0], &cpi17->vuhba_flags[0], VUHBALEN); + cpi17->max_target = cpi->max_target; + cpi17->max_lun = cpi->max_lun; + cpi17->async_flags = cpi->async_flags; + cpi17->hpath_id = cpi->hpath_id; + cpi17->initiator_id = cpi->initiator_id; + bcopy(&cpi->sim_vid[0], &cpi17->sim_vid[0], SIM_IDLEN); + bcopy(&cpi->hba_vid[0], &cpi17->hba_vid[0], HBA_IDLEN); + bcopy(&cpi->dev_name[0], &cpi17->dev_name[0], DEV_IDLEN); + cpi17->unit_number = cpi->unit_number; + cpi17->bus_id = cpi->bus_id; + cpi17->base_transfer_speed = cpi->base_transfer_speed; + cpi17->protocol = cpi->protocol; + cpi17->protocol_version = cpi->protocol_version; + cpi17->transport = cpi->transport; + cpi17->transport_version = cpi->transport_version; + bcopy(&cpi->xport_specific, &cpi17->xport_specific, + PATHINQ_SETTINGS_SIZE); + cpi17->maxio = cpi->maxio; + cpi17->hba_vendor = cpi->hba_vendor; + cpi17->hba_device = cpi->hba_device; + cpi17->hba_subvendor = cpi->hba_subvendor; + cpi17->hba_subdevice = cpi->hba_subdevice; + } + + xpt_free_ccb(ccb); + + return (error); +} |