From nobody@FreeBSD.org  Fri Jan 11 21:25:21 2008
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 8D85616A417
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 11 Jan 2008 21:25:21 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 826ED13C457
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 11 Jan 2008 21:25:21 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m0BLOC8E070961
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 11 Jan 2008 21:24:12 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.2/8.14.1/Submit) id m0BLOCTA070960;
	Fri, 11 Jan 2008 21:24:12 GMT
	(envelope-from nobody)
Message-Id: <200801112124.m0BLOCTA070960@www.freebsd.org>
Date: Fri, 11 Jan 2008 21:24:12 GMT
From: Sean Bruno <sbruno@miralink.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: sbp_targ cannot handle multiple CTIO's for a single ATIO
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         119575
>Category:       kern
>Synopsis:       [firewire] [patch] sbp_targ cannot handle multiple CTIO's for a single ATIO
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    sbruno
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jan 11 21:30:02 UTC 2008
>Closed-Date:    Thu Apr 04 15:28:32 UTC 2013
>Last-Modified:  Thu Apr 04 15:28:32 UTC 2013
>Originator:     Sean Bruno
>Release:        RELENG_6.2
>Organization:
Miralink Inc
>Environment:
[sbruno@desdemona ~]$ uname -a
FreeBSD desdemona.office.miralink.com 6.2-RELEASE FreeBSD 6.2-RELEASE #0: Fri Jan 12 11:05:30 UTC 2007     root@dessler.cse.buffalo.edu:/usr/obj/usr/src/sys/SMP  i386

>Description:
I have been using sbp_targ with our own custom backend target for about
a month now and have generated the following patch that is required to make
the target work and process data correctly.

Issue 1.  Correct CTIO processing when multiple CTIO's are required for a
single ATIO.  This was handled by creating a unrestricted page table
structure and indexing through the page_table with easier to read
variables.  Split out the processing of the page table into a seperate
function(sbp_targ_xfer_pt) for ease of invocation.

Issue 2.  Change the tag_action for every ATIO to be "MSG_SIMPLE_TASK",
this was causing crashes in my backend target when it was set to "1"

Issue 3. Change default handler in sbp_targ_action1() to CAM_PROVIDE_FAIL

Issue 4. Add new transport type of "XPORT_FW" so that my backend target
can detect the differences between firewire and other XPORT types.

Issue 5.  Move atio assignment so that it is not mis-accessed by the error
handlers.

Issue 6.  Implement code for "CAM_NEW_TRAN_CODE" (That's what I use).

Issue 7.  Remove the number "2" in assignment of firewire speed.  Use
define FWSPD_S400 in it's place.  This is a precursor to detecting the
SIM's bus speed capabilities and using that for this value.

Issue 8.  A lot of debugging code added, along with some comments.  They
really helped me out and should be incorporated in some form or fashion
into the code for the "next person".

TODO items

Issue 9. Possible race condition around orbi->refcount
Issue 10. Implement compatibility with sbp so they can coexist
Issue 11. Implement detection of bus speed so firewire 800 cards can be used

>How-To-Repeat:
Try to use sbp_targ with a backend target.
>Fix:
Issues 1-8 are resolved with the patch attached to this PR.

Issues 9-11 are under construction.  :)

Partial credit for these fixes should go to Justin Gibbs.

Patch attached with submission follows:

--- firewire/sbp_targ.c	Fri Jan 11 13:21:04 2008
+++ /home/sbruno/work/FreeBSD_RELENG_6_13APR07/src/sys/dev/firewire/sbp_targ.c	Thu Jan 10 02:53:30 2008
@@ -182,19 +182,6 @@
 #endif
 };
 
-/*
- * Urestricted page table format 
- * states that the segment length
- * and high base addr are in the first
- * 32 bits and the base low is in 
- * the second
- */
-struct unrestricted_page_table_fmt {
-	uint16_t segment_len;
-	uint16_t segment_base_high;
-	uint32_t segment_base_low;
-};
-
 struct orb_info {
 	struct sbp_targ_softc *sc;
 	struct fw_device *fwdev;
@@ -217,10 +204,7 @@
 	struct corb4 orb4;
 	STAILQ_ENTRY(orb_info) link;
 	uint32_t orb[8];
-	struct unrestricted_page_table_fmt *page_table;
-	struct unrestricted_page_table_fmt *cur_pte;
-	struct unrestricted_page_table_fmt *last_pte;
-	uint32_t  last_block_read;
+	uint32_t *page_table;
 	struct sbp_status status;
 };
 
@@ -231,7 +215,6 @@
 static void sbp_targ_recv(struct fw_xfer *);
 static void sbp_targ_fetch_orb(struct sbp_targ_softc *, struct fw_device *,
     uint16_t, uint32_t, struct sbp_targ_login *, int);
-static void sbp_targ_xfer_pt(struct orb_info *);
 
 static void
 sbp_targ_identify(driver_t *driver, device_t parent)
@@ -264,19 +247,13 @@
 	}
 	for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) {
 		next = STAILQ_NEXT(orbi, link);
-		if (debug)
-			printf("%s: free orbi %p\n", __func__, orbi);
 		free(orbi, M_SBP_TARG);
-		orbi = NULL;
 	}
 	callout_stop(&login->hold_callout);
 
 	STAILQ_REMOVE(&login->lstate->logins, login, sbp_targ_login, link);
 	login->lstate->sc->logins[login->id] = NULL;
-	if (debug)
-		printf("%s: free login %p\n", __func__, login);
 	free((void *)login, M_SBP_TARG);
-	login = NULL;
 }
 
 static void
@@ -374,26 +351,20 @@
 	if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD &&
 	    ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
 		*lstate = sc->black_hole;
-		if (debug)
-			printf("setting black hole for this target id(%d)\n", ccb->ccb_h.target_id);
 		return (CAM_REQ_CMP);
 	}
 
+	if (ccb->ccb_h.target_id != 0)
+		return (CAM_TID_INVALID);
+
 	lun = ccb->ccb_h.target_lun;
 	if (lun >= MAX_LUN)
 		return (CAM_LUN_INVALID);
 	
 	*lstate = sc->lstate[lun];
 
-	if (notfound_failure != 0 && *lstate == NULL) {
-		if (debug)
-			printf("%s: lstate for lun is invalid, target(%d), lun(%d)\n",
-				__func__, ccb->ccb_h.target_id, lun);
+	if (notfound_failure != 0 && *lstate == NULL)
 		return (CAM_PATH_INVALID);
-	} else
-		if (debug)
-			printf("%s: setting lstate for tgt(%d) lun(%d)\n",
-				__func__,ccb->ccb_h.target_id, lun);
 
 	return (CAM_REQ_CMP);
 }
@@ -430,18 +401,11 @@
 			printf("Couldn't allocate lstate\n");
 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
 			return;
-		} else {
-			if (debug)
-				printf("%s: malloc'd lstate %p\n",__func__, lstate);
-		}	
-		if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) {
+		}
+		if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD)
 			sc->black_hole = lstate;
-			if (debug)
-				printf("Blackhole set due to target id == %d\n",
-					ccb->ccb_h.target_id);
-		} else
+		else
 			sc->lstate[ccb->ccb_h.target_lun] = lstate;
-
 		memset(lstate, 0, sizeof(*lstate));
 		lstate->sc = sc;
 		status = xpt_create_path(&lstate->path, /*periph*/NULL,
@@ -450,7 +414,6 @@
 					 xpt_path_lun_id(ccb->ccb_h.path));
 		if (status != CAM_REQ_CMP) {
 			free(lstate, M_SBP_TARG);
-			lstate = NULL;
 			xpt_print_path(ccb->ccb_h.path);
 			printf("Couldn't allocate path\n");
 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
@@ -470,7 +433,6 @@
 
 		if (lstate == NULL) {
 			ccb->ccb_h.status = CAM_LUN_INVALID;
-			printf("Invalid lstate for this target\n");
 			return;
 		}
 		ccb->ccb_h.status = CAM_REQ_CMP;
@@ -486,7 +448,6 @@
 		}
 
 		if (ccb->ccb_h.status != CAM_REQ_CMP) {
-			printf("status != CAM_REQ_CMP\n");
 			return;
 		}
 
@@ -504,10 +465,7 @@
 			sc->black_hole = NULL;
 		else
 			sc->lstate[ccb->ccb_h.target_lun] = NULL;
-		if (debug)
-			printf("%s: free lstate %p\n", __func__, lstate);
 		free(lstate, M_SBP_TARG);
-		lstate = NULL;
 
 		/* bus reset */
 		sc->fd.fc->ibr(sc->fd.fc);
@@ -560,8 +518,7 @@
 	STAILQ_FOREACH(orbi, &login->orbs, link)
 		if (orbi->orb_lo == tag_id)
 			goto found;
-	printf("%s: orb not found tag_id=0x%08x init_id=%d\n",
-			 __func__, tag_id, init_id);
+	printf("%s: orb not found tag_id=0x%08x\n", __func__, tag_id);
 	return (NULL);
 found:
 	return (orbi);
