int bppkqfilter(dev_t dev, struct knote *kn) { struct bpp_softc *sc; struct klist *klist; int s; sc = device_lookup_private(&bpp_cd, BPPUNIT(dev)); switch (kn->kn_filter) { case EVFILT_READ: klist = &sc->sc_rsel.sel_klist; kn->kn_fop = &bppread_filtops; break; case EVFILT_WRITE: klist = &sc->sc_wsel.sel_klist; kn->kn_fop = &bppwrite_filtops; break; default: return EINVAL; } kn->kn_hook = sc; s = splbpp(); SLIST_INSERT_HEAD(klist, kn, kn_selnext); splx(s); return 0; }
int bppopen(dev_t dev, int flags, int mode, struct lwp *l) { int unit = BPPUNIT(dev); struct bpp_softc *sc; struct lsi64854_softc *lsi; uint16_t irq; int s; if (unit >= bpp_cd.cd_ndevs) return ENXIO; sc = device_lookup_private(&bpp_cd, unit); if ((sc->sc_flags & (BPP_OPEN|BPP_XCLUDE)) == (BPP_OPEN|BPP_XCLUDE)) return EBUSY; lsi = &sc->sc_lsi64854; /* Set default parameters */ sc->sc_hwcurrent = sc->sc_hwdefault; s = splbpp(); bpp_setparams(sc, &sc->sc_hwdefault); splx(s); /* Enable interrupts */ irq = BPP_ERR_IRQ_EN; irq |= sc->sc_hwdefault.hw_irq; bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR, irq); return 0; }
int bppopen(dev_t dev, int flags, int mode, struct proc *p) { int unit = BPPUNIT(dev); struct bpp_softc *sc; struct lsi64854_softc *lsi; u_int16_t irq; int s; if (unit >= bpp_cd.cd_ndevs) return (ENXIO); if ((sc = bpp_cd.cd_devs[unit]) == NULL) return (ENXIO); lsi = &sc->sc_lsi64854; /* Set default parameters */ s = splbpp(); bpp_setparams(sc, &sc->sc_hwstate); splx(s); /* Enable interrupts */ irq = BPP_ERR_IRQ_EN; irq |= sc->sc_hwstate.hw_irq; bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR, irq); return (0); }
static void filt_bppwdetach(struct knote *kn) { struct bpp_softc *sc = kn->kn_hook; int s; s = splbpp(); SLIST_REMOVE(&sc->sc_wsel.sel_klist, kn, knote, kn_selnext); splx(s); }
int bppioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) { struct bpp_softc *sc; struct proc *p = l->l_proc; struct hwstate *hw, *chw; int error = 0; int s; sc = device_lookup_private(&bpp_cd, BPPUNIT(dev)); switch(cmd) { case BPPIOCSPARAM: chw = &sc->sc_hwcurrent; hw = (struct hwstate *)data; /* * Extract and store user-settable bits. */ #define _bpp_set(reg,mask) do { \ chw->reg &= ~(mask); \ chw->reg |= (hw->reg & (mask)); \ } while (/* CONSTCOND */ 0) _bpp_set(hw_hcr, BPP_HCR_DSS_MASK|BPP_HCR_DSW_MASK); _bpp_set(hw_ocr, BPP_OCR_USER); _bpp_set(hw_tcr, BPP_TCR_USER); _bpp_set(hw_or, BPP_OR_USER); _bpp_set(hw_irq, BPP_IRQ_USER); #undef _bpp_set /* Apply settings */ s = splbpp(); bpp_setparams(sc, chw); splx(s); break; case BPPIOCGPARAM: *((struct hwstate *)data) = sc->sc_hwcurrent; break; case TIOCEXCL: s = splbpp(); sc->sc_flags |= BPP_XCLUDE; splx(s); break; case TIOCNXCL: s = splbpp(); sc->sc_flags &= ~BPP_XCLUDE; splx(s); break; case FIOASYNC: mutex_enter(proc_lock); if (*(int *)data) { if (sc->sc_asyncproc != NULL) error = EBUSY; else sc->sc_asyncproc = p; } else sc->sc_asyncproc = NULL; mutex_exit(proc_lock); break; default: break; } return error; }
int bppwrite(dev_t dev, struct uio *uio, int flags) { struct bpp_softc *sc; struct lsi64854_softc *lsi; int error = 0; int s; sc = device_lookup_private(&bpp_cd, BPPUNIT(dev)); lsi = &sc->sc_lsi64854; /* * Wait until the DMA engine is free. */ s = splbpp(); while ((sc->sc_flags & BPP_LOCKED) != 0) { if ((flags & IO_NDELAY) != 0) { splx(s); return EWOULDBLOCK; } sc->sc_flags |= BPP_WANT; error = tsleep(sc->sc_buf, PZERO|PCATCH, "bppwrite", 0); if (error != 0) { splx(s); return error; } } sc->sc_flags |= BPP_LOCKED; splx(s); /* * Move data from user space into our private buffer * and start DMA. */ while (uio->uio_resid > 0) { uint8_t *bp = sc->sc_buf; size_t len = min(sc->sc_bufsz, uio->uio_resid); if ((error = uiomove(bp, len, uio)) != 0) break; while (len > 0) { uint8_t tcr; size_t size = len; DMA_SETUP(lsi, &bp, &len, 0, &size); #ifdef DEBUG if (bppdebug) { int i; uint8_t *b = bp; printf("bpp: writing %ld : ", len); for (i = 0; i < len; i++) printf("%c(0x%x)", b[i], b[i]); printf("\n"); } #endif /* Clear direction control bit */ tcr = bus_space_read_1(lsi->sc_bustag, lsi->sc_regs, L64854_REG_TCR); tcr &= ~BPP_TCR_DIR; bus_space_write_1(lsi->sc_bustag, lsi->sc_regs, L64854_REG_TCR, tcr); /* Enable DMA */ s = splbpp(); DMA_GO(lsi); error = tsleep(sc, PZERO|PCATCH, "bppdma", 0); splx(s); if (error != 0) goto out; /* Bail out if bottom half reported an error */ if ((error = sc->sc_error) != 0) goto out; /* * lsi64854_pp_intr() does this part. * * len -= size; */ } } out: DPRINTF(("bpp done %x\n", error)); s = splbpp(); sc->sc_flags &= ~BPP_LOCKED; if ((sc->sc_flags & BPP_WANT) != 0) { sc->sc_flags &= ~BPP_WANT; wakeup(sc->sc_buf); } splx(s); return error; }