From owner-p4-projects@FreeBSD.ORG Mon Mar 30 04:52:58 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 73EED106566C; Mon, 30 Mar 2009 04:52:58 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 318C1106564A for ; Mon, 30 Mar 2009 04:52:58 +0000 (UTC) (envelope-from scottl@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 1A7B28FC15 for ; Mon, 30 Mar 2009 04:52:58 +0000 (UTC) (envelope-from scottl@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n2U4qvBn015183 for ; Mon, 30 Mar 2009 04:52:57 GMT (envelope-from scottl@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n2U4qveh015181 for perforce@freebsd.org; Mon, 30 Mar 2009 04:52:57 GMT (envelope-from scottl@freebsd.org) Date: Mon, 30 Mar 2009 04:52:57 GMT Message-Id: <200903300452.n2U4qveh015181@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to scottl@freebsd.org using -f From: Scott Long To: Perforce Change Reviews Cc: Subject: PERFORCE change 159988 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Mar 2009 04:52:59 -0000 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 -__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 #include @@ -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 -__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 #include @@ -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 -__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 #include @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -66,7 +65,6 @@ #include #include #include -#include #include /* 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" + * + * 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 + * + * + * 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 + * and: Martin Renters + */ + { 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 + * Drive: + * + * Reported by: Jeremy Lea + * Drive: + * + * 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 + * 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 ) 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 + * 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 + * 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 + * 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 + */ + { 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 + */ + { 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 + */ + { 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 */ + { T_PROCESSOR, SIP_MEDIA_FIXED, "Cabletrn", "EA41*", "*" }, + CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0 + }, + { + /* Submitted by: Matthew Dodd */ + { 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) <<<