@@ -573,7 +530,7 @@
 	struct orb_info *norbi;
 
 	for (; orbi != NULL; orbi = norbi) {
-		printf("%s: status=%d ccb=%p\n", __func__, orbi->state, orbi->ccb);
+		printf("%s: status=%d\n", __func__, orbi->state);
 		norbi = STAILQ_NEXT(orbi, link);
 		if (orbi->state != ORBI_STATUS_ABORTED) {
 			if (orbi->ccb != NULL) {
@@ -583,10 +540,7 @@
 			}
 			if (orbi->state <= ORBI_STATUS_ATIO) {
 				sbp_targ_remove_orb_info(orbi->login, orbi);
-				if (debug)
-					printf("%s: free orbi %p\n", __func__, orbi);
 				free(orbi, M_SBP_TARG);
-				orbi = NULL;
 			} else
 				orbi->state = ORBI_STATUS_ABORTED;
 		}
@@ -598,22 +552,12 @@
 {
 	struct orb_info *orbi;
 
+	orbi = (struct orb_info *)xfer->sc;
 	if (xfer->resp != 0) {
 		/* XXX */
 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
 	}
-
-	orbi = (struct orb_info *)xfer->sc;
-	if ( orbi->page_table != NULL ) {
-		if (debug)
-			printf("%s:  free orbi->page_table %p\n", __func__, orbi->page_table);
-		free(orbi->page_table, M_SBP_TARG);
-		orbi->page_table = NULL;
-	}
-	if (debug)
-		printf("%s: free orbi %p\n", __func__, orbi);
 	free(orbi, M_SBP_TARG);
-	orbi = NULL;
 	fw_xfer_free(xfer);
 }
 
@@ -627,7 +571,7 @@
 		sbp_targ_remove_orb_info(orbi->login, orbi);
 
 	xfer = fwmem_write_block(orbi->fwdev, (void *)orbi,
-	    /*spd*/FWSPD_S400, fifo_hi, fifo_lo,
+	    /*spd*/2, fifo_hi, fifo_lo,
 	    sizeof(uint32_t) * (orbi->status.len + 1), (char *)&orbi->status,
 	    sbp_targ_free_orbi);
 
@@ -637,10 +581,6 @@
 	}
 }
 
