Date: Mon, 23 Apr 2007 22:57:59 GMT From: Scott Long <scottl@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 118684 for review Message-ID: <200704232257.l3NMvx9n072058@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=118684 Change 118684 by scottl@scottl-x64 on 2007/04/23 22:57:58 Split out the probe periph into scsi/scsi_probe.c. Put the quirk table and function into scsi/scsi_xpt.c. Move needed structure and function definitions into scsi_probe.h and scsi_xpt.h. This will be refined as the SCSI transport separation continues. Affected files ... .. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#62 edit .. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.h#9 edit .. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_probe.c#6 add .. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.c#1 add .. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.h#1 add .. //depot/projects/scottl-camlock/src/sys/conf/files#22 edit .. //depot/projects/scottl-camlock/src/sys/modules/cam/Makefile#10 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#62 (text+ko) ==== @@ -65,6 +65,8 @@ #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 <cam/scsi/scsi_probe.h> #include <machine/stdarg.h> /* for xpt_print below */ #include "opt_cam.h" @@ -90,9 +92,6 @@ 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. @@ -101,119 +100,6 @@ #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 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 refcount; - u_int generation; -}; - -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); @@ -264,370 +150,6 @@ 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_NOSERIAL|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_NOSERIAL|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_NOSERIAL|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 - }, - { - /* - * Maxtor Personal Storage 3000XT (Firewire) - * hangs upon serial number probing. - */ - { - T_DIRECT, SIP_MEDIA_FIXED, "Maxtor", - "1394 storage", "*" - }, - 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, @@ -673,22 +195,13 @@ static periph_init_t xpt_periph_init; -static periph_init_t probe_periph_init; - static struct periph_driver xpt_driver = { xpt_periph_init, "xpt", 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_driver); -PERIPHDRIVER_DECLARE(probe, probe_driver); static d_open_t xptopen; @@ -864,17 +377,6 @@ 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); @@ -975,12 +477,6 @@ } static void -probe_periph_init() -{ -} - - -static void xptdone(struct cam_periph *periph, union ccb *done_ccb) { /* Caller will release the CCB */ @@ -5028,7 +4524,7 @@ * Take the default quirk entry until we have inquiry * data and can determine a better quirk to use. */ - device->quirk = &xpt_quirk_table[xpt_quirk_table_size - 1]; + device->quirk = xpt_default_quirk; bzero(&device->inq_data, sizeof(device->inq_data)); device->inq_flags = 0; device->queue_flags = 0; @@ -5449,33 +4945,6 @@ } } -typedef enum { - PROBE_TUR, - PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */ - PROBE_FULL_INQUIRY, - PROBE_MODE_SENSE, - PROBE_SERIAL_NUM, - PROBE_TUR_FOR_NEGOTIATION, - PROBE_INQUIRY_BASIC_DV1, - PROBE_INQUIRY_BASIC_DV2, - PROBE_DV_EXIT -} probe_action; - -typedef enum { - PROBE_INQUIRY_CKSUM = 0x01, - PROBE_SERIAL_CKSUM = 0x02, - PROBE_NO_ANNOUNCE = 0x04 -} probe_flags; - -typedef struct { - TAILQ_HEAD(, ccb_hdr) request_ccbs; - probe_action action; - union ccb saved_ccb; - probe_flags flags; - MD5_CTX context; - u_int8_t digest[16]; -} probe_softc; - static void xpt_scan_lun(struct cam_periph *periph, struct cam_path *path, cam_flags flags, union ccb *request_ccb) @@ -5545,11 +5014,7 @@ } if ((old_periph = cam_periph_find(path, "probe")) != NULL) { - probe_softc *softc; - - softc = (probe_softc *)old_periph->softc; - TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, - periph_links.tqe); + probe_insert_ccbq(old_periph, &request_ccb->ccb_h); } else { status = cam_periph_alloc(proberegister, NULL, probecleanup, probestart, "probe", @@ -5574,773 +5039,6 @@ free(done_ccb, M_TEMP); } -static cam_status -proberegister(struct cam_periph *periph, void *arg) -{ - union ccb *request_ccb; /* CCB representing the probe request */ - cam_status status; - probe_softc *softc; - - request_ccb = (union ccb *)arg; - if (periph == NULL) { - printf("proberegister: periph was NULL!!\n"); - return(CAM_REQ_CMP_ERR); - } - - if (request_ccb == NULL) { - printf("proberegister: no probe CCB, " - "can't register device\n"); - return(CAM_REQ_CMP_ERR); - } - - softc = (probe_softc *)malloc(sizeof(*softc), M_TEMP, M_NOWAIT); - - if (softc == NULL) { - printf("proberegister: Unable to probe new device. " - "Unable to allocate softc\n"); - return(CAM_REQ_CMP_ERR); - } - TAILQ_INIT(&softc->request_ccbs); - TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, - periph_links.tqe); - softc->flags = 0; - periph->softc = softc; - status = cam_periph_acquire(periph); - if (status != CAM_REQ_CMP) { - return (status); - } - - - /* - * Ensure we've waited at least a bus settle - * delay before attempting to probe the device. - * For HBAs that don't do bus resets, this won't make a difference. - */ - cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, - scsi_delay); - probeschedule(periph); - return(CAM_REQ_CMP); -} - -static void -probeschedule(struct cam_periph *periph) -{ - struct ccb_pathinq cpi; - union ccb *ccb; - probe_softc *softc; - - softc = (probe_softc *)periph->softc; - ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs); - - xpt_setup_ccb(&cpi.ccb_h, periph->path, /*priority*/1); - cpi.ccb_h.func_code = XPT_PATH_INQ; - xpt_action((union ccb *)&cpi); - - /* - * If a device has gone away and another device, or the same one, - * is back in the same place, it should have a unit attention - * condition pending. It will not report the unit attention in - * response to an inquiry, which may leave invalid transfer - * negotiations in effect. The TUR will reveal the unit attention - * condition. Only send the TUR for lun 0, since some devices - * will get confused by commands other than inquiry to non-existent - * luns. If you think a device has gone away start your scan from - * lun 0. This will insure that any bogus transfer settings are - * invalidated. - * - * If we haven't seen the device before and the controller supports - * some kind of transfer negotiation, negotiate with the first - * sent command if no bus reset was performed at startup. This - * ensures that the device is not confused by transfer negotiation - * settings left over by loader or BIOS action. - */ - if (((ccb->ccb_h.path->device->flags & CAM_DEV_UNCONFIGURED) == 0) - && (ccb->ccb_h.target_lun == 0)) { - softc->action = PROBE_TUR; - } else if ((cpi.hba_inquiry & (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) != 0 - && (cpi.hba_misc & PIM_NOBUSRESET) != 0) { - proberequestdefaultnegotiation(periph); - softc->action = PROBE_INQUIRY; - } else { - softc->action = PROBE_INQUIRY; - } - - if (ccb->crcn.flags & CAM_EXPECT_INQ_CHANGE) - softc->flags |= PROBE_NO_ANNOUNCE; - else - softc->flags &= ~PROBE_NO_ANNOUNCE; - - xpt_schedule(periph, ccb->ccb_h.pinfo.priority); -} - -static void -probestart(struct cam_periph *periph, union ccb *start_ccb) -{ - /* Probe the device that our peripheral driver points to */ - struct ccb_scsiio *csio; - probe_softc *softc; - - CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n")); - - softc = (probe_softc *)periph->softc; - csio = &start_ccb->csio; - - switch (softc->action) { - case PROBE_TUR: - case PROBE_TUR_FOR_NEGOTIATION: - case PROBE_DV_EXIT: - { - scsi_test_unit_ready(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - SSD_FULL_SIZE, - /*timeout*/60000); - break; - } - case PROBE_INQUIRY: - case PROBE_FULL_INQUIRY: - case PROBE_INQUIRY_BASIC_DV1: - case PROBE_INQUIRY_BASIC_DV2: - { - u_int inquiry_len; - struct scsi_inquiry_data *inq_buf; - - inq_buf = &periph->path->device->inq_data; - - /* - * If the device is currently configured, we calculate an - * MD5 checksum of the inquiry data, and if the serial number - * length is greater than 0, add the serial number data - * into the checksum as well. Once the inquiry and the - * serial number check finish, we attempt to figure out - * whether we still have the same device. - */ - if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { - - MD5Init(&softc->context); - MD5Update(&softc->context, (unsigned char *)inq_buf, - sizeof(struct scsi_inquiry_data)); - softc->flags |= PROBE_INQUIRY_CKSUM; - if (periph->path->device->serial_num_len > 0) { - MD5Update(&softc->context, - periph->path->device->serial_num, - periph->path->device->serial_num_len); - softc->flags |= PROBE_SERIAL_CKSUM; - } - MD5Final(softc->digest, &softc->context); - } - - if (softc->action == PROBE_INQUIRY) - inquiry_len = SHORT_INQUIRY_LENGTH; - else - inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf); - - /* - * Some parallel SCSI devices fail to send an - * ignore wide residue message when dealing with - * odd length inquiry requests. Round up to be - * safe. - */ - inquiry_len = roundup2(inquiry_len, 2); - - if (softc->action == PROBE_INQUIRY_BASIC_DV1 - || softc->action == PROBE_INQUIRY_BASIC_DV2) { - inq_buf = malloc(inquiry_len, M_TEMP, M_NOWAIT); - } - if (inq_buf == NULL) { - xpt_print(periph->path, "malloc failure- skipping Basic" - "Domain Validation\n"); - softc->action = PROBE_DV_EXIT; - scsi_test_unit_ready(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - SSD_FULL_SIZE, - /*timeout*/60000); - break; - } - scsi_inquiry(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - (u_int8_t *)inq_buf, - inquiry_len, - /*evpd*/FALSE, - /*page_code*/0, - SSD_MIN_SIZE, - /*timeout*/60 * 1000); - break; - } - case PROBE_MODE_SENSE: - { - void *mode_buf; - int mode_buf_len; - - mode_buf_len = sizeof(struct scsi_mode_header_6) - + sizeof(struct scsi_mode_blk_desc) - + sizeof(struct scsi_control_page); - mode_buf = malloc(mode_buf_len, M_TEMP, M_NOWAIT); - if (mode_buf != NULL) { - scsi_mode_sense(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - /*dbd*/FALSE, - SMS_PAGE_CTRL_CURRENT, - SMS_CONTROL_MODE_PAGE, - mode_buf, - mode_buf_len, - SSD_FULL_SIZE, - /*timeout*/60000); - break; - } - xpt_print(periph->path, "Unable to mode sense control page - " - "malloc failure\n"); - softc->action = PROBE_SERIAL_NUM; - } - /* FALLTHROUGH */ - case PROBE_SERIAL_NUM: - { - struct scsi_vpd_unit_serial_number *serial_buf; - struct cam_ed* device; - - serial_buf = NULL; - device = periph->path->device; - device->serial_num = NULL; - device->serial_num_len = 0; - - if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0) - serial_buf = (struct scsi_vpd_unit_serial_number *) - malloc(sizeof(*serial_buf), M_TEMP, - M_NOWAIT | M_ZERO); - - if (serial_buf != NULL) { - scsi_inquiry(csio, - /*retries*/4, - probedone, - MSG_SIMPLE_Q_TAG, - (u_int8_t *)serial_buf, - sizeof(*serial_buf), - /*evpd*/TRUE, - SVPD_UNIT_SERIAL_NUMBER, - SSD_MIN_SIZE, - /*timeout*/60 * 1000); - break; - } - /* - * We'll have to do without, let our probedone - * routine finish up for us. - */ - start_ccb->csio.data_ptr = NULL; - probedone(periph, start_ccb); - return; - } - } - xpt_action(start_ccb); -} - -static void -proberequestdefaultnegotiation(struct cam_periph *periph) -{ - struct ccb_trans_settings cts; - - xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); - cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; - cts.type = CTS_TYPE_USER_SETTINGS; - xpt_action((union ccb *)&cts); - if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - return; - } - cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; - cts.type = CTS_TYPE_CURRENT_SETTINGS; - xpt_action((union ccb *)&cts); -} - -/* - * Backoff Negotiation Code- only pertinent for SPI devices. - */ -static int -proberequestbackoff(struct cam_periph *periph, struct cam_ed *device) -{ - struct ccb_trans_settings cts; - struct ccb_trans_settings_spi *spi; - - memset(&cts, 0, sizeof (cts)); - xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1); - cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; - cts.type = CTS_TYPE_CURRENT_SETTINGS; - xpt_action((union ccb *)&cts); - if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - if (bootverbose) { - xpt_print(periph->path, - "failed to get current device settings\n"); - } - return (0); - } - if (cts.transport != XPORT_SPI) { - if (bootverbose) { - xpt_print(periph->path, "not SPI transport\n"); - } - return (0); - } - spi = &cts.xport_specific.spi; - - /* - * We cannot renegotiate sync rate if we don't have one. - */ - if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { - if (bootverbose) { - xpt_print(periph->path, "no sync rate known\n"); - } - return (0); - } - - /* - * We'll assert that we don't have to touch PPR options- the - * SIM will see what we do with period and offset and adjust - * the PPR options as appropriate. - */ - - /* - * A sync rate with unknown or zero offset is nonsensical. - * A sync period of zero means Async. - */ - if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0 - || spi->sync_offset == 0 || spi->sync_period == 0) { - if (bootverbose) { - xpt_print(periph->path, "no sync rate available\n"); - } - return (0); - } - - if (device->flags & CAM_DEV_DV_HIT_BOTTOM) { - CAM_DEBUG(periph->path, CAM_DEBUG_INFO, - ("hit async: giving up on DV\n")); - return (0); - } - - - /* - * Jump sync_period up by one, but stop at 5MHz and fall back to Async. - * We don't try to remember 'last' settings to see if the SIM actually - * gets into the speed we want to set. We check on the SIM telling - * us that a requested speed is bad, but otherwise don't try and - * check the speed due to the asynchronous and handshake nature - * of speed setting. - */ >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704232257.l3NMvx9n072058>