Module Name:    src
Committed By:   ahoka
Date:           Sun Mar 27 13:33:04 UTC 2011

Modified Files:
        src/sys/dev/nand: files.nand nand.c nand.h nandemulator.c

Log Message:
Add support for redifining page read and program functions by drivers.
Some controllers implement read/write in one step, so this is required
to support those.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/nand/files.nand
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/nand/nand.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/nand/nand.h
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/nand/nandemulator.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/nand/files.nand
diff -u src/sys/dev/nand/files.nand:1.2 src/sys/dev/nand/files.nand:1.3
--- src/sys/dev/nand/files.nand:1.2	Wed Mar  9 10:05:08 2011
+++ src/sys/dev/nand/files.nand	Sun Mar 27 13:33:04 2011
@@ -1,4 +1,4 @@
-# $NetBSD: files.nand,v 1.2 2011/03/09 10:05:08 ahoka Exp $
+# $NetBSD: files.nand,v 1.3 2011/03/27 13:33:04 ahoka Exp $
 
 define	nandbus	{ }
 
@@ -15,3 +15,5 @@
 file	dev/nand/nandemulator.c	nandemulator
 
 defflag opt_nand.h		NAND_BBT
+defflag opt_nand.h		NAND_DEBUG
+defflag opt_nand.h		NAND_VERBOSE

Index: src/sys/dev/nand/nand.c
diff -u src/sys/dev/nand/nand.c:1.5 src/sys/dev/nand/nand.c:1.6
--- src/sys/dev/nand/nand.c:1.5	Wed Mar  9 12:33:59 2011
+++ src/sys/dev/nand/nand.c	Sun Mar 27 13:33:04 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nand.c,v 1.5 2011/03/09 12:33:59 ahoka Exp $	*/
+/*	$NetBSD: nand.c,v 1.6 2011/03/27 13:33:04 ahoka Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -34,7 +34,7 @@
 /* Common driver for NAND chips implementing the ONFI 2.2 specification */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nand.c,v 1.5 2011/03/09 12:33:59 ahoka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nand.c,v 1.6 2011/03/27 13:33:04 ahoka Exp $");
 
 #include "locators.h"
 
@@ -63,9 +63,7 @@
 static int nand_search(device_t, cfdata_t, const int *, void *);
 static void nand_address_row(device_t, size_t);
 static void nand_address_column(device_t, size_t, size_t);
-static void nand_readid(device_t, struct nand_chip *);
-static void nand_read_parameter_page(device_t, struct nand_chip *);
-static const char *nand_midtoname(int);
+static int nand_fill_chip_structure(device_t, struct nand_chip *);
 static int nand_scan_media(device_t, struct nand_chip *);
 static bool nand_check_wp(device_t);
 
@@ -79,6 +77,7 @@
 int nand_cachesync_timeout = 1;
 int nand_cachesync_nodenum;
 
+#ifdef NAND_VERBOSE
 const struct nand_manufacturer nand_mfrs[] = {
 	{ NAND_MFR_AMD,		"AMD" },
 	{ NAND_MFR_FUJITSU,	"Fujitsu" },
@@ -92,6 +91,22 @@
 	{ NAND_MFR_UNKNOWN,	"Unknown" }
 };
 
+static const char *
+nand_midtoname(int id)
+{
+	int i;
+
+	for (i = 0; nand_mfrs[i].id != 0; i++) {
+		if (nand_mfrs[i].id == id)
+			return nand_mfrs[i].name;
+	}
+
+	KASSERT(nand_mfrs[i].id == 0);
+
+	return nand_mfrs[i].name;
+}
+#endif
+
 /* ARGSUSED */
 int
 nand_match(device_t parent, cfdata_t match, void *aux)
@@ -108,7 +123,7 @@
 	struct nand_chip *chip = &sc->sc_chip;
 
 	sc->sc_dev = self;
-	sc->nand_dev = parent;
+	sc->controller_dev = parent;
 	sc->nand_if = naa->naa_nand_if;
 
 	aprint_naive("\n");
@@ -238,6 +253,7 @@
 	return UNCONF;
 }
 
+/* ask for a nand driver to attach to the controller */
 device_t
 nand_attach_mi(struct nand_interface *nand_if, device_t parent)
 {
@@ -245,23 +261,50 @@
 
 	KASSERT(nand_if != NULL);
 
+	/* fill the defaults if we have null pointers */
+	if (nand_if->program_page == NULL) {
+		nand_if->program_page = &nand_default_program_page;
+	}
+
+	if (nand_if->read_page == NULL) {
+		nand_if->read_page = &nand_default_read_page;
+	}
+
 	arg.naa_nand_if = nand_if;
 	return config_found_ia(parent, "nandbus", &arg, nand_print);
 }
 
-static const char *
-nand_midtoname(int id)
+/* default everything to reasonable values, to ease future api changes */
+void
+nand_init_interface(struct nand_interface *interface)
 {
-	int i;
-
-	for (i = 0; nand_mfrs[i].id != 0; i++) {
-		if (nand_mfrs[i].id == id)
-			return nand_mfrs[i].name;
-	}
-
-	KASSERT(nand_mfrs[i].id == 0);
+	interface->select = &nand_default_select;
+	interface->command = NULL;
+	interface->address = NULL;
+	interface->read_buf_byte = NULL;
+	interface->read_buf_word = NULL;
+	interface->read_byte = NULL;
+	interface->read_word = NULL;
+	interface->write_buf_byte = NULL;
+	interface->write_buf_word = NULL;
+	interface->write_byte = NULL;
+	interface->write_word = NULL;
+	interface->busy = NULL;
+
+	/*-
+	 * most drivers dont want to change this, but some implement
+	 * read/program in one step
+	 */
+	interface->program_page = &nand_default_program_page;
+	interface->read_page = &nand_default_read_page;
 
-	return nand_mfrs[i].name;
+	/* default to soft ecc, that should work everywhere */
+	interface->ecc_compute = &nand_default_ecc_compute;
+	interface->ecc_correct = &nand_default_ecc_correct;
+	interface->ecc_prepare = NULL;
+	interface->ecc.necc_code_size = 3;
+	interface->ecc.necc_block_size = 256;
+	interface->ecc.necc_type = NAND_ECC_TYPE_SW;
 }
 
 #if 0
@@ -284,7 +327,7 @@
 #endif
 
 static int