-/*
- * Generate the appropriate CAM status for the
- * target.
- */
 static void
 sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb)
 {
@@ -654,7 +594,6 @@
 	sbp_status->status = 0; /* XXX */
 	sbp_status->dead = 0; /* XXX */
 
-	ccb->ccb_h.status= CAM_REQ_CMP;
 	switch (ccb->csio.scsi_status) {
 	case SCSI_STATUS_OK:
 		if (debug)
@@ -662,21 +601,15 @@
 		sbp_status->len = 1;
 		break;
 	case SCSI_STATUS_CHECK_COND:
-		if (debug)
-			printf("%s: STATUS SCSI_STATUS_CHECK_COND\n", __func__);
-		goto process_scsi_status;
 	case SCSI_STATUS_BUSY:
-		if (debug)
-			printf("%s: STATUS SCSI_STATUS_BUSY\n", __func__);
-		goto process_scsi_status;
 	case SCSI_STATUS_CMD_TERMINATED:
-		if (debug)
-			printf("%s: STATUS SCSI_STATUS_CMD_TERMINATED\n", __func__);
-process_scsi_status:
 	{
 		struct sbp_cmd_status *sbp_cmd_status;
 		struct scsi_sense_data *sense;
 
+		if (debug)
+			printf("%s: STATUS %d\n", __func__,
+			    ccb->csio.scsi_status);
 		sbp_cmd_status = (struct sbp_cmd_status *)&sbp_status->data[0];
 		sbp_cmd_status->status = ccb->csio.scsi_status;
 		sense = &ccb->csio.sense_data;
@@ -713,7 +646,6 @@
 		bcopy(&sense->sense_key_spec[0],
 		    &sbp_cmd_status->s_keydep[0], 3);
 
-		ccb->ccb_h.status |= CAM_SENT_SENSE;
 		break;
 	}
 	default:
@@ -724,17 +656,10 @@
 	sbp_targ_status_FIFO(orbi,
 	    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
 
+	if (orbi->page_table != NULL)
+		free(orbi->page_table, M_SBP_TARG);
 }
 
-/*
- * Invoked as a callback handler from fwmem_read/write_block
- *
- * Process read/write of initiator address space
- * completion and pass status onto the backend target.
- * If this is a partial read/write for a CCB then
- * we decrement the orbi's refcount to indicate
- * the status of the read/write is complete
- */
 static void
 sbp_targ_cam_done(struct fw_xfer *xfer)
 {
@@ -743,9 +668,10 @@
 
 	orbi = (struct orb_info *)xfer->sc;
 
-	if (debug)
+	if (debug > 1)
 		printf("%s: resp=%d refcount=%d\n", __func__,
 			xfer->resp, orbi->refcount);
+
 	if (xfer->resp != 0) {
 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
 		orbi->status.resp = SBP_TRANS_FAIL;
@@ -762,27 +688,13 @@
 			if (debug)
 				printf("%s: orbi aborted\n", __func__);
 			sbp_targ_remove_orb_info(orbi->login, orbi);
-			if (orbi->page_table != NULL) {
-				if (debug)
-					printf("%s: free orbi->page_table %p\n",
-						__func__, orbi->page_table);
+			if (orbi->page_table != NULL)
 				free(orbi->page_table, M_SBP_TARG);
-				orbi->page_table = NULL;
-			}
-			if (debug)
-				printf("%s: free orbi %p\n", __func__, orbi);
 			free(orbi, M_SBP_TARG);
-			orbi = NULL;
-		} else if (orbi->status.resp == ORBI_STATUS_NONE) {
-			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
-				if (debug) 
-					printf("%s: CAM_SEND_STATUS set %0x\n", __func__, ccb->ccb_h.flags);
+		} else if (orbi->status.resp == 0) {
+			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0)
 				sbp_targ_send_status(orbi, ccb);
-			} else {
-				if (debug)
-					printf("%s: CAM_SEND_STATUS not set %0x\n", __func__, ccb->ccb_h.flags);
-				ccb->ccb_h.status = CAM_REQ_CMP;
-			}
+			ccb->ccb_h.status = CAM_REQ_CMP;
 			xpt_done(ccb);
 		} else {
 			orbi->status.len = 1;
@@ -848,13 +760,6 @@
 	return (CAM_PATH_INVALID);
 }
 
-/*
- * directly execute a read or write to the initiator
- * address space and set hand(sbp_targ_cam_done) to 
- * process the completion from the SIM to the target.
- * set orbi->refcount to inidicate that a read/write
- * is inflight to/from the initiator.
- */
 static void
 sbp_targ_xfer_buf(struct orb_info *orbi, u_int offset,
     uint16_t dst_hi, uint32_t dst_lo, u_int size,
@@ -874,21 +779,16 @@
 		len = MIN(size, 2048 /* XXX */);
 		size -= len;
 		orbi->refcount ++;
-		if (ccb_dir == CAM_DIR_OUT) {
-			if (debug)
-				printf("%s: CAM_DIR_OUT --> read block in?\n",__func__);
+		if (ccb_dir == CAM_DIR_OUT)
 			xfer = fwmem_read_block(orbi->fwdev,
-			   (void *)orbi, /*spd*/FWSPD_S400,
+			   (void *)orbi, /*spd*/2,
 			    dst_hi, dst_lo + off, len,
 			    ptr + off, hand);
-	       } else {
-			if (debug)
-				printf("%s: CAM_DIR_IN --> write block out?\n",__func__);
+		else
 			xfer = fwmem_write_block(orbi->fwdev,
-			   (void *)orbi, /*spd*/FWSPD_S400,
+			   (void *)orbi, /*spd*/2,
 			    dst_hi, dst_lo + off, len,
 			    ptr + off, hand);
-		}
 		if (xfer == NULL) {
 			printf("%s: xfer == NULL", __func__);
 			/* XXX what should we do?? */
@@ -902,23 +802,18 @@
 sbp_targ_pt_done(struct fw_xfer *xfer)
 {
 	struct orb_info *orbi;
-	struct unrestricted_page_table_fmt *pt;
-	uint32_t i;
+	union ccb *ccb;
+	u_int i, offset, res, len;
+	uint32_t t1, t2, *p;
 
 	orbi = (struct orb_info *)xfer->sc;
-
+	ccb = orbi->ccb;
 	if (orbi->state == ORBI_STATUS_ABORTED) {
 		if (debug)
 			printf("%s: orbi aborted\n", __func__);
 		sbp_targ_remove_orb_info(orbi->login, orbi);
-		if (debug) {
-			printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
-			printf("%s: free orbi %p\n", __func__, orbi);
-		}
 		free(orbi->page_table, M_SBP_TARG);
-		orbi->page_table = NULL;
 		free(orbi, M_SBP_TARG);
-		orbi = NULL;
 		fw_xfer_free(xfer);
 		return;
 	}
@@ -932,156 +827,58 @@
 
 		sbp_targ_status_FIFO(orbi,
 		    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
-		if (debug)
-			printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
 		free(orbi->page_table, M_SBP_TARG);
-		orbi->page_table = NULL;
 		fw_xfer_free(xfer);
 		return;
 	}
+	res = ccb->csio.dxfer_len;
+	offset = 0;
+	if (debug)
+		printf("%s: dxfer_len=%d\n", __func__, res);
 	orbi->refcount ++;
-	/*
-	 * Set endianess here so we don't have 
-	 * to deal with is later
-	 */
-	for (i = 0, pt = orbi->page_table; i < orbi->orb4.data_size; i++, pt++) {
-		pt->segment_len = ntohs(pt->segment_len);
-		if (debug)
-			printf("%s:segment_len = %u\n", __func__,pt->segment_len);
-		pt->segment_base_high = ntohs(pt->segment_base_high);
-		pt->segment_base_low = ntohl(pt->segment_base_low);
+	for (p = orbi->page_table, i = orbi->orb4.data_size; i > 0; i --) {
+		t1 = ntohl(*p++);
+		t2 = ntohl(*p++);
+		if (debug > 1)
+			printf("page_table: %04x:%08x %d\n", 
+			    t1 & 0xffff, t2, t1>>16);
+		len = MIN(t1 >> 16, res);
+		res -= len;
+		sbp_targ_xfer_buf(orbi, offset, t1 & 0xffff, t2, len,
+		    sbp_targ_cam_done);
+		offset += len;
+		if (res == 0)
+			break;
 	}
-
-	sbp_targ_xfer_pt(orbi);
-
 	orbi->refcount --;
 	if (orbi->refcount == 0)
 		printf("%s: refcount == 0\n", __func__);
-	fw_xfer_free(xfer);
-	return;
-}
-
-static void sbp_targ_xfer_pt(struct orb_info *orbi)
-{
-	union ccb *ccb;
-	uint32_t res, offset, len;
-
-	ccb = orbi->ccb;
-	if (debug)
-		printf("%s: dxfer_len=%d\n", __func__, ccb->csio.dxfer_len);
-	res = ccb->csio.dxfer_len;
+	if (res !=0)
+		/* XXX handle res != 0 case */
+		printf("%s: page table is too small(%d)\n", __func__, res);
 
-	/*
-	 * If the page table required multiple CTIO's to 
-	 * complete, then cur_pte is non NULL 
-	 * and we need to start from the last position
-	 * If this is the first pass over a page table
-         * then we just start at the beginning of the page
-         * table.
-	 *
-	 * Parse the unrestricted page table and figure out where we need
-	 * to shove the data from this read request.
-	 */
-	for (offset = 0, len = 0; (res != 0) && (orbi->cur_pte < orbi->last_pte); offset += len) {
-		len = MIN(orbi->cur_pte->segment_len, res);
-		res -= len;
-		if (debug)
-			printf("%s:page_table: %04x:%08x segment_len(%u) res(%u) len(%u)\n", 
-				__func__, orbi->cur_pte->segment_base_high,
-				orbi->cur_pte->segment_base_low,
-				orbi->cur_pte->segment_len,
-				res, len);
-		sbp_targ_xfer_buf(orbi, offset, 
-				orbi->cur_pte->segment_base_high,
-				orbi->cur_pte->segment_base_low,
-				len, sbp_targ_cam_done);
-               /*
-                * If we have only written partially to
-                * this page table, then we need to save
-                * our position for the next CTIO.  If we
-                * have completed the page table, then we
-                * are safe to move on to the next entry.
-                */
-		if (len == orbi->cur_pte->segment_len) {
-                       orbi->cur_pte++;
-               } else {
-                       uint32_t saved_base_low;
-
-                       /* Handle transfers that cross a 4GB boundary. */
-                       saved_base_low = orbi->cur_pte->segment_base_low;
-                       orbi->cur_pte->segment_base_low += len;
-                       if (orbi->cur_pte->segment_base_low < saved_base_low)
-                           orbi->cur_pte->segment_base_high++;
-
-                       orbi->cur_pte->segment_len -= len;
-               }
-	}
-	if (debug) {
-		printf("%s: base_low(%08x) page_table_off(%p) last_block(%u)\n",
-			__func__, orbi->cur_pte->segment_base_low, 
-		orbi->cur_pte, orbi->last_block_read);	
-	}
-       if (res != 0)
-           printf("Warning - short pt encountered.  "
-                  "Could not transfer all data.\n");
+	fw_xfer_free(xfer);
 	return;
 }
 
-/*
- * Create page table in local memory
- * and transfer it from the initiator
- * in order to know where we are supposed
- * to put the data.
- */
 static void
 sbp_targ_fetch_pt(struct orb_info *orbi)
 {
 	struct fw_xfer *xfer;
 
-	/*
-	 * Pull in page table from initiator
- 	 * and setup for data from our
-	 * backend device.
-	 */
-	if (orbi->page_table == NULL) {
-		orbi->page_table = malloc(orbi->orb4.data_size*
-					  sizeof(struct unrestricted_page_table_fmt),
-					  M_SBP_TARG,
-					  M_NOWAIT|M_ZERO);
-		if (orbi->page_table == NULL)
-			goto error;
-		orbi->cur_pte = orbi->page_table;
-		orbi->last_pte = orbi->page_table + orbi->orb4.data_size;
-		orbi->last_block_read = orbi->orb4.data_size;
-		if (debug && orbi->page_table != NULL) 
-			printf("%s: malloc'd orbi->page_table(%p), orb4.data_size(%u)\n",
-				 __func__, orbi->page_table, orbi->orb4.data_size);
-
-		xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/FWSPD_S400,
-		    			orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*
-					sizeof(struct unrestricted_page_table_fmt),
-			    		(void *)orbi->page_table, sbp_targ_pt_done);
-
-		if (xfer != NULL)
-			return;
-	} else {
-		/*
-		 * This is a CTIO for a page table we have
-		 * already malloc'd, so just directly invoke
-		 * the xfer function on the orbi.
-		 */
-		sbp_targ_xfer_pt(orbi);
-
+	if (debug)
+		printf("%s: page_table_size=%d\n",
+		    __func__, orbi->orb4.data_size);
+	orbi->page_table = malloc(orbi->orb4.data_size*8, M_SBP_TARG, M_NOWAIT);
+	if (orbi->page_table == NULL)
+		goto error;
+	xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/2,
+		    orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*8,
+			    (void *)orbi->page_table, sbp_targ_pt_done);
+	if (xfer != NULL)
 		return;
-	}
 error:
 	orbi->ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
-	if (debug)	
-		printf("%s: free orbi->page_table %p due to xfer == NULL\n", __func__, orbi->page_table);
-	if (orbi->page_table != NULL) {
-		free(orbi->page_table, M_SBP_TARG);
-		orbi->page_table = NULL;
-	}
 	xpt_done(orbi->ccb);
 	return;
 }
@@ -1104,7 +901,7 @@
 		struct orb_info *orbi;
 
 		if (debug)
-			printf("%s: XPT_CONT_TARGET_IO(0x%08x)\n", __func__, ccb->csio.tag_id);
+			printf("%s: XPT_CONT_TARGET_IO\n", __func__);
 
 		if (status != CAM_REQ_CMP) {
 			ccb->ccb_h.status = status;
@@ -1123,12 +920,7 @@
 			if (debug)
 				printf("%s: ctio aborted\n", __func__);
 			sbp_targ_remove_orb_info(orbi->login, orbi);
-			if (debug)
-				printf("%s: free orbi %p\n", __func__, orbi);
 			free(orbi, M_SBP_TARG);
-			orbi = NULL;
-			ccb->ccb_h.status = CAM_REQ_ABORTED;
-			xpt_done(ccb);
 			break;
 		}
 		orbi->state = ORBI_STATUS_CTIO;
@@ -1160,28 +952,23 @@
 			break;
 		}
 
-		if (ccb_dir != CAM_DIR_NONE) {
+		/* Sanity check */
+		if (ccb_dir != CAM_DIR_NONE &&
+		    orbi->orb4.data_size != ccb->csio.dxfer_len)
+			printf("%s: data_size(%d) != dxfer_len(%d)\n",
+			    __func__, orbi->orb4.data_size,
+			    ccb->csio.dxfer_len);
+
+		if (ccb_dir != CAM_DIR_NONE)
 			sbp_targ_xfer_buf(orbi, 0, orbi->data_hi,
 			    orbi->data_lo,
 			    MIN(orbi->orb4.data_size, ccb->csio.dxfer_len),
 			    sbp_targ_cam_done);
-			if ( orbi->orb4.data_size > ccb->csio.dxfer_len ) {
-                       		orbi->data_lo += ccb->csio.dxfer_len;
-                       		orbi->orb4.data_size -= ccb->csio.dxfer_len;
-               		}
-
-		}
 
 		if (ccb_dir == CAM_DIR_NONE) {
-			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
-				if (debug) 
-					printf("%s: CAM_SEND_STATUS set %0x\n", __func__, ccb->ccb_h.flags);
+			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0)
 				sbp_targ_send_status(orbi, ccb);
-			} else {
-				if (debug)
-					printf("%s: CAM_SEND_STATUS not set %0x\n", __func__, ccb->ccb_h.flags);
-				ccb->ccb_h.status = CAM_REQ_CMP;
-			}
+			ccb->ccb_h.status = CAM_REQ_CMP;
 			xpt_done(ccb);
 		}
 		break;
@@ -1236,9 +1023,7 @@
 		cpi->target_sprt = PIT_PROCESSOR
 				 | PIT_DISCONNECT
 				 | PIT_TERM_IO;
