aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-floppy.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:38 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:38 -0400
commit0127854d7c96612a454bed6de242e28f8021fa7f (patch)
tree32aef08c4908b511c732d32f50a688ef14a4d0a2 /drivers/ide/ide-floppy.c
parent49cac39e71bd6bbcf934c6ba837e21503902c088 (diff)
ide-floppy: move floppy ioctls handling to ide-floppy_ioctl.c
While at it: - idefloppy_create_read_capacity_cmd() -> ide_floppy_create_read_capacity_cmd() - idefloppy_create_mode_sense_cmd() -> ide_floppy_create_mode_sense_cmd() - idefloppy_create_request_sense_cmd() -> ide_floppy_create_request_sense_cmd() - idefloppy_create_format_unit_cmd() -> ide_floppy_create_format_unit_cmd() - idefloppy_get_sfrp_bit() -> ide_floppy_get_sfrp_bit() Acked-by: Borislav Petkov <petkovbb@gmail.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-floppy.c')
-rw-r--r--drivers/ide/ide-floppy.c296
1 files changed, 9 insertions, 287 deletions
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 78d92835a3c1..ca12a230d9a6 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -46,6 +46,8 @@
46#include <linux/io.h> 46#include <linux/io.h>
47#include <asm/unaligned.h> 47#include <asm/unaligned.h>
48 48
49#include "ide-floppy.h"
50
49/* define to see debug info */ 51/* define to see debug info */
50#define IDEFLOPPY_DEBUG_LOG 0 52#define IDEFLOPPY_DEBUG_LOG 0
51 53
@@ -75,61 +77,11 @@
75#define CAPACITY_CURRENT 0x02 77#define CAPACITY_CURRENT 0x02
76#define CAPACITY_NO_CARTRIDGE 0x03 78#define CAPACITY_NO_CARTRIDGE 0x03
77 79
78/*
79 * Most of our global data which we need to save even as we leave the driver
80 * due to an interrupt or a timer event is stored in a variable of type
81 * idefloppy_floppy_t, defined below.
82 */
83typedef struct ide_floppy_obj {
84 ide_drive_t *drive;
85 ide_driver_t *driver;
86 struct gendisk *disk;
87 struct kref kref;
88 unsigned int openers; /* protected by BKL for now */
89
90 /* Current packet command */
91 struct ide_atapi_pc *pc;
92 /* Last failed packet command */
93 struct ide_atapi_pc *failed_pc;
94 /* used for blk_{fs,pc}_request() requests */
95 struct ide_atapi_pc queued_pc;
96
97 struct ide_atapi_pc request_sense_pc;
98 struct request request_sense_rq;
99
100 /* Last error information */
101 u8 sense_key, asc, ascq;
102 /* delay this long before sending packet command */
103 u8 ticks;
104 int progress_indication;
105
106 /* Device information */
107 /* Current format */
108 int blocks, block_size, bs_factor;
109 /* Last format capacity descriptor */
110 u8 cap_desc[8];
111 /* Copy of the flexible disk page */
112 u8 flexible_disk_page[32];
113} idefloppy_floppy_t;
114
115#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */ 80#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
116 81
117/* IOCTLs used in low-level formatting. */
118#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600
119#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601
120#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602
121#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603
122
123/* Error code returned in rq->errors to the higher part of the driver. */ 82/* Error code returned in rq->errors to the higher part of the driver. */
124#define IDEFLOPPY_ERROR_GENERAL 101 83#define IDEFLOPPY_ERROR_GENERAL 101
125 84
126/*
127 * Pages of the SELECT SENSE / MODE SENSE packet commands.
128 * See SFF-8070i spec.
129 */
130#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b
131#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05
132
133static DEFINE_MUTEX(idefloppy_ref_mutex); 85static DEFINE_MUTEX(idefloppy_ref_mutex);
134 86
135#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref) 87#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
@@ -245,7 +197,7 @@ static void ide_floppy_callback(ide_drive_t *drive)
245 idefloppy_end_request(drive, uptodate, 0); 197 idefloppy_end_request(drive, uptodate, 0);
246} 198}
247 199
248static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc) 200void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
249{ 201{
250 ide_init_pc(pc); 202 ide_init_pc(pc);
251 pc->c[0] = GPCMD_REQUEST_SENSE; 203 pc->c[0] = GPCMD_REQUEST_SENSE;
@@ -264,7 +216,7 @@ static void idefloppy_retry_pc(ide_drive_t *drive)
264 struct ide_atapi_pc *pc = &floppy->request_sense_pc; 216 struct ide_atapi_pc *pc = &floppy->request_sense_pc;
265 217
266 (void)ide_read_error(drive); 218 (void)ide_read_error(drive);
267 idefloppy_create_request_sense_cmd(pc); 219 ide_floppy_create_request_sense_cmd(pc);
268 ide_queue_pc_head(drive, floppy->disk, pc, rq); 220 ide_queue_pc_head(drive, floppy->disk, pc, rq);
269} 221}
270 222
@@ -382,7 +334,7 @@ static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent)
382 pc->c[4] = prevent; 334 pc->c[4] = prevent;
383} 335}
384 336
385static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) 337void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
386{ 338{
387 ide_init_pc(pc); 339 ide_init_pc(pc);
388 pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES; 340 pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
@@ -391,30 +343,8 @@ static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
391 pc->req_xfer = 255; 343 pc->req_xfer = 255;
392} 344}
393 345
394static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
395 int l, int flags)
396{
397 ide_init_pc(pc);
398 pc->c[0] = GPCMD_FORMAT_UNIT;
399 pc->c[1] = 0x17;
400
401 memset(pc->buf, 0, 12);
402 pc->buf[1] = 0xA2;
403 /* Default format list header, u8 1: FOV/DCRT/IMM bits set */
404
405 if (flags & 1) /* Verify bit on... */
406 pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */
407 pc->buf[3] = 8;
408
409 put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
410 put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
411 pc->buf_size = 12;
412 pc->flags |= PC_FLAG_WRITING;
413}
414
415/* A mode sense command is used to "sense" floppy parameters. */ 346/* A mode sense command is used to "sense" floppy parameters. */
416static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, 347void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
417 u8 page_code)
418{ 348{
419 u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ 349 u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
420 350
@@ -563,7 +493,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
563 u16 transfer_rate, sector_size, cyls, rpm; 493 u16 transfer_rate, sector_size, cyls, rpm;
564 u8 heads, sectors; 494 u8 heads, sectors;
565 495
566 idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); 496 ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
567 497
568 if (ide_queue_pc_tail(drive, disk, &pc)) { 498 if (ide_queue_pc_tail(drive, disk, &pc)) {
569 printk(KERN_ERR "ide-floppy: Can't get flexible disk page" 499 printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
@@ -611,25 +541,6 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
611 return 0; 541 return 0;
612} 542}
613 543
614static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
615{
616 idefloppy_floppy_t *floppy = drive->driver_data;
617 struct ide_atapi_pc pc;
618
619 drive->atapi_flags &= ~IDE_AFLAG_SRFP;
620
621 idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);
622 pc.flags |= PC_FLAG_SUPPRESS_ERROR;
623
624 if (ide_queue_pc_tail(drive, floppy->disk, &pc))
625 return 1;
626
627 if (pc.buf[8 + 2] & 0x40)
628 drive->atapi_flags |= IDE_AFLAG_SRFP;
629
630 return 0;
631}
632
633/* 544/*
634 * Determine if a media is present in the floppy drive, and if so, its LBA 545 * Determine if a media is present in the floppy drive, and if so, its LBA
635 * capacity. 546 * capacity.
@@ -649,7 +560,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
649 floppy->bs_factor = 1; 560 floppy->bs_factor = 1;
650 set_capacity(floppy->disk, 0); 561 set_capacity(floppy->disk, 0);
651 562
652 idefloppy_create_read_capacity_cmd(&pc); 563 ide_floppy_create_read_capacity_cmd(&pc);
653 if (ide_queue_pc_tail(drive, disk, &pc)) { 564 if (ide_queue_pc_tail(drive, disk, &pc)) {
654 printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); 565 printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
655 return 1; 566 return 1;
@@ -730,129 +641,6 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
730 return rc; 641 return rc;
731} 642}
732 643
733/*
734 * Obtain the list of formattable capacities.
735 * Very similar to ide_floppy_get_capacity, except that we push the capacity
736 * descriptors to userland, instead of our own structures.
737 *
738 * Userland gives us the following structure:
739 *
740 * struct idefloppy_format_capacities {
741 * int nformats;
742 * struct {
743 * int nblocks;
744 * int blocksize;
745 * } formats[];
746 * };
747 *
748 * userland initializes nformats to the number of allocated formats[] records.
749 * On exit we set nformats to the number of records we've actually initialized.
750 */
751
752static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
753{
754 struct ide_floppy_obj *floppy = drive->driver_data;
755 struct ide_atapi_pc pc;
756 u8 header_len, desc_cnt;
757 int i, blocks, length, u_array_size, u_index;
758 int __user *argp;
759
760 if (get_user(u_array_size, arg))
761 return -EFAULT;
762
763 if (u_array_size <= 0)
764 return -EINVAL;
765
766 idefloppy_create_read_capacity_cmd(&pc);
767 if (ide_queue_pc_tail(drive, floppy->disk, &pc)) {
768 printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
769 return -EIO;
770 }
771
772 header_len = pc.buf[3];
773 desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
774
775 u_index = 0;
776 argp = arg + 1;
777
778 /*
779 * We always skip the first capacity descriptor. That's the current
780 * capacity. We are interested in the remaining descriptors, the
781 * formattable capacities.
782 */
783 for (i = 1; i < desc_cnt; i++) {
784 unsigned int desc_start = 4 + i*8;
785
786 if (u_index >= u_array_size)
787 break; /* User-supplied buffer too small */
788
789 blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
790 length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
791
792 if (put_user(blocks, argp))
793 return -EFAULT;
794
795 ++argp;
796
797 if (put_user(length, argp))
798 return -EFAULT;
799
800 ++argp;
801
802 ++u_index;
803 }
804
805 if (put_user(u_index, arg))
806 return -EFAULT;
807
808 return 0;
809}
810
811/*
812 * Get ATAPI_FORMAT_UNIT progress indication.
813 *
814 * Userland gives a pointer to an int. The int is set to a progress
815 * indicator 0-65536, with 65536=100%.
816 *
817 * If the drive does not support format progress indication, we just check
818 * the dsc bit, and return either 0 or 65536.
819 */
820
821static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
822{
823 idefloppy_floppy_t *floppy = drive->driver_data;
824 struct ide_atapi_pc pc;
825 int progress_indication = 0x10000;
826
827 if (drive->atapi_flags & IDE_AFLAG_SRFP) {
828 idefloppy_create_request_sense_cmd(&pc);
829 if (ide_queue_pc_tail(drive, floppy->disk, &pc))
830 return -EIO;
831
832 if (floppy->sense_key == 2 &&
833 floppy->asc == 4 &&
834 floppy->ascq == 4)
835 progress_indication = floppy->progress_indication;
836
837 /* Else assume format_unit has finished, and we're at 0x10000 */
838 } else {
839 ide_hwif_t *hwif = drive->hwif;
840 unsigned long flags;
841 u8 stat;
842
843 local_irq_save(flags);
844 stat = hwif->tp_ops->read_status(hwif);
845 local_irq_restore(flags);
846
847 progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000;
848 }
849
850 if (put_user(progress_indication, arg))
851 return -EFAULT;
852
853 return 0;
854}
855
856static sector_t idefloppy_capacity(ide_drive_t *drive) 644static sector_t idefloppy_capacity(ide_drive_t *drive)
857{ 645{
858 idefloppy_floppy_t *floppy = drive->driver_data; 646 idefloppy_floppy_t *floppy = drive->driver_data;
@@ -1118,73 +906,6 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
1118 return 0; 906 return 0;
1119} 907}
1120 908
1121static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
1122{
1123 idefloppy_floppy_t *floppy = drive->driver_data;
1124 struct ide_atapi_pc pc;
1125 int blocks, length, flags, err = 0;
1126
1127 if (floppy->openers > 1) {
1128 /* Don't format if someone is using the disk */
1129 drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
1130 return -EBUSY;
1131 }
1132
1133 drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
1134
1135 /*
1136 * Send ATAPI_FORMAT_UNIT to the drive.
1137 *
1138 * Userland gives us the following structure:
1139 *
1140 * struct idefloppy_format_command {
1141 * int nblocks;
1142 * int blocksize;
1143 * int flags;
1144 * } ;
1145 *
1146 * flags is a bitmask, currently, the only defined flag is:
1147 *
1148 * 0x01 - verify media after format.
1149 */
1150 if (get_user(blocks, arg) ||
1151 get_user(length, arg+1) ||
1152 get_user(flags, arg+2)) {
1153 err = -EFAULT;
1154 goto out;
1155 }
1156
1157 (void) idefloppy_get_sfrp_bit(drive);
1158 idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
1159
1160 if (ide_queue_pc_tail(drive, floppy->disk, &pc))
1161 err = -EIO;
1162
1163out:
1164 if (err)
1165 drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
1166 return err;
1167}
1168
1169static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
1170 unsigned int cmd, void __user *argp)
1171{
1172 switch (cmd) {
1173 case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
1174 return 0;
1175 case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
1176 return ide_floppy_get_format_capacities(drive, argp);
1177 case IDEFLOPPY_IOCTL_FORMAT_START:
1178 if (!(file->f_mode & 2))
1179 return -EPERM;
1180 return ide_floppy_format_unit(drive, (int __user *)argp);
1181 case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
1182 return ide_floppy_get_format_progress(drive, argp);
1183 default:
1184 return -ENOTTY;
1185 }
1186}
1187
1188static int idefloppy_ioctl(struct inode *inode, struct file *file, 909static int idefloppy_ioctl(struct inode *inode, struct file *file,
1189 unsigned int cmd, unsigned long arg) 910 unsigned int cmd, unsigned long arg)
1190{ 911{
@@ -1316,6 +1037,7 @@ static int __init idefloppy_init(void)
1316} 1037}
1317 1038
1318MODULE_ALIAS("ide:*m-floppy*"); 1039MODULE_ALIAS("ide:*m-floppy*");
1040MODULE_ALIAS("ide-floppy");
1319module_init(idefloppy_init); 1041module_init(idefloppy_init);
1320module_exit(idefloppy_exit); 1042module_exit(idefloppy_exit);
1321MODULE_LICENSE("GPL"); 1043MODULE_LICENSE("GPL");