Binding sbp_targ to another address
Hidetoshi Shimokawa
simokawa at FreeBSD.ORG
Thu Feb 28 20:36:22 UTC 2008
You are right about using fw_bindadd() but I'm afraid that
you should not implement it in sbp_targ because it is not
sbp specific as far as I remember.
On Tue, Feb 26, 2008 at 10:24 AM, Sean Bruno <sbruno at miralink.com> wrote:
>
> 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;
>
>
>
--
/\ Hidetoshi Shimokawa
\/ simokawa at FreeBSD.ORG
More information about the freebsd-firewire
mailing list