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