PERFORCE change 160378 for review

Scott Long scottl at FreeBSD.org
Wed Apr 8 07:13:12 PDT 2009


http://perforce.freebsd.org/chv.cgi?CH=160378

Change 160378 by scottl at scottl-deimos on 2009/04/08 14:13:08

	Separate xpt_action into a transport-specific action, and bring some
	helper functions over with it.  Also create a async notification
	vector.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#83 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.h#15 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.c#9 edit

Differences ...

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

@@ -204,11 +204,6 @@
 					u_int32_t async_code,
 					struct cam_path *path,
 					void *async_arg);
-static void		xpt_dev_async(u_int32_t async_code,
-				      struct cam_eb *bus,
-				      struct cam_et *target,
-				      struct cam_ed *device,
-				      void *async_arg);
 static path_id_t xptnextfreepathid(void);
 static path_id_t xptpathid(const char *sim_name, int sim_unit, int sim_bus);
 static union ccb *xpt_get_ccb(struct cam_ed *device);
@@ -286,10 +281,6 @@
 static xpt_busfunc_t	xptsetasyncbusfunc;
 static cam_status	xptregister(struct cam_periph *periph,
 				    void *arg);
-static void	 xpt_set_transfer_settings(struct ccb_trans_settings *cts,
-					   struct cam_ed *device,
-					   int async_update);
-static void	 xpt_toggle_tags(struct cam_path *path);
 static void	 xpt_start_tags(struct cam_path *path);
 static __inline int xpt_schedule_dev_allocq(struct cam_eb *bus,
 					    struct cam_ed *dev);
@@ -2415,49 +2406,17 @@
 	CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_action\n"));
 
 	start_ccb->ccb_h.status = CAM_REQ_INPROG;
+	(*(start_ccb->ccb_h.path->bus->xport->xpt_action_func))(start_ccb);
+}
 
