static void cfi_disk_write(struct cfi_softc *sc, struct bio *bp) { long resid; u_int top; KASSERT(sc->sc_width == 1 || sc->sc_width == 2 || sc->sc_width == 4, ("sc_width %d", sc->sc_width)); if (bp->bio_offset > sc->sc_size) { bp->bio_flags |= BIO_ERROR; bp->bio_error = EIO; goto done; } resid = bp->bio_bcount; while (resid > 0) { /* * Finish the current block if we're about to write * to a different block. */ if (sc->sc_writing) { top = sc->sc_wrofs + sc->sc_wrbufsz; if (bp->bio_offset < sc->sc_wrofs || bp->bio_offset >= top) cfi_block_finish(sc); } /* Start writing to a (new) block if applicable. */ if (!sc->sc_writing) { bp->bio_error = cfi_block_start(sc, bp->bio_offset); if (bp->bio_error) { bp->bio_flags |= BIO_ERROR; goto done; } } top = sc->sc_wrofs + sc->sc_wrbufsz; bcopy(bp->bio_data, sc->sc_wrbuf + bp->bio_offset - sc->sc_wrofs, MIN(top - bp->bio_offset, resid)); resid -= MIN(top - bp->bio_offset, resid); } bp->bio_resid = resid; done: biodone(bp); }
static int cfi_devwrite(struct cdev *dev, struct uio *uio, int ioflag) { struct cfi_softc *sc; u_int ofs, top; int error; sc = dev->si_drv1; error = (uio->uio_offset > sc->sc_size) ? EIO : 0; while (error == 0 && uio->uio_resid > 0 && uio->uio_offset < sc->sc_size) { ofs = uio->uio_offset; /* * Finish the current block if we're about to write * to a different block. */ if (sc->sc_writing) { top = sc->sc_wrofs + sc->sc_wrbufsz; if (ofs < sc->sc_wrofs || ofs >= top) cfi_block_finish(sc); } /* Start writing to a (new) block if applicable. */ if (!sc->sc_writing) { error = cfi_block_start(sc, uio->uio_offset); if (error) break; } top = sc->sc_wrofs + sc->sc_wrbufsz; error = uiomove(sc->sc_wrbuf + ofs - sc->sc_wrofs, MIN(top - ofs, uio->uio_resid), uio); } return (error); }