Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Feb 2008 17:24:14 -0800
From:      Sean Bruno <sbruno@miralink.com>
To:        freebsd-firewire@freebsd.org
Cc:        Hidetoshi Shimokawa <simokawa@FreeBSD.ORG>
Subject:   Re: Binding sbp_targ to another address
Message-ID:  <47C36A3E.1070701@miralink.com>
In-Reply-To: <47C31B2A.2030701@miralink.com>
References:  <47C31B2A.2030701@miralink.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Sean Bruno wrote:
> It looks like SBP-2 defines the BUSY_TIMEOUT as a CSR that sbp_targ 
> needs to accept from a windows initiator.
>
> How do I bind sbp_targ to 0x210 so that I can accept that value?
>
> Sean
I came up with the attached diff, I think I got it right.

Bind to the appropriate address and then setup a handler for that register:

Index: /branches/miralink.FreeBSD.6/src/sys/dev/firewire/sbp_targ.c
===================================================================
--- /branches/miralink.FreeBSD.6/src/sys/dev/firewire/sbp_targ.c (revision 5135)
+++ /branches/miralink.FreeBSD.6/src/sys/dev/firewire/sbp_targ.c (revision 5137)
@@ -72,13 +72,14 @@
  * management/command block agent registers
  *
  * BASE 0xffff f001 0000 management port
  * BASE 0xffff f001 0020 command port for login id 0
  * BASE 0xffff f001 0040 command port for login id 1
+ * BASE 0xffff f001 (0x20 * [login_id + 1]) for login_id
  *
  */
-#define SBP_TARG_MGM	 0x10000	/* offset from 0xffff f000 000 */
+#define SBP_TARG_MGM	 0x10000	/* offset from 0xffff f000 0000 */
 #define SBP_TARG_BIND_HI	0xffff
 #define SBP_TARG_BIND_LO(l)	(0xf0000000 + SBP_TARG_MGM + 0x20 * ((l) + 1))
 #define SBP_TARG_BIND_START	(((u_int64_t)SBP_TARG_BIND_HI << 32) | \
 				    SBP_TARG_BIND_LO(-1))
 #define SBP_TARG_BIND_END	(((u_int64_t)SBP_TARG_BIND_HI << 32) | \
@@ -136,10 +137,11 @@
 struct sbp_targ_softc {
         struct firewire_dev_comm fd;
 	struct cam_sim *sim;
 	struct cam_path *path;
 	struct fw_bind fwb;
+	struct fw_bind busy_timeout;
 	int ndevs;
 	int flags;
 	struct crom_chunk unit;
 	struct sbp_targ_lstate *lstate[MAX_LUN];
 	struct sbp_targ_lstate *black_hole;
@@ -170,10 +172,14 @@
 #endif
 };
 
 struct morb4 {
 #if BYTE_ORDER == BIG_ENDIAN
+	uint16_t reserved;
+	uint16_t off_hi;
+	uint32_t off_lo;
+	uint64_t reserved2;	
 	uint32_t n:1,
 		  rq_fmt:2,
 		  :9,
 		  fun:4,
 		  id:16;
@@ -181,10 +187,14 @@
 	uint32_t id:16,
 		  fun:4,
 		  :9,
 		  rq_fmt:2,
 		  n:1;
+	uint64_t reserved2;
+	uint32_t off_lo;
+	uint16_t off_hi;
+	uint16_t reserved;
 #endif
 };
 
 /*
  * Urestricted page table format 
@@ -242,10 +252,11 @@
 static char *orb_fun_name[] = {
 	ORB_FUN_NAMES
 };
 
 static void sbp_targ_recv(struct fw_xfer *);
+static void sbp_targ_busy_timeout(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_send_agent_state(struct fw_xfer *);
 
@@ -629,21 +640,10 @@
 			} else
 				orbi->state = ORBI_STATUS_ABORTED;
 		}
 	}
 }
-#if 0
-static void
-sbp_targ_abort_task(struct orb_info *orbi)
-{
-}
-
-static void
-sbp_targ_abort_task_set(struct orb_info *orbi)
-{
-}
-#endif
 
 static void
 sbp_targ_free_orbi(struct fw_xfer *xfer)
 {
 	struct orb_info *orbi;
@@ -1565,10 +1565,12 @@
 	struct sbp_targ_login *login;
 	struct fw_pkt *fp;
 	uint32_t *orb;
 	struct morb4 *orb4;
 	struct orb_info *orbi;
+	uint32_t aborted_orb;
+	uint64_t abort_hi;
 	int i;
 
 	orbi = (struct orb_info *)xfer->sc;
 	if (xfer->resp != 0) {
 		printf("%s: xfer->resp = %d\n", __func__, xfer->resp);
@@ -1588,11 +1590,11 @@
 	orb = orbi->orb;
 	/* swap payload */
 	for (i = 0; i < 8; i ++) {
 		orb[i] = ntohl(orb[i]);
 	}
