summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorjchandra <jchandra@FreeBSD.org>2012-03-27 15:13:12 +0000
committerjchandra <jchandra@FreeBSD.org>2012-03-27 15:13:12 +0000
commit4cab4cc0c449d52fbd34b538334bc118c4203465 (patch)
tree5714184431ba097d887da8f2470a8d978a946f50 /sys/dev
parent0ee65aa24ed3bff9fc4a2b3f62e35821de1fa15f (diff)
downloadFreeBSD-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.c33
-rw-r--r--sys/dev/cfi/cfi_dev.c4
-rw-r--r--sys/dev/cfi/cfi_disk.c6
-rw-r--r--sys/dev/cfi/cfi_var.h1
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 *);
OpenPOWER on IntegriCloud