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