drivers/scsi/scsi_ioctl.c

Source file repositories/reference/linux-study-clean/drivers/scsi/scsi_ioctl.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/scsi_ioctl.c
Extension
.c
Size
25053 bytes
Lines
989
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct compat_cdrom_generic_command {
	unsigned char	cmd[CDROM_PACKET_SIZE];
	compat_caddr_t	buffer;
	compat_uint_t	buflen;
	compat_int_t	stat;
	compat_caddr_t	sense;
	unsigned char	data_direction;
	unsigned char	pad[3];
	compat_int_t	quiet;
	compat_int_t	timeout;
	compat_caddr_t	unused;
};
#endif

static int scsi_get_cdrom_generic_arg(struct cdrom_generic_command *cgc,
				      const void __user *arg)
{
#ifdef CONFIG_COMPAT
	if (in_compat_syscall()) {
		struct compat_cdrom_generic_command cgc32;

		if (copy_from_user(&cgc32, arg, sizeof(cgc32)))
			return -EFAULT;

		*cgc = (struct cdrom_generic_command) {
			.buffer		= compat_ptr(cgc32.buffer),
			.buflen		= cgc32.buflen,
			.stat		= cgc32.stat,
			.sense		= compat_ptr(cgc32.sense),
			.data_direction	= cgc32.data_direction,
			.quiet		= cgc32.quiet,
			.timeout	= cgc32.timeout,
			.unused		= compat_ptr(cgc32.unused),
		};
		memcpy(&cgc->cmd, &cgc32.cmd, CDROM_PACKET_SIZE);
		return 0;
	}
#endif
	if (copy_from_user(cgc, arg, sizeof(*cgc)))
		return -EFAULT;

	return 0;
}

static int scsi_put_cdrom_generic_arg(const struct cdrom_generic_command *cgc,
				      void __user *arg)
{
#ifdef CONFIG_COMPAT
	if (in_compat_syscall()) {
		struct compat_cdrom_generic_command cgc32 = {
			.buffer		= (uintptr_t)(cgc->buffer),
			.buflen		= cgc->buflen,
			.stat		= cgc->stat,
			.sense		= (uintptr_t)(cgc->sense),
			.data_direction	= cgc->data_direction,
			.quiet		= cgc->quiet,
			.timeout	= cgc->timeout,
			.unused		= (uintptr_t)(cgc->unused),
		};
		memcpy(&cgc32.cmd, &cgc->cmd, CDROM_PACKET_SIZE);

		if (copy_to_user(arg, &cgc32, sizeof(cgc32)))
			return -EFAULT;

		return 0;
	}
#endif
	if (copy_to_user(arg, cgc, sizeof(*cgc)))
		return -EFAULT;

	return 0;
}

static int scsi_cdrom_send_packet(struct scsi_device *sdev, bool open_for_write,
		void __user *arg)
{
	struct cdrom_generic_command cgc;
	struct sg_io_hdr hdr;
	int err;

	err = scsi_get_cdrom_generic_arg(&cgc, arg);
	if (err)
		return err;

	cgc.timeout = clock_t_to_jiffies(cgc.timeout);
	memset(&hdr, 0, sizeof(hdr));
	hdr.interface_id = 'S';
	hdr.cmd_len = sizeof(cgc.cmd);
	hdr.dxfer_len = cgc.buflen;
	switch (cgc.data_direction) {

Annotation

Implementation Notes