drivers/misc/phantom.c

Source file repositories/reference/linux-study-clean/drivers/misc/phantom.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/phantom.c
Extension
.c
Size
13273 bytes
Lines
565
Domain
Driver Families
Bucket
drivers/misc
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 phantom_file_ops = {
	.open = phantom_open,
	.release = phantom_release,
	.unlocked_ioctl = phantom_ioctl,
	.compat_ioctl = phantom_compat_ioctl,
	.poll = phantom_poll,
};

static irqreturn_t phantom_isr(int irq, void *data)
{
	struct phantom_device *dev = data;
	unsigned int i;
	u32 ctl;

	spin_lock(&dev->regs_lock);
	ctl = ioread32(dev->iaddr + PHN_CONTROL);
	if (!(ctl & PHN_CTL_IRQ)) {
		spin_unlock(&dev->regs_lock);
		return IRQ_NONE;
	}

	iowrite32(0, dev->iaddr);
	iowrite32(0xc0, dev->iaddr);

	if (dev->status & PHB_NOT_OH) {
		struct phm_regs *r = &dev->oregs;
		u32 m = min(r->count, 8U);

		for (i = 0; i < m; i++)
			if (r->mask & BIT(i))
				iowrite32(r->values[i], dev->oaddr + i);

		dev->ctl_reg ^= PHN_CTL_AMP;
		iowrite32(dev->ctl_reg, dev->iaddr + PHN_CONTROL);
	}
	spin_unlock(&dev->regs_lock);

	ioread32(dev->iaddr); /* PCI posting */

	atomic_inc(&dev->counter);
	wake_up_interruptible(&dev->wait);

	return IRQ_HANDLED;
}

/*
 * Init and deinit driver
 */

static unsigned int phantom_get_free(void)
{
	unsigned int i;

	for (i = 0; i < PHANTOM_MAX_MINORS; i++)
		if (phantom_devices[i] == 0)
			break;

	return i;
}

static int phantom_probe(struct pci_dev *pdev,
	const struct pci_device_id *pci_id)
{
	struct phantom_device *pht;
	unsigned int minor;
	int retval;

	retval = pci_enable_device(pdev);
	if (retval) {
		dev_err(&pdev->dev, "pci_enable_device failed!\n");
		goto err;
	}

	minor = phantom_get_free();
	if (minor == PHANTOM_MAX_MINORS) {
		dev_err(&pdev->dev, "too many devices found!\n");
		retval = -EIO;
		goto err_dis;
	}

	phantom_devices[minor] = 1;

	retval = pci_request_regions(pdev, "phantom");
	if (retval) {
		dev_err(&pdev->dev, "pci_request_regions failed!\n");
		goto err_null;
	}

	retval = -ENOMEM;
	pht = kzalloc_obj(*pht);

Annotation

Implementation Notes