From owner-freebsd-scsi Tue Mar 4 20: 3: 3 2003 Delivered-To: freebsd-scsi@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 56BC537B401 for ; Tue, 4 Mar 2003 20:02:54 -0800 (PST) Received: from aslan.scsiguy.com (mail.scsiguy.com [63.229.232.106]) by mx1.FreeBSD.org (Postfix) with ESMTP id 29A5343F85 for ; Tue, 4 Mar 2003 20:02:53 -0800 (PST) (envelope-from gibbs@scsiguy.com) Received: from aslan.scsiguy.com (aslan.scsiguy.com [63.229.232.106]) by aslan.scsiguy.com (8.12.6/8.12.5) with ESMTP id h2541POU094261; Tue, 4 Mar 2003 21:01:25 -0700 (MST) (envelope-from gibbs@scsiguy.com) Date: Tue, 04 Mar 2003 21:01:25 -0700 From: "Justin T. Gibbs" To: Nate Lawson , "John S. Bucy" Cc: freebsd-scsi@FreeBSD.ORG Subject: Re: vendor specific commands Message-ID: <964280000.1046836885@aslan.scsiguy.com> In-Reply-To: References: X-Mailer: Mulberry/3.0.1 (Linux/x86) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline Sender: owner-freebsd-scsi@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org > 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