diff options
author | jchandra <jchandra@FreeBSD.org> | 2012-03-27 15:13:12 +0000 |
---|---|---|
committer | jchandra <jchandra@FreeBSD.org> | 2012-03-27 15:13:12 +0000 |
commit | 4cab4cc0c449d52fbd34b538334bc118c4203465 (patch) | |
tree | 5714184431ba097d887da8f2470a8d978a946f50 /sys/dev | |
parent | 0ee65aa24ed3bff9fc4a2b3f62e35821de1fa15f (diff) | |
download | FreeBSD-src-4cab4cc0c449d52fbd34b538334bc118c4203465.zip FreeBSD-src-4cab4cc0c449d52fbd34b538334bc118c4203465.tar.gz |
CFI fixes for big endian archs.
The flash commands and responses are little-endian and have to be
byte swapped on big-endian systems. However the raw read of data
need not be swapped.
Make the cfi_read and cfi_write do the swapping, and provide a
cfi_read_raw which does not byte swap for reading data from
flash.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/cfi/cfi_core.c | 33 | ||||
-rw-r--r-- | sys/dev/cfi/cfi_dev.c | 4 | ||||
-rw-r--r-- | sys/dev/cfi/cfi_disk.c | 6 | ||||
-rw-r--r-- | sys/dev/cfi/cfi_var.h | 1 |
4 files changed, 36 insertions, 8 deletions
diff --git a/sys/dev/cfi/cfi_core.c b/sys/dev/cfi/cfi_core.c index 6179f0a..b85f6f3 100644 --- a/sys/dev/cfi/cfi_core.c +++ b/sys/dev/cfi/cfi_core.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/bus.h> #include <sys/conf.h> +#include <sys/endian.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> @@ -54,7 +55,7 @@ devclass_t cfi_devclass; devclass_t cfi_diskclass; uint32_t -cfi_read(struct cfi_softc *sc, u_int ofs) +cfi_read_raw(struct cfi_softc *sc, u_int ofs) { uint32_t val; @@ -76,6 +77,32 @@ cfi_read(struct cfi_softc *sc, u_int ofs) return (val); } +uint32_t +cfi_read(struct cfi_softc *sc, u_int ofs) +{ + uint32_t val; + uint16_t sval; + + ofs &= ~(sc->sc_width - 1); + switch (sc->sc_width) { + case 1: + val = bus_space_read_1(sc->sc_tag, sc->sc_handle, ofs); + break; + case 2: + sval = bus_space_read_2(sc->sc_tag, sc->sc_handle, ofs); + val = le16toh(sval); + break; + case 4: + val = bus_space_read_4(sc->sc_tag, sc->sc_handle, ofs); + val = le32toh(val); + break; + default: + val = ~0; + break; + } + return (val); +} + static void cfi_write(struct cfi_softc *sc, u_int ofs, u_int val) { @@ -86,10 +113,10 @@ cfi_write(struct cfi_softc *sc, u_int ofs, u_int val) bus_space_write_1(sc->sc_tag, sc->sc_handle, ofs, val); break; case 2: - bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, val); + bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, htole16(val)); break; case 4: - bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, val); + bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, htole32(val)); break; } } diff --git a/sys/dev/cfi/cfi_dev.c b/sys/dev/cfi/cfi_dev.c index 9b232bd..d511eac 100644 --- a/sys/dev/cfi/cfi_dev.c +++ b/sys/dev/cfi/cfi_dev.c @@ -103,7 +103,7 @@ cfi_block_start(struct cfi_softc *sc, u_int ofs) /* Read the block from flash for byte-serving. */ ptr.x8 = sc->sc_wrbuf; for (r = 0; r < sc->sc_wrbufsz; r += sc->sc_width) { - val = cfi_read(sc, sc->sc_wrofs + r); + val = cfi_read_raw(sc, sc->sc_wrofs + r); switch (sc->sc_width) { case 1: *(ptr.x8)++ = val; @@ -189,7 +189,7 @@ cfi_devread(struct cdev *dev, struct uio *uio, int ioflag) while (error == 0 && uio->uio_resid > 0 && uio->uio_offset < sc->sc_size) { ofs = uio->uio_offset; - val = cfi_read(sc, ofs); + val = cfi_read_raw(sc, ofs); switch (sc->sc_width) { case 1: buf.x8[0] = val; diff --git a/sys/dev/cfi/cfi_disk.c b/sys/dev/cfi/cfi_disk.c index 20f422b..55f78ea 100644 --- a/sys/dev/cfi/cfi_disk.c +++ b/sys/dev/cfi/cfi_disk.c @@ -182,19 +182,19 @@ cfi_disk_read(struct cfi_softc *sc, struct bio *bp) if (sc->sc_width == 1) { uint8_t *dp = (uint8_t *)bp->bio_data; while (resid > 0 && bp->bio_offset < sc->sc_size) { - *dp++ = cfi_read(sc, bp->bio_offset); + *dp++ = cfi_read_raw(sc, bp->bio_offset); bp->bio_offset += 1, resid -= 1; } } else if (sc->sc_width == 2) { uint16_t *dp = (uint16_t *)bp->bio_data; while (resid > 0 && bp->bio_offset < sc->sc_size) { - *dp++ = cfi_read(sc, bp->bio_offset); + *dp++ = cfi_read_raw(sc, bp->bio_offset); bp->bio_offset += 2, resid -= 2; } } else { uint32_t *dp = (uint32_t *)bp->bio_data; while (resid > 0 && bp->bio_offset < sc->sc_size) { - *dp++ = cfi_read(sc, bp->bio_offset); + *dp++ = cfi_read_raw(sc, bp->bio_offset); bp->bio_offset += 4, resid -= 4; } } diff --git a/sys/dev/cfi/cfi_var.h b/sys/dev/cfi/cfi_var.h index 4dd9a60..15c7769 100644 --- a/sys/dev/cfi/cfi_var.h +++ b/sys/dev/cfi/cfi_var.h @@ -71,6 +71,7 @@ int cfi_probe(device_t); int cfi_attach(device_t); int cfi_detach(device_t); +uint32_t cfi_read_raw(struct cfi_softc *, u_int); uint32_t cfi_read(struct cfi_softc *, u_int); uint8_t cfi_read_qry(struct cfi_softc *, u_int); int cfi_write_block(struct cfi_softc *); |