📄 ftl.patch
字号:
+ return -EIO;+ }++ /* Grab a free block */+ blk = find_free(dev);+ if (blk == 0) {+ static int ne = 0;+ if (++ne < 5)+ printk(KERN_NOTICE "ftl: internal error: no free blocks!\n");+ return -ENOSPC;+ }++ /* Tag the BAM entry, and write the new block */+ log_addr = dev->bam_index * bsize + blk * SECTOR_SIZE;+ dev->EUNInfo[dev->bam_index].Free--;+ dev->FreeTotal--;+ if (set_bam_entry(dev, log_addr, 0xfffffffe))+ return -EIO;+ dev->EUNInfo[dev->bam_index].Deleted++;+ offset = (dev->EUNInfo[dev->bam_index].Offset + blk * SECTOR_SIZE);+ ret = (*dev->flash->ops->write)(dev->flash, buffer,+ count, offset + dev->base_offset, 0);+ if (ret) {+ printk(KERN_NOTICE "ftl: block write failed!\n");+ printk(KERN_NOTICE "ftl: log_addr = 0x%x, virt_addr"+ " = 0x%x, Offset = 0x%lx\n", log_addr, virt_addr,+ offset);+ printk("Error writing flash mem.\n");+ return -EIO;+ }++ /* Only delete the old entry when the new entry is ready */+ old_addr = dev->VirtualBlockMap[sector+i];+ if (old_addr != 0xffffffff) {+ dev->VirtualBlockMap[sector+i] = 0xffffffff;+ dev->EUNInfo[old_addr/bsize].Deleted++;+ if (set_bam_entry(dev, old_addr, 0))+ return -EIO;+ }++ /* Finally, set up the new pointers */+ if (set_bam_entry(dev, log_addr, virt_addr))+ return -EIO;+ dev->VirtualBlockMap[sector+i] = log_addr;+ dev->EUNInfo[dev->bam_index].Deleted--;++ buffer += SECTOR_SIZE;+ virt_addr += SECTOR_SIZE;+ }+ return 0;+} /* ftl_write */++/*======================================================================++ IOCTL calls for getting device parameters.++======================================================================*/++static int ftl_ioctl(struct inode *inode, struct file *file,+ u_int cmd, u_long arg)+{+ struct hd_geometry *geo = (struct hd_geometry *)arg;+ int ret = 0, minor = MINOR(inode->i_rdev);+ ftl_dev_t *dev;+ u_long sect;++ dev = dev_table[DEVICE_NR(minor)];+ if (dev==NULL)+ return -ENODEV;++ switch (cmd) {+ case HDIO_GETGEO:+ if (!access_ok(VERIFY_WRITE, (long *)arg, sizeof(*geo)))+ return -EFAULT;+ /* Sort of arbitrary: round size down to 4K boundary */+ sect = dev->header.FormattedSize/SECTOR_SIZE;+ put_user(1, (char *)&geo->heads);+ put_user(8, (char *)&geo->sectors);+ put_user((sect>>3), (short *)&geo->cylinders);+ put_user(ftl_hd[minor].start_sect, (u_long *)&geo->start);+ break;+ case BLKGETSIZE:+ if (!access_ok(VERIFY_WRITE, (long *)arg, sizeof(long)))+ return -EFAULT;+ put_user(dev->header.FormattedSize/SECTOR_SIZE, (long *)arg);+ break;+ case BLKRRPART:+ ret = ftl_reread_partitions(minor);+ break;+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,3)+ case BLKFLSBUF:+ if (!suser())+ return -EACCES;+ fsync_dev(inode->i_rdev);+ invalidate_buffers(inode->i_rdev);+ break;+ RO_IOCTLS(inode->i_rdev, arg);+#else+ case BLKROSET:+ case BLKROGET:+ case BLKFLSBUF:+ ret = blk_ioctl(inode->i_rdev, cmd, arg);+ break;+#endif+ default:+ ret = -EINVAL;+ }++ return ret;+} /* ftl_ioctl */++/*======================================================================++ Handler for block device requests++======================================================================*/++static int ftl_reread_partitions(int minor)+{+ int d = DEVICE_NR(minor);+ ftl_dev_t *dev = dev_table[d];+ int i, whole;+ struct super_block *sb;++ DEBUG("ftl: ftl_reread_partition(minor=%d) dev=0x%p, d=%d\n", minor, dev, d);+ if (dev->locked || (dev->open > 1))+ return -EBUSY;+ dev->locked = 1;++ whole = minor & ~(MAX_PART-1);+ for (i = 0; i < MAX_PART; i++) {+ if (ftl_hd[whole+i].nr_sects > 0) {+ kdev_t rdev = MKDEV(FTL_MAJOR, whole+i);+ sync_dev(rdev);+ sb = get_super(rdev);+ if (sb)+ invalidate_inodes(sb);+ invalidate_buffers(rdev);+ }+ ftl_hd[whole+i].start_sect = 0;+ ftl_hd[whole+i].nr_sects = 0;+ }++ if (scan_header(dev) == 0) {+ ftl_hd[whole].nr_sects =+ dev->header.FormattedSize/SECTOR_SIZE;+ } else {+ ftl_hd[whole >> PART_BITS].start_sect = -1;+ }+ /* resetup_one_dev(&ftl_gendisk, whole); * XXX */+ resetup_one_dev(&ftl_gendisk, whole >> PART_BITS);++#ifdef FLASH_DEBUG+ for (i = 0; i < MAX_PART; i++) {+ if (ftl_hd[whole+i].nr_sects > 0)+ printk(KERN_INFO " %d: start %ld size %ld\n", i,+ ftl_hd[whole+i].start_sect,+ ftl_hd[whole+i].nr_sects);+ }+#endif++ dev->locked = 0;+ wake_up(&ftl_wait_open);+ return 0;+}++/**+ gendisk init function.+ */++static void ftl_geninit(struct gendisk *gendisk)+{+ int i;+ ftl_dev_t *dev;+ for (i = 0; i < MAX_DEV; i++) {+ dev = dev_table[i];+ if (dev==NULL)+ break;+ }+ gendisk->nr_real = i;+}+++/*======================================================================++ Handler for block device requests++======================================================================*/++static void do_ftl_request(void)+{+ int ret, minor;+ ftl_dev_t *dev;++ /*DEBUG("ftl: starting do_ftl_request()\n");*/++ do {+ sti();+ INIT_REQUEST;++ minor = MINOR(CURRENT->rq_dev);++ dev = dev_table[DEVICE_NR(minor)];+ ret = 0;++ switch (CURRENT->cmd) {++ case READ:+ ret = ftl_read(dev, CURRENT->buffer,+ CURRENT->sector+ftl_hd[minor].start_sect,+ CURRENT->current_nr_sectors);+ break;++ case WRITE:+ ret = ftl_write(dev, CURRENT->buffer,+ CURRENT->sector+ftl_hd[minor].start_sect,+ CURRENT->current_nr_sectors);+ break;++ default:+ panic("ftl: unknown block command!\n");++ }+ end_request((ret == 0) ? 1 : 0);+ } while (1);+} /* do_ftl_request */++/*====================================================================*/++#ifdef OLD_PCCARD+static int __init init_ftl(void)+{+ servinfo_t serv;+ int i;++ DEBUG("%s\n", version);++ CardServices(GetCardServicesInfo, &serv);+ if (serv.Revision != CS_RELEASE_CODE) {+ printk(KERN_NOTICE "ftl_cs: Card Services release "+ "does not match!\n");+ return -1;+ }++ register_pccard_driver(&dev_info, &ftl_attach, &ftl_detach);++ major_dev = register_blkdev(major_dev, "ftl", &ftl_blk_fops);+ if (major_dev == 0) {+ printk(KERN_NOTICE "ftl_cs: unable to grab major "+ "device number!\n");+ return -ENODEV;+ }++ for (i = 0; i < MINOR_NR(MAX_DEV, 0, 0); i++)+ ftl_blocksizes[i] = 1024;+ for (i = 0; i < MAX_DEV*MAX_PART; i++) {+ ftl_hd[i].nr_sects = 0;+ ftl_hd[i].start_sect = -1;+ }+ blksize_size[major_dev] = ftl_blocksizes;+ ftl_gendisk.major = major_dev;+ blk_dev[major_dev].request_fn = DEVICE_REQUEST;+ ftl_gendisk.next = gendisk_head;+ gendisk_head = &ftl_gendisk;+ init_waitqueue_head(&ftl_wait_open);++ return 0;+}++static void __exit exit_ftl(void)+{+ int i;+ dev_link_t *link;+ struct gendisk *gd, **gdp;++ DEBUG("ftl_cs: unloading\n");+ unregister_pccard_driver(&dev_info);+ if (major_dev != 0) {+ unregister_blkdev(major_dev, "ftl");+ blk_dev[major_dev].request_fn = NULL;+ blksize_size[major_dev] = NULL;+ }+ for (i = 0; i < MAX_DEV; i++) {+ link = dev_table[i];+ if (link) {+ if (link->state & DEV_CONFIG)+ ftl_release((u_long)link);+ ftl_detach(link);+ }+ }+ for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))+ if (*gdp == &ftl_gendisk) {+ gd = *gdp; *gdp = gd->next;+ break;+ }+}++module_init(init_ftl);+module_exit(exit_ftl);++#endif /* OLD_PCCARD */+++static ftl_dev_t *ftl_attach(flash_device_info_t *flash,+ off_t offset, size_t size)+{+ ftl_dev_t *dev;+ int i;+ int minor_dev;+ u_int block_size;++ DEBUG("ftl_attach()\n");++ for (i = 0; i < MAX_DEV; i++) {+ if (dev_table[i] == NULL) {+ break;+ }+ }++ if (i == MAX_DEV) {+ printk(KERN_NOTICE "ftl: no devices available\n");+ return NULL;+ }++ minor_dev = i;+ dev = kmalloc(sizeof(ftl_dev_t), GFP_KERNEL);+ if (dev == NULL)+ return NULL;++ dev_table[minor_dev] = dev;+ memset(dev, 0, sizeof(ftl_dev_t));+ /* init_waitqueue(&dev->erase_pending); */+ dev->flash = flash;+ dev->base_offset = offset;+ block_size = 0;++ for (i=0;i<flash->num_regions;i++) {+ if ( (offset + size >= flash->region[i].offset) &&+ (offset < flash->region[i].offset ++ flash->region[i].sector_size*flash->region[i].num_sectors)) {+ if (flash->region[i].sector_size > block_size) {+ block_size = flash->region[i].sector_size;+ }+ }+ }+ dev->region.BlockSize = block_size;+ dev->region.RegionSize = size;+ dev->dev = MKDEV(FTL_MAJOR, MINOR_NR(minor_dev, 0));++ printk("ftl: /dev/ftl%c - size: %d kB blocksize: %d kB at flash%d\n",+ minor_dev+'a', dev->region.RegionSize>>10, dev->region.BlockSize>>10,+ MINOR(flash->dev));++ return dev;+} /* ftl_attach */++int ftl_init(void)+{+ int i;+ flash_device_info_t *flash;++ DEBUG("ftl_init()\n");++ if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {+ printk("unable to get major %d for ftl devices\n", FTL_MAJOR);+ return -1;+ }++ for (i = 0; i < MINOR_NR(MAX_DEV, 0); i++)+ ftl_blocksizes[i] = 1024;++ for (i = 0; i < MINOR_NR(MAX_DEV, 0); i++) {+ ftl_hd[i].nr_sects = 0;+ ftl_hd[i].start_sect = -1;+ }++ blksize_size[FTL_MAJOR] = ftl_blocksizes;+ ftl_gendisk.major = FTL_MAJOR;+ blk_dev[FTL_MAJOR].request_fn = DEVICE_REQUEST;+ ftl_gendisk.next = gendisk_head;+ gendisk_head = &ftl_gendisk;+ init_waitqueue(&ftl_wait_open);++ for (i=0;i<sizeof(boot_table)/sizeof(struct boot_ftl);i++) {+ for (flash=flash_devices; flash != NULL; flash=flash->next) {+ if (MINOR(flash->dev)==boot_table[i].minor) {+ break;+ }+ }+ if (flash==NULL) {+ printk("No flash device %d found. Can't create ftl device for it.\n", i);+ } else {+ ftl_attach(flash, boot_table[i].start, boot_table[i].size);+ }+ }++ return 0;+}+ diff -u linux-2.2.13/drivers/block/ll_rw_blk.c.ORIG drivers/block/ll_rw_blk.c--- linux-2.2.13/drivers/block/ll_rw_blk.c.ORIG Fri Oct 22 23:09:45 1999+++ linux-2.2.13/drivers/block/ll_rw_blk.c Mon Jan 10 20:18:44 2000@@ -819,6 +819,9 @@ #ifdef CONFIG_BLK_DEV_RAM rd_init(); #endif+#ifdef CONFIG_BLK_DEV_FTL+ ftl_init();+#endif #ifdef CONFIG_BLK_DEV_LOOP loop_init(); #endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -