2 * linux/drivers/char/qpmouse.c
4 * Driver for a 82C710 C&T mouse interface chip.
6 * Based on the PS/2 driver by Johan Myreen.
8 * Corrections in device setup for some laptop mice & trackballs.
9 * 02Feb93 (troyer@saifr00.cfsat.Honeywell.COM,mch@wimsey.bc.ca)
11 * Modified by Johan Myreen (jem@iki.fi) 04Aug93
12 * to include support for QuickPort mouse.
14 * Changed references to "QuickPort" with "82C710" since "QuickPort"
15 * is not what this driver is all about -- QuickPort is just a
16 * connector type, and this driver is for the mouse port on the Chips
17 * & Technologies 82C710 interface chip. 15Nov93 jem@iki.fi
19 * Added support for SIGIO. 28Jul95 jem@iki.fi
21 * Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com
23 * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
26 #include <linux/module.h>
28 #include <linux/sched.h>
29 #include <linux/kernel.h>
30 #include <linux/interrupt.h>
31 #include <linux/fcntl.h>
32 #include <linux/errno.h>
33 #include <linux/timer.h>
34 #include <linux/malloc.h>
35 #include <linux/miscdevice.h>
36 #include <linux/random.h>
37 #include <linux/poll.h>
38 #include <linux/init.h>
41 #include <asm/uaccess.h>
42 #include <asm/system.h>
43 #include <asm/semaphore.h>
45 #include <linux/pc_keyb.h> /* mouse enable command.. */
49 * We use the same minor number as the PS/2 mouse for (bad) historical
52 #define PSMOUSE_MINOR 1 /* Minor device # for this mouse */
53 #define QP_BUF_SIZE 2048
58 wait_queue_head_t proc_list
;
59 struct fasync_struct
*fasync
;
60 unsigned char buf
[QP_BUF_SIZE
];
63 static struct qp_queue
*queue
;
65 static unsigned int get_from_queue(void)
72 result
= queue
->buf
[queue
->tail
];
73 queue
->tail
= (queue
->tail
+ 1) & (QP_BUF_SIZE
-1);
79 static inline int queue_empty(void)
81 return queue
->head
== queue
->tail
;
84 static int fasync_qp(int fd
, struct file
*filp
, int on
)
88 retval
= fasync_helper(fd
, filp
, on
, &queue
->fasync
);
98 #define QP_DATA 0x310 /* Data Port I/O Address */
99 #define QP_STATUS 0x311 /* Status Port I/O Address */
101 #define QP_DEV_IDLE 0x01 /* Device Idle */
102 #define QP_RX_FULL 0x02 /* Device Char received */
103 #define QP_TX_IDLE 0x04 /* Device XMIT Idle */
104 #define QP_RESET 0x08 /* Device Reset */
105 #define QP_INTS_ON 0x10 /* Device Interrupt On */
106 #define QP_ERROR_FLAG 0x20 /* Device Error */
107 #define QP_CLEAR 0x40 /* Device Clear */
108 #define QP_ENABLE 0x80 /* Device Enable */
112 static int qp_present
= 0;
113 static int qp_count
= 0;
114 static int qp_data
= QP_DATA
;
115 static int qp_status
= QP_STATUS
;
117 static int poll_qp_status(void);
118 static int probe_qp(void);
121 * Interrupt handler for the 82C710 mouse port. A character
122 * is waiting in the 82C710.
125 static void qp_interrupt(int cpl
, void *dev_id
, struct pt_regs
* regs
)
127 int head
= queue
->head
;
128 int maxhead
= (queue
->tail
-1) & (QP_BUF_SIZE
-1);
130 add_mouse_randomness(queue
->buf
[head
] = inb(qp_data
));
131 if (head
!= maxhead
) {
133 head
&= QP_BUF_SIZE
-1;
136 kill_fasync(&queue
->fasync
, SIGIO
, POLL_IN
);
137 wake_up_interruptible(&queue
->proc_list
);
140 static int release_qp(struct inode
* inode
, struct file
* file
)
142 unsigned char status
;
144 fasync_qp(-1, file
, 0);
146 if (!poll_qp_status())
147 printk("Warning: Mouse device busy in release_qp()\n");
148 status
= inb_p(qp_status
);
149 outb_p(status
& ~(QP_ENABLE
|QP_INTS_ON
), qp_status
);
150 if (!poll_qp_status())
151 printk("Warning: Mouse device busy in release_qp()\n");
152 free_irq(QP_IRQ
, NULL
);
158 * Install interrupt handler.
159 * Enable the device, enable interrupts.
162 static int open_qp(struct inode
* inode
, struct file
* file
)
164 unsigned char status
;
172 if (request_irq(QP_IRQ
, qp_interrupt
, 0, "PS/2 Mouse", NULL
)) {
177 status
= inb_p(qp_status
);
178 status
|= (QP_ENABLE
|QP_RESET
);
179 outb_p(status
, qp_status
);
180 status
&= ~(QP_RESET
);
181 outb_p(status
, qp_status
);
183 queue
->head
= queue
->tail
= 0; /* Flush input queue */
184 status
|= QP_INTS_ON
;
185 outb_p(status
, qp_status
); /* Enable interrupts */
187 while (!poll_qp_status()) {
188 printk("Error: Mouse device busy in open_qp()\n");
190 status
&= ~(QP_ENABLE
|QP_INTS_ON
);
191 outb_p(status
, qp_status
);
192 free_irq(QP_IRQ
, NULL
);
196 outb_p(AUX_ENABLE_DEV
, qp_data
); /* Wake up mouse */
201 * Write to the 82C710 mouse device.
204 static ssize_t
write_qp(struct file
* file
, const char * buffer
,
205 size_t count
, loff_t
*ppos
)
211 if (!poll_qp_status())
213 get_user(c
, buffer
++);
216 file
->f_dentry
->d_inode
->i_mtime
= CURRENT_TIME
;
220 static unsigned int poll_qp(struct file
*file
, poll_table
* wait
)
222 poll_wait(file
, &queue
->proc_list
, wait
);
224 return POLLIN
| POLLRDNORM
;
229 * Wait for device to send output char and flush any input char.
232 #define MAX_RETRIES (60)
234 static int poll_qp_status(void)
238 while ((inb(qp_status
)&(QP_RX_FULL
|QP_TX_IDLE
|QP_DEV_IDLE
))
239 != (QP_DEV_IDLE
|QP_TX_IDLE
)
240 && retries
< MAX_RETRIES
) {
242 if (inb_p(qp_status
)&(QP_RX_FULL
))
244 current
->state
= TASK_INTERRUPTIBLE
;
245 schedule_timeout((5*HZ
+ 99) / 100);
248 return !(retries
==MAX_RETRIES
);
252 * Put bytes from input queue to buffer.
255 static ssize_t
read_qp(struct file
* file
, char * buffer
,
256 size_t count
, loff_t
*ppos
)
258 DECLARE_WAITQUEUE(wait
, current
);
263 if (file
->f_flags
& O_NONBLOCK
)
265 add_wait_queue(&queue
->proc_list
, &wait
);
267 set_current_state(TASK_INTERRUPTIBLE
);
268 if (queue_empty() && !signal_pending(current
)) {
272 current
->state
= TASK_RUNNING
;
273 remove_wait_queue(&queue
->proc_list
, &wait
);
275 while (i
> 0 && !queue_empty()) {
276 c
= get_from_queue();
277 put_user(c
, buffer
++);
281 file
->f_dentry
->d_inode
->i_atime
= CURRENT_TIME
;
284 if (signal_pending(current
))
289 struct file_operations qp_fops
= {
302 static struct miscdevice qp_mouse
= {
303 PSMOUSE_MINOR
, "QPmouse", &qp_fops
307 * Function to read register in 82C710.
310 static inline unsigned char read_710(unsigned char index
)
312 outb_p(index
, 0x390); /* Write index */
313 return inb_p(0x391); /* Read the data */
318 * See if we can find a 82C710 device. Read mouse address.
321 static int __init
probe_qp(void)
323 outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
324 outb_p(0xaa, 0x3fa); /* Inverse of 55 */
325 outb_p(0x36, 0x3fa); /* Address the chip */
326 outb_p(0xe4, 0x3fa); /* 390/4; 390 = config address */
327 outb_p(0x1b, 0x2fa); /* Inverse of e4 */
328 if (read_710(0x0f) != 0xe4) /* Config address found? */
329 return 0; /* No: no 82C710 here */
330 qp_data
= read_710(0x0d)*4; /* Get mouse I/O address */
331 qp_status
= qp_data
+1;
333 outb_p(0x0f, 0x391); /* Close config mode */
337 int __init
qpmouse_init(void)
342 printk(KERN_INFO
"82C710 type pointing device detected -- driver installed.\n");
343 /* printk("82C710 address = %x (should be 0x310)\n", qp_data); */
345 misc_register(&qp_mouse
);
346 queue
= (struct qp_queue
*) kmalloc(sizeof(*queue
), GFP_KERNEL
);
347 memset(queue
, 0, sizeof(*queue
));
348 queue
->head
= queue
->tail
= 0;
349 init_waitqueue_head(&queue
->proc_list
);
355 int init_module(void)
357 return qpmouse_init();
360 void cleanup_module(void)
362 misc_deregister(&qp_mouse
);