svn commit: r258200 - head/sys/dev/nand

Ian Lepore ian at FreeBSD.org
Fri Nov 15 23:41:33 UTC 2013


Author: ian
Date: Fri Nov 15 23:41:32 2013
New Revision: 258200
URL: http://svnweb.freebsd.org/changeset/base/258200

Log:
  ONFI parameters are little-endian, hence we must take care to convert them
  to native endianness.  We must also pay attention to unaligned accesses.
  
  Copy the interesting parameters to a new struct so the rest of the code can
  forget about these problems.
  
  Submitted by:	Kristof Provost <kristof at sigsegv.be> (cleanup) and me (orig).

Modified:
  head/sys/dev/nand/nand.c
  head/sys/dev/nand/nand.h
  head/sys/dev/nand/nand_generic.c

Modified: head/sys/dev/nand/nand.c
==============================================================================
--- head/sys/dev/nand/nand.c	Fri Nov 15 23:37:33 2013	(r258199)
+++ head/sys/dev/nand/nand.c	Fri Nov 15 23:41:32 2013	(r258200)
@@ -115,7 +115,7 @@ nand_init(struct nand_softc *nand, devic
 }
 
 void
-nand_onfi_set_params(struct nand_chip *chip, struct onfi_params *params)
+nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params)
 {
 	struct chip_geom *cg;
 

Modified: head/sys/dev/nand/nand.h
==============================================================================
--- head/sys/dev/nand/nand.h	Fri Nov 15 23:37:33 2013	(r258199)
+++ head/sys/dev/nand/nand.h	Fri Nov 15 23:41:32 2013	(r258200)
@@ -235,6 +235,20 @@ struct onfi_params {
 }__attribute__((packed));
 CTASSERT(sizeof(struct onfi_params) == 256);
 
+struct onfi_chip_params {
+	uint8_t luns;
+	uint32_t blocks_per_lun;
+	uint32_t pages_per_block;
+	uint32_t bytes_per_page;
+	uint32_t spare_bytes_per_page;
+	uint16_t t_bers;
+	uint16_t t_prog;
+	uint16_t t_r;
+	uint16_t t_ccs;
+	uint16_t features;
+	uint8_t address_cycles;
+};
+
 struct nand_ecc_data {
 	int	eccsize;		/* Number of data bytes per ECC step */
 	int	eccmode;
@@ -367,7 +381,7 @@ void nand_init(struct nand_softc *nand, 
 void nand_detach(struct nand_softc *nand);
 struct nand_params *nand_get_params(struct nand_id *id);
 
-void nand_onfi_set_params(struct nand_chip *chip, struct onfi_params *params);
+void nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params);
 void nand_set_params(struct nand_chip *chip, struct nand_params *params);
 int  nand_init_stat(struct nand_chip *chip);
 void nand_destroy_stat(struct nand_chip *chip);

Modified: head/sys/dev/nand/nand_generic.c
==============================================================================
--- head/sys/dev/nand/nand_generic.c	Fri Nov 15 23:37:33 2013	(r258199)
+++ head/sys/dev/nand/nand_generic.c	Fri Nov 15 23:41:32 2013	(r258200)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/bus.h>
 #include <sys/conf.h>
+#include <sys/endian.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/rman.h>
@@ -73,7 +74,7 @@ static int small_program_page(device_t, 
 static int small_program_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
 
 static int onfi_is_blk_bad(device_t, uint32_t, uint8_t *);
-static int onfi_read_parameter(struct nand_chip *, struct onfi_params *);
+static int onfi_read_parameter(struct nand_chip *, struct onfi_chip_params *);
 
 static int nand_send_address(device_t, int32_t, int32_t, int8_t);
 
@@ -206,7 +207,7 @@ generic_nand_attach(device_t dev)
 {
 	struct nand_chip *chip;
 	struct nandbus_ivar *ivar;
-	struct onfi_params *onfi_params;
+	struct onfi_chip_params *onfi_chip_params;
 	device_t nandbus, nfc;
 	int err;
 
@@ -225,25 +226,24 @@ generic_nand_attach(device_t dev)
 	chip->nand = device_get_softc(nfc);
 
 	if (ivar->is_onfi) {
-		onfi_params = malloc(sizeof(struct onfi_params),
+		onfi_chip_params = malloc(sizeof(struct onfi_chip_params),
 		    M_NAND, M_WAITOK | M_ZERO);
-		if (onfi_params == NULL)
-			return (ENXIO);
+		if (onfi_chip_params == NULL)
+			return (ENOMEM);
 
-		if (onfi_read_parameter(chip, onfi_params)) {
+		if (onfi_read_parameter(chip, onfi_chip_params)) {
 			nand_debug(NDBG_GEN,"Could not read parameter page!\n");
-			free(onfi_params, M_NAND);
+			free(onfi_chip_params, M_NAND);
 			return (ENXIO);
 		}
 
-		nand_onfi_set_params(chip, onfi_params);
+		nand_onfi_set_params(chip, onfi_chip_params);
 		/* Set proper column and row cycles */
-		ivar->cols = (onfi_params->address_cycles >> 4) & 0xf;
-		ivar->rows = onfi_params->address_cycles & 0xf;
-		free(onfi_params, M_NAND);
+		ivar->cols = (onfi_chip_params->address_cycles >> 4) & 0xf;
+		ivar->rows = onfi_chip_params->address_cycles & 0xf;
+		free(onfi_chip_params, M_NAND);
 
 	} else {
-
 		nand_set_params(chip, ivar->params);
 	}
 
@@ -340,9 +340,10 @@ onfi_crc(const void *buf, size_t buflen)
 }
 
 static int
-onfi_read_parameter(struct nand_chip *chip, struct onfi_params *params)
+onfi_read_parameter(struct nand_chip *chip, struct onfi_chip_params *chip_params)
 {
 	device_t nandbus;
+	struct onfi_params params;
 	int found, sigcount, trycopy;
 
 	nand_debug(NDBG_GEN,"read parameter");
@@ -373,20 +374,32 @@ onfi_read_parameter(struct nand_chip *ch
 	 * rule that the signature is valid if any 2 of the 4 bytes are correct.
 	 */
 	for (found= 0, trycopy = 0; !found && trycopy < 3; trycopy++) {
-		NANDBUS_READ_BUFFER(nandbus, params, sizeof(struct onfi_params));
-		sigcount  = params->signature[0] == 'O';
-		sigcount += params->signature[1] == 'N';
-		sigcount += params->signature[2] == 'F';
-		sigcount += params->signature[3] == 'I';
+		NANDBUS_READ_BUFFER(nandbus, &params, sizeof(struct onfi_params));
+		sigcount  = params.signature[0] == 'O';
+		sigcount += params.signature[1] == 'N';
+		sigcount += params.signature[2] == 'F';
+		sigcount += params.signature[3] == 'I';
 		if (sigcount < 2)
 			continue;
-		if (onfi_crc(params, 254) != params->crc)
+		if (onfi_crc(&params, 254) != params.crc)
 			continue;
 		found = 1;
 	}
 	if (!found)
 		return (ENXIO);
 
+	chip_params->luns = params.luns;
+	chip_params->blocks_per_lun = le32dec(&params.blocks_per_lun);
+	chip_params->pages_per_block = le32dec(&params.pages_per_block);
+	chip_params->bytes_per_page = le32dec(&params.bytes_per_page);
+	chip_params->spare_bytes_per_page = le32dec(&params.spare_bytes_per_page);
+	chip_params->t_bers = le16dec(&params.t_bers);
+	chip_params->t_prog = le16dec(&params.t_prog);
+	chip_params->t_r = le16dec(&params.t_r);
+	chip_params->t_ccs = le16dec(&params.t_ccs);
+	chip_params->features = le16dec(&params.features);
+	chip_params->address_cycles = params.address_cycles;
+
 	return (0);
 }
 


More information about the svn-src-head mailing list