diff --git a/sys/cam/cam_compat.c b/sys/cam/cam_compat.c index b8e57bb7e6b8..b3d861931568 100644 --- a/sys/cam/cam_compat.c +++ b/sys/cam/cam_compat.c @@ -149,7 +149,24 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, ccbb = (uint8_t *)&hdr[1]; ccbb17 = (uint8_t *)&hdr17[1]; - bcopy(ccbb17, ccbb, CAM_0X17_DATA_LEN); + if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) { + struct ccb_trans_settings *cts; + struct ccb_trans_settings_0x17 *cts17; + + cts = &ccb->cts; + cts17 = (struct ccb_trans_settings_0x17 *)hdr17; + cts->type = cts17->type; + cts->protocol = cts17->protocol; + cts->protocol_version = cts17->protocol_version; + cts->transport = cts17->transport; + cts->transport_version = cts17->transport_version; + bcopy(&cts17->proto_specific, &cts->proto_specific, + sizeof(cts17->proto_specific)); + bcopy(&cts17->xport_specific, &cts->xport_specific, + sizeof(cts17->xport_specific)); + } else { + bcopy(ccbb17, ccbb, CAM_0X17_DATA_LEN); + } error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td); @@ -205,6 +222,21 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, cpi17->hba_device = cpi->hba_device; cpi17->hba_subvendor = cpi->hba_subvendor; cpi17->hba_subdevice = cpi->hba_subdevice; + } else if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) { + struct ccb_trans_settings *cts; + struct ccb_trans_settings_0x17 *cts17; + + cts = &ccb->cts; + cts17 = (struct ccb_trans_settings_0x17 *)hdr17; + cts17->type = cts17->type; + cts17->protocol = cts->protocol; + cts17->protocol_version = cts->protocol_version; + cts17->transport = cts->transport; + cts17->transport_version = cts->transport_version; + bcopy(&cts->proto_specific, &cts17->proto_specific, + sizeof(cts17->proto_specific)); + bcopy(&cts->xport_specific, &cts17->xport_specific, + sizeof(cts17->xport_specific)); } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) { /* Copy the rest of the header over */ bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN); @@ -257,7 +289,24 @@ cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag, ccbb = (uint8_t *)&hdr[1]; ccbb18 = (uint8_t *)&hdr18[1]; - bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN); + if (ccb->ccb_h.func_code == XPT_SET_TRAN_SETTINGS) { + struct ccb_trans_settings *cts; + struct ccb_trans_settings_0x18 *cts18; + + cts = &ccb->cts; + cts18 = (struct ccb_trans_settings_0x18 *)hdr18; + cts->type = cts18->type; + cts->protocol = cts18->protocol; + cts->protocol_version = cts18->protocol_version; + cts->transport = cts18->transport; + cts->transport_version = cts18->transport_version; + bcopy(&cts18->proto_specific, &cts->proto_specific, + sizeof(cts18->proto_specific)); + bcopy(&cts18->xport_specific, &cts->xport_specific, + sizeof(cts18->xport_specific)); + } else { + bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN); + } error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td); @@ -280,10 +329,27 @@ cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag, hdr18->sim_priv = hdr->sim_priv; hdr18->timeout = hdr->timeout; - bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN); + if (ccb->ccb_h.func_code == XPT_GET_TRAN_SETTINGS) { + struct ccb_trans_settings *cts; + struct ccb_trans_settings_0x18 *cts18; - if (ccb->ccb_h.func_code == XPT_DEV_MATCH) + cts = &ccb->cts; + cts18 = (struct ccb_trans_settings_0x18 *)hdr18; + cts18->type = cts18->type; + cts18->protocol = cts->protocol; + cts18->protocol_version = cts->protocol_version; + cts18->transport = cts->transport; + cts18->transport_version = cts->transport_version; + bcopy(&cts->proto_specific, &cts18->proto_specific, + sizeof(cts18->proto_specific)); + bcopy(&cts->xport_specific, &cts18->xport_specific, + sizeof(cts18->xport_specific)); + } else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) { + bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN); cam_compat_translate_dev_match_0x18(ccb); + } else { + bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN); + } xpt_free_ccb(ccb); diff --git a/sys/cam/cam_compat.h b/sys/cam/cam_compat.h index 9a2097fb4bf9..72a3608032ce 100644 --- a/sys/cam/cam_compat.h +++ b/sys/cam/cam_compat.h @@ -43,8 +43,8 @@ int cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, #define CAM_VERSION_0x16 0x16 /* The size of the union ccb didn't change when going to 0x17 */ -#define CAMIOCOMMAND_0x16 _IOWR(CAM_VERSION_0x16, 2, union ccb) -#define CAMGETPASSTHRU_0x16 _IOWR(CAM_VERSION_0x16, 3, union ccb) +#define CAMIOCOMMAND_0x16 _IOC(IOC_INOUT, CAM_VERSION_0x16, 2, CAM_0X17_LEN) +#define CAMGETPASSTHRU_0x16 _IOC(IOC_INOUT, CAM_VERSION_0x16, 3, CAM_0X17_LEN) #define CAM_SCATTER_VALID_0x16 0x00000010 #define CAM_SG_LIST_PHYS_0x16 0x00040000 @@ -110,8 +110,30 @@ struct ccb_pathinq_0x17 { u_int16_t hba_subdevice; /* HBA subdevice ID */ }; -#define CAM_0X17_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr) + sizeof(struct ccb_hdr_0x17)) -#define CAM_0X17_DATA_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr_0x17)) +struct ccb_trans_settings_0x17 { + struct ccb_hdr_0x17 ccb_h; + cts_type type; /* Current or User settings */ + cam_proto protocol; + u_int protocol_version; + cam_xport transport; + u_int transport_version; + union { + u_int valid; /* Which fields to honor */ + struct ccb_trans_settings_ata ata; + struct ccb_trans_settings_scsi scsi; + } proto_specific; + union { + u_int valid; /* Which fields to honor */ + struct ccb_trans_settings_spi spi; + struct ccb_trans_settings_fc fc; + struct ccb_trans_settings_sas sas; + struct ccb_trans_settings_pata ata; + struct ccb_trans_settings_sata sata; + } xport_specific; +}; + +#define CAM_0X17_DATA_LEN CAM_0X18_DATA_LEN +#define CAM_0X17_LEN (sizeof(struct ccb_hdr_0x17) + CAM_0X17_DATA_LEN) #define CAMIOCOMMAND_0x17 _IOC(IOC_INOUT, CAM_VERSION_0x17, 2, CAM_0X17_LEN) #define CAMGETPASSTHRU_0x17 _IOC(IOC_INOUT, CAM_VERSION_0x17, 3, CAM_0X17_LEN) @@ -146,6 +168,28 @@ typedef enum { CAM_EXTLUN_VALID_0x18 = 0x00000001,/* 64bit lun field is valid */ } ccb_xflags_0x18; +struct ccb_trans_settings_0x18 { + struct ccb_hdr_0x18 ccb_h; + cts_type type; /* Current or User settings */ + cam_proto protocol; + u_int protocol_version; + cam_xport transport; + u_int transport_version; + union { + u_int valid; /* Which fields to honor */ + struct ccb_trans_settings_ata ata; + struct ccb_trans_settings_scsi scsi; + } proto_specific; + union { + u_int valid; /* Which fields to honor */ + struct ccb_trans_settings_spi spi; + struct ccb_trans_settings_fc fc; + struct ccb_trans_settings_sas sas; + struct ccb_trans_settings_pata ata; + struct ccb_trans_settings_sata sata; + } xport_specific; +}; + struct dev_match_result_0x18 { dev_match_type type; union { @@ -169,8 +213,8 @@ struct dev_match_result_0x18 { } result; }; -#define CAM_0X18_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr) + sizeof(struct ccb_hdr_0x18)) -#define CAM_0X18_DATA_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr_0x18)) +#define CAM_0X18_DATA_LEN (sizeof(union ccb) - 2*sizeof(void *) - sizeof(struct ccb_hdr)) +#define CAM_0X18_LEN (sizeof(struct ccb_hdr_0x18) + CAM_0X18_DATA_LEN) #define CAMIOCOMMAND_0x18 _IOC(IOC_INOUT, CAM_VERSION_0x18, 2, CAM_0X18_LEN) #define CAMGETPASSTHRU_0x18 _IOC(IOC_INOUT, CAM_VERSION_0x18, 3, CAM_0X18_LEN)