Binding sbp_targ to another address
Sean Bruno
sbruno at miralink.com
Tue Feb 26 01:24:19 UTC 2008
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;
More information about the freebsd-firewire
mailing list