Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Jan 2008 21:24:12 GMT
From:      Sean Bruno <sbruno@miralink.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/119575: sbp_targ cannot handle multiple CTIO's for a single ATIO
Message-ID:  <200801112124.m0BLOCTA070960@www.freebsd.org>
Resent-Message-ID: <200801112130.m0BLU2Q0011856@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         119575
>Category:       misc
>Synopsis:       sbp_targ cannot handle multiple CTIO's for a single ATIO
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jan 11 21:30:02 UTC 2008
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:



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