-	switch (start_ccb->ccb_h.func_code) {
-	case XPT_SCSI_IO:
-	{
-		struct cam_ed *device;
-#ifdef CAMDEBUG
-		char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
-		struct cam_path *path;
+void
+xpt_action_default(union ccb *start_ccb)
+{
 
-		path = start_ccb->ccb_h.path;
-#endif
+	CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_action_default\n"));
 
-		/*
-		 * For the sake of compatibility with SCSI-1
-		 * devices that may not understand the identify
-		 * message, we include lun information in the
-		 * second byte of all commands.  SCSI-1 specifies
-		 * that luns are a 3 bit value and reserves only 3
-		 * bits for lun information in the CDB.  Later
-		 * revisions of the SCSI spec allow for more than 8
-		 * luns, but have deprecated lun information in the
-		 * CDB.  So, if the lun won't fit, we must omit.
-		 *
-		 * Also be aware that during initial probing for devices,
-		 * the inquiry information is unknown but initialized to 0.
-		 * This means that this code will be exercised while probing
-		 * devices with an ANSI revision greater than 2.
-		 */
-		device = start_ccb->ccb_h.path->device;
-		if (device->protocol_version <= SCSI_REV_2
-		 && start_ccb->ccb_h.target_lun < 8
-		 && (start_ccb->ccb_h.flags & CAM_CDB_POINTER) == 0) {
 
-			start_ccb->csio.cdb_io.cdb_bytes[1] |=
-			    start_ccb->ccb_h.target_lun << 5;
-		}
-		start_ccb->csio.scsi_status = SCSI_STATUS_OK;
-		CAM_DEBUG(path, CAM_DEBUG_CDB,("%s. CDB: %s\n",
-			  scsi_op_desc(start_ccb->csio.cdb_io.cdb_bytes[0],
-			  	       &path->device->inq_data),
-			  scsi_cdb_string(start_ccb->csio.cdb_io.cdb_bytes,
-					  cdb_str, sizeof(cdb_str))));
-	}
+	switch (start_ccb->ccb_h.func_code) {
 	/* FALLTHROUGH */
 	case XPT_TARGET_IO:
 	case XPT_CONT_TARGET_IO:
@@ -2481,13 +2440,6 @@
 			xpt_run_dev_sendq(path->bus);
 		break;
 	}
-	case XPT_SET_TRAN_SETTINGS:
-	{
-		xpt_set_transfer_settings(&start_ccb->cts,
-					  start_ccb->ccb_h.path->device,
-					  /*async_update*/FALSE);
-		break;
-	}
 	case XPT_CALC_GEOMETRY:
 	{
 		struct cam_sim *sim;
@@ -2573,7 +2525,6 @@
 	case XPT_EN_LUN:
 	case XPT_IMMED_NOTIFY:
 	case XPT_NOTIFY_ACK:
-	case XPT_GET_TRAN_SETTINGS:
 	case XPT_RESET_BUS:
 	{
 		struct cam_sim *sim;
@@ -2938,14 +2889,6 @@
 		start_ccb->ccb_h.status = CAM_REQ_CMP;
 		break;
 	}
-	case XPT_SCAN_BUS:
-		xpt_scan_bus(start_ccb->ccb_h.path->periph, start_ccb);
-		break;
-	case XPT_SCAN_LUN:
-		xpt_scan_lun(start_ccb->ccb_h.path->periph,
-			     start_ccb->ccb_h.path, start_ccb->crcn.flags,
-			     start_ccb);
-		break;
 	case XPT_DEBUG: {
 #ifdef CAMDEBUG
 #ifdef CAM_DEBUG_DELAY
@@ -3947,8 +3890,9 @@
 			 && device->lun_id != CAM_LUN_WILDCARD)
 				continue;
 
-			xpt_dev_async(async_code, bus, target,
-				      device, async_arg);
+			(*(bus->xport->xpt_dev_async_func))(async_code, bus,
+							    target, device,
+							    async_arg);
 
 			xpt_async_bcast(&device->asyncs, async_code,
 					path, async_arg);
@@ -3988,70 +3932,6 @@
 	}
 }
 
-/*
- * Handle any per-device event notifications that require action by the XPT.
- */
-static void
-xpt_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
-	      struct cam_ed *device, void *async_arg)
-{
-	cam_status status;
-	struct cam_path newpath;
-
-	/*
-	 * We only need to handle events for real devices.
-	 */
-	if (target->target_id == CAM_TARGET_WILDCARD
-	 || device->lun_id == CAM_LUN_WILDCARD)
-		return;
-
-	/*
-	 * We need our own path with wildcards expanded to
-	 * handle certain types of events.
-	 */
-	if ((async_code == AC_SENT_BDR)
-	 || (async_code == AC_BUS_RESET)
-	 || (async_code == AC_INQ_CHANGED))
-		status = xpt_compile_path(&newpath, NULL,
-					  bus->path_id,
-					  target->target_id,
-					  device->lun_id);
-	else
-		status = CAM_REQ_CMP_ERR;
-
-	if (status == CAM_REQ_CMP) {
-
-		/*
-		 * Allow transfer negotiation to occur in a
-		 * tag free environment.
-		 */
-		if (async_code == AC_SENT_BDR
-		 || async_code == AC_BUS_RESET)
-			xpt_toggle_tags(&newpath);
-
-		if (async_code == AC_INQ_CHANGED) {
-			/*
-			 * We've sent a start unit command, or
-			 * something similar to a device that
-			 * may have caused its inquiry data to
-			 * change. So we re-scan the device to
-			 * refresh the inquiry data for it.
-			 */
-			xpt_scan_lun(newpath.periph, &newpath,
-				     CAM_EXPECT_INQ_CHANGE, NULL);
-		}
-		xpt_release_path(&newpath);
-	} else if (async_code == AC_LOST_DEVICE) {
-		device->flags |= CAM_DEV_UNCONFIGURED;
-	} else if (async_code == AC_TRANSFER_NEG) {
-		struct ccb_trans_settings *settings;
-
-		settings = (struct ccb_trans_settings *)async_arg;
-		xpt_set_transfer_settings(settings, device,
-					  /*async_update*/TRUE);
-	}
-}
-
 u_int32_t
 xpt_freeze_devq(struct cam_path *path, u_int count)
 {
@@ -4526,326 +4406,6 @@
 }
 
 static void
-xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
-			  int async_update)
-{
-	struct	ccb_pathinq cpi;
-	struct	ccb_trans_settings cur_cts;
-	struct	ccb_trans_settings_scsi *scsi;
-	struct	ccb_trans_settings_scsi *cur_scsi;
-	struct	cam_sim *sim;
-	struct	scsi_inquiry_data *inq_data;
-
-	if (device == NULL) {
-		cts->ccb_h.status = CAM_PATH_INVALID;
-		xpt_done((union ccb *)cts);
-		return;
-	}
-
-	if (cts->protocol == PROTO_UNKNOWN
-	 || cts->protocol == PROTO_UNSPECIFIED) {
-		cts->protocol = device->protocol;
-		cts->protocol_version = device->protocol_version;
-	}
-
-	if (cts->protocol_version == PROTO_VERSION_UNKNOWN
-	 || cts->protocol_version == PROTO_VERSION_UNSPECIFIED)
-		cts->protocol_version = device->protocol_version;
-
-	if (cts->protocol != device->protocol) {
-		xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n",
-		       cts->protocol, device->protocol);
-		cts->protocol = device->protocol;
-	}
-
-	if (cts->protocol_version > device->protocol_version) {
-		if (bootverbose) {
-			xpt_print(cts->ccb_h.path, "Down reving Protocol "
-			    "Version from %d to %d?\n", cts->protocol_version,
-			    device->protocol_version);
-		}
-		cts->protocol_version = device->protocol_version;
-	}
-
-	if (cts->transport == XPORT_UNKNOWN
-	 || cts->transport == XPORT_UNSPECIFIED) {
-		cts->transport = device->transport;
-		cts->transport_version = device->transport_version;
-	}
-
-	if (cts->transport_version == XPORT_VERSION_UNKNOWN
-	 || cts->transport_version == XPORT_VERSION_UNSPECIFIED)
-		cts->transport_version = device->transport_version;
-
-	if (cts->transport != device->transport) {
-		xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n",
-		    cts->transport, device->transport);
-		cts->transport = device->transport;
-	}
-
-	if (cts->transport_version > device->transport_version) {
-		if (bootverbose) {
-			xpt_print(cts->ccb_h.path, "Down reving Transport "
-			    "Version from %d to %d?\n", cts->transport_version,
-			    device->transport_version);
-		}
-		cts->transport_version = device->transport_version;
-	}
-
-	sim = cts->ccb_h.path->bus->sim;
-
-	/*
-	 * Nothing more of interest to do unless
-	 * this is a device connected via the
-	 * SCSI protocol.
-	 */
-	if (cts->protocol != PROTO_SCSI) {
-		if (async_update == FALSE)
-			(*(sim->sim_action))(sim, (union ccb *)cts);
-		return;
-	}
-
-	inq_data = &device->inq_data;
-	scsi = &cts->proto_specific.scsi;
-	xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1);
-	cpi.ccb_h.func_code = XPT_PATH_INQ;
-	xpt_action((union ccb *)&cpi);
-
-	/* SCSI specific sanity checking */
-	if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0
-	 || (INQ_DATA_TQ_ENABLED(inq_data)) == 0
-	 || (device->queue_flags & SCP_QUEUE_DQUE) != 0
-	 || (device->mintags == 0)) {
-		/*
-		 * Can't tag on hardware that doesn't support tags,
-		 * doesn't have it enabled, or has broken tag support.
-		 */
-		scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
-	}
-
-	if (async_update == FALSE) {
-		/*
-		 * Perform sanity checking against what the
-		 * controller and device can do.
-		 */
-		xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1);
-		cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
-		cur_cts.type = cts->type;
-		xpt_action((union ccb *)&cur_cts);
-		if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
-			return;
-		}
-		cur_scsi = &cur_cts.proto_specific.scsi;
-		if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
-			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
-			scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB;
-		}
-		if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0)
-			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
-	}
-
-	/* SPI specific sanity checking */
-	if (cts->transport == XPORT_SPI && async_update == FALSE) {
-		u_int spi3caps;
-		struct ccb_trans_settings_spi *spi;
-		struct ccb_trans_settings_spi *cur_spi;
-
-		spi = &cts->xport_specific.spi;
-
-		cur_spi = &cur_cts.xport_specific.spi;
-
-		/* Fill in any gaps in what the user gave us */
-		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
-			spi->sync_period = cur_spi->sync_period;
-		if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
-			spi->sync_period = 0;
-		if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
-			spi->sync_offset = cur_spi->sync_offset;
-		if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
-			spi->sync_offset = 0;
-		if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
-			spi->ppr_options = cur_spi->ppr_options;
-		if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
-			spi->ppr_options = 0;
-		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
-			spi->bus_width = cur_spi->bus_width;
-		if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
-			spi->bus_width = 0;
-		if ((spi->valid & CTS_SPI_VALID_DISC) == 0) {
-			spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
-			spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB;
-		}
-		if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0)
-			spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
-		if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
-		  && (inq_data->flags & SID_Sync) == 0
-		  && cts->type == CTS_TYPE_CURRENT_SETTINGS)
-		 || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) {
-			/* Force async */
-			spi->sync_period = 0;
-			spi->sync_offset = 0;
-		}
-
-		switch (spi->bus_width) {
-		case MSG_EXT_WDTR_BUS_32_BIT:
-			if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
-			  || (inq_data->flags & SID_WBus32) != 0
-			  || cts->type == CTS_TYPE_USER_SETTINGS)
-			 && (cpi.hba_inquiry & PI_WIDE_32) != 0)
-				break;
-			/* Fall Through to 16-bit */
-		case MSG_EXT_WDTR_BUS_16_BIT:
-			if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
-			  || (inq_data->flags & SID_WBus16) != 0
-			  || cts->type == CTS_TYPE_USER_SETTINGS)
-			 && (cpi.hba_inquiry & PI_WIDE_16) != 0) {
-				spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
-				break;
-			}
-			/* Fall Through to 8-bit */
-		default: /* New bus width?? */
-		case MSG_EXT_WDTR_BUS_8_BIT:
-			/* All targets can do this */
-			spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
-			break;
-		}
-
-		spi3caps = cpi.xport_specific.spi.ppr_options;
-		if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
-		 && cts->type == CTS_TYPE_CURRENT_SETTINGS)
-			spi3caps &= inq_data->spi3data;
-
-		if ((spi3caps & SID_SPI_CLOCK_DT) == 0)
-			spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
-
-		if ((spi3caps & SID_SPI_IUS) == 0)
-			spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ;
-
-		if ((spi3caps & SID_SPI_QAS) == 0)
-			spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
-
-		/* No SPI Transfer settings are allowed unless we are wide */
-		if (spi->bus_width == 0)
-			spi->ppr_options = 0;
-
-		if ((spi->valid & CTS_SPI_VALID_DISC)
-		 && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) {
-			/*
-			 * Can't tag queue without disconnection.
-			 */
-			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
-			scsi->valid |= CTS_SCSI_VALID_TQ;
-		}
-
-		/*
-		 * If we are currently performing tagged transactions to
-		 * this device and want to change its negotiation parameters,
-		 * go non-tagged for a bit to give the controller a chance to
-		 * negotiate unhampered by tag messages.
-		 */
-		if (cts->type == CTS_TYPE_CURRENT_SETTINGS
-		 && (device->inq_flags & SID_CmdQue) != 0
-		 && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
-		 && (spi->flags & (CTS_SPI_VALID_SYNC_RATE|
-				   CTS_SPI_VALID_SYNC_OFFSET|
-				   CTS_SPI_VALID_BUS_WIDTH)) != 0)
-			xpt_toggle_tags(cts->ccb_h.path);
-	}
-
-	if (cts->type == CTS_TYPE_CURRENT_SETTINGS
-	 && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
-		int device_tagenb;
-
-		/*
-		 * If we are transitioning from tags to no-tags or
-		 * vice-versa, we need to carefully freeze and restart
-		 * the queue so that we don't overlap tagged and non-tagged
-		 * commands.  We also temporarily stop tags if there is
-		 * a change in transfer negotiation settings to allow
-		 * "tag-less" negotiation.
-		 */
-		if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
-		 || (device->inq_flags & SID_CmdQue) != 0)
-			device_tagenb = TRUE;
-		else
-			device_tagenb = FALSE;
-
-		if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
-		  && device_tagenb == FALSE)
-		 || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0
-		  && device_tagenb == TRUE)) {
-
-			if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
-				/*
-				 * Delay change to use tags until after a
-				 * few commands have gone to this device so
-				 * the controller has time to perform transfer
-				 * negotiations without tagged messages getting
-				 * in the way.
-				 */
-				device->tag_delay_count = CAM_TAG_DELAY_COUNT;
-				device->flags |= CAM_DEV_TAG_AFTER_COUNT;
-			} else {
-				struct ccb_relsim crs;
-
-				xpt_freeze_devq(cts->ccb_h.path, /*count*/1);
-		  		device->inq_flags &= ~SID_CmdQue;
-				xpt_dev_ccbq_resize(cts->ccb_h.path,
-						    sim->max_dev_openings);
-				device->flags &= ~CAM_DEV_TAG_AFTER_COUNT;
-				device->tag_delay_count = 0;
-
-				xpt_setup_ccb(&crs.ccb_h, cts->ccb_h.path,
-					      /*priority*/1);
-				crs.ccb_h.func_code = XPT_REL_SIMQ;
-				crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
-				crs.openings
-				    = crs.release_timeout
-				    = crs.qfrozen_cnt
-				    = 0;
-				xpt_action((union ccb *)&crs);
-			}
-		}
-	}
-	if (async_update == FALSE)
-		(*(sim->sim_action))(sim, (union ccb *)cts);
-}
-
-
-static void
-xpt_toggle_tags(struct cam_path *path)
-{
-	struct cam_ed *dev;
-
-	/*
-	 * Give controllers a chance to renegotiate
-	 * before starting tag operations.  We
-	 * "toggle" tagged queuing off then on
-	 * which causes the tag enable command delay
-	 * counter to come into effect.
-	 */
-	dev = path->device;
-	if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
-	 || ((dev->inq_flags & SID_CmdQue) != 0
- 	  && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) {
-		struct ccb_trans_settings cts;
-
-		xpt_setup_ccb(&cts.ccb_h, path, 1);
-		cts.protocol = PROTO_SCSI;
-		cts.protocol_version = PROTO_VERSION_UNSPECIFIED;
-		cts.transport = XPORT_UNSPECIFIED;
-		cts.transport_version = XPORT_VERSION_UNSPECIFIED;
-		cts.proto_specific.scsi.flags = 0;
-		cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
-		xpt_set_transfer_settings(&cts, path->device,
-					  /*async_update*/TRUE);
-		cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
-		xpt_set_transfer_settings(&cts, path->device,
-					  /*async_update*/TRUE);
-	}
-}
-
-static void
 xpt_start_tags(struct cam_path *path)
 {
 	struct ccb_relsim crs;

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

@@ -173,6 +173,7 @@
 typedef struct cam_ed * (*xpt_alloc_device_func)(struct cam_eb *bus,
 					         struct cam_et *target,
 					         lun_id_t lun_id);
+typedef void (*xpt_action_func)(union ccb *start_ccb);
 
 #if defined(CAM_DEBUG_FLAGS) && !defined(CAMDEBUG)
 #error "You must have options CAMDEBUG to use options CAM_DEBUG_FLAGS"
@@ -199,6 +200,7 @@
 MALLOC_DECLARE(M_CAMXPT);
 
 void			xpt_action(union ccb *new_ccb);
+void			xpt_action_default(union ccb *new_ccb);
 static struct cam_ed*	xpt_alloc_device(struct cam_eb *bus,
 					 struct cam_et *target,
 					 lun_id_t lun_id);

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_xpt.c#9 (text+ko) ====

@@ -540,6 +540,15 @@
 		 scsi_alloc_device(struct cam_eb *bus, struct cam_et *target,
 				   lun_id_t lun_id);
 static void	 scsi_devise_transport(struct cam_path *path);
+static void	 xpt_set_transfer_settings(struct ccb_trans_settings *cts,
+					   struct cam_ed *device,
+					   int async_update);
+static void	 xpt_toggle_tags(struct cam_path *path);
+static void	 xpt_dev_async(u_int32_t async_code,
+			       struct cam_eb *bus,
+			       struct cam_et *target,
+			       struct cam_ed *device,
+			       void *async_arg);
 
 static void
 probe_periph_init()
@@ -1938,3 +1947,476 @@
 	xpt_action((union ccb *)&cts);
 }
 