-		cpi->transport = XPORT_FW;
-		cpi->hba_misc = PIM_NOINITIATOR
-			      | PIM_NOBUSRESET;
+		cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE;
 		cpi->hba_eng_cnt = 0;
 		cpi->max_target = 7; /* XXX */
 		cpi->max_lun = MAX_LUN - 1;
@@ -1276,41 +1061,10 @@
 		xpt_done(ccb);
 		break;
 	}
-#ifdef CAM_NEW_TRAN_CODE
-	case XPT_SET_TRAN_SETTINGS:
-		ccb->ccb_h.status = CAM_REQ_INVALID;
-		xpt_done(ccb);
-		break;
-	case XPT_GET_TRAN_SETTINGS:
-	{
-                struct ccb_trans_settings *cts = &ccb->cts;
-                struct ccb_trans_settings_scsi *scsi =
-                    &cts->proto_specific.scsi;
-                struct ccb_trans_settings_spi *spi =
-                    &cts->xport_specific.spi;
-
-                cts->protocol = PROTO_SCSI;
-                cts->protocol_version = SCSI_REV_2;
-                cts->transport = XPORT_FW;     /* should have a FireWire */
-                cts->transport_version = 2;
-                spi->valid = CTS_SPI_VALID_DISC;
-                spi->flags = CTS_SPI_FLAGS_DISC_ENB;
-                scsi->valid = CTS_SCSI_VALID_TQ;
-                scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
-#if 0
-                printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:\n",
-                        device_get_nameunit(sc->fd.dev),
-                        ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
-#endif
-                cts->ccb_h.status = CAM_REQ_CMP;
-                xpt_done(ccb);
-		break;
-	}
-#endif
 	default:
-		printf("%s: unknown function 0x%x\n",
+		printf("%s: unknown function %d\n",
 		    __func__, ccb->ccb_h.func_code);
-		ccb->ccb_h.status = CAM_PROVIDE_FAIL;
+		ccb->ccb_h.status = CAM_REQ_INVALID;
 		xpt_done(ccb);
 		break;
 	}
@@ -1361,17 +1115,10 @@
 	}
 	fp = &xfer->recv.hdr;
 
-	atio = orbi->atio; 
-
 	if (orbi->state == ORBI_STATUS_ABORTED) {
 		printf("%s: aborted\n", __func__);
 		sbp_targ_remove_orb_info(orbi->login, orbi);
-		if (debug)
-			printf("%s: free orbi %p\n", __func__, orbi);
 		free(orbi, M_SBP_TARG);
-		orbi = NULL;
-		atio->ccb_h.status = CAM_REQ_ABORTED;
-		xpt_done((union ccb*)atio);
 		goto done0;
 	}
 	orbi->state = ORBI_STATUS_ATIO;
@@ -1387,18 +1134,19 @@
 		printf("%s: rq_fmt(%d) != 0\n", __func__, orb4->rq_fmt);
 	}
 
+	atio = orbi->atio;
 	atio->ccb_h.target_id = 0; /* XXX */
 	atio->ccb_h.target_lun = orbi->login->lstate->lun;
 	atio->sense_len = 0;
-	atio->tag_action = MSG_SIMPLE_TASK;
+	atio->tag_action = 1; /* XXX */
 	atio->tag_id = orbi->orb_lo;
 	atio->init_id = orbi->login->id;
 
 	atio->ccb_h.flags = CAM_TAG_ACTION_VALID;
-	bytes = (u_char *)&orb[5];
+	bytes = (char *)&orb[5];
 	if (debug)
-		printf("%s: %p %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		    __func__, (void *)atio,
+		printf("%s: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		    __func__,
 		    bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
 		    bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]);
 	switch (bytes[0] >> 5) {
@@ -1476,8 +1224,6 @@
 	if (login == NULL) {
 		printf("%s: malloc failed\n", __func__);
 		return (NULL);
-	} else if (debug) {
-		printf("%s: malloc'd login %p\n", __func__, login);
 	}
 
 	login->id = i;
@@ -1541,10 +1287,11 @@
 		lun = orb4->id;
 		lstate = orbi->sc->lstate[lun];
 
-		if (lun >= MAX_LUN || lstate == NULL
-	         || (exclusive
-		  && STAILQ_FIRST(&lstate->logins) != NULL
-		  && STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev)) {
+		if (lun >= MAX_LUN || lstate == NULL ||
+		    (exclusive && 
+		    STAILQ_FIRST(&lstate->logins) != NULL &&
+		    STAILQ_FIRST(&lstate->logins)->fwdev != orbi->fwdev)
+		    ) {
 			/* error */
 			orbi->status.dead = 1;
 			orbi->status.status = STATUS_ACCESS_DENY;
@@ -1563,7 +1310,6 @@
 			break;
 		}
 
-		printf("%s:  login id=%d\n", __func__, login->id);
 		login->fifo_hi = orb[6];
 		login->fifo_lo = orb[7];
 		login->loginres.len = htons(sizeof(uint32_t) * 4);
@@ -1572,7 +1318,7 @@
 		login->loginres.cmd_lo = htonl(SBP_TARG_BIND_LO(login->id));
 		login->loginres.recon_hold = htons(login->hold_sec);
 
-		fwmem_write_block(orbi->fwdev, NULL, /*spd*/FWSPD_S400, orb[2], orb[3],
+		fwmem_write_block(orbi->fwdev, NULL, /*spd*/2, orb[2], orb[3],
 		    sizeof(struct sbp_login_res), (void *)&login->loginres,
 		    fw_asy_callback_free);
 		STAILQ_INSERT_TAIL(&lstate->logins, login, link);
@@ -1633,10 +1379,7 @@
 	sbp_targ_fetch_orb(orbi->login->lstate->sc, orbi->fwdev,
 	    (uint16_t)orb0, orb1, orbi->login, FETCH_CMD);
 done:
-	if (debug)
-		printf("%s: free orbi %p\n", __func__, orbi);
 	free(orbi, M_SBP_TARG);
-	orbi = NULL;
 	fw_xfer_free(xfer);
 	return;
 }
@@ -1649,13 +1392,11 @@
 	struct orb_info *orbi;
 
 	if (debug)
-		printf("%s: fetch orb mode %d, %04x:%08x\n", __func__, mode, orb_hi, orb_lo);
+		printf("%s: fetch orb %04x:%08x\n", __func__, orb_hi, orb_lo);
 	orbi = malloc(sizeof(struct orb_info), M_SBP_TARG, M_NOWAIT | M_ZERO);
 	if (orbi == NULL) {
 		printf("%s: malloc failed\n", __func__);
 		return;
-	} else if (debug) {
-		printf("%s: malloc'd orbi %p\n", __func__, orbi);
 	}
 	orbi->sc = sc;
 	orbi->fwdev = fwdev;
@@ -1664,19 +1405,14 @@
 	orbi->orb_lo = orb_lo;
 	orbi->status.orb_hi = htons(orb_hi);
 	orbi->status.orb_lo = htonl(orb_lo);
-	orbi->page_table = NULL;
 
 	switch (mode) {
 	case FETCH_MGM:
-		if (debug)
-			printf("%s: FETCH_MGM for orbi %p\n", __func__, orbi);
-		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
+		fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
 		    sizeof(uint32_t) * 8, &orbi->orb[0],
 		    sbp_targ_mgm_handler);
 		break;
 	case FETCH_CMD:
-		if (debug)
-			printf("%s: FETCH_CMD for orbi %p\n", __func__, orbi);
 		orbi->state = ORBI_STATUS_FETCH;
 		login->last_hi = orb_hi;
 		login->last_lo = orb_lo;
@@ -1695,17 +1431,15 @@
 			break;
 		}
 		SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle);
-		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
+		fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
 		    sizeof(uint32_t) * 8, &orbi->orb[0],
 		    sbp_targ_cmd_handler);
 		STAILQ_INSERT_TAIL(&login->orbs, orbi, link);
 		break;
 	case FETCH_POINTER:
-		if (debug)
-			printf("%s: FETCH_POINTER for orbi %p\n", __func__, orbi);
 		orbi->state = ORBI_STATUS_POINTER;
 		login->flags |= F_LINK_ACTIVE;
-		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
+		fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
 		    sizeof(uint32_t) * 2, &orbi->orb[0],
 		    sbp_targ_pointer_handler);
 		break;
