struct fw_xfer * fwmem_read_block( struct fw_device *fwdev, caddr_t sc, uint8_t spd, uint16_t dst_hi, uint32_t dst_lo, int len, void *data, void (*hand)(struct fw_xfer *)) { struct fw_xfer *xfer; struct fw_pkt *fp; xfer = fwmem_xfer_req(fwdev, sc, spd, 0, roundup2(len, 4), hand); if (xfer == NULL) return NULL; fp = &xfer->send.hdr; fp->mode.rreqb.tcode = FWTCODE_RREQB; fp->mode.rreqb.dest_hi = dst_hi; fp->mode.rreqb.dest_lo = dst_lo; fp->mode.rreqb.len = len; fp->mode.rreqb.extcode = 0; xfer->send.payload = NULL; xfer->recv.payload = data; if (fwmem_debug) printf("fwmem_read_block: %d %04x:%08x %d\n", fwdev->dst, dst_hi, dst_lo, len); if (fw_asyreq(xfer->fc, -1, xfer) == 0) return xfer; fw_xfer_free(xfer); return NULL; }
struct fw_xfer * fwmem_read_quad( struct fw_device *fwdev, caddr_t sc, uint8_t spd, uint16_t dst_hi, uint32_t dst_lo, void *data, void (*hand)(struct fw_xfer *)) { struct fw_xfer *xfer; struct fw_pkt *fp; xfer = fwmem_xfer_req(fwdev, sc, spd, 0, 4, hand); if (xfer == NULL) { return NULL; } fp = &xfer->send.hdr; fp->mode.rreqq.tcode = FWTCODE_RREQQ; fp->mode.rreqq.dest_hi = dst_hi; fp->mode.rreqq.dest_lo = dst_lo; xfer->send.payload = NULL; xfer->recv.payload = (uint32_t *)data; if (fwmem_debug) printf("fwmem_read_quad: %d %04x:%08x\n", fwdev->dst, dst_hi, dst_lo); if (fw_asyreq(xfer->fc, -1, xfer) == 0) return xfer; fw_xfer_free(xfer); return NULL; }
/* Async. stream output */ static void fwe_as_output(struct fwe_softc *fwe, struct ifnet *ifp) { struct mbuf *m; struct fw_xfer *xfer; struct fw_xferq *xferq; struct fw_pkt *fp; int i = 0; xfer = NULL; xferq = fwe->fd.fc->atq; while ((xferq->queued < xferq->maxq - 1) && (ifp->if_snd.ifq_head != NULL)) { FWE_LOCK(fwe); xfer = STAILQ_FIRST(&fwe->xferlist); if (xfer == NULL) { #if 0 printf("if_fwe: lack of xfer\n"); #endif FWE_UNLOCK(fwe); break; } STAILQ_REMOVE_HEAD(&fwe->xferlist, link); FWE_UNLOCK(fwe); IF_DEQUEUE(&ifp->if_snd, m); if (m == NULL) { FWE_LOCK(fwe); STAILQ_INSERT_HEAD(&fwe->xferlist, xfer, link); FWE_UNLOCK(fwe); break; } #if defined(__DragonFly__) || __FreeBSD_version < 500000 if (ifp->if_bpf != NULL) bpf_mtap(ifp, m); #else BPF_MTAP(ifp, m); #endif /* keep ip packet alignment for alpha */ M_PREPEND(m, ETHER_ALIGN, M_NOWAIT); fp = &xfer->send.hdr; *(uint32_t *)&xfer->send.hdr = *(int32_t *)&fwe->pkt_hdr; fp->mode.stream.len = m->m_pkthdr.len; xfer->mbuf = m; xfer->send.pay_len = m->m_pkthdr.len; if (fw_asyreq(fwe->fd.fc, -1, xfer) != 0) { /* error */ ifp->if_oerrors ++; /* XXX set error code */ fwe_output_callback(xfer); } else { ifp->if_opackets ++; i++; } } #if 0 if (i > 1) printf("%d queued\n", i); #endif if (i > 0) xferq->start(fwe->fd.fc); }