drivers/comedi/drivers/ni_tiocmd.c

Source file repositories/reference/linux-study-clean/drivers/comedi/drivers/ni_tiocmd.c

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/ni_tiocmd.c
Extension
.c
Size
13983 bytes
Lines
500
Domain
Driver Families
Bucket
drivers/comedi
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

else if (cmd->start_src == TRIG_EXT) {
			int reg = CR_CHAN(cmd->start_arg);

			if (reg >= NI_NAMES_BASE) {
				/* using a device-global name. lookup reg */
				reg = ni_get_reg_value(reg,
						       NI_CtrArmStartTrigger(cidx),
						       routing_tables);
				/* mark this as a raw register value */
				reg |= NI_GPCT_HW_ARM;
			}
			ret = ni_tio_arm(counter, true, reg);
		}
	}
	return ret;
}

static int ni_tio_output_cmd(struct comedi_subdevice *s)
{
	struct ni_gpct *counter = s->private;

	dev_err(counter->counter_dev->dev->class_dev,
		"output commands not yet implemented.\n");
	return -ENOTSUPP;
}

static int ni_tio_cmd_setup(struct comedi_subdevice *s)
{
	struct comedi_cmd *cmd = &s->async->cmd;
	struct ni_gpct *counter = s->private;
	unsigned int cidx = counter->counter_index;
	const struct ni_route_tables *routing_tables =
		counter->counter_dev->routing_tables;
	int set_gate_source = 0;
	unsigned int gate_source;
	int retval = 0;

	if (cmd->scan_begin_src == TRIG_EXT) {
		set_gate_source = 1;
		gate_source = cmd->scan_begin_arg;
	} else if (cmd->convert_src == TRIG_EXT) {
		set_gate_source = 1;
		gate_source = cmd->convert_arg;
	}
	if (set_gate_source) {
		if (CR_CHAN(gate_source) >= NI_NAMES_BASE) {
			/* Lookup and use the real register values */
			int reg = ni_get_reg_value(CR_CHAN(gate_source),
						   NI_CtrGate(cidx),
						   routing_tables);
			if (reg < 0)
				return -EINVAL;
			retval = ni_tio_set_gate_src_raw(counter, 0, reg);
		} else {
			/*
			 * This function must be used separately since it does
			 * not expect real register values and attempts to
			 * convert these to real register values.
			 */
			retval = ni_tio_set_gate_src(counter, 0, gate_source);
		}
	}
	if (cmd->flags & CMDF_WAKE_EOS) {
		ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
				GI_GATE_INTERRUPT_ENABLE(cidx),
				GI_GATE_INTERRUPT_ENABLE(cidx));
	}
	return retval;
}

int ni_tio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
	struct ni_gpct *counter = s->private;
	struct comedi_async *async = s->async;
	struct comedi_cmd *cmd = &async->cmd;
	int retval = 0;
	unsigned long flags;

	spin_lock_irqsave(&counter->lock, flags);
	if (!counter->mite_chan) {
		dev_err(counter->counter_dev->dev->class_dev,
			"commands only supported with DMA.  ");
		dev_err(counter->counter_dev->dev->class_dev,
			"Interrupt-driven commands not yet implemented.\n");
		retval = -EIO;
	} else {
		retval = ni_tio_cmd_setup(s);
		if (retval == 0) {
			if (cmd->flags & CMDF_WRITE)
				retval = ni_tio_output_cmd(s);

Annotation

Implementation Notes