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