Associating driver to the existing device

Submitted by vishal.soni
on May 30, 2005 - 4:33am

[vishal@vishalsoni ~]$ uname -a
Linux vishalsoni 2.6.9-1.667 #1 Tue Nov 2 14:41:25 EST 2004 i686 i686 i386 GNU/Linux
[vishal@vishalsoni ~]$ ll /dev/mem
crw-r----- 1 root kmem 1, 1 May 30 2005 /dev/mem

We have the device /dev/mem with major no. 1 and minor no.1. I am trying to associate a driver to this device.. so that any read/write/mmap happening to this device.. gives control to my driver.
I am able to Successfully register the device ( dmesg tells this) & below is the code.

int LinuxTestMemDevice_init(void)
{
int rv = -1;
int devno = MKDEV(1,1);
struct cdev my_cdev;
printk("<1>pdcd: Skelton Driver, version %s\n", DRIVER_VERSION);
my_cdev.owner=THIS_MODULE;
my_cdev.ops =&my_fops;
rv = cdev_add(&my_cdev,devno,1);

if(rv) {
printk("<1> Error in registering the char device\n");
return -1;
}
else {
printk("<1> :------------- Succesfully registered the device -----------\n");
printk("<1> : Major no. of device is :: %d\n",MAJOR(devno));
printk("<1> : Minor no. of device is :: %d\n",MINOR(devno));
}
return 0;
}

Registration is successful.......
Now when i try to do
[vishal@vishalsoni ~]$ cat /dev/mem
my implementation of open does not get called.

As a test.. i have written, just one line code.

static int my_open(struct inode *imem, struct file *fmem)
{
printk("<1> INSIDE my_open ..................\n");
return 1;
}

Where am i going wrong !!!!!!

sorry

on
May 30, 2005 - 8:06am

Everywhere? -- Sorry, but you asked.

You did not 'register' the device with alloc_chrdev_region(), which would have failed, because /dev/mem already is a character device with a driver (cdev_add() assumes you own this device number and simply returns the result of kobj_map(), which only fails, if the memory allocation went wrong (you can see all this by grepping for the function implementations, or in case of cdev_add() by grepping for call sites)). Why didn't you simply 'invent' a new device number and execute the associated "mknod 640 /dev/mydev c [MAJOR MINOR]". Also your variable my_cdev is on the function stack (local to the function), which is bad in many ways: after the function returns to the caller the space is reused, the structure you added to a global list is overwritten in unpredictable ways and many times. You are lucky your code wasn't called, it would have crashed, or even kernel internal modifications of the structure would have changed local variables of completely unrelated functions in funny ways. The working code i found in the linux sources allocates struct cdev's with cdev_alloc(). Also module init functions seem to return error numbers and not simply -1 for error, but i could not verify that.

Buy http://www.oreilly.com/catalog/linuxdrive3/ and try again..

>> Everywhere? -- Sorry, but

on
May 31, 2005 - 5:28am

>> Everywhere? -- Sorry, but you asked.
Yeah...... i was.

>> You did not 'register' the device with alloc_chrdev_region(),

>> which would have failed, because /dev/mem already is a character

>> device with a driver (cdev_add() assumes you own this device number

>> and simply returns the result of kobj_map(), which only fails, if

>> the memory allocation went wrong (you can see all this by grepping

>> for the function implementations, or in case of cdev_add() by

>> grepping for call sites)).

Done....... but this tooo succesfully registers the device.

int LinuxTestMemDevice_init(void)
{
int rv = -1;
int devno = MKDEV(1,1);
struct cdev *my_cdev=NULL;
my_cdev= cdev_alloc();
if(my_cdev == NULL) {
printk("<1> Error in cdev_alloc()\n");
return -1;
}
printk("Skelton Driver, version %s\n", DRIVER_VERSION);
my_cdev->owner=THIS_MODULE;
my_cdev->ops =&my_fops;
rv = cdev_add(my_cdev,devno,1);
if(rv) {
printk(" Error in registering the char device\n");
return -1;
}
else {
printk(" Succesfully registered the device -----------\n");
printk(" : Major no. of device is :: %d\n",MAJOR(devno));
printk(" : Minor no. of device is :: %d\n",MINOR(devno));
}

return 0;
}

>> Why didn't you simply 'invent' a new device number and execute the
associated "mknod 640 /dev/mydev c [MAJOR MINOR]".

This is actually, what i don't intend to do... i want to associate my driver to /dev/mem device..so that any read/write/mmap done by XServer on to this device.... makes my driver fuctions called.

What i am trying to do.. is to work on Linux Display System. XServer uses /dev/mem device(i.e video memory is mapped to the user space and XServer directly writes on to it).
I would like to gain control over the flow of data from XServer to this Memory Mapped Device i.e /dev/mem

>> Also your variable my_cdev is on the function stack (local to the

>> function), which is bad in many ways: after the function returns

>> to the caller the space is reused, the structure you added to a

>> global list is overwritten in unpredictable ways and many times.

>> You are lucky your code wasn't called, it would have crashed, or

>> even kernel internal modifications of the structure would have

>> changed local variables of completely unrelated functions in funny

>> ways. The working code i found in the linux sources allocates

>> struct cdev's with cdev_alloc(). Also module init functions seem to

Got U !!

>> return error numbers and not simply -1 for error, but i could not verify that.

Nope...... no errors in registering the device.

Change the X Server

on
June 1, 2005 - 3:01am

Sounds like you're trying to do things in the wrong place; you'd be better off altering X to use a different device to access memory.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.