drivers/char/xillybus/xillybus_core.c

Source file repositories/reference/linux-study-clean/drivers/char/xillybus/xillybus_core.c

File Facts

System
Linux kernel
Corpus path
drivers/char/xillybus/xillybus_core.c
Extension
.c
Size
50605 bytes
Lines
1991
Domain
Driver Families
Bucket
drivers/char
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 xillybus_fops = {
	.owner      = THIS_MODULE,
	.read       = xillybus_read,
	.write      = xillybus_write,
	.open       = xillybus_open,
	.flush      = xillybus_flush,
	.release    = xillybus_release,
	.llseek     = xillybus_llseek,
	.poll       = xillybus_poll,
};

struct xilly_endpoint *xillybus_init_endpoint(struct device *dev)
{
	struct xilly_endpoint *endpoint;

	endpoint = devm_kzalloc(dev, sizeof(*endpoint), GFP_KERNEL);
	if (!endpoint)
		return NULL;

	endpoint->dev = dev;
	endpoint->msg_counter = 0x0b;
	endpoint->failed_messages = 0;
	endpoint->fatal_error = 0;

	init_waitqueue_head(&endpoint->ep_wait);
	mutex_init(&endpoint->register_mutex);

	return endpoint;
}
EXPORT_SYMBOL(xillybus_init_endpoint);

static int xilly_quiesce(struct xilly_endpoint *endpoint)
{
	long t;

	endpoint->idtlen = -1;

	iowrite32((u32) (endpoint->dma_using_dac & 0x0001),
		  endpoint->registers + fpga_dma_control_reg);

	t = wait_event_interruptible_timeout(endpoint->ep_wait,
					     (endpoint->idtlen >= 0),
					     XILLY_TIMEOUT);
	if (t <= 0) {
		dev_err(endpoint->dev,
			"Failed to quiesce the device on exit.\n");
		return -ENODEV;
	}
	return 0;
}

int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint)
{
	int rc;
	long t;

	void *bootstrap_resources;
	int idtbuffersize = (1 << PAGE_SHIFT);
	struct device *dev = endpoint->dev;

	/*
	 * The bogus IDT is used during bootstrap for allocating the initial
	 * message buffer, and then the message buffer and space for the IDT
	 * itself. The initial message buffer is of a single page's size, but
	 * it's soon replaced with a more modest one (and memory is freed).
	 */

	unsigned char bogus_idt[8] = { 1, 224, (PAGE_SHIFT)-2, 0,
				       3, 192, PAGE_SHIFT, 0 };
	struct xilly_idt_handle idt_handle;

	/*
	 * Writing the value 0x00000001 to Endianness register signals which
	 * endianness this processor is using, so the FPGA can swap words as
	 * necessary.
	 */

	iowrite32(1, endpoint->registers + fpga_endian_reg);

	/* Bootstrap phase I: Allocate temporary message buffer */

	bootstrap_resources = devres_open_group(dev, NULL, GFP_KERNEL);
	if (!bootstrap_resources)
		return -ENOMEM;

	endpoint->num_channels = 0;

	rc = xilly_setupchannels(endpoint, bogus_idt, 1);
	if (rc)
		return rc;

Annotation

Implementation Notes