• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 324
  • Last Modified:

driver compilation gives warning,and insmod gives error

Hi,

   I have built a very small diver in linux kernel 2.2. When I compile with the following command:

"gcc -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.2.16/include -O -Wall xxx_drv.c"

  it flashes the warning "At top level: warning: initialization from incompatible pointer type".
   
And on running "insmod xxx_drv.o" it gives message
"xxx_drv.o: couldn't find the kernel version the module was compiled for.", though i have used the line

"#define __NO_VERSION__".

So, trying to be specific, my questions are:

1. What should I do for the above problem. ;-)
2. What to do to integrate it with the kernel, i.e., I don't want to run insmod everytime? It should be loaded at boot-up time.
3. Why do different file_operations structures have different no. of enteries???

------------------------------

As the code is short, I am pasting it below:

/////////////////////////////////////////////////////////

#include <linux/config.h>

#ifndef __KERNEL__
#define __KERNEL__
#endif

#define __NO_VERSION__

#include <linux/config.h>

#ifdef CONFIG_SMP
#define __SMP__
#endif

/* system include files */
#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/tty.h"
#include "linux/signal.h"
#include "linux/errno.h"
#include "asm/io.h"
#include "asm/segment.h"
#include "asm/system.h"
#include "asm/irq.h"

#include <linux/ioport.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/fcntl.h>



int
xxx_write(struct inode *inode, struct file *file, char *buffer, int count) {

     int          offset = 0;

    if (count > 4095)
        return(-ENOMEM);
    if (count <= 0)
        return(-EINVAL);

    while (count > 0) {
         outb( *(buffer++),0x378); /*0x378 is the starting address of the parallel port.*/
         offset++;
    }
    return offset; /* return number of bytes written */
}



/* This is the structure I found at a site*/

static struct file_operations xxx_fops = {
    NULL,         /* lseek()   */
    NULL,     /* read()    */
    xxx_write,    /* write()   */
    NULL,         /* readdir() */
    NULL,         /* select()  */
    NULL,    /* ioctl()   */
    NULL,         /* mmap()    */
   NULL,     /* open()    */    
    NULL     /* close()   */
    };



long
xxx_init(long kmem_start) {
     EXPORT_NO_SYMBOLS;
    printk("Sample Device Driver Initialization\n");

    if (register_chrdev(22, "xxx", &xxx_fops))
        printk("error--cannot register to major device 22!\n");
    /* detect hardware and initialize it */
    return kmem_start;
}



void cleanup_module(void)
   {
      unregister_chrdev(22, "xxx");
   }
/////////////////////////////////////////////////////////
0
adija
Asked:
adija
  • 6
  • 5
1 Solution
 
bryanhCommented:
>"xxx_drv.o: couldn't find the kernel version the module
>was compiled for.", though i have used the line
>
>"#define __NO_VERSION__".

__NO_VERSION__ means "don't generate the kernel version in the module."  But Insmod will not load a module that doesn't contain the kernel version.  So take that out.