-	orb4 = (struct morb4 *)&orb[4];
+	orb4 = (struct morb4 *)&orb;
 	if (debug)
 		printf("%s: %s\n", __func__, orb_fun_name[orb4->fun]);
 
 	orbi->status.src = SRC_NO_NEXT;
 
@@ -1689,11 +1691,14 @@
 		/*
 		 * Find the orb to be aborted.
 		 * If we haven't fetched, just drop it on the floor.
 		 * If we have fetched, process normally and don't worry about it.
 		 */
-		printf("%s: Abort Task recieved for orb\n", __func__);
+		abort_hi = orb4->off_hi;
+		aborted_orb = (abort_hi << 32) + (orb4->off_lo >> 2);
+		printf("%s: Abort Task recieved for orb %d\n", __func__, aborted_orb);
+		sbp_targ_abort((struct orb_info *)aborted_orb);
 		break;
 	case ORB_FUN_ATS: /* TODO */
 		printf("%s: Abort Task Set recieved for orb\n",__func__ );
 		break;
 	case ORB_FUN_LUR: /* TODO */
@@ -1842,10 +1847,11 @@
 	int rtcode = 0;
 
 	if (login_id < 0 || login_id >= MAX_LOGINS)
 		return(RESP_ADDRESS_ERROR);
 
+	printf("%s: made it here\n",__func__);
 	sc = (struct sbp_targ_softc *)xfer->sc;
 	login = sc->logins[login_id];
 	if (login == NULL)
 		return(RESP_ADDRESS_ERROR);
 
@@ -1963,11 +1969,11 @@
 static void
 sbp_targ_recv(struct fw_xfer *xfer)
 {
 	struct fw_pkt *fp, *sfp;
 	struct fw_device *fwdev;
-	uint32_t lo;
+	uint32_t lo = 0;
 	int s, rtcode;
 	struct sbp_targ_softc *sc;
 
 	s = splfw();
 	sc = (struct sbp_targ_softc *)xfer->sc;
@@ -1975,24 +1981,23 @@
 	fwdev = fw_noderesolve_nodeid(sc->fd.fc, fp->mode.wreqb.src & 0x3f);
 	if (fwdev == NULL) {
 		printf("%s: cannot resolve nodeid=%d\n",
 		    __func__, fp->mode.wreqb.src & 0x3f);
 		rtcode = RESP_TYPE_ERROR; /* XXX */
-		goto done;
-	}
-	lo = fp->mode.wreqb.dest_lo;
-	if (lo == SBP_TARG_BIND_LO(-1))
-		rtcode = sbp_targ_mgm(xfer, fwdev);
-	else if (lo >= SBP_TARG_BIND_LO(0))
-		rtcode = sbp_targ_cmd(xfer, fwdev, SBP_TARG_LOGIN_ID(lo),
-		    lo % 0x20);
-	else
-		rtcode = RESP_ADDRESS_ERROR;
-
-done:
+	} else {
+		lo = fp->mode.wreqb.dest_lo;
+		if (lo == SBP_TARG_BIND_LO(-1))
+			rtcode = sbp_targ_mgm(xfer, fwdev);
+		else if (lo >= SBP_TARG_BIND_LO(0))
+			rtcode = sbp_targ_cmd(xfer, fwdev, SBP_TARG_LOGIN_ID(lo),
+		    	lo % 0x20);
+		else
+			rtcode = RESP_ADDRESS_ERROR;
+	}
+
 	if (rtcode != 0)
