PERFORCE change 118702 for review

Scott Long scottl at FreeBSD.org
Tue Apr 24 04:36:15 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=118702

Change 118702 by scottl at scottl-x64 on 2007/04/24 04:36:12

	Move the bus and LUN scan code to scsi_xpt.c

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#63 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.h#10 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.c#2 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.h#2 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#63 (text+ko) ====

@@ -100,31 +100,6 @@
 #define CAM_MAX_HIGHPOWER  4
 #endif
 
-static int cam_srch_hi = 0;
-TUNABLE_INT("kern.cam.cam_srch_hi", &cam_srch_hi);
-static int sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS);
-SYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
-    sysctl_cam_search_luns, "I",
-    "allow search above LUN 7 for SCSI3 and greater devices");
-
-#define	CAM_SCSI2_MAXLUN	8
-/*
- * If we're not quirked to search <= the first 8 luns
- * and we are either quirked to search above lun 8,
- * or we're > SCSI-2 and we've enabled hilun searching,
- * or we're > SCSI-2 and the last lun was a success,
- * we can look for luns above lun 8.
- */
-#define	CAN_SRCH_HI_SPARSE(dv)				\
-  (((dv->quirk->quirks & CAM_QUIRK_NOHILUNS) == 0) 	\
-  && ((dv->quirk->quirks & CAM_QUIRK_HILUNS)		\
-  || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2 && cam_srch_hi)))
-
-#define	CAN_SRCH_HI_DENSE(dv)				\
-  (((dv->quirk->quirks & CAM_QUIRK_NOHILUNS) == 0) 	\
-  && ((dv->quirk->quirks & CAM_QUIRK_HILUNS)		\
-  || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2)))
-
 typedef enum {
 	XPT_FLAG_OPEN		= 0x01
 } xpt_flags;
@@ -275,14 +250,6 @@
 MODULE_VERSION(cam, 1);
 
 
-static cam_status	xpt_compile_path(struct cam_path *new_path,
-					 struct cam_periph *perph,
-					 path_id_t path_id,
-					 target_id_t target_id,
-					 lun_id_t lun_id);
-
-static void		xpt_release_path(struct cam_path *path);
-
 static void		xpt_async_bcast(struct async_list *async_head,
 					u_int32_t async_code,
 					struct cam_path *path,
@@ -319,11 +286,6 @@
 		 xpt_find_target(struct cam_eb *bus, target_id_t target_id);
 static struct cam_ed*
 		 xpt_find_device(struct cam_et *target, lun_id_t lun_id);
-static void	 xpt_scan_bus(struct cam_periph *periph, union ccb *ccb);
-static void	 xpt_scan_lun(struct cam_periph *periph,
-			      struct cam_path *path, cam_flags flags,
-			      union ccb *ccb);
-static void	 xptscandone(struct cam_periph *periph, union ccb *done_ccb);
 static xpt_busfunc_t	xptconfigbuscountfunc;
 static xpt_busfunc_t	xptconfigfunc;
 static void	 xpt_config(void *arg);
@@ -3492,7 +3454,7 @@
 	return (status);
 }
 
-static cam_status
+cam_status
 xpt_compile_path(struct cam_path *new_path, struct cam_periph *perph,
 		 path_id_t path_id, target_id_t target_id, lun_id_t lun_id)
 {
@@ -3563,7 +3525,7 @@
 	return (status);
 }
 
-static void
+void
 xpt_release_path(struct cam_path *path)
 {
 	CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_release_path\n"));
@@ -4677,386 +4639,6 @@
 	return (device);
 }
 
-typedef struct {
-	union	ccb *request_ccb;
-	struct 	ccb_pathinq *cpi;
-	int	counter;
-} xpt_scan_bus_info;
-
-/*
- * To start a scan, request_ccb is an XPT_SCAN_BUS ccb.
- * As the scan progresses, xpt_scan_bus is used as the
- * callback on completion function.
- */
-static void
-xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
-{
-	CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
-		  ("xpt_scan_bus\n"));
-	switch (request_ccb->ccb_h.func_code) {
-	case XPT_SCAN_BUS:
-	{
-		xpt_scan_bus_info *scan_info;
-		union	ccb *work_ccb;
-		struct	cam_path *path;
-		u_int	i;
-		u_int	max_target;
-		u_int	initiator_id;
-
-		/* Find out the characteristics of the bus */
-		work_ccb = xpt_alloc_ccb_nowait();
-		if (work_ccb == NULL) {
-			request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
-			xpt_done(request_ccb);
-			return;
-		}
-		xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path,
-			      request_ccb->ccb_h.pinfo.priority);
-		work_ccb->ccb_h.func_code = XPT_PATH_INQ;
-		xpt_action(work_ccb);
-		if (work_ccb->ccb_h.status != CAM_REQ_CMP) {
-			request_ccb->ccb_h.status = work_ccb->ccb_h.status;
-			xpt_free_ccb(work_ccb);
-			xpt_done(request_ccb);
-			return;
-		}
-
-		if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) {
-			/*
-			 * Can't scan the bus on an adapter that
-			 * cannot perform the initiator role.
-			 */
-			request_ccb->ccb_h.status = CAM_REQ_CMP;
-			xpt_free_ccb(work_ccb);
-			xpt_done(request_ccb);
-			return;
-		}
-
-		/* Save some state for use while we probe for devices */
-		scan_info = (xpt_scan_bus_info *)
-		    malloc(sizeof(xpt_scan_bus_info), M_TEMP, M_NOWAIT);
-		scan_info->request_ccb = request_ccb;
-		scan_info->cpi = &work_ccb->cpi;
-
-		/* Cache on our stack so we can work asynchronously */
-		max_target = scan_info->cpi->max_target;
-		initiator_id = scan_info->cpi->initiator_id;
-
-
-		/*
-		 * We can scan all targets in parallel, or do it sequentially.
-		 */
-		if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
-			max_target = 0;
-			scan_info->counter = 0;
-		} else {
-			scan_info->counter = scan_info->cpi->max_target + 1;
-			if (scan_info->cpi->initiator_id < scan_info->counter) {
-				scan_info->counter--;
-			}
-		}
-		
-		for (i = 0; i <= max_target; i++) {
-			cam_status status;
-			if (i == initiator_id)
-				continue;
-
-			status = xpt_create_path(&path, xpt_periph,
-						 request_ccb->ccb_h.path_id,
-						 i, 0);
-			if (status != CAM_REQ_CMP) {
-				printf("xpt_scan_bus: xpt_create_path failed"
-				       " with status %#x, bus scan halted\n",
-				       status);
-				free(scan_info, M_TEMP);
-				request_ccb->ccb_h.status = status;
-				xpt_free_ccb(work_ccb);
-				xpt_done(request_ccb);
-				break;
-			}
-			work_ccb = xpt_alloc_ccb_nowait();
-			if (work_ccb == NULL) {
-				free(scan_info, M_TEMP);
-				xpt_free_path(path);
-				request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
-				xpt_done(request_ccb);
-				break;
-			}
-			xpt_setup_ccb(&work_ccb->ccb_h, path,
-				      request_ccb->ccb_h.pinfo.priority);
-			work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
-			work_ccb->ccb_h.cbfcnp = xpt_scan_bus;
-			work_ccb->ccb_h.ppriv_ptr0 = scan_info;
-			work_ccb->crcn.flags = request_ccb->crcn.flags;
-			xpt_action(work_ccb);
-		}
-		break;
-	}
-	case XPT_SCAN_LUN:
-	{
-		cam_status status;
-		struct cam_path *path;
-		xpt_scan_bus_info *scan_info;
-		path_id_t path_id;
-		target_id_t target_id;
-		lun_id_t lun_id;
-
-		/* Reuse the same CCB to query if a device was really found */
-		scan_info = (xpt_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0;
-		xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path,
-			      request_ccb->ccb_h.pinfo.priority);
-		request_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
-
-		path_id = request_ccb->ccb_h.path_id;
-		target_id = request_ccb->ccb_h.target_id;
-		lun_id = request_ccb->ccb_h.target_lun;
-		xpt_action(request_ccb);
-
-		if (request_ccb->ccb_h.status != CAM_REQ_CMP) {
-			struct cam_ed *device;
-			struct cam_et *target;
-			int phl;
-
-			/*
-			 * If we already probed lun 0 successfully, or
-			 * we have additional configured luns on this
-			 * target that might have "gone away", go onto
-			 * the next lun.
-			 */
-			target = request_ccb->ccb_h.path->target;
-			/*
-			 * We may touch devices that we don't
-			 * hold references too, so ensure they
-			 * don't disappear out from under us.
-			 * The target above is referenced by the
-			 * path in the request ccb.
-			 */
-			phl = 0;
-			device = TAILQ_FIRST(&target->ed_entries);
-			if (device != NULL) {
-				phl = CAN_SRCH_HI_SPARSE(device);
-				if (device->lun_id == 0)
-					device = TAILQ_NEXT(device, links);
-			}
-			if ((lun_id != 0) || (device != NULL)) {
-				if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl)
-					lun_id++;
-			}
-		} else {
-			struct cam_ed *device;
-			
-			device = request_ccb->ccb_h.path->device;
-
-			if ((device->quirk->quirks & CAM_QUIRK_NOLUNS) == 0) {
-				/* Try the next lun */
-				if (lun_id < (CAM_SCSI2_MAXLUN-1)
-				  || CAN_SRCH_HI_DENSE(device))
-					lun_id++;
-			}
-		}
-
-		/*
-		 * Free the current request path- we're done with it.
-		 */
-		xpt_free_path(request_ccb->ccb_h.path);
-
-		/*
-		 * Check to see if we scan any further luns.
-		 */
-		if (lun_id == request_ccb->ccb_h.target_lun
-                 || lun_id > scan_info->cpi->max_lun) {
-			int done;
-
- hop_again:
-			done = 0;
-			if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
-				scan_info->counter++;
-				if (scan_info->counter == 
-				    scan_info->cpi->initiator_id) {
-					scan_info->counter++;
-				}
-				if (scan_info->counter >=
-				    scan_info->cpi->max_target+1) {
-					done = 1;
-				}
-			} else {
-				scan_info->counter--;
-				if (scan_info->counter == 0) {
-					done = 1;
-				}
-			}
-			if (done) {
-				xpt_free_ccb(request_ccb);
-				xpt_free_ccb((union ccb *)scan_info->cpi);
-				request_ccb = scan_info->request_ccb;
-				free(scan_info, M_TEMP);
-				request_ccb->ccb_h.status = CAM_REQ_CMP;
-				xpt_done(request_ccb);
-				break;
-			}
-
-			if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) {
-				break;
-			}
-			status = xpt_create_path(&path, xpt_periph,
-			    scan_info->request_ccb->ccb_h.path_id,
-			    scan_info->counter, 0);
-			if (status != CAM_REQ_CMP) {
-				printf("xpt_scan_bus: xpt_create_path failed"
-				    " with status %#x, bus scan halted\n",
-			       	    status);
-				xpt_free_ccb(request_ccb);
-				xpt_free_ccb((union ccb *)scan_info->cpi);
-				request_ccb = scan_info->request_ccb;
-				free(scan_info, M_TEMP);
-				request_ccb->ccb_h.status = status;
-				xpt_done(request_ccb);
-				break;
-			}
-			xpt_setup_ccb(&request_ccb->ccb_h, path,
-			    request_ccb->ccb_h.pinfo.priority);
-			request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
-			request_ccb->ccb_h.cbfcnp = xpt_scan_bus;
-			request_ccb->ccb_h.ppriv_ptr0 = scan_info;
-			request_ccb->crcn.flags =
-			    scan_info->request_ccb->crcn.flags;
-		} else {
-			status = xpt_create_path(&path, xpt_periph,
-						 path_id, target_id, lun_id);
-			if (status != CAM_REQ_CMP) {
-				printf("xpt_scan_bus: xpt_create_path failed "
-				       "with status %#x, halting LUN scan\n",
-			 	       status);
-				goto hop_again;
-			}
-			xpt_setup_ccb(&request_ccb->ccb_h, path,
-				      request_ccb->ccb_h.pinfo.priority);
-			request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
-			request_ccb->ccb_h.cbfcnp = xpt_scan_bus;
-			request_ccb->ccb_h.ppriv_ptr0 = scan_info;
-			request_ccb->crcn.flags =
-				scan_info->request_ccb->crcn.flags;
-		}
-		xpt_action(request_ccb);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-static void
-xpt_scan_lun(struct cam_periph *periph, struct cam_path *path,
-	     cam_flags flags, union ccb *request_ccb)
-{
-	struct ccb_pathinq cpi;
-	cam_status status;
-	struct cam_path *new_path;
-	struct cam_periph *old_periph;
-
-	CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
-		  ("xpt_scan_lun\n"));
-	
-	xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
-	cpi.ccb_h.func_code = XPT_PATH_INQ;
-	xpt_action((union ccb *)&cpi);
-
-	if (cpi.ccb_h.status != CAM_REQ_CMP) {
-		if (request_ccb != NULL) {
-			request_ccb->ccb_h.status = cpi.ccb_h.status;
-			xpt_done(request_ccb);
-		}
-		return;
-	}
-
-	if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) {
-		/*
-		 * Can't scan the bus on an adapter that
-		 * cannot perform the initiator role.
-		 */
-		if (request_ccb != NULL) {
-			request_ccb->ccb_h.status = CAM_REQ_CMP;
-			xpt_done(request_ccb);
-		}
-		return;
-	}
-
-	if (request_ccb == NULL) {
-		request_ccb = malloc(sizeof(union ccb), M_TEMP, M_NOWAIT);
-		if (request_ccb == NULL) {
-			xpt_print(path, "xpt_scan_lun: can't allocate CCB, "
-			    "can't continue\n");
-			return;
-		}
-		new_path = malloc(sizeof(*new_path), M_TEMP, M_NOWAIT);
-		if (new_path == NULL) {
-			xpt_print(path, "xpt_scan_lun: can't allocate path, "
-			    "can't continue\n");
-			free(request_ccb, M_TEMP);
-			return;
-		}
-		status = xpt_compile_path(new_path, xpt_periph,
-					  path->bus->path_id,
-					  path->target->target_id,
-					  path->device->lun_id);
-
-		if (status != CAM_REQ_CMP) {
-			xpt_print(path, "xpt_scan_lun: can't compile path, "
-			    "can't continue\n");
-			free(request_ccb, M_TEMP);
-			free(new_path, M_TEMP);
-			return;
-		}
-		xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1);
-		request_ccb->ccb_h.cbfcnp = xptscandone;
-		request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
-		request_ccb->crcn.flags = flags;
-	}
-
-	if ((old_periph = cam_periph_find(path, "probe")) != NULL) {
-		probe_insert_ccbq(old_periph, &request_ccb->ccb_h);
-	} else {
-		status = cam_periph_alloc(proberegister, NULL, probecleanup,
-					  probestart, "probe",
-					  CAM_PERIPH_BIO,
-					  request_ccb->ccb_h.path, NULL, 0,
-					  request_ccb);
-
-		if (status != CAM_REQ_CMP) {
-			xpt_print(path, "xpt_scan_lun: cam_alloc_periph "
-			    "returned an error, can't continue probe\n");
-			request_ccb->ccb_h.status = status;
-			xpt_done(request_ccb);
-		}
-	}
-}
-
-static void
-xptscandone(struct cam_periph *periph, union ccb *done_ccb)
-{
-	xpt_release_path(done_ccb->ccb_h.path);
-	free(done_ccb->ccb_h.path, M_TEMP);
-	free(done_ccb, M_TEMP);
-}
-
-static int
-sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS)
-{
-	int error, bool;
-
-	bool = cam_srch_hi;
-	error = sysctl_handle_int(oidp, &bool, sizeof(bool), req);
-	if (error != 0 || req->newptr == NULL)
-		return (error);
-	if (bool == 0 || bool == 1) {
-		cam_srch_hi = bool;
-		return (0);
-	} else {
-		return (EINVAL);
-	}
-}
-
-
 void
 xpt_devise_transport(struct cam_path *path)
 {

==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.h#10 (text+ko) ====

@@ -80,6 +80,14 @@
 void			xpt_rescan(union ccb *ccb);
 void			xpt_lock_buses(void);
 void			xpt_unlock_buses(void);
+cam_status		xpt_compile_path(struct cam_path *new_path,
+					 struct cam_periph *perph,
+					 path_id_t path_id,
+					 target_id_t target_id,
+					 lun_id_t lun_id);
+
+void			xpt_release_path(struct cam_path *path);
+
 #endif /* _KERNEL */
 
 #endif /* _CAM_CAM_XPT_H */

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.c#2 (text+ko) ====

@@ -64,6 +64,7 @@
 #include <cam/scsi/scsi_message.h>
 #include <cam/scsi/scsi_pass.h>
 #include <cam/scsi/scsi_xpt.h>
+#include <cam/scsi/scsi_probe.h>
 #include <machine/stdarg.h>	/* for xpt_print below */
 #include "opt_cam.h"
 
@@ -431,6 +432,31 @@
 struct xpt_quirk_entry *xpt_default_quirk =
     &xpt_quirk_table[(sizeof(xpt_quirk_table) / sizeof(*xpt_quirk_table)) - 1];
 
+#define	CAM_SCSI2_MAXLUN	8
+/*
+ * If we're not quirked to search <= the first 8 luns
+ * and we are either quirked to search above lun 8,
+ * or we're > SCSI-2 and we've enabled hilun searching,
+ * or we're > SCSI-2 and the last lun was a success,
+ * we can look for luns above lun 8.
+ */
+#define	CAN_SRCH_HI_SPARSE(dv)				\
+  (((dv->quirk->quirks & CAM_QUIRK_NOHILUNS) == 0) 	\
+  && ((dv->quirk->quirks & CAM_QUIRK_HILUNS)		\
+  || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2 && cam_srch_hi)))
+
+#define	CAN_SRCH_HI_DENSE(dv)				\
+  (((dv->quirk->quirks & CAM_QUIRK_NOHILUNS) == 0) 	\
+  && ((dv->quirk->quirks & CAM_QUIRK_HILUNS)		\
+  || (SID_ANSI_REV(&dv->inq_data) > SCSI_REV_2)))
+
+static int cam_srch_hi = 0;
+TUNABLE_INT("kern.cam.cam_srch_hi", &cam_srch_hi);
+static int sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS);
+SYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
+    sysctl_cam_search_luns, "I",
+    "allow search above LUN 7 for SCSI3 and greater devices");
+
 
 void
 xpt_find_quirk(struct cam_ed *device)