(Why would anyone code #define __NO_VERSION__?  Because he is going to link two object files together to create an LKM, and he wants only one kernel version generated).

>At top level: warning: initialization from incompatible pointer type".
 
This is just about impossible to debug without looking at the source code line number in the message and then the source line.  One of your data structures is probably used in a macro that requires a different data type.

>I don't want to run insmod everytime? It should be loaded at boot-up time.

So put an 'insmod' command in one of your startup scripts.  People often use a more complex method to do this, but it isn't any better.

>Why do different file_operations structures have different no. of enteries???

Entry?  Do you mean member initializer?  Structures don't have entries.  If you mean some drivers initialize different numbers of members in their file_operations structures, the answer is because not all drivers care to provide all the possible file operations.  In GNU C, when you specify an initializer for some members and not others, the others get initialized to NULL.


By the way, EE works best when you post separate questions separately.  There are different experts for different questions, even in the same area.
0
 
adijaAuthor Commented:
Hi,
  I'll keep inmind to send different questions the next time. The "insmod" style in startup files seems good to me.

This reply corresponds to my first problem,i.e., -
1. What should I do ...

      I deleted the line "#define __NO_VERSION__" from the source file, but still the same error message flashes on screen:
"xxx_drv.o: couldn't find the kernel version the module was compiled for."

I am using kernel 2.2

0
 
adijaAuthor Commented:
Hi,

  This query is with respect to my first question's second problem,i.e.:

"While comipling the source file with the command
gcc -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.2.16/include -O -Wall xxx_drv.c"

the compiler flashes a warning:
"xxx_drv.o: couldn't find the kernel version the module was compiled for."

I've seen it, and the line number corresponding to the error contains the member initializer xxx_write of file_operations structure. To make it clear, my pasting my xxx_fops structure from the source code indicating the line that triggers the warning.

static struct file_operations xxx_fops = {
   NULL,         /* lseek()   */
   NULL,     /* read()    */
   xxx_write,    /* write()   */  //THIS IS THE LINE THAT
//CORRESPONDS TO THE SOURCE OF THE WARNING
   NULL,         /* readdir() */
   NULL,         /* select()  */
   NULL,    /* ioctl()   */
   NULL,         /* mmap()    */
  NULL,     /* open()    */    
   NULL     /* close()   */
   };


Thanks in advance.

aditya
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
bryanhCommented:
>"xxx_drv.o: couldn't find the kernel version the module was compiled for."

OK, this is pretty simple then.  You're loading an object module which is not an LKM.  The surest way to differentiate a loadable kernel module from some random .o file is to do 'objdump --headers xxx_drv.o'.  That lists all the sections in the .o file.  If it's an LKM, one of those sections is called ".modinfo".  I bet xxx_drv.o doesn't have one.

So how does an LKM get a .modinfo section?  By having its source code include <linux/module.h>.  That's what makes an LKM an LKM.

I recommend reading the MODULE-HOWTO (which I wrote).  It isn't really geared to developing LKMs as much as toward using them, but it has some valuable background information like this.
0
 
bryanhCommented:
>I've seen it, and the line number corresponding to the
>error contains the member initializer xxx_write of
>file_operations structure.

OK, that's a pretty common error.  If you don't get the parameter list and return type of your xxx_write() function exactly right, this is the error message (and note that the message was incorrectly pasted into the above reply -- the real error, from the original posting, is about a type mismatch).

You need to compare your declaration of xxx_write() to the write routine from a working module.  Here's one I found in drivers/char/tty_io.c:

static ssize_t tty_write(struct file *, const char *, size_t, loff_t *);

(Really, you're supposed just to look at the declaration of struct file_ops, but looking at an example is probably easier here).
0
 
adijaAuthor Commented:
Hi,
  Thanks for the second one, I added "const" and the compilation error has gone. But as I made a mistake of posting several questions at once, I can't accpet it until I get all answers this time. sorry.

aditya
0
 
adijaAuthor Commented:
Hi,
  I have already added <linux/module.h>. And now I've also added <linux/version.h>. But the insmod error reamins as is.

  What's your link to LKM files? And any other suggestions.

Thanks.

aditya
0
 
bryanhCommented:
First, you really should do the objdump I mentioned to narrow the problem down.  If you don't have a .modinfo section, there's no point in even trying to load it.

I think you're probably missing the -DMODULE on the compile command.  Defining the MODULE macro is what tells the source code that it's supposed to generate a loadable module instead of one that can be statically bound into the base kernel (many modules can be built both ways).

You shouldn't include <linux/version.h> unless you have code that refers to the symbol in it.  module.h has such code, but includes version.h itself.
0
 
adijaAuthor Commented:
Hi,
  I ran objdump. You were right. It doesn't have a .modinfo.  This was kernel 2.4
  And when yesterday I complied it on kernel 2.2, it gave the following messages:
/tmp/cc1rWGVn.s: Assembler messages:
/tmp/cc1rWGVn.s:9:Warning: Ignoring changed section attributes for .modinfo

    And when I ran insmod, it have error that resource is busy.  I want to use the address of parallel port, i.e., 0x378. You can read my init function for that matter.
 
Thanks
0
 
bryanhCommented:
Are you saying you've solved the missing version problem and now your module init function is running and the init function is returning an error?

The xxx_init() function above is strange.  It takes an argument even though a module init function doesn't have arguments.  And it returns that argument as its return code.  The return code is supposed to be 0 if the initialization succeeded and a negative errno  error code if it didn't succeed.  In the latter case, Linux unloads the module.

For some reason I don't understand, if the init function returns a positive number (which means it's broken, like this one), the module loader proceeds as if it returned -EBUSY, which would result in the busy message you see.
0
 
adijaAuthor Commented:
Hi,
  I think this is just a small problem left, so I'm accepting our comment as answer. Moreover, with your courtesy we can talk about it with less severity.

Thanks.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now