Thanks gobs
=Eric
PS. Yes, I did define __KERNEL__ and MODULE at the top of my only source
file, before the #include's.
/****cut here*******
/*
main.c
*/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <asm/system.h>
#include <asm/segment.h>
#include "d0.h"
int d0_major = D0_MAJOR;
int d0_nr_devs = D0_NR_DEVS;
d0_dev *devlist, *curdev;
struct file_operations d0_fops =
{
NULL,
d0_read,
d0_write,
NULL,
NULL,
NULL,
NULL,
d0_open,
d0_release,
NULL,
};
int init_module(void)
{
int num;
printk(KERN_CRIT "Entering init_module()\n");
if((devlist = (d0_dev *)kmalloc(sizeof(d0_dev), GFP_KERNEL)) == 0)
return -ENOMEM;
curdev = devlist;
printk(KERN_CRIT"init_module() created device at %p\n", curdev);
num = register_chrdev(d0_major, "d0", &d0_fops);
//need error trap here
return num;
}
void cleanup_module(void)
{
unregister_chrdev(d0_major, "d0");
trimlist(devlist);
kfree(devlist);
}
int d0_open(struct inode *inode, struct file *fp)
{
int type = TYPE(inode->i_rdev);
//int num = NUM(inode->i_rdev);
printk(KERN_CRIT"d0_open() entered\n");
if(type)
{
if(type > MAX_TYPE)
return -ENODEV;
fp->f_op = &d0_fops;
return fp->f_op->open(inode, fp);
}
if((fp->f_flags & O_ACCMODE) == O_WRONLY)
trimlist(curdev = devlist);
fp->private_data = devlist;
MOD_INC_USE_COUNT;
return 0;
}
void d0_release(struct inode *inode, struct file * fp)
{
trimlist(curdev = devlist);
MOD_DEC_USE_COUNT;
}
int d0_read(struct inode *inode, struct file * fp, char *buf, int buflen)
{
unsigned long f_pos = fp->f_pos;
printk(KERN_CRIT"d0_read() entered\n");
curdev = get_cur_dev(curdev ? curdev : devlist, fp->f_pos/sizeof(devlist->data));
if(f_pos + buflen > sizeof(devlist->data))
buflen = sizeof(devlist->data) - f_pos;
printk(KERN_CRIT"d0_read() sets buflen to %d\n", buflen);
memcpy_tofs(buf, curdev->data + f_pos, buflen);
fp->f_pos += buflen;
return buflen;
}
int d0_write(struct inode *inode, struct file * fp, const char * buf, int buflen)
{
unsigned long dev_no;
unsigned long f_pos = fp->f_pos;
f_pos = (unsigned long)fp->f_pos % sizeof(devlist->data); //offset
dev_no = (unsigned long)fp->f_pos / sizeof(devlist->data); //index
printk(KERN_CRIT "d0_write() says f_pos is %ld, dev_no is %ld\n", f_pos, dev_no);
curdev = get_cur_dev(curdev ? curdev : devlist, dev_no);
if(f_pos + buflen > sizeof(devlist->data))
{
buflen = sizeof(devlist->data) - f_pos;
printk(KERN_CRIT "d0_write trimmed buflen\n");
}
printk(KERN_CRIT "d0_write() set buflen to %d\n", buflen);
if(buflen == 0)
{
printk(KERN_CRIT "Buffer overrun, size is %d\n", buflen);
curdev->next = (d0_dev *)kmalloc(sizeof(d0_dev), GFP_KERNEL);
if(curdev->next == 0)
return -ENOMEM;
curdev = curdev->next;
return 0;
}
memcpy_fromfs(curdev->data + f_pos, buf, buflen);
fp->f_pos += buflen;
return buflen;
}
struct d0_dev *get_cur_dev(struct d0_dev *d, unsigned long index)
{
unsigned long current_offset;
d0_dev *dret;
printk(KERN_CRIT"get_cur_dev() entered\n");
if(!d)
{
printk(KERN_CRIT"get_cur_dev() got a null pointer!\n");
return 0;
}
printk(KERN_CRIT"get_cur_dev() about to get offset using ptr %p\n", d);
//can walk forward, but 'backward' walks of SLL require going to the
//head and starting over
for(dret = devlist, current_offset = 0; (current_offset < index) && dret; dret = d->next)
;
printk(KERN_CRIT"Leaving get_cur_dev(), returning %p\n", dret);
return dret;
}
int trimlist(d0_dev * list)
{
int i;
for(i = 0, list = list->next; list; list = list->next, ++i)
kfree(list);
printk(KERN_CRIT"trimlist wiped out %d items\n", i);
return i;
}
/********cut here *************/
/*
d0.h
*/
#define D0_MAJOR 64
#define D0_NR_DEVS 1
#define MAX_TYPE 5
#define TYPE(dev) (MINOR(dev) >> 4)
#define NUM(dev) (MINOR(dev) & 0xf)
typedef struct d0_dev{
char data[0x100 - sizeof(struct d0_dev *)];
struct d0_dev *next;
} d0_dev;
int d0_open(struct inode *inode, struct file *fp);
void d0_release(struct inode *inode, struct file *fp);
int d0_read(struct inode *inode, struct file * fp, char *buf, int buflen);
int d0_write(struct inode *inode, struct file * fp, const char * buf, int buflen);
struct d0_dev *get_cur_dev(struct d0_dev *d, unsigned long offset);
int trimlist(d0_dev * list);
#makefile
MAKEFILE=Makefile
SRCS = main.c
HEADERS = d0.h
d0.o : $(SRCS) $(HEADERS) $(MAKEFILE)
cc -c -O -Wall -o d0.o $(SRCS)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu