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