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; }
static int fw_close (struct dev_close_args *ap) { cdev_t dev = ap->a_head.a_dev; struct firewire_softc *sc; struct firewire_comm *fc; struct fw_drv1 *d; int unit = DEV2UNIT(dev); struct fw_xfer *xfer; struct fw_bind *fwb; int err = 0; if (DEV_FWMEM(dev)) return fwmem_close(ap); sc = devclass_get_softc(firewire_devclass, unit); fc = sc->fc; d = (struct fw_drv1 *)dev->si_drv1; 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); } /* remove binding */ for (fwb = STAILQ_FIRST(&ir->binds); fwb != NULL; fwb = STAILQ_FIRST(&ir->binds)) { STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist); STAILQ_REMOVE_HEAD(&ir->binds, chlist); kfree(fwb, M_FW); } 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; } kfree(dev->si_drv1, M_FW); dev->si_drv1 = NULL; return err; }