drivers/scsi/st.c

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

File Facts

System
Linux kernel
Corpus path
drivers/scsi/st.c
Extension
.c
Size
135465 bytes
Lines
5055
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations st_fops =
{
	.owner =	THIS_MODULE,
	.read =		st_read,
	.write =	st_write,
	.unlocked_ioctl = st_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = st_compat_ioctl,
#endif
	.open =		st_open,
	.flush =	st_flush,
	.release =	st_release,
	.llseek =	noop_llseek,
};

static int create_one_cdev(struct scsi_tape *tape, int mode, int rew)
{
	int i, error;
	dev_t cdev_devno;
	struct cdev *cdev;
	struct device *dev;
	struct st_modedef *STm = &(tape->modes[mode]);
	char name[10];
	int dev_num = tape->index;

	cdev_devno = MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, rew));

	cdev = cdev_alloc();
	if (!cdev) {
		pr_err("st%d: out of memory. Device not attached.\n", dev_num);
		error = -ENOMEM;
		goto out;
	}
	cdev->owner = THIS_MODULE;
	cdev->ops = &st_fops;
	STm->cdevs[rew] = cdev;

	error = cdev_add(cdev, cdev_devno, 1);
	if (error) {
		pr_err("st%d: Can't add %s-rewind mode %d\n", dev_num,
		       rew ? "non" : "auto", mode);
		pr_err("st%d: Device not attached.\n", dev_num);
		goto out_free;
	}

	i = mode << (4 - ST_NBR_MODE_BITS);
	snprintf(name, 10, "%s%s%s", rew ? "n" : "",
		 tape->name, st_formats[i]);

	dev = device_create(&st_sysfs_class, &tape->device->sdev_gendev,
			    cdev_devno, &tape->modes[mode], "%s", name);
	if (IS_ERR(dev)) {
		pr_err("st%d: device_create failed\n", dev_num);
		error = PTR_ERR(dev);
		goto out_free;
	}

	STm->devs[rew] = dev;

	return 0;
out_free:
	cdev_del(STm->cdevs[rew]);
out:
	STm->cdevs[rew] = NULL;
	STm->devs[rew] = NULL;
	return error;
}

static int create_cdevs(struct scsi_tape *tape)
{
	int mode, error;
	for (mode = 0; mode < ST_NBR_MODES; ++mode) {
		error = create_one_cdev(tape, mode, 0);
		if (error)
			return error;
		error = create_one_cdev(tape, mode, 1);
		if (error)
			return error;
	}

	return sysfs_create_link(&tape->device->sdev_gendev.kobj,
				 &tape->modes[0].devs[0]->kobj, "tape");
}

static void remove_cdevs(struct scsi_tape *tape)
{
	int mode, rew;
	sysfs_remove_link(&tape->device->sdev_gendev.kobj, "tape");
	for (mode = 0; mode < ST_NBR_MODES; mode++) {
		struct st_modedef *STm = &(tape->modes[mode]);

Annotation

Implementation Notes