1 #include <linux/init.h>
2 #include <linux/module.h>
4 #include <linux/cdev.h>
5 #include <linux/kernel.h>
6 #include <linux/errno.h>
7 #include <asm/uaccess.h>
10 #include "modulbus_register.h"
13 #define DRIVER_NAME "vmoddor"
14 #define PFX DRIVER_NAME ": "
16 static struct vmod_devices dt
, *dev_table
= &dt
;
18 static struct vmoddor_dev vmoddor
[VMODDOR_MAX_DEVICES
];
20 static struct cdev
*cdev
;
23 static inline void vmoddor_write_word(struct vmoddor_dev
*pd
, int offset
, uint16_t value
)
25 unsigned long ioaddr
= pd
->handle
+ offset
;
27 if (pd
->is_big_endian
)
28 iowrite16be(value
, (u16
*)ioaddr
);
30 iowrite16(value
, (u16
*)ioaddr
);
33 static void vmoddor_write_byte(struct vmoddor_dev
*pd
, int offset
, uint8_t value
)
35 unsigned long ioaddr
= pd
->handle
+ offset
;
37 iowrite8(value
, (u8
*)ioaddr
);
40 static void vmoddor_write_4bits(struct vmoddor_dev
*pd
, int offset
, uint8_t value
)
42 vmoddor_write_byte(pd
, offset
, value
& 0xf);
45 int vmoddor_open(struct inode
*ino
, struct file
*filp
)
50 int vmoddor_release(struct inode
*ino
, struct file
*filp
)
55 static int vmoddor_ioctl(struct inode
*inode
, struct file
*fp
, unsigned op
,
58 unsigned int minor
= iminor(inode
);
59 struct vmoddor_dev
*pd
= &vmoddor
[minor
];
67 struct vmoddor_arg val
;
69 if(copy_from_user((char *)&val
, (char *)arg
, sizeof(struct vmoddor_arg
)))
77 vmoddor_write_word(pd
, 0, val
.data
);
84 vmoddor_write_byte(pd
, val
.offset
, val
.data
& 0xff);
88 if((val
.offset
< 2) || (val
.offset
> 5))
91 vmoddor_write_4bits(pd
, val
.offset
, val
.data
& 0xff);
100 printk(KERN_INFO PFX
"Ioctl operation not implemented\n");
108 struct file_operations vmoddor_fops
= {
109 .owner
= THIS_MODULE
,
110 .ioctl
= vmoddor_ioctl
,
111 .open
= vmoddor_open
,
112 .release
= vmoddor_release
116 static int __init
vmoddor_init(void)
123 printk (KERN_INFO PFX
"Init Module\n");
125 err
= read_params(DRIVER_NAME
, dev_table
);
129 printk(KERN_INFO PFX
"initialized driver for %d (max %d) cards\n",
130 dev_table
->num_modules
, VMODDOR_MAX_DEVICES
);
132 err
= alloc_chrdev_region(&dev
, 0, VMODDOR_MAX_DEVICES
, "vmoddor");
134 printk(KERN_ALERT PFX
"Cannot allocate character device\n");
144 cdev_init(cdev
, &vmoddor_fops
);
145 cdev
->owner
= THIS_MODULE
;
146 cdev
->ops
= &vmoddor_fops
;
148 err
= cdev_add(cdev
, dev
, VMODDOR_MAX_DEVICES
);
150 printk(KERN_ALERT PFX
"Error %d adding device\n", err
);
154 for(i
= 0; i
< dev_table
->num_modules
; i
++){
155 struct vmod_dev
*mod
= &dev_table
->module
[i
];
157 vmoddor
[i
].lun
= mod
->lun
;
158 vmoddor
[i
].cname
= mod
->carrier_name
;
159 vmoddor
[i
].carrier
= mod
->carrier_lun
;
160 vmoddor
[i
].slot
= mod
->slot
;
161 vmoddor
[i
].handle
= mod
->address
;
163 vmoddor
[i
].is_big_endian
= mod
->is_big_endian
;
170 unregister_chrdev_region(dev
, VMODDOR_MAX_DEVICES
);
175 static void __exit
vmoddor_exit(void)
178 unregister_chrdev_region(dev
, VMODDOR_MAX_DEVICES
);
179 printk(KERN_INFO PFX
"Exit module.\n");
182 module_init(vmoddor_init
);
183 module_exit(vmoddor_exit
);
185 MODULE_AUTHOR("Samuel I. Gonsalvez");
186 MODULE_LICENSE("GPL");
187 MODULE_DESCRIPTION("VMODDOR device driver");
188 MODULE_VERSION("1.0");