This source file includes following definitions.
- aux_write_dev
- aux_write_ack
- aux_write_cmd
- get_from_queue
- queue_empty
- aux_interrupt
- qp_interrupt
- release_aux
- release_qp
- open_aux
- open_qp
- write_aux
- write_qp
- read_aux
- aux_select
- psaux_init
- poll_aux_status
- poll_qp_status
- read_710
- probe_qp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #include <linux/sched.h>
29 #include <linux/kernel.h>
30 #include <linux/fcntl.h>
31 #include <linux/errno.h>
32 #include <linux/timer.h>
33
34 #include <asm/io.h>
35 #include <asm/segment.h>
36 #include <asm/system.h>
37
38 #include <linux/config.h>
39
40
41 #define AUX_INPUT_PORT 0x60
42 #define AUX_OUTPUT_PORT 0x60
43 #define AUX_COMMAND 0x64
44 #define AUX_STATUS 0x64
45
46
47 #define AUX_OBUF_FULL 0x21
48 #define AUX_IBUF_FULL 0x02
49
50
51 #define AUX_CMD_WRITE 0x60
52 #define AUX_MAGIC_WRITE 0xd4
53
54 #define AUX_INTS_ON 0x47
55 #define AUX_INTS_OFF 0x65
56
57 #define AUX_DISABLE 0xa7
58 #define AUX_ENABLE 0xa8
59
60
61 #define AUX_SET_RES 0xe8
62 #define AUX_SET_SCALE11 0xe6
63 #define AUX_SET_SCALE21 0xe7
64 #define AUX_GET_SCALE 0xe9
65 #define AUX_SET_STREAM 0xea
66 #define AUX_SET_SAMPLE 0xf3
67 #define AUX_ENABLE_DEV 0xf4
68 #define AUX_DISABLE_DEV 0xf5
69 #define AUX_RESET 0xff
70
71 #define MAX_RETRIES 60
72 #define AUX_IRQ 12
73 #define AUX_BUF_SIZE 2048
74
75
76
77 #define QP_DATA 0x310
78 #define QP_STATUS 0x311
79
80 #define QP_DEV_IDLE 0x01
81 #define QP_RX_FULL 0x02
82 #define QP_TX_IDLE 0x04
83 #define QP_RESET 0x08
84 #define QP_INTS_ON 0x10
85 #define QP_ERROR_FLAG 0x20
86 #define QP_CLEAR 0x40
87 #define QP_ENABLE 0x80
88
89 #define QP_IRQ 12
90
91 extern unsigned char aux_device_present;
92 extern unsigned char kbd_read_mask;
93
94 struct aux_queue {
95 unsigned long head;
96 unsigned long tail;
97 struct wait_queue *proc_list;
98 unsigned char buf[AUX_BUF_SIZE];
99 };
100
101 static struct aux_queue *queue;
102 static int aux_ready = 0;
103 static int aux_busy = 0;
104 static int aux_present = 0;
105 static int poll_aux_status(void);
106
107 #ifdef CONFIG_82C710_MOUSE
108 static int qp_present = 0;
109 static int qp_busy = 0;
110 static int qp_data = QP_DATA;
111 static int qp_status = QP_STATUS;
112
113 static int poll_qp_status(void);
114 static int probe_qp(void);
115 #endif
116
117
118
119
120
121
122 static void aux_write_dev(int val)
123 {
124 poll_aux_status();
125 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
126 poll_aux_status();
127 outb_p(val,AUX_OUTPUT_PORT);
128 }
129
130
131
132
133
134 #if defined INITIALIZE_DEVICE
135 static int aux_write_ack(int val)
136 {
137 int retries = 0;
138
139 aux_write_dev(val);
140 while ((inb(AUX_STATUS) & AUX_OBUF_FULL) != AUX_OBUF_FULL
141 && retries < MAX_RETRIES) {
142 current->state = TASK_INTERRUPTIBLE;
143 current->timeout = jiffies + (5*HZ + 99) / 100;
144 schedule();
145 retries++;
146 }
147
148 if ((inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
149 {
150 return (inb(AUX_INPUT_PORT));
151 }
152 return 0;
153 }
154 #endif
155
156
157
158
159
160 static void aux_write_cmd(int val)
161 {
162 poll_aux_status();
163 outb_p(AUX_CMD_WRITE,AUX_COMMAND);
164 poll_aux_status();
165 outb_p(val,AUX_OUTPUT_PORT);
166 }
167
168
169 static unsigned int get_from_queue(void)
170 {
171 unsigned int result;
172 unsigned long flags;
173
174 save_flags(flags);
175 cli();
176 result = queue->buf[queue->tail];
177 queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
178 restore_flags(flags);
179 return result;
180 }
181
182
183 static inline int queue_empty(void)
184 {
185 return queue->head == queue->tail;
186 }
187
188
189
190
191
192
193
194
195 static void aux_interrupt(int cpl, struct pt_regs * regs)
196 {
197 int head = queue->head;
198 int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
199
200 queue->buf[head] = inb(AUX_INPUT_PORT);
201 if (head != maxhead) {
202 head++;
203 head &= AUX_BUF_SIZE-1;
204 }
205 queue->head = head;
206 aux_ready = 1;
207 wake_up_interruptible(&queue->proc_list);
208 }
209
210
211
212
213
214
215 #ifdef CONFIG_82C710_MOUSE
216 static void qp_interrupt(int cpl, struct pt_regs * regs)
217 {
218 int head = queue->head;
219 int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
220
221 queue->buf[head] = inb(qp_data);
222 if (head != maxhead) {
223 head++;
224 head &= AUX_BUF_SIZE-1;
225 }
226 queue->head = head;
227 aux_ready = 1;
228 wake_up_interruptible(&queue->proc_list);
229 }
230 #endif
231
232
233 static void release_aux(struct inode * inode, struct file * file)
234 {
235 #ifndef __alpha__
236 aux_write_dev(AUX_DISABLE_DEV);
237 #endif
238 aux_write_cmd(AUX_INTS_OFF);
239 poll_aux_status();
240 outb_p(AUX_DISABLE,AUX_COMMAND);
241 poll_aux_status();
242 free_irq(AUX_IRQ);
243 aux_busy = 0;
244 }
245
246 #ifdef CONFIG_82C710_MOUSE
247 static void release_qp(struct inode * inode, struct file * file)
248 {
249 unsigned char status;
250
251 if (!poll_qp_status())
252 printk("Warning: Mouse device busy in release_qp()\n");
253 status = inb_p(qp_status);
254 outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
255 if (!poll_qp_status())
256 printk("Warning: Mouse device busy in release_qp()\n");
257 free_irq(QP_IRQ);
258 qp_busy = 0;
259 }
260 #endif
261
262
263
264
265
266
267 static int open_aux(struct inode * inode, struct file * file)
268 {
269 if (!aux_present)
270 return -EINVAL;
271 if (aux_busy)
272 return -EBUSY;
273 if (!poll_aux_status())
274 return -EBUSY;
275 aux_busy = 1;
276 queue->head = queue->tail = 0;
277 if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse")) {
278 aux_busy = 0;
279 return -EBUSY;
280 }
281 poll_aux_status();
282 outb_p(AUX_ENABLE,AUX_COMMAND);
283 aux_write_dev(AUX_ENABLE_DEV);
284 aux_write_cmd(AUX_INTS_ON);
285 poll_aux_status();
286 aux_ready = 0;
287 return 0;
288 }
289
290 #ifdef CONFIG_82C710_MOUSE
291
292
293
294
295
296
297 static int open_qp(struct inode * inode, struct file * file)
298 {
299 unsigned char status;
300
301 if (!qp_present)
302 return -EINVAL;
303
304 if (qp_busy)
305 return -EBUSY;
306
307 if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse"))
308 return -EBUSY;
309
310 qp_busy = 1;
311
312 status = inb_p(qp_status);
313 status |= (QP_ENABLE|QP_RESET);
314 outb_p(status, qp_status);
315 status &= ~(QP_RESET);
316 outb_p(status, qp_status);
317
318 queue->head = queue->tail = 0;
319 status |= QP_INTS_ON;
320 outb_p(status, qp_status);
321
322 while (!poll_qp_status()) {
323 printk("Error: Mouse device busy in open_qp()\n");
324 return -EBUSY;
325 }
326
327 outb_p(AUX_ENABLE_DEV, qp_data);
328
329 return 0;
330 }
331 #endif
332
333
334
335
336
337 static int write_aux(struct inode * inode, struct file * file, char * buffer, int count)
338 {
339 int i = count;
340
341 while (i--) {
342 if (!poll_aux_status())
343 return -EIO;
344 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
345 if (!poll_aux_status())
346 return -EIO;
347 outb_p(get_user(buffer++),AUX_OUTPUT_PORT);
348 }
349 inode->i_mtime = CURRENT_TIME;
350 return count;
351 }
352
353
354 #ifdef CONFIG_82C710_MOUSE
355
356
357
358
359 static int write_qp(struct inode * inode, struct file * file, char * buffer, int count)
360 {
361 int i = count;
362
363 while (i--) {
364 if (!poll_qp_status())
365 return -EIO;
366 outb_p(get_user(buffer++), qp_data);
367 }
368 inode->i_mtime = CURRENT_TIME;
369 return count;
370 }
371 #endif
372
373
374
375
376
377
378 static int read_aux(struct inode * inode, struct file * file, char * buffer, int count)
379 {
380 struct wait_queue wait = { current, NULL };
381 int i = count;
382 unsigned char c;
383
384 if (queue_empty()) {
385 if (file->f_flags & O_NONBLOCK)
386 return -EAGAIN;
387 add_wait_queue(&queue->proc_list, &wait);
388 repeat:
389 current->state = TASK_INTERRUPTIBLE;
390 if (queue_empty() && !(current->signal & ~current->blocked)) {
391 schedule();
392 goto repeat;
393 }
394 current->state = TASK_RUNNING;
395 remove_wait_queue(&queue->proc_list, &wait);
396 }
397 while (i > 0 && !queue_empty()) {
398 c = get_from_queue();
399 put_user(c, buffer++);
400 i--;
401 }
402 aux_ready = !queue_empty();
403 if (count-i) {
404 inode->i_atime = CURRENT_TIME;
405 return count-i;
406 }
407 if (current->signal & ~current->blocked)
408 return -ERESTARTSYS;
409 return 0;
410 }
411
412
413 static int aux_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
414 {
415 if (sel_type != SEL_IN)
416 return 0;
417 if (aux_ready)
418 return 1;
419 select_wait(&queue->proc_list, wait);
420 return 0;
421 }
422
423
424 struct file_operations psaux_fops = {
425 NULL,
426 read_aux,
427 write_aux,
428 NULL,
429 aux_select,
430 NULL,
431 NULL,
432 open_aux,
433 release_aux,
434 };
435
436
437
438
439
440
441
442 unsigned long psaux_init(unsigned long kmem_start)
443 {
444 int qp_found = 0;
445
446 #ifdef CONFIG_82C710_MOUSE
447 if ((qp_found = probe_qp())) {
448 printk("82C710 type pointing device detected -- driver installed.\n");
449
450 qp_present = 1;
451 psaux_fops.write = write_qp;
452 psaux_fops.open = open_qp;
453 psaux_fops.release = release_qp;
454 poll_qp_status();
455 } else
456 #endif
457 if (aux_device_present == 0xaa) {
458 printk("PS/2 auxiliary pointing device detected -- driver installed.\n");
459 aux_present = 1;
460 kbd_read_mask = AUX_OBUF_FULL;
461 poll_aux_status();
462 } else {
463 return kmem_start;
464 }
465 queue = (struct aux_queue *) kmem_start;
466 kmem_start += sizeof (struct aux_queue);
467 queue->head = queue->tail = 0;
468 queue->proc_list = NULL;
469 if (!qp_found) {
470 #if defined INITIALIZE_DEVICE
471 outb_p(AUX_ENABLE,AUX_COMMAND);
472 aux_write_ack(AUX_SET_SAMPLE);
473 aux_write_ack(100);
474 aux_write_ack(AUX_SET_RES);
475 aux_write_ack(3);
476 aux_write_ack(AUX_SET_SCALE21);
477 poll_aux_status();
478 #endif
479 outb_p(AUX_DISABLE,AUX_COMMAND);
480 aux_write_cmd(AUX_INTS_OFF);
481 poll_aux_status();
482 }
483 return kmem_start;
484 }
485
486 static int poll_aux_status(void)
487 {
488 int retries=0;
489
490 while ((inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
491 if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
492 inb_p(AUX_INPUT_PORT);
493 current->state = TASK_INTERRUPTIBLE;
494 current->timeout = jiffies + (5*HZ + 99) / 100;
495 schedule();
496 retries++;
497 }
498 return !(retries==MAX_RETRIES);
499 }
500
501 #ifdef CONFIG_82C710_MOUSE
502
503
504
505
506 static int poll_qp_status(void)
507 {
508 int retries=0;
509
510 while ((inb(qp_status)&(QP_RX_FULL|QP_TX_IDLE|QP_DEV_IDLE))
511 != (QP_DEV_IDLE|QP_TX_IDLE)
512 && retries < MAX_RETRIES) {
513
514 if (inb_p(qp_status)&(QP_RX_FULL))
515 inb_p(qp_data);
516 current->state = TASK_INTERRUPTIBLE;
517 current->timeout = jiffies + (5*HZ + 99) / 100;
518 schedule();
519 retries++;
520 }
521 return !(retries==MAX_RETRIES);
522 }
523
524
525
526
527
528 static inline unsigned char read_710(unsigned char index)
529 {
530 outb_p(index, 0x390);
531 return inb_p(0x391);
532 }
533
534
535
536
537
538 static int probe_qp(void)
539 {
540 outb_p(0x55, 0x2fa);
541 outb_p(0xaa, 0x3fa);
542 outb_p(0x36, 0x3fa);
543 outb_p(0xe4, 0x3fa);
544 outb_p(0x1b, 0x2fa);
545 if (read_710(0x0f) != 0xe4)
546 return 0;
547 qp_data = read_710(0x0d)*4;
548 qp_status = qp_data+1;
549 outb_p(0x0f, 0x390);
550 outb_p(0x0f, 0x391);
551 return 1;
552 }
553 #endif