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