File: /usr/src/linux/drivers/mtd/nftlcore.c

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.73 2001/06/09 01:09:43 dwmw2 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/config.h>
15     #include <linux/kernel.h>
16     #include <linux/module.h>
17     #include <asm/errno.h>
18     #include <asm/io.h>
19     #include <asm/uaccess.h>
20     #include <linux/miscdevice.h>
21     #include <linux/pci.h>
22     #include <linux/delay.h>
23     #include <linux/slab.h>
24     #include <linux/sched.h>
25     #include <linux/init.h>
26     #include <linux/blkpg.h>
27     
28     #ifdef CONFIG_KMOD
29     #include <linux/kmod.h>
30     #endif
31     #include <linux/mtd/mtd.h>
32     #include <linux/mtd/nftl.h>
33     #include <linux/mtd/compatmac.h>
34     
35     /* maximum number of loops while examining next block, to have a
36        chance to detect consistency problems (they should never happen
37        because of the checks done in the mounting */
38     
39     #define MAX_LOOPS 10000
40     
41     /* NFTL block device stuff */
42     #define MAJOR_NR NFTL_MAJOR
43     #define DEVICE_REQUEST nftl_request
44     #define DEVICE_OFF(device)
45     
46     
47     #include <linux/blk.h>
48     #include <linux/hdreg.h>
49     
50     /* Linux-specific block device functions */
51     
52     /* I _HATE_ the Linux block device setup more than anything else I've ever
53      *  encountered, except ...
54      */
55     
56     static int nftl_sizes[256];
57     static int nftl_blocksizes[256];
58     
59     /* .. for the Linux partition table handling. */
60     struct hd_struct part_table[256];
61     
62     #if LINUX_VERSION_CODE < 0x20328
63     static void dummy_init (struct gendisk *crap)
64     {}
65     #endif
66     
67     static struct gendisk nftl_gendisk = {
68     	major:		MAJOR_NR,
69     	major_name:	"nftl",
70     	minor_shift:	NFTL_PARTN_BITS,	/* Bits to shift to get real from partition */
71     	max_p:		(1<<NFTL_PARTN_BITS)-1,	/* Number of partitions per real */
72     #if LINUX_VERSION_CODE < 0x20328
73     	max_nr:		MAX_NFTLS,      /* maximum number of real */
74     	init:		dummy_init,     /* init function */
75     #endif
76     	part:		part_table,     /* hd struct */
77     	sizes:		nftl_sizes,     /* block sizes */
78     };
79     
80     struct NFTLrecord *NFTLs[MAX_NFTLS];
81     
82     static void NFTL_setup(struct mtd_info *mtd)
83     {
84     	int i;
85     	struct NFTLrecord *nftl;
86     	unsigned long temp;
87     	int firstfree = -1;
88     
89     	DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n");
90     
91     	for (i = 0; i < MAX_NFTLS; i++) {
92     		if (!NFTLs[i] && firstfree == -1)
93     			firstfree = i;
94     		else if (NFTLs[i] && NFTLs[i]->mtd == mtd) {
95     			/* This is a Spare Media Header for an NFTL we've already found */
96     			DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n");
97     			return;
98     		}
99     	}
100             if (firstfree == -1) {
101     		printk(KERN_WARNING "No more NFTL slot available\n");
102     		return;
103             }
104     
105     	nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
106     	if (!nftl) {
107     		printk(KERN_WARNING "Out of memory for NFTL data structures\n");
108     		return;
109     	}
110     
111     	init_MUTEX(&nftl->mutex);
112     
113             /* get physical parameters */
114     	nftl->EraseSize = mtd->erasesize;
115             nftl->nb_blocks = mtd->size / mtd->erasesize;
116     	nftl->mtd = mtd;
117     
118             if (NFTL_mount(nftl) < 0) {
119     		printk(KERN_WARNING "Could not mount NFTL device\n");
120     		kfree(nftl);
121     		return;
122             }
123     
124     	/* OK, it's a new one. Set up all the data structures. */
125     #ifdef PSYCHO_DEBUG
126     	printk("Found new NFTL nftl%c\n", firstfree + 'a');
127     #endif
128     
129             /* linux stuff */
130     	nftl->usecount = 0;
131     	nftl->cylinders = 1024;
132     	nftl->heads = 16;
133     
134     	temp = nftl->cylinders * nftl->heads;
135     	nftl->sectors = nftl->nr_sects / temp;
136     	if (nftl->nr_sects % temp) {
137     		nftl->sectors++;
138     		temp = nftl->cylinders * nftl->sectors;
139     		nftl->heads = nftl->nr_sects / temp;
140     
141     		if (nftl->nr_sects % temp) {
142     			nftl->heads++;
143     			temp = nftl->heads * nftl->sectors;
144     			nftl->cylinders = nftl->nr_sects / temp;
145     		}
146     	}
147     
148     	if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) {
149     		printk(KERN_WARNING "Cannot calculate an NFTL geometry to "
150     		       "match size of 0x%lx.\n", nftl->nr_sects);
151     		printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n", 
152     		       nftl->cylinders, nftl->heads , nftl->sectors, 
153     		       (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors );
154     
155     		/* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */
156     	}
157     	NFTLs[firstfree] = nftl;
158     	/* Finally, set up the block device sizes */
159     	nftl_sizes[firstfree * 16] = nftl->nr_sects;
160     	//nftl_blocksizes[firstfree*16] = 512;
161     	part_table[firstfree * 16].nr_sects = nftl->nr_sects;
162     
163     	nftl_gendisk.nr_real++;
164     
165     	/* partition check ... */
166     #if LINUX_VERSION_CODE < 0x20328
167     	resetup_one_dev(&nftl_gendisk, firstfree);
168     #else
169     	grok_partitions(&nftl_gendisk, firstfree, 1<<NFTL_PARTN_BITS, nftl->nr_sects);
170     #endif
171     }
172     
173     static void NFTL_unsetup(int i)
174     {
175     	struct NFTLrecord *nftl = NFTLs[i];
176     
177     	DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i);
178     	
179     	NFTLs[i] = NULL;
180     	
181     	if (nftl->ReplUnitTable)
182     		kfree(nftl->ReplUnitTable);
183     	if (nftl->EUNtable)
184     		kfree(nftl->EUNtable);
185     		      
186     	nftl_gendisk.nr_real--;
187     	kfree(nftl);
188     }
189     
190     /* Search the MTD device for NFTL partitions */
191     static void NFTL_notify_add(struct mtd_info *mtd)
192     {
193     	DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name);
194     
195     	if (mtd) {
196     		if (!mtd->read_oob) {
197     			/* If this MTD doesn't have out-of-band data,
198     			   then there's no point continuing */
199     			DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n");
200     			return;
201     		}
202     		DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", 
203     		      mtd->read, mtd->size, mtd->erasesize);
204     
205                     NFTL_setup(mtd);
206     	}
207     }
208     
209     static void NFTL_notify_remove(struct mtd_info *mtd)
210     {
211     	int i;
212     
213     	for (i = 0; i < MAX_NFTLS; i++) {
214     		if (NFTLs[i] && NFTLs[i]->mtd == mtd)
215     			NFTL_unsetup(i);
216     	}
217     }
218     
219     #ifdef CONFIG_NFTL_RW
220     
221     /* Actual NFTL access routines */
222     /* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used
223      *	when the give Virtual Unit Chain
224      */
225     static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
226     {
227     	/* For a given Virtual Unit Chain: find or create a free block and
228     	   add it to the chain */
229     	/* We're passed the number of the last EUN in the chain, to save us from
230     	   having to look it up again */
231     	u16 pot = nftl->LastFreeEUN;
232     	int silly = -1;
233     
234     	/* Normally, we force a fold to happen before we run out of free blocks completely */
235     	if (!desperate && nftl->numfreeEUNs < 2) {
236     		DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n");
237     		return 0xffff;
238     	}
239     
240     	/* Scan for a free block */
241     	do {
242     		if (nftl->ReplUnitTable[pot] == BLOCK_FREE) {
243     			nftl->LastFreeEUN = pot;
244     			nftl->numfreeEUNs--;
245     			return pot;
246     		}
247     
248     		/* This will probably point to the MediaHdr unit itself,
249     		   right at the beginning of the partition. But that unit
250     		   (and the backup unit too) should have the UCI set
251     		   up so that it's not selected for overwriting */
252     		if (++pot > nftl->lastEUN)
253     			pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN);
254     
255     		if (!silly--) {
256     			printk("Argh! No free blocks found! LastFreeEUN = %d, "
257     			       "FirstEUN = %d\n", nftl->LastFreeEUN, 
258     			       le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));
259     			return 0xffff;
260     		}
261     	} while (pot != nftl->LastFreeEUN);
262     
263     	return 0xffff;
264     }
265     
266     static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
267     {
268     	u16 BlockMap[MAX_SECTORS_PER_UNIT];
269     	unsigned char BlockLastState[MAX_SECTORS_PER_UNIT];
270     	unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT];
271     	unsigned int thisEUN;
272     	int block;
273     	int silly;
274     	unsigned int targetEUN;
275     	struct nftl_oob oob;
276     	int inplace = 1;
277             size_t retlen;
278     
279     	memset(BlockMap, 0xff, sizeof(BlockMap));
280     	memset(BlockFreeFound, 0, sizeof(BlockFreeFound));
281     
282     	thisEUN = nftl->EUNtable[thisVUC];
283     
284     	if (thisEUN == BLOCK_NIL) {
285     		printk(KERN_WARNING "Trying to fold non-existent "
286     		       "Virtual Unit Chain %d!\n", thisVUC);
287     		return BLOCK_NIL;
288     	}
289     	
290     	/* Scan to find the Erase Unit which holds the actual data for each
291     	   512-byte block within the Chain.
292     	*/
293             silly = MAX_LOOPS;
294     	targetEUN = BLOCK_NIL;
295     	while (thisEUN <= nftl->lastEUN ) {
296                     unsigned int status, foldmark;
297     
298     		targetEUN = thisEUN;
299     		for (block = 0; block < nftl->EraseSize / 512; block ++) {
300     			MTD_READOOB(nftl->mtd,
301     				    (thisEUN * nftl->EraseSize) + (block * 512),
302     				    16 , &retlen, (char *)&oob);
303     			if (block == 2) {
304                                     foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
305                                     if (foldmark == FOLD_MARK_IN_PROGRESS) {
306                                             DEBUG(MTD_DEBUG_LEVEL1, 
307                                                   "Write Inhibited on EUN %d\n", thisEUN);
308     					inplace = 0;
309     				} else {
310     					/* There's no other reason not to do inplace,
311     					   except ones that come later. So we don't need
312     					   to preserve inplace */
313     					inplace = 1;
314     				}
315     			}
316                             status = oob.b.Status | oob.b.Status1;
317     			BlockLastState[block] = status;
318     
319     			switch(status) {
320     			case SECTOR_FREE:
321     				BlockFreeFound[block] = 1;
322     				break;
323     
324     			case SECTOR_USED:
325     				if (!BlockFreeFound[block])
326     					BlockMap[block] = thisEUN;
327     				else
328     					printk(KERN_WARNING 
329     					       "SECTOR_USED found after SECTOR_FREE "
330     					       "in Virtual Unit Chain %d for block %d\n",
331     					       thisVUC, block);
332     				break;
333     			case SECTOR_IGNORE:
334     			case SECTOR_DELETED:
335     				break;
336     			default:
337     				printk("Unknown status for block %d in EUN %d: %x\n",
338     				       block, thisEUN, status);
339     			}
340     		}
341     
342     		if (!silly--) {
343     			printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",
344     			       thisVUC);
345     			return BLOCK_NIL;
346     		}
347     		
348     		thisEUN = nftl->ReplUnitTable[thisEUN];
349     	}
350     
351     	if (inplace) {
352     		/* We're being asked to be a fold-in-place. Check
353     		   that all blocks are either present or SECTOR_FREE
354     		   in the target block. If not, we're going to have
355     		   to fold out-of-place anyway.
356     		*/
357     		for (block = 0; block < nftl->EraseSize / 512 ; block++) {
358     			if (BlockLastState[block] != SECTOR_FREE &&
359     			    BlockMap[block] != targetEUN) {
360     				DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, "
361     				      "block %d was %x lastEUN, "
362     				      "and is in EUN %d (%s) %d\n",
363     				      thisVUC, block, BlockLastState[block],
364     				      BlockMap[block], 
365     				      BlockMap[block]== targetEUN ? "==" : "!=",
366     				      targetEUN);
367     				inplace = 0;
368     				break;
369     			}
370     		}
371     
372     		if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) &&
373     		    pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&
374     		    BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=
375     		    SECTOR_FREE) {
376     			DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. "
377     			      "Folding out of place.\n", targetEUN);
378     			inplace = 0;
379     		}
380     	}
381     	
382     	if (!inplace) {
383     		DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "
384     		      "Trying out-of-place\n", thisVUC);
385     		/* We need to find a targetEUN to fold into. */
386     		targetEUN = NFTL_findfreeblock(nftl, 1);
387     		if (targetEUN == BLOCK_NIL) {
388     			/* Ouch. Now we're screwed. We need to do a 
389     			   fold-in-place of another chain to make room
390     			   for this one. We need a better way of selecting
391     			   which chain to fold, because makefreeblock will 
392     			   only ask us to fold the same one again.
393     			*/
394     			printk(KERN_WARNING
395     			       "NFTL_findfreeblock(desperate) returns 0xffff.\n");
396     			return BLOCK_NIL;
397     		}
398     	} else {
399                 /* We put a fold mark in the chain we are folding only if
400                    we fold in place to help the mount check code. If we do
401                    not fold in place, it is possible to find the valid
402                    chain by selecting the longer one */
403                 oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
404                 oob.u.c.unused = 0xffffffff;
405                 MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, 
406                              8, &retlen, (char *)&oob.u);
407             }
408     
409     	/* OK. We now know the location of every block in the Virtual Unit Chain,
410     	   and the Erase Unit into which we are supposed to be copying.
411     	   Go for it.
412     	*/
413     	DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN);
414     	for (block = 0; block < nftl->EraseSize / 512 ; block++) {
415     		unsigned char movebuf[512];
416     		int ret;
417     
418     		/* If it's in the target EUN already, or if it's pending write, do nothing */
419     		if (BlockMap[block] == targetEUN ||
420     		    (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) {
421     			continue;
422     		}
423     
424                     /* copy only in non free block (free blocks can only
425                        happen in case of media errors or deleted blocks) */
426                     if (BlockMap[block] == BLOCK_NIL)
427                             continue;
428                     
429                     ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block])
430                                       + (block * 512), 512, &retlen, movebuf, (char *)&oob); 
431                     if (ret < 0) {
432                         ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block])
433                                           + (block * 512), 512, &retlen,
434                                           movebuf, (char *)&oob); 
435                         if (ret != -EIO) 
436                             printk("Error went away on retry.\n");
437                     }
438                     MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512),
439                                  512, &retlen, movebuf, (char *)&oob);
440     	}
441             
442             /* add the header so that it is now a valid chain */
443             oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum
444                     = cpu_to_le16(thisVUC);
445             oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
446             
447             MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8, 
448                          8, &retlen, (char *)&oob.u);
449     
450     	/* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
451     
452     	/* At this point, we have two different chains for this Virtual Unit, and no way to tell 
453     	   them apart. If we crash now, we get confused. However, both contain the same data, so we
454     	   shouldn't actually lose data in this case. It's just that when we load up on a medium which
455     	   has duplicate chains, we need to free one of the chains because it's not necessary any more.
456     	*/
457     	thisEUN = nftl->EUNtable[thisVUC];
458     	DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n");
459     
460     	/* For each block in the old chain (except the targetEUN of course), 
461     	   free it and make it available for future use */
462     	while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
463     		unsigned int EUNtmp;
464     
465                     EUNtmp = nftl->ReplUnitTable[thisEUN];
466     
467                     if (NFTL_formatblock(nftl, thisEUN) < 0) {
468     			/* could not erase : mark block as reserved
469     			 * FixMe: Update Bad Unit Table on disk
470     			 */
471     			nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
472                     } else {
473     			/* correctly erased : mark it as free */
474     			nftl->ReplUnitTable[thisEUN] = BLOCK_FREE;
475     			nftl->numfreeEUNs++;
476                     }
477                     thisEUN = EUNtmp;
478     	}
479     	
480     	/* Make this the new start of chain for thisVUC */
481     	nftl->ReplUnitTable[targetEUN] = BLOCK_NIL;
482     	nftl->EUNtable[thisVUC] = targetEUN;
483     
484     	return targetEUN;
485     }
486     
487     u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
488     {
489     	/* This is the part that needs some cleverness applied. 
490     	   For now, I'm doing the minimum applicable to actually
491     	   get the thing to work.
492     	   Wear-levelling and other clever stuff needs to be implemented
493     	   and we also need to do some assessment of the results when
494     	   the system loses power half-way through the routine.
495     	*/
496     	u16 LongestChain = 0;
497     	u16 ChainLength = 0, thislen;
498     	u16 chain, EUN;
499     
500     	for (chain = 0; chain < nftl->MediaHdr.FormattedSize / nftl->EraseSize; chain++) {
501     		EUN = nftl->EUNtable[chain];
502     		thislen = 0;
503     
504     		while (EUN <= nftl->lastEUN) {
505     			thislen++;
506     			//printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN);
507     			EUN = nftl->ReplUnitTable[EUN] & 0x7fff;
508     			if (thislen > 0xff00) {
509     				printk("Endless loop in Virtual Chain %d: Unit %x\n",
510     				       chain, EUN);
511     			}
512     			if (thislen > 0xff10) {
513     				/* Actually, don't return failure. Just ignore this chain and
514     				   get on with it. */
515     				thislen = 0;
516     				break;
517     			}
518     		}
519     
520     		if (thislen > ChainLength) {
521     			//printk("New longest chain is %d with length %d\n", chain, thislen);
522     			ChainLength = thislen;
523     			LongestChain = chain;
524     		}
525     	}
526     
527     	if (ChainLength < 2) {
528     		printk(KERN_WARNING "No Virtual Unit Chains available for folding. "
529     		       "Failing request\n");
530     		return 0xffff;
531     	}
532     
533     	return NFTL_foldchain (nftl, LongestChain, pendingblock);
534     }
535     
536     /* NFTL_findwriteunit: Return the unit number into which we can write 
537                            for this block. Make it available if it isn't already
538     */
539     static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
540     {
541     	u16 lastEUN;
542     	u16 thisVUC = block / (nftl->EraseSize / 512);
543     	unsigned int writeEUN;
544     	unsigned long blockofs = (block * 512) & (nftl->EraseSize -1);
545     	size_t retlen;
546     	int silly, silly2 = 3;
547     	struct nftl_oob oob;
548     
549     	do {
550     		/* Scan the media to find a unit in the VUC which has
551     		   a free space for the block in question.
552     		*/
553     
554     		/* This condition catches the 0x[7f]fff cases, as well as 
555     		   being a sanity check for past-end-of-media access
556     		*/
557     		lastEUN = BLOCK_NIL;
558     		writeEUN = nftl->EUNtable[thisVUC];
559                     silly = MAX_LOOPS;
560     		while (writeEUN <= nftl->lastEUN) {
561     			struct nftl_bci bci;
562     			size_t retlen;
563                             unsigned int status;
564     
565     			lastEUN = writeEUN;
566     
567     			MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs,
568     				    8, &retlen, (char *)&bci);
569     			
570     			DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
571     			      block , writeEUN, le16_to_cpu(bci.Status));
572     
573                             status = bci.Status | bci.Status1;
574     			switch(status) {
575     			case SECTOR_FREE:
576     				return writeEUN;
577     
578     			case SECTOR_DELETED:
579     			case SECTOR_USED:
580     			case SECTOR_IGNORE:
581     				break;
582     			default:
583     				// Invalid block. Don't use it any more. Must implement.
584     				break;			
585     			}
586     			
587     			if (!silly--) { 
588     				printk(KERN_WARNING
589     				       "Infinite loop in Virtual Unit Chain 0x%x\n",
590     				       thisVUC);
591     				return 0xffff;
592     			}
593     
594     			/* Skip to next block in chain */
595     			writeEUN = nftl->ReplUnitTable[writeEUN];
596     		}
597     
598     		/* OK. We didn't find one in the existing chain, or there 
599     		   is no existing chain. */
600     
601     		/* Try to find an already-free block */
602     		writeEUN = NFTL_findfreeblock(nftl, 0);
603     
604     		if (writeEUN == BLOCK_NIL) {
605     			/* That didn't work - there were no free blocks just
606     			   waiting to be picked up. We're going to have to fold
607     			   a chain to make room.
608     			*/
609     
610     			/* First remember the start of this chain */
611     			//u16 startEUN = nftl->EUNtable[thisVUC];
612     			
613     			//printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
614     			writeEUN = NFTL_makefreeblock(nftl, 0xffff);
615     
616     			if (writeEUN == BLOCK_NIL) {
617     				/* OK, we accept that the above comment is 
618     				   lying - there may have been free blocks
619     				   last time we called NFTL_findfreeblock(),
620     				   but they are reserved for when we're
621     				   desperate. Well, now we're desperate.
622     				*/
623     				DEBUG(MTD_DEBUG_LEVEL1, "Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
624     				writeEUN = NFTL_findfreeblock(nftl, 1);
625     			}
626     			if (writeEUN == BLOCK_NIL) {
627     				/* Ouch. This should never happen - we should
628     				   always be able to make some room somehow. 
629     				   If we get here, we've allocated more storage 
630     				   space than actual media, or our makefreeblock
631     				   routine is missing something.
632     				*/
633     				printk(KERN_WARNING "Cannot make free space.\n");
634     				return BLOCK_NIL;
635     			}			
636     			//printk("Restarting scan\n");
637     			lastEUN = BLOCK_NIL;
638     			continue;
639     		}
640     
641     		/* We've found a free block. Insert it into the chain. */
642     		
643     		if (lastEUN != BLOCK_NIL) {
644                         thisVUC |= 0x8000; /* It's a replacement block */
645     		} else {
646                         /* The first block in a new chain */
647                         nftl->EUNtable[thisVUC] = writeEUN;
648     		}
649     
650     		/* set up the actual EUN we're writing into */
651     		/* Both in our cache... */
652     		nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
653     
654     		/* ... and on the flash itself */
655     		MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8,
656     			    &retlen, (char *)&oob.u);
657     
658     		oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
659     
660     		MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8,
661                                  &retlen, (char *)&oob.u);
662     
663                     /* we link the new block to the chain only after the
664                        block is ready. It avoids the case where the chain
665                        could point to a free block */
666                     if (lastEUN != BLOCK_NIL) {
667     			/* Both in our cache... */
668     			nftl->ReplUnitTable[lastEUN] = writeEUN;
669     			/* ... and on the flash itself */
670     			MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8,
671     				    8, &retlen, (char *)&oob.u);
672     
673     			oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
674     				= cpu_to_le16(writeEUN);
675     
676     			MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8,
677     				     8, &retlen, (char *)&oob.u);
678     		}
679     
680     		return writeEUN;
681     
682     	} while (silly2--);
683     
684     	printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n",
685     	       thisVUC);
686     	return 0xffff;
687     }
688     
689     static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer)
690     {
691     	u16 writeEUN;
692     	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
693     	size_t retlen;
694     	u8 eccbuf[6];
695     
696     	writeEUN = NFTL_findwriteunit(nftl, block);
697     
698     	if (writeEUN == BLOCK_NIL) {
699     		printk(KERN_WARNING
700     		       "NFTL_writeblock(): Cannot find block to write to\n");
701     		/* If we _still_ haven't got a block to use, we're screwed */
702     		return 1;
703     	}
704     
705     	MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs,
706     		     512, &retlen, (char *)buffer, (char *)eccbuf);
707             /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */
708     
709     	return 0;
710     }
711     #endif /* CONFIG_NFTL_RW */
712     
713     static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer)
714     {
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 (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs,
728     					8, &retlen, (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 %d 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%x\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     		u_char eccbuf[6];
768     		if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf))
769     			return -EIO;
770     	}
771     	return 0;
772     }
773     
774     static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
775     {
776     	struct NFTLrecord *nftl;
777     	int p;
778     
779     	nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS];
780     
781     	if (!nftl) return -EINVAL;
782     
783     	switch (cmd) {
784     	case HDIO_GETGEO: {
785     		struct hd_geometry g;
786     
787     		g.heads = nftl->heads;
788     		g.sectors = nftl->sectors;
789     		g.cylinders = nftl->cylinders;
790     		g.start = part_table[MINOR(inode->i_rdev)].start_sect;
791     		return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
792     	}
793     	case BLKGETSIZE:   /* Return device size */
794     		return put_user(part_table[MINOR(inode->i_rdev)].nr_sects,
795                                     (long *) arg);
796     	case BLKGETSIZE64:
797     		return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9,
798                                     (u64 *)arg);
799     		
800     	case BLKFLSBUF:
801     		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
802     		fsync_dev(inode->i_rdev);
803     		invalidate_buffers(inode->i_rdev);
804     		if (nftl->mtd->sync)
805     			nftl->mtd->sync(nftl->mtd);
806     		return 0;
807     
808     	case BLKRRPART:
809     		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
810     		if (nftl->usecount > 1) return -EBUSY;
811     		/* 
812     		 * We have to flush all buffers and invalidate caches,
813     		 * or we won't be able to re-use the partitions,
814     		 * if there was a change and we don't want to reboot
815     		 */
816     		p = (1<<NFTL_PARTN_BITS) - 1;
817     		while (p-- > 0) {
818     			kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p);
819     			if (part_table[p].nr_sects > 0)
820     				invalidate_device (devp, 1);
821     
822     			part_table[MINOR(inode->i_dev)+p].start_sect = 0;
823     			part_table[MINOR(inode->i_dev)+p].nr_sects = 0;
824     		}
825     		
826     #if LINUX_VERSION_CODE < 0x20328
827     		resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS);
828     #else
829     		grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS,
830     				1<<NFTL_PARTN_BITS, nftl->nr_sects);
831     #endif
832     		return 0;
833     
834     #if (LINUX_VERSION_CODE < 0x20303)		
835     	RO_IOCTLS(inode->i_rdev, arg);  /* ref. linux/blk.h */
836     #else
837     	case BLKROSET:
838     	case BLKROGET:
839     	case BLKSSZGET:
840     		return blk_ioctl(inode->i_rdev, cmd, arg);
841     #endif
842     
843     	default:
844     		return -EINVAL;
845     	}
846     }
847     
848     void nftl_request(RQFUNC_ARG)
849     {
850     	unsigned int dev, block, nsect;
851     	struct NFTLrecord *nftl;
852     	char *buffer;
853     	struct request *req;
854     	int res;
855     
856     	while (1) {
857     		INIT_REQUEST;	/* blk.h */
858     		req = CURRENT;
859     		
860     		/* We can do this because the generic code knows not to
861     		   touch the request at the head of the queue */
862     		spin_unlock_irq(&io_request_lock);
863     
864     		DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n");
865     		DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n",
866     		      (req->cmd == READ) ? "Read " : "Write",
867     		      req->sector, req->current_nr_sectors);
868     
869     		dev = MINOR(req->rq_dev);
870     		block = req->sector;
871     		nsect = req->current_nr_sectors;
872     		buffer = req->buffer;
873     		res = 1; /* succeed */
874     
875     		if (dev >= MAX_NFTLS * (1<<NFTL_PARTN_BITS)) {
876     			/* there is no such partition */
877     			printk("nftl: bad minor number: device = %s\n",
878     			       kdevname(req->rq_dev));
879     			res = 0; /* fail */
880     			goto repeat;
881     		}
882     		
883     		nftl = NFTLs[dev / (1<<NFTL_PARTN_BITS)];
884     		DEBUG(MTD_DEBUG_LEVEL3, "Waiting for mutex\n");
885     		down(&nftl->mutex);
886     		DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n");
887     
888     		if (block + nsect > part_table[dev].nr_sects) {
889     			/* access past the end of device */
890     			printk("nftl%c%d: bad access: block = %d, count = %d\n",
891     			       (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect);
892     			up(&nftl->mutex);
893     			res = 0; /* fail */
894     			goto repeat;
895     		}
896     		
897     		block += part_table[dev].start_sect;
898     		
899     		if (req->cmd == READ) {
900     			DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x "
901     			      "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors);
902     	
903     			for ( ; nsect > 0; nsect-- , block++, buffer += 512) {
904     				/* Read a single sector to req->buffer + (512 * i) */
905     				if (NFTL_readblock(nftl, block, buffer)) {
906     					DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n");
907     					up(&nftl->mutex);
908     					res = 0;
909     					goto repeat;
910     				}
911     			}
912     
913     			DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n");
914     			up(&nftl->mutex);
915     			goto repeat;
916     		} else if (req->cmd == WRITE) {
917     			DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x "
918     			      "(req->nr_sectors == %lx)\n", nsect, block,
919     			      req->nr_sectors);
920     #ifdef CONFIG_NFTL_RW
921     			for ( ; nsect > 0; nsect-- , block++, buffer += 512) {
922     				/* Read a single sector to req->buffer + (512 * i) */
923     				if (NFTL_writeblock(nftl, block, buffer)) {
924     					DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n");
925     					up(&nftl->mutex);
926     					res = 0;
927     					goto repeat;
928     				}
929     			}
930     			DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n");
931     #else
932     			res = 0; /* Writes always fail */
933     #endif /* CONFIG_NFTL_RW */
934     			up(&nftl->mutex);
935     			goto repeat;
936     		} else {
937     			DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n");
938     			up(&nftl->mutex);
939     			res = 0;
940     			goto repeat;
941     		}
942     	repeat: 
943     		DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res);
944     		spin_lock_irq(&io_request_lock);
945     		end_request(res);
946     	}
947     }
948     
949     static int nftl_open(struct inode *ip, struct file *fp)
950     {
951     	int nftlnum = MINOR(ip->i_rdev) >> NFTL_PARTN_BITS;
952     	struct NFTLrecord *thisNFTL;
953     	thisNFTL = NFTLs[nftlnum];
954     
955     	DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n");
956     
957     #ifdef CONFIG_KMOD
958     	if (!thisNFTL && nftlnum == 0) {
959     		request_module("docprobe");
960     		thisNFTL = NFTLs[nftlnum];
961     	}
962     #endif
963     	if (!thisNFTL) {
964     		DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", 
965     		      nftlnum, ip->i_rdev, ip, fp);
966     		return -ENODEV;
967     	}
968     
969     #ifndef CONFIG_NFTL_RW
970     	if (fp->f_mode & FMODE_WRITE)
971     		return -EROFS;
972     #endif /* !CONFIG_NFTL_RW */
973     
974     	thisNFTL->usecount++;
975     	MOD_INC_USE_COUNT;
976     	if (!get_mtd_device(thisNFTL->mtd, -1)) {
977     		MOD_DEC_USE_COUNT;
978     		return /* -E'SBUGGEREDOFF */ -ENXIO;
979     	}
980     
981     	return 0;
982     }
983     
984     static int nftl_release(struct inode *inode, struct file *fp)
985     {
986     	struct NFTLrecord *thisNFTL;
987     
988     	thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16];
989     
990     	DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n");
991     
992     	invalidate_device(inode->i_rdev, 1);
993     
994     	if (thisNFTL->mtd->sync)
995     		thisNFTL->mtd->sync(thisNFTL->mtd);
996     	thisNFTL->usecount--;
997     	MOD_DEC_USE_COUNT;
998     
999     	put_mtd_device(thisNFTL->mtd);
1000     
1001     	return 0;
1002     }
1003     #if LINUX_VERSION_CODE < 0x20326
1004     static struct file_operations nftl_fops = {
1005     	read:		block_read,
1006     	write:		block_write,
1007     	ioctl:		nftl_ioctl,
1008     	open:		nftl_open,
1009     	release:	nftl_release,
1010     	fsync:		block_fsync,
1011     };
1012     #else
1013     static struct block_device_operations nftl_fops = 
1014     {
1015     	open:		nftl_open,
1016     	release:	nftl_release,
1017     	ioctl: 		nftl_ioctl
1018     };
1019     #endif
1020     
1021     
1022     
1023     /****************************************************************************
1024      *
1025      * Module stuff
1026      *
1027      ****************************************************************************/
1028     
1029     static struct mtd_notifier nftl_notifier = {
1030     	add:	NFTL_notify_add,
1031     	remove:	NFTL_notify_remove
1032     };
1033     
1034     static int __init init_nftl(void)
1035     {
1036     	int i;
1037     
1038     	printk(KERN_NOTICE
1039     	       "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n");
1040     #ifdef PRERELEASE 
1041     	printk(KERN_INFO"$Id: nftlcore.c,v 1.73 2001/06/09 01:09:43 dwmw2 Exp $\n");
1042     #endif
1043     
1044     	if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){
1045     		printk("unable to register NFTL block device on major %d\n",
1046     		       MAJOR_NR);
1047     		return -EBUSY;
1048     	} else {
1049     		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request);
1050     
1051     		/* set block size to 1kB each */
1052     		for (i = 0; i < 256; i++) {
1053     			nftl_blocksizes[i] = 1024;
1054     		}
1055     		blksize_size[MAJOR_NR] = nftl_blocksizes;
1056     
1057     		add_gendisk(&nftl_gendisk);
1058     	}
1059     	
1060     	register_mtd_user(&nftl_notifier);
1061     
1062     	return 0;
1063     }
1064     
1065     static void __exit cleanup_nftl(void)
1066     {
1067       	unregister_mtd_user(&nftl_notifier);
1068       	unregister_blkdev(MAJOR_NR, "nftl");
1069       	
1070       	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1071     
1072     	del_gendisk(&nftl_gendisk);
1073     }
1074     
1075     module_init(init_nftl);
1076     module_exit(cleanup_nftl);
1077