Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Mar 2009 04:52:57 GMT
From:      Scott Long <scottl@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 159988 for review
Message-ID:  <200903300452.n2U4qveh015181@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=159988

Change 159988 by scottl@scottl-deimos on 2009/03/30 04:52:03

	Get CAM back in sync with HEAD so that it can be worked on again.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/cam.h#4 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/cam_periph.c#25 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/cam_periph.h#15 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/cam_sim.c#12 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/cam_sim.h#11 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#79 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt_sim.h#5 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_all.c#7 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_all.h#9 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_cd.c#23 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_ch.c#15 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_da.c#38 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_low.c#15 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_pass.c#26 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_pt.c#11 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_sa.c#16 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_ses.c#17 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_sg.c#11 integrate
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_target.c#14 integrate

Differences ...

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

@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/cam/cam.h,v 1.11 2005/01/05 22:34:34 imp Exp $
+ * $FreeBSD: src/sys/cam/cam.h,v 1.12 2008/09/18 14:48:46 sbruno Exp $
  */
 
 #ifndef _CAM_CAM_H
@@ -129,6 +129,7 @@
 				 * requests for the target at the sim level
 				 * back into the XPT queue.
 				 */
+	CAM_SCSI_IT_NEXUS_LOST,	/* Initiator/Target Nexus lost. */
 	CAM_IDE = 0x33,		/* Initiator Detected Error */
 	CAM_RESRC_UNAVAIL,	/* Resource Unavailable */
 	CAM_UNACKED_EVENT,	/* Unacknowledged Event by Host */

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

@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/cam_periph.c,v 1.70 2008/02/12 11:07:33 raj Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/cam_periph.c,v 1.77 2009/02/09 17:02:54 fjoe Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -171,6 +171,10 @@
 			break;
 	}
 	xpt_unlock_buses();
+	if (*p_drv == NULL) {
+		printf("cam_periph_alloc: invalid periph name '%s'\n", name);
+		return (CAM_REQ_INVALID);
+	}
 
 	sim = xpt_path_sim(path);
 	path_id = xpt_path_path_id(path);
@@ -290,7 +294,7 @@
 }
 
 void
-cam_periph_release(struct cam_periph *periph)
+cam_periph_release_locked(struct cam_periph *periph)
 {
 
 	if (periph == NULL)
@@ -302,17 +306,28 @@
 		camperiphfree(periph);
 	}
 	xpt_unlock_buses();
