驱动源代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#define INT_DEV_NAME "intdev"
#define INT_DEV_MAJOR 240
#define INT_WRITE_ADDR 0x0378
#define INT_READ_ADDR 0x0379
#define INT_CTRL_ADDR 0x037A
#define PRINT_IRQ 7
#define PRINT_IRQ_ENABLE_MASK 0x10
#define INT_BUFF_MAX 64
typedef struct
{
unsigned long time;
} __attribute__((packed)) R_INT_INFO;
R_INT_INFO intbuffer[INT_BUFF_MAX];
int intcount = 0;
void int_clear(void)
{
int lp;
for(lp = 0; lp < INT_BUFF_MAX; lp++)
{
intbuffer[lp].time = 0;
}
intcount = 0;
}
irqreturn_t int_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
if(intcount < INT_BUFF_MAX)
{
intbuffer[intcount].time = get_jiffies_64( );
intcount++;
}
printk("int_init interrupt\n");
return IRQ_HANDLED;
}
int int_open (struct inode *inode, struct file *filp)
{
if(!request_irq(PRINT_IRQ , int_interrupt, SA_INTERRUPT, INT_DEV_NAME,
NULL))
printk("int_init open\n");
{
outb(PRINT_IRQ_ENABLE_MASK, INT_CTRL_ADDR);
}
int_clear( );
return 0;
}
ssize_t int_read(struct file *filp, char *buf, size_t count, loff_t
*f_pos)
{
int readcount;
char *ptrdata;
int loop;
readcount = count / sizeof(R_INT_INFO);
if(readcount > intcount) readcount = intcount;
ptrdata = (char *) &intbuffer[0];
for(loop = 0; loop < readcount * sizeof(R_INT_INFO); loop++)
{
put_user(ptrdata[loop], (char *) &buf[loop]);
}
return readcount * sizeof(R_INT_INFO);
}
ssize_t int_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
unsigned char status;
int loop;
int_clear( );
for(loop = 0; loop < count; loop++)
{
get_user(status, (char *) buf);
outb(status , INT_WRITE_ADDR);
}
return count;
}
int int_release (struct inode *inode, struct file *filp)
{
outb(0x00, INT_CTRL_ADDR);
free_irq(PRINT_IRQ , NULL);
printk("int_init release\n");
return 0;
}
struct file_operations int_fops =
{
.owner = THIS_MODULE,
.read = int_read,
.write = int_write,
.open = int_open,
.release = int_release,
};
int int_init(void)
{
int result;
result = register_chrdev(INT_DEV_MAJOR, INT_DEV_NAME, &int_fops);
if (result < 0) return result;
printk("int_init init\n");
return 0;
}
void int_exit(void)
{
unregister_chrdev(INT_DEV_MAJOR, INT_DEV_NAME);
printk("int_init exit\n");
}
module_init(int_init);
module_exit(int_exit);
MODULE_LICENSE("Dual BSD/GPL");
應用程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define DEVICE_FILENAME "/dev/intdev"
typedef struct
{
unsigned long time;
} __attribute__((packed)) R_INT_INFO;
#define INT_BUFF_MAX 64
int main( )
{
int dev;
R_INT_INFO intbuffer[INT_BUFF_MAX];
int intcount;
char buff[128];
int loop;
dev = open(DEVICE_FILENAME, O_RDWR | O_NDELAY);
if(dev >= 0)
{
printf("start...\n");
buff[0] = 0xFF;
write(dev,buff,1);
printf("wait... input\n");
while(1)
{
memset(intbuffer, 0, sizeof(intbuffer));
intcount = read(dev,(char *) &intbuffer[0],sizeof(R_INT_INFO))/sizeof(R_INT_INFO) ;
if(intcount) break;
}
printf("input ok...\n");
sleep(1);
memset(intbuffer, 0, sizeof(intbuffer));
printf("read interrupt times\n");
intcount = read(dev,(char *) intbuffer,sizeof(intbuffer)) / sizeof(R_INT_INFO) ;
for(loop =0; loop < intcount; loop++)
{
printf("index = %d time = %ld\n", loop, intbuffer[loop].time);
}
printf("led flashing...\n");
for(loop=0; loop<5; loop++)
{
buff[0] = 0xFF;
write(dev,buff,1);
sleep(1);
buff[0] = 0x00;
write(dev,buff,1);
sleep(1);
}
close(dev);
}
return 0;
}
内核版本
Linux version 2.6.18-53.el5 (
mockbuild@builder6.centos.org) (gcc version 4.1.2 20070626 (Red Hat 4.1.2-14)) #1 SMP Mon Nov 12 02:22:48 EST 2007
[root@localhost chap12]# cat /proc/interrupts
CPU0
0: 54553037 IO-APIC-edge timer
1: 19605 IO-APIC-edge i8042
6: 5 IO-APIC-edge floppy
7: 0 IO-APIC-edge parport0
8: 1 IO-APIC-edge rtc
9: 0 IO-APIC-level acpi
12: 85275 IO-APIC-edge i8042
15: 190577 IO-APIC-edge ide1
169: 43736 IO-APIC-level vmxnet ether
177: 0 IO-APIC-level uhci_hcd:usb1, Ensoniq AudioPCI
185: 0 IO-APIC-level ehci_hcd:usb2
193: 71539 IO-APIC-level ioc0
NMI: 0
LOC: 54557867
ERR: 0
MIS: 0