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