-		printf("%s: rtcode = %d\n", __func__, rtcode);
+		printf("%s: rtcode = %d lo == 0x%x\n", __func__, rtcode, lo);
 	sfp = &xfer->send.hdr;
 	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;
@@ -2002,10 +2007,47 @@
 
 	fw_asyreq(xfer->fc, -1, xfer);
 	splx(s);
 }
 
+static void
+sbp_targ_busy_timeout(struct fw_xfer *xfer)
+{
+	struct fw_pkt *fp, *sfp;
+	struct fw_device *fwdev;
+	uint32_t lo = 0;
+	int s, rtcode;
+	struct sbp_targ_softc *sc;
+
+	s = splfw();
+	sc = (struct sbp_targ_softc *)xfer->sc;
+	fp = &xfer->recv.hdr;
+	fwdev = fw_noderesolve_nodeid(sc->fd.fc, fp->mode.wreqb.src & 0x3f);
+	if (fwdev == NULL) {
+		printf("%s: cannot resolve nodeid=%d\n",
+		    __func__, fp->mode.wreqb.src & 0x3f);
+		rtcode = RESP_TYPE_ERROR; /* XXX */
+	} else {
+		printf("%s: BUSY_TIMEOUT Recieved\n", __func__);
+		rtcode = 0;
+	}
+	if (rtcode != 0)
+		printf("%s: rtcode = %d lo == 0x%x\n", __func__, rtcode, lo);
+
+	sfp = &xfer->send.hdr;
+	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;
+	sfp->mode.wres.tcode = FWTCODE_WRES;
+	sfp->mode.wres.rtcode = rtcode;
+	sfp->mode.wres.pri = 0;
+
+	fw_asyreq(xfer->fc, -1, xfer);
+	splx(s);
+}
+
 static int
 sbp_targ_attach(device_t dev)
 {
 	struct sbp_targ_softc *sc;
 	struct cam_devq *devq;
@@ -2048,10 +2090,21 @@
 	STAILQ_INIT(&sc->fwb.xferlist);
 	fw_xferlist_add(&sc->fwb.xferlist, M_SBP_TARG,
 	    /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */,
 	    sc->fd.fc, (void *)sc, sbp_targ_recv);
 	fw_bindadd(sc->fd.fc, &sc->fwb);
+	/*
+	 * setup CSR for BUSY_TIMEOUT from 
+	 * initiator(0x210)
+	 */
+	sc->busy_timeout.start = 0xfffff0000000 | BUSY_TIMEOUT;
+	sc->busy_timeout.end =   0xfffff0000000 | BUSY_TIMEOUT; 
+	STAILQ_INIT(&sc->busy_timeout.xferlist);
+	fw_xferlist_add(&sc->busy_timeout.xferlist, M_SBP_TARG,
+	    /*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */,
+	    sc->fd.fc, (void *)sc, sbp_targ_busy_timeout);
+	fw_bindadd(sc->fd.fc, &sc->busy_timeout);
 	return 0;
 
 fail:
 	cam_sim_free(sc->sim, /*free_devq*/TRUE);
 	return (ENXIO);
@@ -2089,10 +2142,11 @@
 		sc->black_hole = NULL;
 	}
 			
 	fw_bindremove(sc->fd.fc, &sc->fwb);
 	fw_xferlist_remove(&sc->fwb.xferlist);
+	fw_bindremove(sc->fd.fc, &sc->busy_timeout);
 
 	return 0;
 }
 
 static devclass_t sbp_targ_devclass;





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