Hi guys
I'm on SuSE 8.2, development package installed. I'm logged in as root.
I'm trying to follow the book: "Linux Device Drivers", chapter 9, available online. I hope someone can tell me what I need to do to use request_irq() and free_irq() in my source.
I found the list of required header files to include for request_irq() in online manual pages - i guess my first hint that I'm heading into bad territory is that request_irq() has no manual page on my system.
Currently, I have included <linux/sched.h>, <linux/signal.h>, and <asm/irq.h>.
Also included is:
for nanosleep time struct: <linux/time.h>
for inb(): <asm/io.h> (tested, working)
for ioperm(): <unistd.h>
Using gcc, command line "make epp", I assume these are linker errors:
undefined reference to 'request_irq()'
undefined reference to 'free_irq()'
I understand that sched.h only declares the function as an external function, and the function is only defined in
/usr/src/linux-2.4.20.SuSE/arch/x86_64/kernel/irq.c
but I can't link it into my code.
So how do I start playing with request_irq()? I understand I have to write a kernel level driver that installs an interrupt handler using request_irq(), and then command the driver from user space.
How do I write this kernel level driver? Does anyone have any examples?
How do I give this driver I write an interface in user space, and how do I control this interface?
Thanks for your input
Here's my code that I've tried:
/***********************************
my working directory /root/prog/ppdev
int.c
***********************************/
#include <asm/io.h>
#include <linux/time.h>
#include <unistd.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <asm/irq.h>
#define EPP_BASE 0x378
#define EPP_SPPD EPP_BASE
#define EPP_STAT EPP_BASE + 1
#define EPP_CNTL EPP_BASE + 2
#define EPP_ADDR EPP_BASE + 3
#define EPP_DATA EPP_BASE + 4
#define EPP_W16H EPP_BASE + 5
#define EPP_W32L EPP_BASE + 6
#define EPP_W32H EPP_BASE + 7
#define EPP_SI_WAIT (1<<7)
#define EPP_SI_IRQ (1<<6)
#define EPP_SI_PAPEROUT (1<<5)
#define EPP_SI_SELECT (1<<4)
#define EPP_SI_ERR (1<<3)
#define EPP_S_NIRQ (1<<2)
#define EPP_S_RESERVD (1<<1)
#define EPP_S_TIMEOUT (1<<0)
#define EPP_C_NC7 (1<<7)
#define EPP_C_NC6 (1<<6)
#define EPP_C_BIDIREN (1<<5)
#define EPP_C_IRQEN (1<<4)
#define EPP_CO_ADDRSTROBE (1<<3)
#define EPP_CO_RESET (1<<2)
#define EPP_CO_DATASTROBE (1<<1)
#define EPP_CO_WRITE (1<<0)
//#include <unistd.h> // ioperm()
/*
extern int request_irq(unsigned int,
void (*handler)(int, void *, struct pt_regs *),
unsigned long, const char *, void *);
extern void free_irq(unsigned int, void *);
*/
struct ppintstruct
{
int com;
};
void ppinterrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int readval = inb(EPP_DATA);
struct ppintstruct *ppis = (struct ppintstruct *)dev_id;
(*ppis).com = 0x02;
}
int main(int argc, char **argv)
{
int retval;
char *dev_name;
struct ppintstruct *ppis;
struct timespec stimespec;
// Make the device name string space.
dev_name = (char *)malloc(128);
// Get pointer to far memory to use in our interrupt handler.
ppis = (struct ppintstruct *)malloc(sizeof(struct ppintstruct));
sprintf(dev_name, "DSP IF"); // Our device name.
(*ppis).com = 0x00; // Initialise our check variable.
// The handler routine changes this to 0x02 if run.
retval = ioperm(EPP_BASE, 8, 1); // Request permission
// to use EPP IO registers.
if(retval != 0)
{
printf("RW access to ports not granted.\n");
return 0;
}
retval = request_irq(7, ppinterrupt, 0, dev_name, 0);
// Install our handler.
if(retval != 0)
{
printf("Access to IRQ not granted.\n");
return -1;
}
outb((unsigned char)0x10, EPP_CNTL);
// Hardware enable EPP interrupts
// on port pin 10 (ack/interrupt).
printf("Waiting 0.1 milliseconds for interrupt to occur.\n");
stimespec.tv_sec = 0;
stimespec.tv_nsec = 100000;
nanosleep(stimespec);
outb((unsigned char)0x00, EPP_CNTL);
// Turn off interrupt generation.
free_irq(7, ppis);
retval = ioperm(EPP_BASE, 8, 0); // Release IO permissions.
free(dev_name); // Deallocate dynamic memory.
// Report on experiment.
if((*ppis).com == 0x02) {
printf("Interrupt caught - 0x02 returned.\n");
} else {
printf("No interrupt caught.\n");
}
}
/***********************************
end of int.c
***********************************/
the command line output it generates when I compile:
/***********************************
my working directory /root/prog/ppdev
command line output
***********************************/
linux:~/prog/ppdev # make int
cc int.c -o int
/tmp/ccOIRmwt.o(.text+0xc9): In function `main':
: undefined reference to `request_irq'
/tmp/ccOIRmwt.o(.text+0x151): In function `main':
: undefined reference to `free_irq'
collect2: ld returned 1 exit status
make: *** [int] Error 1
linux:~/prog/ppdev #
/***********************************
end of command line output
***********************************/