Blame view
drivers/ide/ide-floppy_ioctl.c
7.21 KB
0127854d7 ide-floppy: move ... |
1 2 3 4 5 6 7 |
/* * ide-floppy IOCTLs handling. */ #include <linux/kernel.h> #include <linux/ide.h> #include <linux/cdrom.h> |
2a48fc0ab block: autoconver... |
8 |
#include <linux/mutex.h> |
0127854d7 ide-floppy: move ... |
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include <asm/unaligned.h> #include <scsi/scsi_ioctl.h> #include "ide-floppy.h" /* * Obtain the list of formattable capacities. * Very similar to ide_floppy_get_capacity, except that we push the capacity * descriptors to userland, instead of our own structures. * * Userland gives us the following structure: * * struct idefloppy_format_capacities { * int nformats; * struct { * int nblocks; * int blocksize; * } formats[]; * }; * * userland initializes nformats to the number of allocated formats[] records. * On exit we set nformats to the number of records we've actually initialized. */ |
2a48fc0ab block: autoconver... |
34 |
static DEFINE_MUTEX(ide_floppy_ioctl_mutex); |
07bd3f473 ide-floppy: alloc... |
35 36 37 |
static int ide_floppy_get_format_capacities(ide_drive_t *drive, struct ide_atapi_pc *pc, int __user *arg) |
0127854d7 ide-floppy: move ... |
38 |
{ |
806f80a6f ide: add generic ... |
39 |
struct ide_disk_obj *floppy = drive->driver_data; |
0127854d7 ide-floppy: move ... |
40 41 |
int i, blocks, length, u_array_size, u_index; int __user *argp; |
41fa9f863 ide: decrease siz... |
42 |
u8 pc_buf[256], header_len, desc_cnt; |
0127854d7 ide-floppy: move ... |
43 44 45 46 47 48 |
if (get_user(u_array_size, arg)) return -EFAULT; if (u_array_size <= 0) return -EINVAL; |
07bd3f473 ide-floppy: alloc... |
49 |
ide_floppy_create_read_capacity_cmd(pc); |
41fa9f863 ide: decrease siz... |
50 |
|
b13345f39 ide-atapi: add a ... |
51 |
if (ide_queue_pc_tail(drive, floppy->disk, pc, pc_buf, pc->req_xfer)) { |
0127854d7 ide-floppy: move ... |
52 53 54 55 |
printk(KERN_ERR "ide-floppy: Can't get floppy parameters "); return -EIO; } |
b13345f39 ide-atapi: add a ... |
56 |
header_len = pc_buf[3]; |
0127854d7 ide-floppy: move ... |
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ u_index = 0; argp = arg + 1; /* * We always skip the first capacity descriptor. That's the current * capacity. We are interested in the remaining descriptors, the * formattable capacities. */ for (i = 1; i < desc_cnt; i++) { unsigned int desc_start = 4 + i*8; if (u_index >= u_array_size) break; /* User-supplied buffer too small */ |
b13345f39 ide-atapi: add a ... |
72 73 |
blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]); length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]); |
0127854d7 ide-floppy: move ... |
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
if (put_user(blocks, argp)) return -EFAULT; ++argp; if (put_user(length, argp)) return -EFAULT; ++argp; ++u_index; } if (put_user(u_index, arg)) return -EFAULT; return 0; } |
5122e5174 ide-floppy/ide_fl... |
93 94 95 |
static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, u8 *buf, int b, int l, int flags) |
0127854d7 ide-floppy: move ... |
96 97 98 99 |
{ ide_init_pc(pc); pc->c[0] = GPCMD_FORMAT_UNIT; pc->c[1] = 0x17; |
5122e5174 ide-floppy/ide_fl... |
100 101 |
memset(buf, 0, 12); buf[1] = 0xA2; |
0127854d7 ide-floppy: move ... |
102 103 104 |
/* Default format list header, u8 1: FOV/DCRT/IMM bits set */ if (flags & 1) /* Verify bit on... */ |
5122e5174 ide-floppy/ide_fl... |
105 106 |
buf[1] ^= 0x20; /* ... turn off DCRT bit */ buf[3] = 8; |
0127854d7 ide-floppy: move ... |
107 |
|
5122e5174 ide-floppy/ide_fl... |
108 109 110 |
put_unaligned(cpu_to_be32(b), (unsigned int *)(&buf[4])); put_unaligned(cpu_to_be32(l), (unsigned int *)(&buf[8])); pc->req_xfer = 12; |
0127854d7 ide-floppy: move ... |
111 112 |
pc->flags |= PC_FLAG_WRITING; } |
07bd3f473 ide-floppy: alloc... |
113 |
static int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc) |
0127854d7 ide-floppy: move ... |
114 |
{ |
0df962777 ide-floppy: remov... |
115 |
struct ide_disk_obj *floppy = drive->driver_data; |
802e66342 ide-floppy/ide_fl... |
116 |
u8 buf[20]; |
0127854d7 ide-floppy: move ... |
117 118 |
drive->atapi_flags &= ~IDE_AFLAG_SRFP; |
07bd3f473 ide-floppy: alloc... |
119 120 |
ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE); pc->flags |= PC_FLAG_SUPPRESS_ERROR; |
0127854d7 ide-floppy: move ... |
121 |
|
802e66342 ide-floppy/ide_fl... |
122 |
if (ide_queue_pc_tail(drive, floppy->disk, pc, buf, pc->req_xfer)) |
0127854d7 ide-floppy: move ... |
123 |
return 1; |
802e66342 ide-floppy/ide_fl... |
124 |
if (buf[8 + 2] & 0x40) |
0127854d7 ide-floppy: move ... |
125 126 127 128 |
drive->atapi_flags |= IDE_AFLAG_SRFP; return 0; } |
07bd3f473 ide-floppy: alloc... |
129 130 |
static int ide_floppy_format_unit(ide_drive_t *drive, struct ide_atapi_pc *pc, int __user *arg) |
0127854d7 ide-floppy: move ... |
131 |
{ |
0df962777 ide-floppy: remov... |
132 |
struct ide_disk_obj *floppy = drive->driver_data; |
5122e5174 ide-floppy/ide_fl... |
133 |
u8 buf[12]; |
0127854d7 ide-floppy: move ... |
134 135 136 137 |
int blocks, length, flags, err = 0; if (floppy->openers > 1) { /* Don't format if someone is using the disk */ |
e01286282 ide: IDE_AFLAG_FO... |
138 |
drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; |
0127854d7 ide-floppy: move ... |
139 140 |
return -EBUSY; } |
e01286282 ide: IDE_AFLAG_FO... |
141 |
drive->dev_flags |= IDE_DFLAG_FORMAT_IN_PROGRESS; |
0127854d7 ide-floppy: move ... |
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
/* * Send ATAPI_FORMAT_UNIT to the drive. * * Userland gives us the following structure: * * struct idefloppy_format_command { * int nblocks; * int blocksize; * int flags; * } ; * * flags is a bitmask, currently, the only defined flag is: * * 0x01 - verify media after format. */ if (get_user(blocks, arg) || get_user(length, arg+1) || get_user(flags, arg+2)) { err = -EFAULT; goto out; } |
07bd3f473 ide-floppy: alloc... |
164 |
ide_floppy_get_sfrp_bit(drive, pc); |
5122e5174 ide-floppy/ide_fl... |
165 |
ide_floppy_create_format_unit_cmd(pc, buf, blocks, length, flags); |
0127854d7 ide-floppy: move ... |
166 |
|
5122e5174 ide-floppy/ide_fl... |
167 |
if (ide_queue_pc_tail(drive, floppy->disk, pc, buf, pc->req_xfer)) |
0127854d7 ide-floppy: move ... |
168 169 170 171 |
err = -EIO; out: if (err) |
e01286282 ide: IDE_AFLAG_FO... |
172 |
drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS; |
0127854d7 ide-floppy: move ... |
173 174 175 176 177 178 179 180 181 182 183 184 |
return err; } /* * Get ATAPI_FORMAT_UNIT progress indication. * * Userland gives a pointer to an int. The int is set to a progress * indicator 0-65536, with 65536=100%. * * If the drive does not support format progress indication, we just check * the dsc bit, and return either 0 or 65536. */ |
07bd3f473 ide-floppy: alloc... |
185 186 187 |
static int ide_floppy_get_format_progress(ide_drive_t *drive, struct ide_atapi_pc *pc, int __user *arg) |
0127854d7 ide-floppy: move ... |
188 |
{ |
0df962777 ide-floppy: remov... |
189 |
struct ide_disk_obj *floppy = drive->driver_data; |
60cfab85d ide-floppy/ide_fl... |
190 |
u8 sense_buf[18]; |
0127854d7 ide-floppy: move ... |
191 192 193 |
int progress_indication = 0x10000; if (drive->atapi_flags & IDE_AFLAG_SRFP) { |
07bd3f473 ide-floppy: alloc... |
194 |
ide_create_request_sense_cmd(drive, pc); |
60cfab85d ide-floppy/ide_fl... |
195 |
if (ide_queue_pc_tail(drive, floppy->disk, pc, sense_buf, |
b13345f39 ide-atapi: add a ... |
196 |
pc->req_xfer)) |
0127854d7 ide-floppy: move ... |
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
return -EIO; if (floppy->sense_key == 2 && floppy->asc == 4 && floppy->ascq == 4) progress_indication = floppy->progress_indication; /* Else assume format_unit has finished, and we're at 0x10000 */ } else { ide_hwif_t *hwif = drive->hwif; unsigned long flags; u8 stat; local_irq_save(flags); stat = hwif->tp_ops->read_status(hwif); local_irq_restore(flags); progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000; } if (put_user(progress_indication, arg)) return -EFAULT; return 0; } |
5bb1536a0 ide-floppy: move ... |
222 223 224 |
static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd) { |
0df962777 ide-floppy: remov... |
225 |
struct ide_disk_obj *floppy = drive->driver_data; |
5bb1536a0 ide-floppy: move ... |
226 227 228 229 230 231 232 233 234 235 236 237 238 |
struct gendisk *disk = floppy->disk; int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0; if (floppy->openers > 1) return -EBUSY; ide_set_media_lock(drive, disk, prevent); if (cmd == CDROMEJECT) ide_do_start_stop(drive, disk, 2); return 0; } |
07bd3f473 ide-floppy: alloc... |
239 240 241 |
static int ide_floppy_format_ioctl(ide_drive_t *drive, struct ide_atapi_pc *pc, fmode_t mode, unsigned int cmd, void __user *argp) |
0127854d7 ide-floppy: move ... |
242 243 244 245 246 |
{ switch (cmd) { case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: return 0; case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: |
07bd3f473 ide-floppy: alloc... |
247 |
return ide_floppy_get_format_capacities(drive, pc, argp); |
0127854d7 ide-floppy: move ... |
248 |
case IDEFLOPPY_IOCTL_FORMAT_START: |
badf8082c [PATCH] switch id... |
249 |
if (!(mode & FMODE_WRITE)) |
0127854d7 ide-floppy: move ... |
250 |
return -EPERM; |
07bd3f473 ide-floppy: alloc... |
251 |
return ide_floppy_format_unit(drive, pc, (int __user *)argp); |
0127854d7 ide-floppy: move ... |
252 |
case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: |
07bd3f473 ide-floppy: alloc... |
253 |
return ide_floppy_get_format_progress(drive, pc, argp); |
0127854d7 ide-floppy: move ... |
254 255 256 257 |
default: return -ENOTTY; } } |
5bb1536a0 ide-floppy: move ... |
258 |
|
badf8082c [PATCH] switch id... |
259 260 |
int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) |
5bb1536a0 ide-floppy: move ... |
261 |
{ |
5bb1536a0 ide-floppy: move ... |
262 263 264 |
struct ide_atapi_pc pc; void __user *argp = (void __user *)arg; int err; |
2a48fc0ab block: autoconver... |
265 |
mutex_lock(&ide_floppy_ioctl_mutex); |
8a6cfeb6d block: push down ... |
266 267 268 269 |
if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) { err = ide_floppy_lockdoor(drive, &pc, arg, cmd); goto out; } |
5bb1536a0 ide-floppy: move ... |
270 |
|
07bd3f473 ide-floppy: alloc... |
271 |
err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp); |
5bb1536a0 ide-floppy: move ... |
272 |
if (err != -ENOTTY) |
8a6cfeb6d block: push down ... |
273 |
goto out; |
5bb1536a0 ide-floppy: move ... |
274 275 276 277 278 279 |
/* * skip SCSI_IOCTL_SEND_COMMAND (deprecated) * and CDROM_SEND_PACKET (legacy) ioctls */ if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) |
577ebb374 block: add and us... |
280 |
err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp); |
5bb1536a0 ide-floppy: move ... |
281 282 |
if (err == -ENOTTY) |
1bddd9e64 [PATCH] lose the ... |
283 |
err = generic_ide_ioctl(drive, bdev, cmd, arg); |
5bb1536a0 ide-floppy: move ... |
284 |
|
8a6cfeb6d block: push down ... |
285 |
out: |
2a48fc0ab block: autoconver... |
286 |
mutex_unlock(&ide_floppy_ioctl_mutex); |
5bb1536a0 ide-floppy: move ... |
287 288 |
return err; } |