diff options
Diffstat (limited to 'drivers/ide/ide-floppy.c')
-rw-r--r-- | drivers/ide/ide-floppy.c | 319 |
1 files changed, 10 insertions, 309 deletions
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 | |||