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/moxa-ia261.h>
31 #define MOXA_DIO_MINOR 104
33 static unsigned int di_addr
=MOXA_IA261_UART_DIO_VIRT_BASE
+ 0x60;
34 static unsigned int do_addr
=MOXA_IA261_UART_DIO_VIRT_BASE
+ 0x50;
35 static unsigned char do_state_keep
=0;
38 // DIO file operaiton function call
46 #define IOCTL_DIO_GET_MODE 1
47 #define IOCTL_DIO_SET_MODE 2
48 #define IOCTL_DIO_GET_DATA 3
49 #define IOCTL_DIO_SET_DATA 4
50 #define IOCTL_SET_DOUT 15
51 #define IOCTL_GET_DOUT 16
52 #define IOCTL_GET_DIN 17
53 struct dio_set_struct
{
55 int mode_data
; // 1 for input, 0 for output, 1 for high, 0 for low
59 struct proc_dir_entry
* dio_proc
;
60 #define dio_proc_name "driver/dio"
61 int dio_read_proc(char *page
, char **start
, off_t off
, int count
, int *eof
, void *data
)
65 unsigned char di_state
;
67 for ( pin_count
= 0; pin_count
< MAX_DIO
; pin_count
++ )
68 out
+= sprintf(out
, "DO[%d]:%s\n", pin_count
, do_state_keep
&(1<<pin_count
)?"HIGH":"LOW");
69 di_state
= inb(di_addr
);
70 for ( pin_count
= 0; pin_count
< MAX_DIO
; pin_count
++ )
71 out
+= sprintf(out
, "DI[%d]:%s\n", pin_count
, di_state
&(1<<pin_count
)?"HIGH":"LOW");
73 len
= out
-page
- off
;
85 int dio_write_proc(struct file
*file
, const char __user
*buffer
, unsigned long count
, void *data
)
87 char kbuffer
[64], mode
[2], pin
[3];
88 int num_count
, var_num
, byte_count
;
90 if ( copy_from_user(kbuffer
, (char*)buffer
, count
) )
93 kbuffer
[count
+1] = '\0';
96 num_count
= var_num
= 0 ;
98 for ( byte_count
= 0 ; byte_count
< count
; byte_count
++ ) {
99 if ( kbuffer
[byte_count
] != ' ' && kbuffer
[byte_count
] != '\0' && kbuffer
[byte_count
] != '\n' ) {
100 if ( var_num
== 0 ) {
102 if ( num_count
> 2 ) {
103 printk("The max pin number is %d !!\n",MAX_DIO
);
106 pin
[num_count
-1] = kbuffer
[byte_count
];
107 pin
[num_count
] = '\0';
109 if ( var_num
== 1 ) { // to read high or low for output(DO) mode
111 if ( num_count
> 1 ) {
112 printk("The high = %d, low = %d !!\n", DIO_HIGH
, DIO_LOW
);
115 mode
[num_count
-1] = kbuffer
[byte_count
];
116 mode
[num_count
] = '\0';
126 num_count
= simple_strtol(pin
, NULL
, 0); // to keep pin number
127 byte_count
= simple_strtol(mode
, NULL
, 0); // to keep state setting
129 if ( num_count
>= MAX_DIO
) {
130 //printk("The max pin number is %d !!\n",MAX_GPIO-1);
131 goto error_write_proc
;
134 if ( byte_count
== DIO_HIGH
)
135 do_state_keep
|= (1 << num_count
);
136 else if ( byte_count
== DIO_LOW
)
137 do_state_keep
&= !(1<< num_count
);
139 goto error_write_proc
;
140 outb(do_state_keep
, do_addr
);
148 static int dio_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
150 struct dio_set_struct set
;
151 unsigned char di_state
;
154 case IOCTL_SET_DOUT
:
155 if ( copy_from_user(&set
, (struct dio_set_struct
*)arg
, sizeof(struct dio_set_struct
)) )
157 if ( set
.io_number
< 0 || set
.io_number
>= MAX_DIO
)
159 if ( set
.mode_data
== DIO_HIGH
)
160 do_state_keep
|= (1<<set
.io_number
);
161 else if ( set
.mode_data
== DIO_LOW
)
162 do_state_keep
&= !(1<<set
.io_number
);
165 outb(do_state_keep
, do_addr
);
167 case IOCTL_GET_DOUT
:
169 if ( copy_from_user(&set
, (struct dio_set_struct
*)arg
, sizeof(struct dio_set_struct
)) )
171 if ( set
.io_number
< 0 || set
.io_number
>= MAX_DIO
)
173 if ( cmd
== IOCTL_GET_DOUT
) {
174 if ( do_state_keep
& (1<<set
.io_number
) )
179 di_state
= inb(di_addr
);
180 if ( di_state
& (1<<set
.io_number
) )
185 if ( copy_to_user((struct dio_set_struct
*)arg
, &set
, sizeof(struct dio_set_struct
)) )
194 static int dio_open(struct inode
*inode
, struct file
*file
)
196 if ( MINOR(inode
->i_rdev
) == MOXA_DIO_MINOR
)
202 static int dio_release(struct inode
*inode
, struct file
*file
)
207 static struct file_operations dio_fops
= {
215 static struct miscdevice dio_dev
= {
221 static void __exit
dio_exit(void)
223 remove_proc_entry(dio_proc_name
,0);
224 misc_deregister(&dio_dev
);
227 static int __init
dio_init(void)
229 printk("Moxa IA261 Register DI/DO misc ver1.0 ");
230 if ( misc_register(&dio_dev
) ) {
235 outb(do_state_keep
, do_addr
);
236 dio_proc
= create_proc_entry(dio_proc_name
, 0, NULL
);
237 dio_proc
->read_proc
= dio_read_proc
;
238 dio_proc
->write_proc
= dio_write_proc
;
244 module_init(dio_init
);
245 module_exit(dio_exit
);
247 MODULE_AUTHOR("Victor Yu");
248 MODULE_LICENSE("GPL");