This source file includes following definitions.
- aux_write_dev
- aux_write_ack
- aux_write_cmd
- get_from_queue
- queue_empty
- aux_interrupt
- release_aux
- open_aux
- write_aux
- read_aux
- aux_select
- psaux_init
- poll_status
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <linux/timer.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
22 #include <linux/fcntl.h>
23 #include <linux/errno.h>
24
25 #include <asm/io.h>
26 #include <asm/segment.h>
27 #include <asm/system.h>
28
29
30 #define AUX_INPUT_PORT 0x60
31 #define AUX_OUTPUT_PORT 0x60
32 #define AUX_COMMAND 0x64
33 #define AUX_STATUS 0x64
34
35
36 #define AUX_OBUF_FULL 0x01
37 #define AUX_IBUF_FULL 0x02
38
39
40 #define AUX_CMD_WRITE 0x60
41 #define AUX_MAGIC_WRITE 0xd4
42
43 #define AUX_INTS_ON 0x47
44 #define AUX_INTS_OFF 0x65
45
46 #define AUX_DISABLE 0xa7
47 #define AUX_ENABLE 0xa8
48
49
50 #define AUX_SET_RES 0xe8
51 #define AUX_SET_SCALE 0xe9
52 #define AUX_SET_STREAM 0xea
53 #define AUX_SET_SAMPLE 0xf3
54 #define AUX_ENABLE_DEV 0xf4
55 #define AUX_DISABLE_DEV 0xf5
56 #define AUX_RESET 0xff
57
58 #define MAX_RETRIES 3
59 #define AUX_IRQ 12
60 #define AUX_BUF_SIZE 2048
61
62 extern unsigned char aux_device_present;
63
64 struct aux_queue {
65 unsigned long head;
66 unsigned long tail;
67 struct wait_queue *proc_list;
68 unsigned char buf[AUX_BUF_SIZE];
69 };
70
71 static struct aux_queue *queue;
72 static int aux_ready = 0;
73 static int aux_busy = 0;
74 static int aux_present = 0;
75
76 static int poll_status(void);
77
78
79
80
81 static void aux_write_dev(int val)
82 {
83 poll_status();
84 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
85 poll_status();
86 outb_p(val,AUX_OUTPUT_PORT);
87
88 }
89
90 #if 0
91
92
93
94
95 static int aux_write_ack(int val)
96 {
97 aux_write_dev(val);
98 while ((inb(AUX_STATUS) & AUX_OBUF_FULL) == 0);
99 if ((inb(AUX_STATUS) & 0x20) == 0x20)
100 {
101 return (inb(AUX_INPUT_PORT));
102 }
103 return 0;
104 }
105 #endif
106
107
108
109
110
111 static void aux_write_cmd(int val)
112 {
113 poll_status();
114 outb_p(AUX_CMD_WRITE,AUX_COMMAND);
115 poll_status();
116 outb_p(val,AUX_OUTPUT_PORT);
117 }
118
119
120 static unsigned int get_from_queue(void)
121 {
122 unsigned int result;
123 unsigned long flags;
124
125 save_flags(flags);
126 cli();
127 result = queue->buf[queue->tail];
128 queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
129 restore_flags(flags);
130 return result;
131 }
132
133
134 static inline int queue_empty(void)
135 {
136 return queue->head == queue->tail;
137 }
138
139
140
141
142
143
144
145 static void aux_interrupt(int cpl)
146 {
147 int head = queue->head;
148 int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
149
150 queue->buf[head] = inb(AUX_INPUT_PORT);
151 if (head != maxhead) {
152 head++;
153 head &= AUX_BUF_SIZE-1;
154 }
155 queue->head = head;
156 aux_ready = 1;
157 wake_up_interruptible(&queue->proc_list);
158 }
159
160
161 static void release_aux(struct inode * inode, struct file * file)
162 {
163 poll_status();
164 aux_write_dev(AUX_DISABLE_DEV);
165 poll_status();
166 outb_p(AUX_DISABLE,AUX_COMMAND);
167 aux_write_cmd(AUX_INTS_OFF);
168 free_irq(AUX_IRQ);
169 aux_busy = 0;
170 }
171
172
173
174
175
176
177
178 static int open_aux(struct inode * inode, struct file * file)
179 {
180 if (!aux_present)
181 return -EINVAL;
182 if (aux_busy)
183 return -EBUSY;
184 if (!poll_status())
185 return -EBUSY;
186 aux_busy = 1;
187 queue->head = queue->tail = 0;
188 if (request_irq(AUX_IRQ, aux_interrupt))
189 return -EBUSY;
190 aux_write_dev(AUX_ENABLE_DEV);
191 aux_write_cmd(AUX_INTS_ON);
192 poll_status();
193 outb_p(AUX_ENABLE,AUX_COMMAND);
194 return 0;
195 }
196
197
198
199
200
201
202 static int write_aux(struct inode * inode, struct file * file, char * buffer, int count)
203 {
204 int i = count;
205
206 while (i--) {
207 if (!poll_status())
208 return -EIO;
209 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
210 if (!poll_status())
211 return -EIO;
212 outb_p(get_fs_byte(buffer++),AUX_OUTPUT_PORT);
213 }
214 inode->i_mtime = CURRENT_TIME;
215 return count;
216 }
217
218
219
220
221
222
223 static int read_aux(struct inode * inode, struct file * file, char * buffer, int count)
224 {
225 struct wait_queue wait = { current, NULL };
226 int i = count;
227 unsigned char c;
228
229 if (queue_empty()) {
230 if (file->f_flags & O_NONBLOCK)
231 return -EAGAIN;
232 add_wait_queue(&queue->proc_list, &wait);
233 repeat:
234 current->state = TASK_INTERRUPTIBLE;
235 if (queue_empty() && !(current->signal & ~current->blocked)) {
236 schedule();
237 goto repeat;
238 }
239 current->state = TASK_RUNNING;
240 remove_wait_queue(&queue->proc_list, &wait);
241 }
242 while (i > 0 && !queue_empty()) {
243 c = get_from_queue();
244 put_fs_byte(c, buffer++);
245 i--;
246 }
247 aux_ready = !queue_empty();
248 if (count-i) {
249 inode->i_atime = CURRENT_TIME;
250 return count-i;
251 }
252 if (current->signal & ~current->blocked)
253 return -ERESTARTSYS;
254 return 0;
255 }
256
257
258 static int aux_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
259 {
260 if (sel_type != SEL_IN)
261 return 0;
262 if (aux_ready)
263 return 1;
264 select_wait(&queue->proc_list, wait);
265 return 0;
266 }
267
268
269 struct file_operations psaux_fops = {
270 NULL,
271 read_aux,
272 write_aux,
273 NULL,
274 aux_select,
275 NULL,
276 NULL,
277 open_aux,
278 release_aux,
279 };
280
281
282 unsigned long psaux_init(unsigned long kmem_start)
283 {
284 if (aux_device_present != 0xaa) {
285 return kmem_start;
286 }
287 printk("PS/2 type pointing device detected and installed.\n");
288 queue = (struct aux_queue *) kmem_start;
289 kmem_start += sizeof (struct aux_queue);
290 queue->head = queue->tail = 0;
291 queue->proc_list = NULL;
292 aux_present = 1;
293 poll_status();
294 outb_p(AUX_DISABLE,AUX_COMMAND);
295 aux_write_cmd(AUX_INTS_OFF);
296 return kmem_start;
297 }
298
299
300 static int poll_status(void)
301 {
302 int retries=0;
303
304 while ((inb(AUX_STATUS)&0x03) && retries++ < MAX_RETRIES) {
305 if (inb_p(AUX_STATUS)&0x01)
306 inb_p(AUX_INPUT_PORT);
307 current->state = TASK_INTERRUPTIBLE;
308 current->timeout = jiffies + 5;
309 schedule();
310 }
311 return !(retries==MAX_RETRIES);
312 }