mtd/drivers/mtd/devices doc2000.c,1.53,1.54

David Woodhouse dwmw2 at infradead.org
Mon Jun 30 09:06:04 EDT 2003


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

Modified Files:
	doc2000.c 
Log Message:
Allow large reads/writes on DiskOnChip, for JFFS2

Index: doc2000.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/devices/doc2000.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- doc2000.c	11 Jun 2003 09:45:19 -0000	1.53
+++ doc2000.c	30 Jun 2003 13:06:01 -0000	1.54
@@ -609,6 +609,7 @@
 	unsigned char syndrome[6];
 	volatile char dummy;
 	int i, len256 = 0, ret=0;
+	size_t left = len;
 
 	docptr = this->virtadr;
 
@@ -618,122 +619,131 @@
 
 	down(&this->lock);
 
-	/* Don't allow a single read to cross a 512-byte block boundary */
-	if (from + len > ((from | 0x1ff) + 1))
-		len = ((from | 0x1ff) + 1) - from;
-
-	/* The ECC will not be calculated correctly if less than 512 is read */
-	if (len != 0x200 && eccbuf)
-		printk(KERN_WARNING
-		       "ECC needs a full sector read (adr: %lx size %lx)\n",
-		       (long) from, (long) len);
-
-	/* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
-
-
-	/* Find the chip which is to be used and select it */
-	mychip = &this->chips[from >> (this->chipshift)];
-
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(this, mychip->floor);
-		DoC_SelectChip(this, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(this, mychip->chip);
-	}
+	*retlen = 0;
+	while (left) {
+		len = left;
+
+		/* Don't allow a single read to cross a 512-byte block boundary */
+		if (from + len > ((from | 0x1ff) + 1))
+			len = ((from | 0x1ff) + 1) - from;
+
+		/* The ECC will not be calculated correctly if less than 512 is read */
+		if (len != 0x200 && eccbuf)
+			printk(KERN_WARNING
+			       "ECC needs a full sector read (adr: %lx size %lx)\n",
+			       (long) from, (long) len);
+
+		/* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
+
+
+		/* Find the chip which is to be used and select it */
+		mychip = &this->chips[from >> (this->chipshift)];
+
+		if (this->curfloor != mychip->floor) {
+			DoC_SelectFloor(this, mychip->floor);
+			DoC_SelectChip(this, mychip->chip);
+		} else if (this->curchip != mychip->chip) {
+			DoC_SelectChip(this, mychip->chip);
+		}
 
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
+		this->curfloor = mychip->floor;
+		this->curchip = mychip->chip;
 
-	DoC_Command(this,
-		    (!this->page256
-		     && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
-		    CDSN_CTRL_WP);
-	DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
-		    CDSN_CTRL_ECC_IO);
-
-	if (eccbuf) {
-		/* Prime the ECC engine */
-		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
-		WriteDOC(DOC_ECC_EN, docptr, ECCConf);
-	} else {
-		/* disable the ECC engine */
-		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
-		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
-	}
+		DoC_Command(this,
+			    (!this->page256
+			     && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
+			    CDSN_CTRL_WP);
+		DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
+			    CDSN_CTRL_ECC_IO);
 
-	/* treat crossing 256-byte sector for 2M x 8bits devices */
-	if (this->page256 && from + len > (from | 0xff) + 1) {
-		len256 = (from | 0xff) + 1 - from;
-		DoC_ReadBuf(this, buf, len256);
-
-		DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
-		DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
-			    CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
-	}
+		if (eccbuf) {
+			/* Prime the ECC engine */
+			WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+			WriteDOC(DOC_ECC_EN, docptr, ECCConf);
+		} else {
+			/* disable the ECC engine */
+			WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+			WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+		}
+
+		/* treat crossing 256-byte sector for 2M x 8bits devices */
+		if (this->page256 && from + len > (from | 0xff) + 1) {
+			len256 = (from | 0xff) + 1 - from;
+			DoC_ReadBuf(this, buf, len256);
+
+			DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
+			DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
+				    CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
+		}
 
-	DoC_ReadBuf(this, &buf[len256], len - len256);
+		DoC_ReadBuf(this, &buf[len256], len - len256);
 
-	/* Let the caller know we completed it */
-	*retlen = len;
+		/* Let the caller know we completed it */
+		*retlen += len;
 
-	if (eccbuf) {
-		/* Read the ECC data through the DiskOnChip ECC logic */
-		/* Note: this will work even with 2M x 8bit devices as   */
-		/*       they have 8 bytes of OOB per 256 page. mf.      */
-		DoC_ReadBuf(this, eccbuf, 6);
-
-		/* Flush the pipeline */
-		if (DoC_is_Millennium(this)) {
-			dummy = ReadDOC(docptr, ECCConf);
-			dummy = ReadDOC(docptr, ECCConf);
-			i = ReadDOC(docptr, ECCConf);
-		} else {
-			dummy = ReadDOC(docptr, 2k_ECCStatus);
-			dummy = ReadDOC(docptr, 2k_ECCStatus);
-			i = ReadDOC(docptr, 2k_ECCStatus);
-		}
+		if (eccbuf) {
+			/* Read the ECC data through the DiskOnChip ECC logic */
+			/* Note: this will work even with 2M x 8bit devices as   */
+			/*       they have 8 bytes of OOB per 256 page. mf.      */
+			DoC_ReadBuf(this, eccbuf, 6);
+
+			/* Flush the pipeline */
+			if (DoC_is_Millennium(this)) {
+				dummy = ReadDOC(docptr, ECCConf);
+				dummy = ReadDOC(docptr, ECCConf);
+				i = ReadDOC(docptr, ECCConf);
+			} else {
+				dummy = ReadDOC(docptr, 2k_ECCStatus);
+				dummy = ReadDOC(docptr, 2k_ECCStatus);
+				i = ReadDOC(docptr, 2k_ECCStatus);
+			}
 
-		/* Check the ECC Status */
-		if (i & 0x80) {
-			int nb_errors;
-			/* There was an ECC error */
+			/* Check the ECC Status */
+			if (i & 0x80) {
+				int nb_errors;
+				/* There was an ECC error */
 #ifdef ECC_DEBUG
-			printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
+				printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-			/* Read the ECC syndrom through the DiskOnChip ECC logic.
-			   These syndrome will be all ZERO when there is no error */
-			for (i = 0; i < 6; i++) {
-				syndrome[i] =
-				    ReadDOC(docptr, ECCSyndrome0 + i);
-			}
-                        nb_errors = doc_decode_ecc(buf, syndrome);
+				/* Read the ECC syndrom through the DiskOnChip ECC logic.
+				   These syndrome will be all ZERO when there is no error */
+				for (i = 0; i < 6; i++) {
+					syndrome[i] =
+					    ReadDOC(docptr, ECCSyndrome0 + i);
+				}
+	                        nb_errors = doc_decode_ecc(buf, syndrome);
 
 #ifdef ECC_DEBUG
-			printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
+				printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
 #endif
-                        if (nb_errors < 0) {
-				/* We return error, but have actually done the read. Not that
-				   this can be told to user-space, via sys_read(), but at least
-				   MTD-aware stuff can know about it by checking *retlen */
-				ret = -EIO;
-                        }
-		}
+	                        if (nb_errors < 0) {
+					/* We return error, but have actually done the read. Not that
+					   this can be told to user-space, via sys_read(), but at least
+					   MTD-aware stuff can know about it by checking *retlen */
+					ret = -EIO;
+	                        }
+			}
 
 #ifdef PSYCHO_DEBUG
-		printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-			     (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
-			     eccbuf[3], eccbuf[4], eccbuf[5]);
+			printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+				     (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
+				     eccbuf[3], eccbuf[4], eccbuf[5]);
 #endif
 		
-		/* disable the ECC engine */
-		WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
-	}
+			/* disable the ECC engine */
+			WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
+		}
+
+		/* according to 11.4.1, we need to wait for the busy line 
+	         * drop if we read to the end of the page.  */
+		if(0 == ((from + len) & 0x1ff))
+		{
+		    DoC_WaitReady(this);
+		}
 
-	/* according to 11.4.1, we need to wait for the busy line 
-         * drop if we read to the end of the page.  */
-	if(0 == ((from + *retlen) & 0x1ff))
-	{
-	    DoC_WaitReady(this);
+		from += len;
+		left -= len;
+		buf += len;
 	}
 
 	up(&this->lock);
@@ -758,6 +768,7 @@
 	volatile char dummy;
 	int len256 = 0;
 	struct Nand *mychip;
+	size_t left = len;
 
 	docptr = this->virtadr;
 
@@ -767,55 +778,114 @@
 
 	down(&this->lock);
 
-	/* Don't allow a single write to cross a 512-byte block boundary */
-	if (to + len > ((to | 0x1ff) + 1))
-		len = ((to | 0x1ff) + 1) - to;
-
-	/* The ECC will not be calculated correctly if less than 512 is written */
-	if (len != 0x200 && eccbuf)
-		printk(KERN_WARNING
-		       "ECC needs a full sector write (adr: %lx size %lx)\n",
-		       (long) to, (long) len);
-
-	/* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
-
-	/* Find the chip which is to be used and select it */
-	mychip = &this->chips[to >> (this->chipshift)];
-
-	if (this->curfloor != mychip->floor) {
-		DoC_SelectFloor(this, mychip->floor);
-		DoC_SelectChip(this, mychip->chip);
-	} else if (this->curchip != mychip->chip) {
-		DoC_SelectChip(this, mychip->chip);
-	}
+	*retlen = 0;
+	while (left) {
+		len = left;
+
+		/* Don't allow a single write to cross a 512-byte block boundary */
+		if (to + len > ((to | 0x1ff) + 1))
+			len = ((to | 0x1ff) + 1) - to;
+
+		/* The ECC will not be calculated correctly if less than 512 is written */
+/* DBB-
+		if (len != 0x200 && eccbuf)
+			printk(KERN_WARNING
+			       "ECC needs a full sector write (adr: %lx size %lx)\n",
+			       (long) to, (long) len);
+   -DBB */
+
+		/* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
+
+		/* Find the chip which is to be used and select it */
+		mychip = &this->chips[to >> (this->chipshift)];
+
+		if (this->curfloor != mychip->floor) {
+			DoC_SelectFloor(this, mychip->floor);
+			DoC_SelectChip(this, mychip->chip);
+		} else if (this->curchip != mychip->chip) {
+			DoC_SelectChip(this, mychip->chip);
+		}
 
-	this->curfloor = mychip->floor;
-	this->curchip = mychip->chip;
+		this->curfloor = mychip->floor;
+		this->curchip = mychip->chip;
 
-	/* Set device to main plane of flash */
-	DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
-	DoC_Command(this,
-		    (!this->page256
-		     && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
-		    CDSN_CTRL_WP);
-
-	DoC_Command(this, NAND_CMD_SEQIN, 0);
-	DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
-
-	if (eccbuf) {
-		/* Prime the ECC engine */
-		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
-		WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
-	} else {
-		/* disable the ECC engine */
-		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
-		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
-	}
+		/* Set device to main plane of flash */
+		DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
+		DoC_Command(this,
+			    (!this->page256
+			     && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
+			    CDSN_CTRL_WP);
+
+		DoC_Command(this, NAND_CMD_SEQIN, 0);
+		DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
+
+		if (eccbuf) {
+			/* Prime the ECC engine */
+			WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+			WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+		} else {
+			/* disable the ECC engine */
+			WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
+			WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+		}
+
+		/* treat crossing 256-byte sector for 2M x 8bits devices */
+		if (this->page256 && to + len > (to | 0xff) + 1) {
+			len256 = (to | 0xff) + 1 - to;
+			DoC_WriteBuf(this, buf, len256);
+
+			DoC_Command(this, NAND_CMD_PAGEPROG, 0);
+
+			DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
+			/* There's an implicit DoC_WaitReady() in DoC_Command */
+
+			dummy = ReadDOC(docptr, CDSNSlowIO);
+			DoC_Delay(this, 2);
+
+			if (ReadDOC_(docptr, this->ioreg) & 1) {
+				printk(KERN_ERR "Error programming flash\n");
+				/* Error in programming */
+				*retlen = 0;
+				up(&this->lock);
+				return -EIO;
+			}
+
+			DoC_Command(this, NAND_CMD_SEQIN, 0);
+			DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
+				    CDSN_CTRL_ECC_IO);
+		}
+
+		DoC_WriteBuf(this, &buf[len256], len - len256);
 
-	/* treat crossing 256-byte sector for 2M x 8bits devices */
-	if (this->page256 && to + len > (to | 0xff) + 1) {
-		len256 = (to | 0xff) + 1 - to;
-		DoC_WriteBuf(this, buf, len256);
+		if (eccbuf) {
+			WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
+				 CDSNControl);
+
+			if (DoC_is_Millennium(this)) {
+				WriteDOC(0, docptr, NOP);
+				WriteDOC(0, docptr, NOP);
+				WriteDOC(0, docptr, NOP);
+			} else {
+				WriteDOC_(0, docptr, this->ioreg);
+				WriteDOC_(0, docptr, this->ioreg);
+				WriteDOC_(0, docptr, this->ioreg);
+			}
+
+			/* Read the ECC data through the DiskOnChip ECC logic */
+			for (di = 0; di < 6; di++) {
+				eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
+			}
+
+			/* Reset the ECC engine */
+			WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
+
+#ifdef PSYCHO_DEBUG
+			printk
+			    ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+			     (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+			     eccbuf[4], eccbuf[5]);
+#endif
+		}
 
 		DoC_Command(this, NAND_CMD_PAGEPROG, 0);
 
@@ -833,78 +903,33 @@
 			return -EIO;
 		}
 
-		DoC_Command(this, NAND_CMD_SEQIN, 0);
-		DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
-			    CDSN_CTRL_ECC_IO);
-	}
-
-	DoC_WriteBuf(this, &buf[len256], len - len256);
-
-	if (eccbuf) {
-		WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
-			 CDSNControl);
-
-		if (DoC_is_Millennium(this)) {
-			WriteDOC(0, docptr, NOP);
-			WriteDOC(0, docptr, NOP);
-			WriteDOC(0, docptr, NOP);
-		} else {
-			WriteDOC_(0, docptr, this->ioreg);
-			WriteDOC_(0, docptr, this->ioreg);
-			WriteDOC_(0, docptr, this->ioreg);
-		}
-
-		/* Read the ECC data through the DiskOnChip ECC logic */
-		for (di = 0; di < 6; di++) {
-			eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
-		}
-
-		/* Reset the ECC engine */
-		WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
-
-#ifdef PSYCHO_DEBUG
-		printk
-		    ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
-		     (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
-		     eccbuf[4], eccbuf[5]);
-#endif
-	}
-
-	DoC_Command(this, NAND_CMD_PAGEPROG, 0);
-
-	DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
-	/* There's an implicit DoC_WaitReady() in DoC_Command */
-
-	dummy = ReadDOC(docptr, CDSNSlowIO);
-	DoC_Delay(this, 2);
-
-	if (ReadDOC_(docptr, this->ioreg) & 1) {
-		printk(KERN_ERR "Error programming flash\n");
-		/* Error in programming */
-		*retlen = 0;
-		up(&this->lock);
-		return -EIO;
-	}
-
-	/* Let the caller know we completed it */
-	*retlen = len;
+		/* Let the caller know we completed it */
+		*retlen += len;
 		
-	if (eccbuf) {
-		unsigned char x[8];
-		size_t dummy;
-		int ret;
-
-		/* Write the ECC data to flash */
-		for (di=0; di<6; di++)
-			x[di] = eccbuf[di];
+		if (eccbuf) {
+			unsigned char x[8];
+			size_t dummy;
+			int ret;
+
+			/* Write the ECC data to flash */
+			for (di=0; di<6; di++)
+				x[di] = eccbuf[di];
 		
-		x[6]=0x55;
-		x[7]=0x55;
+			x[6]=0x55;
+			x[7]=0x55;
 		
-		ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
-		up(&this->lock);
-		return ret;
+			ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
+			if (ret) {
+				up(&this->lock);
+				return ret;
+			}
+		}
+
+		to += len;
+		left -= len;
+		buf += len;
 	}
+
 	up(&this->lock);
 	return 0;
 }




More information about the linux-mtd-cvs mailing list