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