diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-17 12:09:13 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-17 12:09:13 -0400 |
commit | c84d9bbe7c77aea7e1194da056d44a2ed982e72b (patch) | |
tree | c7b9ee5e2b94ba87a2124e731bd8281439c0fb5d /drivers | |
parent | cedd120cac61fa149ba215eabc57b2578068be00 (diff) |
ide-floppy: factor out generic disk handling code to ide-gd-floppy.c
While at it:
- idefloppy_do_request() -> ide_floppy_do_request()
- idefloppy_end_request() -> ide_floppy_end_request()
- idefloppy_setup() -> ide_floppy_setup()
There should be no functional changes caused by this patch.
Acked-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ide/Makefile | 2 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 319 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.h | 19 | ||||
-rw-r--r-- | drivers/ide/ide-gd-floppy.c | 298 |
4 files changed, 327 insertions, 311 deletions
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 8aad9395a427..7eeeab597959 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
@@ -39,7 +39,7 @@ obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o | |||
39 | 39 | ||
40 | ide-disk_mod-y += ide-gd.o ide-disk.o ide-disk_ioctl.o | 40 | ide-disk_mod-y += ide-gd.o ide-disk.o ide-disk_ioctl.o |
41 | ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o | 41 | ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o |
42 | ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o | 42 | ide-floppy_mod-y += ide-gd-floppy.o ide-floppy.o ide-floppy_ioctl.o |
43 | 43 | ||
44 | ifeq ($(CONFIG_IDE_PROC_FS), y) | 44 | ifeq ($(CONFIG_IDE_PROC_FS), y) |
45 | ide-disk_mod-y += ide-disk_proc.o | 45 | ide-disk_mod-y += ide-disk_proc.o |
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 791a9d6f371c..802e0968e32f 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -15,12 +15,6 @@ | |||
15 | * Documentation/ide/ChangeLog.ide-floppy.1996-2002 | 15 | * Documentation/ide/ChangeLog.ide-floppy.1996-2002 |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define DRV_NAME "ide-floppy" | ||
19 | #define PFX DRV_NAME ": " | ||
20 | |||
21 | #define IDEFLOPPY_VERSION "1.00" | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/types.h> | 18 | #include <linux/types.h> |
25 | #include <linux/string.h> | 19 | #include <linux/string.h> |
26 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
@@ -49,19 +43,6 @@ | |||
49 | 43 | ||
50 | #include "ide-floppy.h" | 44 | #include "ide-floppy.h" |
51 | 45 | ||
52 | /* module parameters */ | ||
53 | static unsigned long debug_mask; | ||
54 | module_param(debug_mask, ulong, 0644); | ||
55 | |||
56 | /* define to see debug info */ | ||
57 | #define IDEFLOPPY_DEBUG_LOG 0 | ||
58 | |||
59 | #if IDEFLOPPY_DEBUG_LOG | ||
60 | #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) | ||
61 | #else | ||
62 | #define ide_debug_log(lvl, fmt, args...) do {} while (0) | ||
63 | #endif | ||
64 | |||
65 | /* | 46 | /* |
66 | * After each failed packet command we issue a request sense command and retry | 47 | * After each failed packet command we issue a request sense command and retry |
67 | * the packet command IDEFLOPPY_MAX_PC_RETRIES times. | 48 | * the packet command IDEFLOPPY_MAX_PC_RETRIES times. |
@@ -83,41 +64,11 @@ module_param(debug_mask, ulong, 0644); | |||
83 | /* Error code returned in rq->errors to the higher part of the driver. */ | 64 | /* Error code returned in rq->errors to the higher part of the driver. */ |
84 | #define IDEFLOPPY_ERROR_GENERAL 101 | 65 | #define IDEFLOPPY_ERROR_GENERAL 101 |
85 | 66 | ||
86 | static DEFINE_MUTEX(idefloppy_ref_mutex); | ||
87 | |||
88 | static void idefloppy_cleanup_obj(struct kref *); | ||
89 | |||
90 | static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) | ||
91 | { | ||
92 | struct ide_floppy_obj *floppy = NULL; | ||
93 | |||
94 | mutex_lock(&idefloppy_ref_mutex); | ||
95 | floppy = ide_drv_g(disk, ide_floppy_obj); | ||
96 | if (floppy) { | ||
97 | if (ide_device_get(floppy->drive)) | ||
98 | floppy = NULL; | ||
99 | else | ||
100 | kref_get(&floppy->kref); | ||
101 | } | ||
102 | mutex_unlock(&idefloppy_ref_mutex); | ||
103 | return floppy; | ||
104 | } | ||
105 | |||
106 | static void ide_floppy_put(struct ide_floppy_obj *floppy) | ||
107 | { | ||
108 | ide_drive_t *drive = floppy->drive; | ||
109 | |||
110 | mutex_lock(&idefloppy_ref_mutex); | ||
111 | kref_put(&floppy->kref, idefloppy_cleanup_obj); | ||
112 | ide_device_put(drive); | ||
113 | mutex_unlock(&idefloppy_ref_mutex); | ||
114 | } | ||
115 | |||
116 | /* | 67 | /* |
117 | * Used to finish servicing a request. For read/write requests, we will call | 68 | * Used to finish servicing a request. For read/write requests, we will call |
118 | * ide_end_request to pass to the next buffer. | 69 | * ide_end_request to pass to the next buffer. |
119 | */ | 70 | */ |
120 | static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) | 71 | int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) |
121 | { | 72 | { |
122 | idefloppy_floppy_t *floppy = drive->driver_data; | 73 | idefloppy_floppy_t *floppy = drive->driver_data; |
123 | struct request *rq = HWGROUP(drive)->rq; | 74 | struct request *rq = HWGROUP(drive)->rq; |
@@ -161,7 +112,7 @@ static void idefloppy_update_buffers(ide_drive_t *drive, | |||
161 | struct bio *bio = rq->bio; | 112 | struct bio *bio = rq->bio; |
162 | 113 | ||
163 | while ((bio = rq->bio) != NULL) | 114 | while ((bio = rq->bio) != NULL) |
164 | idefloppy_end_request(drive, 1, 0); | 115 | ide_floppy_end_request(drive, 1, 0); |
165 | } | 116 | } |
166 | 117 | ||
167 | static void ide_floppy_callback(ide_drive_t *drive, int dsc) | 118 | static void ide_floppy_callback(ide_drive_t *drive, int dsc) |
@@ -200,7 +151,7 @@ static void ide_floppy_callback(ide_drive_t *drive, int dsc) | |||
200 | "Aborting request!\n"); | 151 | "Aborting request!\n"); |
201 | } | 152 | } |
202 | 153 | ||
203 | idefloppy_end_request(drive, uptodate, 0); | 154 | ide_floppy_end_request(drive, uptodate, 0); |
204 | } | 155 | } |
205 | 156 | ||
206 | static void ide_floppy_report_error(idefloppy_floppy_t *floppy, | 157 | static void ide_floppy_report_error(idefloppy_floppy_t *floppy, |
@@ -329,8 +280,8 @@ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, | |||
329 | pc->req_xfer = pc->buf_size = rq->data_len; | 280 | pc->req_xfer = pc->buf_size = rq->data_len; |
330 | } | 281 | } |
331 | 282 | ||
332 | static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, | 283 | ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, struct request *rq, |
333 | struct request *rq, sector_t block_s) | 284 | sector_t block_s) |
334 | { | 285 | { |
335 | idefloppy_floppy_t *floppy = drive->driver_data; | 286 | idefloppy_floppy_t *floppy = drive->driver_data; |
336 | ide_hwif_t *hwif = drive->hwif; | 287 | ide_hwif_t *hwif = drive->hwif; |
@@ -353,7 +304,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, | |||
353 | else | 304 | else |
354 | printk(KERN_ERR PFX "%s: I/O error\n", drive->name); | 305 | printk(KERN_ERR PFX "%s: I/O error\n", drive->name); |
355 | 306 | ||
356 | idefloppy_end_request(drive, 0, 0); | 307 | ide_floppy_end_request(drive, 0, 0); |
357 | return ide_stopped; | 308 | return ide_stopped; |
358 | } | 309 | } |
359 | if (blk_fs_request(rq)) { | 310 | if (blk_fs_request(rq)) { |
@@ -361,7 +312,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, | |||
361 | (rq->nr_sectors % floppy->bs_factor)) { | 312 | (rq->nr_sectors % floppy->bs_factor)) { |
362 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", | 313 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", |
363 | drive->name); | 314 | drive->name); |
364 | idefloppy_end_request(drive, 0, 0); | 315 | ide_floppy_end_request(drive, 0, 0); |
365 | return ide_stopped; | 316 | return ide_stopped; |
366 | } | 317 | } |
367 | pc = &floppy->queued_pc; | 318 | pc = &floppy->queued_pc; |
@@ -373,7 +324,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, | |||
373 | idefloppy_blockpc_cmd(floppy, pc, rq); | 324 | idefloppy_blockpc_cmd(floppy, pc, rq); |
374 | } else { | 325 | } else { |
375 | blk_dump_rq_flags(rq, PFX "unsupported command in queue"); | 326 | blk_dump_rq_flags(rq, PFX "unsupported command in queue"); |
376 | idefloppy_end_request(drive, 0, 0); | 327 | ide_floppy_end_request(drive, 0, 0); |
377 | return ide_stopped; | 328 | return ide_stopped; |
378 | } | 329 | } |
379 | 330 | ||
@@ -455,7 +406,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) | |||
455 | * Determine if a media is present in the floppy drive, and if so, its LBA | 406 | * Determine if a media is present in the floppy drive, and if so, its LBA |
456 | * capacity. | 407 | * capacity. |
457 | */ | 408 | */ |
458 | static int ide_floppy_get_capacity(ide_drive_t *drive) | 409 | int ide_floppy_get_capacity(ide_drive_t *drive) |
459 | { | 410 | { |
460 | idefloppy_floppy_t *floppy = drive->driver_data; | 411 | idefloppy_floppy_t *floppy = drive->driver_data; |
461 | struct gendisk *disk = floppy->disk; | 412 | struct gendisk *disk = floppy->disk; |
@@ -554,12 +505,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) | |||
554 | return rc; | 505 | return rc; |
555 | } | 506 | } |
556 | 507 | ||
557 | sector_t ide_floppy_capacity(ide_drive_t *drive) | 508 | void ide_floppy_setup(ide_drive_t *drive) |
558 | { | ||
559 | return drive->capacity64; | ||
560 | } | ||
561 | |||
562 | static void idefloppy_setup(ide_drive_t *drive) | ||
563 | { | 509 | { |
564 | struct ide_floppy_obj *floppy = drive->driver_data; | 510 | struct ide_floppy_obj *floppy = drive->driver_data; |
565 | u16 *id = drive->id; | 511 | u16 *id = drive->id; |
@@ -601,248 +547,3 @@ static void idefloppy_setup(ide_drive_t *drive) | |||
601 | 547 | ||
602 | drive->dev_flags |= IDE_DFLAG_ATTACH; | 548 | drive->dev_flags |= IDE_DFLAG_ATTACH; |
603 | } | 549 | } |
604 | |||
605 | static void ide_floppy_remove(ide_drive_t *drive) | ||
606 | { | ||
607 | idefloppy_floppy_t *floppy = drive->driver_data; | ||
608 | struct gendisk *g = floppy->disk; | ||
609 | |||
610 | ide_proc_unregister_driver(drive, floppy->driver); | ||
611 | |||
612 | del_gendisk(g); | ||
613 | |||
614 | ide_floppy_put(floppy); | ||
615 | } | ||
616 | |||
617 | static void idefloppy_cleanup_obj(struct kref *kref) | ||
618 | { | ||
619 | struct ide_floppy_obj *floppy = to_ide_drv(kref, ide_floppy_obj); | ||
620 | ide_drive_t *drive = floppy->drive; | ||
621 | struct gendisk *g = floppy->disk; | ||
622 | |||
623 | drive->driver_data = NULL; | ||
624 | g->private_data = NULL; | ||
625 | put_disk(g); | ||
626 | kfree(floppy); | ||
627 | } | ||
628 | |||
629 | static int ide_floppy_probe(ide_drive_t *); | ||
630 | |||
631 | static ide_driver_t idefloppy_driver = { | ||
632 | .gen_driver = { | ||
633 | .owner = THIS_MODULE, | ||
634 | .name = "ide-floppy", | ||
635 | .bus = &ide_bus_type, | ||
636 | }, | ||
637 | .probe = ide_floppy_probe, | ||
638 | .remove = ide_floppy_remove, | ||
639 | .version = IDEFLOPPY_VERSION, | ||
640 | .do_request = idefloppy_do_request, | ||
641 | .end_request = idefloppy_end_request, | ||
642 | .error = __ide_error, | ||
643 | #ifdef CONFIG_IDE_PROC_FS | ||
644 | .proc = ide_floppy_proc, | ||
645 | .settings = ide_floppy_settings, | ||
646 | #endif | ||
647 | }; | ||
648 | |||
649 | static int idefloppy_open(struct inode *inode, struct file *filp) | ||
650 | { | ||
651 | struct gendisk *disk = inode->i_bdev->bd_disk; | ||
652 | struct ide_floppy_obj *floppy; | ||
653 | ide_drive_t *drive; | ||
654 | int ret = 0; | ||
655 | |||
656 | floppy = ide_floppy_get(disk); | ||
657 | if (!floppy) | ||
658 | return -ENXIO; | ||
659 | |||
660 | drive = floppy->drive; | ||
661 | |||
662 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
663 | |||
664 | floppy->openers++; | ||
665 | |||
666 | if (floppy->openers == 1) { | ||
667 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
668 | /* Just in case */ | ||
669 | |||
670 | if (ide_do_test_unit_ready(drive, disk)) | ||
671 | ide_do_start_stop(drive, disk, 1); | ||
672 | |||
673 | ret = ide_floppy_get_capacity(drive); | ||
674 | |||
675 | set_capacity(disk, ide_floppy_capacity(drive)); | ||
676 | |||
677 | if (ret && (filp->f_flags & O_NDELAY) == 0) { | ||
678 | /* | ||
679 | * Allow O_NDELAY to open a drive without a disk, or with an | ||
680 | * unreadable disk, so that we can get the format capacity | ||
681 | * of the drive or begin the format - Sam | ||
682 | */ | ||
683 | ret = -EIO; | ||
684 | goto out_put_floppy; | ||
685 | } | ||
686 | |||
687 | if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) { | ||
688 | ret = -EROFS; | ||
689 | goto out_put_floppy; | ||
690 | } | ||
691 | |||
692 | ide_set_media_lock(drive, disk, 1); | ||
693 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; | ||
694 | check_disk_change(inode->i_bdev); | ||
695 | } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { | ||
696 | ret = -EBUSY; | ||
697 | goto out_put_floppy; | ||
698 | } | ||
699 | return 0; | ||
700 | |||
701 | out_put_floppy: | ||
702 | floppy->openers--; | ||
703 | ide_floppy_put(floppy); | ||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | static int idefloppy_release(struct inode *inode, struct file *filp) | ||
708 | { | ||
709 | struct gendisk *disk = inode->i_bdev->bd_disk; | ||
710 | struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj); | ||
711 | ide_drive_t *drive = floppy->drive; | ||
712 | |||
713 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
714 | |||
715 | if (floppy->openers == 1) { | ||
716 | ide_set_media_lock(drive, disk, 0); | ||
717 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
718 | } | ||
719 | |||
720 | floppy->openers--; | ||
721 | |||
722 | ide_floppy_put(floppy); | ||
723 | |||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
728 | { | ||
729 | struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk, | ||
730 | ide_floppy_obj); | ||
731 | ide_drive_t *drive = floppy->drive; | ||
732 | |||
733 | geo->heads = drive->bios_head; | ||
734 | geo->sectors = drive->bios_sect; | ||
735 | geo->cylinders = (u16)drive->bios_cyl; /* truncate */ | ||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int idefloppy_media_changed(struct gendisk *disk) | ||
740 | { | ||
741 | struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj); | ||
742 | ide_drive_t *drive = floppy->drive; | ||
743 | int ret; | ||
744 | |||
745 | /* do not scan partitions twice if this is a removable device */ | ||
746 | if (drive->dev_flags & IDE_DFLAG_ATTACH) { | ||
747 | drive->dev_flags &= ~IDE_DFLAG_ATTACH; | ||
748 | return 0; | ||
749 | } | ||
750 | ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED); | ||
751 | drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED; | ||
752 | return ret; | ||
753 | } | ||
754 | |||
755 | static int idefloppy_revalidate_disk(struct gendisk *disk) | ||
756 | { | ||
757 | struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj); | ||
758 | set_capacity(disk, ide_floppy_capacity(floppy->drive)); | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static struct block_device_operations idefloppy_ops = { | ||
763 | .owner = THIS_MODULE, | ||
764 | .open = idefloppy_open, | ||
765 | .release = idefloppy_release, | ||
766 | .ioctl = ide_floppy_ioctl, | ||
767 | .getgeo = idefloppy_getgeo, | ||
768 | .media_changed = idefloppy_media_changed, | ||
769 | .revalidate_disk = idefloppy_revalidate_disk | ||
770 | }; | ||
771 | |||
772 | static int ide_floppy_probe(ide_drive_t *drive) | ||
773 | { | ||
774 | idefloppy_floppy_t *floppy; | ||
775 | struct gendisk *g; | ||
776 | |||
777 | if (!strstr("ide-floppy", drive->driver_req)) | ||
778 | goto failed; | ||
779 | |||
780 | if (drive->media != ide_floppy) | ||
781 | goto failed; | ||
782 | |||
783 | if (!ide_check_atapi_device(drive, DRV_NAME)) { | ||
784 | printk(KERN_ERR PFX "%s: not supported by this version of " | ||
785 | DRV_NAME "\n", drive->name); | ||
786 | goto failed; | ||
787 | } | ||
788 | floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL); | ||
789 | if (!floppy) { | ||
790 | printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n", | ||
791 | drive->name); | ||
792 | goto failed; | ||
793 | } | ||
794 | |||
795 | g = alloc_disk_node(1 << PARTN_BITS, hwif_to_node(drive->hwif)); | ||
796 | if (!g) | ||
797 | goto out_free_floppy; | ||
798 | |||
799 | ide_init_disk(g, drive); | ||
800 | |||
801 | kref_init(&floppy->kref); | ||
802 | |||
803 | floppy->drive = drive; | ||
804 | floppy->driver = &idefloppy_driver; | ||
805 | floppy->disk = g; | ||
806 | |||
807 | g->private_data = &floppy->driver; | ||
808 | |||
809 | drive->driver_data = floppy; | ||
810 | |||
811 | drive->debug_mask = debug_mask; | ||
812 | |||
813 | idefloppy_setup(drive); | ||
814 | |||
815 | set_capacity(g, ide_floppy_capacity(drive)); | ||
816 | |||
817 | g->minors = 1 << PARTN_BITS; | ||
818 | g->driverfs_dev = &drive->gendev; | ||
819 | if (drive->dev_flags & IDE_DFLAG_REMOVABLE) | ||
820 | g->flags = GENHD_FL_REMOVABLE; | ||
821 | g->fops = &idefloppy_ops; | ||
822 | add_disk(g); | ||
823 | return 0; | ||
824 | |||
825 | out_free_floppy: | ||
826 | kfree(floppy); | ||
827 | failed: | ||
828 | return -ENODEV; | ||
829 | } | ||
830 | |||
831 | static void __exit idefloppy_exit(void) | ||
832 | { | ||
833 | driver_unregister(&idefloppy_driver.gen_driver); | ||
834 | } | ||
835 | |||
836 | static int __init idefloppy_init(void) | ||
837 | { | ||
838 | printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n"); | ||
839 | return driver_register(&idefloppy_driver.gen_driver); | ||
840 | } | ||
841 | |||
842 | MODULE_ALIAS("ide:*m-floppy*"); | ||
843 | MODULE_ALIAS("ide-floppy"); | ||
844 | module_init(idefloppy_init); | ||
845 | module_exit(idefloppy_exit); | ||
846 | MODULE_LICENSE("GPL"); | ||
847 | MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); | ||
848 | |||
diff --git a/drivers/ide/ide-floppy.h b/drivers/ide/ide-floppy.h index 17cf865e583d..836a70e6e3ef 100644 --- a/drivers/ide/ide-floppy.h +++ b/drivers/ide/ide-floppy.h | |||
@@ -1,6 +1,18 @@ | |||
1 | #ifndef __IDE_FLOPPY_H | 1 | #ifndef __IDE_FLOPPY_H |
2 | #define __IDE_FLOPPY_H | 2 | #define __IDE_FLOPPY_H |
3 | 3 | ||
4 | #define DRV_NAME "ide-floppy" | ||
5 | #define PFX DRV_NAME ": " | ||
6 | |||
7 | /* define to see debug info */ | ||
8 | #define IDEFLOPPY_DEBUG_LOG 0 | ||
9 | |||
10 | #if IDEFLOPPY_DEBUG_LOG | ||
11 | #define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) | ||
12 | #else | ||
13 | #define ide_debug_log(lvl, fmt, args...) do {} while (0) | ||
14 | #endif | ||
15 | |||
4 | /* | 16 | /* |
5 | * Most of our global data which we need to save even as we leave the driver | 17 | * Most of our global data which we need to save even as we leave the driver |
6 | * due to an interrupt or a timer event is stored in a variable of type | 18 | * due to an interrupt or a timer event is stored in a variable of type |
@@ -45,10 +57,15 @@ typedef struct ide_floppy_obj { | |||
45 | #define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 | 57 | #define IDEFLOPPY_IOCTL_FORMAT_START 0x4602 |
46 | #define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 | 58 | #define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603 |
47 | 59 | ||
60 | sector_t ide_floppy_capacity(ide_drive_t *); | ||
61 | |||
48 | /* ide-floppy.c */ | 62 | /* ide-floppy.c */ |
49 | void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8); | 63 | void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8); |
50 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *); | 64 | void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *); |
51 | sector_t ide_floppy_capacity(ide_drive_t *); | 65 | int ide_floppy_get_capacity(ide_drive_t *); |
66 | void ide_floppy_setup(ide_drive_t *); | ||
67 | ide_startstop_t ide_floppy_do_request(ide_drive_t *, struct request *, sector_t); | ||
68 | int ide_floppy_end_request(ide_drive_t *, int, int); | ||
52 | 69 | ||
53 | /* ide-floppy_ioctl.c */ | 70 | /* ide-floppy_ioctl.c */ |
54 | int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long); | 71 | int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long); |
diff --git a/drivers/ide/ide-gd-floppy.c b/drivers/ide/ide-gd-floppy.c new file mode 100644 index 000000000000..7afd013b4c55 --- /dev/null +++ b/drivers/ide/ide-gd-floppy.c | |||
@@ -0,0 +1,298 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <linux/string.h> | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/errno.h> | ||
6 | #include <linux/genhd.h> | ||
7 | #include <linux/mutex.h> | ||
8 | #include <linux/ide.h> | ||
9 | #include <linux/hdreg.h> | ||
10 | |||
11 | #include "ide-floppy.h" | ||
12 | |||
13 | #define IDEFLOPPY_VERSION "1.00" | ||
14 | |||
15 | /* module parameters */ | ||
16 | static unsigned long debug_mask; | ||
17 | module_param(debug_mask, ulong, 0644); | ||
18 | |||
19 | static DEFINE_MUTEX(idefloppy_ref_mutex); | ||
20 | |||
21 | static void idefloppy_cleanup_obj(struct kref *); | ||
22 | |||
23 | static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk) | ||
24 | { | ||
25 | struct ide_floppy_obj *floppy = NULL; | ||
26 | |||
27 | mutex_lock(&idefloppy_ref_mutex); | ||
28 | floppy = ide_drv_g(disk, ide_floppy_obj); | ||
29 | if (floppy) { | ||
30 | if (ide_device_get(floppy->drive)) | ||
31 | floppy = NULL; | ||
32 | else | ||
33 | kref_get(&floppy->kref); | ||
34 | } | ||
35 | mutex_unlock(&idefloppy_ref_mutex); | ||
36 | return floppy; | ||
37 | } | ||
38 | |||
39 | static void ide_floppy_put(struct ide_floppy_obj *floppy) | ||
40 | { | ||
41 | ide_drive_t *drive = floppy->drive; | ||
42 | |||
43 | mutex_lock(&idefloppy_ref_mutex); | ||
44 | kref_put(&floppy->kref, idefloppy_cleanup_obj); | ||
45 | ide_device_put(drive); | ||
46 | mutex_unlock(&idefloppy_ref_mutex); | ||
47 | } | ||
48 | |||
49 | sector_t ide_floppy_capacity(ide_drive_t *drive) | ||
50 | { | ||
51 | return drive->capacity64; | ||
52 | } | ||
53 | |||
54 | static void ide_floppy_remove(ide_drive_t *drive) | ||
55 | { | ||
56 | idefloppy_floppy_t *floppy = drive->driver_data; | ||
57 | struct gendisk *g = floppy->disk; | ||
58 | |||
59 | ide_proc_unregister_driver(drive, floppy->driver); | ||
60 | |||
61 | del_gendisk(g); | ||
62 | |||
63 | ide_floppy_put(floppy); | ||
64 | } | ||
65 | |||
66 | static void idefloppy_cleanup_obj(struct kref *kref) | ||
67 | { | ||
68 | struct ide_floppy_obj *floppy = to_ide_drv(kref, ide_floppy_obj); | ||
69 | ide_drive_t *drive = floppy->drive; | ||
70 | struct gendisk *g = floppy->disk; | ||
71 | |||
72 | drive->driver_data = NULL; | ||
73 | g->private_data = NULL; | ||
74 | put_disk(g); | ||
75 | kfree(floppy); | ||
76 | } | ||
77 | |||
78 | static int ide_floppy_probe(ide_drive_t *); | ||
79 | |||
80 | static ide_driver_t idefloppy_driver = { | ||
81 | .gen_driver = { | ||
82 | .owner = THIS_MODULE, | ||
83 | .name = "ide-floppy", | ||
84 | .bus = &ide_bus_type, | ||
85 | }, | ||
86 | .probe = ide_floppy_probe, | ||
87 | .remove = ide_floppy_remove, | ||
88 | .version = IDEFLOPPY_VERSION, | ||
89 | .do_request = ide_floppy_do_request, | ||
90 | .end_request = ide_floppy_end_request, | ||
91 | .error = __ide_error, | ||
92 | #ifdef CONFIG_IDE_PROC_FS | ||
93 | .proc = ide_floppy_proc, | ||
94 | .settings = ide_floppy_settings, | ||
95 | #endif | ||
96 | }; | ||
97 | |||
98 | static int idefloppy_open(struct inode *inode, struct file *filp) | ||
99 | { | ||
100 | struct gendisk *disk = inode->i_bdev->bd_disk; | ||
101 | struct ide_floppy_obj *floppy; | ||
102 | ide_drive_t *drive; | ||
103 | int ret = 0; | ||
104 | |||
105 | floppy = ide_floppy_get(disk); | ||
106 | if (!floppy) | ||
107 | return -ENXIO; | ||
108 | |||
109 | drive = floppy->drive; | ||
110 | |||
111 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
112 | |||
113 | floppy->openers++; | ||
114 | |||
115 | if (floppy->openers == 1) { | ||
116 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
117 | /* Just in case */ | ||
118 | |||
119 | if (ide_do_test_unit_ready(drive, disk)) | ||
120 | ide_do_start_stop(drive, disk, 1); | ||
121 | |||
122 | ret = ide_floppy_get_capacity(drive); | ||
123 | |||
124 | set_capacity(disk, ide_floppy_capacity(drive)); | ||
125 | |||
126 | if (ret && (filp->f_flags & O_NDELAY) == 0) { | ||
127 | /* | ||
128 | * Allow O_NDELAY to open a drive without a disk, or with an | ||
129 | * unreadable disk, so that we can get the format capacity | ||
130 | * of the drive or begin the format - Sam | ||
131 | */ | ||
132 | ret = -EIO; | ||
133 | goto out_put_floppy; | ||
134 | } | ||
135 | |||
136 | if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) { | ||
137 | ret = -EROFS; | ||
138 | goto out_put_floppy; | ||
139 | } | ||
140 | |||
141 | ide_set_media_lock(drive, disk, 1); | ||
142 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; | ||
143 | check_disk_change(inode->i_bdev); | ||
144 | } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) { | ||
145 | ret = -EBUSY; | ||
146 | goto out_put_floppy; | ||
147 | } | ||
148 | return 0; | ||
149 | |||
150 | out_put_floppy: | ||
151 | floppy->openers--; | ||
152 | ide_floppy_put(floppy); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | static int idefloppy_release(struct inode *inode, struct file *filp) | ||
157 | { | ||
158 | struct gendisk *disk = inode->i_bdev->bd_disk; | ||
159 | struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj); | ||
160 | ide_drive_t *drive = floppy->drive; | ||
161 | |||
162 | ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__); | ||
163 | |||
164 | if (floppy->openers == 1) { | ||
165 | ide_set_media_lock(drive, disk, 0); | ||
166 | drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; | ||
167 | } | ||
168 | |||
169 | floppy->openers--; | ||
170 | |||
171 | ide_floppy_put(floppy); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
177 | { | ||
178 | struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk, | ||
179 | ide_floppy_obj); | ||
180 | ide_drive_t *drive = floppy->drive; | ||
181 | |||
182 | geo->heads = drive->bios_head; | ||
183 | geo->sectors = drive->bios_sect; | ||
184 | geo->cylinders = (u16)drive->bios_cyl; /* truncate */ | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int idefloppy_media_changed(struct gendisk *disk) | ||
189 | { | ||
190 | struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj); | ||
191 | ide_drive_t *drive = floppy->drive; | ||
192 | int ret; | ||
193 | |||
194 | /* do not scan partitions twice if this is a removable device */ | ||
195 | if (drive->dev_flags & IDE_DFLAG_ATTACH) { | ||
196 | drive->dev_flags &= ~IDE_DFLAG_ATTACH; | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED); | ||
201 | drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED; | ||
202 | |||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | static int idefloppy_revalidate_disk(struct gendisk *disk) | ||
207 | { | ||
208 | struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj); | ||
209 | set_capacity(disk, ide_floppy_capacity(floppy->drive)); | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static struct block_device_operations idefloppy_ops = { | ||
214 | .owner = THIS_MODULE, | ||
215 | .open = idefloppy_open, | ||
216 | .release = idefloppy_release, | ||
217 | .ioctl = ide_floppy_ioctl, | ||
218 | .getgeo = idefloppy_getgeo, | ||
219 | .media_changed = idefloppy_media_changed, | ||
220 | .revalidate_disk = idefloppy_revalidate_disk | ||
221 | }; | ||
222 | |||
223 | static int ide_floppy_probe(ide_drive_t *drive) | ||
224 | { | ||
225 | idefloppy_floppy_t *floppy; | ||
226 | struct gendisk *g; | ||
227 | |||
228 | if (!strstr("ide-floppy", drive->driver_req)) | ||
229 | goto failed; | ||
230 | |||
231 | if (drive->media != ide_floppy) | ||
232 | goto failed; | ||
233 | |||
234 | if (!ide_check_atapi_device(drive, DRV_NAME)) { | ||
235 | printk(KERN_ERR PFX "%s: not supported by this version of " | ||
236 | DRV_NAME "\n", drive->name); | ||
237 | goto failed; | ||
238 | } | ||
239 | floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL); | ||
240 | if (!floppy) { | ||
241 | printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n", | ||
242 | drive->name); | ||
243 | goto failed; | ||
244 | } | ||
245 | |||
246 | g = alloc_disk_node(1 << PARTN_BITS, hwif_to_node(drive->hwif)); | ||
247 | if (!g) | ||
248 | goto out_free_floppy; | ||
249 | |||
250 | ide_init_disk(g, drive); | ||
251 | |||
252 | kref_init(&floppy->kref); | ||
253 | |||
254 | floppy->drive = drive; | ||
255 | floppy->driver = &idefloppy_driver; | ||
256 | floppy->disk = g; | ||
257 | |||
258 | g->private_data = &floppy->driver; | ||
259 | |||
260 | drive->driver_data = floppy; | ||
261 | |||
262 | drive->debug_mask = debug_mask; | ||
263 | |||
264 | ide_floppy_setup(drive); | ||
265 | |||
266 | set_capacity(g, ide_floppy_capacity(drive)); | ||
267 | |||
268 | g->minors = 1 << PARTN_BITS; | ||
269 | g->driverfs_dev = &drive->gendev; | ||
270 | if (drive->dev_flags & IDE_DFLAG_REMOVABLE) | ||
271 | g->flags = GENHD_FL_REMOVABLE; | ||
272 | g->fops = &idefloppy_ops; | ||
273 | add_disk(g); | ||
274 | return 0; | ||
275 | |||
276 | out_free_floppy: | ||
277 | kfree(floppy); | ||
278 | failed: | ||
279 | return -ENODEV; | ||
280 | } | ||
281 | |||
282 | static int __init idefloppy_init(void) | ||
283 | { | ||
284 | printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n"); | ||
285 | return driver_register(&idefloppy_driver.gen_driver); | ||
286 | } | ||
287 | |||
288 | static void __exit idefloppy_exit(void) | ||
289 | { | ||
290 | driver_unregister(&idefloppy_driver.gen_driver); | ||
291 | } | ||
292 | |||
293 | MODULE_ALIAS("ide:*m-floppy*"); | ||
294 | MODULE_ALIAS("ide-floppy"); | ||
295 | module_init(idefloppy_init); | ||
296 | module_exit(idefloppy_exit); | ||
297 | MODULE_LICENSE("GPL"); | ||
298 | MODULE_DESCRIPTION("ATAPI FLOPPY Driver"); | ||