drivers/comedi/drivers/comedi_8254.c

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

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/comedi_8254.c
Extension
.c
Size
19951 bytes
Lines
730
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

if (ns <= *nanosec && ns > ns_glb) {
				ns_glb = ns;
				d1_glb = d1;
				d2_glb = d2;
			}
			if (ns >= *nanosec && ns < ns_lub) {
				ns_lub = ns;
				d1_lub = d1;
				d2_lub = d2;
			}
		}
	}

	switch (flags & CMDF_ROUND_MASK) {
	case CMDF_ROUND_NEAREST:
	default:
		ns_high = d1_lub * d2_lub * i8254->osc_base;
		ns_low = d1_glb * d2_glb * i8254->osc_base;
		if (ns_high - *nanosec < *nanosec - ns_low) {
			d1 = d1_lub;
			d2 = d2_lub;
		} else {
			d1 = d1_glb;
			d2 = d2_glb;
		}
		break;
	case CMDF_ROUND_UP:
		d1 = d1_lub;
		d2 = d2_lub;
		break;
	case CMDF_ROUND_DOWN:
		d1 = d1_glb;
		d2 = d2_glb;
		break;
	}

	*nanosec = d1 * d2 * i8254->osc_base;
	i8254->next_div1 = d1;
	i8254->next_div2 = d2;
}
EXPORT_SYMBOL_GPL(comedi_8254_cascade_ns_to_timer);

/**
 * comedi_8254_ns_to_timer - calculate the divisor value for nanosec timing
 * @i8254:	comedi_8254 struct for the timer
 * @nanosec:	the desired ns time
 * @flags:	comedi_cmd flags
 */
void comedi_8254_ns_to_timer(struct comedi_8254 *i8254,
			     unsigned int *nanosec, unsigned int flags)
{
	unsigned int divisor;

	switch (flags & CMDF_ROUND_MASK) {
	default:
	case CMDF_ROUND_NEAREST:
		divisor = DIV_ROUND_CLOSEST(*nanosec, i8254->osc_base);
		break;
	case CMDF_ROUND_UP:
		divisor = DIV_ROUND_UP(*nanosec, i8254->osc_base);
		break;
	case CMDF_ROUND_DOWN:
		divisor = *nanosec / i8254->osc_base;
		break;
	}
	if (divisor < 2)
		divisor = 2;
	if (divisor > I8254_MAX_COUNT)
		divisor = I8254_MAX_COUNT;

	*nanosec = divisor * i8254->osc_base;
	i8254->next_div = divisor;
}
EXPORT_SYMBOL_GPL(comedi_8254_ns_to_timer);

/**
 * comedi_8254_set_busy - set/clear the "busy" flag for a given counter
 * @i8254:	comedi_8254 struct for the timer
 * @counter:	the counter number
 * @busy:	set/clear flag
 */
void comedi_8254_set_busy(struct comedi_8254 *i8254,
			  unsigned int counter, bool busy)
{
	if (counter < 3)
		i8254->busy[counter] = busy;
}
EXPORT_SYMBOL_GPL(comedi_8254_set_busy);

static int comedi_8254_insn_read(struct comedi_device *dev,

Annotation

Implementation Notes