⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftl.patch

📁 linux交叉编译环境个软件和内核的补丁。
💻 PATCH
📖 第 1 页 / 共 4 页
字号:
+    NULL,		/* readdir */+    NULL,		/* poll */+    ftl_ioctl,		/* ioctl */+    NULL,		/* mmap */+    ftl_open,		/* open */+    NULL,               /* flush */+    ftl_close,		/* release */+    block_fsync		/* fsync */+};++/*======================================================================++    Scan_header() checks to see if a memory region contains an FTL+    partition.  build_maps() reads all the erase unit headers, builds+    the erase unit map, and then builds the virtual page map.++======================================================================*/++static int scan_header(ftl_dev_t *dev)+{+    erase_unit_header_t header;+    off_t offset;+    size_t count;+    int ret;++    DEBUG("scan_header(%p)\n", dev);++    /* Search first megabyte for a valid FTL header */+    count = sizeof(header);+    for (offset = 0;+	 offset < 0x100000;+	 offset += dev->region.BlockSize) {+	ret = (*dev->flash->ops->read)(dev->flash, (char *)&header,+                                       count, offset + dev->base_offset, 0);+	if (ret) {+            printk("Error reading flash mem.\n");+	    return -1;+	}+	if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;+    }+    if (offset == 0x100000) {+	printk(KERN_NOTICE "ftl: FTL header not found.\n");+	return -1;+    }+    if ((header.NumEraseUnits > 65536) || (header.BlockSize != 9) ||+	(header.EraseUnitSize < 10) || (header.EraseUnitSize > 31) ||+	(header.NumTransferUnits >= header.NumEraseUnits)) {+	printk(KERN_NOTICE "ftl: FTL header corrupt!\n");+	return -1;+    }+    dev->header = header;+    return 0;+}++static int build_maps(ftl_dev_t *dev)+{+    erase_unit_header_t header;+    u_short xvalid, xtrans, i;+    u_int blocks, j;+    int hdr_ok, ret;+    size_t count;+    off_t offset;++    DEBUG("build_maps(%p)\n", dev);++    /* Set up erase unit maps */+    dev->DataUnits = dev->header.NumEraseUnits - dev->header.NumTransferUnits;+    dev->EUNInfo = kmalloc(dev->DataUnits * sizeof(struct eun_info_t), GFP_KERNEL);+    for (i = 0; i < dev->DataUnits; i++)+	dev->EUNInfo[i].Offset = 0xffffffff;+    dev->XferInfo =+	kmalloc(dev->header.NumTransferUnits * sizeof(struct xfer_info_t), GFP_KERNEL);++    count = sizeof(header);+    xvalid = xtrans = 0;+    for (i = 0; i < dev->header.NumEraseUnits; i++) {+	offset = ((i + dev->header.FirstPhysicalEUN)+		      << dev->header.EraseUnitSize);+	ret = (*dev->flash->ops->read)(dev->flash, (char *)&header,+                                       count, offset + dev->base_offset, 0);+	if (ret) {+            printk("Error reading flash mem.\n");+	    return -1;+	}+	/* Is this a transfer partition? */+	hdr_ok = (strcmp(header.DataOrgTuple+3, "FTL100") == 0);+	if (hdr_ok && (header.LogicalEUN < dev->DataUnits) &&+	    (dev->EUNInfo[header.LogicalEUN].Offset == 0xffffffff)) {+	    dev->EUNInfo[header.LogicalEUN].Offset = offset;+	    dev->EUNInfo[header.LogicalEUN].EraseCount = header.EraseCount;+	    xvalid++;+	} else {+	    if (xtrans == dev->header.NumTransferUnits) {+		printk(KERN_NOTICE+                       "ftl: format error: too many transfer units!\n");+		return -1;+	    }+	    if (hdr_ok && (header.LogicalEUN == 0xffff)) {+		dev->XferInfo[xtrans].state = XFER_PREPARED;+		dev->XferInfo[xtrans].EraseCount = header.EraseCount;+	    } else {+		dev->XferInfo[xtrans].state = XFER_UNKNOWN;+		/* Pick anything reasonable for the erase count */+		dev->XferInfo[xtrans].EraseCount =+		    dev->header.EraseCount;+	    }+	    dev->XferInfo[xtrans].Offset = offset;+	    xtrans++;+	}+    }+    /* Check for format trouble */+    header = dev->header;+    if ((xtrans != header.NumTransferUnits) ||+	(xvalid+xtrans != header.NumEraseUnits)) {+	printk(KERN_NOTICE "cs: format error: erase units don't add up!\n");+	return -1;+    }++    /* Set up virtual page map */+    blocks = header.FormattedSize >> header.BlockSize;+    dev->VirtualBlockMap = vmalloc(blocks * sizeof(u_int));+    memset(dev->VirtualBlockMap, 0xff, blocks * sizeof(u_int));+    dev->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize;+    count = dev->BlocksPerUnit * sizeof(u_int);++    dev->bam_cache = kmalloc(dev->BlocksPerUnit * sizeof(u_int), GFP_KERNEL);+    dev->bam_index = 0xffff;+    dev->FreeTotal = 0;+    for (i = 0; i < dev->DataUnits; i++) {+	dev->EUNInfo[i].Free = 0;+	dev->EUNInfo[i].Deleted = 0;+	offset = dev->EUNInfo[i].Offset + header.BAMOffset;+	ret = (*dev->flash->ops->read)(dev->flash, (char *)dev->bam_cache,+                                       count, offset + dev->base_offset, 0);+	if (ret) {+            printk("Error reading flash mem.\n");+	    return -1;+	}+	for (j = 0; j < dev->BlocksPerUnit; j++) {+	    if (BLOCK_FREE(dev->bam_cache[j])) {+                dev->EUNInfo[i].Free++;+		dev->FreeTotal++;+	    } else if ((BLOCK_TYPE(dev->bam_cache[j]) == BLOCK_DATA) &&+                       (BLOCK_NUMBER(dev->bam_cache[j]) < blocks)) {+                dev->VirtualBlockMap[BLOCK_NUMBER(dev->bam_cache[j])] =+                (i << header.EraseUnitSize) + (j << header.BlockSize);+            } else if (BLOCK_DELETED(dev->bam_cache[j])) {+		dev->EUNInfo[i].Deleted++;+            }+	}+    }++    return 0;++} /* build_maps */++/*======================================================================++    Erase_xfer() schedules an asynchronous erase operation for a+    transfer unit.++======================================================================*/++static int erase_xfer(ftl_dev_t *dev, u_short xfernum)+{+    int ret;+    struct xfer_info_t *xfer;+    off_t offset;+    size_t count;++    xfer = &dev->XferInfo[xfernum];+    DEBUG("ftl: erasing xfer unit at 0x%x\n", xfer->Offset);+    xfer->state = XFER_ERASING;++#if 0+    /* Is there a free erase slot? */+    for (;;) {+	for (i = 0; i < MAX_ERASE; i++)+	    if (!ERASE_IN_PROGRESS(dev->eraseq[i].State)) break;+	if (i < MAX_ERASE) break;+	DEBUG("ftl_cs: erase queue is full\n");+	sleep_on(&dev->erase_pending);+    }++    /* Queue the request */+    dev->eraseq[i].State = ERASE_QUEUED;+    dev->eraseq[i].Handle = part->handle;+    dev->eraseq[i].Offset = xfer->Offset;+    dev->eraseq[i].Size = part->region.BlockSize;+    dev->eraseq[i].Optional = part;+    ret = CardServices(CheckEraseQueue, dev->eraseq_handle);+    if (ret != CS_SUCCESS) {+	cs_error(CheckEraseQueue, ret);+	return -EIO;+    }+#endif /* 0 */++    offset = xfer->Offset;+    count = dev->region.BlockSize;++    ret = (*dev->flash->ops->erase_sector)(dev->flash,+                                           offset + dev->base_offset, count);+    if (ret) {+      xfer->state = XFER_FAILED;+      printk("Error erasing flash mem.\n");+      return -EIO;+    } else {+      xfer->state = XFER_ERASED;+    }++    xfer->EraseCount++;+    return ret;+} /* erase_xfer */+++#if 0+static void save_status(eraseq_entry_t *erase)+{+    partition_t *part;+    struct xfer_info_t *xfer;+    int i;++    /* Look up the transfer unit */+    part = (partition_t *)(erase->Optional);+    for (i = 0; i < part->header.NumTransferUnits; i++)+	if (part->XferInfo[i].Offset == erase->Offset) break;+    if (i == part->header.NumTransferUnits) {+	printk(KERN_NOTICE "ftl_cs: internal error: "+	       "erase lookup failed!\n");+	return;+    }+    xfer = &part->XferInfo[i];+    if (erase->State == ERASE_PASSED)+	xfer->state = XFER_ERASED;+    else {+	xfer->state = XFER_FAILED;+	printk(KERN_NOTICE "ftl_cs: erase failed: state = %d\n",+	       erase->State);+    }+}+#endif /* 0 */++/*======================================================================++    Prepare_xfer() takes a freshly erased transfer unit and gives+    it an appropriate header.++======================================================================*/++static void prepare_xfer(ftl_dev_t *dev, int i)+{+    erase_unit_header_t header;+    struct xfer_info_t *xfer;+    int nbam, ret;+    u_int ctl;+    off_t offset;+    size_t count;++    xfer = &dev->XferInfo[i];+    xfer->state = XFER_FAILED;++    DEBUG("ftl: preparing xfer unit at 0x%x\n", xfer->Offset);++    /* Write the transfer unit header */+    header = dev->header;+    header.LogicalEUN = 0xffff;+    header.EraseCount = xfer->EraseCount;+    count = sizeof(header);+    offset = xfer->Offset;+    ret = (*dev->flash->ops->write)(dev->flash, (char *)&header,+                                    count, offset + dev->base_offset, 0);+    if (ret) {+      printk("Error writing flash mem.\n");+      return;+    }++    /* Write the BAM stub */+    nbam = (dev->BlocksPerUnit * sizeof(u_int) ++	    dev->header.BAMOffset + SECTOR_SIZE - 1) / SECTOR_SIZE;+    offset = xfer->Offset + dev->header.BAMOffset;+    count = sizeof(u_int);+    ctl = BLOCK_CONTROL;+    for (i = 0; i < nbam; i++, offset += sizeof(u_int)) {+      ret = (*dev->flash->ops->write)(dev->flash, (char *)&ctl,+                                      count, offset + dev->base_offset, 0);+      if (ret) {+        printk("Error writing flash mem.\n");+        return;+      }+    }+    xfer->state = XFER_PREPARED;++} /* prepare_xfer */++/*======================================================================++    Copy_erase_unit() takes a full erase block and a transfer unit,+    copies everything to the transfer unit, then swaps the block+    pointers.++    All data blocks are copied to the corresponding blocks in the+    target unit, so the virtual block map does not need to be+    updated.++======================================================================*/++static int copy_erase_unit(ftl_dev_t *dev, u_short srcunit, u_short xferunit)+{+    u_char buf[SECTOR_SIZE];+    struct eun_info_t *eun;+    struct xfer_info_t *xfer;+    u_int src, dest, free, i;+    u_short unit;+    int ret;+    off_t offset;+    size_t count;++    eun = &dev->EUNInfo[srcunit];+    xfer = &dev->XferInfo[xferunit];++    DEBUG("ftl: copying block 0x%x to 0x%x\n", eun->Offset, xfer->Offset);++    /* Read current BAM */+    if (dev->bam_index != srcunit) {+	offset = eun->Offset + dev->header.BAMOffset;+	count = dev->BlocksPerUnit * sizeof(u_int);+	ret = (*dev->flash->ops->read)(dev->flash, (char *)dev->bam_cache,+                                       count, offset + dev->base_offset, 0);+	/* mark the cache bad, in case we get an error later */+	dev->bam_index = 0xffff;+	if (ret)+          goto read_error;+    }++    /* Write the LogicalEUN for the transfer unit */+    xfer->state = XFER_UNKNOWN;+    count = sizeof(u_short);+    offset = xfer->Offset + 20; /* Bad! */+    unit = 0x7fff;+    ret = (*dev->flash->ops->write)(dev->flash, (char *)&unit,+                                    count, offset + dev->base_offset, 0);+    if (ret)+      goto write_error;++    /* Copy all data blocks from source unit to transfer unit */+    src = eun->Offset; dest = xfer->Offset;+    count = SECTOR_SIZE;+    free = 0;+    ret = 0;+    for (i = 0; i < dev->BlocksPerUnit; i++) {+	switch (BLOCK_TYPE(dev->bam_cache[i])) {+	case BLOCK_CONTROL:+	    /* This gets updated later */+	    break;+	case BLOCK_DATA:+	case BLOCK_REPLACEMENT:+	    offset = src;+            ret = (*dev->flash->ops->read)(dev->flash, &buf[0],+                                           count, offset + dev->base_offset, 0);+	    if (ret) goto read_error;+	    offset = dest;+            ret = (*dev->flash->ops->write)(dev->flash, &buf[0],+                                            count, offset + dev->base_offset, 0);+	    if (ret) goto write_error;+	    break;+	default:+	    /* All other blocks must be free */+	    dev->bam_cache[i] = 0xffffffff;+	    free++;+	    break;+	}+	src += SECTOR_SIZE;+	dest += SECTOR_SIZE;+    }++    /* Write the BAM to the transfer unit */+    offset = xfer->Offset + dev->header.BAMOffset;+    count = dev->BlocksPerUnit * sizeof(u_int);+    ret = (*dev->flash->ops->write)(dev->flash, (char *)dev->bam_cache,+                                    count, offset + dev->base_offset, 0);+    if (ret) goto write_error;++    /* All clear? Then update the LogicalEUN again */+    offset = xfer->Offset + 20; /* Bad! */+    count = sizeof(u_short);+    ret = (*dev->flash->ops->write)(dev->flash,  (char *)&srcunit,+                                    count, offset + dev->base_offset, 0);+    if (ret) goto write_error;++    /* Update the maps and usage stats*/+    i = xfer->EraseCount;+    xfer->EraseCount = eun->EraseCount;+    eun->EraseCount = i;+    i = xfer->Offset;+    xfer->Offset = eun->Offset;+    eun->Offset = i;+    dev->FreeTotal -= eun->Free;+    dev->FreeTotal += free;+    eun->Free = free;+    eun->Deleted = 0;++    /* Now, the cache should be valid for the new block */+    dev->bam_index = srcunit;++    return 0;++read_error:+    printk("Error reading flash mem.\n");+    return ret;++write_error:+    printk("Error writing flash mem.\n");+    return ret;+} /* copy_erase_unit */+

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -