Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 04 Mar 2003 21:01:25 -0700
From:      "Justin T. Gibbs" <gibbs@scsiguy.com>
To:        Nate Lawson <nate@root.org>, "John S. Bucy" <bucy@ece.cmu.edu>
Cc:        freebsd-scsi@FreeBSD.ORG
Subject:   Re: vendor specific commands
Message-ID:  <964280000.1046836885@aslan.scsiguy.com>
In-Reply-To: <Pine.BSF.4.21.0303041157110.80894-100000@root.org>
References:   <Pine.BSF.4.21.0303041157110.80894-100000@root.org>

next in thread | previous in thread | raw e-mail | index | archive | help
> A quick scan of the SCSI HBA drivers shows that none of them seem to do
> anything interesting with grp6/7len so it looks like you would have to
> update the device driver to pass these to the card firmware before your
> code would work.

In the case of the aic7xxx driver, all that is necessary is to pass
the vendor unique cdb lengths in the enable lun command, and modify
the ahc_handle_en_lun() routine to place these values in positions
6 and 7 of the CMDSIZE table.  The firmware will do the rest.  The
following untested patch does this and cleans up the resource leaks
on certain enable lun failure cases.  I'm not that fond of the structure
of this routine, so I will likely break ahc_handle_en_lun() into subroutines
so as to avoid the goto mess before I check this in.

--
Justin

Index: aic7xxx.c
===================================================================
RCS file: /usr/cvs/src/sys/dev/aic7xxx/aic7xxx.c,v
retrieving revision 1.41.2.26
diff -d -u -r1.41.2.26 aic7xxx.c
--- aic7xxx.c	20 Jan 2003 23:59:19 -0000	1.41.2.26
+++ aic7xxx.c	5 Mar 2003 03:59:45 -0000
@@ -6949,13 +6949,12 @@
 	u_long	   s;
 	char	   channel;
 
+	ahc_lock(ahc, &s);
 	status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, &lstate,
 				     /*notfound_failure*/FALSE);
 
-	if (status != CAM_REQ_CMP) {
-		ccb->ccb_h.status = status;
-		return;
-	}
+	if (status != CAM_REQ_CMP)
+		goto done;
 
 	if (cam_sim_bus(sim) == 0)
 		our_id = ahc->our_id;
@@ -7012,33 +7011,9 @@
 		}
 	}
 
-	if (status != CAM_REQ_CMP) {
-		ccb->ccb_h.status = status;
-		return;
-	}
-
-	/*
-	 * We now have an id that is valid.
-	 * If we aren't in target mode, switch modes.
-	 */
-	if ((ahc->flags & AHC_TARGETROLE) == 0
-	 && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
-		u_long	s;
+	if (status != CAM_REQ_CMP)
+		goto done;
 
-		printf("Configuring Target Mode\n");
-		ahc_lock(ahc, &s);
-		if (LIST_FIRST(&ahc->pending_scbs) != NULL) {
-			ccb->ccb_h.status = CAM_BUSY;
-			ahc_unlock(ahc, &s);
-			return;
-		}
-		ahc->flags |= AHC_TARGETROLE;
-		if ((ahc->features & AHC_MULTIROLE) == 0)
-			ahc->flags &= ~AHC_INITIATORROLE;
-		ahc_pause(ahc);
-		ahc_loadseq(ahc);
-		ahc_unlock(ahc, &s);
-	}
 	cel = &ccb->cel;
 	target = ccb->ccb_h.target_id;
 	lun = ccb->ccb_h.target_lun;