@@ -1755,7 +1489,7 @@
 	switch (reg) {
 	case 0x08:	/* ORB_POINTER */
 		if (debug)
-			printf("%s: ORB_POINTER (%d)\n", __func__, login_id);
+			printf("%s: ORB_POINTER\n", __func__);
 		if ((login->flags & F_LINK_ACTIVE) != 0) {
 			if (debug)
 				printf("link active (ORB_POINTER)\n");
@@ -1768,14 +1502,14 @@
 		break;
 	case 0x04:	/* AGENT_RESET */
 		if (debug)
-			printf("%s: AGENT RESET (%d)\n", __func__, login_id);
+			printf("%s: AGENT RESET\n", __func__);
 		login->last_hi = 0xffff;
 		login->last_lo = 0xffffffff;
 		sbp_targ_abort(STAILQ_FIRST(&login->orbs));
 		break;
 	case 0x10:	/* DOORBELL */
 		if (debug)
-			printf("%s: DOORBELL (%d)\n", __func__, login_id);
+			printf("%s: DOORBELL\n", __func__);
 		if (login->last_hi == 0xffff &&
 		    login->last_lo == 0xffffffff) {
 			printf("%s: no previous pointer(DOORBELL)\n",
@@ -1792,13 +1526,13 @@
 		    login, FETCH_POINTER);
 		break;
 	case 0x00:	/* AGENT_STATE */
-		printf("%s: AGENT_STATE (%d:ignore)\n", __func__, login_id);
+		printf("%s: AGENT_STATE (ignore)\n", __func__);
 		break;
 	case 0x14:	/* UNSOLICITED_STATE_ENABLE */
-		printf("%s: UNSOLICITED_STATE_ENABLE (%d:ignore)\n", __func__, login_id);
+		printf("%s: UNSOLICITED_STATE_ENABLE (ignore)\n", __func__);
 		break;
 	default:
-		printf("%s: invalid register %d(%d)\n", __func__, reg, login_id);
+		printf("%s: invalid register %d\n", __func__, reg);
 		rtcode = RESP_ADDRESS_ERROR;
 	}
 
@@ -1860,7 +1594,7 @@
 	if (rtcode != 0)
 		printf("%s: rtcode = %d\n", __func__, rtcode);
 	sfp = &xfer->send.hdr;
-	xfer->send.spd = FWSPD_S400; 
+	xfer->send.spd = 2; /* XXX */
 	xfer->hand = sbp_targ_resp_callback;
 	sfp->mode.wres.dst = fp->mode.wreqb.src;
 	sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt;
@@ -1881,8 +1615,6 @@
         sc = (struct sbp_targ_softc *) device_get_softc(dev);
 	bzero((void *)sc, sizeof(struct sbp_targ_softc));
 
-
- 
 	sc->fd.fc = device_get_ivars(dev);
 	sc->fd.dev = dev;
 	sc->fd.post_explore = (void *) sbp_targ_post_explore;
@@ -1943,18 +1675,12 @@
 		lstate = sc->lstate[i];
 		if (lstate != NULL) {
 			xpt_free_path(lstate->path);
-			if (debug)
-				printf("%s: lstate free %p\n", __func__, lstate);
 			free(lstate, M_SBP_TARG);
-			lstate = NULL;
 		}
 	}
 	if (sc->black_hole != NULL) {
 		xpt_free_path(sc->black_hole->path);
-		if (debug)
-			printf("%s: free blackhole? %p\n", __func__, sc->black_hole);
 		free(sc->black_hole, M_SBP_TARG);
-		sc->black_hole = NULL;
 	}
 			
 	fw_bindremove(sc->fd.fc, &sc->fwb);


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->simokawa 
Responsible-Changed-By: simokawa 
Responsible-Changed-When: Wed Jan 16 22:32:47 UTC 2008 
Responsible-Changed-Why:  
I'll take care of this PR. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=119575 

From: Sean Bruno <sean.bruno@dsl-only.net>
To: bug-followup@FreeBSD.org, sbruno@miralink.com
Cc:  
Subject: Re: kern/119575: [firewire] [patch] sbp_targ cannot handle
	multiple CTIO's for a single ATIO
Date: Wed, 30 Jan 2008 11:03:46 -0800

 Looks like I've run into a new item for my TODO list.
 
 Item 12:  firewire_xfer_timeout() finding timed out transactions.
 Timeout too small at 200 msec?
 
 Sean
 

From: Sean Bruno <sean.bruno@dsl-only.net>
To: bug-followup@FreeBSD.org, sbruno@miralink.com
Cc:  
Subject: Re: kern/119575: [firewire] [patch] sbp_targ cannot handle
	multiple CTIO's for a single ATIO
Date: Wed, 30 Jan 2008 14:30:45 -0800

 Ah, now windows is exploding all over the place.
 
 Looks like I need to implement all of the task management functions:
 
 ORB_FUN_ATA  <--- Abort task
 ORB_FUN_ATS  <--- Abort task set
 ORB_FUN_LUR  <--- Logical unit reset
 ORB_FUN_RST  <--- Target reset
 
 So add this to the todo list as item 13
 
Responsible-Changed-From-To: simokawa->sbruno 
Responsible-Changed-By: sbruno 
Responsible-Changed-When: Tue Sep 29 17:52:59 UTC 2009 
Responsible-Changed-Why:  
I'm a committer now, I'll take care of this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=119575 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/119575: commit references a PR
Date: Wed, 25 Jan 2012 23:34:23 +0000 (UTC)

 Author: sbruno
 Date: Wed Jan 25 23:33:50 2012
 New Revision: 230558
 URL: http://svn.freebsd.org/changeset/base/230558
 
 Log:
   Update sbp_targ such that it can actually handle multiple CTIO's during operation
   
   PR:	kern/119575
 
 Modified:
   head/sys/dev/firewire/sbp_targ.c
 
 Modified: head/sys/dev/firewire/sbp_targ.c
 ==============================================================================
 --- head/sys/dev/firewire/sbp_targ.c	Wed Jan 25 22:39:22 2012	(r230557)
 +++ head/sys/dev/firewire/sbp_targ.c	Wed Jan 25 23:33:50 2012	(r230558)
 @@ -62,6 +62,7 @@
  #include <cam/cam_debug.h>
  #include <cam/cam_periph.h>
  #include <cam/scsi/scsi_all.h>
 +#include <cam/scsi/scsi_message.h>
  
  #define SBP_TARG_RECV_LEN	8
  #define MAX_INITIATORS		8
 @@ -186,6 +187,21 @@ struct morb4 {
  #endif
  };
  
 + 
 +/*
 + * Urestricted page table format 
 + * states that the segment length
 + * and high base addr are in the first
 + * 32 bits and the base low is in 
 + * the second
 + */
 +struct unrestricted_page_table_fmt {
 +	uint16_t segment_len;
 +	uint16_t segment_base_high;
 +	uint32_t segment_base_low;
 +};
 +
 +
  struct orb_info {
  	struct sbp_targ_softc *sc;
  	struct fw_device *fwdev;
 @@ -208,7 +224,10 @@ struct orb_info {
  	struct corb4 orb4;
  	STAILQ_ENTRY(orb_info) link;
  	uint32_t orb[8];
 -	uint32_t *page_table;
 +	struct unrestricted_page_table_fmt *page_table;
 +	struct unrestricted_page_table_fmt *cur_pte;
 +	struct unrestricted_page_table_fmt *last_pte;
 +	uint32_t  last_block_read;
  	struct sbp_status status;
  };
  
 @@ -219,6 +238,7 @@ static char *orb_fun_name[] = {
  static void sbp_targ_recv(struct fw_xfer *);
  static void sbp_targ_fetch_orb(struct sbp_targ_softc *, struct fw_device *,
      uint16_t, uint32_t, struct sbp_targ_login *, int);
 +static void sbp_targ_xfer_pt(struct orb_info *);
  static void sbp_targ_abort(struct sbp_targ_softc *, struct orb_info *);
  
  static void
 @@ -252,13 +272,19 @@ sbp_targ_dealloc_login(struct sbp_targ_l
  	}
  	for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) {
  		next = STAILQ_NEXT(orbi, link);
 +		if (debug)
 +			printf("%s: free orbi %p\n", __func__, orbi);
  		free(orbi, M_SBP_TARG);
 +		orbi = NULL;
  	}
  	callout_stop(&login->hold_callout);
  
  	STAILQ_REMOVE(&login->lstate->logins, login, sbp_targ_login, link);
  	login->lstate->sc->logins[login->id] = NULL;
 +	if (debug)
 +		printf("%s: free login %p\n", __func__, login);
  	free((void *)login, M_SBP_TARG);
 +	login = NULL;
  }
  
  static void
 @@ -361,20 +387,26 @@ sbp_targ_find_devs(struct sbp_targ_softc
  	if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD &&
  	    ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
  		*lstate = sc->black_hole;
 +		if (debug)
 +			printf("setting black hole for this target id(%d)\n", ccb->ccb_h.target_id);
  		return (CAM_REQ_CMP);
  	}
  
 -	if (ccb->ccb_h.target_id != 0)
 -		return (CAM_TID_INVALID);
 -
  	lun = ccb->ccb_h.target_lun;
  	if (lun >= MAX_LUN)
  		return (CAM_LUN_INVALID);
  	
  	*lstate = sc->lstate[lun];
  
 -	if (notfound_failure != 0 && *lstate == NULL)
 +	if (notfound_failure != 0 && *lstate == NULL) {
 +		if (debug)
 +			printf("%s: lstate for lun is invalid, target(%d), lun(%d)\n",
 +				__func__, ccb->ccb_h.target_id, lun);
  		return (CAM_PATH_INVALID);
 +	} else
 +		if (debug)
 +			printf("%s: setting lstate for tgt(%d) lun(%d)\n",
 +				__func__,ccb->ccb_h.target_id, lun);
  
  	return (CAM_REQ_CMP);
  }
 @@ -411,11 +443,18 @@ sbp_targ_en_lun(struct sbp_targ_softc *s
  			printf("Couldn't allocate lstate\n");
  			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  			return;
 -		}
 -		if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD)
 +		} else {
 +			if (debug)
 +				printf("%s: malloc'd lstate %p\n",__func__, lstate);
 +		}	
 +		if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD) {
  			sc->black_hole = lstate;
 -		else
 +			if (debug)
 +				printf("Blackhole set due to target id == %d\n",
 +					ccb->ccb_h.target_id);
 +		} else
  			sc->lstate[ccb->ccb_h.target_lun] = lstate;
 +
  		memset(lstate, 0, sizeof(*lstate));
  		lstate->sc = sc;
  		status = xpt_create_path(&lstate->path, /*periph*/NULL,
 @@ -424,6 +463,7 @@ sbp_targ_en_lun(struct sbp_targ_softc *s
  					 xpt_path_lun_id(ccb->ccb_h.path));
  		if (status != CAM_REQ_CMP) {
  			free(lstate, M_SBP_TARG);
 +			lstate = NULL;
  			xpt_print_path(ccb->ccb_h.path);
  			printf("Couldn't allocate path\n");
  			ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
 @@ -443,6 +483,7 @@ sbp_targ_en_lun(struct sbp_targ_softc *s
  
  		if (lstate == NULL) {
  			ccb->ccb_h.status = CAM_LUN_INVALID;
 +			printf("Invalid lstate for this target\n");
  			return;
  		}
  		ccb->ccb_h.status = CAM_REQ_CMP;
 @@ -458,6 +499,7 @@ sbp_targ_en_lun(struct sbp_targ_softc *s
  		}
  
  		if (ccb->ccb_h.status != CAM_REQ_CMP) {
 +			printf("status != CAM_REQ_CMP\n");
  			return;
  		}
  
 @@ -475,7 +517,10 @@ sbp_targ_en_lun(struct sbp_targ_softc *s
  			sc->black_hole = NULL;
  		else
  			sc->lstate[ccb->ccb_h.target_lun] = NULL;
 +		if (debug)
 +			printf("%s: free lstate %p\n", __func__, lstate);
  		free(lstate, M_SBP_TARG);
 +		lstate = NULL;
  
  		/* bus reset */
  		sc->fd.fc->ibr(sc->fd.fc);
 @@ -538,7 +583,7 @@ sbp_targ_get_orb_info(struct sbp_targ_ls
  		if (orbi->orb_lo == tag_id)
  			goto found;
  	printf("%s: orb not found tag_id=0x%08x init_id=%d\n",
 -				 __func__, tag_id, init_id);
 +			 __func__, tag_id, init_id);
  	return (NULL);
  found:
  	return (orbi);
 @@ -559,12 +604,13 @@ sbp_targ_abort(struct sbp_targ_softc *sc
  				xpt_done(orbi->ccb);
  				orbi->ccb = NULL;
  			}
 -#if 0
  			if (orbi->state <= ORBI_STATUS_ATIO) {
  				sbp_targ_remove_orb_info_locked(orbi->login, orbi);
 +				if (debug)
 +					printf("%s: free orbi %p\n", __func__, orbi);
  				free(orbi, M_SBP_TARG);
 +				orbi = NULL;
  			} else
 -#endif
  				orbi->state = ORBI_STATUS_ABORTED;
  		}
  	}
 @@ -576,12 +622,21 @@ sbp_targ_free_orbi(struct fw_xfer *xfer)
  {
  	struct orb_info *orbi;
  
 -	orbi = (struct orb_info *)xfer->sc;
  	if (xfer->resp != 0) {
  		/* XXX */
  		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
  	}
 +	orbi = (struct orb_info *)xfer->sc;
 +	if ( orbi->page_table != NULL ) {
 +		if (debug)
 +			printf("%s:  free orbi->page_table %p\n", __func__, orbi->page_table);
 +		free(orbi->page_table, M_SBP_TARG);
 +		orbi->page_table = NULL;
 +	}
 +	if (debug)
 +		printf("%s: free orbi %p\n", __func__, orbi);
  	free(orbi, M_SBP_TARG);
 +	orbi = NULL;
  	fw_xfer_free(xfer);
  }
  
 @@ -595,7 +650,7 @@ sbp_targ_status_FIFO(struct orb_info *or
  		sbp_targ_remove_orb_info(orbi->login, orbi);
  
  	xfer = fwmem_write_block(orbi->fwdev, (void *)orbi,
 -	    /*spd*/2, fifo_hi, fifo_lo,
 +	    /*spd*/FWSPD_S400, fifo_hi, fifo_lo,
  	    sizeof(uint32_t) * (orbi->status.len + 1), (char *)&orbi->status,
  	    sbp_targ_free_orbi);
  
 @@ -605,6 +660,10 @@ sbp_targ_status_FIFO(struct orb_info *or
  	}
  }
  
 +/*
 + * Generate the appropriate CAM status for the
 + * target.
 + */
  static void
  sbp_targ_send_status(struct orb_info *orbi, union ccb *ccb)
  {
 @@ -621,6 +680,8 @@ sbp_targ_send_status(struct orb_info *or
  	sbp_status->status = 0; /* XXX */
  	sbp_status->dead = 0; /* XXX */
  
 +	ccb->ccb_h.status= CAM_REQ_CMP;
 +
  	switch (ccb->csio.scsi_status) {
  	case SCSI_STATUS_OK:
  		if (debug)
 @@ -628,8 +689,15 @@ sbp_targ_send_status(struct orb_info *or
  		sbp_status->len = 1;
  		break;
  	case SCSI_STATUS_CHECK_COND:
 +		if (debug)
 +			printf("%s: STATUS SCSI_STATUS_CHECK_COND\n", __func__);
 +		goto process_scsi_status;
  	case SCSI_STATUS_BUSY:
 +		if (debug)
 +			printf("%s: STATUS SCSI_STATUS_BUSY\n", __func__);
 +		goto process_scsi_status;
  	case SCSI_STATUS_CMD_TERMINATED:
 +process_scsi_status:
  	{
  		struct sbp_cmd_status *sbp_cmd_status;
  		struct scsi_sense_data *sense;
 @@ -640,9 +708,6 @@ sbp_targ_send_status(struct orb_info *or
  		int64_t sinfo;
  		int sense_len;
  
 -		if (debug)
 -			printf("%s: STATUS %d\n", __func__,
 -			    ccb->csio.scsi_status);
  		sbp_cmd_status = (struct sbp_cmd_status *)&sbp_status->data[0];
  		sbp_cmd_status->status = ccb->csio.scsi_status;
  		sense = &ccb->csio.sense_data;
 @@ -734,6 +799,7 @@ sbp_targ_send_status(struct orb_info *or
  		if (scsi_get_sks(sense, sense_len, sks) == 0) {
  			bcopy(sks, &sbp_cmd_status->s_keydep[0], sizeof(sks));
  			sbp_status->len = 5;
 +			ccb->ccb_h.status |= CAM_SENT_SENSE;
  		}
  
  		break;
 @@ -743,13 +809,20 @@ sbp_targ_send_status(struct orb_info *or
  		    sbp_status->status);
  	}
  
 -	if (orbi->page_table != NULL)
 -		free(orbi->page_table, M_SBP_TARG);
  
  	sbp_targ_status_FIFO(orbi,
  	    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
  }
  
 +/*
 + * Invoked as a callback handler from fwmem_read/write_block
 + *
 + * Process read/write of initiator address space
 + * completion and pass status onto the backend target.
 + * If this is a partial read/write for a CCB then
 + * we decrement the orbi's refcount to indicate
 + * the status of the read/write is complete
 + */
  static void
  sbp_targ_cam_done(struct fw_xfer *xfer)
  {
 @@ -758,7 +831,7 @@ sbp_targ_cam_done(struct fw_xfer *xfer)
  
  	orbi = (struct orb_info *)xfer->sc;
  
 -	if (debug > 1)
 +	if (debug)
  		printf("%s: resp=%d refcount=%d\n", __func__,
  			xfer->resp, orbi->refcount);
  
 @@ -779,13 +852,26 @@ sbp_targ_cam_done(struct fw_xfer *xfer)
  			if (debug)
  				printf("%s: orbi aborted\n", __func__);
  			sbp_targ_remove_orb_info(orbi->login, orbi);
 -			if (orbi->page_table != NULL)
 +			if (orbi->page_table != NULL) {
 +				if (debug)
 +					printf("%s: free orbi->page_table %p\n",
 +						__func__, orbi->page_table);
  				free(orbi->page_table, M_SBP_TARG);
 +			}
 +			if (debug)
 +				printf("%s: free orbi %p\n", __func__, orbi);
  			free(orbi, M_SBP_TARG);
 -		} else if (orbi->status.resp == 0) {
 -			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0)
 +			orbi = NULL;
 +		} else if (orbi->status.resp == ORBI_STATUS_NONE) {
 +			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
 +				if (debug) 
 +					printf("%s: CAM_SEND_STATUS set %0x\n", __func__, ccb->ccb_h.flags);
  				sbp_targ_send_status(orbi, ccb);
 -			ccb->ccb_h.status = CAM_REQ_CMP;
 +			} else {
 +				if (debug)
 +					printf("%s: CAM_SEND_STATUS not set %0x\n", __func__, ccb->ccb_h.flags);
 +				ccb->ccb_h.status = CAM_REQ_CMP;
 +			}
  			SBP_LOCK(orbi->sc);
  			xpt_done(ccb);
  			SBP_UNLOCK(orbi->sc);
 @@ -855,6 +941,13 @@ sbp_targ_abort_ccb(struct sbp_targ_softc
  	return (CAM_PATH_INVALID);
  }
  
 +/*
 + * directly execute a read or write to the initiator
 + * address space and set hand(sbp_targ_cam_done) to 
 + * process the completion from the SIM to the target.
 + * set orbi->refcount to inidicate that a read/write
 + * is inflight to/from the initiator.
 + */
  static void
  sbp_targ_xfer_buf(struct orb_info *orbi, u_int offset,
      uint16_t dst_hi, uint32_t dst_lo, u_int size,
 @@ -874,16 +967,21 @@ sbp_targ_xfer_buf(struct orb_info *orbi,
  		len = MIN(size, 2048 /* XXX */);
  		size -= len;
  		orbi->refcount ++;
 -		if (ccb_dir == CAM_DIR_OUT)
 +		if (ccb_dir == CAM_DIR_OUT) {
 +			if (debug)
 +				printf("%s: CAM_DIR_OUT --> read block in?\n",__func__);
  			xfer = fwmem_read_block(orbi->fwdev,
 -			   (void *)orbi, /*spd*/2,
 +			   (void *)orbi, /*spd*/FWSPD_S400,
  			    dst_hi, dst_lo + off, len,
  			    ptr + off, hand);
 -		else
 +		} else {
 +			if (debug)
 +				printf("%s: CAM_DIR_IN --> write block out?\n",__func__);
  			xfer = fwmem_write_block(orbi->fwdev,
 -			   (void *)orbi, /*spd*/2,
 +			   (void *)orbi, /*spd*/FWSPD_S400,
  			    dst_hi, dst_lo + off, len,
  			    ptr + off, hand);
 +		}
  		if (xfer == NULL) {
  			printf("%s: xfer == NULL", __func__);
  			/* XXX what should we do?? */
 @@ -897,18 +995,22 @@ static void
  sbp_targ_pt_done(struct fw_xfer *xfer)
  {
  	struct orb_info *orbi;
 -	union ccb *ccb;
 -	u_int i, offset, res, len;
 -	uint32_t t1, t2, *p;
 +	struct unrestricted_page_table_fmt *pt;
 +	uint32_t i;
  
  	orbi = (struct orb_info *)xfer->sc;
 -	ccb = orbi->ccb;
 +
  	if (orbi->state == ORBI_STATUS_ABORTED) {
  		if (debug)
  			printf("%s: orbi aborted\n", __func__);
  		sbp_targ_remove_orb_info(orbi->login, orbi);
 +		if (debug) {
 +			printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
 +			printf("%s: free orbi %p\n", __func__, orbi);
 +		}
  		free(orbi->page_table, M_SBP_TARG);
  		free(orbi, M_SBP_TARG);
 +		orbi = NULL;
  		fw_xfer_free(xfer);
  		return;
  	}
 @@ -920,60 +1022,158 @@ sbp_targ_pt_done(struct fw_xfer *xfer)
  		orbi->status.len = 1;
  		sbp_targ_abort(orbi->sc, STAILQ_NEXT(orbi, link));
  
 +		if (debug)
 +			printf("%s: free orbi->page_table %p\n", __func__, orbi->page_table);
 +
  		sbp_targ_status_FIFO(orbi,
  		    orbi->login->fifo_hi, orbi->login->fifo_lo, /*dequeue*/1);
  		free(orbi->page_table, M_SBP_TARG);
 +		orbi->page_table = NULL;
  		fw_xfer_free(xfer);
  		return;
  	}
 -	res = ccb->csio.dxfer_len;
 -	offset = 0;
 -	if (debug)
 -		printf("%s: dxfer_len=%d\n", __func__, res);
 -	orbi->refcount ++;
 -	for (p = orbi->page_table, i = orbi->orb4.data_size; i > 0; i --) {
 -		t1 = ntohl(*p++);
 -		t2 = ntohl(*p++);
 -		if (debug > 1)
 -			printf("page_table: %04x:%08x %d\n", 
 -			    t1 & 0xffff, t2, t1>>16);
 -		len = MIN(t1 >> 16, res);
 -		res -= len;
 -		sbp_targ_xfer_buf(orbi, offset, t1 & 0xffff, t2, len,
 -		    sbp_targ_cam_done);
 -		offset += len;
 -		if (res == 0)
 -			break;
 +	orbi->refcount++;
 +/*
 + * Set endianess here so we don't have 
 + * to deal with is later
 + */
 +	for (i = 0, pt = orbi->page_table; i < orbi->orb4.data_size; i++, pt++) {
 +		pt->segment_len = ntohs(pt->segment_len);
 +		if (debug)
 +			printf("%s:segment_len = %u\n", __func__,pt->segment_len);
 +		pt->segment_base_high = ntohs(pt->segment_base_high);
 +		pt->segment_base_low = ntohl(pt->segment_base_low);
  	}
 -	orbi->refcount --;
 +
 +	sbp_targ_xfer_pt(orbi);
 +
 +	orbi->refcount--;
  	if (orbi->refcount == 0)
  		printf("%s: refcount == 0\n", __func__);
 -	if (res !=0)
 -		/* XXX handle res != 0 case */
 -		printf("%s: page table is too small(%d)\n", __func__, res);
  
  	fw_xfer_free(xfer);
  	return;
  }
  
 +static void sbp_targ_xfer_pt(struct orb_info *orbi)
 +{
 +	union ccb *ccb;
 +	uint32_t res, offset, len;
 +
 +	ccb = orbi->ccb;
 +	if (debug)
 +		printf("%s: dxfer_len=%d\n", __func__, ccb->csio.dxfer_len);
 +	res = ccb->csio.dxfer_len;
 +	/*
 +	 * If the page table required multiple CTIO's to 
 +	 * complete, then cur_pte is non NULL 
 +	 * and we need to start from the last position
 +	 * If this is the first pass over a page table
 +	 * then we just start at the beginning of the page
 +	 * table.
 +	 *
 +	 * Parse the unrestricted page table and figure out where we need
 +	 * to shove the data from this read request.
 +	 */
 +	for (offset = 0, len = 0; (res != 0) && (orbi->cur_pte < orbi->last_pte); offset += len) {
 +		len = MIN(orbi->cur_pte->segment_len, res);
 +		res -= len;
 +		if (debug)
 +			printf("%s:page_table: %04x:%08x segment_len(%u) res(%u) len(%u)\n", 
 +				__func__, orbi->cur_pte->segment_base_high,
 +				orbi->cur_pte->segment_base_low,
 +				orbi->cur_pte->segment_len,
 +				res, len);
 +		sbp_targ_xfer_buf(orbi, offset, 
 +				orbi->cur_pte->segment_base_high,
 +				orbi->cur_pte->segment_base_low,
 +				len, sbp_targ_cam_done);
 +		/*
 +		 * If we have only written partially to
 +		 * this page table, then we need to save
 +		 * our position for the next CTIO.  If we
 +		 * have completed the page table, then we
 +		 * are safe to move on to the next entry.
 +		 */
 +		if (len == orbi->cur_pte->segment_len) {
 +			orbi->cur_pte++;
 +		} else {
 +			uint32_t saved_base_low;
 +
 +			/* Handle transfers that cross a 4GB boundary. */
 +			saved_base_low = orbi->cur_pte->segment_base_low;
 +			orbi->cur_pte->segment_base_low += len;
 +			if (orbi->cur_pte->segment_base_low < saved_base_low)
 +				orbi->cur_pte->segment_base_high++;
 +
 +			orbi->cur_pte->segment_len -= len;
 +		}
 +	}
 +	if (debug) {
 +		printf("%s: base_low(%08x) page_table_off(%p) last_block(%u)\n",
 +			__func__, orbi->cur_pte->segment_base_low, 
 +			orbi->cur_pte, orbi->last_block_read);  
 +	}
 +	if (res != 0)
 +		printf("Warning - short pt encountered.  "
 +			"Could not transfer all data.\n");
 +	return;
 +}
 +
 +/*
 + * Create page table in local memory
 + * and transfer it from the initiator
 + * in order to know where we are supposed
 + * to put the data.
 + */
 +
  static void
  sbp_targ_fetch_pt(struct orb_info *orbi)
  {
  	struct fw_xfer *xfer;
  
 -	if (debug)
 -		printf("%s: page_table_size=%d\n",
 -		    __func__, orbi->orb4.data_size);
 -	orbi->page_table = malloc(orbi->orb4.data_size*8, M_SBP_TARG, M_NOWAIT);
 -	if (orbi->page_table == NULL)
 -		goto error;
 -	xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/2,
 -		    orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*8,
 -			    (void *)orbi->page_table, sbp_targ_pt_done);
 -	if (xfer != NULL)
 +	/*
 +	 * Pull in page table from initiator
 +	 * and setup for data from our
 +	 * backend device.
 +	 */
 +	if (orbi->page_table == NULL) {
 +		orbi->page_table = malloc(orbi->orb4.data_size*
 +					  sizeof(struct unrestricted_page_table_fmt),
 +					  M_SBP_TARG, M_NOWAIT|M_ZERO);
 +		if (orbi->page_table == NULL)
 +			goto error;
 +		orbi->cur_pte = orbi->page_table;
 +		orbi->last_pte = orbi->page_table + orbi->orb4.data_size;
 +		orbi->last_block_read = orbi->orb4.data_size;
 +		if (debug && orbi->page_table != NULL) 
 +			printf("%s: malloc'd orbi->page_table(%p), orb4.data_size(%u)\n",
 + 				__func__, orbi->page_table, orbi->orb4.data_size);
 +
 +		xfer = fwmem_read_block(orbi->fwdev, (void *)orbi, /*spd*/FWSPD_S400,
 +					orbi->data_hi, orbi->data_lo, orbi->orb4.data_size*
 +					sizeof(struct unrestricted_page_table_fmt),
 +					(void *)orbi->page_table, sbp_targ_pt_done);
 +
 +		if (xfer != NULL)
 +			return;
 +	} else {
 +		/*
 +		 * This is a CTIO for a page table we have
 +		 * already malloc'd, so just directly invoke
 +		 * the xfer function on the orbi.
 +		 */
 +		sbp_targ_xfer_pt(orbi);
  		return;
 +	}
  error:
  	orbi->ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
 +	if (debug)      
 +		printf("%s: free orbi->page_table %p due to xfer == NULL\n", __func__, orbi->page_table);
 +	if (orbi->page_table != NULL) {
 +		free(orbi->page_table, M_SBP_TARG);
 +		orbi->page_table = NULL;
 +	}
  	xpt_done(orbi->ccb);
  	return;
  }
 @@ -1016,6 +1216,8 @@ sbp_targ_action1(struct cam_sim *sim, un
  			if (debug)
  				printf("%s: ctio aborted\n", __func__);
  			sbp_targ_remove_orb_info_locked(orbi->login, orbi);
 +			if (debug)
 +				printf("%s: free orbi %p\n", __func__, orbi);
  			free(orbi, M_SBP_TARG);
  			ccb->ccb_h.status = CAM_REQ_ABORTED;
  			xpt_done(ccb);
 @@ -1051,17 +1253,16 @@ sbp_targ_action1(struct cam_sim *sim, un
  		}
  
  		/* Sanity check */
 -		if (ccb_dir != CAM_DIR_NONE &&
 -		    orbi->orb4.data_size != ccb->csio.dxfer_len)
 -			printf("%s: data_size(%d) != dxfer_len(%d)\n",
 -			    __func__, orbi->orb4.data_size,
 -			    ccb->csio.dxfer_len);
 -
 -		if (ccb_dir != CAM_DIR_NONE)
 +		if (ccb_dir != CAM_DIR_NONE) {
  			sbp_targ_xfer_buf(orbi, 0, orbi->data_hi,
  			    orbi->data_lo,
  			    MIN(orbi->orb4.data_size, ccb->csio.dxfer_len),
  			    sbp_targ_cam_done);
 +			if ( orbi->orb4.data_size > ccb->csio.dxfer_len ) {
 +				orbi->data_lo += ccb->csio.dxfer_len;
 +				orbi->orb4.data_size -= ccb->csio.dxfer_len;
 +			}
 +		}
  
  		if (ccb_dir == CAM_DIR_NONE) {
  			if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
 @@ -1125,7 +1326,8 @@ sbp_targ_action1(struct cam_sim *sim, un
  		cpi->target_sprt = PIT_PROCESSOR
  				 | PIT_DISCONNECT
  				 | PIT_TERM_IO;
 -		cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE;
 +		cpi->transport = XPORT_SPI; /* FIXME add XPORT_FW type to cam */
 +		cpi->hba_misc = PIM_NOBUSRESET | PIM_NOBUSRESET;
  		cpi->hba_eng_cnt = 0;
  		cpi->max_target = 7; /* XXX */
  		cpi->max_lun = MAX_LUN - 1;
 @@ -1163,10 +1365,42 @@ sbp_targ_action1(struct cam_sim *sim, un
  		xpt_done(ccb);
  		break;
  	}
 +#ifdef CAM_NEW_TRAN_CODE
 +	case XPT_SET_TRAN_SETTINGS:
 +		ccb->ccb_h.status = CAM_REQ_INVALID;
 +		xpt_done(ccb);
 +		break;
 +	case XPT_GET_TRAN_SETTINGS:
 +	{
 +		struct ccb_trans_settings *cts = &ccb->cts;
 +		struct ccb_trans_settings_scsi *scsi =
 +			&cts->proto_specific.scsi;
 +		struct ccb_trans_settings_spi *spi =
 +			&cts->xport_specific.spi;
 +
 +		cts->protocol = PROTO_SCSI;
 +		cts->protocol_version = SCSI_REV_2;
 +		cts->transport = XPORT_FW;     /* should have a FireWire */
 +		cts->transport_version = 2;
 +		spi->valid = CTS_SPI_VALID_DISC;
 +		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
 +		scsi->valid = CTS_SCSI_VALID_TQ;
 +		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
 +#if 0
 +		printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:\n",
 +			device_get_nameunit(sc->fd.dev),
 +			ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
 +#endif
 +		cts->ccb_h.status = CAM_REQ_CMP;
 +		xpt_done(ccb);
 +		break;
 +	}
 +#endif
 +
  	default:
 -		printf("%s: unknown function %d\n",
 +		printf("%s: unknown function 0x%x\n",
  		    __func__, ccb->ccb_h.func_code);
 -		ccb->ccb_h.status = CAM_REQ_INVALID;
 +		ccb->ccb_h.status = CAM_PROVIDE_FAIL;
  		xpt_done(ccb);
  		break;
  	}
 @@ -1245,7 +1479,7 @@ sbp_targ_cmd_handler(struct fw_xfer *xfe
  	atio->ccb_h.target_id = 0; /* XXX */
  	atio->ccb_h.target_lun = orbi->login->lstate->lun;
  	atio->sense_len = 0;
 -	atio->tag_action = 1; /* XXX */
 +	atio->tag_action = MSG_SIMPLE_TASK;
  	atio->tag_id = orbi->orb_lo;
  	atio->init_id = orbi->login->id;
  
 @@ -1429,7 +1663,7 @@ sbp_targ_mgm_handler(struct fw_xfer *xfe
  		login->loginres.recon_hold = htons(login->hold_sec);
  
  		STAILQ_INSERT_TAIL(&lstate->logins, login, link);
 -		fwmem_write_block(orbi->fwdev, NULL, /*spd*/2, orb[2], orb[3],
 +		fwmem_write_block(orbi->fwdev, NULL, /*spd*/FWSPD_S400, orb[2], orb[3],
  		    sizeof(struct sbp_login_res), (void *)&login->loginres,
  		    fw_asy_callback_free);
  		/* XXX return status after loginres is successfully written */
 @@ -1515,10 +1749,11 @@ sbp_targ_fetch_orb(struct sbp_targ_softc
  	orbi->orb_lo = orb_lo;
  	orbi->status.orb_hi = htons(orb_hi);
  	orbi->status.orb_lo = htonl(orb_lo);
 +	orbi->page_table = NULL;
  
  	switch (mode) {
  	case FETCH_MGM:
 -		fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
 +		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
  		    sizeof(uint32_t) * 8, &orbi->orb[0],
  		    sbp_targ_mgm_handler);
  		break;
 @@ -1545,14 +1780,14 @@ sbp_targ_fetch_orb(struct sbp_targ_softc
  		SLIST_REMOVE_HEAD(&login->lstate->accept_tios, sim_links.sle);
  		STAILQ_INSERT_TAIL(&login->orbs, orbi, link);
  		SBP_UNLOCK(sc);
 -		fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
 +		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
  		    sizeof(uint32_t) * 8, &orbi->orb[0],
  		    sbp_targ_cmd_handler);
  		break;
  	case FETCH_POINTER:
  		orbi->state = ORBI_STATUS_POINTER;
  		login->flags |= F_LINK_ACTIVE;
 -		fwmem_read_block(fwdev, (void *)orbi, /*spd*/2, orb_hi, orb_lo,
 +		fwmem_read_block(fwdev, (void *)orbi, /*spd*/FWSPD_S400, orb_hi, orb_lo,
  		    sizeof(uint32_t) * 2, &orbi->orb[0],
  		    sbp_targ_pointer_handler);
  		break;
 @@ -1709,7 +1944,7 @@ done:
  	if (rtcode != 0)
  		printf("%s: rtcode = %d\n", __func__, rtcode);
  	sfp = &xfer->send.hdr;
 -	xfer->send.spd = 2; /* XXX */
 +	xfer->send.spd = FWSPD_S400;
  	xfer->hand = sbp_targ_resp_callback;
  	sfp->mode.wres.dst = fp->mode.wreqb.src;
  	sfp->mode.wres.tlrt = fp->mode.wreqb.tlrt;
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: sbruno 
State-Changed-When: Wed Jan 25 23:52:41 UTC 2012 
State-Changed-Why:  


http://www.freebsd.org/cgi/query-pr.cgi?pr=119575 
State-Changed-From-To: patched->closed 
State-Changed-By: sbruno 
State-Changed-When: Thu Apr 4 15:28:01 UTC 2013 
State-Changed-Why:  
Patches applied quite some time ago 

http://www.freebsd.org/cgi/query-pr.cgi?pr=119575 
>Unformatted:
