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