PERFORCE change 159988 for review
Scott Long
scottl at FreeBSD.org
Sun Mar 29 21:52:59 PDT 2009
http://perforce.freebsd.org/chv.cgi?CH=159988
Change 159988 by scottl at 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 at 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 at 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 at uop.cs.uop.edu>
+ * and: Martin Renters <martin at 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 at trantor.xs4all.nl>
+ * Drive: <SEAGATE ST36530N 1444>
+ *
+ * Reported by: Jeremy Lea <reg at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at jurai.net> */
+ { T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" },
+ CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
+ },
+ {
+ /* Submitted by: Matthew Dodd <winter at 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) <<<
More information about the p4-projects
mailing list