Date: Mon, 25 Feb 2008 17:24:14 -0800 From: Sean Bruno <sbruno@miralink.com> To: freebsd-firewire@freebsd.org Cc: Hidetoshi Shimokawa <simokawa@FreeBSD.ORG> Subject: Re: Binding sbp_targ to another address Message-ID: <47C36A3E.1070701@miralink.com> In-Reply-To: <47C31B2A.2030701@miralink.com> References: <47C31B2A.2030701@miralink.com>
next in thread | previous in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?47C36A3E.1070701>