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_busy = 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_busy = 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 aux_write_cmd(AUX_INTS_OFF);
264 poll_aux_status();
265 outb_p(AUX_DISABLE,AUX_COMMAND);
266 poll_aux_status();
267 free_irq(AUX_IRQ);
268 fasync_aux(inode, file, 0);
269 aux_busy = 0;
270 }
271
272 #ifdef CONFIG_82C710_MOUSE
273 static void release_qp(struct inode * inode, struct file * file)
274 {
275 unsigned char status;
276
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 fasync_aux(inode, file, 0);
285 qp_busy = 0;
286 }
287 #endif
288
289 static int fasync_aux(struct inode *inode, struct file *filp, int on)
290 {
291 int retval;
292
293 retval = fasync_helper(inode, filp, on, &queue->fasync);
294 if (retval < 0)
295 return retval;
296 return 0;
297 }
298
299
300
301
302
303
304 static int open_aux(struct inode * inode, struct file * file)
305 {
306 if (!aux_present)
307 return -EINVAL;
308 if (aux_busy)
309 return -EBUSY;
310 if (!poll_aux_status())
311 return -EBUSY;
312 aux_busy = 1;
313 queue->head = queue->tail = 0;
314 if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse")) {
315 aux_busy = 0;
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 return 0;
325 }
326
327 #ifdef CONFIG_82C710_MOUSE
328
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_busy)
342 return -EBUSY;
343
344 if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse"))
345 return -EBUSY;
346
347 qp_busy = 1;
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 return -EBUSY;
362 }
363
364 outb_p(AUX_ENABLE_DEV, qp_data);
365
366 return 0;
367 }
368 #endif
369
370
371
372
373
374 static int write_aux(struct inode * inode, struct file * file, const char * buffer, int count)
375 {
376 int i = count;
377
378 while (i--) {
379 if (!poll_aux_status())
380 return -EIO;
381 outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
382 if (!poll_aux_status())
383 return -EIO;
384 outb_p(get_user(buffer++),AUX_OUTPUT_PORT);
385 }
386 inode->i_mtime = CURRENT_TIME;
387 return count;
388 }
389
390
391 #ifdef CONFIG_82C710_MOUSE
392
393
394
395
396 static int write_qp(struct inode * inode, struct file * file, const char * buffer, int count)
397 {
398 int i = count;
399
400 while (i--) {
401 if (!poll_qp_status())
402 return -EIO;
403 outb_p(get_user(buffer++), qp_data);
404 }
405 inode->i_mtime = CURRENT_TIME;
406 return count;
407 }
408 #endif
409
410
411
412
413
414
415 static int read_aux(struct inode * inode, struct file * file, char * buffer, int count)
416 {
417 struct wait_queue wait = { current, NULL };
418 int i = count;
419 unsigned char c;
420
421 if (queue_empty()) {
422 if (file->f_flags & O_NONBLOCK)
423 return -EAGAIN;
424 add_wait_queue(&queue->proc_list, &wait);
425 repeat:
426 current->state = TASK_INTERRUPTIBLE;
427 if (queue_empty() && !(current->signal & ~current->blocked)) {
428 schedule();
429 goto repeat;
430 }
431 current->state = TASK_RUNNING;
432 remove_wait_queue(&queue->proc_list, &wait);
433 }
434 while (i > 0 && !queue_empty()) {
435 c = get_from_queue();
436 put_user(c, buffer++);
437 i--;
438 }
439 aux_ready = !queue_empty();
440 if (count-i) {
441 inode->i_atime = CURRENT_TIME;
442 return count-i;
443 }
444 if (current->signal & ~current->blocked)
445 return -ERESTARTSYS;
446 return 0;
447 }
448
449
450 static int aux_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
451 {
452 if (sel_type != SEL_IN)
453 return 0;
454 if (aux_ready)
455 return 1;
456 select_wait(&queue->proc_list, wait);
457 return 0;
458 }
459
460
461 struct file_operations psaux_fops = {
462 NULL,
463 read_aux,
464 write_aux,
465 NULL,
466 aux_select,
467 NULL,
468 NULL,
469 open_aux,
470 release_aux,
471 NULL,
472 fasync_aux,
473 };
474
475
476
477
478
479
480 static struct mouse psaux_mouse = {
481 PSMOUSE_MINOR, "ps2aux", &psaux_fops
482 };
483
484 unsigned long psaux_init(unsigned long kmem_start)
485 {
486 int qp_found = 0;
487
488 #ifdef CONFIG_82C710_MOUSE
489 if ((qp_found = probe_qp())) {
490 printk("82C710 type pointing device detected -- driver installed.\n");
491
492 qp_present = 1;
493 psaux_fops.write = write_qp;
494 psaux_fops.open = open_qp;
495 psaux_fops.release = release_qp;
496 } else
497 #endif
498 if (aux_device_present == 0xaa) {
499 printk("PS/2 auxiliary pointing device detected -- driver installed.\n");
500 aux_present = 1;
501 kbd_read_mask = AUX_OBUF_FULL;
502 mouse_register(&psaux_mouse);
503 } else {
504 #ifdef MODULE
505 return -EIO;
506 #else
507 return kmem_start;
508 #endif
509 }
510 queue = (struct aux_queue *) kmem_start;
511 kmem_start += sizeof (struct aux_queue);
512 memset(queue, 0, sizeof(*queue));
513 queue->head = queue->tail = 0;
514 queue->proc_list = NULL;
515 if (!qp_found) {
516 #if defined INITIALIZE_DEVICE
517 outb_p(AUX_ENABLE,AUX_COMMAND);
518 aux_write_ack(AUX_SET_SAMPLE);
519 aux_write_ack(100);
520 aux_write_ack(AUX_SET_RES);
521 aux_write_ack(3);
522 aux_write_ack(AUX_SET_SCALE21);
523 poll_aux_status_nosleep();
524 #endif
525 outb_p(AUX_DISABLE,AUX_COMMAND);
526 poll_aux_status_nosleep();
527 outb_p(AUX_CMD_WRITE,AUX_COMMAND);
528 poll_aux_status_nosleep();
529 outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT);
530 }
531 #ifdef MODULE
532 return 0;
533 #else
534 return kmem_start;
535 #endif
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