-nand_read_legacy_parameters(device_t self, struct nand_chip *chip)
+nand_fill_chip_structure_legacy(device_t self, struct nand_chip *chip)
 {
 	switch (chip->nc_manf_id) {
 	case NAND_MFR_MICRON:
@@ -327,9 +370,9 @@
 		
 		aprint_normal(": Legacy NAND Flash\n");
 		
-		nand_readid(self, chip);
+		nand_read_id(self, &chip->nc_manf_id, &chip->nc_dev_id);
 
-		if (nand_read_legacy_parameters(self, chip)) {
+		if (nand_fill_chip_structure_legacy(self, chip)) {
 			aprint_error_dev(self,
 			    "can't read device parameters for legacy chip\n");
 			return 1;
@@ -339,8 +382,14 @@
 
 		aprint_normal(": ONFI NAND Flash\n");
 
-		nand_readid(self, chip);
-		nand_read_parameter_page(self, chip);
+		nand_read_id(self, &chip->nc_manf_id, &chip->nc_dev_id);
+		
+		if (nand_fill_chip_structure(self, chip)) {
+			aprint_error_dev(self,
+			    "can't read device parameters\n");
+			
+			return 1;
+		}
 	}
 
 #ifdef NAND_VERBOSE
@@ -425,37 +474,41 @@
 	return 0;
 }
 
-static void
-nand_readid(device_t self, struct nand_chip *chip)
+void
+nand_read_id(device_t self, uint8_t *manf, uint8_t *dev)
 {
 	nand_select(self, true);
 	nand_command(self, ONFI_READ_ID);
 	nand_address(self, 0x00);
 	
-	nand_read_byte(self, &chip->nc_manf_id);
-	nand_read_byte(self, &chip->nc_dev_id);
+	nand_read_byte(self, manf);
+	nand_read_byte(self, dev);
 	
 	nand_select(self, false);
 }
 
-static void
-nand_read_parameter_page(device_t self, struct nand_chip *chip)
+int
+nand_read_parameter_page(device_t self, struct onfi_parameter_page *params)
 {
-	struct onfi_parameter_page params;
 	uint8_t *bufp;
-	uint8_t	vendor[13], model[21];
 	uint16_t crc;
-	int i;
+	int i;//, tries = 0;
 
-	KASSERT(sizeof(params) == 256);
+	KASSERT(sizeof(*params) == 256);
 
+//read_params:
+//	tries++;
+	
 	nand_select(self, true);
 	nand_command(self, ONFI_READ_PARAMETER_PAGE);
 	nand_address(self, 0x00);
 
 	nand_busy(self);
 
-	bufp = (uint8_t *)&params;
+	/* TODO check the signature if it contains at least 2 letters */
+
+	bufp = (uint8_t *)params;
+	/* XXX why i am not using read_buf? */
 	for (i = 0; i < 256; i++) {
 		nand_read_byte(self, &bufp[i]);
 	}
@@ -464,9 +517,24 @@
 	/* validate the parameter page with the crc */
 	crc = nand_crc16(bufp, 254);
 
-	if (crc != params.param_integrity_crc) {
+	if (crc != params->param_integrity_crc) {
 		aprint_error_dev(self, "parameter page crc check failed\n");
 		/* TODO: we should read the next parameter page copy */
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+nand_fill_chip_structure(device_t self, struct nand_chip *chip)
+{
+	struct onfi_parameter_page params;
+	uint8_t	vendor[13], model[21];
+	int i;
+
+	if (nand_read_parameter_page(self, &params)) {
+		return 1;
 	}
 
 	/* strip manufacturer and model string */
@@ -480,8 +548,11 @@
 	aprint_normal_dev(self, "vendor: %s, model: %s\n", vendor, model);
 
 	/* XXX TODO multiple LUNs */
-	if (__predict_false(params.param_numluns != 1)) {
-		panic("more than one LUNs are not supported yet!\n");
+	if (params.param_numluns != 1) {
+		aprint_error_dev(self,
+		    "more than one LUNs are not supported yet!\n");
+
+		return 1;
 	}
 
 	chip->nc_size = params.param_pagesize * params.param_blocksize *
@@ -504,6 +575,8 @@
 
 	if (params.param_features & ONFI_FEATURE_EXTENDED_PARAM)
 		chip->nc_flags |= NC_EXTENDED_PARAM;
+
+	return 0;
 }
 
 /* ARGSUSED */
@@ -583,9 +656,9 @@
 	nand_busy(self);
 }
 
-/* read a page with ecc correction */
+/* read a page with ecc correction, default implementation */
 int
-nand_read_page(device_t self, size_t offset, uint8_t *data)
+nand_default_read_page(device_t self, size_t offset, uint8_t *data)
 {
 	struct nand_softc *sc = device_private(self);
 	struct nand_chip *chip = &sc->sc_chip;
@@ -672,8 +745,8 @@
 	return 0;
 }
 
-static int
-nand_program_page(device_t self, size_t page, const uint8_t *data)
+int
+nand_default_program_page(device_t self, size_t page, const uint8_t *data)
 {
 	struct nand_softc *sc = device_private(self);
 	struct nand_chip *chip = &sc->sc_chip;
@@ -739,8 +812,9 @@
 	return 0;
 }
 
+/* read the OOB of a page */
 int
-nand_read_oob(device_t self, size_t page, void *oob)
+nand_read_oob(device_t self, size_t page, uint8_t *oob)
 {
 	struct nand_softc *sc = device_private(self);
 	struct nand_chip *chip = &sc->sc_chip;

Index: src/sys/dev/nand/nand.h
diff -u src/sys/dev/nand/nand.h:1.3 src/sys/dev/nand/nand.h:1.4
--- src/sys/dev/nand/nand.h:1.3	Wed Mar  9 10:05:08 2011
+++ src/sys/dev/nand/nand.h	Sun Mar 27 13:33:04 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nand.h,v 1.3 2011/03/09 10:05:08 ahoka Exp $	*/
+/*	$NetBSD: nand.h,v 1.4 2011/03/27 13:33:04 ahoka Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -41,52 +41,9 @@
 #include <sys/buf.h>
 #include <sys/time.h>
 
+#include <dev/nand/onfi.h>
 #include <dev/flash/flash.h>
 
-/* flash interface implementation */
-int nand_flash_isbad(device_t, uint64_t);
-int nand_flash_markbad(device_t, uint64_t);
-int nand_flash_write(device_t, off_t, size_t, size_t *, const u_char *);
-int nand_flash_read(device_t, off_t, size_t, size_t *, uint8_t *);
-int nand_flash_erase(device_t, struct flash_erase_instruction *);
-
-/* nand specific functions */
-int nand_erase_block(device_t, size_t);
-
-int nand_io_submit(device_t, struct buf *);
-void nand_sync_thread(void *);
-int nand_sync_thread_start(device_t);
-void nand_sync_thread_stop(device_t);
-
-bool nand_isfactorybad(device_t, flash_addr_t);
-bool nand_iswornoutbad(device_t, flash_addr_t);
-bool nand_isbad(device_t, flash_addr_t);
-void nand_markbad(device_t, size_t);
-
-int nand_read_page(device_t, size_t, uint8_t *);
-int nand_read_oob(device_t, size_t, void *);
-
-/*
- * default functions for driver development
- */
-void nand_default_select(device_t, bool);
-int nand_default_ecc_compute(device_t, const uint8_t *, uint8_t *);
-int nand_default_ecc_correct(device_t, uint8_t *, const uint8_t *,
-    const uint8_t *);
-
-static inline void nand_busy(device_t);
-static inline void nand_select(device_t, bool);
-static inline void nand_command(device_t, uint8_t);
-static inline void nand_address(device_t, uint32_t);
-static inline void nand_read_buf_byte(device_t, void *, size_t);
-static inline void nand_read_buf_word(device_t, void *, size_t);
-static inline void nand_read_byte(device_t, uint8_t *);
-static inline void nand_write_buf_byte(device_t, const void *, size_t);
-static inline void nand_write_buf_word(device_t, const void *, size_t);
-//static inline bool nand_block_isbad(device_t, off_t);
-//static inline void nand_block_markbad(device_t, off_t);
-//static inline bool nand_isbusy(device_t);
-
 //#define NAND_DEBUG 1
 #ifdef NAND_DEBUG
 #define DPRINTF(x)	if (nanddebug) printf x
@@ -96,7 +53,7 @@
 #define DPRINTFN(n,x)
 #endif
 
-#define NAND_VERBOSE
+//#define NAND_VERBOSE
 
 /* same as in linux for compatibility */
 enum {
@@ -192,7 +149,7 @@
 /* driver softc for nand */
 struct nand_softc {
 	device_t sc_dev;
-	device_t nand_dev;
+	device_t controller_dev;
 	struct nand_interface *nand_if;
 	void *nand_softc;
 	struct nand_chip sc_chip;
@@ -213,7 +170,8 @@
 /* structure holding the nand api */
 struct nand_interface
 {
-	void (*select) (device_t, bool);
+	/* basic nand controller commands */
+	void (*select) (device_t, bool); /* optional */
 	void (*command) (device_t, uint8_t);
 	void (*address) (device_t, uint8_t);
 	void (*read_buf_byte) (device_t, void *, size_t);
@@ -226,12 +184,17 @@
 	void (*write_word) (device_t, uint16_t);
 	void (*busy) (device_t);
 
+	/* "smart" controllers may override read/program functions */
+	int (*read_page) (device_t, size_t, uint8_t *); /* optional */
+	int (*program_page) (device_t, size_t, const uint8_t *); /* optional */
+
 	/* functions specific to ecc computation */
-	int (*ecc_prepare)(device_t, int);
+	int (*ecc_prepare)(device_t, int); /* optional */
 	int (*ecc_compute)(device_t, const uint8_t *, uint8_t *);
 	int (*ecc_correct)(device_t, uint8_t *, const uint8_t *,
 	    const uint8_t *);
 
+	/* information for the ecc engine */
 	struct nand_ecc ecc;
 
 	/* flash partition information */
@@ -244,23 +207,21 @@
 	struct nand_interface *naa_nand_if;
 };
 
-device_t nand_attach_mi(struct nand_interface *nand_if, device_t dev);
-
 static inline void
 nand_busy(device_t device)
 {
 	struct nand_softc *sc = device_private(device);
 	
 	KASSERT(sc->nand_if->select != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->select(sc->nand_dev, true);
+	sc->nand_if->select(sc->controller_dev, true);
 	
 	if (sc->nand_if->busy != NULL) {
-		sc->nand_if->busy(sc->nand_dev);
+		sc->nand_if->busy(sc->controller_dev);
 	}
 
-	sc->nand_if->select(sc->nand_dev, false);
+	sc->nand_if->select(sc->controller_dev, false);
 }
 
 static inline void
@@ -269,9 +230,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->select != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->select(sc->nand_dev, enable);
+	sc->nand_if->select(sc->controller_dev, enable);
 }
 
 static inline void
@@ -280,9 +241,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->address != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->address(sc->nand_dev, address);
+	sc->nand_if->address(sc->controller_dev, address);
 }
 
 static inline void
@@ -291,9 +252,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->command != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 
-	sc->nand_if->command(sc->nand_dev, command);
+	sc->nand_if->command(sc->controller_dev, command);
 }
 
 static inline void
@@ -302,9 +263,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->read_byte != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->read_byte(sc->nand_dev, data);
+	sc->nand_if->read_byte(sc->controller_dev, data);
 }
 
 static inline void
@@ -313,9 +274,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->write_byte != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->write_byte(sc->nand_dev, data);
+	sc->nand_if->write_byte(sc->controller_dev, data);
 }
 
 static inline void
@@ -324,9 +285,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->read_word != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->read_word(sc->nand_dev, data);
+	sc->nand_if->read_word(sc->controller_dev, data);
 }
 
 static inline void
@@ -335,9 +296,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->write_word != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->write_word(sc->nand_dev, data);
+	sc->nand_if->write_word(sc->controller_dev, data);
 }
 
 static inline void
@@ -346,9 +307,9 @@
 	struct nand_softc *sc = device_private(self);
 
 	KASSERT(sc->nand_if->read_buf_byte != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->read_buf_byte(sc->nand_dev, buf, size);	
+	sc->nand_if->read_buf_byte(sc->controller_dev, buf, size);	
 }
 
 static inline void
@@ -357,9 +318,9 @@
 	struct nand_softc *sc = device_private(self);
 
 	KASSERT(sc->nand_if->read_buf_word != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 	
-	sc->nand_if->read_buf_word(sc->nand_dev, buf, size);	
+	sc->nand_if->read_buf_word(sc->controller_dev, buf, size);	
 }
 
 static inline void
@@ -368,9 +329,9 @@
 	struct nand_softc *sc = device_private(self);
 	
 	KASSERT(sc->nand_if->write_buf_byte != NULL);
-	KASSERT(sc->nand_dev != NULL);
-	
-	sc->nand_if->write_buf_byte(sc->nand_dev, buf, size);	
+	KASSERT(sc->controller_dev != NULL);
+
+	sc->nand_if->write_buf_byte(sc->controller_dev, buf, size);	
 }
 
 static inline void
@@ -379,9 +340,9 @@
 	struct nand_softc *sc = device_private(self);
 
 	KASSERT(sc->nand_if->write_buf_word != NULL);
-	KASSERT(sc->nand_dev != NULL);
-	
-	sc->nand_if->write_buf_word(sc->nand_dev, buf, size);	
+	KASSERT(sc->controller_dev != NULL);
+
+	sc->nand_if->write_buf_word(sc->controller_dev, buf, size);	
 }
 
 static inline int
