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