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