Binding sbp_targ to another address
Hidetoshi Shimokawa
simokawa at FreeBSD.ORG
Thu Feb 28 21:10:48 UTC 2008
I think we should have something like fwcsr.c to implement CSR and provide
a interface to initialize/manipulate those registers and sbp_targ should use
the interface.
On Fri, Feb 29, 2008 at 5:42 AM, Sean Bruno <sbruno at miralink.com> wrote:
> Hidetoshi Shimokawa wrote:
> > 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.
> >
> >
> Yes. It is not specific to SBP-2, but it is mandatory by SBP-2.
>
> Where do you think it should be bound?
>
> Sean
>
>
> > 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