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
82
83 static void aux_write_dev(int val)
84 {
85 poll_status();
86 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
87 poll_status();
88 outb_p(val,AUX_OUTPUT_PORT);
89
90 }
91
92
93
94
95
96
97 static int aux_write_ack(int val)
98 {
99 aux_write_dev(val);
100 while ((inb(AUX_STATUS) & AUX_OBUF_FULL) == 0);
101 if ((inb(AUX_STATUS) & 0x20) == 0x20)
102 {
103 return (inb(AUX_INPUT_PORT));
104 }
105 return 0;
106 }
107
108
109
110
111
112
113 static void aux_write_cmd(int val)
114 {
115 poll_status();
116 outb_p(AUX_CMD_WRITE,AUX_COMMAND);
117 poll_status();
118 outb_p(val,AUX_OUTPUT_PORT);
119 }
120
121
122 static unsigned int get_from_queue()
123 {
124 unsigned int result;
125 unsigned long flags;
126
127 __asm__ __volatile__ ("pushfl ; popl %0; cli":"=r" (flags));
128 result = queue->buf[queue->tail];
129 queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
130 __asm__ __volatile__ ("pushl %0 ; popfl"::"r" (flags));
131 return result;
132 }
133
134
135 static inline int queue_empty()
136 {
137 return queue->head == queue->tail;
138 }
139
140
141
142
143
144
145
146 static void aux_interrupt(int cpl)
147 {
148 int head = queue->head;
149 int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
150
151 queue->buf[head] = inb(AUX_INPUT_PORT);
152 if (head != maxhead) {
153 head++;
154 head &= AUX_BUF_SIZE-1;
155 }
156 queue->head = head;
157 aux_ready = 1;
158 wake_up(&queue->proc_list);
159 }
160
161
162 static void release_aux(struct inode * inode, struct file * file)
163 {
164 poll_status();
165 outb_p(AUX_DISABLE,AUX_COMMAND);
166 aux_write_dev(AUX_DISABLE_DEV);
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 int i = count;
226 unsigned char c;
227
228 if (queue_empty()) {
229 if (file->f_flags & O_NONBLOCK)
230 return -EAGAIN;
231 cli();
232 interruptible_sleep_on(&queue->proc_list);
233 sti();
234 }
235 while (i > 0 && !queue_empty()) {
236 c = get_from_queue();
237 put_fs_byte(c, buffer++);
238 i--;
239 }
240 aux_ready = !queue_empty();
241 if (count-i) {
242 inode->i_atime = CURRENT_TIME;
243 return count-i;
244 }
245 if (current->signal & ~current->blocked)
246 return -ERESTARTSYS;
247 return 0;
248 }
249
250
251 static int aux_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
252 {
253 if (sel_type != SEL_IN)
254 return 0;
255 if (aux_ready)
256 return 1;
257 select_wait(&queue->proc_list, wait);
258 return 0;
259 }
260
261
262 struct file_operations psaux_fops = {
263 NULL,
264 read_aux,
265 write_aux,
266 NULL,
267 aux_select,
268 NULL,
269 NULL,
270 open_aux,
271 release_aux,
272 };
273
274
275 unsigned long psaux_init(unsigned long kmem_start)
276 {
277 if (aux_device_present != 0xaa) {
278 return kmem_start;
279 }
280 printk("PS/2 type pointing device detected and installed.\n");
281 queue = (struct aux_queue *) kmem_start;
282 kmem_start += sizeof (struct aux_queue);
283 queue->head = queue->tail = 0;
284 queue->proc_list = NULL;
285 aux_present = 1;
286 return kmem_start;
287 }
288
289
290 static int poll_status(void)
291 {
292 int retries=0;
293
294 while ((inb(AUX_STATUS)&0x03) && retries++ < MAX_RETRIES) {
295 if (inb_p(AUX_STATUS)&0x01)
296 inb_p(AUX_INPUT_PORT);
297 current->state = TASK_INTERRUPTIBLE;
298 current->timeout = jiffies + 5;
299 schedule();
300 }
301 return !(retries==MAX_RETRIES);
302 }