@@ -7048,25 +7023,30 @@
 		target_mask <<= 8;
 
 	if (cel->enable != 0) {
+		struct	ahc_tmode_tstate *new_tstate;
 		u_int scsiseq;
 
-		/* Are we already enabled?? */
+		new_tstate = NULL;
 		if (lstate != NULL) {
 			xpt_print_path(ccb->ccb_h.path);
 			printf("Lun already enabled\n");
-			ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
-			return;
+			status = CAM_LUN_ALRDY_ENA;
+			goto done;
 		}
 
-		if (cel->grp6_len != 0
-		 || cel->grp7_len != 0) {
-			/*
-			 * Don't (yet?) support vendor
-			 * specific commands.
-			 */
-			ccb->ccb_h.status = CAM_REQ_INVALID;
-			printf("Non-zero Group Codes\n");
-			return;
+		if (cel->grp6_len != ahc->grp6_len
+		 && ahc->grp6_len != 0) {
+			status = CAM_REQ_INVALID;
+			printf("Group 6 CDB length conflicts "
+			       "with another lun\n");
+			goto done;
+		}
+		if (cel->grp7_len != ahc->grp7_len
+		 && ahc->grp7_len != 0) {
+			status = CAM_REQ_INVALID;
+			printf("Group 7 CDB length conflicts "
+			       "with another lun\n");
+			goto done;
 		}
 
 		/*
@@ -7074,20 +7054,21 @@
 		 * Setup our data structures.
 		 */
 		if (target != CAM_TARGET_WILDCARD && tstate == NULL) {
-			tstate = ahc_alloc_tstate(ahc, target, channel);
-			if (tstate == NULL) {
+			new_tstate = ahc_alloc_tstate(ahc, target, channel);
+			if (new_tstate == NULL) {
 				xpt_print_path(ccb->ccb_h.path);
 				printf("Couldn't allocate tstate\n");
-				ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
-				return;
+				status = CAM_RESRC_UNAVAIL;
+				goto done;
 			}
+			tstate = new_tstate;
 		}
 		lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT);
 		if (lstate == NULL) {
 			xpt_print_path(ccb->ccb_h.path);
 			printf("Couldn't allocate lstate\n");
-			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
-			return;
+			status = CAM_RESRC_UNAVAIL;
+			goto cleanup;
 		}
 		memset(lstate, 0, sizeof(*lstate));
 		status = xpt_create_path(&lstate->path, /*periph*/NULL,
@@ -7095,17 +7076,40 @@
 					 xpt_path_target_id(ccb->ccb_h.path),
 					 xpt_path_lun_id(ccb->ccb_h.path));
 		if (status != CAM_REQ_CMP) {
-			free(lstate, M_DEVBUF);
-			xpt_print_path(ccb->ccb_h.path);
 			printf("Couldn't allocate path\n");
-			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
-			return;
+			status = CAM_RESRC_UNAVAIL;
+cleanup:
+			if (lstate != NULL)
+				free(lstate, M_DEVBUF);
+			if (new_tstate != NULL)
+				ahc_free_tstate(ahc, target, channel,
+						/*force*/FALSE);
+			goto done;
 		}
 		SLIST_INIT(&lstate->accept_tios);
 		SLIST_INIT(&lstate->immed_notifies);
-		ahc_lock(ahc, &s);
+		/*
+		 * We now have an id that is valid.
+		 * Complete controller configuration.
+		 */
 		ahc_pause(ahc);
 		if (target != CAM_TARGET_WILDCARD) {
+			/*
+			 * If we aren't in target mode, switch modes.
+			 */
+			if ((ahc->flags & AHC_TARGETROLE) == 0) {
+				if (LIST_FIRST(&ahc->pending_scbs) != NULL) {
+					status = CAM_BUSY;
+					xpt_free_path(lstate->path);
+					ahc_unpause(ahc);
+					goto cleanup;
+				}
+				printf("Configuring Target Mode\n");
+				ahc->flags |= AHC_TARGETROLE;
+				if ((ahc->features & AHC_MULTIROLE) == 0)
+					ahc->flags &= ~AHC_INITIATORROLE;
+				ahc_loadseq(ahc);
+			}
 			tstate->enabled_luns[lun] = lstate;
 			ahc->enabled_luns++;
 
@@ -7159,6 +7163,11 @@
 			}
 		} else
 			ahc->black_hole = lstate;
+		/* Set Group6 and Group7 cdb lengths */
+		ahc->grp6_len = cel->grp6_len;
+		ahc->grp7_len = cel->grp7_len;
+		ahc_outb(ahc, CMDSIZE_TABLE + 6, ahc->grp6_len);
+		ahc_outb(ahc, CMDSIZE_TABLE + 7, ahc->grp7_len);
 		/* Allow select-in operations */
 		if (ahc->black_hole != NULL && ahc->enabled_luns > 0) {
 			scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE);
@@ -7169,8 +7178,7 @@
 			ahc_outb(ahc, SCSISEQ, scsiseq);
 		}
 		ahc_unpause(ahc);
