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