xref: /linux/drivers/mtd/nftlcore.c (revision 7014568bad55c20b7ee4f439d78c9e875912d51f)
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 
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 
151 	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
152 	*retlen = ops.oobretlen;
153 	return res;
154 }
155 
156 /*
157  * Write oob data to flash
158  */
159 int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
160 		   size_t *retlen, uint8_t *buf)
161 {
162 	struct mtd_oob_ops ops;
163 	int res;
164 
165 	ops.mode = MTD_OOB_PLACE;
166 	ops.ooboffs = offs & (mtd->writesize - 1);
167 	ops.ooblen = len;
168 	ops.oobbuf = buf;
169 	ops.datbuf = NULL;
170 
171 	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
172 	*retlen = ops.oobretlen;
173 	return res;
174 }
175 
176 #ifdef CONFIG_NFTL_RW
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 /* 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 		DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n");
215 		return 0xffff;
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 0xffff;
238 		}
239 	} while (pot != nftl->LastFreeEUN);
240 
241 	return 0xffff;
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 					DEBUG(MTD_DEBUG_LEVEL1,
286 					      "Write Inhibited on EUN %d\n", thisEUN);
287 					inplace = 0;
288 				} else {
289 					/* There's no other reason not to do inplace,
290 					   except ones that come later. So we don't need
291 					   to preserve inplace */
292 					inplace = 1;
293 				}
294 			}
295 			status = oob.b.Status | oob.b.Status1;
296 			BlockLastState[block] = status;
297 
298 			switch(status) {
299 			case SECTOR_FREE:
300 				BlockFreeFound[block] = 1;
301 				break;
302 
303 			case SECTOR_USED:
304 				if (!BlockFreeFound[block])
305 					BlockMap[block] = thisEUN;
306 				else
307 					printk(KERN_WARNING
308 					       "SECTOR_USED found after SECTOR_FREE "
309 					       "in Virtual Unit Chain %d for block %d\n",
310 					       thisVUC, block);
311 				break;
312 			case SECTOR_DELETED:
313 				if (!BlockFreeFound[block])
314 					BlockMap[block] = BLOCK_NIL;
315 				else
316 					printk(KERN_WARNING
317 					       "SECTOR_DELETED found after SECTOR_FREE "
318 					       "in Virtual Unit Chain %d for block %d\n",
319 					       thisVUC, block);
320 				break;
321 
322 			case SECTOR_IGNORE:
323 				break;
324 			default:
325 				printk("Unknown status for block %d in EUN %d: %x\n",
326 				       block, thisEUN, status);
327 			}
328 		}
329 
330 		if (!silly--) {
331 			printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",
332 			       thisVUC);
333 			return BLOCK_NIL;
334 		}
335 
336 		thisEUN = nftl->ReplUnitTable[thisEUN];
337 	}
338 
339 	if (inplace) {
340 		/* We're being asked to be a fold-in-place. Check
341 		   that all blocks which actually have data associated
342 		   with them (i.e. BlockMap[block] != BLOCK_NIL) are
343 		   either already present or SECTOR_FREE in the target
344 		   block. If not, we're going to have to fold out-of-place
345 		   anyway.
346 		*/
347 		for (block = 0; block < nftl->EraseSize / 512 ; block++) {
348 			if (BlockLastState[block] != SECTOR_FREE &&
349 			    BlockMap[block] != BLOCK_NIL &&
350 			    BlockMap[block] != targetEUN) {
351 				DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, "
352 				      "block %d was %x lastEUN, "
353 				      "and is in EUN %d (%s) %d\n",
354 				      thisVUC, block, BlockLastState[block],
355 				      BlockMap[block],
356 				      BlockMap[block]== targetEUN ? "==" : "!=",
357 				      targetEUN);
358 				inplace = 0;
359 				break;
360 			}
361 		}
362 
363 		if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) &&
364 		    pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&
365 		    BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=
366 		    SECTOR_FREE) {
367 			DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. "
368 			      "Folding out of place.\n", targetEUN);
369 			inplace = 0;
370 		}
371 	}
372 
373 	if (!inplace) {
374 		DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "
375 		      "Trying out-of-place\n", thisVUC);
376 		/* We need to find a targetEUN to fold into. */
377 		targetEUN = NFTL_findfreeblock(nftl, 1);
378 		if (targetEUN == BLOCK_NIL) {
379 			/* Ouch. Now we're screwed. We need to do a
380 			   fold-in-place of another chain to make room
381 			   for this one. We need a better way of selecting
382 			   which chain to fold, because makefreeblock will
383 			   only ask us to fold the same one again.
384 			*/
385 			printk(KERN_WARNING
386 			       "NFTL_findfreeblock(desperate) returns 0xffff.\n");
387 			return BLOCK_NIL;
388 		}
389 	} else {
390 		/* We put a fold mark in the chain we are folding only if we
391                fold in place to help the mount check code. If we do not fold in
392                place, it is possible to find the valid chain by selecting the
393                longer one */
394 		oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
395 		oob.u.c.unused = 0xffffffff;
396 		nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
397 			       8, &retlen, (char *)&oob.u);
398 	}
399 
400 	/* OK. We now know the location of every block in the Virtual Unit Chain,
401 	   and the Erase Unit into which we are supposed to be copying.
402 	   Go for it.
403 	*/
404 	DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN);
405 	for (block = 0; block < nftl->EraseSize / 512 ; block++) {
406 		unsigned char movebuf[512];
407 		int ret;
408 
409 		/* If it's in the target EUN already, or if it's pending write, do nothing */
410 		if (BlockMap[block] == targetEUN ||
411 		    (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) {
412 			continue;
413 		}
414 
415 		/* copy only in non free block (free blocks can only
416                    happen in case of media errors or deleted blocks) */
417 		if (BlockMap[block] == BLOCK_NIL)
418 			continue;
419 
420 		ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
421 				512, &retlen, movebuf);
422 		if (ret < 0 && ret != -EUCLEAN) {
423 			ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block])
424 					+ (block * 512), 512, &retlen,
425 					movebuf);
426 			if (ret != -EIO)
427 				printk("Error went away on retry.\n");
428 		}
429 		memset(&oob, 0xff, sizeof(struct nftl_oob));
430 		oob.b.Status = oob.b.Status1 = SECTOR_USED;
431 
432 		nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
433 			   (block * 512), 512, &retlen, movebuf, (char *)&oob);
434 	}
435 
436 	/* add the header so that it is now a valid chain */
437 	oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
438 	oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
439 
440 	nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
441 		       8, &retlen, (char *)&oob.u);
442 
443 	/* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
444 
445 	/* At this point, we have two different chains for this Virtual Unit, and no way to tell
446 	   them apart. If we crash now, we get confused. However, both contain the same data, so we
447 	   shouldn't actually lose data in this case. It's just that when we load up on a medium which
448 	   has duplicate chains, we need to free one of the chains because it's not necessary any more.
449 	*/
450 	thisEUN = nftl->EUNtable[thisVUC];
451 	DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n");
452 
453 	/* For each block in the old chain (except the targetEUN of course),
454 	   free it and make it available for future use */
455 	while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
456 		unsigned int EUNtmp;
457 
458 		EUNtmp = nftl->ReplUnitTable[thisEUN];
459 
460 		if (NFTL_formatblock(nftl, thisEUN) < 0) {
461 			/* could not erase : mark block as reserved
462 			 */
463 			nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
464 		} else {
465 			/* correctly erased : mark it as free */
466 			nftl->ReplUnitTable[thisEUN] = BLOCK_FREE;
467 			nftl->numfreeEUNs++;
468 		}
469 		thisEUN = EUNtmp;
470 	}
471 
472 	/* Make this the new start of chain for thisVUC */
473 	nftl->ReplUnitTable[targetEUN] = BLOCK_NIL;
474 	nftl->EUNtable[thisVUC] = targetEUN;
475 
476 	return targetEUN;
477 }
478 
479 static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
480 {
481 	/* This is the part that needs some cleverness applied.
482 	   For now, I'm doing the minimum applicable to actually
483 	   get the thing to work.
484 	   Wear-levelling and other clever stuff needs to be implemented
485 	   and we also need to do some assessment of the results when
486 	   the system loses power half-way through the routine.
487 	*/
488 	u16 LongestChain = 0;
489 	u16 ChainLength = 0, thislen;
490 	u16 chain, EUN;
491 
492 	for (chain = 0; chain < le32_to_cpu(nftl->MediaHdr.FormattedSize) / nftl->EraseSize; chain++) {
493 		EUN = nftl->EUNtable[chain];
494 		thislen = 0;
495 
496 		while (EUN <= nftl->lastEUN) {
497 			thislen++;
498 			//printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN);
499 			EUN = nftl->ReplUnitTable[EUN] & 0x7fff;
500 			if (thislen > 0xff00) {
501 				printk("Endless loop in Virtual Chain %d: Unit %x\n",
502 				       chain, EUN);
503 			}
504 			if (thislen > 0xff10) {
505 				/* Actually, don't return failure. Just ignore this chain and
506 				   get on with it. */
507 				thislen = 0;
508 				break;
509 			}
510 		}
511 
512 		if (thislen > ChainLength) {
513 			//printk("New longest chain is %d with length %d\n", chain, thislen);
514 			ChainLength = thislen;
515 			LongestChain = chain;
516 		}
517 	}
518 
519 	if (ChainLength < 2) {
520 		printk(KERN_WARNING "No Virtual Unit Chains available for folding. "
521 		       "Failing request\n");
522 		return 0xffff;
523 	}
524 
525 	return NFTL_foldchain (nftl, LongestChain, pendingblock);
526 }
527 
528 /* NFTL_findwriteunit: Return the unit number into which we can write
529                        for this block. Make it available if it isn't already
530 */
531 static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
532 {
533 	u16 lastEUN;
534 	u16 thisVUC = block / (nftl->EraseSize / 512);
535 	struct mtd_info *mtd = nftl->mbd.mtd;
536 	unsigned int writeEUN;
537 	unsigned long blockofs = (block * 512) & (nftl->EraseSize -1);
538 	size_t retlen;
539 	int silly, silly2 = 3;
540 	struct nftl_oob oob;
541 
542 	do {
543 		/* Scan the media to find a unit in the VUC which has
544 		   a free space for the block in question.
545 		*/
546 
547 		/* This condition catches the 0x[7f]fff cases, as well as
548 		   being a sanity check for past-end-of-media access
549 		*/
550 		lastEUN = BLOCK_NIL;
551 		writeEUN = nftl->EUNtable[thisVUC];
552 		silly = MAX_LOOPS;
553 		while (writeEUN <= nftl->lastEUN) {
554 			struct nftl_bci bci;
555 			size_t retlen;
556 			unsigned int status;
557 
558 			lastEUN = writeEUN;
559 
560 			nftl_read_oob(mtd,
561 				      (writeEUN * nftl->EraseSize) + blockofs,
562 				      8, &retlen, (char *)&bci);
563 
564 			DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
565 			      block , writeEUN, le16_to_cpu(bci.Status));
566 
567 			status = bci.Status | bci.Status1;
568 			switch(status) {
569 			case SECTOR_FREE:
570 				return writeEUN;
571 
572 			case SECTOR_DELETED:
573 			case SECTOR_USED:
574 			case SECTOR_IGNORE:
575 				break;
576 			default:
577 				// Invalid block. Don't use it any more. Must implement.
578 				break;
579 			}
580 
581 			if (!silly--) {
582 				printk(KERN_WARNING
583 				       "Infinite loop in Virtual Unit Chain 0x%x\n",
584 				       thisVUC);
585 				return 0xffff;
586 			}
587 
588 			/* Skip to next block in chain */
589 			writeEUN = nftl->ReplUnitTable[writeEUN];
590 		}
591 
592 		/* OK. We didn't find one in the existing chain, or there
593 		   is no existing chain. */
594 
595 		/* Try to find an already-free block */
596 		writeEUN = NFTL_findfreeblock(nftl, 0);
597 
598 		if (writeEUN == BLOCK_NIL) {
599 			/* That didn't work - there were no free blocks just
600 			   waiting to be picked up. We're going to have to fold
601 			   a chain to make room.
602 			*/
603 
604 			/* First remember the start of this chain */
605 			//u16 startEUN = nftl->EUNtable[thisVUC];
606 
607 			//printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
608 			writeEUN = NFTL_makefreeblock(nftl, 0xffff);
609 
610 			if (writeEUN == BLOCK_NIL) {
611 				/* OK, we accept that the above comment is
612 				   lying - there may have been free blocks
613 				   last time we called NFTL_findfreeblock(),
614 				   but they are reserved for when we're
615 				   desperate. Well, now we're desperate.
616 				*/
617 				DEBUG(MTD_DEBUG_LEVEL1, "Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
618 				writeEUN = NFTL_findfreeblock(nftl, 1);
619 			}
620 			if (writeEUN == BLOCK_NIL) {
621 				/* Ouch. This should never happen - we should
622 				   always be able to make some room somehow.
623 				   If we get here, we've allocated more storage
624 				   space than actual media, or our makefreeblock
625 				   routine is missing something.
626 				*/
627 				printk(KERN_WARNING "Cannot make free space.\n");
628 				return BLOCK_NIL;
629 			}
630 			//printk("Restarting scan\n");
631 			lastEUN = BLOCK_NIL;
632 			continue;
633 		}
634 
635 		/* We've found a free block. Insert it into the chain. */
636 
637 		if (lastEUN != BLOCK_NIL) {
638 			thisVUC |= 0x8000; /* It's a replacement block */
639 		} else {
640 			/* The first block in a new chain */
641 			nftl->EUNtable[thisVUC] = writeEUN;
642 		}
643 
644 		/* set up the actual EUN we're writing into */
645 		/* Both in our cache... */
646 		nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
647 
648 		/* ... and on the flash itself */
649 		nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
650 			      &retlen, (char *)&oob.u);
651 
652 		oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
653 
654 		nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
655 			       &retlen, (char *)&oob.u);
656 
657 		/* we link the new block to the chain only after the
658                    block is ready. It avoids the case where the chain
659                    could point to a free block */
660 		if (lastEUN != BLOCK_NIL) {
661 			/* Both in our cache... */
662 			nftl->ReplUnitTable[lastEUN] = writeEUN;
663 			/* ... and on the flash itself */
664 			nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
665 				      8, &retlen, (char *)&oob.u);
666 
667 			oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
668 				= cpu_to_le16(writeEUN);
669 
670 			nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
671 				       8, &retlen, (char *)&oob.u);
672 		}
673 
674 		return writeEUN;
675 
676 	} while (silly2--);
677 
678 	printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n",
679 	       thisVUC);
680 	return 0xffff;
681 }
682 
683 static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
684 			   char *buffer)
685 {
686 	struct NFTLrecord *nftl = (void *)mbd;
687 	u16 writeEUN;
688 	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
689 	size_t retlen;
690 	struct nftl_oob oob;
691 
692 	writeEUN = NFTL_findwriteunit(nftl, block);
693 
694 	if (writeEUN == BLOCK_NIL) {
695 		printk(KERN_WARNING
696 		       "NFTL_writeblock(): Cannot find block to write to\n");
697 		/* If we _still_ haven't got a block to use, we're screwed */
698 		return 1;
699 	}
700 
701 	memset(&oob, 0xff, sizeof(struct nftl_oob));
702 	oob.b.Status = oob.b.Status1 = SECTOR_USED;
703 
704 	nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
705 		   512, &retlen, (char *)buffer, (char *)&oob);
706 	return 0;
707 }
708 #endif /* CONFIG_NFTL_RW */
709 
710 static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
711 			  char *buffer)
712 {
713 	struct NFTLrecord *nftl = (void *)mbd;
714 	struct mtd_info *mtd = nftl->mbd.mtd;
715 	u16 lastgoodEUN;
716 	u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];
717 	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
718 	unsigned int status;
719 	int silly = MAX_LOOPS;
720 	size_t retlen;
721 	struct nftl_bci bci;
722 
723 	lastgoodEUN = BLOCK_NIL;
724 
725 	if (thisEUN != BLOCK_NIL) {
726 		while (thisEUN < nftl->nb_blocks) {
727 			if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
728 					  blockofs, 8, &retlen,
729 					  (char *)&bci) < 0)
730 				status = SECTOR_IGNORE;
731 			else
732 				status = bci.Status | bci.Status1;
733 
734 			switch (status) {
735 			case SECTOR_FREE:
736 				/* no modification of a sector should follow a free sector */
737 				goto the_end;
738 			case SECTOR_DELETED:
739 				lastgoodEUN = BLOCK_NIL;
740 				break;
741 			case SECTOR_USED:
742 				lastgoodEUN = thisEUN;
743 				break;
744 			case SECTOR_IGNORE:
745 				break;
746 			default:
747 				printk("Unknown status for block %ld in EUN %d: %x\n",
748 				       block, thisEUN, status);
749 				break;
750 			}
751 
752 			if (!silly--) {
753 				printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%lx\n",
754 				       block / (nftl->EraseSize / 512));
755 				return 1;
756 			}
757 			thisEUN = nftl->ReplUnitTable[thisEUN];
758 		}
759 	}
760 
761  the_end:
762 	if (lastgoodEUN == BLOCK_NIL) {
763 		/* the requested block is not on the media, return all 0x00 */
764 		memset(buffer, 0, 512);
765 	} else {
766 		loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
767 		size_t retlen;
768 		int res = mtd->read(mtd, ptr, 512, &retlen, buffer);
769 
770 		if (res < 0 && res != -EUCLEAN)
771 			return -EIO;
772 	}
773 	return 0;
774 }
775 
776 static int nftl_getgeo(struct mtd_blktrans_dev *dev,  struct hd_geometry *geo)
777 {
778 	struct NFTLrecord *nftl = (void *)dev;
779 
780 	geo->heads = nftl->heads;
781 	geo->sectors = nftl->sectors;
782 	geo->cylinders = nftl->cylinders;
783 
784 	return 0;
785 }
786 
787 /****************************************************************************
788  *
789  * Module stuff
790  *
791  ****************************************************************************/
792 
793 
794 static struct mtd_blktrans_ops nftl_tr = {
795 	.name		= "nftl",
796 	.major		= NFTL_MAJOR,
797 	.part_bits	= NFTL_PARTN_BITS,
798 	.blksize 	= 512,
799 	.getgeo		= nftl_getgeo,
800 	.readsect	= nftl_readblock,
801 #ifdef CONFIG_NFTL_RW
802 	.writesect	= nftl_writeblock,
803 #endif
804 	.add_mtd	= nftl_add_mtd,
805 	.remove_dev	= nftl_remove_dev,
806 	.owner		= THIS_MODULE,
807 };
808 
809 extern char nftlmountrev[];
810 
811 static int __init init_nftl(void)
812 {
813 	printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.98 $, nftlmount.c %s\n", nftlmountrev);
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