-		ahc_unlock(ahc, &s);
-		ccb->ccb_h.status = CAM_REQ_CMP;
+		status = CAM_REQ_CMP;
 		xpt_print_path(ccb->ccb_h.path);
 		printf("Lun now enabled for target mode\n");
 	} else {
@@ -7178,40 +7186,35 @@
 		int i, empty;
 
 		if (lstate == NULL) {
-			ccb->ccb_h.status = CAM_LUN_INVALID;
-			return;
+			status = CAM_LUN_INVALID;
+			goto done;
 		}
 
-		ahc_lock(ahc, &s);
 		
-		ccb->ccb_h.status = CAM_REQ_CMP;
 		LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
 			struct ccb_hdr *ccbh;
 
 			ccbh = &scb->io_ctx->ccb_h;
 			if (ccbh->func_code == XPT_CONT_TARGET_IO
 			 && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
-				printf("CTIO pending\n");
-				ccb->ccb_h.status = CAM_REQ_INVALID;
-				ahc_unlock(ahc, &s);
-				return;
+				printf("CTIOs pending\n");
+				status = CAM_REQ_INVALID;
+				break;
 			}
 		}
 
 		if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
 			printf("ATIOs pending\n");
-			ccb->ccb_h.status = CAM_REQ_INVALID;
+			status = CAM_REQ_INVALID;
 		}
 
 		if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
 			printf("INOTs pending\n");
-			ccb->ccb_h.status = CAM_REQ_INVALID;
+			status = CAM_REQ_INVALID;
 		}
 
-		if (ccb->ccb_h.status != CAM_REQ_CMP) {
-			ahc_unlock(ahc, &s);
-			return;
-		}
+		if (ccb->ccb_h.status != CAM_REQ_CMP)
+			goto done;
 
 		xpt_print_path(ccb->ccb_h.path);
 		printf("Target mode disabled\n");
@@ -7249,14 +7252,9 @@
 		} else {
 
 			ahc->black_hole = NULL;
-
-			/*
-			 * We can't allow selections without
-			 * our black hole device.
-			 */
-			empty = TRUE;
 		}
-		if (ahc->enabled_luns == 0) {
+		if (ahc->enabled_luns == 0
+		 || ahc->black_hole == NULL) {
 			/* Disallow select-in */
 			u_int scsiseq;
 
@@ -7275,9 +7273,18 @@
 				ahc_loadseq(ahc);
 			}
 		}
+		if (ahc->enabled_luns == 0) {
+			ahc->grp6_len = 0;
+			ahc->grp7_len = 0;
+			ahc_outb(ahc, CMDSIZE_TABLE + 6, 0);
+			ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);
+		}
 		ahc_unpause(ahc);
-		ahc_unlock(ahc, &s);
 	}
+
+done:
+	ccb->ccb_h.status = status;
+	ahc_unlock(ahc, &s);
 }
 
 static void
Index: aic7xxx.h
===================================================================
RCS file: /usr/cvs/src/sys/dev/aic7xxx/aic7xxx.h,v
retrieving revision 1.16.2.15
diff -d -u -r1.16.2.15 aic7xxx.h
--- aic7xxx.h	20 Jan 2003 23:59:20 -0000	1.16.2.15
+++ aic7xxx.h	5 Mar 2003 03:09:14 -0000
@@ -37,9 +37,9 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: aic7xxx.h,v 1.16.2.15 2003/01/20 23:59:20 gibbs Exp $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#70 $
  *
- * $FreeBSD$
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.h,v 1.16.2.15 2003/01/20 23:59:20 gibbs Exp $
  */
 
 #ifndef _AIC7XXX_H_
@@ -1048,6 +1048,10 @@
 
 	/* Number of enabled target mode device on this card */
 	u_int			  enabled_luns;
+
+	/* Vendor Unique CDB Lengths for target mode */
+	u_int8_t		  grp6_len;
+	u_int8_t		  grp7_len;
 
 	/* Initialization level of this data structure */
 	u_int			  init_level;


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-scsi" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?964280000.1046836885>