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 <kris...@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);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to