drivers/comedi/drivers/dt2814.c

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

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/dt2814.c
Extension
.c
Size
8768 bytes
Lines
373
Domain
Driver Families
Bucket
drivers/comedi
Inferred role
Driver Families: implementation source
Status
source 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

// SPDX-License-Identifier: GPL-2.0+
/*
 * comedi/drivers/dt2814.c
 * Hardware driver for Data Translation DT2814
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
 */
/*
 * Driver: dt2814
 * Description: Data Translation DT2814
 * Author: ds
 * Status: complete
 * Devices: [Data Translation] DT2814 (dt2814)
 *
 * Configuration options:
 * [0] - I/O port base address
 * [1] - IRQ
 *
 * This card has 16 analog inputs multiplexed onto a 12 bit ADC.  There
 * is a minimally useful onboard clock.  The base frequency for the
 * clock is selected by jumpers, and the clock divider can be selected
 * via programmed I/O.  Unfortunately, the clock divider can only be
 * a power of 10, from 1 to 10^7, of which only 3 or 4 are useful.  In
 * addition, the clock does not seem to be very accurate.
 */

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/comedi/comedidev.h>
#include <linux/delay.h>

#define DT2814_CSR 0
#define DT2814_DATA 1

/*
 * flags
 */

#define DT2814_FINISH 0x80
#define DT2814_ERR 0x40
#define DT2814_BUSY 0x20
#define DT2814_ENB 0x10
#define DT2814_CHANMASK 0x0f

#define DT2814_TIMEOUT 10
#define DT2814_MAX_SPEED 100000	/* Arbitrary 10 khz limit */

static int dt2814_ai_notbusy(struct comedi_device *dev,
			     struct comedi_subdevice *s,
			     struct comedi_insn *insn,
			     unsigned long context)
{
	unsigned int status;

	status = inb(dev->iobase + DT2814_CSR);
	if (context)
		*(unsigned int *)context = status;
	if (status & DT2814_BUSY)
		return -EBUSY;
	return 0;
}

static int dt2814_ai_clear(struct comedi_device *dev)
{
	unsigned int status = 0;
	int ret;

	/* Wait until not busy and get status register value. */
	ret = comedi_timeout(dev, NULL, NULL, dt2814_ai_notbusy,
			     (unsigned long)&status);
	if (ret)
		return ret;

	if (status & (DT2814_FINISH | DT2814_ERR)) {
		/*
		 * There unread data, or the error flag is set.
		 * Read the data register twice to clear the condition.
		 */
		inb(dev->iobase + DT2814_DATA);
		inb(dev->iobase + DT2814_DATA);
	}
	return 0;
}

static int dt2814_ai_eoc(struct comedi_device *dev,
			 struct comedi_subdevice *s,
			 struct comedi_insn *insn,
			 unsigned long context)
{

Annotation

Implementation Notes