This source file includes following definitions.
- get_from_queue
- queue_empty
- aux_interrupt
- release_aux
- open_aux
- write_aux
- read_aux
- aux_select
- psaux_init
- poll_status
1
2
3
4
5
6
7
8
9
10
11 #include <linux/timer.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/fcntl.h>
15 #include <linux/errno.h>
16
17 #include <asm/io.h>
18 #include <asm/segment.h>
19 #include <asm/system.h>
20
21 #define AUX_INPUT_PORT 0x60
22 #define AUX_OUTPUT_PORT 0x60
23 #define AUX_COMMAND 0x64
24 #define AUX_STATUS 0x64
25
26 #define MAX_RETRIES 3
27 #define AUX_IRQ 12
28 #define AUX_BUF_SIZE 2048
29
30 extern unsigned char aux_device_present;
31
32 struct aux_queue {
33 unsigned long head;
34 unsigned long tail;
35 struct wait_queue *proc_list;
36 unsigned char buf[AUX_BUF_SIZE];
37 };
38
39 static struct aux_queue *queue;
40 static int aux_ready = 0;
41 static int aux_busy = 0;
42 static int aux_present = 0;
43
44 static int poll_status(void);
45
46
47 static unsigned int get_from_queue()
48 {
49 unsigned int result;
50 unsigned long flags;
51
52 __asm__ __volatile__ ("pushfl ; popl %0; cli":"=r" (flags));
53 result = queue->buf[queue->tail];
54 queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
55 __asm__ __volatile__ ("pushl %0 ; popfl"::"r" (flags));
56 return result;
57 }
58
59
60 static inline int queue_empty()
61 {
62 return queue->head == queue->tail;
63 }
64
65
66
67
68
69
70
71 static void aux_interrupt(int cpl)
72 {
73 int head = queue->head;
74 int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
75
76 queue->buf[head] = inb(AUX_INPUT_PORT);
77 if (head != maxhead) {
78 head++;
79 head &= AUX_BUF_SIZE-1;
80 }
81 queue->head = head;
82 aux_ready = 1;
83 wake_up(&queue->proc_list);
84 }
85
86
87 static void release_aux(struct inode * inode, struct file * file)
88 {
89 poll_status();
90 outb_p(0xa7,AUX_COMMAND);
91 poll_status();
92 outb_p(0x60,AUX_COMMAND);
93 poll_status();
94 outb_p(0x65,AUX_OUTPUT_PORT);
95 free_irq(AUX_IRQ);
96 aux_busy = 0;
97 }
98
99
100
101
102
103
104
105 static int open_aux(struct inode * inode, struct file * file)
106 {
107 if (aux_busy)
108 return -EBUSY;
109 if (!aux_present)
110 return -EINVAL;
111 if (!poll_status())
112 return -EBUSY;
113 aux_busy = 1;
114 queue->head = queue->tail = 0;
115 if (request_irq(AUX_IRQ, aux_interrupt))
116 return -EBUSY;
117 outb_p(0x60,AUX_COMMAND);
118 poll_status();
119 outb_p(0x47,AUX_OUTPUT_PORT);
120 poll_status();
121 outb_p(0xa8,AUX_COMMAND);
122 return 0;
123 }
124
125
126
127
128
129
130 static int write_aux(struct inode * inode, struct file * file, char * buffer, int count)
131 {
132 int i = count;
133
134 while (i--) {
135 if (!poll_status())
136 return -EIO;
137 outb_p(0xd4,AUX_COMMAND);
138 if (!poll_status())
139 return -EIO;
140 outb_p(get_fs_byte(buffer++),AUX_OUTPUT_PORT);
141 }
142 inode->i_mtime = CURRENT_TIME;
143 return count;
144 }
145
146
147
148
149
150
151 static int read_aux(struct inode * inode, struct file * file, char * buffer, int count)
152 {
153 int i = count;
154 unsigned char c;
155
156 if (queue_empty()) {
157 if (file->f_flags & O_NONBLOCK)
158 return -EWOULDBLOCK;
159 cli();
160 interruptible_sleep_on(&queue->proc_list);
161 sti();
162 }
163 while (i > 0 && !queue_empty()) {
164 c = get_from_queue();
165 put_fs_byte(c, buffer++);
166 i--;
167 }
168 aux_ready = !queue_empty();
169 if (count-i) {
170 inode->i_atime = CURRENT_TIME;
171 return count-i;
172 }
173 if (current->signal & ~current->blocked)
174 return -ERESTARTSYS;
175 return 0;
176 }
177
178
179 static int aux_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
180 {
181 if (sel_type != SEL_IN)
182 return 0;
183 if (aux_ready)
184 return 1;
185 select_wait(&queue->proc_list, wait);
186 return 0;
187 }
188
189
190 struct file_operations psaux_fops = {
191 NULL,
192 read_aux,
193 write_aux,
194 NULL,
195 aux_select,
196 NULL,
197 open_aux,
198 release_aux,
199 };
200
201
202 long psaux_init(long kmem_start)
203 {
204 if (aux_device_present != 0xaa) {
205 printk("No PS/2 type pointing device detected.\n");
206 return kmem_start;
207 }
208 printk("PS/2 type pointing device detected and installed.\n");
209 queue = (struct aux_queue *) kmem_start;
210 kmem_start += sizeof (struct aux_queue);
211 queue->head = queue->tail = 0;
212 queue->proc_list = 0;
213 aux_present = 1;
214 return kmem_start;
215 }
216
217
218 static int poll_status(void)
219 {
220 int retries=0;
221
222 while ((inb(AUX_STATUS)&0x03) && retries++ < MAX_RETRIES) {
223 if (inb_p(AUX_STATUS)&0x01)
224 inb_p(AUX_INPUT_PORT);
225 current->state = TASK_INTERRUPTIBLE;
226 current->timeout = jiffies + 5;
227 schedule();
228 }
229 return !(retries==MAX_RETRIES);
230 }