@@ -391,9 +352,9 @@
 	struct nand_softc *sc = device_private(self);
 
 	KASSERT(sc->nand_if->ecc_correct != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 
-	return sc->nand_if->ecc_correct(sc->nand_dev, data, oldcode, newcode);
+	return sc->nand_if->ecc_correct(sc->controller_dev, data, oldcode, newcode);
 }
 
 static inline void
@@ -402,9 +363,9 @@
 	struct nand_softc *sc = device_private(self);
 
 	KASSERT(sc->nand_if->ecc_compute != NULL);
-	KASSERT(sc->nand_dev != NULL);
+	KASSERT(sc->controller_dev != NULL);
 
-	sc->nand_if->ecc_compute(sc->nand_dev, data, code);	
+	sc->nand_if->ecc_compute(sc->controller_dev, data, code);	
 }
 
 static inline void
@@ -412,10 +373,30 @@
 {
 	struct nand_softc *sc = device_private(self);
 
-	KASSERT(sc->nand_dev != NULL);
-	
+	KASSERT(sc->controller_dev != NULL);
+
 	if (sc->nand_if->ecc_prepare != NULL)
-		sc->nand_if->ecc_prepare(sc->nand_dev, mode);
+		sc->nand_if->ecc_prepare(sc->controller_dev, mode);
+}
+
+static inline int
+nand_program_page(device_t self, size_t offset, const uint8_t *data)
+{
+	struct nand_softc *sc = device_private(self);
+
+	KASSERT(sc->nand_if->program_page != NULL);
+
+	return sc->nand_if->program_page(self, offset, data);
+}
+
+static inline int
+nand_read_page(device_t self, size_t offset, uint8_t *data)
+{
+	struct nand_softc *sc = device_private(self);
+
+	KASSERT(sc->nand_if->read_page != NULL);
+
+	return sc->nand_if->read_page(self, offset, data);
 }
 
 #if 0
