diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mtd/ftl.c | 239 |
1 files changed, 114 insertions, 125 deletions
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index e40e34d3c7d6..d3e54f36e118 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -175,16 +175,16 @@ static int ftl_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg); static int ftl_open(struct inode *inode, struct file *file); static release_t ftl_close(struct inode *inode, struct file *file); -static int ftl_revalidate(kdev_t dev); +static int ftl_revalidate(struct gendisk *disk); static void ftl_erase_callback(struct erase_info *done); static struct block_device_operations ftl_blk_fops = { - owner: THIS_MODULE, - open: ftl_open, - release: ftl_close, - ioctl: ftl_ioctl, - revalidate: ftl_revalidate, + .owner = THIS_MODULE, + .open = ftl_open, + .release = ftl_close, + .ioctl = ftl_ioctl, + .revalidate_disk= ftl_revalidate, }; /*====================================================================== @@ -823,61 +823,53 @@ static u_int32_t find_free(partition_t *part) static int ftl_open(struct inode *inode, struct file *file) { - int minor = minor(inode->i_rdev); - partition_t *partition; + partition_t *partition = inode->i_bdev->bd_disk->private_data; + if (!partition) + return -ENODEV; - if (minor>>4 >= MAX_MTD_DEVICES) - return -ENODEV; - - partition = myparts[minor>>4]; - - if (!partition) - return -ENODEV; - - if (partition->state != FTL_FORMATTED) - return -ENXIO; + if (partition->state != FTL_FORMATTED) + return -ENXIO; - if (get_capacity(partition->disk) == 0) - return -ENXIO; + if (get_capacity(partition->disk) == 0) + return -ENXIO; - if (!get_mtd_device(partition->mtd, -1)) - return /* -E'SBUGGEREDOFF */ -ENXIO; + if (!get_mtd_device(partition->mtd, -1)) + return /* -E'SBUGGEREDOFF */ -ENXIO; - if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) { - put_mtd_device(partition->mtd); - return -EROFS; - } + if ((file->f_mode & 2) && !(partition->mtd->flags & MTD_CLEAR_BITS) ) { + put_mtd_device(partition->mtd); + return -EROFS; + } - DEBUG(0, "ftl_cs: ftl_open(%d)\n", minor); + DEBUG(0, "ftl_cs: ftl_open(%s)\n", inode->i_bdev->b_disk->disk_name); - atomic_inc(&partition->open); + atomic_inc(&partition->open); - return 0; + return 0; } /*====================================================================*/ static release_t ftl_close(struct inode *inode, struct file *file) { - int minor = minor(inode->i_rdev); - partition_t *part = myparts[minor >> 4]; - int i; + partition_t *part = inode->i_bdev->bd_disk->private_data; + int i; - DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor); + DEBUG(0, "ftl_cs: ftl_close(%s)\n", inode->i_bdev->b_disk->disk_name); - /* Wait for any pending erase operations to complete */ - if (part->mtd->sync) - part->mtd->sync(part->mtd); + /* Wait for any pending erase operations to complete */ + if (part->mtd->sync) + part->mtd->sync(part->mtd); - for (i = 0; i < part->header.NumTransferUnits; i++) { - if (part->XferInfo[i].state == XFER_ERASED) - prepare_xfer(part, i); - } + for (i = 0; i < part->header.NumTransferUnits; i++) { + if (part->XferInfo[i].state == XFER_ERASED) + prepare_xfer(part, i); + } - atomic_dec(&part->open); + atomic_dec(&part->open); - put_mtd_device(part->mtd); - release_return(0); + put_mtd_device(part->mtd); + release_return(0); } /* ftl_close */ @@ -1091,25 +1083,26 @@ static int ftl_write(partition_t *part, caddr_t buffer, 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); - partition_t *part= myparts[minor >> 4]; - u_long sect; - - if (!part) - return -ENODEV; /* How? */ - - if (cmd != HDIO_GETGEO) - return -EINVAL; - ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo)); - if (ret) return ret; - /* Sort of arbitrary: round size down to 4K boundary */ - sect = le32_to_cpu(part->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(get_start_sect(inode->i_bdev), (u_long *)&geo->start); - return 0; + partition_t *part = inode->i_bdev->bd_disk->private_data; + struct hd_geometry *geo = (struct hd_geometry *)arg; + int ret = 0; + u_long sect; + + if (!part) + return -ENODEV; /* How? */ + + if (cmd != HDIO_GETGEO) + return -EINVAL; + ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo)); + if (ret) + return ret; + /* Sort of arbitrary: round size down to 4K boundary */ + sect = le32_to_cpu(part->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(get_start_sect(inode->i_bdev), (u_long *)&geo->start); + return 0; } /* ftl_ioctl */ /*====================================================================== @@ -1118,13 +1111,11 @@ static int ftl_ioctl(struct inode *inode, struct file *file, ======================================================================*/ -static int ftl_revalidate(kdev_t dev) +static int ftl_revalidate(struct gendisk *disk) { - int unit = minor(dev) >> 4; - partition_t *part = myparts[unit]; + partition_t *part = disk->private_data; scan_header(part); - set_capacity(part->disk, - le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); + set_capacity(disk, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); return 0; } @@ -1134,50 +1125,48 @@ static int ftl_revalidate(kdev_t dev) ======================================================================*/ -static void do_ftl_request(request_arg_t) -{ - int ret, minor; - partition_t *part; +static struct request_queue ftl_queue; - do { - // sti(); - if (blk_queue_empty(QUEUE)) - return; +static void do_ftl_request(struct request_queue *q) +{ + struct request *req; + partition_t *part; + int ret; + + do { + // sti(); + if (blk_queue_empty(q)) + return; + req = elv_next_request(q); + part = req->rq_disk->private_data; + if (part) { + ret = 0; + switch (rq_data_dir(CURRENT)) { + case READ: + ret = ftl_read(part, req->buffer, req->sector, + req->current_nr_sectors); + if (ret) + printk("ftl_read returned %d\n", ret); + break; + case WRITE: + ret = ftl_write(part, req->buffer, req->sector, + req->current_nr_sectors); + if (ret) + printk("ftl_write returned %d\n", ret); + break; + default: + panic("ftl_cs: unknown block command!\n"); + } + } else { + ret = 1; + printk("NULL part in ftl_request\n"); + } + + if (!ret) + req->sector += req->current_nr_sectors; - minor = minor(CURRENT->rq_dev); - - part = myparts[minor >> 4]; - if (part) { - ret = 0; - - switch (rq_data_dir(CURRENT)) { - case READ: - ret = ftl_read(part, CURRENT->buffer, CURRENT->sector, - CURRENT->current_nr_sectors); - if (ret) printk("ftl_read returned %d\n", ret); - break; - - case WRITE: - ret = ftl_write(part, CURRENT->buffer, CURRENT->sector, - CURRENT->current_nr_sectors); - if (ret) printk("ftl_write returned %d\n", ret); - break; - - default: - panic("ftl_cs: unknown block command!\n"); - - } - } else { - ret = 1; - printk("NULL part in ftl_request\n"); - } - - if (!ret) { - CURRENT->sector += CURRENT->current_nr_sectors; - } - - end_request(CURRENT, (ret == 0) ? 1 : 0); - } while (1); + end_request(req, (ret == 0) ? 1 : 0); + } while (1); } /* do_ftl_request */ /*====================================================================*/ @@ -1246,6 +1235,8 @@ static void ftl_notify_add(struct mtd_info *mtd) atomic_set(&partition->open, 0); myparts[device] = partition; set_capacity(disk, le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE); + disk->private_data = partition; + disk->queue = &ftl_queue; add_disk(disk); #ifdef PCMCIA_DEBUG printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n", @@ -1287,31 +1278,29 @@ static void ftl_notify_remove(struct mtd_info *mtd) int init_ftl(void) { - static spinlock_t lock = SPIN_LOCK_UNLOCKED; - DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n"); - - if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { - printk(KERN_NOTICE "ftl_cs: unable to grab major " - "device number!\n"); - return -EAGAIN; - } - blk_init_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR), &do_ftl_request, &lock); - register_mtd_user(&ftl_notifier); - - return 0; + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n"); + + if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { + printk(KERN_NOTICE "ftl_cs: unable to grab major " + "device number!\n"); + return -EAGAIN; + } + blk_init_queue(&ftl_queue, &do_ftl_request, &lock); + register_mtd_user(&ftl_notifier); + return 0; } static void __exit cleanup_ftl(void) { - unregister_mtd_user(&ftl_notifier); - unregister_blkdev(FTL_MAJOR, "ftl"); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR)); + unregister_mtd_user(&ftl_notifier); + unregister_blkdev(FTL_MAJOR, "ftl"); + blk_cleanup_queue(&ftl_queue); } module_init(init_ftl); module_exit(cleanup_ftl); - MODULE_LICENSE("Dual MPL/GPL"); MODULE_AUTHOR("David Hinds <dhinds@sonic.net>"); MODULE_DESCRIPTION("Support code for Flash Translation Layer, used on PCMCIA devices and M-Systems DiskOnChip 1000"); |