+}
+
+void
+cam_periph_release(struct cam_periph *periph)
+{
+	struct cam_sim *sim;
 
+	if (periph == NULL)
+		return;
+	
+	sim = periph->sim;
+	mtx_assert(sim->mtx, MA_NOTOWNED);
+	mtx_lock(sim->mtx);
+	cam_periph_release_locked(periph);
+	mtx_unlock(sim->mtx);
 }
 
 int
 cam_periph_hold(struct cam_periph *periph, int priority)
 {
-	struct mtx *mtx;
 	int error;
 
-	mtx_assert(periph->sim->mtx, MA_OWNED);
-
 	/*
 	 * Increment the reference count on the peripheral
 	 * while we wait for our lock attempt to succeed
@@ -323,14 +338,12 @@
 	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
 		return (ENXIO);
 
-	mtx = periph->sim->mtx;
-	if (mtx == &Giant)
-		mtx = NULL;
-
+	mtx_assert(periph->sim->mtx, MA_OWNED);
 	while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
 		periph->flags |= CAM_PERIPH_LOCK_WANTED;
-		if ((error = msleep(periph, mtx, priority, "caplck", 0)) != 0) {
-			cam_periph_release(periph);
+		if ((error = mtx_sleep(periph, periph->sim->mtx, priority,
+		    "caplck", 0)) != 0) {
+			cam_periph_release_locked(periph);
 			return (error);
 		}
 	}
@@ -351,7 +364,7 @@
 		wakeup(periph);
 	}
 
-	cam_periph_release(periph);
+	cam_periph_release_locked(periph);
 }
 
 /*
@@ -750,7 +763,6 @@
 cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
 {
 	struct ccb_hdr *ccb_h;
-	struct mtx *mtx;
 
 	mtx_assert(periph->sim->mtx, MA_OWNED);
 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdgetccb\n"));
@@ -763,11 +775,8 @@
 		 && (SLIST_FIRST(&periph->ccb_list)->pinfo.priority == priority))
 			break;
 		mtx_assert(periph->sim->mtx, MA_OWNED);
-		if (periph->sim->mtx == &Giant)
-			mtx = NULL;
-		else
-			mtx = periph->sim->mtx;
-		msleep(&periph->ccb_list, mtx, PRIBIO, "cgticb", 0);
+		mtx_sleep(&periph->ccb_list, periph->sim->mtx, PRIBIO, "cgticb",
+		    0);
 	}
 
 	ccb_h = SLIST_FIRST(&periph->ccb_list);
@@ -778,17 +787,12 @@
 void
 cam_periph_ccbwait(union ccb *ccb)
 {
-	struct mtx *mtx;
 	struct cam_sim *sim;
 
 	sim = xpt_path_sim(ccb->ccb_h.path);
-	if (sim->mtx == &Giant)
-		mtx = NULL;
-	else
-		mtx = sim->mtx;
 	if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX)
 	 || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG))
-		msleep(&ccb->ccb_h.cbfcnp, mtx, PRIBIO, "cbwait", 0);
+		mtx_sleep(&ccb->ccb_h.cbfcnp, sim->mtx, PRIBIO, "cbwait", 0);
 }
 
 int

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

@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/cam/cam_periph.h,v 1.18 2007/04/19 22:46:26 scottl Exp $
+ * $FreeBSD: src/sys/cam/cam_periph.h,v 1.19 2008/12/19 14:31:40 trasz Exp $
  */
 
 #ifndef _CAM_CAM_PERIPH_H
@@ -141,6 +141,7 @@
 struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
 cam_status	cam_periph_acquire(struct cam_periph *periph);
 void		cam_periph_release(struct cam_periph *periph);
+void		cam_periph_release_locked(struct cam_periph *periph);
 int		cam_periph_hold(struct cam_periph *periph, int priority);
 void		cam_periph_unhold(struct cam_periph *periph);
 void		cam_periph_invalidate(struct cam_periph *periph);

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

@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/cam_sim.c,v 1.11 2007/04/19 14:28:43 scottl Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/cam_sim.c,v 1.13 2008/12/19 14:33:29 trasz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -84,6 +84,7 @@
 	sim->max_tagged_dev_openings = max_tagged_dev_transactions;
 	sim->max_dev_openings = max_dev_transactions;
 	sim->flags = 0;
+	sim->refcount = 1;
 	sim->devq = queue;
 	sim->mtx = mtx;
 	if (mtx == &Giant) {
@@ -103,12 +104,42 @@
 void
 cam_sim_free(struct cam_sim *sim, int free_devq)
 {
+	int error;
+
+	sim->refcount--;
+	if (sim->refcount > 0) {
+		error = msleep(sim, sim->mtx, PRIBIO, "simfree", 0);
+		KASSERT(error == 0, ("invalid error value for msleep(9)"));
+	}
+
+	KASSERT(sim->refcount == 0, ("sim->refcount == 0"));
+
 	if (free_devq)
 		cam_simq_free(sim->devq);
 	free(sim, M_CAMSIM);
 }
 
 void
+cam_sim_release(struct cam_sim *sim)
+{
+	KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
+	mtx_assert(sim->mtx, MA_OWNED);
+
+	sim->refcount--;
+	if (sim->refcount == 0)
+		wakeup(sim);
+}
+
+void
+cam_sim_hold(struct cam_sim *sim)
+{
+	KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
+	mtx_assert(sim->mtx, MA_OWNED);
+
+	sim->refcount++;
+}
+
+void
 cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id)
 {
 	sim->path_id = path_id;

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

@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/cam/cam_sim.h,v 1.8 2007/04/19 14:28:43 scottl Exp $
+ * $FreeBSD: src/sys/cam/cam_sim.h,v 1.10 2008/12/22 16:58:47 scottl Exp $
  */
 
 #ifndef _CAM_CAM_SIM_H
@@ -61,6 +61,8 @@
 				int max_tagged_dev_transactions,
 				struct cam_devq *queue);
 void		  cam_sim_free(struct cam_sim *sim, int free_devq);
+void		  cam_sim_hold(struct cam_sim *sim);
+void		  cam_sim_release(struct cam_sim *sim);
 
 /* Optional sim attributes may be set with these. */
 void	cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id);
@@ -105,8 +107,9 @@
 #define CAM_SIM_ON_DONEQ		0x04
 	struct callout		callout;
 	struct cam_devq 	*devq;	/* Device Queue to use for this SIM */
+	int			refcount; /* References to the SIM. */
 
-	/* "Pool" of inactive ccbs managed by xpt_alloc_ccb and xpt_free_ccb */
+	/* "Pool" of inactive ccbs managed by xpt_get_ccb and xpt_release_ccb */
 	SLIST_HEAD(,ccb_hdr)	ccb_freeq;
 	/*
 	 * Maximum size of ccb pool.  Modified as devices are added/removed

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

@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/cam_xpt.c,v 1.196 2008/02/26 08:09:29 scottl Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/cam_xpt.c,v 1.213 2009/02/16 18:02:32 scottl Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -36,7 +36,6 @@
 #include <sys/types.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
-#include <sys/module.h>
 #include <sys/time.h>
 #include <sys/conf.h>
 #include <sys/fcntl.h>
@@ -66,7 +65,6 @@
 #include <cam/scsi/scsi_all.h>
 #include <cam/scsi/scsi_message.h>
 #include <cam/scsi/scsi_pass.h>
-#include <cam/scsi/scsi_xpt.h>
 #include <machine/stdarg.h>	/* for xpt_print below */
 #include "opt_cam.h"
 
@@ -92,6 +90,9 @@
 	void		*callback_arg;
 };
 
