1/* 2 * IDE ioctls handling. 3 */ 4 5#include <linux/export.h> 6#include <linux/hdreg.h> 7#include <linux/ide.h> 8#include <linux/slab.h> 9 10static const struct ide_ioctl_devset ide_ioctl_settings[] = { 11{ HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit }, 12{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings }, 13{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq }, 14{ HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma }, 15{ -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode }, 16{ 0 } 17}; 18 19int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, 20 unsigned int cmd, unsigned long arg, 21 const struct ide_ioctl_devset *s) 22{ 23 const struct ide_devset *ds; 24 int err = -EOPNOTSUPP; 25 26 for (; (ds = s->setting); s++) { 27 if (ds->get && s->get_ioctl == cmd) 28 goto read_val; 29 else if (ds->set && s->set_ioctl == cmd) 30 goto set_val; 31 } 32 33 return err; 34 35read_val: 36 mutex_lock(&ide_setting_mtx); 37 err = ds->get(drive); 38 mutex_unlock(&ide_setting_mtx); 39 return err >= 0 ? put_user(err, (long __user *)arg) : err; 40 41set_val: 42 if (bdev != bdev->bd_contains) 43 err = -EINVAL; 44 else { 45 if (!capable(CAP_SYS_ADMIN)) 46 err = -EACCES; 47 else { 48 mutex_lock(&ide_setting_mtx); 49 err = ide_devset_execute(drive, ds, arg); 50 mutex_unlock(&ide_setting_mtx); 51 } 52 } 53 return err; 54} 55EXPORT_SYMBOL_GPL(ide_setting_ioctl); 56 57static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, 58 unsigned long arg) 59{ 60 u16 *id = NULL; 61 int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142; 62 int rc = 0; 63 64 if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { 65 rc = -ENOMSG; 66 goto out; 67 } 68 69 /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */ 70 id = kmalloc(ATA_ID_WORDS * 2, GFP_KERNEL); 71 if (id == NULL) { 72 rc = -ENOMEM; 73 goto out; 74 } 75 76 memcpy(id, drive->id, size); 77 ata_id_to_hd_driveid(id); 78 79 if (copy_to_user((void __user *)arg, id, size)) 80 rc = -EFAULT; 81 82 kfree(id); 83out: 84 return rc; 85} 86 87static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg) 88{ 89 return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) 90 << IDE_NICE_DSC_OVERLAP) | 91 (!!(drive->dev_flags & IDE_DFLAG_NICE1) 92 << IDE_NICE_1), (long __user *)arg); 93} 94 95static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) 96{ 97 if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) 98 return -EPERM; 99 100 if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) && 101 (drive->media != ide_tape)) 102 return -EPERM; 103 104 if ((arg >> IDE_NICE_DSC_OVERLAP) & 1) 105 drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP; 106 else 107 drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; 108 109 if ((arg >> IDE_NICE_1) & 1) 110 drive->dev_flags |= IDE_DFLAG_NICE1; 111 else 112 drive->dev_flags &= ~IDE_DFLAG_NICE1; 113 114 return 0; 115} 116 117static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) 118{ 119 u8 *buf = NULL; 120 int bufsize = 0, err = 0; 121 u8 args[4], xfer_rate = 0; 122 struct ide_cmd cmd; 123 struct ide_taskfile *tf = &cmd.tf; 124 125 if (NULL == (void *) arg) { 126 struct request *rq; 127 128 rq = blk_get_request(drive->queue, READ, __GFP_WAIT); 129 rq->cmd_type = REQ_TYPE_ATA_TASKFILE; 130 err = blk_execute_rq(drive->queue, NULL, rq, 0); 131 blk_put_request(rq); 132 133 return err; 134 } 135 136 if (copy_from_user(args, (void __user *)arg, 4)) 137 return -EFAULT; 138 139 memset(&cmd, 0, sizeof(cmd)); 140 tf->feature = args[2]; 141 if (args[0] == ATA_CMD_SMART) { 142 tf->nsect = args[3]; 143 tf->lbal = args[1]; 144 tf->lbam = ATA_SMART_LBAM_PASS; 145 tf->lbah = ATA_SMART_LBAH_PASS; 146 cmd.valid.out.tf = IDE_VALID_OUT_TF; 147 cmd.valid.in.tf = IDE_VALID_NSECT; 148 } else { 149 tf->nsect = args[1]; 150 cmd.valid.out.tf = IDE_VALID_FEATURE | IDE_VALID_NSECT; 151 cmd.valid.in.tf = IDE_VALID_NSECT; 152 } 153 tf->command = args[0]; 154 cmd.protocol = args[3] ? ATA_PROT_PIO : ATA_PROT_NODATA; 155 156 if (args[3]) { 157 cmd.tf_flags |= IDE_TFLAG_IO_16BIT; 158 bufsize = SECTOR_SIZE * args[3]; 159 buf = kzalloc(bufsize, GFP_KERNEL); 160 if (buf == NULL) 161 return -ENOMEM; 162 } 163 164 if (tf->command == ATA_CMD_SET_FEATURES && 165 tf->feature == SETFEATURES_XFER && 166 tf->nsect >= XFER_SW_DMA_0) { 167 xfer_rate = ide_find_dma_mode(drive, tf->nsect); 168 if (xfer_rate != tf->nsect) { 169 err = -EINVAL; 170 goto abort; 171 } 172 173 cmd.tf_flags |= IDE_TFLAG_SET_XFER; 174 } 175 176 err = ide_raw_taskfile(drive, &cmd, buf, args[3]); 177 178 args[0] = tf->status; 179 args[1] = tf->error; 180 args[2] = tf->nsect; 181abort: 182 if (copy_to_user((void __user *)arg, &args, 4)) 183 err = -EFAULT; 184 if (buf) { 185 if (copy_to_user((void __user *)(arg + 4), buf, bufsize)) 186 err = -EFAULT; 187 kfree(buf); 188 } 189 return err; 190} 191 192static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg) 193{ 194 void __user *p = (void __user *)arg; 195 int err = 0; 196 u8 args[7]; 197 struct ide_cmd cmd; 198 199 if (copy_from_user(args, p, 7)) 200 return -EFAULT; 201 202 memset(&cmd, 0, sizeof(cmd)); 203 memcpy(&cmd.tf.feature, &args[1], 6); 204 cmd.tf.command = args[0]; 205 cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; 206 cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; 207 208 err = ide_no_data_taskfile(drive, &cmd); 209 210 args[0] = cmd.tf.command; 211 memcpy(&args[1], &cmd.tf.feature, 6); 212 213 if (copy_to_user(p, args, 7)) 214 err = -EFAULT; 215 216 return err; 217} 218 219static int generic_drive_reset(ide_drive_t *drive) 220{ 221 struct request *rq; 222 int ret = 0; 223 224 rq = blk_get_request(drive->queue, READ, __GFP_WAIT); 225 rq->cmd_type = REQ_TYPE_SPECIAL; 226 rq->cmd_len = 1; 227 rq->cmd[0] = REQ_DRIVE_RESET; 228 if (blk_execute_rq(drive->queue, NULL, rq, 1)) 229 ret = rq->errors; 230 blk_put_request(rq); 231 return ret; 232} 233 234int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev, 235 unsigned int cmd, unsigned long arg) 236{ 237 int err; 238 239 err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings); 240 if (err != -EOPNOTSUPP) 241 return err; 242 243 switch (cmd) { 244 case HDIO_OBSOLETE_IDENTITY: 245 case HDIO_GET_IDENTITY: 246 if (bdev != bdev->bd_contains) 247 return -EINVAL; 248 return ide_get_identity_ioctl(drive, cmd, arg); 249 case HDIO_GET_NICE: 250 return ide_get_nice_ioctl(drive, arg); 251 case HDIO_SET_NICE: 252 if (!capable(CAP_SYS_ADMIN)) 253 return -EACCES; 254 return ide_set_nice_ioctl(drive, arg); 255#ifdef CONFIG_IDE_TASK_IOCTL 256 case HDIO_DRIVE_TASKFILE: 257 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 258 return -EACCES; 259 if (drive->media == ide_disk) 260 return ide_taskfile_ioctl(drive, arg); 261 return -ENOMSG; 262#endif 263 case HDIO_DRIVE_CMD: 264 if (!capable(CAP_SYS_RAWIO)) 265 return -EACCES; 266 return ide_cmd_ioctl(drive, arg); 267 case HDIO_DRIVE_TASK: 268 if (!capable(CAP_SYS_RAWIO)) 269 return -EACCES; 270 return ide_task_ioctl(drive, arg); 271 case HDIO_DRIVE_RESET: 272 if (!capable(CAP_SYS_ADMIN)) 273 return -EACCES; 274 return generic_drive_reset(drive); 275 case HDIO_GET_BUSSTATE: 276 if (!capable(CAP_SYS_ADMIN)) 277 return -EACCES; 278 if (put_user(BUSSTATE_ON, (long __user *)arg)) 279 return -EFAULT; 280 return 0; 281 case HDIO_SET_BUSSTATE: 282 if (!capable(CAP_SYS_ADMIN)) 283 return -EACCES; 284 return -EOPNOTSUPP; 285 default: 286 return -EINVAL; 287 } 288} 289EXPORT_SYMBOL(generic_ide_ioctl); 290