@@ -448,3 +474,381 @@
 	device->quirk = (struct xpt_quirk_entry *)match;
 }
 
+typedef struct {
+	union	ccb *request_ccb;
+	struct 	ccb_pathinq *cpi;
+	int	counter;
+} xpt_scan_bus_info;
+
+/*
+ * To start a scan, request_ccb is an XPT_SCAN_BUS ccb.
+ * As the scan progresses, xpt_scan_bus is used as the
+ * callback on completion function.
+ */
+void
+xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
+{
+	CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
+		  ("xpt_scan_bus\n"));
+	switch (request_ccb->ccb_h.func_code) {
+	case XPT_SCAN_BUS:
+	{
+		xpt_scan_bus_info *scan_info;
+		union	ccb *work_ccb;
+		struct	cam_path *path;
+		u_int	i;
+		u_int	max_target;
+		u_int	initiator_id;
+
+		/* Find out the characteristics of the bus */
+		work_ccb = xpt_alloc_ccb_nowait();
+		if (work_ccb == NULL) {
+			request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+			xpt_done(request_ccb);
+			return;
+		}
+		xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path,
+			      request_ccb->ccb_h.pinfo.priority);
+		work_ccb->ccb_h.func_code = XPT_PATH_INQ;
+		xpt_action(work_ccb);
+		if (work_ccb->ccb_h.status != CAM_REQ_CMP) {
+			request_ccb->ccb_h.status = work_ccb->ccb_h.status;
+			xpt_free_ccb(work_ccb);
+			xpt_done(request_ccb);
+			return;
+		}
+
+		if ((work_ccb->cpi.hba_misc & PIM_NOINITIATOR) != 0) {
+			/*
+			 * Can't scan the bus on an adapter that
+			 * cannot perform the initiator role.
+			 */
+			request_ccb->ccb_h.status = CAM_REQ_CMP;
+			xpt_free_ccb(work_ccb);
+			xpt_done(request_ccb);
+			return;
+		}
+
+		/* Save some state for use while we probe for devices */
+		scan_info = (xpt_scan_bus_info *)
+		    malloc(sizeof(xpt_scan_bus_info), M_TEMP, M_NOWAIT);
+		scan_info->request_ccb = request_ccb;
+		scan_info->cpi = &work_ccb->cpi;
+
+		/* Cache on our stack so we can work asynchronously */
+		max_target = scan_info->cpi->max_target;
+		initiator_id = scan_info->cpi->initiator_id;
+
+
+		/*
+		 * We can scan all targets in parallel, or do it sequentially.
+		 */
+		if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
+			max_target = 0;
+			scan_info->counter = 0;
+		} else {
+			scan_info->counter = scan_info->cpi->max_target + 1;
+			if (scan_info->cpi->initiator_id < scan_info->counter) {
+				scan_info->counter--;
+			}
+		}
+		
+		for (i = 0; i <= max_target; i++) {
+			cam_status status;
+			if (i == initiator_id)
+				continue;
+
+			status = xpt_create_path(&path, xpt_periph,
+						 request_ccb->ccb_h.path_id,
+						 i, 0);
+			if (status != CAM_REQ_CMP) {
+				printf("xpt_scan_bus: xpt_create_path failed"
+				       " with status %#x, bus scan halted\n",
+				       status);
+				free(scan_info, M_TEMP);
+				request_ccb->ccb_h.status = status;
+				xpt_free_ccb(work_ccb);
+				xpt_done(request_ccb);
+				break;
+			}
+			work_ccb = xpt_alloc_ccb_nowait();
+			if (work_ccb == NULL) {
+				free(scan_info, M_TEMP);
+				xpt_free_path(path);
+				request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+				xpt_done(request_ccb);
+				break;
+			}
+			xpt_setup_ccb(&work_ccb->ccb_h, path,
+				      request_ccb->ccb_h.pinfo.priority);
+			work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
+			work_ccb->ccb_h.cbfcnp = xpt_scan_bus;
+			work_ccb->ccb_h.ppriv_ptr0 = scan_info;
+			work_ccb->crcn.flags = request_ccb->crcn.flags;
+			xpt_action(work_ccb);
+		}
+		break;
+	}
+	case XPT_SCAN_LUN:
+	{
+		cam_status status;
+		struct cam_path *path;
+		xpt_scan_bus_info *scan_info;
+		path_id_t path_id;
+		target_id_t target_id;
+		lun_id_t lun_id;
+
+		/* Reuse the same CCB to query if a device was really found */
+		scan_info = (xpt_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0;
+		xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path,
+			      request_ccb->ccb_h.pinfo.priority);
+		request_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+
+		path_id = request_ccb->ccb_h.path_id;
+		target_id = request_ccb->ccb_h.target_id;
+		lun_id = request_ccb->ccb_h.target_lun;
+		xpt_action(request_ccb);
+
+		if (request_ccb->ccb_h.status != CAM_REQ_CMP) {
+			struct cam_ed *device;
+			struct cam_et *target;
+			int phl;
+
+			/*
+			 * If we already probed lun 0 successfully, or
+			 * we have additional configured luns on this
+			 * target that might have "gone away", go onto
+			 * the next lun.
+			 */
+			target = request_ccb->ccb_h.path->target;
+			/*
+			 * We may touch devices that we don't
+			 * hold references too, so ensure they
+			 * don't disappear out from under us.
+			 * The target above is referenced by the
+			 * path in the request ccb.
+			 */
+			phl = 0;
+			device = TAILQ_FIRST(&target->ed_entries);
+			if (device != NULL) {
+				phl = CAN_SRCH_HI_SPARSE(device);
+				if (device->lun_id == 0)
+					device = TAILQ_NEXT(device, links);
+			}
+			if ((lun_id != 0) || (device != NULL)) {
+				if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl)
+					lun_id++;
+			}
+		} else {
+			struct cam_ed *device;
+			
+			device = request_ccb->ccb_h.path->device;
+
+			if ((device->quirk->quirks & CAM_QUIRK_NOLUNS) == 0) {
+				/* Try the next lun */
+				if (lun_id < (CAM_SCSI2_MAXLUN-1)
+				  || CAN_SRCH_HI_DENSE(device))
+					lun_id++;
+			}
+		}
+
+		/*
+		 * Free the current request path- we're done with it.
+		 */
+		xpt_free_path(request_ccb->ccb_h.path);
+
+		/*
+		 * Check to see if we scan any further luns.
+		 */
+		if (lun_id == request_ccb->ccb_h.target_lun
+                 || lun_id > scan_info->cpi->max_lun) {
+			int done;
+
+ hop_again:
+			done = 0;
+			if (scan_info->cpi->hba_misc & PIM_SEQSCAN) {
+				scan_info->counter++;
+				if (scan_info->counter == 
+				    scan_info->cpi->initiator_id) {
+					scan_info->counter++;
+				}
+				if (scan_info->counter >=
+				    scan_info->cpi->max_target+1) {
+					done = 1;
+				}
+			} else {
+				scan_info->counter--;
+				if (scan_info->counter == 0) {
+					done = 1;
+				}
+			}
+			if (done) {
+				xpt_free_ccb(request_ccb);
+				xpt_free_ccb((union ccb *)scan_info->cpi);
+				request_ccb = scan_info->request_ccb;
+				free(scan_info, M_TEMP);
+				request_ccb->ccb_h.status = CAM_REQ_CMP;
+				xpt_done(request_ccb);
+				break;
+			}
+
+			if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) {
+				break;
+			}
+			status = xpt_create_path(&path, xpt_periph,
+			    scan_info->request_ccb->ccb_h.path_id,
+			    scan_info->counter, 0);
+			if (status != CAM_REQ_CMP) {
+				printf("xpt_scan_bus: xpt_create_path failed"
+				    " with status %#x, bus scan halted\n",
+			       	    status);
+				xpt_free_ccb(request_ccb);
+				xpt_free_ccb((union ccb *)scan_info->cpi);
+				request_ccb = scan_info->request_ccb;
+				free(scan_info, M_TEMP);
+				request_ccb->ccb_h.status = status;
+				xpt_done(request_ccb);
+				break;
+			}
+			xpt_setup_ccb(&request_ccb->ccb_h, path,
+			    request_ccb->ccb_h.pinfo.priority);
+			request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
+			request_ccb->ccb_h.cbfcnp = xpt_scan_bus;
+			request_ccb->ccb_h.ppriv_ptr0 = scan_info;
+			request_ccb->crcn.flags =
+			    scan_info->request_ccb->crcn.flags;
+		} else {
+			status = xpt_create_path(&path, xpt_periph,
+						 path_id, target_id, lun_id);
+			if (status != CAM_REQ_CMP) {
+				printf("xpt_scan_bus: xpt_create_path failed "
+				       "with status %#x, halting LUN scan\n",
+			 	       status);
+				goto hop_again;
+			}
+			xpt_setup_ccb(&request_ccb->ccb_h, path,
+				      request_ccb->ccb_h.pinfo.priority);
+			request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
+			request_ccb->ccb_h.cbfcnp = xpt_scan_bus;
+			request_ccb->ccb_h.ppriv_ptr0 = scan_info;
+			request_ccb->crcn.flags =
+				scan_info->request_ccb->crcn.flags;
+		}
+		xpt_action(request_ccb);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+void
+xpt_scan_lun(struct cam_periph *periph, struct cam_path *path,
+	     cam_flags flags, union ccb *request_ccb)
+{
+	struct ccb_pathinq cpi;
+	cam_status status;
+	struct cam_path *new_path;
+	struct cam_periph *old_periph;
+
+	CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
+		  ("xpt_scan_lun\n"));
+	
+	xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
+	cpi.ccb_h.func_code = XPT_PATH_INQ;
+	xpt_action((union ccb *)&cpi);
+
+	if (cpi.ccb_h.status != CAM_REQ_CMP) {
+		if (request_ccb != NULL) {
+			request_ccb->ccb_h.status = cpi.ccb_h.status;
+			xpt_done(request_ccb);
+		}
+		return;
+	}
+
+	if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) {
+		/*
+		 * Can't scan the bus on an adapter that
+		 * cannot perform the initiator role.
+		 */
+		if (request_ccb != NULL) {
+			request_ccb->ccb_h.status = CAM_REQ_CMP;
+			xpt_done(request_ccb);
+		}
+		return;
+	}
+
+	if (request_ccb == NULL) {
+		request_ccb = malloc(sizeof(union ccb), M_TEMP, M_NOWAIT);
+		if (request_ccb == NULL) {
+			xpt_print(path, "xpt_scan_lun: can't allocate CCB, "
+			    "can't continue\n");
+			return;
+		}
+		new_path = malloc(sizeof(*new_path), M_TEMP, M_NOWAIT);
+		if (new_path == NULL) {
+			xpt_print(path, "xpt_scan_lun: can't allocate path, "
+			    "can't continue\n");
+			free(request_ccb, M_TEMP);
+			return;
+		}
+		status = xpt_compile_path(new_path, xpt_periph,
+					  path->bus->path_id,
+					  path->target->target_id,
+					  path->device->lun_id);
+
+		if (status != CAM_REQ_CMP) {
+			xpt_print(path, "xpt_scan_lun: can't compile path, "
+			    "can't continue\n");
+			free(request_ccb, M_TEMP);
+			free(new_path, M_TEMP);
+			return;
+		}
+		xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1);
+		request_ccb->ccb_h.cbfcnp = xptscandone;
+		request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
+		request_ccb->crcn.flags = flags;
+	}
+
+	if ((old_periph = cam_periph_find(path, "probe")) != NULL) {
+		probe_insert_ccbq(old_periph, &request_ccb->ccb_h);
+	} else {
+		status = cam_periph_alloc(proberegister, NULL, probecleanup,
+					  probestart, "probe",
+					  CAM_PERIPH_BIO,
+					  request_ccb->ccb_h.path, NULL, 0,
+					  request_ccb);
+
+		if (status != CAM_REQ_CMP) {
+			xpt_print(path, "xpt_scan_lun: cam_alloc_periph "
+			    "returned an error, can't continue probe\n");
+			request_ccb->ccb_h.status = status;
+			xpt_done(request_ccb);
+		}
+	}
+}
+
+void
+xptscandone(struct cam_periph *periph, union ccb *done_ccb)
+{
+	xpt_release_path(done_ccb->ccb_h.path);
+	free(done_ccb->ccb_h.path, M_TEMP);
+	free(done_ccb, M_TEMP);
+}
+
+static int
+sysctl_cam_search_luns(SYSCTL_HANDLER_ARGS)
+{
+	int error, bool;
+
+	bool = cam_srch_hi;
+	error = sysctl_handle_int(oidp, &bool, sizeof(bool), req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+	if (bool == 0 || bool == 1) {
+		cam_srch_hi = bool;
+		return (0);
+	} else {
+		return (EINVAL);
+	}
+}

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.h#2 (text+ko) ====

@@ -115,5 +115,9 @@
 };
 
 void	 xpt_find_quirk(struct cam_ed *device);
+void	 xpt_scan_bus(struct cam_periph *periph, union ccb *ccb);
+void	 xpt_scan_lun(struct cam_periph *periph, struct cam_path *path,
+		      cam_flags flags, union ccb *ccb);
+void	 xptscandone(struct cam_periph *periph, union ccb *done_ccb);
 
 extern struct xpt_quirk_entry *xpt_default_quirk;


More information about the p4-projects mailing list