+SLIST_HEAD(async_list, async_node);
+SLIST_HEAD(periph_list, cam_periph);
+
 /*
  * This is the maximum number of high powered commands (e.g. start unit)
  * that can be outstanding at a particular time.
@@ -100,6 +101,148 @@
 #define CAM_MAX_HIGHPOWER  4
 #endif
 
+/*
+ * Structure for queueing a device in a run queue.
+ * There is one run queue for allocating new ccbs,
+ * and another for sending ccbs to the controller.
+ */
+struct cam_ed_qinfo {
+	cam_pinfo pinfo;
+	struct	  cam_ed *device;
+};
+
+/*
+ * The CAM EDT (Existing Device Table) contains the device information for
+ * all devices for all busses in the system.  The table contains a
+ * cam_ed structure for each device on the bus.
+ */
+struct cam_ed {
+	TAILQ_ENTRY(cam_ed) links;
+	struct	cam_ed_qinfo alloc_ccb_entry;
+	struct	cam_ed_qinfo send_ccb_entry;
+	struct	cam_et	 *target;
+	struct	cam_sim  *sim;
+	lun_id_t	 lun_id;
+	struct	camq drvq;		/*
+					 * Queue of type drivers wanting to do
+					 * work on this device.
+					 */
+	struct	cam_ccbq ccbq;		/* Queue of pending ccbs */
+	struct	async_list asyncs;	/* Async callback info for this B/T/L */
+	struct	periph_list periphs;	/* All attached devices */
+	u_int	generation;		/* Generation number */
+	struct	cam_periph *owner;	/* Peripheral driver's ownership tag */
+	struct	xpt_quirk_entry *quirk;	/* Oddities about this device */
+					/* Storage for the inquiry data */
+	cam_proto	 protocol;
+	u_int		 protocol_version;
+	cam_xport	 transport;
+	u_int		 transport_version;
+	struct		 scsi_inquiry_data inq_data;
+	u_int8_t	 inq_flags;	/*
+					 * Current settings for inquiry flags.
+					 * This allows us to override settings
+					 * like disconnection and tagged
+					 * queuing for a device.
+					 */
+	u_int8_t	 queue_flags;	/* Queue flags from the control page */
+	u_int8_t	 serial_num_len;
+	u_int8_t	*serial_num;
+	u_int32_t	 qfrozen_cnt;
+	u_int32_t	 flags;
+#define CAM_DEV_UNCONFIGURED	 	0x01
+#define CAM_DEV_REL_TIMEOUT_PENDING	0x02
+#define CAM_DEV_REL_ON_COMPLETE		0x04
+#define CAM_DEV_REL_ON_QUEUE_EMPTY	0x08
+#define CAM_DEV_RESIZE_QUEUE_NEEDED	0x10
+#define CAM_DEV_TAG_AFTER_COUNT		0x20
+#define CAM_DEV_INQUIRY_DATA_VALID	0x40
+#define	CAM_DEV_IN_DV			0x80
+#define	CAM_DEV_DV_HIT_BOTTOM		0x100
+	u_int32_t	 tag_delay_count;
+#define	CAM_TAG_DELAY_COUNT		5
+	u_int32_t	 tag_saved_openings;
+	u_int32_t	 refcount;
+	struct callout	 callout;
+};
+
+/*
+ * Each target is represented by an ET (Existing Target).  These
+ * entries are created when a target is successfully probed with an
+ * identify, and removed when a device fails to respond after a number
+ * of retries, or a bus rescan finds the device missing.
+ */
+struct cam_et {
+	TAILQ_HEAD(, cam_ed) ed_entries;
+	TAILQ_ENTRY(cam_et) links;
+	struct	cam_eb	*bus;
+	target_id_t	target_id;
+	u_int32_t	refcount;
+	u_int		generation;
+	struct		timeval last_reset;
+};
+
+/*
+ * Each bus is represented by an EB (Existing Bus).  These entries
+ * are created by calls to xpt_bus_register and deleted by calls to
+ * xpt_bus_deregister.
+ */
+struct cam_eb {
+	TAILQ_HEAD(, cam_et) et_entries;
+	TAILQ_ENTRY(cam_eb)  links;
+	path_id_t	     path_id;
+	struct cam_sim	     *sim;
+	struct timeval	     last_reset;
+	u_int32_t	     flags;
+#define	CAM_EB_RUNQ_SCHEDULED	0x01
+	u_int32_t	     refcount;
+	u_int		     generation;
+	device_t	     parent_dev;
+};
+
+struct cam_path {
+	struct cam_periph *periph;
+	struct cam_eb	  *bus;
+	struct cam_et	  *target;
+	struct cam_ed	  *device;
+};
+
+struct xpt_quirk_entry {
+	struct scsi_inquiry_pattern inq_pat;
+	u_int8_t quirks;
+#define	CAM_QUIRK_NOLUNS	0x01
+#define	CAM_QUIRK_NOSERIAL	0x02
+#define	CAM_QUIRK_HILUNS	0x04
+#define	CAM_QUIRK_NOHILUNS	0x08
+	u_int mintags;
+	u_int maxtags;
+};
+
+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;
@@ -125,6 +268,359 @@
 	struct mtx		xpt_lock;
 };
 