+static void
+scsi_action(union ccb *start_ccb)
+{
+
+	switch (start_ccb->ccb_h.func_code) {
+	case XPT_SCSI_IO:
+	{
+		struct cam_ed *device;
+#ifdef CAMDEBUG
+		char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
+		struct cam_path *path;
+
+		path = start_ccb->ccb_h.path;
+#endif
+
+		/*
+		 * For the sake of compatibility with SCSI-1
+		 * devices that may not understand the identify
+		 * message, we include lun information in the
+		 * second byte of all commands.  SCSI-1 specifies
+		 * that luns are a 3 bit value and reserves only 3
+		 * bits for lun information in the CDB.  Later
+		 * revisions of the SCSI spec allow for more than 8
+		 * luns, but have deprecated lun information in the
+		 * CDB.  So, if the lun won't fit, we must omit.
+		 *
+		 * Also be aware that during initial probing for devices,
+		 * the inquiry information is unknown but initialized to 0.
+		 * This means that this code will be exercised while probing
+		 * devices with an ANSI revision greater than 2.
+		 */
+		device = start_ccb->ccb_h.path->device;
+		if (device->protocol_version <= SCSI_REV_2
+		 && start_ccb->ccb_h.target_lun < 8
+		 && (start_ccb->ccb_h.flags & CAM_CDB_POINTER) == 0) {
+
+			start_ccb->csio.cdb_io.cdb_bytes[1] |=
+			    start_ccb->ccb_h.target_lun << 5;
+		}
+		start_ccb->csio.scsi_status = SCSI_STATUS_OK;
+		CAM_DEBUG(path, CAM_DEBUG_CDB,("%s. CDB: %s\n",
+			  scsi_op_desc(start_ccb->csio.cdb_io.cdb_bytes[0],
+			  	       &path->device->inq_data),
+			  scsi_cdb_string(start_ccb->csio.cdb_io.cdb_bytes,
+					  cdb_str, sizeof(cdb_str))));
+	}
+	{
+		struct cam_path *path;
+		int runq;
+
+		path = start_ccb->ccb_h.path;
+
+		cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
+		if (path->device->qfrozen_cnt == 0)
+			runq = xpt_schedule_dev_sendq(path->bus, path->device);
+		else
+			runq = 0;
+		if (runq != 0)
+			xpt_run_dev_sendq(path->bus);
+		break;
+	}
+	case XPT_SET_TRAN_SETTINGS:
+	{
+		xpt_set_transfer_settings(&start_ccb->cts,
+					  start_ccb->ccb_h.path->device,
+					  /*async_update*/FALSE);
+		break;
+	}
+	case XPT_SCAN_BUS:
+		xpt_scan_bus(start_ccb->ccb_h.path->periph, start_ccb);
+		break;
+	case XPT_SCAN_LUN:
+		xpt_scan_lun(start_ccb->ccb_h.path->periph,
+			     start_ccb->ccb_h.path, start_ccb->crcn.flags,
+			     start_ccb);
+		break;
+	case XPT_GET_TRAN_SETTINGS:
+	{
+		struct cam_sim *sim;
+
+		sim = start_ccb->ccb_h.path->bus->sim;
+		(*(sim->sim_action))(sim, start_ccb);
+		break;
+	}
+	default:
+		xpt_action_default(start_ccb);
+		break;
+	}
+}
+
+static void
+xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
+			  int async_update)
+{
+	struct	ccb_pathinq cpi;
+	struct	ccb_trans_settings cur_cts;
+	struct	ccb_trans_settings_scsi *scsi;
+	struct	ccb_trans_settings_scsi *cur_scsi;
+	struct	cam_sim *sim;
+	struct	scsi_inquiry_data *inq_data;
+
+	if (device == NULL) {
+		cts->ccb_h.status = CAM_PATH_INVALID;
+		xpt_done((union ccb *)cts);
+		return;
+	}
+
+	if (cts->protocol == PROTO_UNKNOWN
+	 || cts->protocol == PROTO_UNSPECIFIED) {
+		cts->protocol = device->protocol;
+		cts->protocol_version = device->protocol_version;
+	}
+
+	if (cts->protocol_version == PROTO_VERSION_UNKNOWN
+	 || cts->protocol_version == PROTO_VERSION_UNSPECIFIED)
+		cts->protocol_version = device->protocol_version;
+
+	if (cts->protocol != device->protocol) {
+		xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n",
+		       cts->protocol, device->protocol);
+		cts->protocol = device->protocol;
+	}
+
+	if (cts->protocol_version > device->protocol_version) {
+		if (bootverbose) {
+			xpt_print(cts->ccb_h.path, "Down reving Protocol "
+			    "Version from %d to %d?\n", cts->protocol_version,
+			    device->protocol_version);
+		}
+		cts->protocol_version = device->protocol_version;
+	}
+
+	if (cts->transport == XPORT_UNKNOWN
+	 || cts->transport == XPORT_UNSPECIFIED) {
+		cts->transport = device->transport;
+		cts->transport_version = device->transport_version;
+	}
+
+	if (cts->transport_version == XPORT_VERSION_UNKNOWN
+	 || cts->transport_version == XPORT_VERSION_UNSPECIFIED)
+		cts->transport_version = device->transport_version;
+
+	if (cts->transport != device->transport) {
+		xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n",
+		    cts->transport, device->transport);
+		cts->transport = device->transport;
+	}
+
+	if (cts->transport_version > device->transport_version) {
+		if (bootverbose) {
+			xpt_print(cts->ccb_h.path, "Down reving Transport "
+			    "Version from %d to %d?\n", cts->transport_version,
+			    device->transport_version);
+		}
+		cts->transport_version = device->transport_version;
+	}
+
+	sim = cts->ccb_h.path->bus->sim;
+
+	/*
+	 * Nothing more of interest to do unless
+	 * this is a device connected via the
+	 * SCSI protocol.
+	 */
+	if (cts->protocol != PROTO_SCSI) {
+		if (async_update == FALSE)
+			(*(sim->sim_action))(sim, (union ccb *)cts);
+		return;
+	}
+
+	inq_data = &device->inq_data;
+	scsi = &cts->proto_specific.scsi;
+	xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1);
+	cpi.ccb_h.func_code = XPT_PATH_INQ;
+	xpt_action((union ccb *)&cpi);
+
+	/* SCSI specific sanity checking */
+	if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0
+	 || (INQ_DATA_TQ_ENABLED(inq_data)) == 0
+	 || (device->queue_flags & SCP_QUEUE_DQUE) != 0
+	 || (device->mintags == 0)) {
+		/*
+		 * Can't tag on hardware that doesn't support tags,
+		 * doesn't have it enabled, or has broken tag support.
+		 */
+		scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
+	}
+
+	if (async_update == FALSE) {
+		/*
+		 * Perform sanity checking against what the
+		 * controller and device can do.
+		 */
+		xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1);
+		cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+		cur_cts.type = cts->type;
+		xpt_action((union ccb *)&cur_cts);
+		if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+			return;
+		}
+		cur_scsi = &cur_cts.proto_specific.scsi;
+		if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
+			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
+			scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB;
+		}
+		if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0)
+			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
+	}
+
+	/* SPI specific sanity checking */
+	if (cts->transport == XPORT_SPI && async_update == FALSE) {
+		u_int spi3caps;
+		struct ccb_trans_settings_spi *spi;
+		struct ccb_trans_settings_spi *cur_spi;
+
+		spi = &cts->xport_specific.spi;
+
+		cur_spi = &cur_cts.xport_specific.spi;
+
+		/* Fill in any gaps in what the user gave us */
+		if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
+			spi->sync_period = cur_spi->sync_period;
+		if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
+			spi->sync_period = 0;
+		if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
+			spi->sync_offset = cur_spi->sync_offset;
+		if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
+			spi->sync_offset = 0;
+		if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
+			spi->ppr_options = cur_spi->ppr_options;
+		if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
+			spi->ppr_options = 0;
+		if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
+			spi->bus_width = cur_spi->bus_width;
+		if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
+			spi->bus_width = 0;
+		if ((spi->valid & CTS_SPI_VALID_DISC) == 0) {
+			spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
+			spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB;
+		}
+		if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0)
+			spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
+		if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
+		  && (inq_data->flags & SID_Sync) == 0
+		  && cts->type == CTS_TYPE_CURRENT_SETTINGS)
+		 || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)) {
+			/* Force async */
+			spi->sync_period = 0;
+			spi->sync_offset = 0;
+		}
+
+		switch (spi->bus_width) {
+		case MSG_EXT_WDTR_BUS_32_BIT:
+			if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
+			  || (inq_data->flags & SID_WBus32) != 0
+			  || cts->type == CTS_TYPE_USER_SETTINGS)
+			 && (cpi.hba_inquiry & PI_WIDE_32) != 0)
+				break;
+			/* Fall Through to 16-bit */
+		case MSG_EXT_WDTR_BUS_16_BIT:
+			if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
+			  || (inq_data->flags & SID_WBus16) != 0
+			  || cts->type == CTS_TYPE_USER_SETTINGS)
+			 && (cpi.hba_inquiry & PI_WIDE_16) != 0) {
+				spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
+				break;
+			}
+			/* Fall Through to 8-bit */
+		default: /* New bus width?? */
+		case MSG_EXT_WDTR_BUS_8_BIT:
+			/* All targets can do this */
+			spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+			break;
+		}
+
+		spi3caps = cpi.xport_specific.spi.ppr_options;
+		if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
+		 && cts->type == CTS_TYPE_CURRENT_SETTINGS)
+			spi3caps &= inq_data->spi3data;
+
+		if ((spi3caps & SID_SPI_CLOCK_DT) == 0)
+			spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
+
+		if ((spi3caps & SID_SPI_IUS) == 0)
+			spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ;
+
+		if ((spi3caps & SID_SPI_QAS) == 0)
+			spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
+
+		/* No SPI Transfer settings are allowed unless we are wide */
+		if (spi->bus_width == 0)
+			spi->ppr_options = 0;
+
+		if ((spi->valid & CTS_SPI_VALID_DISC)
+		 && ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0)) {
+			/*
+			 * Can't tag queue without disconnection.
+			 */
+			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
+			scsi->valid |= CTS_SCSI_VALID_TQ;
+		}
+
+		/*
+		 * If we are currently performing tagged transactions to
+		 * this device and want to change its negotiation parameters,
+		 * go non-tagged for a bit to give the controller a chance to
+		 * negotiate unhampered by tag messages.
+		 */
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS
+		 && (device->inq_flags & SID_CmdQue) != 0
+		 && (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
+		 && (spi->flags & (CTS_SPI_VALID_SYNC_RATE|
+				   CTS_SPI_VALID_SYNC_OFFSET|
+				   CTS_SPI_VALID_BUS_WIDTH)) != 0)
+			xpt_toggle_tags(cts->ccb_h.path);
+	}
+
+	if (cts->type == CTS_TYPE_CURRENT_SETTINGS
+	 && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
+		int device_tagenb;
+
+		/*
+		 * If we are transitioning from tags to no-tags or
+		 * vice-versa, we need to carefully freeze and restart
+		 * the queue so that we don't overlap tagged and non-tagged
+		 * commands.  We also temporarily stop tags if there is
+		 * a change in transfer negotiation settings to allow
+		 * "tag-less" negotiation.
+		 */
+		if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
+		 || (device->inq_flags & SID_CmdQue) != 0)
+			device_tagenb = TRUE;
+		else
+			device_tagenb = FALSE;
+
+		if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
+		  && device_tagenb == FALSE)
+		 || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0
+		  && device_tagenb == TRUE)) {
+
+			if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
+				/*
+				 * Delay change to use tags until after a
+				 * few commands have gone to this device so
+				 * the controller has time to perform transfer
+				 * negotiations without tagged messages getting
+				 * in the way.
+				 */
+				device->tag_delay_count = CAM_TAG_DELAY_COUNT;
+				device->flags |= CAM_DEV_TAG_AFTER_COUNT;
+			} else {
+				struct ccb_relsim crs;
+
+				xpt_freeze_devq(cts->ccb_h.path, /*count*/1);
+		  		device->inq_flags &= ~SID_CmdQue;
+				xpt_dev_ccbq_resize(cts->ccb_h.path,
+						    sim->max_dev_openings);
+				device->flags &= ~CAM_DEV_TAG_AFTER_COUNT;
+				device->tag_delay_count = 0;
+
+				xpt_setup_ccb(&crs.ccb_h, cts->ccb_h.path,
+					      /*priority*/1);
+				crs.ccb_h.func_code = XPT_REL_SIMQ;
+				crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
+				crs.openings
+				    = crs.release_timeout
+				    = crs.qfrozen_cnt
+				    = 0;
+				xpt_action((union ccb *)&crs);
+			}
+		}
+	}
+	if (async_update == FALSE)
+		(*(sim->sim_action))(sim, (union ccb *)cts);
+}
+
+static void
+xpt_toggle_tags(struct cam_path *path)
+{
+	struct cam_ed *dev;
+
+	/*
+	 * Give controllers a chance to renegotiate
+	 * before starting tag operations.  We
+	 * "toggle" tagged queuing off then on
+	 * which causes the tag enable command delay
+	 * counter to come into effect.
+	 */
+	dev = path->device;
+	if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
+	 || ((dev->inq_flags & SID_CmdQue) != 0
+ 	  && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) {
+		struct ccb_trans_settings cts;
+
+		xpt_setup_ccb(&cts.ccb_h, path, 1);
+		cts.protocol = PROTO_SCSI;
+		cts.protocol_version = PROTO_VERSION_UNSPECIFIED;
+		cts.transport = XPORT_UNSPECIFIED;
+		cts.transport_version = XPORT_VERSION_UNSPECIFIED;
+		cts.proto_specific.scsi.flags = 0;
+		cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
+		xpt_set_transfer_settings(&cts, path->device,
+					  /*async_update*/TRUE);
+		cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
+		xpt_set_transfer_settings(&cts, path->device,
+					  /*async_update*/TRUE);
+	}
+}
+
+/*
+ * Handle any per-device event notifications that require action by the XPT.
+ */
+static void
+xpt_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
+	      struct cam_ed *device, void *async_arg)

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


More information about the p4-projects mailing list