Binding sbp_targ to another address
Sean Bruno
sbruno at miralink.com
Thu Feb 28 20:42:10 UTC 2008
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;
>>
>>
>>
>>
>
>
>
>
More information about the freebsd-firewire
mailing list