@@ -423,11 +404,11 @@
 nand_block_isbad(device_t self, off_t block)
 {
 	struct nand_softc *sc = device_private(self);
-	
+
 	KASSERT(sc->nand_if->block_isbad != NULL);
-	KASSERT(sc->nand_dev != NULL);
-	
-	return sc->nand_if->block_isbad(sc->nand_dev, block);
+	KASSERT(sc->controller_dev != NULL);
+
+	return sc->nand_if->block_isbad(sc->controller_dev, block);
 }
 #endif
 
@@ -473,4 +454,58 @@
 	printf("\n--------------\n");
 }
 
+/* flash interface implementation */
+int nand_flash_isbad(device_t, uint64_t);
+int nand_flash_markbad(device_t, uint64_t);
+int nand_flash_write(device_t, off_t, size_t, size_t *, const u_char *);
+int nand_flash_read(device_t, off_t, size_t, size_t *, uint8_t *);
+int nand_flash_erase(device_t, struct flash_erase_instruction *);
+
+/* nand specific functions */
+int nand_erase_block(device_t, size_t);
+
+int nand_io_submit(device_t, struct buf *);
+void nand_sync_thread(void *);
+int nand_sync_thread_start(device_t);
+void nand_sync_thread_stop(device_t);
+
+bool nand_isfactorybad(device_t, flash_addr_t);
+bool nand_iswornoutbad(device_t, flash_addr_t);
+bool nand_isbad(device_t, flash_addr_t);
+void nand_markbad(device_t, size_t);
+
+//int nand_read_page(device_t, size_t, uint8_t *);
+int nand_read_oob(device_t, size_t, uint8_t *);
+//int nand_program_page(device_t, size_t, const uint8_t *);
+
+device_t nand_attach_mi(struct nand_interface *, device_t);
+void nand_init_interface(struct nand_interface *);
+
+/* controller drivers may use these functions to get info about the chip */
+void nand_read_id(device_t, uint8_t *, uint8_t *);
+int nand_read_parameter_page(device_t, struct onfi_parameter_page *);
+
+/*
+ * default functions for driver development
+ */
+void nand_default_select(device_t, bool);
+int nand_default_ecc_compute(device_t, const uint8_t *, uint8_t *);
+int nand_default_ecc_correct(device_t, uint8_t *, const uint8_t *,
+    const uint8_t *);
+int nand_default_read_page(device_t, size_t, uint8_t *);
+int nand_default_program_page(device_t, size_t, const uint8_t *);
+
+static inline void nand_busy(device_t);
+static inline void nand_select(device_t, bool);
+static inline void nand_command(device_t, uint8_t);
+static inline void nand_address(device_t, uint32_t);
+static inline void nand_read_buf_byte(device_t, void *, size_t);
+static inline void nand_read_buf_word(device_t, void *, size_t);
+static inline void nand_read_byte(device_t, uint8_t *);
+static inline void nand_write_buf_byte(device_t, const void *, size_t);
+static inline void nand_write_buf_word(device_t, const void *, size_t);
+//static inline bool nand_block_isbad(device_t, off_t);
+//static inline void nand_block_markbad(device_t, off_t);
+//static inline bool nand_isbusy(device_t);
+
 #endif	/* _NAND_H_ */

