LQ Newbie
Registered: Apr 2006
Location: Hyderabad
Distribution: redhat(linux 2.4.21-15.ELSMP)
Posts: 8
Original Poster
Rep:
|
this is my code in kernel space
#define MODULE
#define __KERNEL__
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/sched.h>
#include<linux/interrupt.h>
#include<linux/fs.h>
#include<asm/current.h>
#include<linux/ioport.h>
#include<asm/io.h>
#include<errno.h>
#include<asm/uaccess.h>
#include<linux/init.h>
#include<linux/delay.h>
#include "defs.h"
#include "serialcmd.h"
#define MAX 20
#define NAME lifo
MODULE_LICENSE("GPL");
static INT32S divisor;
static INT8U setparity;
static INT8U kbuff[MAX];
static INT32U i,result,STAT,time_out=0;
static BOOLEAN FLAG=0;
DECLARE_WAIT_QUEUE_HEAD(my_q);
static INT32S lifo_open(struct inode *, struct file *);
ssize_t lifo_read(struct file *,char *,size_t , loff_t *);
ssize_t lifo_write(struct file *,const char *,size_t , loff_t *);
static int lifo_close(struct inode *,struct file *);
static int lifo_ioctl(struct inode *inode,struct file *filep,unsigned int cmd,unsigned long arg);
static int lifo_ioctl(struct inode *inode,struct file *filep,unsigned int cmd,unsigned long arg)
{
time_out=arg;
}
void serial_handler(INT32S irq_num,void *dev_id,struct pt_regs *regs)
{
printk("\n Irq number is %d ", irq_num);
static INT8U ch;
static INT32U len;
STAT = inb_p(IIR);
printk("\n status is %x",STAT);
STAT &=0x06;
printk("\n Change due to ANDing with 0x06 in status is %x",STAT);
switch(STAT)
{
/*writing the characters to transmit register */
case 2:
len = strlen(kbuff);
if(FLAG == 1)
{
for(i=0; i<len; i++)
outb_p(kbuff[i],BASE+0);
i=0;
FLAG = 0;
}
break;
/* reading the characters from the receive register */
case 4:
i = 0;
while((ch = inb_p(BASE+0)) !='\0')
kbuff[i++] = ch;
break;
default:
break;
}
}
static INT32S lifo_open(struct inode *inode, struct file *filep)
{
static int result;
printk("\n In open , Initialising all needed registers\n");
outb(0x07, IER);
outb(0x87, FCR);
outb(0x03, LCR);
result = request_irq(4,serial_handler,0,"my_origin",(void*)1234);
if(result < 0)
{
printk("\n Error in requesting Irq\n");
return result;
}
printk("\n Handler is requested\n");
return 0;
}
/*Here we will get the irq line no. and the control will be transferred to serial_handler which is interrupt handler*/
ssize_t lifo_read(struct file *filep,char *ubuff,size_t len, loff_t *offset)
{
time_out=time_out*101;
printk("\n In read \n");
if (i==0)
{
copy_to_user(ubuff,"\n No data available\n",20);
/* if(time_out==0)
{
sleep_on(&my_q);
copy_to_user((void *)ubuff,(void *)kbuff,i);
}
else
{
sleep_on_timeout(&my_q,time_out);
copy_to_user((void *)ubuff,(void *)kbuff,i);
time_out=0;
}*/
}
else
{
printk("i=%d",i);
printk("time out=%d",time_out);
copy_to_user((void *)ubuff,(void *)kbuff,i);
}
return i;
}
ssize_t lifo_write(struct file *filep,const char *ubuff,size_t len, loff_t *offset)
{
STAT = inb_p(LCR);
STAT &= 0x7f;
outb(STAT,LCR);
result=copy_from_user((void *)kbuff,(void *)ubuff,20);
FLAG = 1;
printk("\n Write succeed %c \n",ubuff[0]);
wake_up(&my_q);
return 0;
}
static int lifo_close(struct inode *inode,struct file *filep)
{
free_irq(4,(void *)1234);
printk("\nWe've closed the device");
return 0;
}
struct file_operations fops=
{
open: lifo_open,
read: lifo_read,
release: lifo_close,
write: lifo_write,
ioctl: lifo_ioctl
};
int register_dd(void)
{
int result;
printk("\nThe device is registerered");
result=register_chrdev(254,"lifo",&fops);
if(result<0)
{
printk("error");
return(result);
}
return 0;
}
void unregister_dd(void)
{
printk("\nThe device is unregistered");
unregister_chrdev(254,"lifo");
}
module_init(register_dd);
module_exit(unregister_dd);
I have recompiled the kernel 2.4.21-ELsmp and inserted Generic driver as module also
and i have removed serial moule also and inserted my own module but unable to go into interrupt handler.my user space code is
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include"serialcmd.h"
#define MAX 20
main()
{
int fd,ch,choice,result,time_out,cont;
char ubuff[MAX];
do
{
system("clear");
printf("\nEnter 1 to open the serial device");
printf("\nEnter 2 to close the serial device");
printf("\nEnter 3 to read from the serial device");
printf("\nEnter 4 to write to the serial device");
printf("\nEnter your choice:");
scanf("%d",&choice);
switch(choice)
{
case 1:
fd=open("/dev/lifo",O_RDWR);
if(fd==-1)
{
perror("\nError in opening the device");
return -1;
}
break;
case 2:
result=close(fd);
if(result=-1)
{
perror("\nError in closing the device");
return -1;
}
break;
case 3:
system("clear");
printf("\nPress '1' to read characters\n");
printf("\nPress '2' to read timed out charaters\n");
fflush(stdout);
printf("\nEnter your choice:\n");
fflush(stdin);
scanf("%d",&ch);
switch(ch)
{
case 1:
result=read(fd,ubuff,strlen(ubuff));
printf("%s",ubuff);
break;
case 2:
printf("\nEnter the time out value in seconds:");
scanf("%d",&time_out);
result=ioctl(fd,TIME_OUT,time_out);
/* if(result=-1)
{
perror("\nError in closing the device");
return -1;
}*/
result=read(fd,ubuff,strlen(ubuff));
/*if(result=-1)
{
perror("\nError in closing the device");
return -1;
}*/
printf("%s",ubuff);
break;
default:
printf("\nEnter a valid choice");
}
break;
case 4:
printf("\nEnter the string to write:");
scanf("%s",ubuff);
result=write(fd,ubuff,strlen(ubuff));
/*if(result=-1)
{
perror("\nError in closing the device");
return -1;
}*/
break;
default:
printf("\nEnter a valid choice");
}
system("clear");
printf("\nEnter 1 to continue, any other key to exit:");
fflush(stdin);
scanf("%d",&cont);
}while(cont==1);
}
ANY device driver specialist help me please.
|