MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / char / moxa_ia261_dio.c
blobe1f4b6f438efa90fbe569a657b021199c071ef3d
1 /*
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:
5 * dio: 104
7 * History:
8 * Date Aurhor Comment
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>
26 #include <asm/io.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
40 #define MAX_DIO 8
42 #define DIO_INPUT 1
43 #define DIO_OUTPUT 0
44 #define DIO_HIGH 1
45 #define DIO_LOW 0
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 {
54 int io_number;
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)
63 char *out = page;
64 int pin_count, len;
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;
74 if (len < count) {
75 *eof = 1;
76 if (len <= 0)
77 return 0;
78 } else
79 len = count;
80 *start = page + off;
82 return len;
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) )
91 return -EFAULT;
93 kbuffer[count+1] = '\0';
94 memset(pin,0,3);
95 memset(mode,0,2);
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 ) {
101 num_count++;
102 if ( num_count > 2 ) {
103 printk("The max pin number is %d !!\n",MAX_DIO);
104 return -EINVAL;
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
110 num_count++;
111 if ( num_count > 1 ) {
112 printk("The high = %d, low = %d !!\n", DIO_HIGH, DIO_LOW);
113 return -EINVAL;
115 mode[num_count-1] = kbuffer[byte_count];
116 mode[num_count] = '\0';
118 } else {
119 if ( pin[0] != 0 ) {
120 var_num = 1;
121 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);
138 else
139 goto error_write_proc;
140 outb(do_state_keep, do_addr);
142 return count;
144 error_write_proc:
145 return -EINVAL;
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;
153 switch ( cmd ) {
154 case IOCTL_SET_DOUT :
155 if ( copy_from_user(&set, (struct dio_set_struct *)arg, sizeof(struct dio_set_struct)) )
156 return -EFAULT;
157 if ( set.io_number < 0 || set.io_number >= MAX_DIO )
158 return -EINVAL;
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);
163 else
164 return -EINVAL;
165 outb(do_state_keep, do_addr);
166 break;
167 case IOCTL_GET_DOUT :
168 case IOCTL_GET_DIN :
169 if ( copy_from_user(&set, (struct dio_set_struct *)arg, sizeof(struct dio_set_struct)) )
170 return -EFAULT;
171 if ( set.io_number < 0 || set.io_number >= MAX_DIO )
172 return -EINVAL;
173 if ( cmd == IOCTL_GET_DOUT ) {
174 if ( do_state_keep & (1<<set.io_number) )
175 set.mode_data = 1;
176 else
177 set.mode_data = 0;
178 } else {
179 di_state = inb(di_addr);
180 if ( di_state & (1<<set.io_number) )
181 set.mode_data = 1;
182 else
183 set.mode_data = 0;
185 if ( copy_to_user((struct dio_set_struct *)arg, &set, sizeof(struct dio_set_struct)) )
186 return -EFAULT;
187 break;
188 default:
189 return -EINVAL;
191 return 0;
194 static int dio_open(struct inode *inode, struct file *file)
196 if ( MINOR(inode->i_rdev) == MOXA_DIO_MINOR )
197 return 0;
199 return -ENODEV;
202 static int dio_release(struct inode *inode, struct file *file)
204 return 0;
207 static struct file_operations dio_fops = {
208 owner:THIS_MODULE,
209 llseek:NULL,
210 ioctl:dio_ioctl,
211 open:dio_open,
212 release:dio_release,
215 static struct miscdevice dio_dev = {
216 MOXA_DIO_MINOR,
217 "dio",
218 &dio_fops
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) ) {
231 printk("fail !\n");
232 return -ENOMEM;
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;
240 printk("OK.\n");
241 return 0;
244 module_init(dio_init);
245 module_exit(dio_exit);
247 MODULE_AUTHOR("Victor Yu");
248 MODULE_LICENSE("GPL");