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()
121 {
122 unsigned int result;
123 unsigned long flags;
124
125 __asm__ __volatile__ ("pushfl ; popl %0; cli":"=r" (flags));
126 result = queue->buf[queue->tail];
127 queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
128 __asm__ __volatile__ ("pushl %0 ; popfl"::"r" (flags));
129 return result;
130 }
131
132
133 static inline int queue_empty()
134 {
135 return queue->head == queue->tail;
136 }
137
138
139
140
141
142
143
144 static void aux_interrupt(int cpl)
145 {
146 int head = queue->head;
147 int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
148
149 queue->buf[head] = inb(AUX_INPUT_PORT);
150 if (head != maxhead) {
151 head++;
152 head &= AUX_BUF_SIZE-1;
153 }
154 queue->head = head;
155 aux_ready = 1;
156 wake_up_interruptible(&queue->proc_list);
157 }
158
159
160 static void release_aux(struct inode * inode, struct file * file)
161 {
162 poll_status();
163 aux_write_dev(AUX_DISABLE_DEV);
164 poll_status();
165 outb_p(AUX_DISABLE,AUX_COMMAND);
166 aux_write_cmd(AUX_INTS_OFF);
167 free_irq(AUX_IRQ);
168 aux_busy = 0;
169 }
170
171
172
173
174
175
176
177 static int open_aux(struct inode * inode, struct file * file)
178 {
179 if (!aux_present)
180 return -EINVAL;
181 if (aux_busy)
182 return -EBUSY;
183 if (!poll_status())
184 return -EBUSY;
185 aux_busy = 1;
186 queue->head = queue->tail = 0;
187 if (request_irq(AUX_IRQ, aux_interrupt))
188 return -EBUSY;
189 aux_write_dev(AUX_ENABLE_DEV);
190 aux_write_cmd(AUX_INTS_ON);
191 poll_status();
192 outb_p(AUX_ENABLE,AUX_COMMAND);
193 return 0;
194 }
195
196
197
198
199
200
201 static int write_aux(struct inode * inode, struct file * file, char * buffer, int count)
202 {
203 int i = count;
204
205 while (i--) {
206 if (!poll_status())
207 return -EIO;
208 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
209 if (!poll_status())
210 return -EIO;
211 outb_p(get_fs_byte(buffer++),AUX_OUTPUT_PORT);
212 }
213 inode->i_mtime = CURRENT_TIME;
214 return count;
215 }
216
217
218
219
220
221
222 static int read_aux(struct inode * inode, struct file * file, char * buffer, int count)
223 {
224 struct wait_queue wait = { current, NULL };
225 int i = count;
226 unsigned char c;
227
228 if (queue_empty()) {
229 if (file->f_flags & O_NONBLOCK)
230 return -EAGAIN;
231 add_wait_queue(&queue->proc_list, &wait);
232 repeat:
233 current->state = TASK_INTERRUPTIBLE;
234 if (queue_empty() && !(current->signal & ~current->blocked)) {
235 schedule();
236 goto repeat;
237 }
238 current->state = TASK_RUNNING;
239 remove_wait_queue(&queue->proc_list, &wait);
240 }
241 while (i > 0 && !queue_empty()) {
242 c = get_from_queue();
243 put_fs_byte(c, buffer++);
244 i--;
245 }
246 aux_ready = !queue_empty();
247 if (count-i) {
248 inode->i_atime = CURRENT_TIME;
249 return count-i;
250 }
251 if (current->signal & ~current->blocked)
252 return -ERESTARTSYS;
253 return 0;
254 }
255
256
257 static int aux_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
258 {
259 if (sel_type != SEL_IN)
260 return 0;
261 if (aux_ready)
262 return 1;
263 select_wait(&queue->proc_list, wait);
264 return 0;
265 }
266
267
268 struct file_operations psaux_fops = {
269 NULL,
270 read_aux,
271 write_aux,
272 NULL,
273 aux_select,
274 NULL,
275 NULL,
276 open_aux,
277 release_aux,
278 };
279
280
281 unsigned long psaux_init(unsigned long kmem_start)
282 {
283 if (aux_device_present != 0xaa) {
284 return kmem_start;
285 }
286 printk("PS/2 type pointing device detected and installed.\n");
287 queue = (struct aux_queue *) kmem_start;
288 kmem_start += sizeof (struct aux_queue);
289 queue->head = queue->tail = 0;
290 queue->proc_list = NULL;
291 aux_present = 1;
292 poll_status();
293 outb_p(AUX_DISABLE,AUX_COMMAND);
294 aux_write_cmd(AUX_INTS_OFF);
295 return kmem_start;
296 }
297
298
299 static int poll_status(void)
300 {
301 int retries=0;
302
303 while ((inb(AUX_STATUS)&0x03) && retries++ < MAX_RETRIES) {
304 if (inb_p(AUX_STATUS)&0x01)
305 inb_p(AUX_INPUT_PORT);
306 current->state = TASK_INTERRUPTIBLE;
307 current->timeout = jiffies + 5;
308 schedule();
309 }
310 return !(retries==MAX_RETRIES);
311 }