static void fwip_stop(struct fwip_softc *fwip) { struct firewire_comm *fc; struct fw_xferq *xferq; struct ifnet *ifp = fwip->fw_softc.fwip_ifp; struct fw_xfer *xfer, *next; int i; fc = fwip->fd.fc; if (fwip->dma_ch >= 0) { xferq = fc->ir[fwip->dma_ch]; if (xferq->flag & FWXFERQ_RUNNING) fc->irx_disable(fc, fwip->dma_ch); xferq->flag &= ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); xferq->hand = NULL; for (i = 0; i < xferq->bnchunk; i ++) m_freem(xferq->bulkxfer[i].mbuf); free(xferq->bulkxfer, M_FWIP); fw_bindremove(fc, &fwip->fwb); for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL; xfer = next) { next = STAILQ_NEXT(xfer, link); fw_xfer_free(xfer); } for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL; xfer = next) { next = STAILQ_NEXT(xfer, link); fw_xfer_free(xfer); } STAILQ_INIT(&fwip->xferlist); xferq->bulkxfer = NULL; fwip->dma_ch = -1; } #if defined(__FreeBSD__) ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); #else ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); #endif }
static int fw_close(struct cdev *dev, int flags, int fmt, fw_proc *td) { struct firewire_comm *fc; struct fw_drv1 *d; struct fw_xfer *xfer; struct fw_bind *fwb; int err = 0; if (DEV_FWMEM(dev)) return fwmem_close(dev, flags, fmt, td); d = dev->si_drv1; fc = d->fc; /* remove binding */ for (fwb = STAILQ_FIRST(&d->binds); fwb != NULL; fwb = STAILQ_FIRST(&d->binds)) { fw_bindremove(fc, fwb); STAILQ_REMOVE_HEAD(&d->binds, chlist); fw_xferlist_remove(&fwb->xferlist); free(fwb, M_FW); } if (d->ir != NULL) { struct fw_xferq *ir = d->ir; if ((ir->flag & FWXFERQ_OPEN) == 0) return (EINVAL); if (ir->flag & FWXFERQ_RUNNING) { ir->flag &= ~FWXFERQ_RUNNING; fc->irx_disable(fc, ir->dmach); } /* free extbuf */ fwdev_freebuf(ir); /* drain receiving buffer */ for (xfer = STAILQ_FIRST(&ir->q); xfer != NULL; xfer = STAILQ_FIRST(&ir->q)) { ir->queued--; STAILQ_REMOVE_HEAD(&ir->q, link); xfer->resp = 0; fw_xfer_done(xfer); } ir->flag &= ~(FWXFERQ_OPEN | FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); d->ir = NULL; } if (d->it != NULL) { struct fw_xferq *it = d->it; if ((it->flag & FWXFERQ_OPEN) == 0) return (EINVAL); if (it->flag & FWXFERQ_RUNNING) { it->flag &= ~FWXFERQ_RUNNING; fc->itx_disable(fc, it->dmach); } /* free extbuf */ fwdev_freebuf(it); it->flag &= ~(FWXFERQ_OPEN | FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); d->it = NULL; } free(dev->si_drv1, M_FW); dev->si_drv1 = NULL; return err; }