diff --git a/sys/cam/cam.h b/sys/cam/cam.h index 20fd3cc0825a..302504fb4fcd 100644 --- a/sys/cam/cam.h +++ b/sys/cam/cam.h @@ -39,16 +39,12 @@ typedef u_int path_id_t; typedef u_int target_id_t; -typedef u_int lun_id_t; -typedef union { - u_int64_t lun64; - u_int8_t lun[8]; -} lun64_id_t; +typedef u_int64_t lun_id_t; #define CAM_XPT_PATH_ID ((path_id_t)~0) #define CAM_BUS_WILDCARD ((path_id_t)~0) #define CAM_TARGET_WILDCARD ((target_id_t)~0) -#define CAM_LUN_WILDCARD ((lun_id_t)~0) +#define CAM_LUN_WILDCARD (~(u_int)0) #define CAM_EXTLUN_BYTE_SWIZZLE(lun) ( \ ((((u_int64_t)lun) & 0xffff000000000000L) >> 48) | \ diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 139bd505ee50..87553c629380 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -109,10 +109,6 @@ typedef enum { CAM_UNLOCKED = 0x80000000 /* Call callback without lock. */ } ccb_flags; -typedef enum { - CAM_EXTLUN_VALID = 0x00000001,/* 64bit lun field is valid */ -} ccb_xflags; - /* XPT Opcodes for xpt_action */ typedef enum { /* Function code flags are bits greater than 0xff */ @@ -326,7 +322,6 @@ struct ccb_hdr { path_id_t path_id; /* Path ID for the request */ target_id_t target_id; /* Target device ID */ lun_id_t target_lun; /* Target LUN number */ - lun64_id_t ext_lun; /* 64bit extended/multi-level LUNs */ u_int32_t flags; /* ccb_flags */ u_int32_t xflags; /* Extended flags */ ccb_ppriv_area periph_priv; @@ -555,7 +550,7 @@ struct ccb_dev_match { /* * Definitions for the path inquiry CCB fields. */ -#define CAM_VERSION 0x18 /* Hex value for current version */ +#define CAM_VERSION 0x19 /* Hex value for current version */ typedef enum { PI_MDP_ABLE = 0x80, /* Supports MDP message */ diff --git a/sys/cam/cam_compat.c b/sys/cam/cam_compat.c index f2914794fe10..bcce814ffdf1 100644 --- a/sys/cam/cam_compat.c +++ b/sys/cam/cam_compat.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -53,6 +54,9 @@ __FBSDID("$FreeBSD$"); static int cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td, d_ioctl_t *cbfnp); +static int cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, + int flag, struct thread *td, d_ioctl_t *cbfnp); +static int cam_compat_translate_dev_match_0x18(union ccb *ccb); int cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, @@ -63,28 +67,28 @@ cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, switch (cmd) { case CAMIOCOMMAND_0x16: { - union ccb *ccb; + struct ccb_hdr_0x17 *hdr17; - 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; + hdr17 = (struct ccb_hdr_0x17 *)addr; + if (hdr17->flags & CAM_SG_LIST_PHYS_0x16) { + hdr17->flags &= ~CAM_SG_LIST_PHYS_0x16; + hdr17->flags |= CAM_DATA_SG_PADDR; } - if (ccb->ccb_h.flags & CAM_DATA_PHYS_0x16) { - ccb->ccb_h.flags &= ~CAM_DATA_PHYS_0x16; - ccb->ccb_h.flags |= CAM_DATA_PADDR; + if (hdr17->flags & CAM_DATA_PHYS_0x16) { + hdr17->flags &= ~CAM_DATA_PHYS_0x16; + hdr17->flags |= CAM_DATA_PADDR; } - if (ccb->ccb_h.flags & CAM_SCATTER_VALID_0x16) { - ccb->ccb_h.flags &= CAM_SCATTER_VALID_0x16; - ccb->ccb_h.flags |= CAM_DATA_SG; + if (hdr17->flags & CAM_SCATTER_VALID_0x16) { + hdr17->flags &= CAM_SCATTER_VALID_0x16; + hdr17->flags |= CAM_DATA_SG; } cmd = CAMIOCOMMAND; - error = (cbfnp)(dev, cmd, addr, flag, td); + error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); break; } case CAMGETPASSTHRU_0x16: cmd = CAMGETPASSTHRU; - error = (cbfnp)(dev, cmd, addr, flag, td); + error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); break; case CAMIOCOMMAND_0x17: cmd = CAMIOCOMMAND; @@ -94,6 +98,14 @@ cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, cmd = CAMGETPASSTHRU; error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp); break; + case CAMIOCOMMAND_0x18: + cmd = CAMIOCOMMAND; + error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp); + break; + case CAMGETPASSTHRU_0x18: + cmd = CAMGETPASSTHRU; + error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp); + break; default: error = ENOTTY; } @@ -127,7 +139,6 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, 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; @@ -159,13 +170,11 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, 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 { + if (ccb->ccb_h.func_code == XPT_PATH_INQ) { struct ccb_pathinq *cpi; struct ccb_pathinq_0x17 *cpi17; + /* The PATH_INQ only needs special handling on the way out */ cpi = &ccb->cpi; cpi17 = (struct ccb_pathinq_0x17 *)hdr17; cpi17->version_num = cpi->version_num; @@ -196,9 +205,151 @@ 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_DEV_MATCH) { + /* Copy the rest of the header over */ + bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN); + + cam_compat_translate_dev_match_0x18(ccb); + } else { + bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN); } xpt_free_ccb(ccb); return (error); } + +static int +cam_compat_handle_0x18(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_0x18 *hdr18; + uint8_t *ccbb, *ccbb18; + u_int error; + + hdr18 = (struct ccb_hdr_0x18 *)addr; + ccb = xpt_alloc_ccb(); + hdr = &ccb->ccb_h; + + hdr->pinfo = hdr18->pinfo; + hdr->xpt_links = hdr18->xpt_links; + hdr->sim_links = hdr18->sim_links; + hdr->periph_links = hdr18->periph_links; + hdr->retry_count = hdr18->retry_count; + hdr->cbfcnp = hdr18->cbfcnp; + hdr->func_code = hdr18->func_code; + hdr->status = hdr18->status; + hdr->path = hdr18->path; + hdr->path_id = hdr18->path_id; + hdr->target_id = hdr18->target_id; + hdr->target_lun = hdr18->target_lun; + if (hdr18->xflags & CAM_EXTLUN_VALID_0x18) + hdr->target_lun = hdr18->ext_lun; + hdr->flags = hdr18->flags; + hdr->xflags = hdr18->xflags; + hdr->periph_priv = hdr18->periph_priv; + hdr->sim_priv = hdr18->sim_priv; + hdr->timeout = hdr18->timeout; + hdr->softtimeout.tv_sec = 0; + hdr->softtimeout.tv_usec = 0; + + ccbb = (uint8_t *)&hdr[1]; + ccbb18 = (uint8_t *)&hdr18[1]; + bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN); + + error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td); + + hdr18->pinfo = hdr->pinfo; + hdr18->xpt_links = hdr->xpt_links; + hdr18->sim_links = hdr->sim_links; + hdr18->periph_links = hdr->periph_links; + hdr18->retry_count = hdr->retry_count; + hdr18->cbfcnp = hdr->cbfcnp; + hdr18->func_code = hdr->func_code; + hdr18->status = hdr->status; + hdr18->path = hdr->path; + hdr18->path_id = hdr->path_id; + hdr18->target_id = hdr->target_id; + hdr18->target_lun = hdr->target_lun; + hdr18->ext_lun = hdr->target_lun; + hdr18->flags = hdr->flags; + hdr18->xflags = hdr->xflags | CAM_EXTLUN_VALID_0x18; + hdr18->periph_priv = hdr->periph_priv; + hdr18->sim_priv = hdr->sim_priv; + hdr18->timeout = hdr->timeout; + + bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN); + + if (ccb->ccb_h.func_code == XPT_DEV_MATCH) + cam_compat_translate_dev_match_0x18(ccb); + + xpt_free_ccb(ccb); + + return (error); +} + +static int +cam_compat_translate_dev_match_0x18(union ccb *ccb) +{ + struct dev_match_result *dm; + struct dev_match_result_0x18 *dm18; + struct cam_periph_map_info mapinfo; + int i; + + /* Remap the CCB into kernel address space */ + bzero(&mapinfo, sizeof(mapinfo)); + cam_periph_mapmem(ccb, &mapinfo); + + dm = ccb->cdm.matches; + /* Translate in-place: old fields are smaller */ + dm18 = (struct dev_match_result_0x18 *)(dm); + + for (i = 0; i < ccb->cdm.num_matches; i++) { + dm18[i].type = dm[i].type; + switch (dm[i].type) { + case DEV_MATCH_PERIPH: + memcpy(&dm18[i].result.periph_result.periph_name, + &dm[i].result.periph_result.periph_name, + DEV_IDLEN); + dm18[i].result.periph_result.unit_number = + dm[i].result.periph_result.unit_number; + dm18[i].result.periph_result.path_id = + dm[i].result.periph_result.path_id; + dm18[i].result.periph_result.target_id = + dm[i].result.periph_result.target_id; + dm18[i].result.periph_result.target_lun = + dm[i].result.periph_result.target_lun; + break; + case DEV_MATCH_DEVICE: + dm18[i].result.device_result.path_id = + dm[i].result.device_result.path_id; + dm18[i].result.device_result.target_id = + dm[i].result.device_result.target_id; + dm18[i].result.device_result.target_lun = + dm[i].result.device_result.target_lun; + dm18[i].result.device_result.protocol = + dm[i].result.device_result.protocol; + memcpy(&dm18[i].result.device_result.inq_data, + &dm[i].result.device_result.inq_data, + sizeof(struct scsi_inquiry_data)); + memcpy(&dm18[i].result.device_result.ident_data, + &dm[i].result.device_result.ident_data, + sizeof(struct ata_params)); + dm18[i].result.device_result.flags = + dm[i].result.device_result.flags; + break; + case DEV_MATCH_BUS: + memcpy(&dm18[i].result.bus_result, + &dm[i].result.bus_result, + sizeof(struct bus_match_result)); + break; + } + } + + cam_periph_unmapmem(ccb, &mapinfo); + + return (0); +} + diff --git a/sys/cam/cam_compat.h b/sys/cam/cam_compat.h index d5bde1ab1ed2..9a2097fb4bf9 100644 --- a/sys/cam/cam_compat.h +++ b/sys/cam/cam_compat.h @@ -65,7 +65,7 @@ struct ccb_hdr_0x17 { struct cam_path *path; /* Compiled path for this ccb */ path_id_t path_id; /* Path ID for the request */ target_id_t target_id; /* Target device ID */ - lun_id_t target_lun; /* Target LUN number */ + u_int target_lun; /* Target LUN number */ u_int32_t flags; /* ccb_flags */ ccb_ppriv_area periph_priv; ccb_spriv_area sim_priv; @@ -116,5 +116,64 @@ struct ccb_pathinq_0x17 { #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) +/* Version 0x18 compatibility */ +#define CAM_VERSION_0x18 0x18 + +struct ccb_hdr_0x18 { + cam_pinfo pinfo; /* Info for priority scheduling */ + camq_entry xpt_links; /* For chaining in the XPT layer */ + camq_entry sim_links; /* For chaining in the SIM layer */ + camq_entry periph_links; /* For chaining in the type driver */ + u_int32_t retry_count; + void (*cbfcnp)(struct cam_periph *, union ccb *); + xpt_opcode func_code; /* XPT function code */ + u_int32_t status; /* Status returned by CAM subsystem */ + struct cam_path *path; /* Compiled path for this ccb */ + path_id_t path_id; /* Path ID for the request */ + target_id_t target_id; /* Target device ID */ + u_int target_lun; /* Target LUN number */ + u_int64_t ext_lun; /* 64-bit LUN, more or less */ + u_int32_t flags; /* ccb_flags */ + u_int32_t xflags; /* extended ccb_flags */ + ccb_ppriv_area periph_priv; + ccb_spriv_area sim_priv; + ccb_qos_area qos; + u_int32_t timeout; /* Hard timeout value in seconds */ + struct timeval softtimeout; /* Soft timeout value in sec + usec */ +}; + +typedef enum { + CAM_EXTLUN_VALID_0x18 = 0x00000001,/* 64bit lun field is valid */ +} ccb_xflags_0x18; + +struct dev_match_result_0x18 { + dev_match_type type; + union { + struct { + char periph_name[DEV_IDLEN]; + u_int32_t unit_number; + path_id_t path_id; + target_id_t target_id; + u_int target_lun; + } periph_result; + struct { + path_id_t path_id; + target_id_t target_id; + u_int target_lun; + cam_proto protocol; + struct scsi_inquiry_data inq_data; + struct ata_params ident_data; + dev_result_flags flags; + } device_result; + struct bus_match_result bus_result; + } 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 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) + #endif #endif diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 69752e1d0f7f..33fc4105d032 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -101,10 +101,8 @@ SYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT|CTLFLAG_RW, 0, 0, (lval) |= (lp)->luns[(i)].lundata[1]; \ } #define CAM_GET_LUN(lp, i, lval) \ - (lval) = scsi_4btoul((lp)->luns[(i)].lundata); \ - (lval) = ((lval) >> 16) | ((lval) << 16); -#define CAM_LUN_ONLY_32BITS(lp, i) \ - (scsi_4btoul(&((lp)->luns[(i)].lundata[4])) == 0) + (lval) = scsi_8btou64((lp)->luns[(i)].lundata); \ + (lval) = CAM_EXTLUN_BYTE_SWIZZLE(lval); /* * If we're not quirked to search <= the first 8 luns @@ -1766,8 +1764,6 @@ probe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new, continue; CAM_GET_SIMPLE_LUN(old, idx1, this_lun); } - if (!CAM_LUN_ONLY_32BITS(old, idx1)) - continue; if (xpt_create_path(&tp, NULL, xpt_path_path_id(path), xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) { @@ -2038,10 +2034,6 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) break; } - /* XXX print warning? */ - if (!CAM_LUN_ONLY_32BITS(target->luns, - scan_info->lunindex[target_id])) - continue; if (CAM_CAN_GET_SIMPLE_LUN(target->luns, scan_info->lunindex[target_id])) { CAM_GET_SIMPLE_LUN(target->luns,