⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 8253.h

📁 最新rtlinux内核源码
💻 H
字号:
/*    comedi/drivers/8253.h    Header file for 8253    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 2000 David A. Schleef <ds@schleef.org>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#ifndef _8253_H#define _8253_H#ifndef CMDTEST#include <linux/comedi.h>#else#include <comedi.h>#endif#define i8253_cascade_ns_to_timer i8253_cascade_ns_to_timer_2divstatic inline void i8253_cascade_ns_to_timer_2div_old(int i8253_osc_base, unsigned int *d1, unsigned int *d2, unsigned int *nanosec, int round_mode){	int divider;	int div1, div2;	int div1_glb, div2_glb, ns_glb;	int div1_lub, div2_lub, ns_lub;	int ns;	divider = (*nanosec + i8253_osc_base / 2) / i8253_osc_base;	/* find 2 integers 1<={x,y}<=65536 such that x*y is	   close to divider */	div1_lub = div2_lub = 0;	div1_glb = div2_glb = 0;	ns_glb = 0;	ns_lub = 0xffffffff;	div2 = 0x10000;	for (div1 = divider / 65536 + 1; div1 < div2; div1++) {		div2 = divider / div1;		ns = i8253_osc_base * div1 * div2;		if (ns <= *nanosec && ns > ns_glb) {			ns_glb = ns;			div1_glb = div1;			div2_glb = div2;		}		div2++;		if (div2 <= 65536) {			ns = i8253_osc_base * div1 * div2;			if (ns > *nanosec && ns < ns_lub) {				ns_lub = ns;				div1_lub = div1;				div2_lub = div2;			}		}	}	*nanosec = div1_lub * div2_lub * i8253_osc_base;	*d1 = div1_lub & 0xffff;	*d2 = div2_lub & 0xffff;	return;}static inline void i8253_cascade_ns_to_timer_power(int i8253_osc_base, unsigned int *d1, unsigned int *d2, unsigned int *nanosec, int round_mode){	int div1, div2;	int base;	for (div1 = 2; div1 <= (1 << 16); div1 <<= 1) {		base = i8253_osc_base * div1;		round_mode &= TRIG_ROUND_MASK;		switch (round_mode) {		case TRIG_ROUND_NEAREST:		default:			div2 = (*nanosec + base / 2) / base;			break;		case TRIG_ROUND_DOWN:			div2 = (*nanosec) / base;			break;		case TRIG_ROUND_UP:			div2 = (*nanosec + base - 1) / base;			break;		}		if (div2 < 2) div2 = 2;		if (div2 <= 65536) {			*nanosec = div2 * base;			*d1 = div1 & 0xffff;			*d2 = div2 & 0xffff;			return;		}	}	/* shouldn't get here */	div1 = 0x10000;	div2 = 0x10000;	*nanosec = div1 * div2 * i8253_osc_base;	*d1 = div1 & 0xffff;	*d2 = div2 & 0xffff;}static inline void i8253_cascade_ns_to_timer_2div(int i8253_osc_base,	unsigned int *d1, unsigned int *d2, unsigned int *nanosec, int round_mode){	unsigned int divider;	unsigned int div1, div2;	unsigned int div1_glb, div2_glb, ns_glb;	unsigned int div1_lub, div2_lub, ns_lub;	unsigned int ns;	unsigned int start;	unsigned int ns_low, ns_high;	/* exit early if everything is already correct (this can save time	 * since this function may be called repeatedly during command tests	 * and execution) */	if(*d1 * *d2 * i8253_osc_base == *nanosec &&		*d1 > 1 && *d1 < 0x10000 &&		*d2 > 1 && *d2 < 0x10000)	{		return;	}	divider = *nanosec / i8253_osc_base;	div1_lub = div2_lub = 0;	div1_glb = div2_glb = 0;	ns_glb = 0;	ns_lub = 0xffffffff;	div2 = 0x10000;	start = divider / div2;	if(start < 2) start = 2;	for (div1 = start; div1 <= divider / div1 + 1; div1++) {		for(div2 = divider / div1; div1 * div2 <= divider + div1 + 1; div2++) {			ns = i8253_osc_base * div1 * div2;			if (ns <= *nanosec && ns > ns_glb) {				ns_glb = ns;				div1_glb = div1;				div2_glb = div2;			}			if (div2 <= 0x10000) {				ns = i8253_osc_base * div1 * div2;				if (ns >= *nanosec && ns < ns_lub) {					ns_lub = ns;					div1_lub = div1;					div2_lub = div2;				}			}		}	}	round_mode &= TRIG_ROUND_MASK;	switch (round_mode) {	case TRIG_ROUND_NEAREST:	default:		ns_high = div1_lub * div2_lub * i8253_osc_base;		ns_low = div1_glb * div2_glb * i8253_osc_base;		if( ns_high - *nanosec < *nanosec - ns_low) {			div1 = div1_lub;			div2 = div2_lub;		} else {			div1 = div1_glb;			div2 = div2_glb;		}		break;	case TRIG_ROUND_UP:		div1 = div1_lub;		div2 = div2_lub;		break;	case TRIG_ROUND_DOWN:		div1 = div1_glb;		div2 = div2_glb;		break;	}	*nanosec = div1 * div2 * i8253_osc_base;	*d1 = div1 & 0xffff;	// masking is done since counter maps zero to 0x10000	*d2 = div2 & 0xffff;	return;}#ifndef CMDTEST/* i8254_load programs 8254 counter chip.  It should also work for the 8253. * base_address is the lowest io address for the chip (the address of counter 0). * counter_number is the counter you want to load (0,1 or 2) * count is the number to load into the counter. * * You probably want to use mode 2. * * Use i8254_mm_load() if you board uses memory-mapped io, it is * the same as i8254_load() except it uses writeb() instead of outb(). * * Neither i8254_load() or i8254_read() do their loading/reading * atomically.  The 16 bit read/writes are performed with two successive * 8 bit read/writes.  So if two parts of your driver do a load/read on * the same counter, it may be necessary to protect these functions * with a spinlock. * * FMH */static inline int i8254_load(unsigned int base_address,	unsigned int counter_number, unsigned int count, unsigned int mode){	unsigned int byte;	static const int counter_control = 3;	if(counter_number > 2) return -1;	if(count > 0xffff) return -1;	if(mode > 5) return -1;	if((mode == 2 || mode == 3) && count == 1) return -1;	byte = counter_number << 6;	byte |= 0x30;	// load low then high byte	byte |= (mode << 1);	// set counter mode	outb(byte, base_address + counter_control);	byte = count & 0xff;	// lsb of counter value	outb(byte, base_address + counter_number);	byte = (count >> 8) & 0xff;	// msb of counter value	outb(byte, base_address + counter_number);	return 0;}static inline int i8254_mm_load(unsigned int base_address,	unsigned int counter_number, unsigned int count, unsigned int mode){	unsigned int byte;	static const int counter_control = 3;	if(counter_number > 2) return -1;	if(count > 0xffff) return -1;	if(mode > 5) return -1;	if((mode == 2 || mode == 3) && count == 1) return -1;	byte = counter_number << 6;	byte |= 0x30;	// load low then high byte	byte |= (mode << 1);	// set counter mode	writeb(byte, base_address + counter_control);	byte = count & 0xff;	// lsb of counter value	writeb(byte, base_address + counter_number);	byte = (count >> 8) & 0xff;	// msb of counter value	writeb(byte, base_address + counter_number);	return 0;}/* Returns 16 bit counter value, should work for 8253 also.*/static inline int i8254_read(unsigned int base_address, unsigned int counter_number){	unsigned int byte;	int ret;	static const int counter_control = 3;	if(counter_number > 2) return -1;	// latch counter	byte = counter_number << 6;	outb(byte, base_address + counter_control);	// read lsb	ret = inb(base_address + counter_number);	// read msb	ret += inb(base_address + counter_number) << 8;	return ret;}#endif#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -