📄 adc.c
字号:
/* ADC.c */
#include<linux/errno.h>
#include<linux/fs.h>
#include<linux/major.h>
#include<linux/kernel.h>
#include<linux/signal.h>
#include<linux/module.h>
#include<linux/sched.h>
#include<asm/io.h>
#include<asm/segment.h>
#include<asm/system.h>
#include "ADC.h"
extern int printk(const char* fmt, ...);
int adc_busy=0;
unsigned short data_port,control_port,status_port;
static int adc_open(struct inode * inode,struct file * file)
{
unsigned int minor=MINOR(inode->i_rdev);
if (minor>7) return -ENODEV;
if (adc_busy==ADC_BUSY) return -EBUSY;
adc_busy=ADC_BUSY;
return 0;
}
static void adc_close(struct inode * inode,struct file * file)
{
adc_busy=ADC_FREE;
}
static int adc_read(struct inode * inode,struct file * file,char * buf,int count)
{
unsigned char data[16];
int adc_val;
unsigned int temp_val;
int temp1,temp2,temp3;
unsigned int minor=MINOR(inode->i_rdev);
if (count < 1) return -EINVAL;
switch (minor)
{
case CHANNEL_0:
temp1=0x8f;
break;
case CHANNEL_1:
temp1=0xcf;
break;
case CHANNEL_2:
temp1=0x9f;
break;
case CHANNEL_3:
temp1=0xdf;
break;
case CHANNEL_4:
temp1=0xaf;
break;
case CHANNEL_5:
temp1=0xef;
break;
case CHANNEL_6:
temp1=0xbf;
break;
case CHANNEL_7:
temp1=0xff;
break;
default:
temp1=0x8f;
break;
}
cli();
for(temp2=0; temp2<8; temp2++)
{
temp3= (temp1 << temp2) & 0x80;
outb(temp3,data_port);
temp3=temp3 | 1;
outb(temp3,data_port);
outb(temp3,data_port); /* this is to make the clk 50% duty cycle*/
/* Duty cycle as measured with a 66 MHz 486 is 48% */
temp3=temp3 & 0xfe;
outb(temp3,data_port);
}
temp3=temp3 & 0x7f;
outb(temp3,data_port);
for(temp2=0; temp2<16; temp2++)
{
temp3= 01;
outb(temp3,data_port);
data[temp2]=inb(data_port+1)&0x80;
temp3=temp3 & 0xfe;
outb(temp3,data_port);
outb(temp3,data_port);
}
sti();
adc_val=0;
for(temp2=0; temp2<16; temp2++)
{
temp_val=( (unsigned int) data[temp2] & 0x00ff) << 8;
adc_val= adc_val | ( (temp_val ^ 0x8000) >> temp2);
}
adc_val=adc_val>> 3;
put_fs_word(adc_val,buf);
/* printk("ADC: Input value from port: %d\n",adc_val); */
return 1;
}
static struct file_operations adc_fops={
NULL,
adc_read,
NULL,
NULL,
NULL,
NULL,
NULL,
adc_open,
adc_close,
NULL
};
int init_module(void)
{
unsigned char ret_val,test_val=0x00;
outb(test_val,PARALLEL_1);
ret_val=inb(PARALLEL_1);
if (ret_val==test_val)
{
data_port=PARALLEL_1;
}
else
{
outb(test_val,PARALLEL_2);
ret_val=inb(PARALLEL_2);
if (ret_val==test_val)
{
data_port=PARALLEL_2;
}
else
{
data_port=PARALLEL_3;
}
}
printk("ADC: init module \n");
if (register_chrdev(ADC_MAJOR,"adc",&adc_fops))
{
printk("Register_chrdev failed: Quitting\n");
return -EIO;
}
else
{
printk("ADC: Device Registered\n");
return 0;
}
}
void cleanup_module(void)
{
int busy=0;
printk("ADC: Cleanup Module \n");
if (adc_busy==ADC_BUSY) busy=1;
if (busy) printk("ADC: Device busy, remove later\n");
if (unregister_chrdev(ADC_MAJOR,"adc")!=0)
{
printk("ADC: Clean up module failed\n");
}
else
{
printk("Clean up module succeeded\n");
}
}
unsigned short test_parallel(void)
{
unsigned char ret_val,test_val=0x55;
unsigned short dport;
outb(test_val,PARALLEL_3);
ret_val=inb(PARALLEL_3);
if (ret_val==test_val)
{
dport=PARALLEL_3;
}
else
{
outb(test_val,PARALLEL_1);
ret_val=inb(PARALLEL_1);
if (ret_val==test_val)
{
dport=PARALLEL_1;
}
else
{
outb(test_val,PARALLEL_2);
ret_val=inb(PARALLEL_2);
if (ret_val==test_val)
{
dport=PARALLEL_1;
}else
{
printk("No Parallel Port Available\n");
return -EIO;
}
}
}
return(dport);
}
int test_adc(void)
{
unsigned char cbyte;
cbyte=inb(data_port+2);
cbyte=cbyte&0xfe;
outb(cbyte,data_port+2);
cbyte=inb(data_port+1);
cbyte=cbyte & 0x80;
if (cbyte) return ADC_NOT_AVAILABLE;
cbyte=inb(data_port+2);
cbyte=cbyte|0x01;
outb(cbyte,data_port+2);
cbyte=inb(data_port+1);
cbyte=cbyte&0x80;
if (!cbyte) return ADC_NOT_AVAILABLE;
return ADC_AVAILABLE;
}
int adc_init(void)
{
int adc_stat;
printk("\n\n");
printk(" General Purpose DAS : Gadre and Engineer \n");
printk(" Copyright 1996 The Peshwe at IUCAA , Pune\n");
data_port=test_parallel();
if (data_port!=0x378 && data_port!=0x278 && data_port!=0x3bc)
{
printk("Parallel Port Not Available\n");
return -EINVAL;
}
printk("The Code detected %x as the parallel port in this machine\n",data_port);
adc_stat=test_adc();
if (adc_stat==1)
{
printk("ADC: registering driver\n");
if (register_chrdev(ADC_MAJOR,"adc",&adc_fops))
{
printk("Register_chrdev failed: Quitting\n");
return -EIO;
}
else
{
printk("ADC: Device Registered\n");
printk(" \t\t SanSon DAS testing Successful \t\t \n\n");
return 0;
}
}
printk("ADC not connected\n");
printk(" \n\n");
return -EIO;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -