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