Index: src/sys/dev/nand/nandemulator.c
diff -u src/sys/dev/nand/nandemulator.c:1.1 src/sys/dev/nand/nandemulator.c:1.2
--- src/sys/dev/nand/nandemulator.c:1.1	Sat Feb 26 18:07:31 2011
+++ src/sys/dev/nand/nandemulator.c	Sun Mar 27 13:33:04 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nandemulator.c,v 1.1 2011/02/26 18:07:31 ahoka Exp $	*/
+/*	$NetBSD: nandemulator.c,v 1.2 2011/03/27 13:33:04 ahoka Exp $	*/
 
 /*-
  * Copyright (c) 2011 Department of Software Engineering,
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nandemulator.c,v 1.1 2011/02/26 18:07:31 ahoka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nandemulator.c,v 1.2 2011/03/27 13:33:04 ahoka Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -182,7 +182,8 @@
 
 	sc->sc_dev = self;
 
-	sc->sc_nand_if.select = &nand_default_select;
+	nand_init_interface(&sc->sc_nand_if);
+
 	sc->sc_nand_if.command = &nandemulator_command;
 	sc->sc_nand_if.address = &nandemulator_address;
 	sc->sc_nand_if.read_buf_byte = &nandemulator_read_buf_byte;
@@ -195,12 +196,8 @@
 	sc->sc_nand_if.write_word = &nandemulator_write_word;
 	sc->sc_nand_if.busy = &nandemulator_busy;
 
-	sc->sc_nand_if.ecc_compute = &nand_default_ecc_compute;
-	sc->sc_nand_if.ecc_correct = &nand_default_ecc_correct;
-	sc->sc_nand_if.ecc_prepare = NULL;
 	sc->sc_nand_if.ecc.necc_code_size = 3;
 	sc->sc_nand_if.ecc.necc_block_size = 256;
-	sc->sc_nand_if.ecc.necc_type = NAND_ECC_TYPE_SW;
 
 	if (!pmf_device_register1(sc->sc_dev, NULL, NULL, NULL))
 		aprint_error_dev(sc->sc_dev,

Reply via email to