xref: /linux/drivers/mtd/nftlcore.c (revision bd628c1bed7902ec1f24ba0fe70758949146abbe)
1 /*
2  * Linux driver for NAND Flash Translation Layer
3  *
4  * Copyright © 1999 Machine Vision Holdings, Inc.
5  * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 #define PRERELEASE
23 
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <asm/errno.h>
27 #include <asm/io.h>
28 #include <linux/uaccess.h>
29 #include <linux/delay.h>
30 #include <linux/slab.h>
31 #include <linux/init.h>
32 #include <linux/hdreg.h>
33 #include <linux/blkdev.h>
34 
35 #include <linux/kmod.h>
36 #include <linux/mtd/mtd.h>
37 #include <linux/mtd/rawnand.h>
38 #include <linux/mtd/nftl.h>
39 #include <linux/mtd/blktrans.h>
40 
41 /* maximum number of loops while examining next block, to have a
42    chance to detect consistency problems (they should never happen
43    because of the checks done in the mounting */
44 
45 #define MAX_LOOPS 10000
46 
47 
48 static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
49 {
50 	struct NFTLrecord *nftl;
51 	unsigned long temp;
52 
53 	if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX)
54 		return;
55 	/* OK, this is moderately ugly.  But probably safe.  Alternatives? */
56 	if (memcmp(mtd->name, "DiskOnChip", 10))
57 		return;
58 
59 	pr_debug("NFTL: add_mtd for %s\n", mtd->name);
60 
61 	nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
62 
63 	if (!nftl)
64 		return;
65 
66 	nftl->mbd.mtd = mtd;
67 	nftl->mbd.devnum = -1;
68 
69 	nftl->mbd.tr = tr;
70 
71         if (NFTL_mount(nftl) < 0) {
72 		printk(KERN_WARNING "NFTL: could not mount device\n");
73 		kfree(nftl);
74 		return;
75         }
76 
77 	/* OK, it's a new one. Set up all the data structures. */
78 
79 	/* Calculate geometry */
80 	nftl->cylinders = 1024;
81 	nftl->heads = 16;
82 
83 	temp = nftl->cylinders * nftl->heads;
84 	nftl->sectors = nftl->mbd.size / temp;
85 	if (nftl->mbd.size % temp) {
86 		nftl->sectors++;
87 		temp = nftl->cylinders * nftl->sectors;
88 		nftl->heads = nftl->mbd.size / temp;
89 
90 		if (nftl->mbd.size % temp) {
91 			nftl->heads++;
92 			temp = nftl->heads * nftl->sectors;
93 			nftl->cylinders = nftl->mbd.size / temp;
94 		}
95 	}
96 
97 	if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) {
98 		/*
99 		  Oh no we don't have
100 		   mbd.size == heads * cylinders * sectors
101 		*/
102 		printk(KERN_WARNING "NFTL: cannot calculate a geometry to "
103 		       "match size of 0x%lx.\n", nftl->mbd.size);
104 		printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d "
105 			"(== 0x%lx sects)\n",
106 			nftl->cylinders, nftl->heads , nftl->sectors,
107 			(long)nftl->cylinders * (long)nftl->heads *
108 			(long)nftl->sectors );
109 	}
110 
111 	if (add_mtd_blktrans_dev(&nftl->mbd)) {
112 		kfree(nftl->ReplUnitTable);
113 		kfree(nftl->EUNtable);
114 		kfree(nftl);
115 		return;
116 	}
117 #ifdef PSYCHO_DEBUG
118 	printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a');
119 #endif
120 }
121 
122 static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
123 {
124 	struct NFTLrecord *nftl = (void *)dev;
125 
126 	pr_debug("NFTL: remove_dev (i=%d)\n", dev->devnum);
127 
128 	del_mtd_blktrans_dev(dev);
129 	kfree(nftl->ReplUnitTable);
130 	kfree(nftl->EUNtable);
131 }
132 
133 /*
134  * Read oob data from flash
135  */
136 int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
137 		  size_t *retlen, uint8_t *buf)
138 {
139 	loff_t mask = mtd->writesize - 1;
140 	struct mtd_oob_ops ops;
141 	int res;
142 
143 	ops.mode = MTD_OPS_PLACE_OOB;
144 	ops.ooboffs = offs & mask;
145 	ops.ooblen = len;
146 	ops.oobbuf = buf;
147 	ops.datbuf = NULL;
148 
149 	res = mtd_read_oob(mtd, offs & ~mask, &ops);
150 	*retlen = ops.oobretlen;
151 	return res;
152 }
153 
154 /*
155  * Write oob data to flash
156  */
157 int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
158 		   size_t *retlen, uint8_t *buf)
159 {
160 	loff_t mask = mtd->writesize - 1;
161 	struct mtd_oob_ops ops;
162 	int res;
163 
164 	ops.mode = MTD_OPS_PLACE_OOB;
165 	ops.ooboffs = offs & mask;
166 	ops.ooblen = len;
167 	ops.oobbuf = buf;
168 	ops.datbuf = NULL;
169 
170 	res = mtd_write_oob(mtd, offs & ~mask, &ops);
171 	*retlen = ops.oobretlen;
172 	return res;
173 }
174 
175 #ifdef CONFIG_NFTL_RW
176 
177 /*
178  * Write data and oob to flash
179  */
180 static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
181 		      size_t *retlen, uint8_t *buf, uint8_t *oob)
182 {
183 	loff_t mask = mtd->writesize - 1;
184 	struct mtd_oob_ops ops;
185 	int res;
186 
187 	ops.mode = MTD_OPS_PLACE_OOB;
188 	ops.ooboffs = offs & mask;
189 	ops.ooblen = mtd->oobsize;
190 	ops.oobbuf = oob;
191 	ops.datbuf = buf;
192 	ops.len = len;
193 
194 	res = mtd_write_oob(mtd, offs & ~mask, &ops);
195 	*retlen = ops.retlen;
196 	return res;
197 }
198 
199 /* Actual NFTL access routines */
200 /* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used
201  *	when the give Virtual Unit Chain
202  */
203 static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
204 {
205 	/* For a given Virtual Unit Chain: find or create a free block and
206 	   add it to the chain */
207 	/* We're passed the number of the last EUN in the chain, to save us from
208 	   having to look it up again */
209 	u16 pot = nftl->LastFreeEUN;
210 	int silly = nftl->nb_blocks;
211 
212 	/* Normally, we force a fold to happen before we run out of free blocks completely */
213 	if (!desperate && nftl->numfreeEUNs < 2) {
214 		pr_debug("NFTL_findfreeblock: there are too few free EUNs\n");
215 		return BLOCK_NIL;
216 	}
217 
218 	/* Scan for a free block */
219 	do {
220 		if (nftl->ReplUnitTable[pot] == BLOCK_FREE) {
221 			nftl->LastFreeEUN = pot;
222 			nftl->numfreeEUNs--;
223 			return pot;
224 		}
225 
226 		/* This will probably point to the MediaHdr unit itself,
227 		   right at the beginning of the partition. But that unit
228 		   (and the backup unit too) should have the UCI set
229 		   up so that it's not selected for overwriting */
230 		if (++pot > nftl->lastEUN)
231 			pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN);
232 
233 		if (!silly--) {
234 			printk("Argh! No free blocks found! LastFreeEUN = %d, "
235 			       "FirstEUN = %d\n", nftl->LastFreeEUN,
236 			       le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));
237 			return BLOCK_NIL;
238 		}
239 	} while (pot != nftl->LastFreeEUN);
240 
241 	return BLOCK_NIL;
242 }
243 
244 static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
245 {
246 	struct mtd_info *mtd = nftl->mbd.mtd;
247 	u16 BlockMap[MAX_SECTORS_PER_UNIT];
248 	unsigned char BlockLastState[MAX_SECTORS_PER_UNIT];
249 	unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT];
250 	unsigned int thisEUN;
251 	int block;
252 	int silly;
253 	unsigned int targetEUN;
254 	struct nftl_oob oob;
255 	int inplace = 1;
256 	size_t retlen;
257 
258 	memset(BlockMap, 0xff, sizeof(BlockMap));
259 	memset(BlockFreeFound, 0, sizeof(BlockFreeFound));
260 
261 	thisEUN = nftl->EUNtable[thisVUC];
262 
263 	if (thisEUN == BLOCK_NIL) {
264 		printk(KERN_WARNING "Trying to fold non-existent "
265 		       "Virtual Unit Chain %d!\n", thisVUC);
266 		return BLOCK_NIL;
267 	}
268 
269 	/* Scan to find the Erase Unit which holds the actual data for each
270 	   512-byte block within the Chain.
271 	*/
272 	silly = MAX_LOOPS;
273 	targetEUN = BLOCK_NIL;
274 	while (thisEUN <= nftl->lastEUN ) {
275 		unsigned int status, foldmark;
276 
277 		targetEUN = thisEUN;
278 		for (block = 0; block < nftl->EraseSize / 512; block ++) {
279 			nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
280 				      (block * 512), 16 , &retlen,
281 				      (char *)&oob);
282 			if (block == 2) {
283 				foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
284 				if (foldmark == FOLD_MARK_IN_PROGRESS) {
285 					pr_debug("Write Inhibited on EUN %d\n", thisEUN);
286 					inplace = 0;
287 				} else {
288 					/* There's no other reason not to do inplace,
289 					   except ones that come later. So we don't need
290 					   to preserve inplace */
291 					inplace = 1;
292 				}
293 			}
294 			status = oob.b.Status | oob.b.Status1;
295 			BlockLastState[block] = status;
296 
297 			switch(status) {
298 			case SECTOR_FREE:
299 				BlockFreeFound[block] = 1;
300 				break;
301 
302 			case SECTOR_USED:
303 				if (!BlockFreeFound[block])
304 					BlockMap[block] = thisEUN;
305 				else
306 					printk(KERN_WARNING
307 					       "SECTOR_USED found after SECTOR_FREE "
308 					       "in Virtual Unit Chain %d for block %d\n",
309 					       thisVUC, block);
310 				break;
311 			case SECTOR_DELETED:
312 				if (!BlockFreeFound[block])
313 					BlockMap[block] = BLOCK_NIL;
314 				else
315 					printk(KERN_WARNING
316 					       "SECTOR_DELETED found after SECTOR_FREE "
317 					       "in Virtual Unit Chain %d for block %d\n",
318 					       thisVUC, block);
319 				break;
320 
321 			case SECTOR_IGNORE:
322 				break;
323 			default:
324 				printk("Unknown status for block %d in EUN %d: %x\n",
325 				       block, thisEUN, status);
326 			}
327 		}
328 
329 		if (!silly--) {
330 			printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",
331 			       thisVUC);
332 			return BLOCK_NIL;
333 		}
334 
335 		thisEUN = nftl->ReplUnitTable[thisEUN];
336 	}
337 
338 	if (inplace) {
339 		/* We're being asked to be a fold-in-place. Check
340 		   that all blocks which actually have data associated
341 		   with them (i.e. BlockMap[block] != BLOCK_NIL) are
342 		   either already present or SECTOR_FREE in the target
343 		   block. If not, we're going to have to fold out-of-place
344 		   anyway.
345 		*/
346 		for (block = 0; block < nftl->EraseSize / 512 ; block++) {
347 			if (BlockLastState[block] != SECTOR_FREE &&
348 			    BlockMap[block] != BLOCK_NIL &&
349 			    BlockMap[block] != targetEUN) {
350 				pr_debug("Setting inplace to 0. VUC %d, "
351 				      "block %d was %x lastEUN, "
352 				      "and is in EUN %d (%s) %d\n",
353 				      thisVUC, block, BlockLastState[block],
354 				      BlockMap[block],
355 				      BlockMap[block]== targetEUN ? "==" : "!=",
356 				      targetEUN);
357 				inplace = 0;
358 				break;
359 			}
360 		}
361 
362 		if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) &&
363 		    pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&
364 		    BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=
365 		    SECTOR_FREE) {
366 			pr_debug("Pending write not free in EUN %d. "
367 			      "Folding out of place.\n", targetEUN);
368 			inplace = 0;
369 		}
370 	}
371 
372 	if (!inplace) {
373 		pr_debug("Cannot fold Virtual Unit Chain %d in place. "
374 		      "Trying out-of-place\n", thisVUC);
375 		/* We need to find a targetEUN to fold into. */
376 		targetEUN = NFTL_findfreeblock(nftl, 1);
377 		if (targetEUN == BLOCK_NIL) {
378 			/* Ouch. Now we're screwed. We need to do a
379 			   fold-in-place of another chain to make room
380 			   for this one. We need a better way of selecting
381 			   which chain to fold, because makefreeblock will
382 			   only ask us to fold the same one again.
383 			*/
384 			printk(KERN_WARNING
385 			       "NFTL_findfreeblock(desperate) returns 0xffff.\n");
386 			return BLOCK_NIL;
387 		}
388 	} else {
389 		/* We put a fold mark in the chain we are folding only if we
390                fold in place to help the mount check code. If we do not fold in
391                place, it is possible to find the valid chain by selecting the
392                longer one */
393 		oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
394 		oob.u.c.unused = 0xffffffff;
395 		nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
396 			       8, &retlen, (char *)&oob.u);
397 	}
398 
399 	/* OK. We now know the location of every block in the Virtual Unit Chain,
400 	   and the Erase Unit into which we are supposed to be copying.
401 	   Go for it.
402 	*/
403 	pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN);
404 	for (block = 0; block < nftl->EraseSize / 512 ; block++) {
405 		unsigned char movebuf[512];
406 		int ret;
407 
408 		/* If it's in the target EUN already, or if it's pending write, do nothing */
409 		if (BlockMap[block] == targetEUN ||
410 		    (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) {
411 			continue;
412 		}
413 
414 		/* copy only in non free block (free blocks can only
415                    happen in case of media errors or deleted blocks) */
416 		if (BlockMap[block] == BLOCK_NIL)
417 			continue;
418 
419 		ret = mtd_read(mtd,
420 			       (nftl->EraseSize * BlockMap[block]) + (block * 512),
421 			       512,
422 			       &retlen,
423 			       movebuf);
424 		if (ret < 0 && !mtd_is_bitflip(ret)) {
425 			ret = mtd_read(mtd,
426 				       (nftl->EraseSize * BlockMap[block]) + (block * 512),
427 				       512,
428 				       &retlen,
429 				       movebuf);
430 			if (ret != -EIO)
431 				printk("Error went away on retry.\n");
432 		}
433 		memset(&oob, 0xff, sizeof(struct nftl_oob));
434 		oob.b.Status = oob.b.Status1 = SECTOR_USED;
435 
436 		nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
437 			   (block * 512), 512, &retlen, movebuf, (char *)&oob);
438 	}
439 
440 	/* add the header so that it is now a valid chain */
441 	oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
442 	oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL;
443 
444 	nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
445 		       8, &retlen, (char *)&oob.u);
446 
447 	/* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
448 
449 	/* At this point, we have two different chains for this Virtual Unit, and no way to tell
450 	   them apart. If we crash now, we get confused. However, both contain the same data, so we
451 	   shouldn't actually lose data in this case. It's just that when we load up on a medium which
452 	   has duplicate chains, we need to free one of the chains because it's not necessary any more.
453 	*/
454 	thisEUN = nftl->EUNtable[thisVUC];
455 	pr_debug("Want to erase\n");
456 
457 	/* For each block in the old chain (except the targetEUN of course),
458 	   free it and make it available for future use */
459 	while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
460 		unsigned int EUNtmp;
461 
462 		EUNtmp = nftl->ReplUnitTable[thisEUN];
463 
464 		if (NFTL_formatblock(nftl, thisEUN) < 0) {
465 			/* could not erase : mark block as reserved
466 			 */
467 			nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
468 		} else {
469 			/* correctly erased : mark it as free */
470 			nftl->ReplUnitTable[thisEUN] = BLOCK_FREE;
471 			nftl->numfreeEUNs++;
472 		}
473 		thisEUN = EUNtmp;
474 	}
475 
476 	/* Make this the new start of chain for thisVUC */
477 	nftl->ReplUnitTable[targetEUN] = BLOCK_NIL;
478 	nftl->EUNtable[thisVUC] = targetEUN;
479 
480 	return targetEUN;
481 }
482 
483 static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
484 {
485 	/* This is the part that needs some cleverness applied.
486 	   For now, I'm doing the minimum applicable to actually
487 	   get the thing to work.
488 	   Wear-levelling and other clever stuff needs to be implemented
489 	   and we also need to do some assessment of the results when
490 	   the system loses power half-way through the routine.
491 	*/
492 	u16 LongestChain = 0;
493 	u16 ChainLength = 0, thislen;
494 	u16 chain, EUN;
495 
496 	for (chain = 0; chain < le32_to_cpu(nftl->MediaHdr.FormattedSize) / nftl->EraseSize; chain++) {
497 		EUN = nftl->EUNtable[chain];
498 		thislen = 0;
499 
500 		while (EUN <= nftl->lastEUN) {
501 			thislen++;
502 			//printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN);
503 			EUN = nftl->ReplUnitTable[EUN] & 0x7fff;
504 			if (thislen > 0xff00) {
505 				printk("Endless loop in Virtual Chain %d: Unit %x\n",
506 				       chain, EUN);
507 			}
508 			if (thislen > 0xff10) {
509 				/* Actually, don't return failure. Just ignore this chain and
510 				   get on with it. */
511 				thislen = 0;
512 				break;
513 			}
514 		}
515 
516 		if (thislen > ChainLength) {
517 			//printk("New longest chain is %d with length %d\n", chain, thislen);
518 			ChainLength = thislen;
519 			LongestChain = chain;
520 		}
521 	}
522 
523 	if (ChainLength < 2) {
524 		printk(KERN_WARNING "No Virtual Unit Chains available for folding. "
525 		       "Failing request\n");
526 		return BLOCK_NIL;
527 	}
528 
529 	return NFTL_foldchain (nftl, LongestChain, pendingblock);
530 }
531 
532 /* NFTL_findwriteunit: Return the unit number into which we can write
533                        for this block. Make it available if it isn't already
534 */
535 static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
536 {
537 	u16 lastEUN;
538 	u16 thisVUC = block / (nftl->EraseSize / 512);
539 	struct mtd_info *mtd = nftl->mbd.mtd;
540 	unsigned int writeEUN;
541 	unsigned long blockofs = (block * 512) & (nftl->EraseSize -1);
542 	size_t retlen;
543 	int silly, silly2 = 3;
544 	struct nftl_oob oob;
545 
546 	do {
547 		/* Scan the media to find a unit in the VUC which has
548 		   a free space for the block in question.
549 		*/
550 
551 		/* This condition catches the 0x[7f]fff cases, as well as
552 		   being a sanity check for past-end-of-media access
553 		*/
554 		lastEUN = BLOCK_NIL;
555 		writeEUN = nftl->EUNtable[thisVUC];
556 		silly = MAX_LOOPS;
557 		while (writeEUN <= nftl->lastEUN) {
558 			struct nftl_bci bci;
559 			size_t retlen;
560 			unsigned int status;
561 
562 			lastEUN = writeEUN;
563 
564 			nftl_read_oob(mtd,
565 				      (writeEUN * nftl->EraseSize) + blockofs,
566 				      8, &retlen, (char *)&bci);
567 
568 			pr_debug("Status of block %d in EUN %d is %x\n",
569 			      block , writeEUN, le16_to_cpu(bci.Status));
570 
571 			status = bci.Status | bci.Status1;
572 			switch(status) {
573 			case SECTOR_FREE:
574 				return writeEUN;
575 
576 			case SECTOR_DELETED:
577 			case SECTOR_USED:
578 			case SECTOR_IGNORE:
579 				break;
580 			default:
581 				// Invalid block. Don't use it any more. Must implement.
582 				break;
583 			}
584 
585 			if (!silly--) {
586 				printk(KERN_WARNING
587 				       "Infinite loop in Virtual Unit Chain 0x%x\n",
588 				       thisVUC);
589 				return BLOCK_NIL;
590 			}
591 
592 			/* Skip to next block in chain */
593 			writeEUN = nftl->ReplUnitTable[writeEUN];
594 		}
595 
596 		/* OK. We didn't find one in the existing chain, or there
597 		   is no existing chain. */
598 
599 		/* Try to find an already-free block */
600 		writeEUN = NFTL_findfreeblock(nftl, 0);
601 
602 		if (writeEUN == BLOCK_NIL) {
603 			/* That didn't work - there were no free blocks just
604 			   waiting to be picked up. We're going to have to fold
605 			   a chain to make room.
606 			*/
607 
608 			/* First remember the start of this chain */
609 			//u16 startEUN = nftl->EUNtable[thisVUC];
610 
611 			//printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
612 			writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL);
613 
614 			if (writeEUN == BLOCK_NIL) {
615 				/* OK, we accept that the above comment is
616 				   lying - there may have been free blocks
617 				   last time we called NFTL_findfreeblock(),
618 				   but they are reserved for when we're
619 				   desperate. Well, now we're desperate.
620 				*/
621 				pr_debug("Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
622 				writeEUN = NFTL_findfreeblock(nftl, 1);
623 			}
624 			if (writeEUN == BLOCK_NIL) {
625 				/* Ouch. This should never happen - we should
626 				   always be able to make some room somehow.
627 				   If we get here, we've allocated more storage
628 				   space than actual media, or our makefreeblock
629 				   routine is missing something.
630 				*/
631 				printk(KERN_WARNING "Cannot make free space.\n");
632 				return BLOCK_NIL;
633 			}
634 			//printk("Restarting scan\n");
635 			lastEUN = BLOCK_NIL;
636 			continue;
637 		}
638 
639 		/* We've found a free block. Insert it into the chain. */
640 
641 		if (lastEUN != BLOCK_NIL) {
642 			thisVUC |= 0x8000; /* It's a replacement block */
643 		} else {
644 			/* The first block in a new chain */
645 			nftl->EUNtable[thisVUC] = writeEUN;
646 		}
647 
648 		/* set up the actual EUN we're writing into */
649 		/* Both in our cache... */
650 		nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
651 
652 		/* ... and on the flash itself */
653 		nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
654 			      &retlen, (char *)&oob.u);
655 
656 		oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
657 
658 		nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
659 			       &retlen, (char *)&oob.u);
660 
661 		/* we link the new block to the chain only after the
662                    block is ready. It avoids the case where the chain
663                    could point to a free block */
664 		if (lastEUN != BLOCK_NIL) {
665 			/* Both in our cache... */
666 			nftl->ReplUnitTable[lastEUN] = writeEUN;
667 			/* ... and on the flash itself */
668 			nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
669 				      8, &retlen, (char *)&oob.u);
670 
671 			oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
672 				= cpu_to_le16(writeEUN);
673 
674 			nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
675 				       8, &retlen, (char *)&oob.u);
676 		}
677 
678 		return writeEUN;
679 
680 	} while (silly2--);
681 
682 	printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n",
683 	       thisVUC);
684 	return BLOCK_NIL;
685 }
686 
687 static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
688 			   char *buffer)
689 {
690 	struct NFTLrecord *nftl = (void *)mbd;
691 	u16 writeEUN;
692 	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
693 	size_t retlen;
694 	struct nftl_oob oob;
695 
696 	writeEUN = NFTL_findwriteunit(nftl, block);
697 
698 	if (writeEUN == BLOCK_NIL) {
699 		printk(KERN_WARNING
700 		       "NFTL_writeblock(): Cannot find block to write to\n");
701 		/* If we _still_ haven't got a block to use, we're screwed */
702 		return 1;
703 	}
704 
705 	memset(&oob, 0xff, sizeof(struct nftl_oob));
706 	oob.b.Status = oob.b.Status1 = SECTOR_USED;
707 
708 	nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
709 		   512, &retlen, (char *)buffer, (char *)&oob);
710 	return 0;
711 }
712 #endif /* CONFIG_NFTL_RW */
713 
714 static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
715 			  char *buffer)
716 {
717 	struct NFTLrecord *nftl = (void *)mbd;
718 	struct mtd_info *mtd = nftl->mbd.mtd;
719 	u16 lastgoodEUN;
720 	u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];
721 	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
722 	unsigned int status;
723 	int silly = MAX_LOOPS;
724 	size_t retlen;
725 	struct nftl_bci bci;
726 
727 	lastgoodEUN = BLOCK_NIL;
728 
729 	if (thisEUN != BLOCK_NIL) {
730 		while (thisEUN < nftl->nb_blocks) {
731 			if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
732 					  blockofs, 8, &retlen,
733 					  (char *)&bci) < 0)
734 				status = SECTOR_IGNORE;
735 			else
736 				status = bci.Status | bci.Status1;
737 
738 			switch (status) {
739 			case SECTOR_FREE:
740 				/* no modification of a sector should follow a free sector */
741 				goto the_end;
742 			case SECTOR_DELETED:
743 				lastgoodEUN = BLOCK_NIL;
744 				break;
745 			case SECTOR_USED:
746 				lastgoodEUN = thisEUN;
747 				break;
748 			case SECTOR_IGNORE:
749 				break;
750 			default:
751 				printk("Unknown status for block %ld in EUN %d: %x\n",
752 				       block, thisEUN, status);
753 				break;
754 			}
755 
756 			if (!silly--) {
757 				printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%lx\n",
758 				       block / (nftl->EraseSize / 512));
759 				return 1;
760 			}
761 			thisEUN = nftl->ReplUnitTable[thisEUN];
762 		}
763 	}
764 
765  the_end:
766 	if (lastgoodEUN == BLOCK_NIL) {
767 		/* the requested block is not on the media, return all 0x00 */
768 		memset(buffer, 0, 512);
769 	} else {
770 		loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
771 		size_t retlen;
772 		int res = mtd_read(mtd, ptr, 512, &retlen, buffer);
773 
774 		if (res < 0 && !mtd_is_bitflip(res))
775 			return -EIO;
776 	}
777 	return 0;
778 }
779 
780 static int nftl_getgeo(struct mtd_blktrans_dev *dev,  struct hd_geometry *geo)
781 {
782 	struct NFTLrecord *nftl = (void *)dev;
783 
784 	geo->heads = nftl->heads;
785 	geo->sectors = nftl->sectors;
786 	geo->cylinders = nftl->cylinders;
787 
788 	return 0;
789 }
790 
791 /****************************************************************************
792  *
793  * Module stuff
794  *
795  ****************************************************************************/
796 
797 
798 static struct mtd_blktrans_ops nftl_tr = {
799 	.name		= "nftl",
800 	.major		= NFTL_MAJOR,
801 	.part_bits	= NFTL_PARTN_BITS,
802 	.blksize 	= 512,
803 	.getgeo		= nftl_getgeo,
804 	.readsect	= nftl_readblock,
805 #ifdef CONFIG_NFTL_RW
806 	.writesect	= nftl_writeblock,
807 #endif
808 	.add_mtd	= nftl_add_mtd,
809 	.remove_dev	= nftl_remove_dev,
810 	.owner		= THIS_MODULE,
811 };
812 
813 static int __init init_nftl(void)
814 {
815 	return register_mtd_blktrans(&nftl_tr);
816 }
817 
818 static void __exit cleanup_nftl(void)
819 {
820 	deregister_mtd_blktrans(&nftl_tr);
821 }
822 
823 module_init(init_nftl);
824 module_exit(cleanup_nftl);
825 
826 MODULE_LICENSE("GPL");
827 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>, Fabrice Bellard <fabrice.bellard@netgem.com> et al.");
828 MODULE_DESCRIPTION("Support code for NAND Flash Translation Layer, used on M-Systems DiskOnChip 2000 and Millennium");
829 MODULE_ALIAS_BLOCKDEV_MAJOR(NFTL_MAJOR);
830