mtd/drivers/mtd mtdconcat.c,1.3,1.4

rkaiser at infradead.org rkaiser at infradead.org
Fri Mar 7 12:45:02 EST 2003


Update of /home/cvs/mtd/drivers/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv12361

Modified Files:
	mtdconcat.c 
Log Message:
Added NAND support (contributed by Christian Gan <cgan at iders.ca>)


Index: mtdconcat.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/mtdconcat.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- mtdconcat.c	21 May 2002 21:04:25 -0000	1.3
+++ mtdconcat.c	7 Mar 2003 17:44:59 -0000	1.4
@@ -3,6 +3,8 @@
  *
  * (C) 2002 Robert Kaiser <rkaiser at sysgo.de>
  *
+ * NAND support by Christian Gan <cgan at iders.ca>
+ *
  * This code is GPL
  *
  * $Id$
@@ -63,16 +65,16 @@
 		size_t size, retsize;
 
 		if (from >= subdev->size)
-		{
+		{   /* Not destined for this subdev */
 			size  = 0;
 			from -= subdev->size;
 		}
 		else
 		{
 			if (from + len > subdev->size)
-				size = subdev->size - from;
+				size = subdev->size - from; /* First part goes into this subdev */
 			else
-				size = len;
+				size = len; /* Entire transaction goes into this subdev */
 
 			err = subdev->read(subdev, from, size, &retsize, buf);
 
@@ -142,6 +144,214 @@
 	return err;
 }
 
+static int concat_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
+            size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
+{
+	struct mtd_concat *concat = CONCAT(mtd);
+	int err = -EINVAL;
+	int i;
+
+	*retlen = 0;
+
+	for(i = 0; i < concat->num_subdev; i++)
+	{
+		struct mtd_info *subdev = concat->subdev[i];
+		size_t size, retsize;
+        
+		if (from >= subdev->size)
+		{   /* Not destined for this subdev */
+			size  = 0;
+			from -= subdev->size;
+		}
+		else
+		{
+			if (from + len > subdev->size)
+				size = subdev->size - from; /* First part goes into this subdev */
+			else
+				size = len; /* Entire transaction goes into this subdev */
+            
+            if (subdev->read_ecc)
+    			err = subdev->read_ecc(subdev, from, size, &retsize, buf, eccbuf, oobsel);
+            else
+                err = -EINVAL;
+
+			if(err)
+				break;
+
+			*retlen += retsize;
+			len -= size;
+			if(len == 0)
+				break;
+
+			err = -EINVAL;
+			buf += size;
+            if (eccbuf)
+            {
+                eccbuf += subdev->oobsize;
+                /* in nand.c at least, eccbufs are tagged with 2 (int)eccstatus',
+                   we must account for these */
+                eccbuf += 2 * (sizeof(int)); 
+            }
+			from = 0;
+		}
+	}
+	return err;
+}
+
+static int concat_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
+            size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
+{
+	struct mtd_concat *concat = CONCAT(mtd);
+	int err = -EINVAL;
+	int i;
+
+	if (!(mtd->flags & MTD_WRITEABLE))
+		return -EROFS;
+
+	*retlen = 0;
+
+	for(i = 0; i < concat->num_subdev; i++)
+	{
+		struct mtd_info *subdev = concat->subdev[i];
+		size_t size, retsize;
+        
+		if (to >= subdev->size)
+		{
+			size  = 0;
+			to -= subdev->size;
+		}
+		else
+		{
+			if (to + len > subdev->size)
+				size = subdev->size - to;
+			else
+				size = len;
+
+			if (!(subdev->flags & MTD_WRITEABLE))
+				err = -EROFS;
+			else if (subdev->write_ecc)
+				err = subdev->write_ecc(subdev, to, size, &retsize, buf, eccbuf, oobsel);
+            else
+                err = -EINVAL;
+
+			if(err)
+				break;
+
+			*retlen += retsize;
+			len -= size;
+			if(len == 0)
+				break;
+
+			err = -EINVAL;
+			buf += size;
+            if (eccbuf)
+                eccbuf += subdev->oobsize;
+			to = 0;
+		}
+	}
+	return err;
+}
+
+static int concat_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
+            size_t *retlen, u_char *buf)
+{
+	struct mtd_concat *concat = CONCAT(mtd);
+	int err = -EINVAL;
+	int i;
+
+	*retlen = 0;
+
+	for(i = 0; i < concat->num_subdev; i++)
+	{
+		struct mtd_info *subdev = concat->subdev[i];
+		size_t size, retsize;
+        
+		if (from >= subdev->size)
+		{   /* Not destined for this subdev */
+			size  = 0;
+			from -= subdev->size;
+		}
+		else
+		{
+			if (from + len > subdev->size)
+				size = subdev->size - from; /* First part goes into this subdev */
+			else
+				size = len; /* Entire transaction goes into this subdev */
+            
+            if (subdev->read_oob)
+    			err = subdev->read_oob(subdev, from, size, &retsize, buf);
+            else
+                err = -EINVAL;
+
+			if(err)
+				break;
+
+			*retlen += retsize;
+			len -= size;
+			if(len == 0)
+				break;
+
+			err = -EINVAL;
+			buf += size;
+			from = 0;
+		}
+	}
+	return err;
+}
+
+static int concat_write_oob (struct mtd_info *mtd, loff_t to, size_t len, 
+            size_t *retlen, const u_char *buf)
+{
+	struct mtd_concat *concat = CONCAT(mtd);
+	int err = -EINVAL;
+	int i;
+
+	if (!(mtd->flags & MTD_WRITEABLE))
+		return -EROFS;
+
+	*retlen = 0;
+
+	for(i = 0; i < concat->num_subdev; i++)
+	{
+		struct mtd_info *subdev = concat->subdev[i];
+		size_t size, retsize;
+        
+		if (to >= subdev->size)
+		{
+			size  = 0;
+			to -= subdev->size;
+		}
+		else
+		{
+			if (to + len > subdev->size)
+				size = subdev->size - to;
+			else
+				size = len;
+
+			if (!(subdev->flags & MTD_WRITEABLE))
+				err = -EROFS;
+			else if (subdev->write_oob)
+				err = subdev->write_oob(subdev, to, size, &retsize, buf);
+            else
+                err = -EINVAL;
+
+			if(err)
+				break;
+
+			*retlen += retsize;
+			len -= size;
+			if(len == 0)
+				break;
+
+			err = -EINVAL;
+			buf += size;
+			to = 0;
+		}
+	}
+	return err;
+}
+
+
 static void concat_erase_callback (struct erase_info *instr)
 {
 	wake_up((wait_queue_head_t *)instr->priv);
@@ -526,14 +736,18 @@
 	 *       because they are messy to implement and they are not
 	 *       used to a great extent anyway.
 	 */
-	concat->mtd.erase   = concat_erase;
-	concat->mtd.read    = concat_read;
-	concat->mtd.write   = concat_write;
-	concat->mtd.sync    = concat_sync;
-	concat->mtd.lock    = concat_lock;
-	concat->mtd.unlock  = concat_unlock;
-	concat->mtd.suspend = concat_suspend;
-	concat->mtd.resume  = concat_resume;
+	concat->mtd.erase     = concat_erase;
+	concat->mtd.read      = concat_read;    
+	concat->mtd.write     = concat_write;
+	concat->mtd.read_ecc  = concat_read_ecc;    
+	concat->mtd.write_ecc = concat_write_ecc;
+	concat->mtd.read_oob  = concat_read_oob;    
+	concat->mtd.write_oob = concat_write_oob;
+	concat->mtd.sync      = concat_sync;
+	concat->mtd.lock      = concat_lock;
+	concat->mtd.unlock    = concat_unlock;
+	concat->mtd.suspend   = concat_suspend;
+	concat->mtd.resume    = concat_resume;
 
 
 	/*





More information about the linux-mtd-cvs mailing list