18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * ide-floppy IOCTLs handling.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/kernel.h>
78c2ecf20Sopenharmony_ci#include <linux/ide.h>
88c2ecf20Sopenharmony_ci#include <linux/compat.h>
98c2ecf20Sopenharmony_ci#include <linux/cdrom.h>
108c2ecf20Sopenharmony_ci#include <linux/mutex.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <scsi/scsi_ioctl.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "ide-floppy.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/*
198c2ecf20Sopenharmony_ci * Obtain the list of formattable capacities.
208c2ecf20Sopenharmony_ci * Very similar to ide_floppy_get_capacity, except that we push the capacity
218c2ecf20Sopenharmony_ci * descriptors to userland, instead of our own structures.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Userland gives us the following structure:
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * struct idefloppy_format_capacities {
268c2ecf20Sopenharmony_ci *	int nformats;
278c2ecf20Sopenharmony_ci *	struct {
288c2ecf20Sopenharmony_ci *		int nblocks;
298c2ecf20Sopenharmony_ci *		int blocksize;
308c2ecf20Sopenharmony_ci *	} formats[];
318c2ecf20Sopenharmony_ci * };
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci * userland initializes nformats to the number of allocated formats[] records.
348c2ecf20Sopenharmony_ci * On exit we set nformats to the number of records we've actually initialized.
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(ide_floppy_ioctl_mutex);
388c2ecf20Sopenharmony_cistatic int ide_floppy_get_format_capacities(ide_drive_t *drive,
398c2ecf20Sopenharmony_ci					    struct ide_atapi_pc *pc,
408c2ecf20Sopenharmony_ci					    int __user *arg)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	struct ide_disk_obj *floppy = drive->driver_data;
438c2ecf20Sopenharmony_ci	int i, blocks, length, u_array_size, u_index;
448c2ecf20Sopenharmony_ci	int __user *argp;
458c2ecf20Sopenharmony_ci	u8 pc_buf[256], header_len, desc_cnt;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	if (get_user(u_array_size, arg))
488c2ecf20Sopenharmony_ci		return -EFAULT;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (u_array_size <= 0)
518c2ecf20Sopenharmony_ci		return -EINVAL;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	ide_floppy_create_read_capacity_cmd(pc);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	if (ide_queue_pc_tail(drive, floppy->disk, pc, pc_buf, pc->req_xfer)) {
568c2ecf20Sopenharmony_ci		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
578c2ecf20Sopenharmony_ci		return -EIO;
588c2ecf20Sopenharmony_ci	}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	header_len = pc_buf[3];
618c2ecf20Sopenharmony_ci	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	u_index = 0;
648c2ecf20Sopenharmony_ci	argp = arg + 1;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/*
678c2ecf20Sopenharmony_ci	 * We always skip the first capacity descriptor.  That's the current
688c2ecf20Sopenharmony_ci	 * capacity.  We are interested in the remaining descriptors, the
698c2ecf20Sopenharmony_ci	 * formattable capacities.
708c2ecf20Sopenharmony_ci	 */
718c2ecf20Sopenharmony_ci	for (i = 1; i < desc_cnt; i++) {
728c2ecf20Sopenharmony_ci		unsigned int desc_start = 4 + i*8;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci		if (u_index >= u_array_size)
758c2ecf20Sopenharmony_ci			break;	/* User-supplied buffer too small */
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		blocks = be32_to_cpup((__be32 *)&pc_buf[desc_start]);
788c2ecf20Sopenharmony_ci		length = be16_to_cpup((__be16 *)&pc_buf[desc_start + 6]);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci		if (put_user(blocks, argp))
818c2ecf20Sopenharmony_ci			return -EFAULT;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci		++argp;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci		if (put_user(length, argp))
868c2ecf20Sopenharmony_ci			return -EFAULT;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci		++argp;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci		++u_index;
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (put_user(u_index, arg))
948c2ecf20Sopenharmony_ci		return -EFAULT;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	return 0;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc,
1008c2ecf20Sopenharmony_ci					      u8 *buf, int b, int l,
1018c2ecf20Sopenharmony_ci					      int flags)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	ide_init_pc(pc);
1048c2ecf20Sopenharmony_ci	pc->c[0] = GPCMD_FORMAT_UNIT;
1058c2ecf20Sopenharmony_ci	pc->c[1] = 0x17;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	memset(buf, 0, 12);
1088c2ecf20Sopenharmony_ci	buf[1] = 0xA2;
1098c2ecf20Sopenharmony_ci	/* Default format list header, u8 1: FOV/DCRT/IMM bits set */
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	if (flags & 1)				/* Verify bit on... */
1128c2ecf20Sopenharmony_ci		buf[1] ^= 0x20;			/* ... turn off DCRT bit */
1138c2ecf20Sopenharmony_ci	buf[3] = 8;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	put_unaligned(cpu_to_be32(b), (unsigned int *)(&buf[4]));
1168c2ecf20Sopenharmony_ci	put_unaligned(cpu_to_be32(l), (unsigned int *)(&buf[8]));
1178c2ecf20Sopenharmony_ci	pc->req_xfer = 12;
1188c2ecf20Sopenharmony_ci	pc->flags |= PC_FLAG_WRITING;
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	struct ide_disk_obj *floppy = drive->driver_data;
1248c2ecf20Sopenharmony_ci	u8 buf[20];
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	drive->atapi_flags &= ~IDE_AFLAG_SRFP;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE);
1298c2ecf20Sopenharmony_ci	pc->flags |= PC_FLAG_SUPPRESS_ERROR;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (ide_queue_pc_tail(drive, floppy->disk, pc, buf, pc->req_xfer))
1328c2ecf20Sopenharmony_ci		return 1;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (buf[8 + 2] & 0x40)
1358c2ecf20Sopenharmony_ci		drive->atapi_flags |= IDE_AFLAG_SRFP;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	return 0;
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic int ide_floppy_format_unit(ide_drive_t *drive, struct ide_atapi_pc *pc,
1418c2ecf20Sopenharmony_ci				  int __user *arg)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	struct ide_disk_obj *floppy = drive->driver_data;
1448c2ecf20Sopenharmony_ci	u8 buf[12];
1458c2ecf20Sopenharmony_ci	int blocks, length, flags, err = 0;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	if (floppy->openers > 1) {
1488c2ecf20Sopenharmony_ci		/* Don't format if someone is using the disk */
1498c2ecf20Sopenharmony_ci		drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
1508c2ecf20Sopenharmony_ci		return -EBUSY;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	drive->dev_flags |= IDE_DFLAG_FORMAT_IN_PROGRESS;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	/*
1568c2ecf20Sopenharmony_ci	 * Send ATAPI_FORMAT_UNIT to the drive.
1578c2ecf20Sopenharmony_ci	 *
1588c2ecf20Sopenharmony_ci	 * Userland gives us the following structure:
1598c2ecf20Sopenharmony_ci	 *
1608c2ecf20Sopenharmony_ci	 * struct idefloppy_format_command {
1618c2ecf20Sopenharmony_ci	 *        int nblocks;
1628c2ecf20Sopenharmony_ci	 *        int blocksize;
1638c2ecf20Sopenharmony_ci	 *        int flags;
1648c2ecf20Sopenharmony_ci	 *        } ;
1658c2ecf20Sopenharmony_ci	 *
1668c2ecf20Sopenharmony_ci	 * flags is a bitmask, currently, the only defined flag is:
1678c2ecf20Sopenharmony_ci	 *
1688c2ecf20Sopenharmony_ci	 *        0x01 - verify media after format.
1698c2ecf20Sopenharmony_ci	 */
1708c2ecf20Sopenharmony_ci	if (get_user(blocks, arg) ||
1718c2ecf20Sopenharmony_ci			get_user(length, arg+1) ||
1728c2ecf20Sopenharmony_ci			get_user(flags, arg+2)) {
1738c2ecf20Sopenharmony_ci		err = -EFAULT;
1748c2ecf20Sopenharmony_ci		goto out;
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	ide_floppy_get_sfrp_bit(drive, pc);
1788c2ecf20Sopenharmony_ci	ide_floppy_create_format_unit_cmd(pc, buf, blocks, length, flags);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	if (ide_queue_pc_tail(drive, floppy->disk, pc, buf, pc->req_xfer))
1818c2ecf20Sopenharmony_ci		err = -EIO;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ciout:
1848c2ecf20Sopenharmony_ci	if (err)
1858c2ecf20Sopenharmony_ci		drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
1868c2ecf20Sopenharmony_ci	return err;
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci/*
1908c2ecf20Sopenharmony_ci * Get ATAPI_FORMAT_UNIT progress indication.
1918c2ecf20Sopenharmony_ci *
1928c2ecf20Sopenharmony_ci * Userland gives a pointer to an int.  The int is set to a progress
1938c2ecf20Sopenharmony_ci * indicator 0-65536, with 65536=100%.
1948c2ecf20Sopenharmony_ci *
1958c2ecf20Sopenharmony_ci * If the drive does not support format progress indication, we just check
1968c2ecf20Sopenharmony_ci * the dsc bit, and return either 0 or 65536.
1978c2ecf20Sopenharmony_ci */
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic int ide_floppy_get_format_progress(ide_drive_t *drive,
2008c2ecf20Sopenharmony_ci					  struct ide_atapi_pc *pc,
2018c2ecf20Sopenharmony_ci					  int __user *arg)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	struct ide_disk_obj *floppy = drive->driver_data;
2048c2ecf20Sopenharmony_ci	u8 sense_buf[18];
2058c2ecf20Sopenharmony_ci	int progress_indication = 0x10000;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	if (drive->atapi_flags & IDE_AFLAG_SRFP) {
2088c2ecf20Sopenharmony_ci		ide_create_request_sense_cmd(drive, pc);
2098c2ecf20Sopenharmony_ci		if (ide_queue_pc_tail(drive, floppy->disk, pc, sense_buf,
2108c2ecf20Sopenharmony_ci				      pc->req_xfer))
2118c2ecf20Sopenharmony_ci			return -EIO;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		if (floppy->sense_key == 2 &&
2148c2ecf20Sopenharmony_ci		    floppy->asc == 4 &&
2158c2ecf20Sopenharmony_ci		    floppy->ascq == 4)
2168c2ecf20Sopenharmony_ci			progress_indication = floppy->progress_indication;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci		/* Else assume format_unit has finished, and we're at 0x10000 */
2198c2ecf20Sopenharmony_ci	} else {
2208c2ecf20Sopenharmony_ci		ide_hwif_t *hwif = drive->hwif;
2218c2ecf20Sopenharmony_ci		unsigned long flags;
2228c2ecf20Sopenharmony_ci		u8 stat;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci		local_irq_save(flags);
2258c2ecf20Sopenharmony_ci		stat = hwif->tp_ops->read_status(hwif);
2268c2ecf20Sopenharmony_ci		local_irq_restore(flags);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci		progress_indication = ((stat & ATA_DSC) == 0) ? 0 : 0x10000;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (put_user(progress_indication, arg))
2328c2ecf20Sopenharmony_ci		return -EFAULT;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	return 0;
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_cistatic int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
2388c2ecf20Sopenharmony_ci			       unsigned long arg, unsigned int cmd)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	struct ide_disk_obj *floppy = drive->driver_data;
2418c2ecf20Sopenharmony_ci	struct gendisk *disk = floppy->disk;
2428c2ecf20Sopenharmony_ci	int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (floppy->openers > 1)
2458c2ecf20Sopenharmony_ci		return -EBUSY;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	ide_set_media_lock(drive, disk, prevent);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	if (cmd == CDROMEJECT)
2508c2ecf20Sopenharmony_ci		ide_do_start_stop(drive, disk, 2);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	return 0;
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic int ide_floppy_format_ioctl(ide_drive_t *drive, struct ide_atapi_pc *pc,
2568c2ecf20Sopenharmony_ci				   fmode_t mode, unsigned int cmd,
2578c2ecf20Sopenharmony_ci				   void __user *argp)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	switch (cmd) {
2608c2ecf20Sopenharmony_ci	case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
2618c2ecf20Sopenharmony_ci		return 0;
2628c2ecf20Sopenharmony_ci	case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
2638c2ecf20Sopenharmony_ci		return ide_floppy_get_format_capacities(drive, pc, argp);
2648c2ecf20Sopenharmony_ci	case IDEFLOPPY_IOCTL_FORMAT_START:
2658c2ecf20Sopenharmony_ci		if (!(mode & FMODE_WRITE))
2668c2ecf20Sopenharmony_ci			return -EPERM;
2678c2ecf20Sopenharmony_ci		return ide_floppy_format_unit(drive, pc, (int __user *)argp);
2688c2ecf20Sopenharmony_ci	case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
2698c2ecf20Sopenharmony_ci		return ide_floppy_get_format_progress(drive, pc, argp);
2708c2ecf20Sopenharmony_ci	default:
2718c2ecf20Sopenharmony_ci		return -ENOTTY;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ciint ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
2768c2ecf20Sopenharmony_ci		     fmode_t mode, unsigned int cmd, unsigned long arg)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct ide_atapi_pc pc;
2798c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
2808c2ecf20Sopenharmony_ci	int err;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	mutex_lock(&ide_floppy_ioctl_mutex);
2838c2ecf20Sopenharmony_ci	if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) {
2848c2ecf20Sopenharmony_ci		err = ide_floppy_lockdoor(drive, &pc, arg, cmd);
2858c2ecf20Sopenharmony_ci		goto out;
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp);
2898c2ecf20Sopenharmony_ci	if (err != -ENOTTY)
2908c2ecf20Sopenharmony_ci		goto out;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	/*
2938c2ecf20Sopenharmony_ci	 * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
2948c2ecf20Sopenharmony_ci	 * and CDROM_SEND_PACKET (legacy) ioctls
2958c2ecf20Sopenharmony_ci	 */
2968c2ecf20Sopenharmony_ci	if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
2978c2ecf20Sopenharmony_ci		err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	if (err == -ENOTTY)
3008c2ecf20Sopenharmony_ci		err = generic_ide_ioctl(drive, bdev, cmd, arg);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ciout:
3038c2ecf20Sopenharmony_ci	mutex_unlock(&ide_floppy_ioctl_mutex);
3048c2ecf20Sopenharmony_ci	return err;
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
3088c2ecf20Sopenharmony_ciint ide_floppy_compat_ioctl(ide_drive_t *drive, struct block_device *bdev,
3098c2ecf20Sopenharmony_ci			    fmode_t mode, unsigned int cmd, unsigned long arg)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	struct ide_atapi_pc pc;
3128c2ecf20Sopenharmony_ci	void __user *argp = compat_ptr(arg);
3138c2ecf20Sopenharmony_ci	int err;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	mutex_lock(&ide_floppy_ioctl_mutex);
3168c2ecf20Sopenharmony_ci	if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) {
3178c2ecf20Sopenharmony_ci		err = ide_floppy_lockdoor(drive, &pc, arg, cmd);
3188c2ecf20Sopenharmony_ci		goto out;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp);
3228c2ecf20Sopenharmony_ci	if (err != -ENOTTY)
3238c2ecf20Sopenharmony_ci		goto out;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/*
3268c2ecf20Sopenharmony_ci	 * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
3278c2ecf20Sopenharmony_ci	 * and CDROM_SEND_PACKET (legacy) ioctls
3288c2ecf20Sopenharmony_ci	 */
3298c2ecf20Sopenharmony_ci	if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
3308c2ecf20Sopenharmony_ci		err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	if (err == -ENOTTY)
3338c2ecf20Sopenharmony_ci		err = generic_ide_ioctl(drive, bdev, cmd, arg);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ciout:
3368c2ecf20Sopenharmony_ci	mutex_unlock(&ide_floppy_ioctl_mutex);
3378c2ecf20Sopenharmony_ci	return err;
3388c2ecf20Sopenharmony_ci}
3398c2ecf20Sopenharmony_ci#endif
340