Member
Registered: Aug 2004
Posts: 76
Original Poster
Rep:
|
And dmesg shows nothing from the printk that I put in read write functions ?
Here I give some code of my module it is big But I cannot give you other way the whole picture
////////////////////////////////
//scull.h////////////////////
////////////////////////////////
#define SCULL_DEBUG
#define FUNCDEBUG
#ifndef SCULL_H
#define SCULL_H
#include <linux/ioctl.h>
#ifndef SCULL_MAJOR
#define SCULL_MAJOR 0
#endif
#ifndef SCULL_NR_DEVS
#define SCULL_NR_DEVS 4
#endif
#ifndef SCULL_NR_DEVS
#define SCULL_NR_DEVS 4
#endif
#ifndef SCULL_QUANTUM
#define SCULL_QUANTUM 4000
#endif
#ifndef SCULL_QSET
#define SCULL_QSET 1000
#endif
//#ifndef SCULL_P_BUFFER
//#define SCULL_PBUFFER 4000
//#endif
#define TYPE(minor) (((minor)>>4)&0xf);//hinible
#define NUM(minor) ((minor)&0xf);//lownible
extern int scull_major;
extern int scull_nr_devs;
extern int scull_quantumn;
extern int scull_qset;
//extern int scull_p_buffer; //pipe.c
struct scull_qset{
void** data;
struct scull_qset* next;
};
struct scull_dev{
struct scull_qset *data;
int quantum;
int qset;
unsigned long size;
unsigned int access_key;
struct semaphore sem;
struct cdev cdev;
};
//int scull_p_init(dev_t dev);
//void scull_p_cleanup();
//int scull_access_init(dev_t dev);
//void scull_access_cleanup();
int scull_trim(struct scull_dev *dev);
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos);
loff_t scull_llseek(struct file *filp, loff_t off, int whence);
int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
#define SCULL_IOCSQUANTUM _IOW(SCULL_IOCMAGIC, 1,int)
/*to be continued ...*/
#endif//SCULL_H
//////////////////////////////
////scull.cpp
///////////////////////////
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include "scull.h"
int read_function_count =0;
int write_function_count =0;
int scull_major = SCULL_MAJOR;
int scull_minor = 0;
int scull_nr_devs=SCULL_NR_DEVS;
int scull_quantum = SCULL_QUANTUM;
int scull_qset=SCULL_QSET;
module_param(scull_major,int,S_IRUGO);
module_param(scull_minor,int,S_IRUGO);
module_param(scull_nr_devs,int,S_IRUGO);
module_param(scull_quantum,int,S_IRUGO);
module_param(scull_qset,int,S_IRUGO);
MODULE_AUTHOR("IgorD");
MODULE_LICENSE("Dual BSD/?GPL");
struct scull_dev *scull_devices;
int scull_trim(struct scull_dev* dev)
{
struct scull_qset *next, *dptr;
int qset=dev->qset;
int i;
#ifdef FUNCDEBUG
printk("<0> scull_trim begin\n");
#endif//FUNCDEBUG
for(dptr=dev->data;dptr;dptr=next){
if(dptr->data){
for (i=0;i<qset;++i);
kfree(dptr->data[i]);
kfree(dptr->data);
dptr->data=NULL;
}
next=dptr->next;
kfree(dptr);
}
dev->size=0;
dev->quantum=scull_quantum;
dev->qset=scull_qset;
dev->data=NULL;
#ifdef FUNCDEBUG
printk("<0> scull_trim end\n");
#endif//FUNCDEBUG
return 0;
}
#ifdef SCULL_DEBUG
int scull_read_procmem(char *buf, char **start, off_t offset, int count, int* eof, void*data){
int i, j, len=0;
int limit=count-80;
for (i=0;i<scull_nr_devs && len<=limit;i++){
struct scull_dev *d=&scull_devices[i];
struct scull_qset *qs =d->data;
if(down_interruptible(&d->sem))
return -ERESTARTSYS;
len+= sprintf(buf+len,"\nDevices %i qset %i, q %i, sz %li\n",i,d->qset,d->quantum,d->size);
for(; qs&& len<=limit;qs=qs->next){
if(qs->data && !qs->next){
sprintf(buf+len," item at %p,qset at %p",qs,qs->data);
for(j=0;j<d->qset;j++){
if(qs->data[j])
len+=sprintf(buf+len,"%4i : %8p\n",j, qs->data[j]);
}
}
}
up(&d->sem);
}
*eof=1;
return len;
}
static void* scull_seq_start(struct seq_file *s, loff_t* pos){
if(*pos >= scull_nr_devs)
return NULL;
return scull_devices+*pos;
}
static void* scull_seq_next(struct seq_file *s, void * v, loff_t* pos){
++(*pos);
if(*pos >= scull_nr_devs)
return NULL;
return scull_devices+*pos;
}
static void scull_seq_stop(struct seq_file *s, void * v){
}
static int scull_seq_show(struct seq_file* s, void *v){
struct scull_dev *dev = (struct scull_dev* ) v;
struct scull_qset *d;
int i;
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
seq_printf(s,"\nDevice %i: qset %i q %i sz %li\n", (int)(dev-scull_devices), dev->qset,dev->quantum, dev->size);
for(d = dev->data;d; d=d->next){
seq_printf(s," item at %p, qset at %p\n",d,d->data);
if (d->data && d->next){
for(i = 0; i < dev->qset; ++i){
if(d->data[i])
seq_printf(s," % 4i: %8p\n",i,d->data[i]);
}
}
}
up(&dev->sem);
return 0;
}
static struct seq_operations scull_seq_ops = {
.start = scull_seq_start,
.next = scull_seq_next,
.stop = scull_seq_stop,
.show =scull_seq_show
};
static int scull_proc_open(struct inode* inode,struct file *file){
return seq_open(file,&scull_seq_ops);
}
static struct file_operations scull_proc_ops = {
.owner =THIS_MODULE,
.open =scull_proc_open,
.read =seq_read,
.llseek=seq_lseek,
.release=seq_release
};
static void scull_create_proc(void){
struct proc_dir_entry *entry;
create_proc_read_entry("scullmem",0,NULL,scull_read_procmem,NULL);
entry = create_proc_entry("scullseq",0,NULL);
if(entry)
entry->proc_fops = &scull_proc_ops;
}
static void scull_remove_proc(void){
remove_proc_entry("scull_mem",NULL);
remove_proc_entry("scull_seq",NULL);
}
/*to be continued*/
#endif
int scull_open(struct inode* inode, struct file* filp)
{
struct scull_dev *dev;
#ifdef FUNCDEBUG
printk("<0> scull_open begin\n");
#endif//FUNCDEBUG
dev=container_of(inode->i_cdev,struct scull_dev, cdev);
filp->private_data=dev;
if((filp->f_flags & O_ACCMODE) == O_WRONLY){
scull_trim(dev);
}
#ifdef FUNCDEBUG
printk("<0> scull_open end\n");
#endif//FUNCDEBUG
return 0;
}
int scull_release(struct inode *inode,struct file *filp){
#ifdef FUNCDEBUG
printk("<0> scull_release begin\n");
#endif//FUNCDEBUG
#ifdef FUNCDEBUG
printk("<0> scull_release end\n");
#endif//FUNCDEBUG
return 0;
}
struct scull_qset *scull_follow(struct scull_dev *dev,int n){
struct scull_qset *qs = dev->data;
#ifdef FUNCDEBUG
printk("<0> scull_follow begin\n");
#endif//FUNCDEBUG
if(qs==NULL){
qs=dev->data=kmalloc(sizeof(struct scull_qset),GFP_KERNEL);
if(qs==NULL)
return NULL;
memset(qs,0,sizeof(struct scull_qset));
}
while(n--){
if(qs->next==NULL){
qs->next=kmalloc(sizeof(struct scull_qset),GFP_KERNEL);
if(qs->next==NULL);
return NULL;
memset(qs->next,0,sizeof(struct scull_qset));
}
qs=qs->next;
continue;
}
#ifdef FUNCDEBUG
printk("<0> scull_follow end\n");
#endif//FUNCDEBUG
return qs;
}
ssize_t scull_read(struct file* flip, char __user *buf, size_t count, loff_t* f_pos){
struct scull_dev* dev=flip->private_data;
struct scull_qset* dptr;
int quantum=dev->quantum,qset=dev->qset;
int itemsize=quantum*qset;
int item,s_pos,q_pos,rest;
ssize_t retval=0;
read_function_count+=1;
#ifdef FUNCDEBUG
printk("<0> scull_read begin\n");
#endif//FUNCDEBUG
if (down_interruptible(&dev->sem))
return -ERESTARTSYS;
if (*f_pos > dev->size)
goto out;
if(*f_pos+count>dev->size)
count=dev->size-*f_pos;
item=(long)*f_pos / itemsize;
rest=(long)*f_pos % itemsize;
s_pos=rest / quantum;q_pos=rest % quantum;
dptr = scull_follow(dev,item);
if(dptr==NULL || !dptr->data || !dptr->data[s_pos])
goto out;
if(count > quantum-q_pos)
count=quantum-q_pos;
if(copy_to_user(buf,dptr->data[s_pos]+q_pos,count)){
retval=-EFAULT;
goto out;
}
*f_pos+=count;
retval=count;
out:
up(&dev->sem);
#ifdef FUNCDEBUG
printk("<0> scull_read end\n");
#endif//FUNCDEBUG
return retval;
}
ssize_t scull_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos){
struct scull_dev *dev =filp->private_data;
struct scull_qset *dptr;
int quantum=dev->quantum, qset=dev->qset;
int itemsize=quantum * qset;
int item, s_pos, q_pos, rest;
ssize_t retval= -ENOMEM;
write_function_count=+1;
#ifdef FUNCDEBUG
printk("<0> scull_write begin\n");
#endif//FUNCDEBUG
if(down_interruptible(&dev->sem))
return -ERESTARTSYS;
item=(long)*f_pos/itemsize;
rest=(long)*f_pos%itemsize;
s_pos=rest/quantum;q_pos=rest%quantum;
dptr=scull_follow(dev,item);
if(dptr==NULL)
goto out;
if(dptr->data==NULL){
dptr->data=kmalloc(qset*sizeof(char *),GFP_KERNEL);
if(dptr->data==NULL)
goto out;
memset(dptr->data,0,qset*sizeof(char *));
}
if(!dptr->data[s_pos]){
dptr->data[s_pos]=kmalloc(quantum,GFP_KERNEL);
if(!dptr->data[s_pos])
goto out;
}
if (count> quantum-q_pos)
count=quantum-q_pos;
if(copy_from_user(dptr->data[s_pos]+q_pos,buf,count)){
retval=-EFAULT;
goto out;
}
*f_pos=+count;
retval=count;
if(dev->size < *f_pos)
dev->size=*f_pos;
out:
up(&dev->sem);
#ifdef FUNCDEBUG
printk("<0> scull_write begin\n");
#endif//FUNCDEBUG
return retval;
}
int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){
#ifdef FUNCDEBUG
printk("<0> scull_ioctl begin\n");
#endif//FUNCDEBUG
//to be continued
#ifdef FUNCDEBUG
printk("<0> scull_ioctl end\n");
#endif//FUNCDEBUG
return 0;
}
loff_t scull_llseek(struct file* filp, loff_t off,int whence){
struct scull_dev *dev=filp->private_data;
loff_t newpos;
#ifdef FUNCDEBUG
printk("<0> scull_llseek begin\n");
#endif//FUNCDEBUG
switch(whence){
case 0: //SEEK_SET
newpos=off;
break;
case 1://SEEK_CUR
newpos=filp->f_pos+off;
break;
case 2://SEEK_END
newpos=dev->size+off;
break;
default:
return -EINVAL;
}
if(newpos<0)return -EINVAL;
filp->f_pos=newpos;
#ifdef FUNCDEBUG
printk("<0> scull_llseek end\n");
#endif//FUNCDEBUG
return newpos;
}
struct file_operations scull_fops={
.owner=THIS_MODULE,
.llseek=scull_llseek,
.read=scull_read,
.write=scull_write,
.ioctl=scull_ioctl,
.open=scull_open,
.release=scull_release
};
//module stuff
void scull_cleanup_module(void){
int i;
dev_t devno=MKDEV(scull_major,scull_minor);
if(scull_devices!=NULL){
for(i=0;i<scull_nr_devs;++i){
scull_trim(scull_devices+i);
cdev_del(&scull_devices[i].cdev);
}
kfree(scull_devices);
}
#ifdef SCULL_DEBUG
scull_remove_proc();
#endif
unregister_chrdev_region(devno,scull_nr_devs);
//scull_p_clean_up();
//scull_access_cleanup();
printk("<0> Scull Module has been unregistered\n");
}
static void scull_setup_cdev(struct scull_dev* dev, int index)
{
int err, devno=MKDEV(scull_major,scull_major+index);
cdev_init(&dev->cdev,&scull_fops);
dev->cdev.owner=THIS_MODULE;
dev->cdev.ops=&scull_fops;
err=cdev_add(&dev->cdev,devno,1);
//if failed
#ifdef FUNCDEBUG
printk("<0> scull_setup_cdev begin\n");
#endif//FUNCDEBUG
if(err)
printk(KERN_NOTICE "Error %d adding scull %d",err,index);
#ifdef FUNCDEBUG
printk("<0> scull_setup_cdev end\n");
#endif//FUNCDEBUG
}
int scull_init_module(void){
int result, i;
dev_t dev=0;
if(scull_major!=0){
dev = MKDEV(scull_major,scull_minor);
result = register_chrdev_region(dev,scull_nr_devs,"scull");
}else{
result = alloc_chrdev_region(&dev,scull_minor,scull_nr_devs,"scull");
scull_major=MAJOR(dev);
}
if (result < 0){
printk(KERN_WARNING "scull cannot get major %d\n", scull_major);
return result;
}
scull_devices=kmalloc(scull_nr_devs*sizeof(struct scull_dev),GFP_KERNEL);
if(scull_devices==NULL){
result =-ENOMEM;
goto fail;
}
memset(scull_devices,0,scull_nr_devs*sizeof(struct scull_dev));
for(i=0;i<scull_nr_devs;++i){
scull_devices[i].quantum=scull_quantum;
scull_devices[i].qset=scull_qset;
init_MUTEX(&scull_devices[i].sem);
scull_setup_cdev(&scull_devices[i],i);
}
dev=MKDEV(scull_major,scull_minor+scull_nr_devs);
//dev += scull_p_init(dev);
//dev += scull_access_init(dev);
#ifdef SCULL_DEBUG
scull_create_proc();
#endif
printk("<0> Scull Module has been registered\n");
return 0;
fail:
scull_cleanup_module();
return result;
}
module_init(scull_init_module);
module_exit(scull_cleanup_module);
Last edited by Igor007; 09-09-2005 at 05:09 PM.
|