drivers/firewire/nosy.c

Source file repositories/reference/linux-study-clean/drivers/firewire/nosy.c

File Facts

System
Linux kernel
Corpus path
drivers/firewire/nosy.c
Extension
.c
Size
17492 bytes
Lines
720
Domain
Driver Families
Bucket
drivers/firewire
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 nosy_ops = {
	.owner =		THIS_MODULE,
	.read =			nosy_read,
	.unlocked_ioctl =	nosy_ioctl,
	.poll =			nosy_poll,
	.open =			nosy_open,
	.release =		nosy_release,
};

#define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */

static void
packet_irq_handler(struct pcilynx *lynx)
{
	struct client *client;
	u32 tcode_mask, tcode, timestamp;
	size_t length;
	struct timespec64 ts64;

	/* FIXME: Also report rcv_speed. */

	length = __le32_to_cpu(lynx->rcv_pcl->pcl_status) & 0x00001fff;
	tcode  = __le32_to_cpu(lynx->rcv_buffer[1]) >> 4 & 0xf;

	ktime_get_real_ts64(&ts64);
	timestamp = ts64.tv_nsec / NSEC_PER_USEC;
	lynx->rcv_buffer[0] = (__force __le32)timestamp;

	if (length == PHY_PACKET_SIZE)
		tcode_mask = 1 << TCODE_PHY_PACKET;
	else
		tcode_mask = 1 << tcode;

	spin_lock(&lynx->client_list_lock);

	list_for_each_entry(client, &lynx->client_list, link)
		if (client->tcode_mask & tcode_mask)
			packet_buffer_put(&client->buffer,
					  lynx->rcv_buffer, length + 4);

	spin_unlock(&lynx->client_list_lock);
}

static void
bus_reset_irq_handler(struct pcilynx *lynx)
{
	struct client *client;
	struct timespec64 ts64;
	u32    timestamp;

	ktime_get_real_ts64(&ts64);
	timestamp = ts64.tv_nsec / NSEC_PER_USEC;

	spin_lock(&lynx->client_list_lock);

	list_for_each_entry(client, &lynx->client_list, link)
		packet_buffer_put(&client->buffer, &timestamp, 4);

	spin_unlock(&lynx->client_list_lock);
}

static irqreturn_t
irq_handler(int irq, void *device)
{
	struct pcilynx *lynx = device;
	u32 pci_int_status;

	pci_int_status = reg_read(lynx, PCI_INT_STATUS);

	if (pci_int_status == ~0)
		/* Card was ejected. */
		return IRQ_NONE;

	if ((pci_int_status & PCI_INT_INT_PEND) == 0)
		/* Not our interrupt, bail out quickly. */
		return IRQ_NONE;

	if ((pci_int_status & PCI_INT_P1394_INT) != 0) {
		u32 link_int_status;

		link_int_status = reg_read(lynx, LINK_INT_STATUS);
		reg_write(lynx, LINK_INT_STATUS, link_int_status);

		if ((link_int_status & LINK_INT_PHY_BUSRESET) > 0)
			bus_reset_irq_handler(lynx);
	}

	/* Clear the PCI_INT_STATUS register only after clearing the
	 * LINK_INT_STATUS register; otherwise the PCI_INT_P1394 will
	 * be set again immediately. */

Annotation

Implementation Notes