Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Feb 2008 05:36:21 +0900
From:      "Hidetoshi Shimokawa" <simokawa@FreeBSD.ORG>
To:        "Sean Bruno" <sbruno@miralink.com>
Cc:        freebsd-firewire@freebsd.org
Subject:   Re: Binding sbp_targ to another address
Message-ID:  <626eb4530802281236q7b81ee9cn1a7067b149c04193@mail.gmail.com>
In-Reply-To: <47C36A3E.1070701@miralink.com>
References:  <47C31B2A.2030701@miralink.com> <47C36A3E.1070701@miralink.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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@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@FreeBSD.ORG



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