Linux Audio

Check our new training course

Loading...
   1/* This version ported to the Linux-MTD system by dwmw2@infradead.org
   2 *
   3 * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   4 * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
   5 *
   6 * Based on:
   7 */
   8/*======================================================================
   9
  10    A Flash Translation Layer memory card driver
  11
  12    This driver implements a disk-like block device driver with an
  13    apparent block size of 512 bytes for flash memory cards.
  14
  15    ftl_cs.c 1.62 2000/02/01 00:59:04
  16
  17    The contents of this file are subject to the Mozilla Public
  18    License Version 1.1 (the "License"); you may not use this file
  19    except in compliance with the License. You may obtain a copy of
  20    the License at http://www.mozilla.org/MPL/
  21
  22    Software distributed under the License is distributed on an "AS
  23    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  24    implied. See the License for the specific language governing
  25    rights and limitations under the License.
  26
  27    The initial developer of the original code is David A. Hinds
  28    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  29    are Copyright © 1999 David A. Hinds.  All Rights Reserved.
  30
  31    Alternatively, the contents of this file may be used under the
  32    terms of the GNU General Public License version 2 (the "GPL"), in
  33    which case the provisions of the GPL are applicable instead of the
  34    above.  If you wish to allow the use of your version of this file
  35    only under the terms of the GPL and not to allow others to use
  36    your version of this file under the MPL, indicate your decision
  37    by deleting the provisions above and replace them with the notice
  38    and other provisions required by the GPL.  If you do not delete
  39    the provisions above, a recipient may use your version of this
  40    file under either the MPL or the GPL.
  41
  42    LEGAL NOTE: The FTL format is patented by M-Systems.  They have
  43    granted a license for its use with PCMCIA devices:
  44
  45     "M-Systems grants a royalty-free, non-exclusive license under
  46      any presently existing M-Systems intellectual property rights
  47      necessary for the design and development of FTL-compatible
  48      drivers, file systems and utilities using the data formats with
  49      PCMCIA PC Cards as described in the PCMCIA Flash Translation
  50      Layer (FTL) Specification."
  51
  52    Use of the FTL format for non-PCMCIA applications may be an
  53    infringement of these patents.  For additional information,
  54    contact M-Systems directly. M-Systems since acquired by Sandisk. 
  55
  56======================================================================*/
  57#include <linux/mtd/blktrans.h>
  58#include <linux/module.h>
  59#include <linux/mtd/mtd.h>
  60/*#define PSYCHO_DEBUG */
  61
  62#include <linux/kernel.h>
  63#include <linux/ptrace.h>
  64#include <linux/slab.h>
  65#include <linux/string.h>
  66#include <linux/timer.h>
  67#include <linux/major.h>
  68#include <linux/fs.h>
  69#include <linux/init.h>
  70#include <linux/hdreg.h>
  71#include <linux/vmalloc.h>
  72#include <linux/blkpg.h>
  73#include <asm/uaccess.h>
  74
  75#include <linux/mtd/ftl.h>
  76
  77/*====================================================================*/
  78
  79/* Parameters that can be set with 'insmod' */
  80static int shuffle_freq = 50;
  81module_param(shuffle_freq, int, 0);
  82
  83/*====================================================================*/
  84
  85/* Major device # for FTL device */
  86#ifndef FTL_MAJOR
  87#define FTL_MAJOR	44
  88#endif
  89
  90
  91/*====================================================================*/
  92
  93/* Maximum number of separate memory devices we'll allow */
  94#define MAX_DEV		4
  95
  96/* Maximum number of regions per device */
  97#define MAX_REGION	4
  98
  99/* Maximum number of partitions in an FTL region */
 100#define PART_BITS	4
 101
 102/* Maximum number of outstanding erase requests per socket */
 103#define MAX_ERASE	8
 104
 105/* Sector size -- shouldn't need to change */
 106#define SECTOR_SIZE	512
 107
 108
 109/* Each memory region corresponds to a minor device */
 110typedef struct partition_t {
 111    struct mtd_blktrans_dev mbd;
 112    uint32_t		state;
 113    uint32_t		*VirtualBlockMap;
 114    uint32_t		*VirtualPageMap;
 115    uint32_t		FreeTotal;
 116    struct eun_info_t {
 117	uint32_t		Offset;
 118	uint32_t		EraseCount;
 119	uint32_t		Free;
 120	uint32_t		Deleted;
 121    } *EUNInfo;
 122    struct xfer_info_t {
 123	uint32_t		Offset;
 124	uint32_t		EraseCount;
 125	uint16_t		state;
 126    } *XferInfo;
 127    uint16_t		bam_index;
 128    uint32_t		*bam_cache;
 129    uint16_t		DataUnits;
 130    uint32_t		BlocksPerUnit;
 131    erase_unit_header_t	header;
 132} partition_t;
 133
 134/* Partition state flags */
 135#define FTL_FORMATTED	0x01
 136
 137/* Transfer unit states */
 138#define XFER_UNKNOWN	0x00
 139#define XFER_ERASING	0x01
 140#define XFER_ERASED	0x02
 141#define XFER_PREPARED	0x03
 142#define XFER_FAILED	0x04
 143
 144/*====================================================================*/
 145
 146
 147static void ftl_erase_callback(struct erase_info *done);
 148
 149
 150/*======================================================================
 151
 152    Scan_header() checks to see if a memory region contains an FTL
 153    partition.  build_maps() reads all the erase unit headers, builds
 154    the erase unit map, and then builds the virtual page map.
 155
 156======================================================================*/
 157
 158static int scan_header(partition_t *part)
 159{
 160    erase_unit_header_t header;
 161    loff_t offset, max_offset;
 162    size_t ret;
 163    int err;
 164    part->header.FormattedSize = 0;
 165    max_offset = (0x100000<part->mbd.mtd->size)?0x100000:part->mbd.mtd->size;
 166    /* Search first megabyte for a valid FTL header */
 167    for (offset = 0;
 168	 (offset + sizeof(header)) < max_offset;
 169	 offset += part->mbd.mtd->erasesize ? : 0x2000) {
 170
 171	err = mtd_read(part->mbd.mtd, offset, sizeof(header), &ret,
 172                       (unsigned char *)&header);
 173
 174	if (err)
 175	    return err;
 176
 177	if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
 178    }
 179
 180    if (offset == max_offset) {
 181	printk(KERN_NOTICE "ftl_cs: FTL header not found.\n");
 182	return -ENOENT;
 183    }
 184    if (header.BlockSize != 9 ||
 185	(header.EraseUnitSize < 10) || (header.EraseUnitSize > 31) ||
 186	(header.NumTransferUnits >= le16_to_cpu(header.NumEraseUnits))) {
 187	printk(KERN_NOTICE "ftl_cs: FTL header corrupt!\n");
 188	return -1;
 189    }
 190    if ((1 << header.EraseUnitSize) != part->mbd.mtd->erasesize) {
 191	printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %x\n",
 192	       1 << header.EraseUnitSize,part->mbd.mtd->erasesize);
 193	return -1;
 194    }
 195    part->header = header;
 196    return 0;
 197}
 198
 199static int build_maps(partition_t *part)
 200{
 201    erase_unit_header_t header;
 202    uint16_t xvalid, xtrans, i;
 203    unsigned blocks, j;
 204    int hdr_ok, ret = -1;
 205    ssize_t retval;
 206    loff_t offset;
 207
 208    /* Set up erase unit maps */
 209    part->DataUnits = le16_to_cpu(part->header.NumEraseUnits) -
 210	part->header.NumTransferUnits;
 211    part->EUNInfo = kmalloc(part->DataUnits * sizeof(struct eun_info_t),
 212			    GFP_KERNEL);
 213    if (!part->EUNInfo)
 214	    goto out;
 215    for (i = 0; i < part->DataUnits; i++)
 216	part->EUNInfo[i].Offset = 0xffffffff;
 217    part->XferInfo =
 218	kmalloc(part->header.NumTransferUnits * sizeof(struct xfer_info_t),
 219		GFP_KERNEL);
 220    if (!part->XferInfo)
 221	    goto out_EUNInfo;
 222
 223    xvalid = xtrans = 0;
 224    for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) {
 225	offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN))
 226		      << part->header.EraseUnitSize);
 227	ret = mtd_read(part->mbd.mtd, offset, sizeof(header), &retval,
 228                       (unsigned char *)&header);
 229
 230	if (ret)
 231	    goto out_XferInfo;
 232
 233	ret = -1;
 234	/* Is this a transfer partition? */
 235	hdr_ok = (strcmp(header.DataOrgTuple+3, "FTL100") == 0);
 236	if (hdr_ok && (le16_to_cpu(header.LogicalEUN) < part->DataUnits) &&
 237	    (part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset == 0xffffffff)) {
 238	    part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset = offset;
 239	    part->EUNInfo[le16_to_cpu(header.LogicalEUN)].EraseCount =
 240		le32_to_cpu(header.EraseCount);
 241	    xvalid++;
 242	} else {
 243	    if (xtrans == part->header.NumTransferUnits) {
 244		printk(KERN_NOTICE "ftl_cs: format error: too many "
 245		       "transfer units!\n");
 246		goto out_XferInfo;
 247	    }
 248	    if (hdr_ok && (le16_to_cpu(header.LogicalEUN) == 0xffff)) {
 249		part->XferInfo[xtrans].state = XFER_PREPARED;
 250		part->XferInfo[xtrans].EraseCount = le32_to_cpu(header.EraseCount);
 251	    } else {
 252		part->XferInfo[xtrans].state = XFER_UNKNOWN;
 253		/* Pick anything reasonable for the erase count */
 254		part->XferInfo[xtrans].EraseCount =
 255		    le32_to_cpu(part->header.EraseCount);
 256	    }
 257	    part->XferInfo[xtrans].Offset = offset;
 258	    xtrans++;
 259	}
 260    }
 261    /* Check for format trouble */
 262    header = part->header;
 263    if ((xtrans != header.NumTransferUnits) ||
 264	(xvalid+xtrans != le16_to_cpu(header.NumEraseUnits))) {
 265	printk(KERN_NOTICE "ftl_cs: format error: erase units "
 266	       "don't add up!\n");
 267	goto out_XferInfo;
 268    }
 269
 270    /* Set up virtual page map */
 271    blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
 272    part->VirtualBlockMap = vmalloc(blocks * sizeof(uint32_t));
 273    if (!part->VirtualBlockMap)
 274	    goto out_XferInfo;
 275
 276    memset(part->VirtualBlockMap, 0xff, blocks * sizeof(uint32_t));
 277    part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize;
 278
 279    part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(uint32_t),
 280			      GFP_KERNEL);
 281    if (!part->bam_cache)
 282	    goto out_VirtualBlockMap;
 283
 284    part->bam_index = 0xffff;
 285    part->FreeTotal = 0;
 286
 287    for (i = 0; i < part->DataUnits; i++) {
 288	part->EUNInfo[i].Free = 0;
 289	part->EUNInfo[i].Deleted = 0;
 290	offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
 291
 292	ret = mtd_read(part->mbd.mtd, offset,
 293                       part->BlocksPerUnit * sizeof(uint32_t), &retval,
 294                       (unsigned char *)part->bam_cache);
 295
 296	if (ret)
 297		goto out_bam_cache;
 298
 299	for (j = 0; j < part->BlocksPerUnit; j++) {
 300	    if (BLOCK_FREE(le32_to_cpu(part->bam_cache[j]))) {
 301		part->EUNInfo[i].Free++;
 302		part->FreeTotal++;
 303	    } else if ((BLOCK_TYPE(le32_to_cpu(part->bam_cache[j])) == BLOCK_DATA) &&
 304		     (BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j])) < blocks))
 305		part->VirtualBlockMap[BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j]))] =
 306		    (i << header.EraseUnitSize) + (j << header.BlockSize);
 307	    else if (BLOCK_DELETED(le32_to_cpu(part->bam_cache[j])))
 308		part->EUNInfo[i].Deleted++;
 309	}
 310    }
 311
 312    ret = 0;
 313    goto out;
 314
 315out_bam_cache:
 316    kfree(part->bam_cache);
 317out_VirtualBlockMap:
 318    vfree(part->VirtualBlockMap);
 319out_XferInfo:
 320    kfree(part->XferInfo);
 321out_EUNInfo:
 322    kfree(part->EUNInfo);
 323out:
 324    return ret;
 325} /* build_maps */
 326
 327/*======================================================================
 328
 329    Erase_xfer() schedules an asynchronous erase operation for a
 330    transfer unit.
 331
 332======================================================================*/
 333
 334static int erase_xfer(partition_t *part,
 335		      uint16_t xfernum)
 336{
 337    int ret;
 338    struct xfer_info_t *xfer;
 339    struct erase_info *erase;
 340
 341    xfer = &part->XferInfo[xfernum];
 342    pr_debug("ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
 343    xfer->state = XFER_ERASING;
 344
 345    /* Is there a free erase slot? Always in MTD. */
 346
 347
 348    erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL);
 349    if (!erase)
 350            return -ENOMEM;
 351
 352    erase->mtd = part->mbd.mtd;
 353    erase->callback = ftl_erase_callback;
 354    erase->addr = xfer->Offset;
 355    erase->len = 1 << part->header.EraseUnitSize;
 356    erase->priv = (u_long)part;
 357
 358    ret = mtd_erase(part->mbd.mtd, erase);
 359
 360    if (!ret)
 361	    xfer->EraseCount++;
 362    else
 363	    kfree(erase);
 364
 365    return ret;
 366} /* erase_xfer */
 367
 368/*======================================================================
 369
 370    Prepare_xfer() takes a freshly erased transfer unit and gives
 371    it an appropriate header.
 372
 373======================================================================*/
 374
 375static void ftl_erase_callback(struct erase_info *erase)
 376{
 377    partition_t *part;
 378    struct xfer_info_t *xfer;
 379    int i;
 380
 381    /* Look up the transfer unit */
 382    part = (partition_t *)(erase->priv);
 383
 384    for (i = 0; i < part->header.NumTransferUnits; i++)
 385	if (part->XferInfo[i].Offset == erase->addr) break;
 386
 387    if (i == part->header.NumTransferUnits) {
 388	printk(KERN_NOTICE "ftl_cs: internal error: "
 389	       "erase lookup failed!\n");
 390	return;
 391    }
 392
 393    xfer = &part->XferInfo[i];
 394    if (erase->state == MTD_ERASE_DONE)
 395	xfer->state = XFER_ERASED;
 396    else {
 397	xfer->state = XFER_FAILED;
 398	printk(KERN_NOTICE "ftl_cs: erase failed: state = %d\n",
 399	       erase->state);
 400    }
 401
 402    kfree(erase);
 403
 404} /* ftl_erase_callback */
 405
 406static int prepare_xfer(partition_t *part, int i)
 407{
 408    erase_unit_header_t header;
 409    struct xfer_info_t *xfer;
 410    int nbam, ret;
 411    uint32_t ctl;
 412    ssize_t retlen;
 413    loff_t offset;
 414
 415    xfer = &part->XferInfo[i];
 416    xfer->state = XFER_FAILED;
 417
 418    pr_debug("ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
 419
 420    /* Write the transfer unit header */
 421    header = part->header;
 422    header.LogicalEUN = cpu_to_le16(0xffff);
 423    header.EraseCount = cpu_to_le32(xfer->EraseCount);
 424
 425    ret = mtd_write(part->mbd.mtd, xfer->Offset, sizeof(header), &retlen,
 426                    (u_char *)&header);
 427
 428    if (ret) {
 429	return ret;
 430    }
 431
 432    /* Write the BAM stub */
 433    nbam = (part->BlocksPerUnit * sizeof(uint32_t) +
 434	    le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE;
 435
 436    offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset);
 437    ctl = cpu_to_le32(BLOCK_CONTROL);
 438
 439    for (i = 0; i < nbam; i++, offset += sizeof(uint32_t)) {
 440
 441	ret = mtd_write(part->mbd.mtd, offset, sizeof(uint32_t), &retlen,
 442                        (u_char *)&ctl);
 443
 444	if (ret)
 445	    return ret;
 446    }
 447    xfer->state = XFER_PREPARED;
 448    return 0;
 449
 450} /* prepare_xfer */
 451
 452/*======================================================================
 453
 454    Copy_erase_unit() takes a full erase block and a transfer unit,
 455    copies everything to the transfer unit, then swaps the block
 456    pointers.
 457
 458    All data blocks are copied to the corresponding blocks in the
 459    target unit, so the virtual block map does not need to be
 460    updated.
 461
 462======================================================================*/
 463
 464static int copy_erase_unit(partition_t *part, uint16_t srcunit,
 465			   uint16_t xferunit)
 466{
 467    u_char buf[SECTOR_SIZE];
 468    struct eun_info_t *eun;
 469    struct xfer_info_t *xfer;
 470    uint32_t src, dest, free, i;
 471    uint16_t unit;
 472    int ret;
 473    ssize_t retlen;
 474    loff_t offset;
 475    uint16_t srcunitswap = cpu_to_le16(srcunit);
 476
 477    eun = &part->EUNInfo[srcunit];
 478    xfer = &part->XferInfo[xferunit];
 479    pr_debug("ftl_cs: copying block 0x%x to 0x%x\n",
 480	  eun->Offset, xfer->Offset);
 481
 482
 483    /* Read current BAM */
 484    if (part->bam_index != srcunit) {
 485
 486	offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
 487
 488	ret = mtd_read(part->mbd.mtd, offset,
 489                       part->BlocksPerUnit * sizeof(uint32_t), &retlen,
 490                       (u_char *)(part->bam_cache));
 491
 492	/* mark the cache bad, in case we get an error later */
 493	part->bam_index = 0xffff;
 494
 495	if (ret) {
 496	    printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");
 497	    return ret;
 498	}
 499    }
 500
 501    /* Write the LogicalEUN for the transfer unit */
 502    xfer->state = XFER_UNKNOWN;
 503    offset = xfer->Offset + 20; /* Bad! */
 504    unit = cpu_to_le16(0x7fff);
 505
 506    ret = mtd_write(part->mbd.mtd, offset, sizeof(uint16_t), &retlen,
 507                    (u_char *)&unit);
 508
 509    if (ret) {
 510	printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n");
 511	return ret;
 512    }
 513
 514    /* Copy all data blocks from source unit to transfer unit */
 515    src = eun->Offset; dest = xfer->Offset;
 516
 517    free = 0;
 518    ret = 0;
 519    for (i = 0; i < part->BlocksPerUnit; i++) {
 520	switch (BLOCK_TYPE(le32_to_cpu(part->bam_cache[i]))) {
 521	case BLOCK_CONTROL:
 522	    /* This gets updated later */
 523	    break;
 524	case BLOCK_DATA:
 525	case BLOCK_REPLACEMENT:
 526	    ret = mtd_read(part->mbd.mtd, src, SECTOR_SIZE, &retlen,
 527                           (u_char *)buf);
 528	    if (ret) {
 529		printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n");
 530		return ret;
 531            }
 532
 533
 534	    ret = mtd_write(part->mbd.mtd, dest, SECTOR_SIZE, &retlen,
 535                            (u_char *)buf);
 536	    if (ret)  {
 537		printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n");
 538		return ret;
 539            }
 540
 541	    break;
 542	default:
 543	    /* All other blocks must be free */
 544	    part->bam_cache[i] = cpu_to_le32(0xffffffff);
 545	    free++;
 546	    break;
 547	}
 548	src += SECTOR_SIZE;
 549	dest += SECTOR_SIZE;
 550    }
 551
 552    /* Write the BAM to the transfer unit */
 553    ret = mtd_write(part->mbd.mtd,
 554                    xfer->Offset + le32_to_cpu(part->header.BAMOffset),
 555                    part->BlocksPerUnit * sizeof(int32_t),
 556                    &retlen,
 557                    (u_char *)part->bam_cache);
 558    if (ret) {
 559	printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n");
 560	return ret;
 561    }
 562
 563
 564    /* All clear? Then update the LogicalEUN again */
 565    ret = mtd_write(part->mbd.mtd, xfer->Offset + 20, sizeof(uint16_t),
 566                    &retlen, (u_char *)&srcunitswap);
 567
 568    if (ret) {
 569	printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n");
 570	return ret;
 571    }
 572
 573
 574    /* Update the maps and usage stats*/
 575    i = xfer->EraseCount;
 576    xfer->EraseCount = eun->EraseCount;
 577    eun->EraseCount = i;
 578    i = xfer->Offset;
 579    xfer->Offset = eun->Offset;
 580    eun->Offset = i;
 581    part->FreeTotal -= eun->Free;
 582    part->FreeTotal += free;
 583    eun->Free = free;
 584    eun->Deleted = 0;
 585
 586    /* Now, the cache should be valid for the new block */
 587    part->bam_index = srcunit;
 588
 589    return 0;
 590} /* copy_erase_unit */
 591
 592/*======================================================================
 593
 594    reclaim_block() picks a full erase unit and a transfer unit and
 595    then calls copy_erase_unit() to copy one to the other.  Then, it
 596    schedules an erase on the expired block.
 597
 598    What's a good way to decide which transfer unit and which erase
 599    unit to use?  Beats me.  My way is to always pick the transfer
 600    unit with the fewest erases, and usually pick the data unit with
 601    the most deleted blocks.  But with a small probability, pick the
 602    oldest data unit instead.  This means that we generally postpone
 603    the next reclamation as long as possible, but shuffle static
 604    stuff around a bit for wear leveling.
 605
 606======================================================================*/
 607
 608static int reclaim_block(partition_t *part)
 609{
 610    uint16_t i, eun, xfer;
 611    uint32_t best;
 612    int queued, ret;
 613
 614    pr_debug("ftl_cs: reclaiming space...\n");
 615    pr_debug("NumTransferUnits == %x\n", part->header.NumTransferUnits);
 616    /* Pick the least erased transfer unit */
 617    best = 0xffffffff; xfer = 0xffff;
 618    do {
 619	queued = 0;
 620	for (i = 0; i < part->header.NumTransferUnits; i++) {
 621	    int n=0;
 622	    if (part->XferInfo[i].state == XFER_UNKNOWN) {
 623		pr_debug("XferInfo[%d].state == XFER_UNKNOWN\n",i);
 624		n=1;
 625		erase_xfer(part, i);
 626	    }
 627	    if (part->XferInfo[i].state == XFER_ERASING) {
 628		pr_debug("XferInfo[%d].state == XFER_ERASING\n",i);
 629		n=1;
 630		queued = 1;
 631	    }
 632	    else if (part->XferInfo[i].state == XFER_ERASED) {
 633		pr_debug("XferInfo[%d].state == XFER_ERASED\n",i);
 634		n=1;
 635		prepare_xfer(part, i);
 636	    }
 637	    if (part->XferInfo[i].state == XFER_PREPARED) {
 638		pr_debug("XferInfo[%d].state == XFER_PREPARED\n",i);
 639		n=1;
 640		if (part->XferInfo[i].EraseCount <= best) {
 641		    best = part->XferInfo[i].EraseCount;
 642		    xfer = i;
 643		}
 644	    }
 645		if (!n)
 646		    pr_debug("XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
 647
 648	}
 649	if (xfer == 0xffff) {
 650	    if (queued) {
 651		pr_debug("ftl_cs: waiting for transfer "
 652		      "unit to be prepared...\n");
 653		mtd_sync(part->mbd.mtd);
 654	    } else {
 655		static int ne = 0;
 656		if (++ne < 5)
 657		    printk(KERN_NOTICE "ftl_cs: reclaim failed: no "
 658			   "suitable transfer units!\n");
 659		else
 660		    pr_debug("ftl_cs: reclaim failed: no "
 661			  "suitable transfer units!\n");
 662
 663		return -EIO;
 664	    }
 665	}
 666    } while (xfer == 0xffff);
 667
 668    eun = 0;
 669    if ((jiffies % shuffle_freq) == 0) {
 670	pr_debug("ftl_cs: recycling freshest block...\n");
 671	best = 0xffffffff;
 672	for (i = 0; i < part->DataUnits; i++)
 673	    if (part->EUNInfo[i].EraseCount <= best) {
 674		best = part->EUNInfo[i].EraseCount;
 675		eun = i;
 676	    }
 677    } else {
 678	best = 0;
 679	for (i = 0; i < part->DataUnits; i++)
 680	    if (part->EUNInfo[i].Deleted >= best) {
 681		best = part->EUNInfo[i].Deleted;
 682		eun = i;
 683	    }
 684	if (best == 0) {
 685	    static int ne = 0;
 686	    if (++ne < 5)
 687		printk(KERN_NOTICE "ftl_cs: reclaim failed: "
 688		       "no free blocks!\n");
 689	    else
 690		pr_debug("ftl_cs: reclaim failed: "
 691		       "no free blocks!\n");
 692
 693	    return -EIO;
 694	}
 695    }
 696    ret = copy_erase_unit(part, eun, xfer);
 697    if (!ret)
 698	erase_xfer(part, xfer);
 699    else
 700	printk(KERN_NOTICE "ftl_cs: copy_erase_unit failed!\n");
 701    return ret;
 702} /* reclaim_block */
 703
 704/*======================================================================
 705
 706    Find_free() searches for a free block.  If necessary, it updates
 707    the BAM cache for the erase unit containing the free block.  It
 708    returns the block index -- the erase unit is just the currently
 709    cached unit.  If there are no free blocks, it returns 0 -- this
 710    is never a valid data block because it contains the header.
 711
 712======================================================================*/
 713
 714#ifdef PSYCHO_DEBUG
 715static void dump_lists(partition_t *part)
 716{
 717    int i;
 718    printk(KERN_DEBUG "ftl_cs: Free total = %d\n", part->FreeTotal);
 719    for (i = 0; i < part->DataUnits; i++)
 720	printk(KERN_DEBUG "ftl_cs:   unit %d: %d phys, %d free, "
 721	       "%d deleted\n", i,
 722	       part->EUNInfo[i].Offset >> part->header.EraseUnitSize,
 723	       part->EUNInfo[i].Free, part->EUNInfo[i].Deleted);
 724}
 725#endif
 726
 727static uint32_t find_free(partition_t *part)
 728{
 729    uint16_t stop, eun;
 730    uint32_t blk;
 731    size_t retlen;
 732    int ret;
 733
 734    /* Find an erase unit with some free space */
 735    stop = (part->bam_index == 0xffff) ? 0 : part->bam_index;
 736    eun = stop;
 737    do {
 738	if (part->EUNInfo[eun].Free != 0) break;
 739	/* Wrap around at end of table */
 740	if (++eun == part->DataUnits) eun = 0;
 741    } while (eun != stop);
 742
 743    if (part->EUNInfo[eun].Free == 0)
 744	return 0;
 745
 746    /* Is this unit's BAM cached? */
 747    if (eun != part->bam_index) {
 748	/* Invalidate cache */
 749	part->bam_index = 0xffff;
 750
 751	ret = mtd_read(part->mbd.mtd,
 752                       part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
 753                       part->BlocksPerUnit * sizeof(uint32_t),
 754                       &retlen,
 755                       (u_char *)(part->bam_cache));
 756
 757	if (ret) {
 758	    printk(KERN_WARNING"ftl: Error reading BAM in find_free\n");
 759	    return 0;
 760	}
 761	part->bam_index = eun;
 762    }
 763
 764    /* Find a free block */
 765    for (blk = 0; blk < part->BlocksPerUnit; blk++)
 766	if (BLOCK_FREE(le32_to_cpu(part->bam_cache[blk]))) break;
 767    if (blk == part->BlocksPerUnit) {
 768#ifdef PSYCHO_DEBUG
 769	static int ne = 0;
 770	if (++ne == 1)
 771	    dump_lists(part);
 772#endif
 773	printk(KERN_NOTICE "ftl_cs: bad free list!\n");
 774	return 0;
 775    }
 776    pr_debug("ftl_cs: found free block at %d in %d\n", blk, eun);
 777    return blk;
 778
 779} /* find_free */
 780
 781
 782/*======================================================================
 783
 784    Read a series of sectors from an FTL partition.
 785
 786======================================================================*/
 787
 788static int ftl_read(partition_t *part, caddr_t buffer,
 789		    u_long sector, u_long nblocks)
 790{
 791    uint32_t log_addr, bsize;
 792    u_long i;
 793    int ret;
 794    size_t offset, retlen;
 795
 796    pr_debug("ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
 797	  part, sector, nblocks);
 798    if (!(part->state & FTL_FORMATTED)) {
 799	printk(KERN_NOTICE "ftl_cs: bad partition\n");
 800	return -EIO;
 801    }
 802    bsize = 1 << part->header.EraseUnitSize;
 803
 804    for (i = 0; i < nblocks; i++) {
 805	if (((sector+i) * SECTOR_SIZE) >= le32_to_cpu(part->header.FormattedSize)) {
 806	    printk(KERN_NOTICE "ftl_cs: bad read offset\n");
 807	    return -EIO;
 808	}
 809	log_addr = part->VirtualBlockMap[sector+i];
 810	if (log_addr == 0xffffffff)
 811	    memset(buffer, 0, SECTOR_SIZE);
 812	else {
 813	    offset = (part->EUNInfo[log_addr / bsize].Offset
 814			  + (log_addr % bsize));
 815	    ret = mtd_read(part->mbd.mtd, offset, SECTOR_SIZE, &retlen,
 816                           (u_char *)buffer);
 817
 818	    if (ret) {
 819		printk(KERN_WARNING "Error reading MTD device in ftl_read()\n");
 820		return ret;
 821	    }
 822	}
 823	buffer += SECTOR_SIZE;
 824    }
 825    return 0;
 826} /* ftl_read */
 827
 828/*======================================================================
 829
 830    Write a series of sectors to an FTL partition
 831
 832======================================================================*/
 833
 834static int set_bam_entry(partition_t *part, uint32_t log_addr,
 835			 uint32_t virt_addr)
 836{
 837    uint32_t bsize, blk, le_virt_addr;
 838#ifdef PSYCHO_DEBUG
 839    uint32_t old_addr;
 840#endif
 841    uint16_t eun;
 842    int ret;
 843    size_t retlen, offset;
 844
 845    pr_debug("ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
 846	  part, log_addr, virt_addr);
 847    bsize = 1 << part->header.EraseUnitSize;
 848    eun = log_addr / bsize;
 849    blk = (log_addr % bsize) / SECTOR_SIZE;
 850    offset = (part->EUNInfo[eun].Offset + blk * sizeof(uint32_t) +
 851		  le32_to_cpu(part->header.BAMOffset));
 852
 853#ifdef PSYCHO_DEBUG
 854    ret = mtd_read(part->mbd.mtd, offset, sizeof(uint32_t), &retlen,
 855                   (u_char *)&old_addr);
 856    if (ret) {
 857	printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret);
 858	return ret;
 859    }
 860    old_addr = le32_to_cpu(old_addr);
 861
 862    if (((virt_addr == 0xfffffffe) && !BLOCK_FREE(old_addr)) ||
 863	((virt_addr == 0) && (BLOCK_TYPE(old_addr) != BLOCK_DATA)) ||
 864	(!BLOCK_DELETED(virt_addr) && (old_addr != 0xfffffffe))) {
 865	static int ne = 0;
 866	if (++ne < 5) {
 867	    printk(KERN_NOTICE "ftl_cs: set_bam_entry() inconsistency!\n");
 868	    printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, old = 0x%x"
 869		   ", new = 0x%x\n", log_addr, old_addr, virt_addr);
 870	}
 871	return -EIO;
 872    }
 873#endif
 874    le_virt_addr = cpu_to_le32(virt_addr);
 875    if (part->bam_index == eun) {
 876#ifdef PSYCHO_DEBUG
 877	if (le32_to_cpu(part->bam_cache[blk]) != old_addr) {
 878	    static int ne = 0;
 879	    if (++ne < 5) {
 880		printk(KERN_NOTICE "ftl_cs: set_bam_entry() "
 881		       "inconsistency!\n");
 882		printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, cache"
 883		       " = 0x%x\n",
 884		       le32_to_cpu(part->bam_cache[blk]), old_addr);
 885	    }
 886	    return -EIO;
 887	}
 888#endif
 889	part->bam_cache[blk] = le_virt_addr;
 890    }
 891    ret = mtd_write(part->mbd.mtd, offset, sizeof(uint32_t), &retlen,
 892                    (u_char *)&le_virt_addr);
 893
 894    if (ret) {
 895	printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n");
 896	printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, new = 0x%x\n",
 897	       log_addr, virt_addr);
 898    }
 899    return ret;
 900} /* set_bam_entry */
 901
 902static int ftl_write(partition_t *part, caddr_t buffer,
 903		     u_long sector, u_long nblocks)
 904{
 905    uint32_t bsize, log_addr, virt_addr, old_addr, blk;
 906    u_long i;
 907    int ret;
 908    size_t retlen, offset;
 909
 910    pr_debug("ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
 911	  part, sector, nblocks);
 912    if (!(part->state & FTL_FORMATTED)) {
 913	printk(KERN_NOTICE "ftl_cs: bad partition\n");
 914	return -EIO;
 915    }
 916    /* See if we need to reclaim space, before we start */
 917    while (part->FreeTotal < nblocks) {
 918	ret = reclaim_block(part);
 919	if (ret)
 920	    return ret;
 921    }
 922
 923    bsize = 1 << part->header.EraseUnitSize;
 924
 925    virt_addr = sector * SECTOR_SIZE | BLOCK_DATA;
 926    for (i = 0; i < nblocks; i++) {
 927	if (virt_addr >= le32_to_cpu(part->header.FormattedSize)) {
 928	    printk(KERN_NOTICE "ftl_cs: bad write offset\n");
 929	    return -EIO;
 930	}
 931
 932	/* Grab a free block */
 933	blk = find_free(part);
 934	if (blk == 0) {
 935	    static int ne = 0;
 936	    if (++ne < 5)
 937		printk(KERN_NOTICE "ftl_cs: internal error: "
 938		       "no free blocks!\n");
 939	    return -ENOSPC;
 940	}
 941
 942	/* Tag the BAM entry, and write the new block */
 943	log_addr = part->bam_index * bsize + blk * SECTOR_SIZE;
 944	part->EUNInfo[part->bam_index].Free--;
 945	part->FreeTotal--;
 946	if (set_bam_entry(part, log_addr, 0xfffffffe))
 947	    return -EIO;
 948	part->EUNInfo[part->bam_index].Deleted++;
 949	offset = (part->EUNInfo[part->bam_index].Offset +
 950		      blk * SECTOR_SIZE);
 951	ret = mtd_write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, buffer);
 952
 953	if (ret) {
 954	    printk(KERN_NOTICE "ftl_cs: block write failed!\n");
 955	    printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, virt_addr"
 956		   " = 0x%x, Offset = 0x%zx\n", log_addr, virt_addr,
 957		   offset);
 958	    return -EIO;
 959	}
 960
 961	/* Only delete the old entry when the new entry is ready */
 962	old_addr = part->VirtualBlockMap[sector+i];
 963	if (old_addr != 0xffffffff) {
 964	    part->VirtualBlockMap[sector+i] = 0xffffffff;
 965	    part->EUNInfo[old_addr/bsize].Deleted++;
 966	    if (set_bam_entry(part, old_addr, 0))
 967		return -EIO;
 968	}
 969
 970	/* Finally, set up the new pointers */
 971	if (set_bam_entry(part, log_addr, virt_addr))
 972	    return -EIO;
 973	part->VirtualBlockMap[sector+i] = log_addr;
 974	part->EUNInfo[part->bam_index].Deleted--;
 975
 976	buffer += SECTOR_SIZE;
 977	virt_addr += SECTOR_SIZE;
 978    }
 979    return 0;
 980} /* ftl_write */
 981
 982static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
 983{
 984	partition_t *part = (void *)dev;
 985	u_long sect;
 986
 987	/* Sort of arbitrary: round size down to 4KiB boundary */
 988	sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
 989
 990	geo->heads = 1;
 991	geo->sectors = 8;
 992	geo->cylinders = sect >> 3;
 993
 994	return 0;
 995}
 996
 997static int ftl_readsect(struct mtd_blktrans_dev *dev,
 998			      unsigned long block, char *buf)
 999{
1000	return ftl_read((void *)dev, buf, block, 1);
1001}
1002
1003static int ftl_writesect(struct mtd_blktrans_dev *dev,
1004			      unsigned long block, char *buf)
1005{
1006	return ftl_write((void *)dev, buf, block, 1);
1007}
1008
1009static int ftl_discardsect(struct mtd_blktrans_dev *dev,
1010			   unsigned long sector, unsigned nr_sects)
1011{
1012	partition_t *part = (void *)dev;
1013	uint32_t bsize = 1 << part->header.EraseUnitSize;
1014
1015	pr_debug("FTL erase sector %ld for %d sectors\n",
1016	      sector, nr_sects);
1017
1018	while (nr_sects) {
1019		uint32_t old_addr = part->VirtualBlockMap[sector];
1020		if (old_addr != 0xffffffff) {
1021			part->VirtualBlockMap[sector] = 0xffffffff;
1022			part->EUNInfo[old_addr/bsize].Deleted++;
1023			if (set_bam_entry(part, old_addr, 0))
1024				return -EIO;
1025		}
1026		nr_sects--;
1027		sector++;
1028	}
1029
1030	return 0;
1031}
1032/*====================================================================*/
1033
1034static void ftl_freepart(partition_t *part)
1035{
1036	vfree(part->VirtualBlockMap);
1037	part->VirtualBlockMap = NULL;
1038	kfree(part->VirtualPageMap);
1039	part->VirtualPageMap = NULL;
1040	kfree(part->EUNInfo);
1041	part->EUNInfo = NULL;
1042	kfree(part->XferInfo);
1043	part->XferInfo = NULL;
1044	kfree(part->bam_cache);
1045	part->bam_cache = NULL;
1046} /* ftl_freepart */
1047
1048static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
1049{
1050	partition_t *partition;
1051
1052	partition = kzalloc(sizeof(partition_t), GFP_KERNEL);
1053
1054	if (!partition) {
1055		printk(KERN_WARNING "No memory to scan for FTL on %s\n",
1056		       mtd->name);
1057		return;
1058	}
1059
1060	partition->mbd.mtd = mtd;
1061
1062	if ((scan_header(partition) == 0) &&
1063	    (build_maps(partition) == 0)) {
1064
1065		partition->state = FTL_FORMATTED;
1066#ifdef PCMCIA_DEBUG
1067		printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n",
1068		       le32_to_cpu(partition->header.FormattedSize) >> 10);
1069#endif
1070		partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9;
1071
1072		partition->mbd.tr = tr;
1073		partition->mbd.devnum = -1;
1074		if (!add_mtd_blktrans_dev((void *)partition))
1075			return;
1076	}
1077
1078	ftl_freepart(partition);
1079	kfree(partition);
1080}
1081
1082static void ftl_remove_dev(struct mtd_blktrans_dev *dev)
1083{
1084	del_mtd_blktrans_dev(dev);
1085	ftl_freepart((partition_t *)dev);
1086}
1087
1088static struct mtd_blktrans_ops ftl_tr = {
1089	.name		= "ftl",
1090	.major		= FTL_MAJOR,
1091	.part_bits	= PART_BITS,
1092	.blksize 	= SECTOR_SIZE,
1093	.readsect	= ftl_readsect,
1094	.writesect	= ftl_writesect,
1095	.discard	= ftl_discardsect,
1096	.getgeo		= ftl_getgeo,
1097	.add_mtd	= ftl_add_mtd,
1098	.remove_dev	= ftl_remove_dev,
1099	.owner		= THIS_MODULE,
1100};
1101
1102static int __init init_ftl(void)
1103{
1104	return register_mtd_blktrans(&ftl_tr);
1105}
1106
1107static void __exit cleanup_ftl(void)
1108{
1109	deregister_mtd_blktrans(&ftl_tr);
1110}
1111
1112module_init(init_ftl);
1113module_exit(cleanup_ftl);
1114
1115
1116MODULE_LICENSE("Dual MPL/GPL");
1117MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
1118MODULE_DESCRIPTION("Support code for Flash Translation Layer, used on PCMCIA devices");