2 * This is Moxa IA261 DI/DO device driver.
3 * It is from misc interface. So the device node major number is 8.
4 * The device node minor number is following:
9 * 12-13-2007 Victor Yu. Create it.
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/types.h>
14 #include <linux/miscdevice.h>
15 #include <linux/fcntl.h>
16 #include <linux/init.h>
17 #include <linux/poll.h>
18 #include <linux/proc_fs.h>
19 #include <linux/spinlock.h>
20 #include <linux/delay.h>
21 #include <linux/rtc.h>
22 #include <linux/timer.h>
23 #include <linux/ioport.h>
24 #include <linux/proc_fs.h>
27 #include <asm/uaccess.h>
28 #include <asm/system.h>
29 #include <asm/arch/cpe/cpe.h>
31 #define MOXA_DIO_MINOR 107
33 #define DI_PADDR 0x88000000
34 #define DO_PADDR 0x84000000
36 static unsigned int di_addr
;
37 static unsigned int do_addr
;
38 static unsigned char do_state_keep
=0;
41 // DIO file operaiton function call
49 #define IOCTL_DIO_GET_MODE 1
50 #define IOCTL_DIO_SET_MODE 2
51 #define IOCTL_DIO_GET_DATA 3
52 #define IOCTL_DIO_SET_DATA 4
53 #define IOCTL_SET_DOUT 15
54 #define IOCTL_GET_DOUT 16
55 #define IOCTL_GET_DIN 17
56 struct dio_set_struct
{
58 int mode_data
; // 1 for input, 0 for output, 1 for high, 0 for low
62 struct proc_dir_entry
* dio_proc
;
63 #define dio_proc_name "driver/dio1"
64 int dio_read_proc(char *page
, char **start
, off_t off
, int count
, int *eof
, void *data
)
68 unsigned char di_state
;
70 for ( pin_count
= 0; pin_count
< MAX_DIO
; pin_count
++ )
71 out
+= sprintf(out
, "DO[%d]:%s\n", pin_count
, do_state_keep
&(1<<pin_count
)?"HIGH":"LOW");
72 di_state
= inb(di_addr
);
73 for ( pin_count
= 0; pin_count
< MAX_DIO
; pin_count
++ )
74 out
+= sprintf(out
, "DI[%d]:%s\n", pin_count
, di_state
&(1<<pin_count
)?"HIGH":"LOW");
76 len
= out
-page
- off
;
88 int dio_write_proc(struct file
*file
, const char __user
*buffer
, unsigned long count
, void *data
)
90 char kbuffer
[64], mode
[2], pin
[3];
91 int num_count
, var_num
, byte_count
;
93 if ( copy_from_user(kbuffer
, (char*)buffer
, count
) )
96 kbuffer
[count
+1] = '\0';
99 num_count
= var_num
= 0 ;
101 for ( byte_count
= 0 ; byte_count
< count
; byte_count
++ ) {
102 if ( kbuffer
[byte_count
] != ' ' && kbuffer
[byte_count
] != '\0' && kbuffer
[byte_count
] != '\n' ) {
103 if ( var_num
== 0 ) {
105 if ( num_count
> 2 ) {
106 printk("The max pin number is %d !!\n",MAX_DIO
);
109 pin
[num_count
-1] = kbuffer
[byte_count
];
110 pin
[num_count
] = '\0';
112 if ( var_num
== 1 ) { // to read high or low for output(DO) mode
114 if ( num_count
> 1 ) {
115 printk("The high = %d, low = %d !!\n", DIO_HIGH
, DIO_LOW
);
118 mode
[num_count
-1] = kbuffer
[byte_count
];
119 mode
[num_count
] = '\0';
129 num_count
= simple_strtol(pin
, NULL
, 0); // to keep pin number
130 byte_count
= simple_strtol(mode
, NULL
, 0); // to keep state setting
132 if ( num_count
>= MAX_DIO
) {
133 //printk("The max pin number is %d !!\n",MAX_GPIO-1);
134 goto error_write_proc
;
137 if ( byte_count
== DIO_HIGH
)
138 do_state_keep
|= (1 << num_count
);
139 else if ( byte_count
== DIO_LOW
)
140 do_state_keep
&= ~(1<< num_count
);
142 goto error_write_proc
;
143 outb(do_state_keep
, do_addr
);
151 static int dio_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
153 struct dio_set_struct set
;
154 unsigned char di_state
;
157 case IOCTL_SET_DOUT
:
158 if ( copy_from_user(&set
, (struct dio_set_struct
*)arg
, sizeof(struct dio_set_struct
)) )
160 if ( set
.io_number
< 0 || set
.io_number
>= MAX_DIO
)
162 if ( set
.mode_data
== DIO_HIGH
)
163 do_state_keep
|= (1<<set
.io_number
);
164 else if ( set
.mode_data
== DIO_LOW
)
165 do_state_keep
&= ~(1<<set
.io_number
);
168 outb(do_state_keep
, do_addr
);
170 case IOCTL_GET_DOUT
:
172 if ( copy_from_user(&set
, (struct dio_set_struct
*)arg
, sizeof(struct dio_set_struct
)) )
174 if ( set
.io_number
< 0 || set
.io_number
>= MAX_DIO
)
176 if ( cmd
== IOCTL_GET_DOUT
) {
177 if ( do_state_keep
& (1<<set
.io_number
) )
182 di_state
= inb(di_addr
);
183 if ( di_state
& (1<<(set
.io_number
+4)) )
188 if ( copy_to_user((struct dio_set_struct
*)arg
, &set
, sizeof(struct dio_set_struct
)) )
197 static int dio_open(struct inode
*inode
, struct file
*file
)
199 if ( MINOR(inode
->i_rdev
) == MOXA_DIO_MINOR
)
205 static int dio_release(struct inode
*inode
, struct file
*file
)
210 static struct file_operations dio_fops
= {
218 static struct miscdevice dio_dev
= {
224 static void __exit
dio_exit(void)
226 remove_proc_entry(dio_proc_name
,0);
227 misc_deregister(&dio_dev
);
228 iounmap((void *)di_addr
);
229 iounmap((void *)do_addr
);
232 static int __init
dio_init(void)
234 printk("Moxa W325 Register DI/DO misc ver1.0 ");
236 di_addr
=(unsigned long) ioremap((unsigned long)DI_PADDR
, 0x4000);
237 do_addr
=(unsigned long) ioremap((unsigned long)DO_PADDR
, 0x4000);
239 if ( di_addr
==NULL
|| do_addr
==NULL
|| misc_register(&dio_dev
) ) {
244 outb(do_state_keep
, do_addr
);
245 dio_proc
= create_proc_entry(dio_proc_name
, 0, NULL
);
246 dio_proc
->read_proc
= dio_read_proc
;
247 dio_proc
->write_proc
= dio_write_proc
;
253 module_init(dio_init
);
254 module_exit(dio_exit
);
256 MODULE_AUTHOR("Victor Yu");
257 MODULE_LICENSE("GPL");