1/*
2 * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)
3 *
4 * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
5 *
6 * Based heavily on the nftlcore.c code which is:
7 * (c) 1999 Machine Vision Holdings, Inc.
8 * Author: David Woodhouse <dwmw2@infradead.org>
9 *
10 * $Id: inftlcore.c,v 1.1.1.1 2007/08/03 18:52:43 Exp $
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/delay.h>
30#include <linux/slab.h>
31#include <linux/sched.h>
32#include <linux/init.h>
33#include <linux/kmod.h>
34#include <linux/hdreg.h>
35#include <linux/mtd/mtd.h>
36#include <linux/mtd/nftl.h>
37#include <linux/mtd/inftl.h>
38#include <linux/mtd/nand.h>
39#include <asm/uaccess.h>
40#include <asm/errno.h>
41#include <asm/io.h>
42
43/*
44 * Maximum number of loops while examining next block, to have a
45 * chance to detect consistency problems (they should never happen
46 * because of the checks done in the mounting.
47 */
48#define MAX_LOOPS 10000
49
50static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
51{
52	struct INFTLrecord *inftl;
53	unsigned long temp;
54
55	if (mtd->type != MTD_NANDFLASH)
56		return;
57	/* OK, this is moderately ugly.  But probably safe.  Alternatives? */
58	if (memcmp(mtd->name, "DiskOnChip", 10))
59		return;
60
61	if (!mtd->block_isbad) {
62		printk(KERN_ERR
63"INFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n"
64"Please use the new diskonchip driver under the NAND subsystem.\n");
65		return;
66	}
67
68	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
69
70	inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
71
72	if (!inftl) {
73		printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
74		return;
75	}
76
77	inftl->mbd.mtd = mtd;
78	inftl->mbd.devnum = -1;
79
80	inftl->mbd.tr = tr;
81
82	if (INFTL_mount(inftl) < 0) {
83		printk(KERN_WARNING "INFTL: could not mount device\n");
84		kfree(inftl);
85		return;
86	}
87
88	/* OK, it's a new one. Set up all the data structures. */
89
90	/* Calculate geometry */
91	inftl->cylinders = 1024;
92	inftl->heads = 16;
93
94	temp = inftl->cylinders * inftl->heads;
95	inftl->sectors = inftl->mbd.size / temp;
96	if (inftl->mbd.size % temp) {
97		inftl->sectors++;
98		temp = inftl->cylinders * inftl->sectors;
99		inftl->heads = inftl->mbd.size / temp;
100
101		if (inftl->mbd.size % temp) {
102			inftl->heads++;
103			temp = inftl->heads * inftl->sectors;
104			inftl->cylinders = inftl->mbd.size / temp;
105		}
106	}
107
108	if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) {
109		/*
110		  Oh no we don't have
111		   mbd.size == heads * cylinders * sectors
112		*/
113		printk(KERN_WARNING "INFTL: cannot calculate a geometry to "
114		       "match size of 0x%lx.\n", inftl->mbd.size);
115		printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d "
116			"(== 0x%lx sects)\n",
117			inftl->cylinders, inftl->heads , inftl->sectors,
118			(long)inftl->cylinders * (long)inftl->heads *
119			(long)inftl->sectors );
120	}
121
122	if (add_mtd_blktrans_dev(&inftl->mbd)) {
123		kfree(inftl->PUtable);
124		kfree(inftl->VUtable);
125		kfree(inftl);
126		return;
127	}
128#ifdef PSYCHO_DEBUG
129	printk(KERN_INFO "INFTL: Found new inftl%c\n", inftl->mbd.devnum + 'a');
130#endif
131	return;
132}
133
134static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
135{
136	struct INFTLrecord *inftl = (void *)dev;
137
138	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: remove_dev (i=%d)\n", dev->devnum);
139
140	del_mtd_blktrans_dev(dev);
141
142	kfree(inftl->PUtable);
143	kfree(inftl->VUtable);
144	kfree(inftl);
145}
146
147/*
148 * Actual INFTL access routines.
149 */
150
151/*
152 * Read oob data from flash
153 */
154int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
155		   size_t *retlen, uint8_t *buf)
156{
157	struct mtd_oob_ops ops;
158	int res;
159
160	ops.mode = MTD_OOB_PLACE;
161	ops.ooboffs = offs & (mtd->writesize - 1);
162	ops.ooblen = len;
163	ops.oobbuf = buf;
164	ops.datbuf = NULL;
165
166	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
167	*retlen = ops.oobretlen;
168	return res;
169}
170
171/*
172 * Write oob data to flash
173 */
174int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
175		    size_t *retlen, uint8_t *buf)
176{
177	struct mtd_oob_ops ops;
178	int res;
179
180	ops.mode = MTD_OOB_PLACE;
181	ops.ooboffs = offs & (mtd->writesize - 1);
182	ops.ooblen = len;
183	ops.oobbuf = buf;
184	ops.datbuf = NULL;
185
186	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
187	*retlen = ops.oobretlen;
188	return res;
189}
190
191/*
192 * Write data and oob to flash
193 */
194static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
195		       size_t *retlen, uint8_t *buf, uint8_t *oob)
196{
197	struct mtd_oob_ops ops;
198	int res;
199
200	ops.mode = MTD_OOB_PLACE;
201	ops.ooboffs = offs;
202	ops.ooblen = mtd->oobsize;
203	ops.oobbuf = oob;
204	ops.datbuf = buf;
205	ops.len = len;
206
207	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
208	*retlen = ops.retlen;
209	return res;
210}
211
212/*
213 * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition.
214 *	This function is used when the give Virtual Unit Chain.
215 */
216static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate)
217{
218	u16 pot = inftl->LastFreeEUN;
219	int silly = inftl->nb_blocks;
220
221	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=%p,"
222		"desperate=%d)\n", inftl, desperate);
223
224	/*
225	 * Normally, we force a fold to happen before we run out of free
226	 * blocks completely.
227	 */
228	if (!desperate && inftl->numfreeEUNs < 2) {
229		DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free "
230			"EUNs (%d)\n", inftl->numfreeEUNs);
231		return 0xffff;
232	}
233
234	/* Scan for a free block */
235	do {
236		if (inftl->PUtable[pot] == BLOCK_FREE) {
237			inftl->LastFreeEUN = pot;
238			return pot;
239		}
240
241		if (++pot > inftl->lastEUN)
242			pot = 0;
243
244		if (!silly--) {
245			printk(KERN_WARNING "INFTL: no free blocks found!  "
246				"EUN range = %d - %d\n", 0, inftl->LastFreeEUN);
247			return BLOCK_NIL;
248		}
249	} while (pot != inftl->LastFreeEUN);
250
251	return BLOCK_NIL;
252}
253
254static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned pendingblock)
255{
256	u16 BlockMap[MAX_SECTORS_PER_UNIT];
257	unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT];
258	unsigned int thisEUN, prevEUN, status;
259	struct mtd_info *mtd = inftl->mbd.mtd;
260	int block, silly;
261	unsigned int targetEUN;
262	struct inftl_oob oob;
263	size_t retlen;
264
265	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
266		"pending=%d)\n", inftl, thisVUC, pendingblock);
267
268	memset(BlockMap, 0xff, sizeof(BlockMap));
269	memset(BlockDeleted, 0, sizeof(BlockDeleted));
270
271	thisEUN = targetEUN = inftl->VUtable[thisVUC];
272
273	if (thisEUN == BLOCK_NIL) {
274		printk(KERN_WARNING "INFTL: trying to fold non-existent "
275		       "Virtual Unit Chain %d!\n", thisVUC);
276		return BLOCK_NIL;
277	}
278
279	/*
280	 * Scan to find the Erase Unit which holds the actual data for each
281	 * 512-byte block within the Chain.
282	 */
283	silly = MAX_LOOPS;
284	while (thisEUN < inftl->nb_blocks) {
285		for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) {
286			if ((BlockMap[block] != 0xffff) || BlockDeleted[block])
287				continue;
288
289			if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
290					   + (block * SECTORSIZE), 16, &retlen,
291					   (char *)&oob) < 0)
292				status = SECTOR_IGNORE;
293			else
294				status = oob.b.Status | oob.b.Status1;
295
296			switch(status) {
297			case SECTOR_FREE:
298			case SECTOR_IGNORE:
299				break;
300			case SECTOR_USED:
301				BlockMap[block] = thisEUN;
302				continue;
303			case SECTOR_DELETED:
304				BlockDeleted[block] = 1;
305				continue;
306			default:
307				printk(KERN_WARNING "INFTL: unknown status "
308					"for block %d in EUN %d: %x\n",
309					block, thisEUN, status);
310				break;
311			}
312		}
313
314		if (!silly--) {
315			printk(KERN_WARNING "INFTL: infinite loop in Virtual "
316				"Unit Chain 0x%x\n", thisVUC);
317			return BLOCK_NIL;
318		}
319
320		thisEUN = inftl->PUtable[thisEUN];
321	}
322
323	/*
324	 * OK. We now know the location of every block in the Virtual Unit
325	 * Chain, and the Erase Unit into which we are supposed to be copying.
326	 * Go for it.
327	 */
328	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: folding chain %d into unit %d\n",
329		thisVUC, targetEUN);
330
331	for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) {
332		unsigned char movebuf[SECTORSIZE];
333		int ret;
334
335		/*
336		 * If it's in the target EUN already, or if it's pending write,
337		 * do nothing.
338		 */
339		if (BlockMap[block] == targetEUN || (pendingblock ==
340		    (thisVUC * (inftl->EraseSize / SECTORSIZE) + block))) {
341			continue;
342		}
343
344		/*
345		 * Copy only in non free block (free blocks can only
346                 * happen in case of media errors or deleted blocks).
347		 */
348		if (BlockMap[block] == BLOCK_NIL)
349			continue;
350
351		ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) +
352				(block * SECTORSIZE), SECTORSIZE, &retlen,
353				movebuf);
354		if (ret < 0 && ret != -EUCLEAN) {
355			ret = mtd->read(mtd,
356					(inftl->EraseSize * BlockMap[block]) +
357					(block * SECTORSIZE), SECTORSIZE,
358					&retlen, movebuf);
359			if (ret != -EIO)
360				DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
361				      "away on retry?\n");
362		}
363		memset(&oob, 0xff, sizeof(struct inftl_oob));
364		oob.b.Status = oob.b.Status1 = SECTOR_USED;
365
366		inftl_write(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
367			    (block * SECTORSIZE), SECTORSIZE, &retlen,
368			    movebuf, (char *)&oob);
369	}
370
371	/*
372	 * Newest unit in chain now contains data from _all_ older units.
373	 * So go through and erase each unit in chain, oldest first. (This
374	 * is important, by doing oldest first if we crash/reboot then it
375	 * it is relatively simple to clean up the mess).
376	 */
377	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: want to erase virtual chain %d\n",
378		thisVUC);
379
380	for (;;) {
381		/* Find oldest unit in chain. */
382		thisEUN = inftl->VUtable[thisVUC];
383		prevEUN = BLOCK_NIL;
384		while (inftl->PUtable[thisEUN] != BLOCK_NIL) {
385			prevEUN = thisEUN;
386			thisEUN = inftl->PUtable[thisEUN];
387		}
388
389		/* Check if we are all done */
390		if (thisEUN == targetEUN)
391			break;
392
393		if (INFTL_formatblock(inftl, thisEUN) < 0) {
394			/*
395			 * Could not erase : mark block as reserved.
396			 */
397			inftl->PUtable[thisEUN] = BLOCK_RESERVED;
398		} else {
399			/* Correctly erased : mark it as free */
400			inftl->PUtable[thisEUN] = BLOCK_FREE;
401			inftl->PUtable[prevEUN] = BLOCK_NIL;
402			inftl->numfreeEUNs++;
403		}
404	}
405
406	return targetEUN;
407}
408
409static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
410{
411	/*
412	 * This is the part that needs some cleverness applied.
413	 * For now, I'm doing the minimum applicable to actually
414	 * get the thing to work.
415	 * Wear-levelling and other clever stuff needs to be implemented
416	 * and we also need to do some assessment of the results when
417	 * the system loses power half-way through the routine.
418	 */
419	u16 LongestChain = 0;
420	u16 ChainLength = 0, thislen;
421	u16 chain, EUN;
422
423	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p,"
424		"pending=%d)\n", inftl, pendingblock);
425
426	for (chain = 0; chain < inftl->nb_blocks; chain++) {
427		EUN = inftl->VUtable[chain];
428		thislen = 0;
429
430		while (EUN <= inftl->lastEUN) {
431			thislen++;
432			EUN = inftl->PUtable[EUN];
433			if (thislen > 0xff00) {
434				printk(KERN_WARNING "INFTL: endless loop in "
435					"Virtual Chain %d: Unit %x\n",
436					chain, EUN);
437				/*
438				 * Actually, don't return failure.
439				 * Just ignore this chain and get on with it.
440				 */
441				thislen = 0;
442				break;
443			}
444		}
445
446		if (thislen > ChainLength) {
447			ChainLength = thislen;
448			LongestChain = chain;
449		}
450	}
451
452	if (ChainLength < 2) {
453		printk(KERN_WARNING "INFTL: no Virtual Unit Chains available "
454			"for folding. Failing request\n");
455		return BLOCK_NIL;
456	}
457
458	return INFTL_foldchain(inftl, LongestChain, pendingblock);
459}
460
461static int nrbits(unsigned int val, int bitcount)
462{
463	int i, total = 0;
464
465	for (i = 0; (i < bitcount); i++)
466		total += (((0x1 << i) & val) ? 1 : 0);
467	return total;
468}
469
470/*
471 * INFTL_findwriteunit: Return the unit number into which we can write
472 *                      for this block. Make it available if it isn't already.
473 */
474static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
475{
476	unsigned int thisVUC = block / (inftl->EraseSize / SECTORSIZE);
477	unsigned int thisEUN, writeEUN, prev_block, status;
478	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize -1);
479	struct mtd_info *mtd = inftl->mbd.mtd;
480	struct inftl_oob oob;
481	struct inftl_bci bci;
482	unsigned char anac, nacs, parity;
483	size_t retlen;
484	int silly, silly2 = 3;
485
486	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=%p,"
487		"block=%d)\n", inftl, block);
488
489	do {
490		/*
491		 * Scan the media to find a unit in the VUC which has
492		 * a free space for the block in question.
493		 */
494		writeEUN = BLOCK_NIL;
495		thisEUN = inftl->VUtable[thisVUC];
496		silly = MAX_LOOPS;
497
498		while (thisEUN <= inftl->lastEUN) {
499			inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
500				       blockofs, 8, &retlen, (char *)&bci);
501
502			status = bci.Status | bci.Status1;
503			DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
504				"EUN %d is %x\n", block , writeEUN, status);
505
506			switch(status) {
507			case SECTOR_FREE:
508				writeEUN = thisEUN;
509				break;
510			case SECTOR_DELETED:
511			case SECTOR_USED:
512				/* Can't go any further */
513				goto hitused;
514			case SECTOR_IGNORE:
515				break;
516			default:
517				/*
518				 * Invalid block. Don't use it any more.
519				 * Must implement.
520				 */
521				break;
522			}
523
524			if (!silly--) {
525				printk(KERN_WARNING "INFTL: infinite loop in "
526					"Virtual Unit Chain 0x%x\n", thisVUC);
527				return 0xffff;
528			}
529
530			/* Skip to next block in chain */
531			thisEUN = inftl->PUtable[thisEUN];
532		}
533
534hitused:
535		if (writeEUN != BLOCK_NIL)
536			return writeEUN;
537
538
539		/*
540		 * OK. We didn't find one in the existing chain, or there
541		 * is no existing chain. Allocate a new one.
542		 */
543		writeEUN = INFTL_findfreeblock(inftl, 0);
544
545		if (writeEUN == BLOCK_NIL) {
546			/*
547			 * That didn't work - there were no free blocks just
548			 * waiting to be picked up. We're going to have to fold
549			 * a chain to make room.
550			 */
551			thisEUN = INFTL_makefreeblock(inftl, 0xffff);
552
553			/*
554			 * Hopefully we free something, lets try again.
555			 * This time we are desperate...
556			 */
557			DEBUG(MTD_DEBUG_LEVEL1, "INFTL: using desperate==1 "
558				"to find free EUN to accommodate write to "
559				"VUC %d\n", thisVUC);
560			writeEUN = INFTL_findfreeblock(inftl, 1);
561			if (writeEUN == BLOCK_NIL) {
562				/*
563				 * Ouch. This should never happen - we should
564				 * always be able to make some room somehow.
565				 * If we get here, we've allocated more storage
566				 * space than actual media, or our makefreeblock
567				 * routine is missing something.
568				 */
569				printk(KERN_WARNING "INFTL: cannot make free "
570					"space.\n");
571#ifdef DEBUG
572				INFTL_dumptables(inftl);
573				INFTL_dumpVUchains(inftl);
574#endif
575				return BLOCK_NIL;
576			}
577		}
578
579		/*
580		 * Insert new block into virtual chain. Firstly update the
581		 * block headers in flash...
582		 */
583		anac = 0;
584		nacs = 0;
585		thisEUN = inftl->VUtable[thisVUC];
586		if (thisEUN != BLOCK_NIL) {
587			inftl_read_oob(mtd, thisEUN * inftl->EraseSize
588				       + 8, 8, &retlen, (char *)&oob.u);
589			anac = oob.u.a.ANAC + 1;
590			nacs = oob.u.a.NACs + 1;
591		}
592
593		prev_block = inftl->VUtable[thisVUC];
594		if (prev_block < inftl->nb_blocks)
595			prev_block -= inftl->firstEUN;
596
597		parity = (nrbits(thisVUC, 16) & 0x1) ? 0x1 : 0;
598		parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0;
599		parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0;
600		parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0;
601
602		oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC);
603		oob.u.a.prevUnitNo = cpu_to_le16(prev_block);
604		oob.u.a.ANAC = anac;
605		oob.u.a.NACs = nacs;
606		oob.u.a.parityPerField = parity;
607		oob.u.a.discarded = 0xaa;
608
609		inftl_write_oob(mtd, writeEUN * inftl->EraseSize + 8, 8,
610				&retlen, (char *)&oob.u);
611
612		/* Also back up header... */
613		oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC);
614		oob.u.b.prevUnitNo = cpu_to_le16(prev_block);
615		oob.u.b.ANAC = anac;
616		oob.u.b.NACs = nacs;
617		oob.u.b.parityPerField = parity;
618		oob.u.b.discarded = 0xaa;
619
620		inftl_write_oob(mtd, writeEUN * inftl->EraseSize +
621				SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
622
623		inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC];
624		inftl->VUtable[thisVUC] = writeEUN;
625
626		inftl->numfreeEUNs--;
627		return writeEUN;
628
629	} while (silly2--);
630
631	printk(KERN_WARNING "INFTL: error folding to make room for Virtual "
632		"Unit Chain 0x%x\n", thisVUC);
633	return 0xffff;
634}
635
636/*
637 * Given a Virtual Unit Chain, see if it can be deleted, and if so do it.
638 */
639static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
640{
641	struct mtd_info *mtd = inftl->mbd.mtd;
642	unsigned char BlockUsed[MAX_SECTORS_PER_UNIT];
643	unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT];
644	unsigned int thisEUN, status;
645	int block, silly;
646	struct inftl_bci bci;
647	size_t retlen;
648
649	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p,"
650		"thisVUC=%d)\n", inftl, thisVUC);
651
652	memset(BlockUsed, 0, sizeof(BlockUsed));
653	memset(BlockDeleted, 0, sizeof(BlockDeleted));
654
655	thisEUN = inftl->VUtable[thisVUC];
656	if (thisEUN == BLOCK_NIL) {
657		printk(KERN_WARNING "INFTL: trying to delete non-existent "
658		       "Virtual Unit Chain %d!\n", thisVUC);
659		return;
660	}
661
662	/*
663	 * Scan through the Erase Units to determine whether any data is in
664	 * each of the 512-byte blocks within the Chain.
665	 */
666	silly = MAX_LOOPS;
667	while (thisEUN < inftl->nb_blocks) {
668		for (block = 0; block < inftl->EraseSize/SECTORSIZE; block++) {
669			if (BlockUsed[block] || BlockDeleted[block])
670				continue;
671
672			if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
673					   + (block * SECTORSIZE), 8 , &retlen,
674					  (char *)&bci) < 0)
675				status = SECTOR_IGNORE;
676			else
677				status = bci.Status | bci.Status1;
678
679			switch(status) {
680			case SECTOR_FREE:
681			case SECTOR_IGNORE:
682				break;
683			case SECTOR_USED:
684				BlockUsed[block] = 1;
685				continue;
686			case SECTOR_DELETED:
687				BlockDeleted[block] = 1;
688				continue;
689			default:
690				printk(KERN_WARNING "INFTL: unknown status "
691					"for block %d in EUN %d: 0x%x\n",
692					block, thisEUN, status);
693			}
694		}
695
696		if (!silly--) {
697			printk(KERN_WARNING "INFTL: infinite loop in Virtual "
698				"Unit Chain 0x%x\n", thisVUC);
699			return;
700		}
701
702		thisEUN = inftl->PUtable[thisEUN];
703	}
704
705	for (block = 0; block < inftl->EraseSize/SECTORSIZE; block++)
706		if (BlockUsed[block])
707			return;
708
709	/*
710	 * For each block in the chain free it and make it available
711	 * for future use. Erase from the oldest unit first.
712	 */
713	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC);
714
715	for (;;) {
716		u16 *prevEUN = &inftl->VUtable[thisVUC];
717		thisEUN = *prevEUN;
718
719		/* If the chain is all gone already, we're done */
720		if (thisEUN == BLOCK_NIL) {
721			DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
722			return;
723		}
724
725		/* Find oldest unit in chain. */
726		while (inftl->PUtable[thisEUN] != BLOCK_NIL) {
727			BUG_ON(thisEUN >= inftl->nb_blocks);
728
729			prevEUN = &inftl->PUtable[thisEUN];
730			thisEUN = *prevEUN;
731		}
732
733		DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
734		      thisEUN, thisVUC);
735
736		if (INFTL_formatblock(inftl, thisEUN) < 0) {
737			/*
738			 * Could not erase : mark block as reserved.
739			 */
740			inftl->PUtable[thisEUN] = BLOCK_RESERVED;
741		} else {
742			/* Correctly erased : mark it as free */
743			inftl->PUtable[thisEUN] = BLOCK_FREE;
744			inftl->numfreeEUNs++;
745		}
746
747		/* Now sort out whatever was pointing to it... */
748		*prevEUN = BLOCK_NIL;
749
750		/* Ideally we'd actually be responsive to new
751		   requests while we're doing this -- if there's
752		   free space why should others be made to wait? */
753		cond_resched();
754	}
755
756	inftl->VUtable[thisVUC] = BLOCK_NIL;
757}
758
759static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
760{
761	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
762	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
763	struct mtd_info *mtd = inftl->mbd.mtd;
764	unsigned int status;
765	int silly = MAX_LOOPS;
766	size_t retlen;
767	struct inftl_bci bci;
768
769	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=%p,"
770		"block=%d)\n", inftl, block);
771
772	while (thisEUN < inftl->nb_blocks) {
773		if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
774				   blockofs, 8, &retlen, (char *)&bci) < 0)
775			status = SECTOR_IGNORE;
776		else
777			status = bci.Status | bci.Status1;
778
779		switch (status) {
780		case SECTOR_FREE:
781		case SECTOR_IGNORE:
782			break;
783		case SECTOR_DELETED:
784			thisEUN = BLOCK_NIL;
785			goto foundit;
786		case SECTOR_USED:
787			goto foundit;
788		default:
789			printk(KERN_WARNING "INFTL: unknown status for "
790				"block %d in EUN %d: 0x%x\n",
791				block, thisEUN, status);
792			break;
793		}
794
795		if (!silly--) {
796			printk(KERN_WARNING "INFTL: infinite loop in Virtual "
797				"Unit Chain 0x%x\n",
798				block / (inftl->EraseSize / SECTORSIZE));
799			return 1;
800		}
801		thisEUN = inftl->PUtable[thisEUN];
802	}
803
804foundit:
805	if (thisEUN != BLOCK_NIL) {
806		loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
807
808		if (inftl_read_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
809			return -EIO;
810		bci.Status = bci.Status1 = SECTOR_DELETED;
811		if (inftl_write_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
812			return -EIO;
813		INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE));
814	}
815	return 0;
816}
817
818static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
819			    char *buffer)
820{
821	struct INFTLrecord *inftl = (void *)mbd;
822	unsigned int writeEUN;
823	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
824	size_t retlen;
825	struct inftl_oob oob;
826	char *p, *pend;
827
828	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=%p,block=%ld,"
829		"buffer=%p)\n", inftl, block, buffer);
830
831	/* Is block all zero? */
832	pend = buffer + SECTORSIZE;
833	for (p = buffer; p < pend && !*p; p++)
834		;
835
836	if (p < pend) {
837		writeEUN = INFTL_findwriteunit(inftl, block);
838
839		if (writeEUN == BLOCK_NIL) {
840			printk(KERN_WARNING "inftl_writeblock(): cannot find "
841				"block to write to\n");
842			/*
843			 * If we _still_ haven't got a block to use,
844			 * we're screwed.
845			 */
846			return 1;
847		}
848
849		memset(&oob, 0xff, sizeof(struct inftl_oob));
850		oob.b.Status = oob.b.Status1 = SECTOR_USED;
851
852		inftl_write(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
853			    blockofs, SECTORSIZE, &retlen, (char *)buffer,
854			    (char *)&oob);
855		/*
856		 * need to write SECTOR_USED flags since they are not written
857		 * in mtd_writeecc
858		 */
859	} else {
860		INFTL_deleteblock(inftl, block);
861	}
862
863	return 0;
864}
865
866static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
867			   char *buffer)
868{
869	struct INFTLrecord *inftl = (void *)mbd;
870	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
871	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
872	struct mtd_info *mtd = inftl->mbd.mtd;
873	unsigned int status;
874	int silly = MAX_LOOPS;
875	struct inftl_bci bci;
876	size_t retlen;
877
878	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
879		"buffer=%p)\n", inftl, block, buffer);
880
881	while (thisEUN < inftl->nb_blocks) {
882		if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
883				  blockofs, 8, &retlen, (char *)&bci) < 0)
884			status = SECTOR_IGNORE;
885		else
886			status = bci.Status | bci.Status1;
887
888		switch (status) {
889		case SECTOR_DELETED:
890			thisEUN = BLOCK_NIL;
891			goto foundit;
892		case SECTOR_USED:
893			goto foundit;
894		case SECTOR_FREE:
895		case SECTOR_IGNORE:
896			break;
897		default:
898			printk(KERN_WARNING "INFTL: unknown status for "
899				"block %ld in EUN %d: 0x%04x\n",
900				block, thisEUN, status);
901			break;
902		}
903
904		if (!silly--) {
905			printk(KERN_WARNING "INFTL: infinite loop in "
906				"Virtual Unit Chain 0x%lx\n",
907				block / (inftl->EraseSize / SECTORSIZE));
908			return 1;
909		}
910
911		thisEUN = inftl->PUtable[thisEUN];
912	}
913
914foundit:
915	if (thisEUN == BLOCK_NIL) {
916		/* The requested block is not on the media, return all 0x00 */
917		memset(buffer, 0, SECTORSIZE);
918	} else {
919		size_t retlen;
920		loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
921		int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
922
923		/* Handle corrected bit flips gracefully */
924		if (ret < 0 && ret != -EUCLEAN)
925			return -EIO;
926	}
927	return 0;
928}
929
930static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
931{
932	struct INFTLrecord *inftl = (void *)dev;
933
934	geo->heads = inftl->heads;
935	geo->sectors = inftl->sectors;
936	geo->cylinders = inftl->cylinders;
937
938	return 0;
939}
940
941static struct mtd_blktrans_ops inftl_tr = {
942	.name		= "inftl",
943	.major		= INFTL_MAJOR,
944	.part_bits	= INFTL_PARTN_BITS,
945	.blksize 	= 512,
946	.getgeo		= inftl_getgeo,
947	.readsect	= inftl_readblock,
948	.writesect	= inftl_writeblock,
949	.add_mtd	= inftl_add_mtd,
950	.remove_dev	= inftl_remove_dev,
951	.owner		= THIS_MODULE,
952};
953
954static int __init init_inftl(void)
955{
956	printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.1.1.1 $, "
957		"inftlmount.c %s\n", inftlmountrev);
958
959	return register_mtd_blktrans(&inftl_tr);
960}
961
962static void __exit cleanup_inftl(void)
963{
964	deregister_mtd_blktrans(&inftl_tr);
965}
966
967module_init(init_inftl);
968module_exit(cleanup_inftl);
969
970MODULE_LICENSE("GPL");
971MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>, David Woodhouse <dwmw2@infradead.org>, Fabrice Bellard <fabrice.bellard@netgem.com> et al.");
972MODULE_DESCRIPTION("Support code for Inverse Flash Translation Layer, used on M-Systems DiskOnChip 2000, Millennium and Millennium Plus");
973