+static const char quantum[] = "QUANTUM";
+static const char sony[] = "SONY";
+static const char west_digital[] = "WDIGTL";
+static const char samsung[] = "SAMSUNG";
+static const char seagate[] = "SEAGATE";
+static const char microp[] = "MICROP";
+
+static struct xpt_quirk_entry xpt_quirk_table[] =
+{
+	{
+		/* Reports QUEUE FULL for temporary resource shortages */
+		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP39100*", "*" },
+		/*quirks*/0, /*mintags*/24, /*maxtags*/32
+	},
+	{
+		/* Reports QUEUE FULL for temporary resource shortages */
+		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP34550*", "*" },
+		/*quirks*/0, /*mintags*/24, /*maxtags*/32
+	},
+	{
+		/* Reports QUEUE FULL for temporary resource shortages */
+		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "XP32275*", "*" },
+		/*quirks*/0, /*mintags*/24, /*maxtags*/32
+	},
+	{
+		/* Broken tagged queuing drive */
+		{ T_DIRECT, SIP_MEDIA_FIXED, microp, "4421-07*", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* Broken tagged queuing drive */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "HP", "C372*", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* Broken tagged queuing drive */
+		{ T_DIRECT, SIP_MEDIA_FIXED, microp, "3391*", "x43h" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * Unfortunately, the Quantum Atlas III has the same
+		 * problem as the Atlas II drives above.
+		 * Reported by: "Johan Granlund" <johan@granlund.nu>
+		 *
+		 * For future reference, the drive with the problem was:
+		 * QUANTUM QM39100TD-SW N1B0
+		 *
+		 * It's possible that Quantum will fix the problem in later
+		 * firmware revisions.  If that happens, the quirk entry
+		 * will need to be made specific to the firmware revisions
+		 * with the problem.
+		 *
+		 */
+		/* Reports QUEUE FULL for temporary resource shortages */
+		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM39100*", "*" },
+		/*quirks*/0, /*mintags*/24, /*maxtags*/32
+	},
+	{
+		/*
+		 * 18 Gig Atlas III, same problem as the 9G version.
+		 * Reported by: Andre Albsmeier
+		 *		<andre.albsmeier@mchp.siemens.de>
+		 *
+		 * For future reference, the drive with the problem was:
+		 * QUANTUM QM318000TD-S N491
+		 */
+		/* Reports QUEUE FULL for temporary resource shortages */
+		{ T_DIRECT, SIP_MEDIA_FIXED, quantum, "QM318000*", "*" },
+		/*quirks*/0, /*mintags*/24, /*maxtags*/32
+	},
+	{
+		/*
+		 * Broken tagged queuing drive
+		 * Reported by: Bret Ford <bford@uop.cs.uop.edu>
+		 *         and: Martin Renters <martin@tdc.on.ca>
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST410800*", "71*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+		/*
+		 * The Seagate Medalist Pro drives have very poor write
+		 * performance with anything more than 2 tags.
+		 *
+		 * Reported by:  Paul van der Zwan <paulz@trantor.xs4all.nl>
+		 * Drive:  <SEAGATE ST36530N 1444>
+		 *
+		 * Reported by:  Jeremy Lea <reg@shale.csir.co.za>
+		 * Drive:  <SEAGATE ST34520W 1281>
+		 *
+		 * No one has actually reported that the 9G version
+		 * (ST39140*) of the Medalist Pro has the same problem, but
+		 * we're assuming that it does because the 4G and 6.5G
+		 * versions of the drive are broken.
+		 */
+	{
+		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST34520*", "*"},
+		/*quirks*/0, /*mintags*/2, /*maxtags*/2
+	},
+	{
+		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST36530*", "*"},
+		/*quirks*/0, /*mintags*/2, /*maxtags*/2
+	},
+	{
+		{ T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"},
+		/*quirks*/0, /*mintags*/2, /*maxtags*/2
+	},
+	{
+		/*
+		 * Slow when tagged queueing is enabled.  Write performance
+		 * steadily drops off with more and more concurrent
+		 * transactions.  Best sequential write performance with
+		 * tagged queueing turned off and write caching turned on.
+		 *
+		 * PR:  kern/10398
+		 * Submitted by:  Hideaki Okada <hokada@isl.melco.co.jp>
+		 * Drive:  DCAS-34330 w/ "S65A" firmware.
+		 *
+		 * The drive with the problem had the "S65A" firmware
+		 * revision, and has also been reported (by Stephen J.
+		 * Roznowski <sjr@home.net>) for a drive with the "S61A"
+		 * firmware revision.
+		 *
+		 * Although no one has reported problems with the 2 gig
+		 * version of the DCAS drive, the assumption is that it
+		 * has the same problems as the 4 gig version.  Therefore
+		 * this quirk entries disables tagged queueing for all
+		 * DCAS drives.
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "IBM", "DCAS*", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* Broken tagged queuing drive */
+		{ T_DIRECT, SIP_MEDIA_REMOVABLE, "iomega", "jaz*", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* Broken tagged queuing drive */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CFP2107*", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* This does not support other than LUN 0 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255
+	},
+	{
+		/*
+		 * Broken tagged queuing drive.
+		 * Submitted by:
+		 * NAKAJI Hiroyuki <nakaji@zeisei.dpri.kyoto-u.ac.jp>
+		 * in PR kern/9535
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN34324U*", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+	},
+        {
+		/*
+		 * Slow when tagged queueing is enabled. (1.5MB/sec versus
+		 * 8MB/sec.)
+		 * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu>
+		 * Best performance with these drives is achieved with
+		 * tagged queueing turned off, and write caching turned on.
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, west_digital, "WDE*", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+        },
+        {
+		/*
+		 * Slow when tagged queueing is enabled. (1.5MB/sec versus
+		 * 8MB/sec.)
+		 * Submitted by: Andrew Gallatin <gallatin@cs.duke.edu>
+		 * Best performance with these drives is achieved with
+		 * tagged queueing turned off, and write caching turned on.
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, west_digital, "ENTERPRISE", "*" },
+		/*quirks*/0, /*mintags*/0, /*maxtags*/0
+        },
+	{
+		/*
+		 * Doesn't handle queue full condition correctly,
+		 * so we need to limit maxtags to what the device
+		 * can handle instead of determining this automatically.
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, samsung, "WN321010S*", "*" },
+		/*quirks*/0, /*mintags*/2, /*maxtags*/32
+	},
+	{
+		/* Really only one LUN */
+		{ T_ENCLOSURE, SIP_MEDIA_FIXED, "SUN", "SENA", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* I can't believe we need a quirk for DPT volumes. */
+		{ T_ANY, SIP_MEDIA_FIXED|SIP_MEDIA_REMOVABLE, "DPT", "*", "*" },
+		CAM_QUIRK_NOLUNS,
+		/*mintags*/0, /*maxtags*/255
+	},
+	{
+		/*
+		 * Many Sony CDROM drives don't like multi-LUN probing.
+		 */
+		{ T_CDROM, SIP_MEDIA_REMOVABLE, sony, "CD-ROM CDU*", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * This drive doesn't like multiple LUN probing.
+		 * Submitted by:  Parag Patel <parag@cgt.com>
+		 */
+		{ T_WORM, SIP_MEDIA_REMOVABLE, sony, "CD-R   CDU9*", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		{ T_WORM, SIP_MEDIA_REMOVABLE, "YAMAHA", "CDR100*", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * The 8200 doesn't like multi-lun probing, and probably
+		 * don't like serial number requests either.
+		 */
+		{
+			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
+			"EXB-8200*", "*"
+		},
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * Let's try the same as above, but for a drive that says
+		 * it's an IPL-6860 but is actually an EXB 8200.
+		 */
+		{
+			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "EXABYTE",
+			"IPL-6860*", "*"
+		},
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * These Hitachi drives don't like multi-lun probing.
+		 * The PR submitter has a DK319H, but says that the Linux
+		 * kernel has a similar work-around for the DK312 and DK314,
+		 * so all DK31* drives are quirked here.
+		 * PR:            misc/18793
+		 * Submitted by:  Paul Haddad <paul@pth.com>
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK31*", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255
+	},
+	{
+		/*
+		 * The Hitachi CJ series with J8A8 firmware apparantly has
+		 * problems with tagged commands.
+		 * PR: 23536
+		 * Reported by: amagai@nue.org
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "DK32CJ*", "J8A8" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * These are the large storage arrays.
+		 * Submitted by:  William Carrel <william.carrel@infospace.com>
+		 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "HITACHI", "OPEN*", "*" },
+		CAM_QUIRK_HILUNS, 2, 1024
+	},
+	{
+		/*
+		 * This old revision of the TDC3600 is also SCSI-1, and
+		 * hangs upon serial number probing.
+		 */
+		{
+			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
+			" TDC 3600", "U07:"
+		},
+		CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * Would repond to all LUNs if asked for.
+		 */
+		{
+			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "CALIPER",
+			"CP150", "*"
+		},
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/*
+		 * Would repond to all LUNs if asked for.
+		 */
+		{
+			T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY",
+			"96X2*", "*"
+		},
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* Submitted by: Matthew Dodd <winter@jurai.net> */
+		{ T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* Submitted by: Matthew Dodd <winter@jurai.net> */
+		{ T_PROCESSOR, SIP_MEDIA_FIXED, "CABLETRN", "EA41*", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* TeraSolutions special settings for TRC-22 RAID */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "TERASOLU", "TRC-22", "*" },
+		  /*quirks*/0, /*mintags*/55, /*maxtags*/255
+	},
+	{
+		/* Veritas Storage Appliance */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "VERITAS", "*", "*" },
+		  CAM_QUIRK_HILUNS, /*mintags*/2, /*maxtags*/1024
+	},
+	{
+		/*
+		 * Would respond to all LUNs.  Device type and removable
+		 * flag are jumper-selectable.
+		 */
+		{ T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED, "MaxOptix",
+		  "Tahiti 1", "*"
+		},
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* EasyRAID E5A aka. areca ARC-6010 */
+		{ T_DIRECT, SIP_MEDIA_FIXED, "easyRAID", "*", "*" },
+		  CAM_QUIRK_NOHILUNS, /*mintags*/2, /*maxtags*/255
+	},
+	{
+		{ T_ENCLOSURE, SIP_MEDIA_FIXED, "DP", "BACKPLANE", "*" },
+		CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+	},
+	{
+		/* Default tagged queuing parameters for all devices */
+		{
+		  T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
+		  /*vendor*/"*", /*product*/"*", /*revision*/"*"
+		},
+		/*quirks*/0, /*mintags*/2, /*maxtags*/255
+	},
+};
+
+static const int xpt_quirk_table_size =
+	sizeof(xpt_quirk_table) / sizeof(*xpt_quirk_table);
+
 typedef enum {
 	DM_RET_COPY		= 0x01,
 	DM_RET_FLAG_MASK	= 0x0f,
@@ -170,13 +666,22 @@
 
 static periph_init_t xpt_periph_init;
 
-static struct periph_driver xpt_periph_driver =
+static periph_init_t probe_periph_init;
+
+static struct periph_driver xpt_driver =
 {
 	xpt_periph_init, "xpt",
-	TAILQ_HEAD_INITIALIZER(xpt_periph_driver.units)
+	TAILQ_HEAD_INITIALIZER(xpt_driver.units)
+};
+
+static struct periph_driver probe_driver =
+{
+	probe_periph_init, "probe",
+	TAILQ_HEAD_INITIALIZER(probe_driver.units)
 };
 
-PERIPHDRIVER_DECLARE(xpt, xpt_periph_driver);
+PERIPHDRIVER_DECLARE(xpt, xpt_driver);
+PERIPHDRIVER_DECLARE(probe, probe_driver);
 
 
 static d_open_t xptopen;
@@ -193,19 +698,6 @@
 };
 
 
-static void dead_sim_action(struct cam_sim *sim, union ccb *ccb);
-static void dead_sim_poll(struct cam_sim *sim);
-
-/* Dummy SIM that is used when the real one has gone. */
-static struct cam_sim cam_dead_sim = {
-	.sim_action =	dead_sim_action,
-	.sim_poll =	dead_sim_poll,
-	.sim_name =	"dead_sim",
-};
-
-#define SIM_DEAD(sim)	((sim) == &cam_dead_sim)
-
-
 /* Storage for debugging datastructures */
 #ifdef	CAMDEBUG
 struct cam_path *cam_dpath;
@@ -235,27 +727,28 @@
 #endif /* CAMDEBUG */
 #endif /* CAM_DEBUG_BUS || CAM_DEBUG_TARGET || CAM_DEBUG_LUN */
 
-static void	xpt_identify(driver_t *driver, device_t parent);
-static int	xpt_probe(device_t dev);
-static int	xpt_attach(device_t dev);
-static int	xpt_detach(device_t dev);
+/* Our boot-time initialization hook */
+static int cam_module_event_handler(module_t, int /*modeventtype_t*/, void *);
 
-static device_method_t xpt_sim_methods[] = {
-	DEVMETHOD(device_identify,	xpt_identify),
-	DEVMETHOD(device_probe,		xpt_probe),
-	DEVMETHOD(device_attach,	xpt_attach),
-	DEVMETHOD(device_detach,	xpt_detach),
-	{ 0, 0 }
+static moduledata_t cam_moduledata = {
+	"cam",
+	cam_module_event_handler,
+	NULL
 };
 
-static driver_t xpt_sim_driver = {
-	"xptsim",
-	xpt_sim_methods,
-	1,	/* XXX Need softc */
-};
+static int	xpt_init(void *);
+
+DECLARE_MODULE(cam, cam_moduledata, SI_SUB_CONFIGURE, SI_ORDER_SECOND);
+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 devclass_t xpt_devclass;
-DRIVER_MODULE(xpt, nexus, xpt_sim_driver, xpt_devclass, 0, 0);
+static void		xpt_release_path(struct cam_path *path);
 
 static void		xpt_async_bcast(struct async_list *async_head,
 					u_int32_t async_code,
@@ -293,6 +786,11 @@
 		 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);
@@ -346,6 +844,17 @@
 static xpt_busfunc_t	xptsetasyncbusfunc;
 static cam_status	xptregister(struct cam_periph *periph,
 				    void *arg);
+static cam_status	proberegister(struct cam_periph *periph,
+				      void *arg);
+static void	 probeschedule(struct cam_periph *probe_periph);
+static void	 probestart(struct cam_periph *periph, union ccb *start_ccb);
+static void	 proberequestdefaultnegotiation(struct cam_periph *periph);
+static int       proberequestbackoff(struct cam_periph *periph,
+				     struct cam_ed *device);
+static void	 probedone(struct cam_periph *periph, union ccb *done_ccb);
+static void	 probecleanup(struct cam_periph *periph);
+static void	 xpt_find_quirk(struct cam_ed *device);
+static void	 xpt_devise_transport(struct cam_path *path);
 static void	 xpt_set_transfer_settings(struct ccb_trans_settings *cts,
 					   struct cam_ed *device,
 					   int async_update);
@@ -379,7 +888,7 @@
 		 */
 		retval = xpt_schedule_dev(&bus->sim->devq->alloc_queue,
 					  &dev->alloc_ccb_entry.pinfo,
-					  CAMQ_GET_HEAD(&dev->drvq)->priority);	
+					  CAMQ_GET_HEAD(&dev->drvq)->priority);
 	} else {
 		retval = 0;
 	}
@@ -446,6 +955,12 @@
 }
 
 static void
+probe_periph_init()
+{
+}
+
+
+static void
 xptdone(struct cam_periph *periph, union ccb *done_ccb)
 {
 	/* Caller will release the CCB */
@@ -474,7 +989,7 @@
 	mtx_lock(&xsoftc.xpt_lock);
 	xsoftc.flags |= XPT_FLAG_OPEN;
 	mtx_unlock(&xsoftc.xpt_lock);
-	
+
 	return(0);
 }
 
@@ -675,7 +1190,7 @@
 	 * (or rather should be) impossible for the device peripheral driver
 	 * list to change since we look at the whole thing in one pass, and
 	 * we do it with lock protection.
-	 * 

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903300452.n2U4qveh015181>