PERFORCE change 49774 for review
Scott Long
scottl at FreeBSD.org
Sat Mar 27 00:30:36 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=49774
Change 49774 by scottl at scottl-junior-camlock on 2004/03/27 00:30:33
Mechanical split of the lun probe and probe periph code into it's
own file. The XPT is still painfully SCSI-aware and will require
a lot of work, but this is a first step.
Affected files ...
.. //depot/projects/scottl-camlock/src/sys/cam/cam_probe.c#1 add
.. //depot/projects/scottl-camlock/src/sys/cam/cam_probe.h#1 add
.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#2 edit
.. //depot/projects/scottl-camlock/src/sys/modules/cam/Makefile#2 edit
Differences ...
==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#2 (text+ko) ====
@@ -55,28 +55,13 @@
#include <cam/cam_xpt_sim.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
+#include <cam/cam_probe.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_pass.h>
#include "opt_cam.h"
-/* Datastructures internal to the xpt layer */
-
-/*
- * Definition of an async handler callback block. These are used to add
- * SIMs and peripherals to the async callback lists.
- */
-struct async_node {
- SLIST_ENTRY(async_node) links;
- u_int32_t event_enable; /* Async Event enables */
- void (*callback)(void *arg, u_int32_t code,
- struct cam_path *path, void *args);
- void *callback_arg;
-};
-
-SLIST_HEAD(async_list, async_node);
-SLIST_HEAD(periph_list, cam_periph);
static STAILQ_HEAD(highpowerlist, ccb_hdr) highpowerq;
/*
@@ -90,120 +75,6 @@
/* number of high powered commands that can go through right now */
static int num_highpower = CAM_MAX_HIGHPOWER;
-/*
- * 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;
- 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 */
-#ifdef CAM_NEW_TRAN_CODE
- cam_proto protocol;
- u_int protocol_version;
- cam_xport transport;
- u_int transport_version;
-#endif /* CAM_NEW_TRAN_CODE */
- 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
- u_int32_t tag_delay_count;
-#define CAM_TAG_DELAY_COUNT 5
- u_int32_t refcount;
- struct callout_handle c_handle;
-};
-
-/*
- * 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;
-};
-
-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
- u_int mintags;
- u_int maxtags;
-};
-#define CAM_SCSI2_MAXLUN 8
-
typedef enum {
XPT_FLAG_OPEN = 0x01
} xpt_flags;
@@ -613,22 +484,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;
@@ -697,15 +559,6 @@
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 void xpt_release_path(struct cam_path *path);
-
static void xpt_async_bcast(struct async_list *async_head,
u_int32_t async_code,
struct cam_path *path,
@@ -743,10 +596,6 @@
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);
@@ -812,14 +661,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 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);
#ifdef CAM_NEW_TRAN_CODE
static void xpt_devise_transport(struct cam_path *path);
#endif /* CAM_NEW_TRAN_CODE */
@@ -923,12 +764,6 @@
}
static void
-probe_periph_init()
-{
-}
-
-
-static void
xptdone(struct cam_periph *periph, union ccb *done_ccb)
{
/* Caller will release the CCB */
@@ -4012,7 +3847,7 @@
return (status);
}
-static cam_status
+cam_status
xpt_compile_path(struct cam_path *new_path, struct cam_periph *perph,
path_id_t path_id, target_id_t target_id, lun_id_t lun_id)
{
@@ -4086,7 +3921,7 @@
return (status);
}
-static void
+void
xpt_release_path(struct cam_path *path)
{
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_release_path\n"));
@@ -5379,682 +5214,7 @@
}
}
-typedef enum {
- PROBE_TUR,
- PROBE_INQUIRY,
- PROBE_FULL_INQUIRY,
- PROBE_MODE_SENSE,
- PROBE_SERIAL_NUM,
- PROBE_TUR_FOR_NEGOTIATION
-} 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)
-{
- struct ccb_pathinq cpi;
- cam_status status;
- struct cam_path *new_path;
- struct cam_periph *old_periph;
- int s;
-
- CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
- ("xpt_scan_lun\n"));
-
- xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
- cpi.ccb_h.func_code = XPT_PATH_INQ;
- xpt_action((union ccb *)&cpi);
-
- if (cpi.ccb_h.status != CAM_REQ_CMP) {
- if (request_ccb != NULL) {
- request_ccb->ccb_h.status = cpi.ccb_h.status;
- xpt_done(request_ccb);
- }
- return;
- }
-
- if ((cpi.hba_misc & PIM_NOINITIATOR) != 0) {
- /*
- * Can't scan the bus on an adapter that
- * cannot perform the initiator role.
- */
- if (request_ccb != NULL) {
- request_ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(request_ccb);
- }
- return;
- }
-
- if (request_ccb == NULL) {
- request_ccb = malloc(sizeof(union ccb), M_TEMP, M_NOWAIT);
- if (request_ccb == NULL) {
- xpt_print_path(path);
- printf("xpt_scan_lun: can't allocate CCB, can't "
- "continue\n");
- return;
- }
- new_path = malloc(sizeof(*new_path), M_TEMP, M_NOWAIT);
- if (new_path == NULL) {
- xpt_print_path(path);
- printf("xpt_scan_lun: can't allocate path, can't "
- "continue\n");
- free(request_ccb, M_TEMP);
- return;
- }
- status = xpt_compile_path(new_path, xpt_periph,
- path->bus->path_id,
- path->target->target_id,
- path->device->lun_id);
-
- if (status != CAM_REQ_CMP) {
- xpt_print_path(path);
- printf("xpt_scan_lun: can't compile path, can't "
- "continue\n");
- free(request_ccb, M_TEMP);
- free(new_path, M_TEMP);
- return;
- }
- xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1);
- request_ccb->ccb_h.cbfcnp = xptscandone;
- request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
- request_ccb->crcn.flags = flags;
- }
-
- s = splsoftcam();
- 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);
- } else {
- status = cam_periph_alloc(proberegister, NULL, probecleanup,
- probestart, "probe",
- CAM_PERIPH_BIO,
- request_ccb->ccb_h.path, NULL, 0,
- request_ccb);
-
- if (status != CAM_REQ_CMP) {
- xpt_print_path(path);
- printf("xpt_scan_lun: cam_alloc_periph returned an "
- "error, can't continue probe\n");
- request_ccb->ccb_h.status = status;
- xpt_done(request_ccb);
- }
- }
- splx(s);
-}
-
-static void
-xptscandone(struct cam_periph *periph, union ccb *done_ccb)
-{
- xpt_release_path(done_ccb->ccb_h.path);
- free(done_ccb->ccb_h.path, M_TEMP);
- free(done_ccb, M_TEMP);
-}
-
-static cam_status
-proberegister(struct cam_periph *periph, void *arg)
-{
- union ccb *request_ccb; /* CCB representing the probe request */
- 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;
- cam_periph_acquire(periph);
- /*
- * 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:
- {
- 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:
- {
- 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 = inq_buf->additional_length + 4;
-
- 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_path(periph->path);
- printf("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;
-#ifdef CAM_NEW_TRAN_CODE
- cts.type = CTS_TYPE_USER_SETTINGS;
-#else /* CAM_NEW_TRAN_CODE */
- cts.flags = CCB_TRANS_USER_SETTINGS;
-#endif /* CAM_NEW_TRAN_CODE */
- xpt_action((union ccb *)&cts);
- cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
-#ifdef CAM_NEW_TRAN_CODE
- cts.type = CTS_TYPE_CURRENT_SETTINGS;
-#else /* CAM_NEW_TRAN_CODE */
- cts.flags &= ~CCB_TRANS_USER_SETTINGS;
- cts.flags |= CCB_TRANS_CURRENT_SETTINGS;
-#endif /* CAM_NEW_TRAN_CODE */
- xpt_action((union ccb *)&cts);
-}
-
-static void
-probedone(struct cam_periph *periph, union ccb *done_ccb)
-{
- probe_softc *softc;
- struct cam_path *path;
- u_int32_t priority;
-
- CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
-
- softc = (probe_softc *)periph->softc;
- path = done_ccb->ccb_h.path;
- priority = done_ccb->ccb_h.pinfo.priority;
-
- switch (softc->action) {
- case PROBE_TUR:
- {
- if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
-
- if (cam_periph_error(done_ccb, 0,
- SF_NO_PRINT, NULL) == ERESTART)
- return;
- else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
- /* Don't wedge the queue */
- xpt_release_devq(done_ccb->ccb_h.path,
- /*count*/1,
- /*run_queue*/TRUE);
- }
- softc->action = PROBE_INQUIRY;
- xpt_release_ccb(done_ccb);
- xpt_schedule(periph, priority);
- return;
- }
- case PROBE_INQUIRY:
- case PROBE_FULL_INQUIRY:
- {
- if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
- struct scsi_inquiry_data *inq_buf;
- u_int8_t periph_qual;
-
- path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
- inq_buf = &path->device->inq_data;
-
- periph_qual = SID_QUAL(inq_buf);
-
- switch(periph_qual) {
- case SID_QUAL_LU_CONNECTED:
- {
- u_int8_t alen;
-
- /*
- * We conservatively request only
- * SHORT_INQUIRY_LEN bytes of inquiry
- * information during our first try
- * at sending an INQUIRY. If the device
- * has more information to give,
- * perform a second request specifying
- * the amount of information the device
- * is willing to give.
- */
- alen = inq_buf->additional_length;
- if (softc->action == PROBE_INQUIRY
- && alen > (SHORT_INQUIRY_LENGTH - 4)) {
- softc->action = PROBE_FULL_INQUIRY;
- xpt_release_ccb(done_ccb);
- xpt_schedule(periph, priority);
- return;
- }
-
- xpt_find_quirk(path->device);
-
-#ifdef CAM_NEW_TRAN_CODE
- xpt_devise_transport(path);
-#endif /* CAM_NEW_TRAN_CODE */
- if ((inq_buf->flags & SID_CmdQue) != 0)
- softc->action = PROBE_MODE_SENSE;
- else
- softc->action = PROBE_SERIAL_NUM;
-
- path->device->flags &= ~CAM_DEV_UNCONFIGURED;
-
- xpt_release_ccb(done_ccb);
- xpt_schedule(periph, priority);
- return;
- }
- default:
- break;
- }
- } else if (cam_periph_error(done_ccb, 0,
- done_ccb->ccb_h.target_lun > 0
- ? SF_RETRY_UA|SF_QUIET_IR
- : SF_RETRY_UA,
- &softc->saved_ccb) == ERESTART) {
- return;
- } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- /* Don't wedge the queue */
- xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
- /*run_queue*/TRUE);
- }
- /*
- * If we get to this point, we got an error status back
- * from the inquiry and the error status doesn't require
- * automatically retrying the command. Therefore, the
- * inquiry failed. If we had inquiry information before
- * for this device, but this latest inquiry command failed,
- * the device has probably gone away. If this device isn't
- * already marked unconfigured, notify the peripheral
- * drivers that this device is no more.
- */
- if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
- /* Send the async notification. */
- xpt_async(AC_LOST_DEVICE, path, NULL);
-
- xpt_release_ccb(done_ccb);
- break;
- }
- case PROBE_MODE_SENSE:
- {
- struct ccb_scsiio *csio;
- struct scsi_mode_header_6 *mode_hdr;
-
- csio = &done_ccb->csio;
- mode_hdr = (struct scsi_mode_header_6 *)csio->data_ptr;
- if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
- struct scsi_control_page *page;
- u_int8_t *offset;
-
- offset = ((u_int8_t *)&mode_hdr[1])
- + mode_hdr->blk_desc_len;
- page = (struct scsi_control_page *)offset;
- path->device->queue_flags = page->queue_flags;
- } else if (cam_periph_error(done_ccb, 0,
- SF_RETRY_UA|SF_NO_PRINT,
- &softc->saved_ccb) == ERESTART) {
- return;
- } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- /* Don't wedge the queue */
- xpt_release_devq(done_ccb->ccb_h.path,
- /*count*/1, /*run_queue*/TRUE);
- }
- xpt_release_ccb(done_ccb);
- free(mode_hdr, M_TEMP);
- softc->action = PROBE_SERIAL_NUM;
- xpt_schedule(periph, priority);
- return;
- }
- case PROBE_SERIAL_NUM:
- {
- struct ccb_scsiio *csio;
- struct scsi_vpd_unit_serial_number *serial_buf;
- u_int32_t priority;
- int changed;
- int have_serialnum;
-
- changed = 1;
- have_serialnum = 0;
- csio = &done_ccb->csio;
- priority = done_ccb->ccb_h.pinfo.priority;
- serial_buf =
- (struct scsi_vpd_unit_serial_number *)csio->data_ptr;
-
- /* Clean up from previous instance of this device */
- if (path->device->serial_num != NULL) {
- free(path->device->serial_num, M_DEVBUF);
- path->device->serial_num = NULL;
- path->device->serial_num_len = 0;
- }
-
- if (serial_buf == NULL) {
- /*
- * Don't process the command as it was never sent
- */
- } else if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP
- && (serial_buf->length > 0)) {
-
- have_serialnum = 1;
- path->device->serial_num =
- (u_int8_t *)malloc((serial_buf->length + 1),
- M_DEVBUF, M_NOWAIT);
- if (path->device->serial_num != NULL) {
- bcopy(serial_buf->serial_num,
- path->device->serial_num,
- serial_buf->length);
- path->device->serial_num_len =
- serial_buf->length;
- path->device->serial_num[serial_buf->length]
- = '\0';
- }
- } else if (cam_periph_error(done_ccb, 0,
- SF_RETRY_UA|SF_NO_PRINT,
- &softc->saved_ccb) == ERESTART) {
- return;
- } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- /* Don't wedge the queue */
- xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
- /*run_queue*/TRUE);
- }
-
- /*
- * Let's see if we have seen this device before.
- */
- if ((softc->flags & PROBE_INQUIRY_CKSUM) != 0) {
- MD5_CTX context;
- u_int8_t digest[16];
-
- MD5Init(&context);
-
- MD5Update(&context,
- (unsigned char *)&path->device->inq_data,
- sizeof(struct scsi_inquiry_data));
-
- if (have_serialnum)
- MD5Update(&context, serial_buf->serial_num,
- serial_buf->length);
-
- MD5Final(digest, &context);
- if (bcmp(softc->digest, digest, 16) == 0)
- changed = 0;
-
- /*
- * XXX Do we need to do a TUR in order to ensure
- * that the device really hasn't changed???
- */
- if ((changed != 0)
- && ((softc->flags & PROBE_NO_ANNOUNCE) == 0))
- xpt_async(AC_LOST_DEVICE, path, NULL);
- }
- if (serial_buf != NULL)
- free(serial_buf, M_TEMP);
-
- if (changed != 0) {
- /*
- * Now that we have all the necessary
- * information to safely perform transfer
- * negotiations... Controllers don't perform
- * any negotiation or tagged queuing until
- * after the first XPT_SET_TRAN_SETTINGS ccb is
- * received. So, on a new device, just retreive
- * the user settings, and set them as the current
- * settings to set the device up.
- */
- proberequestdefaultnegotiation(periph);
- xpt_release_ccb(done_ccb);
-
- /*
- * Perform a TUR to allow the controller to
- * perform any necessary transfer negotiation.
- */
- softc->action = PROBE_TUR_FOR_NEGOTIATION;
- xpt_schedule(periph, priority);
- return;
- }
- xpt_release_ccb(done_ccb);
- break;
- }
- case PROBE_TUR_FOR_NEGOTIATION:
- if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- /* Don't wedge the queue */
- xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
- /*run_queue*/TRUE);
- }
-
- path->device->flags &= ~CAM_DEV_UNCONFIGURED;
-
- if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) {
- /* Inform the XPT that a new device has been found */
- done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
- xpt_action(done_ccb);
-
- xpt_async(AC_FOUND_DEVICE, xpt_periph->path, done_ccb);
- }
- xpt_release_ccb(done_ccb);
- break;
- }
- done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
- TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe);
- done_ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(done_ccb);
- if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
- cam_periph_invalidate(periph);
- cam_periph_release(periph);
- } else {
- probeschedule(periph);
- }
-}
-
-static void
-probecleanup(struct cam_periph *periph)
-{
- free(periph->softc, M_TEMP);
-}
-
-static void
+void
xpt_find_quirk(struct cam_ed *device)
{
caddr_t match;
==== //depot/projects/scottl-camlock/src/sys/modules/cam/Makefile#2 (text+ko) ====
@@ -19,6 +19,7 @@
SRCS+= device_if.h bus_if.h vnode_if.h
SRCS+= cam.c cam_periph.c cam_queue.c
SRCS+= cam_sim.c cam_xpt.c
+SRCS+= scsi_probe.c
SRCS+= scsi_all.c scsi_cd.c scsi_ch.c
SRCS+= scsi_da.c
SRCS+= scsi_pass.c
More information about the p4-projects
mailing list