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

1     /* This version ported to the Linux-MTD system by dwmw2@infradead.org
2      * $Id: ftl.c,v 1.35 2001/06/09 00:40:17 dwmw2 Exp $
3      *
4      * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
5      * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
6      *
7      * Based on:
8      */
9     /*======================================================================
10     
11         A Flash Translation Layer memory card driver
12     
13         This driver implements a disk-like block device driver with an
14         apparent block size of 512 bytes for flash memory cards.
15     
16         ftl_cs.c 1.62 2000/02/01 00:59:04
17     
18         The contents of this file are subject to the Mozilla Public
19         License Version 1.1 (the "License"); you may not use this file
20         except in compliance with the License. You may obtain a copy of
21         the License at http://www.mozilla.org/MPL/
22     
23         Software distributed under the License is distributed on an "AS
24         IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
25         implied. See the License for the specific language governing
26         rights and limitations under the License.
27     
28         The initial developer of the original code is David A. Hinds
29         <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
30         are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
31     
32         Alternatively, the contents of this file may be used under the
33         terms of the GNU General Public License version 2 (the "GPL"), in
34         which case the provisions of the GPL are applicable instead of the
35         above.  If you wish to allow the use of your version of this file
36         only under the terms of the GPL and not to allow others to use
37         your version of this file under the MPL, indicate your decision
38         by deleting the provisions above and replace them with the notice
39         and other provisions required by the GPL.  If you do not delete
40         the provisions above, a recipient may use your version of this
41         file under either the MPL or the GPL.
42     
43         LEGAL NOTE: The FTL format is patented by M-Systems.  They have
44         granted a license for its use with PCMCIA devices:
45     
46          "M-Systems grants a royalty-free, non-exclusive license under
47           any presently existing M-Systems intellectual property rights
48           necessary for the design and development of FTL-compatible
49           drivers, file systems and utilities using the data formats with
50           PCMCIA PC Cards as described in the PCMCIA Flash Translation
51           Layer (FTL) Specification."
52     
53         Use of the FTL format for non-PCMCIA applications may be an
54         infringement of these patents.  For additional information,
55         contact M-Systems (http://www.m-sys.com) directly.
56           
57     ======================================================================*/
58     #include <linux/module.h>
59     #include <linux/mtd/compatmac.h>
60     #include <linux/mtd/mtd.h>
61     /*#define PSYCHO_DEBUG */
62     
63     #include <linux/kernel.h>
64     #include <linux/sched.h>
65     #include <linux/ptrace.h>
66     #include <linux/slab.h>
67     #include <linux/string.h>
68     #include <linux/timer.h>
69     #include <linux/major.h>
70     #include <linux/fs.h>
71     #include <linux/ioctl.h>
72     #include <linux/hdreg.h>
73     #include <stdarg.h>
74     
75     #if (LINUX_VERSION_CODE >= 0x20100)
76     #include <linux/vmalloc.h>
77     #endif
78     #if (LINUX_VERSION_CODE >= 0x20303)
79     #include <linux/blkpg.h>
80     #endif
81     
82     #include <linux/mtd/ftl.h>
83     /*====================================================================*/
84     /* Stuff which really ought to be in compatmac.h */
85     
86     #if (LINUX_VERSION_CODE < 0x20328)
87     #define register_disk(dev, drive, minors, ops, size) \
88         do { (dev)->part[(drive)*(minors)].nr_sects = size; \
89             if (size == 0) (dev)->part[(drive)*(minors)].start_sect = -1; \
90             resetup_one_dev(dev, drive); } while (0);
91     #endif
92     
93     #if (LINUX_VERSION_CODE < 0x20320)
94     #define BLK_DEFAULT_QUEUE(n)    blk_dev[n].request_fn
95     #define blk_init_queue(q, req)  q = (req)
96     #define blk_cleanup_queue(q)    q = NULL
97     #define request_arg_t           void
98     #else
99     #define request_arg_t           request_queue_t *q
100     #endif
101     
102     
103     /*====================================================================*/
104     
105     /* Parameters that can be set with 'insmod' */
106     static int shuffle_freq = 50;
107     MODULE_PARM(shuffle_freq, "i");
108     
109     /*====================================================================*/
110     
111     /* Major device # for FTL device */
112     #ifndef FTL_MAJOR
113     #define FTL_MAJOR	44
114     #endif
115     
116     /* Funky stuff for setting up a block device */
117     #define MAJOR_NR		FTL_MAJOR
118     #define DEVICE_NAME		"ftl"
119     #define DEVICE_REQUEST		do_ftl_request
120     #define DEVICE_ON(device)
121     #define DEVICE_OFF(device)
122     
123     #define DEVICE_NR(minor)	((minor)>>5)
124     #define REGION_NR(minor)	(((minor)>>3)&3)
125     #define PART_NR(minor)		((minor)&7)
126     #define MINOR_NR(dev,reg,part)	(((dev)<<5)+((reg)<<3)+(part))
127     
128     #include <linux/blk.h>
129     
130     /*====================================================================*/
131     
132     /* Maximum number of separate memory devices we'll allow */
133     #define MAX_DEV		4
134     
135     /* Maximum number of regions per device */
136     #define MAX_REGION	4
137     
138     /* Maximum number of partitions in an FTL region */
139     #define PART_BITS	3
140     #define MAX_PART	8
141     
142     /* Maximum number of outstanding erase requests per socket */
143     #define MAX_ERASE	8
144     
145     /* Sector size -- shouldn't need to change */
146     #define SECTOR_SIZE	512
147     
148     
149     /* Each memory region corresponds to a minor device */
150     typedef struct partition_t {
151         struct mtd_info	*mtd;
152         u_int32_t		state;
153         u_int32_t		*VirtualBlockMap;
154         u_int32_t		*VirtualPageMap;
155         u_int32_t		FreeTotal;
156         struct eun_info_t {
157     	u_int32_t		Offset;
158     	u_int32_t		EraseCount;
159     	u_int32_t		Free;
160     	u_int32_t		Deleted;
161         } *EUNInfo;
162         struct xfer_info_t {
163     	u_int32_t		Offset;
164     	u_int32_t		EraseCount;
165     	u_int16_t		state;
166         } *XferInfo;
167         u_int16_t		bam_index;
168         u_int32_t		*bam_cache;
169         u_int16_t		DataUnits;
170         u_int32_t		BlocksPerUnit;
171         erase_unit_header_t	header;
172     #if 0
173         region_info_t	region;
174         memory_handle_t	handle;
175     #endif
176         atomic_t		open;
177     } partition_t;
178     
179     partition_t *myparts[MAX_MTD_DEVICES];
180     
181     static void ftl_notify_add(struct mtd_info *mtd);
182     static void ftl_notify_remove(struct mtd_info *mtd);
183     
184     void ftl_freepart(partition_t *part);
185     
186     static struct mtd_notifier ftl_notifier = {
187     	add:	ftl_notify_add,
188     	remove:	ftl_notify_remove,
189     };
190     
191     /* Partition state flags */
192     #define FTL_FORMATTED	0x01
193     
194     /* Transfer unit states */
195     #define XFER_UNKNOWN	0x00
196     #define XFER_ERASING	0x01
197     #define XFER_ERASED	0x02
198     #define XFER_PREPARED	0x03
199     #define XFER_FAILED	0x04
200     
201     static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)];
202     static int ftl_sizes[MINOR_NR(MAX_DEV, 0, 0)];
203     static int ftl_blocksizes[MINOR_NR(MAX_DEV, 0, 0)];
204     
205     static struct gendisk ftl_gendisk = {
206         major:		FTL_MAJOR,
207         major_name:		"ftl",
208         minor_shift:	PART_BITS,
209         max_p:		MAX_PART,
210     #if (LINUX_VERSION_CODE < 0x20328)
211         max_nr:		MAX_DEV*MAX_PART,
212     #endif
213         part:		ftl_hd,
214         sizes:		ftl_sizes,
215     };
216     
217     /*====================================================================*/
218     
219     static int ftl_ioctl(struct inode *inode, struct file *file,
220     		     u_int cmd, u_long arg);
221     static int ftl_open(struct inode *inode, struct file *file);
222     static release_t ftl_close(struct inode *inode, struct file *file);
223     static int ftl_reread_partitions(int minor);
224     
225     static void ftl_erase_callback(struct erase_info *done);
226     
227     #if LINUX_VERSION_CODE < 0x20326
228     static struct file_operations ftl_blk_fops = {
229         open:	ftl_open,
230         release:	ftl_close,
231         ioctl:	ftl_ioctl,
232         read:	block_read,
233         write:	block_write,
234         fsync:	block_fsync
235     };
236     #else
237     static struct block_device_operations ftl_blk_fops = {
238         open:	ftl_open,
239         release:	ftl_close,
240         ioctl:	ftl_ioctl,
241     };
242     #endif
243     
244     /*======================================================================
245     
246         Scan_header() checks to see if a memory region contains an FTL
247         partition.  build_maps() reads all the erase unit headers, builds
248         the erase unit map, and then builds the virtual page map.
249         
250     ======================================================================*/
251     
252     static int scan_header(partition_t *part)
253     {
254         erase_unit_header_t header;
255         loff_t offset, max_offset;
256         int ret;
257         part->header.FormattedSize = 0;
258         max_offset = (0x100000<part->mtd->size)?0x100000:part->mtd->size;
259         /* Search first megabyte for a valid FTL header */
260         for (offset = 0;
261     	 offset < max_offset;
262     	 offset += part->mtd->erasesize ? : 0x2000) {
263     
264     	ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret, 
265     			      (unsigned char *)&header);
266     	
267     	if (ret) 
268     	    return ret;
269     
270     	if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
271         }
272     
273         if (offset == max_offset) {
274     	printk(KERN_NOTICE "ftl_cs: FTL header not found.\n");
275     	return -ENOENT;
276         }
277         if ((le16_to_cpu(header.NumEraseUnits) > 65536) || header.BlockSize != 9 ||
278     	(header.EraseUnitSize < 10) || (header.EraseUnitSize > 31) ||
279     	(header.NumTransferUnits >= le16_to_cpu(header.NumEraseUnits))) {
280     	printk(KERN_NOTICE "ftl_cs: FTL header corrupt!\n");
281     	return -1;
282         }
283         if ((1 << header.EraseUnitSize) != part->mtd->erasesize) {
284     	printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %x\n",
285     	       1 << header.EraseUnitSize,part->mtd->erasesize);
286     	return -1;
287         }
288         part->header = header;
289         return 0;
290     }
291     
292     static int build_maps(partition_t *part)
293     {
294         erase_unit_header_t header;
295         u_int16_t xvalid, xtrans, i;
296         u_int blocks, j;
297         int hdr_ok, ret = -1;
298         ssize_t retval;
299         loff_t offset;
300     
301         /* Set up erase unit maps */
302         part->DataUnits = le16_to_cpu(part->header.NumEraseUnits) -
303     	part->header.NumTransferUnits;
304         part->EUNInfo = kmalloc(part->DataUnits * sizeof(struct eun_info_t),
305     			    GFP_KERNEL);
306         if (!part->EUNInfo)
307     	    goto out;
308         for (i = 0; i < part->DataUnits; i++)
309     	part->EUNInfo[i].Offset = 0xffffffff;
310         part->XferInfo =
311     	kmalloc(part->header.NumTransferUnits * sizeof(struct xfer_info_t),
312     		GFP_KERNEL);
313         if (!part->XferInfo)
314     	    goto out_EUNInfo;
315     
316         xvalid = xtrans = 0;
317         for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) {
318     	offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN))
319     		      << part->header.EraseUnitSize);
320     	ret = part->mtd->read(part->mtd, offset, sizeof(header), &retval, 
321     			      (unsigned char *)&header);
322     	
323     	if (ret) 
324     	    goto out_XferInfo;
325     
326     	ret = -1;
327     	/* Is this a transfer partition? */
328     	hdr_ok = (strcmp(header.DataOrgTuple+3, "FTL100") == 0);
329     	if (hdr_ok && (le16_to_cpu(header.LogicalEUN) < part->DataUnits) &&
330     	    (part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset == 0xffffffff)) {
331     	    part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset = offset;
332     	    part->EUNInfo[le16_to_cpu(header.LogicalEUN)].EraseCount =
333     		le32_to_cpu(header.EraseCount);
334     	    xvalid++;
335     	} else {
336     	    if (xtrans == part->header.NumTransferUnits) {
337     		printk(KERN_NOTICE "ftl_cs: format error: too many "
338     		       "transfer units!\n");
339     		goto out_XferInfo;
340     	    }
341     	    if (hdr_ok && (le16_to_cpu(header.LogicalEUN) == 0xffff)) {
342     		part->XferInfo[xtrans].state = XFER_PREPARED;
343     		part->XferInfo[xtrans].EraseCount = le32_to_cpu(header.EraseCount);
344     	    } else {
345     		part->XferInfo[xtrans].state = XFER_UNKNOWN;
346     		/* Pick anything reasonable for the erase count */
347     		part->XferInfo[xtrans].EraseCount =
348     		    le32_to_cpu(part->header.EraseCount);
349     	    }
350     	    part->XferInfo[xtrans].Offset = offset;
351     	    xtrans++;
352     	}
353         }
354         /* Check for format trouble */
355         header = part->header;
356         if ((xtrans != header.NumTransferUnits) ||
357     	(xvalid+xtrans != le16_to_cpu(header.NumEraseUnits))) {
358     	printk(KERN_NOTICE "ftl_cs: format error: erase units "
359     	       "don't add up!\n");
360     	goto out_XferInfo;
361         }
362         
363         /* Set up virtual page map */
364         blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
365         part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t));
366         if (!part->VirtualBlockMap)
367     	    goto out_XferInfo;
368     
369         memset(part->VirtualBlockMap, 0xff, blocks * sizeof(u_int32_t));
370         part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize;
371     
372         part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(u_int32_t),
373     			      GFP_KERNEL);
374         if (!part->bam_cache)
375     	    goto out_VirtualBlockMap;
376     
377         part->bam_index = 0xffff;
378         part->FreeTotal = 0;
379     
380         for (i = 0; i < part->DataUnits; i++) {
381     	part->EUNInfo[i].Free = 0;
382     	part->EUNInfo[i].Deleted = 0;
383     	offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
384     	
385     	ret = part->mtd->read(part->mtd, offset,  
386     			      part->BlocksPerUnit * sizeof(u_int32_t), &retval, 
387     			      (unsigned char *)part->bam_cache);
388     	
389     	if (ret) 
390     		goto out_bam_cache;
391     
392     	for (j = 0; j < part->BlocksPerUnit; j++) {
393     	    if (BLOCK_FREE(le32_to_cpu(part->bam_cache[j]))) {
394     		part->EUNInfo[i].Free++;
395     		part->FreeTotal++;
396     	    } else if ((BLOCK_TYPE(le32_to_cpu(part->bam_cache[j])) == BLOCK_DATA) &&
397     		     (BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j])) < blocks))
398     		part->VirtualBlockMap[BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j]))] =
399     		    (i << header.EraseUnitSize) + (j << header.BlockSize);
400     	    else if (BLOCK_DELETED(le32_to_cpu(part->bam_cache[j])))
401     		part->EUNInfo[i].Deleted++;
402     	}
403         }
404         
405         ret = 0;
406         goto out;
407     
408     out_bam_cache:
409         kfree(part->bam_cache);
410     out_VirtualBlockMap:
411         vfree(part->VirtualBlockMap);
412     out_XferInfo:
413         kfree(part->XferInfo);
414     out_EUNInfo:
415         kfree(part->EUNInfo);
416     out:
417         return ret;
418     } /* build_maps */
419     
420     /*======================================================================
421     
422         Erase_xfer() schedules an asynchronous erase operation for a
423         transfer unit.
424         
425     ======================================================================*/
426     
427     static int erase_xfer(partition_t *part,
428     		      u_int16_t xfernum)
429     {
430         int ret;
431         struct xfer_info_t *xfer;
432         struct erase_info *erase;
433     
434         xfer = &part->XferInfo[xfernum];
435         DEBUG(1, "ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
436         xfer->state = XFER_ERASING;
437     
438         /* Is there a free erase slot? Always in MTD. */
439         
440         
441         erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL);
442         if (!erase) 
443                 return -ENOMEM;
444     
445         erase->callback = ftl_erase_callback;
446         erase->addr = xfer->Offset;
447         erase->len = 1 << part->header.EraseUnitSize;
448         erase->priv = (u_long)part;
449         
450         ret = part->mtd->erase(part->mtd, erase);
451     
452         if (!ret)
453     	    xfer->EraseCount++;
454         else
455     	    kfree(erase);
456     
457         return ret;
458     } /* erase_xfer */
459     
460     /*======================================================================
461     
462         Prepare_xfer() takes a freshly erased transfer unit and gives
463         it an appropriate header.
464         
465     ======================================================================*/
466     
467     static void ftl_erase_callback(struct erase_info *erase)
468     {
469         partition_t *part;
470         struct xfer_info_t *xfer;
471         int i;
472         
473         /* Look up the transfer unit */
474         part = (partition_t *)(erase->priv);
475     
476         for (i = 0; i < part->header.NumTransferUnits; i++)
477     	if (part->XferInfo[i].Offset == erase->addr) break;
478     
479         if (i == part->header.NumTransferUnits) {
480     	printk(KERN_NOTICE "ftl_cs: internal error: "
481     	       "erase lookup failed!\n");
482     	return;
483         }
484     
485         xfer = &part->XferInfo[i];
486         if (erase->state == MTD_ERASE_DONE)
487     	xfer->state = XFER_ERASED;
488         else {
489     	xfer->state = XFER_FAILED;
490     	printk(KERN_NOTICE "ftl_cs: erase failed: state = %d\n",
491     	       erase->state);
492         }
493     
494         kfree(erase);
495     
496     } /* ftl_erase_callback */
497     
498     static int prepare_xfer(partition_t *part, int i)
499     {
500         erase_unit_header_t header;
501         struct xfer_info_t *xfer;
502         int nbam, ret;
503         u_int32_t ctl;
504         ssize_t retlen;
505         loff_t offset;
506     
507         xfer = &part->XferInfo[i];
508         xfer->state = XFER_FAILED;
509         
510         DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
511     
512         /* Write the transfer unit header */
513         header = part->header;
514         header.LogicalEUN = cpu_to_le16(0xffff);
515         header.EraseCount = cpu_to_le32(xfer->EraseCount);
516     
517         ret = part->mtd->write(part->mtd, xfer->Offset, sizeof(header),
518     			   &retlen, (u_char *)&header);
519     
520         if (ret) {
521     	return ret;
522         }
523     
524         /* Write the BAM stub */
525         nbam = (part->BlocksPerUnit * sizeof(u_int32_t) +
526     	    le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE;
527     
528         offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset);
529         ctl = cpu_to_le32(BLOCK_CONTROL);
530     
531         for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) {
532     
533     	ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), 
534     			       &retlen, (u_char *)&ctl);
535     
536     	if (ret)
537     	    return ret;
538         }
539         xfer->state = XFER_PREPARED;
540         return 0;
541         
542     } /* prepare_xfer */
543     
544     /*======================================================================
545     
546         Copy_erase_unit() takes a full erase block and a transfer unit,
547         copies everything to the transfer unit, then swaps the block
548         pointers.
549     
550         All data blocks are copied to the corresponding blocks in the
551         target unit, so the virtual block map does not need to be
552         updated.
553         
554     ======================================================================*/
555     
556     static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
557     			   u_int16_t xferunit)
558     {
559         u_char buf[SECTOR_SIZE];
560         struct eun_info_t *eun;
561         struct xfer_info_t *xfer;
562         u_int32_t src, dest, free, i;
563         u_int16_t unit;
564         int ret;
565         ssize_t retlen;
566         loff_t offset;
567         u_int16_t srcunitswap = cpu_to_le16(srcunit);
568     
569         eun = &part->EUNInfo[srcunit];
570         xfer = &part->XferInfo[xferunit];
571         DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
572     	  eun->Offset, xfer->Offset);
573     	
574         
575         /* Read current BAM */
576         if (part->bam_index != srcunit) {
577     
578     	offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
579     
580     	ret = part->mtd->read(part->mtd, offset, 
581     			      part->BlocksPerUnit * sizeof(u_int32_t),
582     			      &retlen, (u_char *) (part->bam_cache));
583     
584     	/* mark the cache bad, in case we get an error later */
585     	part->bam_index = 0xffff;
586     
587     	if (ret) {
588     	    printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");                
589     	    return ret;
590     	}
591         }
592         
593         /* Write the LogicalEUN for the transfer unit */
594         xfer->state = XFER_UNKNOWN;
595         offset = xfer->Offset + 20; /* Bad! */
596         unit = cpu_to_le16(0x7fff);
597     
598         ret = part->mtd->write(part->mtd, offset, sizeof(u_int16_t),
599     			   &retlen, (u_char *) &unit);
600         
601         if (ret) {
602     	printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n");
603     	return ret;
604         }
605         
606         /* Copy all data blocks from source unit to transfer unit */
607         src = eun->Offset; dest = xfer->Offset;
608     
609         free = 0;
610         ret = 0;
611         for (i = 0; i < part->BlocksPerUnit; i++) {
612     	switch (BLOCK_TYPE(le32_to_cpu(part->bam_cache[i]))) {
613     	case BLOCK_CONTROL:
614     	    /* This gets updated later */
615     	    break;
616     	case BLOCK_DATA:
617     	case BLOCK_REPLACEMENT:
618     	    ret = part->mtd->read(part->mtd, src, SECTOR_SIZE,
619                             &retlen, (u_char *) buf);
620     	    if (ret) {
621     		printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n");
622     		return ret;
623                 }
624     
625     
626     	    ret = part->mtd->write(part->mtd, dest, SECTOR_SIZE,
627                             &retlen, (u_char *) buf);
628     	    if (ret)  {
629     		printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n");
630     		return ret;
631                 }
632     
633     	    break;
634     	default:
635     	    /* All other blocks must be free */
636     	    part->bam_cache[i] = cpu_to_le32(0xffffffff);
637     	    free++;
638     	    break;
639     	}
640     	src += SECTOR_SIZE;
641     	dest += SECTOR_SIZE;
642         }
643     
644         /* Write the BAM to the transfer unit */
645         ret = part->mtd->write(part->mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), 
646                         part->BlocksPerUnit * sizeof(int32_t), &retlen, 
647     		    (u_char *)part->bam_cache);
648         if (ret) {
649     	printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n");
650     	return ret;
651         }
652     
653         
654         /* All clear? Then update the LogicalEUN again */
655         ret = part->mtd->write(part->mtd, xfer->Offset + 20, sizeof(u_int16_t),
656     			   &retlen, (u_char *)&srcunitswap);
657     
658         if (ret) {
659     	printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n");
660     	return ret;
661         }    
662         
663         
664         /* Update the maps and usage stats*/
665         i = xfer->EraseCount;
666         xfer->EraseCount = eun->EraseCount;
667         eun->EraseCount = i;
668         i = xfer->Offset;
669         xfer->Offset = eun->Offset;
670         eun->Offset = i;
671         part->FreeTotal -= eun->Free;
672         part->FreeTotal += free;
673         eun->Free = free;
674         eun->Deleted = 0;
675         
676         /* Now, the cache should be valid for the new block */
677         part->bam_index = srcunit;
678         
679         return 0;
680     } /* copy_erase_unit */
681     
682     /*======================================================================
683     
684         reclaim_block() picks a full erase unit and a transfer unit and
685         then calls copy_erase_unit() to copy one to the other.  Then, it
686         schedules an erase on the expired block.
687     
688         What's a good way to decide which transfer unit and which erase
689         unit to use?  Beats me.  My way is to always pick the transfer
690         unit with the fewest erases, and usually pick the data unit with
691         the most deleted blocks.  But with a small probability, pick the
692         oldest data unit instead.  This means that we generally postpone
693         the next reclaimation as long as possible, but shuffle static
694         stuff around a bit for wear leveling.
695         
696     ======================================================================*/
697     
698     static int reclaim_block(partition_t *part)
699     {
700         u_int16_t i, eun, xfer;
701         u_int32_t best;
702         int queued, ret;
703     
704         DEBUG(0, "ftl_cs: reclaiming space...\n");
705         DEBUG(3, "NumTransferUnits == %x\n", part->header.NumTransferUnits);
706         /* Pick the least erased transfer unit */
707         best = 0xffffffff; xfer = 0xffff;
708         do {
709     	queued = 0;
710     	for (i = 0; i < part->header.NumTransferUnits; i++) {
711     	    int n=0;
712     	    if (part->XferInfo[i].state == XFER_UNKNOWN) {
713     		DEBUG(3,"XferInfo[%d].state == XFER_UNKNOWN\n",i);
714     		n=1;
715     		erase_xfer(part, i);
716     	    }
717     	    if (part->XferInfo[i].state == XFER_ERASING) {
718     		DEBUG(3,"XferInfo[%d].state == XFER_ERASING\n",i);
719     		n=1;
720     		queued = 1;
721     	    }
722     	    else if (part->XferInfo[i].state == XFER_ERASED) {
723     		DEBUG(3,"XferInfo[%d].state == XFER_ERASED\n",i);
724     		n=1;
725     		prepare_xfer(part, i);
726     	    }
727     	    if (part->XferInfo[i].state == XFER_PREPARED) {
728     		DEBUG(3,"XferInfo[%d].state == XFER_PREPARED\n",i);
729     		n=1;
730     		if (part->XferInfo[i].EraseCount <= best) {
731     		    best = part->XferInfo[i].EraseCount;
732     		    xfer = i;
733     		}
734     	    }
735     		if (!n)
736     		    DEBUG(3,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
737     
738     	}
739     	if (xfer == 0xffff) {
740     	    if (queued) {
741     		DEBUG(1, "ftl_cs: waiting for transfer "
742     		      "unit to be prepared...\n");
743     		if (part->mtd->sync)
744     			part->mtd->sync(part->mtd);
745     	    } else {
746     		static int ne = 0;
747     		if (++ne < 5)
748     		    printk(KERN_NOTICE "ftl_cs: reclaim failed: no "
749     			   "suitable transfer units!\n");
750     		else
751     		    DEBUG(1, "ftl_cs: reclaim failed: no "
752     			  "suitable transfer units!\n");
753     			
754     		return -EIO;
755     	    }
756     	}
757         } while (xfer == 0xffff);
758     
759         eun = 0;
760         if ((jiffies % shuffle_freq) == 0) {
761     	DEBUG(1, "ftl_cs: recycling freshest block...\n");
762     	best = 0xffffffff;
763     	for (i = 0; i < part->DataUnits; i++)
764     	    if (part->EUNInfo[i].EraseCount <= best) {
765     		best = part->EUNInfo[i].EraseCount;
766     		eun = i;
767     	    }
768         } else {
769     	best = 0;
770     	for (i = 0; i < part->DataUnits; i++)
771     	    if (part->EUNInfo[i].Deleted >= best) {
772     		best = part->EUNInfo[i].Deleted;
773     		eun = i;
774     	    }
775     	if (best == 0) {
776     	    static int ne = 0;
777     	    if (++ne < 5)
778     		printk(KERN_NOTICE "ftl_cs: reclaim failed: "
779     		       "no free blocks!\n");
780     	    else
781     		DEBUG(1,"ftl_cs: reclaim failed: "
782     		       "no free blocks!\n");
783     
784     	    return -EIO;
785     	}
786         }
787         ret = copy_erase_unit(part, eun, xfer);
788         if (!ret)
789     	erase_xfer(part, xfer);
790         else
791     	printk(KERN_NOTICE "ftl_cs: copy_erase_unit failed!\n");
792         return ret;
793     } /* reclaim_block */
794     
795     /*======================================================================
796     
797         Find_free() searches for a free block.  If necessary, it updates
798         the BAM cache for the erase unit containing the free block.  It
799         returns the block index -- the erase unit is just the currently
800         cached unit.  If there are no free blocks, it returns 0 -- this
801         is never a valid data block because it contains the header.
802         
803     ======================================================================*/
804     
805     #ifdef PSYCHO_DEBUG
806     static void dump_lists(partition_t *part)
807     {
808         int i;
809         printk(KERN_DEBUG "ftl_cs: Free total = %d\n", part->FreeTotal);
810         for (i = 0; i < part->DataUnits; i++)
811     	printk(KERN_DEBUG "ftl_cs:   unit %d: %d phys, %d free, "
812     	       "%d deleted\n", i,
813     	       part->EUNInfo[i].Offset >> part->header.EraseUnitSize,
814     	       part->EUNInfo[i].Free, part->EUNInfo[i].Deleted);
815     }
816     #endif
817     
818     static u_int32_t find_free(partition_t *part)
819     {
820         u_int16_t stop, eun;
821         u_int32_t blk;
822         size_t retlen;
823         int ret;
824         
825         /* Find an erase unit with some free space */
826         stop = (part->bam_index == 0xffff) ? 0 : part->bam_index;
827         eun = stop;
828         do {
829     	if (part->EUNInfo[eun].Free != 0) break;
830     	/* Wrap around at end of table */
831     	if (++eun == part->DataUnits) eun = 0;
832         } while (eun != stop);
833     
834         if (part->EUNInfo[eun].Free == 0)
835     	return 0;
836         
837         /* Is this unit's BAM cached? */
838         if (eun != part->bam_index) {
839     	/* Invalidate cache */
840     	part->bam_index = 0xffff;
841     
842     	ret = part->mtd->read(part->mtd, 
843     		       part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
844     		       part->BlocksPerUnit * sizeof(u_int32_t),
845     		       &retlen, (u_char *) (part->bam_cache));
846     	
847     	if (ret) {
848     	    printk(KERN_WARNING"ftl: Error reading BAM in find_free\n");
849     	    return 0;
850     	}
851     	part->bam_index = eun;
852         }
853     
854         /* Find a free block */
855         for (blk = 0; blk < part->BlocksPerUnit; blk++)
856     	if (BLOCK_FREE(le32_to_cpu(part->bam_cache[blk]))) break;
857         if (blk == part->BlocksPerUnit) {
858     #ifdef PSYCHO_DEBUG
859     	static int ne = 0;
860     	if (++ne == 1)
861     	    dump_lists(part);
862     #endif
863     	printk(KERN_NOTICE "ftl_cs: bad free list!\n");
864     	return 0;
865         }
866         DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);
867         return blk;
868         
869     } /* find_free */
870     
871     /*======================================================================
872     
873         This gets a memory handle for the region corresponding to the
874         minor device number.
875         
876     ======================================================================*/
877     
878     static int ftl_open(struct inode *inode, struct file *file)
879     {
880         int minor = MINOR(inode->i_rdev);
881         partition_t *partition;
882     
883         if (minor>>4 >= MAX_MTD_DEVICES)
884     	return -ENODEV;
885     
886         partition = myparts[minor>>4];
887     
888         if (!partition)
889     	return -ENODEV;
890     
891         if (partition->state != FTL_FORMATTED)
892     	return -ENXIO;
893         
894         if (ftl_gendisk.part[minor].nr_sects == 0)
895     	return -ENXIO;
896     
897         MOD_INC_USE_COUNT;
898     
899         if (!get_mtd_device(partition->mtd, -1)) {
900     	    MOD_DEC_USE_COUNT;
901     	    return /* -E'SBUGGEREDOFF */ -ENXIO;
902         }
903         
904         if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) {
905     	    put_mtd_device(partition->mtd);
906     	    MOD_DEC_USE_COUNT;
907                 return -EROFS;
908         }
909         
910         DEBUG(0, "ftl_cs: ftl_open(%d)\n", minor);
911     
912         atomic_inc(&partition->open);
913     
914         return 0;
915     }
916     
917     /*====================================================================*/
918     
919     static release_t ftl_close(struct inode *inode, struct file *file)
920     {
921         int minor = MINOR(inode->i_rdev);
922         partition_t *part = myparts[minor >> 4];
923         int i;
924         
925         DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor);
926     
927         /* Flush all writes */
928         invalidate_device(inode->i_rdev, 1);
929     
930         /* Wait for any pending erase operations to complete */
931         if (part->mtd->sync)
932     	    part->mtd->sync(part->mtd);
933         
934         for (i = 0; i < part->header.NumTransferUnits; i++) {
935     	if (part->XferInfo[i].state == XFER_ERASED)
936     	    prepare_xfer(part, i);
937         }
938     
939         atomic_dec(&part->open);
940     
941         put_mtd_device(part->mtd);
942         MOD_DEC_USE_COUNT;
943         release_return(0);
944     } /* ftl_close */
945     
946     
947     /*======================================================================
948     
949         Read a series of sectors from an FTL partition.
950         
951     ======================================================================*/
952     
953     static int ftl_read(partition_t *part, caddr_t buffer,
954     		    u_long sector, u_long nblocks)
955     {
956         u_int32_t log_addr, bsize;
957         u_long i;
958         int ret;
959         size_t offset, retlen;
960         
961         DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
962     	  part, sector, nblocks);
963         if (!(part->state & FTL_FORMATTED)) {
964     	printk(KERN_NOTICE "ftl_cs: bad partition\n");
965     	return -EIO;
966         }
967         bsize = 1 << part->header.EraseUnitSize;
968     
969         for (i = 0; i < nblocks; i++) {
970     	if (((sector+i) * SECTOR_SIZE) >= le32_to_cpu(part->header.FormattedSize)) {
971     	    printk(KERN_NOTICE "ftl_cs: bad read offset\n");
972     	    return -EIO;
973     	}
974     	log_addr = part->VirtualBlockMap[sector+i];
975     	if (log_addr == 0xffffffff)
976     	    memset(buffer, 0, SECTOR_SIZE);
977     	else {
978     	    offset = (part->EUNInfo[log_addr / bsize].Offset
979     			  + (log_addr % bsize));
980     	    ret = part->mtd->read(part->mtd, offset, SECTOR_SIZE,
981     			   &retlen, (u_char *) buffer);
982     
983     	    if (ret) {
984     		printk(KERN_WARNING "Error reading MTD device in ftl_read()\n");
985     		return ret;
986     	    }
987     	}
988     	buffer += SECTOR_SIZE;
989         }
990         return 0;
991     } /* ftl_read */
992     
993     /*======================================================================
994     
995         Write a series of sectors to an FTL partition
996         
997     ======================================================================*/
998     
999     static int set_bam_entry(partition_t *part, u_int32_t log_addr,
1000     			 u_int32_t virt_addr)
1001     {
1002         u_int32_t bsize, blk, le_virt_addr;
1003     #ifdef PSYCHO_DEBUG
1004         u_int32_t old_addr;
1005     #endif
1006         u_int16_t eun;
1007         int ret;
1008         size_t retlen, offset;
1009     
1010         DEBUG(2, "ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
1011     	  part, log_addr, virt_addr);
1012         bsize = 1 << part->header.EraseUnitSize;
1013         eun = log_addr / bsize;
1014         blk = (log_addr % bsize) / SECTOR_SIZE;
1015         offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) +
1016     		  le32_to_cpu(part->header.BAMOffset));
1017         
1018     #ifdef PSYCHO_DEBUG
1019         ret = part->mtd->read(part->mtd, offset, sizeof(u_int32_t),
1020                             &retlen, (u_char *)&old_addr);
1021         if (ret) {
1022     	printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret);
1023     	return ret;
1024         }
1025         old_addr = le32_to_cpu(old_addr);
1026     
1027         if (((virt_addr == 0xfffffffe) && !BLOCK_FREE(old_addr)) ||
1028     	((virt_addr == 0) && (BLOCK_TYPE(old_addr) != BLOCK_DATA)) ||
1029     	(!BLOCK_DELETED(virt_addr) && (old_addr != 0xfffffffe))) {
1030     	static int ne = 0;
1031     	if (++ne < 5) {
1032     	    printk(KERN_NOTICE "ftl_cs: set_bam_entry() inconsistency!\n");
1033     	    printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, old = 0x%x"
1034     		   ", new = 0x%x\n", log_addr, old_addr, virt_addr);
1035     	}
1036     	return -EIO;
1037         }
1038     #endif
1039         le_virt_addr = cpu_to_le32(virt_addr);
1040         if (part->bam_index == eun) {
1041     #ifdef PSYCHO_DEBUG
1042     	if (le32_to_cpu(part->bam_cache[blk]) != old_addr) {
1043     	    static int ne = 0;
1044     	    if (++ne < 5) {
1045     		printk(KERN_NOTICE "ftl_cs: set_bam_entry() "
1046     		       "inconsistency!\n");
1047     		printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, cache"
1048     		       " = 0x%x\n",
1049     		       le32_to_cpu(part->bam_cache[blk]), old_addr);
1050     	    }
1051     	    return -EIO;
1052     	}
1053     #endif
1054     	part->bam_cache[blk] = le_virt_addr;
1055         }
1056         ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t),
1057                                 &retlen, (u_char *)&le_virt_addr);
1058     
1059         if (ret) {
1060     	printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n");
1061     	printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, new = 0x%x\n",
1062     	       log_addr, virt_addr);
1063         }
1064         return ret;
1065     } /* set_bam_entry */
1066     
1067     static int ftl_write(partition_t *part, caddr_t buffer,
1068     		     u_long sector, u_long nblocks)
1069     {
1070         u_int32_t bsize, log_addr, virt_addr, old_addr, blk;
1071         u_long i;
1072         int ret;
1073         size_t retlen, offset;
1074     
1075         DEBUG(2, "ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
1076     	  part, sector, nblocks);
1077         if (!(part->state & FTL_FORMATTED)) {
1078     	printk(KERN_NOTICE "ftl_cs: bad partition\n");
1079     	return -EIO;
1080         }
1081         /* See if we need to reclaim space, before we start */
1082         while (part->FreeTotal < nblocks) {
1083     	ret = reclaim_block(part);
1084     	if (ret)
1085     	    return ret;
1086         }
1087         
1088         bsize = 1 << part->header.EraseUnitSize;
1089     
1090         virt_addr = sector * SECTOR_SIZE | BLOCK_DATA;
1091         for (i = 0; i < nblocks; i++) {
1092     	if (virt_addr >= le32_to_cpu(part->header.FormattedSize)) {
1093     	    printk(KERN_NOTICE "ftl_cs: bad write offset\n");
1094     	    return -EIO;
1095     	}
1096     
1097     	/* Grab a free block */
1098     	blk = find_free(part);
1099     	if (blk == 0) {
1100     	    static int ne = 0;
1101     	    if (++ne < 5)
1102     		printk(KERN_NOTICE "ftl_cs: internal error: "
1103     		       "no free blocks!\n");
1104     	    return -ENOSPC;
1105     	}
1106     
1107     	/* Tag the BAM entry, and write the new block */
1108     	log_addr = part->bam_index * bsize + blk * SECTOR_SIZE;
1109     	part->EUNInfo[part->bam_index].Free--;
1110     	part->FreeTotal--;
1111     	if (set_bam_entry(part, log_addr, 0xfffffffe)) 
1112     	    return -EIO;
1113     	part->EUNInfo[part->bam_index].Deleted++;
1114     	offset = (part->EUNInfo[part->bam_index].Offset +
1115     		      blk * SECTOR_SIZE);
1116     	ret = part->mtd->write(part->mtd, offset, SECTOR_SIZE, &retlen, 
1117                                          buffer);
1118     
1119     	if (ret) {
1120     	    printk(KERN_NOTICE "ftl_cs: block write failed!\n");
1121     	    printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, virt_addr"
1122     		   " = 0x%x, Offset = 0x%x\n", log_addr, virt_addr,
1123     		   offset);
1124     	    return -EIO;
1125     	}
1126     	
1127     	/* Only delete the old entry when the new entry is ready */
1128     	old_addr = part->VirtualBlockMap[sector+i];
1129     	if (old_addr != 0xffffffff) {
1130     	    part->VirtualBlockMap[sector+i] = 0xffffffff;
1131     	    part->EUNInfo[old_addr/bsize].Deleted++;
1132     	    if (set_bam_entry(part, old_addr, 0))
1133     		return -EIO;
1134     	}
1135     
1136     	/* Finally, set up the new pointers */
1137     	if (set_bam_entry(part, log_addr, virt_addr))
1138     	    return -EIO;
1139     	part->VirtualBlockMap[sector+i] = log_addr;
1140     	part->EUNInfo[part->bam_index].Deleted--;
1141     	
1142     	buffer += SECTOR_SIZE;
1143     	virt_addr += SECTOR_SIZE;
1144         }
1145         return 0;
1146     } /* ftl_write */
1147     
1148     /*======================================================================
1149     
1150         IOCTL calls for getting device parameters.
1151     
1152     ======================================================================*/
1153     
1154     static int ftl_ioctl(struct inode *inode, struct file *file,
1155     		     u_int cmd, u_long arg)
1156     {
1157         struct hd_geometry *geo = (struct hd_geometry *)arg;
1158         int ret = 0, minor = MINOR(inode->i_rdev);
1159         partition_t *part= myparts[minor >> 4];
1160         u_long sect;
1161     
1162         if (!part)
1163     	return -ENODEV; /* How? */
1164     
1165         switch (cmd) {
1166         case HDIO_GETGEO:
1167     	ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo));
1168     	if (ret) return ret;
1169     	/* Sort of arbitrary: round size down to 4K boundary */
1170     	sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
1171     	put_user(1, (char *)&geo->heads);
1172     	put_user(8, (char *)&geo->sectors);
1173     	put_user((sect>>3), (short *)&geo->cylinders);
1174     	put_user(ftl_hd[minor].start_sect, (u_long *)&geo->start);
1175     	break;
1176         case BLKGETSIZE:
1177     	ret = put_user(ftl_hd[minor].nr_sects, (long *)arg);
1178     	break;
1179         case BLKGETSIZE64:
1180     	ret = put_user((u64)ftl_hd[minor].nr_sects << 9, (u64 *)arg);
1181     	break;
1182         case BLKRRPART:
1183     	ret = ftl_reread_partitions(minor);
1184     	break;
1185     #if (LINUX_VERSION_CODE < 0x20303)
1186         case BLKFLSBUF:
1187     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
1188     	if (!capable(CAP_SYS_ADMIN)) return -EACCES;
1189     #endif
1190     	fsync_dev(inode->i_rdev);
1191     	invalidate_buffers(inode->i_rdev);
1192     	break;
1193         RO_IOCTLS(inode->i_rdev, arg);
1194     #else
1195         case BLKROSET:
1196         case BLKROGET:
1197         case BLKFLSBUF:
1198     	ret = blk_ioctl(inode->i_rdev, cmd, arg);
1199     	break;
1200     #endif
1201         default:
1202     	ret = -EINVAL;
1203         }
1204     
1205         return ret;
1206     } /* ftl_ioctl */
1207     
1208     /*======================================================================
1209     
1210         Handler for block device requests
1211     
1212     ======================================================================*/
1213     
1214     static int ftl_reread_partitions(int minor)
1215     {
1216         partition_t *part = myparts[minor >> 4];
1217         int i, whole;
1218     
1219         DEBUG(0, "ftl_cs: ftl_reread_partition(%d)\n", minor);
1220         if ((atomic_read(&part->open) > 1)) {
1221     	    return -EBUSY;
1222         }
1223         whole = minor & ~(MAX_PART-1);
1224     
1225         i = MAX_PART - 1;
1226         while (i-- > 0) {
1227     	if (ftl_hd[whole+i].nr_sects > 0) {
1228     	    kdev_t rdev = MKDEV(FTL_MAJOR, whole+i);
1229     
1230     	    invalidate_device(rdev, 1);
1231     	}
1232     	ftl_hd[whole+i].start_sect = 0;
1233     	ftl_hd[whole+i].nr_sects = 0;
1234         }
1235     
1236         scan_header(part);
1237     
1238         register_disk(&ftl_gendisk, whole >> PART_BITS, MAX_PART,
1239     		  &ftl_blk_fops, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
1240     
1241     #ifdef PCMCIA_DEBUG
1242         for (i = 0; i < MAX_PART; i++) {
1243     	if (ftl_hd[whole+i].nr_sects > 0)
1244     	    printk(KERN_INFO "  %d: start %ld size %ld\n", i,
1245     		   ftl_hd[whole+i].start_sect,
1246     		   ftl_hd[whole+i].nr_sects);
1247         }
1248     #endif
1249         return 0;
1250     }
1251     
1252     /*======================================================================
1253     
1254         Handler for block device requests
1255     
1256     ======================================================================*/
1257     
1258     static void do_ftl_request(request_arg_t)
1259     {
1260         int ret, minor;
1261         partition_t *part;
1262     
1263         do {
1264           //	    sti();
1265     	INIT_REQUEST;
1266     
1267     	minor = MINOR(CURRENT->rq_dev);
1268     	
1269     	part = myparts[minor >> 4];
1270     	if (part) {
1271     	  ret = 0;
1272     	  
1273     	  switch (CURRENT->cmd) {
1274     	  case READ:
1275     	    ret = ftl_read(part, CURRENT->buffer,
1276     			   CURRENT->sector+ftl_hd[minor].start_sect,
1277     			   CURRENT->current_nr_sectors);
1278     	    if (ret) printk("ftl_read returned %d\n", ret);
1279     	    break;
1280     	    
1281     	  case WRITE:
1282     	    ret = ftl_write(part, CURRENT->buffer,
1283     			    CURRENT->sector+ftl_hd[minor].start_sect,
1284     			    CURRENT->current_nr_sectors);
1285     	    if (ret) printk("ftl_write returned %d\n", ret);
1286     	    break;
1287     	    
1288     	  default:
1289     	    panic("ftl_cs: unknown block command!\n");
1290     	    
1291     	  }
1292     	} else {
1293     	  ret = 1;
1294     	  printk("NULL part in ftl_request\n");
1295     	}
1296     	 
1297     	if (!ret) {
1298     	  CURRENT->sector += CURRENT->current_nr_sectors;
1299     	}
1300     	
1301     	end_request((ret == 0) ? 1 : 0);
1302         } while (1);
1303     } /* do_ftl_request */
1304     
1305     /*====================================================================*/
1306     
1307     void ftl_freepart(partition_t *part)
1308     {
1309         if (part->VirtualBlockMap) {
1310     	vfree(part->VirtualBlockMap);
1311     	part->VirtualBlockMap = NULL;
1312         }
1313         if (part->VirtualPageMap) {
1314     	kfree(part->VirtualPageMap);
1315     	part->VirtualPageMap = NULL;
1316         }
1317         if (part->EUNInfo) {
1318     	kfree(part->EUNInfo);
1319     	part->EUNInfo = NULL;
1320         }
1321         if (part->XferInfo) {
1322     	kfree(part->XferInfo);
1323     	part->XferInfo = NULL;
1324         }
1325         if (part->bam_cache) {
1326     	kfree(part->bam_cache);
1327     	part->bam_cache = NULL;
1328         }
1329         
1330     } /* ftl_freepart */
1331     
1332     static void ftl_notify_add(struct mtd_info *mtd)
1333     {
1334     	partition_t *partition;
1335     	int device;
1336     
1337     	for (device=0; device < MAX_MTD_DEVICES && myparts[device]; device++)
1338     		;
1339     
1340     	if (device == MAX_MTD_DEVICES) {
1341     		printk(KERN_NOTICE "Maximum number of FTL partitions reached\n"
1342     		       "Not scanning <%s>\n", mtd->name);
1343     		return;
1344     	}
1345     
1346     	partition = kmalloc(sizeof(partition_t), GFP_KERNEL);
1347     		
1348     	if (!partition) {
1349     		printk(KERN_WARNING "No memory to scan for FTL on %s\n",
1350     		       mtd->name);
1351     		return;
1352     	}    
1353     
1354     	memset(partition, 0, sizeof(partition_t));
1355     
1356     	partition->mtd = mtd;
1357     
1358     	if ((scan_header(partition) == 0) && 
1359     	    (build_maps(partition) == 0)) {
1360     		
1361     		partition->state = FTL_FORMATTED;
1362     		atomic_set(&partition->open, 0);
1363     		myparts[device] = partition;
1364     		ftl_reread_partitions(device << 4);
1365     #ifdef PCMCIA_DEBUG
1366     		printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n",
1367     		       le32_to_cpu(partition->header.FormattedSize) >> 10);
1368     #endif
1369     	} else
1370     		kfree(partition);
1371     }
1372     
1373     static void ftl_notify_remove(struct mtd_info *mtd)
1374     {
1375             int i,j;
1376     
1377     	/* Q: What happens if you try to remove a device which has
1378     	 *    a currently-open FTL partition on it?
1379     	 *
1380     	 * A: You don't. The ftl_open routine is responsible for
1381     	 *    increasing the use count of the driver module which
1382     	 *    it uses.
1383     	 */
1384     
1385     	/* That's the theory, anyway :) */
1386     
1387     	for (i=0; i< MAX_MTD_DEVICES; i++)
1388     		if (myparts[i] && myparts[i]->mtd == mtd) {
1389     
1390     			if (myparts[i]->state == FTL_FORMATTED)
1391     				ftl_freepart(myparts[i]);
1392     			
1393     			myparts[i]->state = 0;
1394     			for (j=0; j<16; j++) {
1395     				ftl_gendisk.part[j].nr_sects=0;
1396     				ftl_gendisk.part[j].start_sect=0;
1397     			}
1398     			kfree(myparts[i]);
1399     			myparts[i] = NULL;
1400     		}
1401     }
1402     
1403     #if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
1404     #define init_ftl init_module
1405     #define cleanup_ftl cleanup_module
1406     #endif
1407     
1408     mod_init_t init_ftl(void)
1409     {
1410         int i;
1411     
1412         memset(myparts, 0, sizeof(myparts));
1413         
1414         DEBUG(0, "$Id: ftl.c,v 1.35 2001/06/09 00:40:17 dwmw2 Exp $\n");
1415         
1416         if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
1417     	printk(KERN_NOTICE "ftl_cs: unable to grab major "
1418     	       "device number!\n");
1419     	return -EAGAIN;
1420         }
1421         
1422         for (i = 0; i < MINOR_NR(MAX_DEV, 0, 0); i++)
1423     	ftl_blocksizes[i] = 1024;
1424         for (i = 0; i < MAX_DEV*MAX_PART; i++) {
1425     	ftl_hd[i].nr_sects = 0;
1426     	ftl_hd[i].start_sect = 0;
1427         }
1428         blksize_size[FTL_MAJOR] = ftl_blocksizes;
1429         ftl_gendisk.major = FTL_MAJOR;
1430         blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request);
1431         add_gendisk(&ftl_gendisk);
1432         
1433         register_mtd_user(&ftl_notifier);
1434         
1435         return 0;
1436     }
1437     
1438     mod_exit_t cleanup_ftl(void)
1439     {
1440         unregister_mtd_user(&ftl_notifier);
1441     
1442         unregister_blkdev(FTL_MAJOR, "ftl");
1443         blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR));
1444         blksize_size[FTL_MAJOR] = NULL;
1445     
1446         del_gendisk(&ftl_gendisk);
1447     }
1448     
1449     module_init(init_ftl);
1450     module_exit(cleanup_ftl);
1451