OSDN Git Service

2.4: USB: fix DoS in pwc USB video driver
[linux-kernel-docs/linux-2.4.36.git] / drivers / char / hp_psaux.c
1 /*
2  *      LASI PS/2 keyboard/psaux driver for HP-PARISC workstations
3  *      
4  *      (c) Copyright 1999 The Puffin Group Inc.
5  *      by Alex deVries <adevries@thepuffingroup.com>
6  *      Copyright 1999, 2000 Philipp Rumpf <prumpf@tux.org>
7  *
8  *      2000/10/26      Debacker Xavier (debackex@esiee.fr)
9  *      implemented the psaux and controlled the mouse scancode based on pc_keyb.c
10  *                      Marteau Thomas (marteaut@esiee.fr)
11  *      fixed leds control
12  *
13  *      2001/12/17      Marteau Thomas (marteaut@esiee.fr)
14  *      get nice initialisation procedure
15  */
16
17 #include <linux/config.h>
18
19 #include <linux/types.h>
20 #include <linux/ptrace.h>       /* interrupt.h wants struct pt_regs defined */
21 #include <linux/interrupt.h>
22 #include <linux/sched.h>        /* for request_irq/free_irq */
23 #include <linux/ioport.h>
24 #include <linux/kernel.h>
25 #include <linux/wait.h>
26 #include <linux/delay.h>
27 #include <linux/errno.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/pc_keyb.h>
31 #include <linux/kbd_kern.h>
32
33 /* mouse includes */
34 #include <linux/miscdevice.h>
35 #include <linux/slab.h>
36 #include <linux/random.h>
37 #include <linux/spinlock.h>
38 #include <linux/smp_lock.h>
39 #include <linux/poll.h>
40
41 #include <asm/hardware.h>
42 #include <asm/keyboard.h>
43 #include <asm/gsc.h>
44 #include <asm/uaccess.h>
45
46 /* HP specific LASI PS/2 keyboard and psaux constants */
47 #define AUX_REPLY_ACK   0xFA    /* Command byte ACK. */
48 #define AUX_RESEND      0xFE    /* Sent by the keyb. Asking for resending the last command. */
49 #define AUX_RECONNECT   0xAA    /* scancode when ps2 device is plugged (back) in */
50
51 #define LASI_PSAUX_OFFSET 0x0100 /* offset from keyboard to psaux port */
52
53 #define LASI_ID         0x00    /* ID and reset port offsets */
54 #define LASI_RESET      0x00
55 #define LASI_RCVDATA    0x04    /* receive and transmit port offsets */
56 #define LASI_XMTDATA    0x04
57 #define LASI_CONTROL    0x08    /* see: control register bits */
58 #define LASI_STATUS     0x0C    /* see: status register bits */
59
60 /* control register bits */
61 #define LASI_CTRL_ENBL  0x01    /* enable interface */
62 #define LASI_CTRL_LPBXR 0x02    /* loopback operation */
63 #define LASI_CTRL_DIAG  0x20    /* directly control clock/data line */
64 #define LASI_CTRL_DATDIR 0x40   /* data line direct control */
65 #define LASI_CTRL_CLKDIR 0x80   /* clock line direct control */
66
67 /* status register bits */
68 #define LASI_STAT_RBNE  0x01
69 #define LASI_STAT_TBNE  0x02
70 #define LASI_STAT_TERR  0x04
71 #define LASI_STAT_PERR  0x08
72 #define LASI_STAT_CMPINTR 0x10
73 #define LASI_STAT_DATSHD 0x40
74 #define LASI_STAT_CLKSHD 0x80
75
76 static spinlock_t       kbd_controller_lock = SPIN_LOCK_UNLOCKED;
77 static unsigned long lasikbd_hpa;
78
79 static volatile int cmd_status;
80
81 static inline u8 read_input(unsigned long hpa)
82 {
83         return gsc_readb(hpa+LASI_RCVDATA);
84 }
85
86 static inline u8 read_control(unsigned long hpa)
87 {
88         return gsc_readb(hpa+LASI_CONTROL);
89 }
90
91 static inline void write_control(u8 val, unsigned long hpa)
92 {
93         gsc_writeb(val, hpa+LASI_CONTROL);
94 }
95
96 static inline u8 read_status(unsigned long hpa)
97 {
98         return gsc_readb(hpa+LASI_STATUS);
99 }
100
101 /* XXX should this grab the spinlock? */
102
103 static int write_output(u8 val, unsigned long hpa)
104 {
105         int wait = 250;
106
107         while (read_status(hpa) & LASI_STAT_TBNE) {
108                 if (!--wait) {
109                         return 0;
110                 }
111                 mdelay(1);
112         }
113         gsc_writeb(val, hpa+LASI_XMTDATA);
114
115         return 1;
116 }
117
118 /* XXX should this grab the spinlock? */
119
120 static u8 wait_input(unsigned long hpa)
121 {
122         int wait = 250;
123
124         while (!(read_status(hpa) & LASI_STAT_RBNE)) {
125                 if (!--wait) {
126                         return 0;
127                 }
128                 mdelay(1);
129         }
130         return read_input(hpa);      
131 }
132
133 /* This function is the PA-RISC adaptation of i386 source */
134
135 static inline int aux_write_ack(u8 val)
136 {
137       return write_output(val, lasikbd_hpa+LASI_PSAUX_OFFSET);
138 }
139
140 /* This is wrong, should do something like the pc driver, which sends
141  * the command up to 3 times at 1 second intervals, checking once
142  * per millisecond for an acknowledge.
143  */
144
145 static void lasikbd_leds(unsigned char leds)
146 {
147         int loop = 1000;
148
149         if (!lasikbd_hpa)
150                 return;
151
152         cmd_status=2;
153         while (cmd_status!=0 && --loop > 0) {
154                 write_output(KBD_CMD_SET_LEDS, lasikbd_hpa);
155                 mdelay(5); 
156         }
157    
158         cmd_status=2;
159         while (cmd_status!=0 && --loop > 0) {
160                 write_output(leds, lasikbd_hpa);
161                 mdelay(5);
162         }
163
164         cmd_status=2;
165         while (cmd_status!=0 && --loop > 0) {
166            write_output(KBD_CMD_ENABLE, lasikbd_hpa);   
167            mdelay(5);
168         }
169         if (loop <= 0)
170                 printk("lasikbd_leds: timeout\n");
171 }
172
173 #if 0
174 /* this might become useful again at some point.  not now  -prumpf */
175 int lasi_ps2_test(void *hpa)
176 {
177         u8 control,c;
178         int i, ret = 0;
179
180         control = read_control(hpa);
181         write_control(control | LASI_CTRL_LPBXR | LASI_CTRL_ENBL, hpa);
182
183         for (i=0; i<256; i++) {
184                 write_output(i, hpa);
185
186                 while (!(read_status(hpa) & LASI_STAT_RBNE))
187                     /* just wait */;
188                     
189                 c = read_input(hpa);
190                 if (c != i)
191                         ret--;
192         }
193
194         write_control(control, hpa);
195
196         return ret;
197 }
198 #endif 
199
200 static int init_keyb(unsigned long hpa)
201 {
202         int res = 0;
203         unsigned long flags;
204
205         spin_lock_irqsave(&kbd_controller_lock, flags);
206
207         if (write_output(KBD_CMD_SET_LEDS, hpa) &&
208                         wait_input(hpa) == AUX_REPLY_ACK &&
209                         write_output(0, hpa) &&
210                         wait_input(hpa) == AUX_REPLY_ACK &&
211                         write_output(KBD_CMD_ENABLE, hpa) &&
212                         wait_input(hpa) == AUX_REPLY_ACK)
213                 res = 1;
214
215         spin_unlock_irqrestore(&kbd_controller_lock, flags);
216
217         return res;
218 }
219
220
221 static void __init lasi_ps2_reset(unsigned long hpa)
222 {
223         u8 control;
224
225         /* reset the interface */
226         gsc_writeb(0xff, hpa+LASI_RESET);
227         gsc_writeb(0x0 , hpa+LASI_RESET);               
228
229         /* enable it */
230         control = read_control(hpa);
231         write_control(control | LASI_CTRL_ENBL, hpa);
232 }
233
234 /* Greatly inspired by pc_keyb.c */
235
236 /*
237  * Wait for keyboard controller input buffer to drain.
238  *
239  * Don't use 'jiffies' so that we don't depend on
240  * interrupts..
241  *
242  * Quote from PS/2 System Reference Manual:
243  *
244  * "Address hex 0060 and address hex 0064 should be written only when
245  * the input-buffer-full bit and output-buffer-full bit in the
246  * Controller Status register are set 0."
247  */
248 #ifdef CONFIG_PSMOUSE
249
250 static struct aux_queue *queue;
251 static unsigned char    mouse_reply_expected;
252 static int              aux_count;
253
254 static int fasync_aux(int fd, struct file *filp, int on)
255 {
256         int retval;
257         
258         retval = fasync_helper(fd, filp, on, &queue->fasync);
259         if (retval < 0)
260                 return retval;
261         
262         return 0;
263 }
264
265
266
267 static inline void handle_mouse_scancode(unsigned char scancode)
268 {
269         if (mouse_reply_expected) {
270                 if (scancode == AUX_REPLY_ACK) {
271                         mouse_reply_expected--;
272                         return;
273                 }
274                 mouse_reply_expected = 0;
275         }
276         else if (scancode == AUX_RECONNECT) {
277                 queue->head = queue->tail = 0;  /* Flush input queue */
278                 return;
279         }
280
281         add_mouse_randomness(scancode);
282         if (aux_count) {
283                 int head = queue->head;
284                                 
285                 queue->buf[head] = scancode;
286                 head = (head + 1) & (AUX_BUF_SIZE-1);
287                 
288                 if (head != queue->tail) {
289                         queue->head = head;
290                         kill_fasync(&queue->fasync, SIGIO, POLL_IN);
291                         wake_up_interruptible(&queue->proc_list);
292                 }
293         }
294 }
295
296 static inline int queue_empty(void)
297 {
298         return queue->head == queue->tail;
299 }
300
301 static unsigned char get_from_queue(void)
302 {
303         unsigned char result;
304         unsigned long flags;
305
306         spin_lock_irqsave(&kbd_controller_lock, flags);
307         result = queue->buf[queue->tail];
308         queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
309         spin_unlock_irqrestore(&kbd_controller_lock, flags);
310
311         return result;
312 }
313
314
315 /*
316  * Write to the aux device.
317  */
318
319 static ssize_t write_aux(struct file * file, const char * buffer,
320                          size_t count, loff_t *ppos)
321 {
322         ssize_t retval = 0;
323
324         if (count) {
325                 ssize_t written = 0;
326
327                 if (count > 32)
328                         count = 32; /* Limit to 32 bytes. */
329                 do {
330                         char c;
331                         get_user(c, buffer++);
332                         written++;
333                 } while (--count);
334                 retval = -EIO;
335                 if (written) {
336                         retval = written;
337                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
338                 }
339         }
340
341         return retval;
342 }
343
344
345
346 static ssize_t read_aux(struct file * file, char * buffer,
347                         size_t count, loff_t *ppos)
348 {
349         DECLARE_WAITQUEUE(wait, current);
350         ssize_t i = count;
351         unsigned char c;
352
353         if (queue_empty()) {
354                 if (file->f_flags & O_NONBLOCK)
355                         return -EAGAIN;
356                 add_wait_queue(&queue->proc_list, &wait);
357 repeat:
358                 set_current_state(TASK_INTERRUPTIBLE);
359                 if (queue_empty() && !signal_pending(current)) {
360                         schedule();
361                         goto repeat;
362                 }
363                 current->state = TASK_RUNNING;
364                 remove_wait_queue(&queue->proc_list, &wait);
365         }
366         while (i > 0 && !queue_empty()) {
367                 c = get_from_queue();
368                 put_user(c, buffer++);
369                 i--;
370         }
371         if (count-i) {
372                 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
373                 return count-i;
374         }
375         if (signal_pending(current))
376                 return -ERESTARTSYS;
377         return 0;
378 }
379
380
381 static int open_aux(struct inode * inode, struct file * file)
382 {
383         if (aux_count++) 
384                 return 0;
385
386         queue->head = queue->tail = 0;  /* Flush input queue */
387         aux_count = 1;
388         aux_write_ack(AUX_ENABLE_DEV);  /* Enable aux device */
389         
390         return 0;
391 }
392
393
394 /* No kernel lock held - fine */
395 static unsigned int aux_poll(struct file *file, poll_table * wait)
396 {
397
398         poll_wait(file, &queue->proc_list, wait);
399         if (!queue_empty())
400                 return POLLIN | POLLRDNORM;
401         return 0;
402 }
403
404
405 static int release_aux(struct inode * inode, struct file * file)
406 {
407         lock_kernel();
408         fasync_aux(-1, file, 0);
409         if (--aux_count) {
410                 unlock_kernel();
411                 return 0;
412         }
413         unlock_kernel();
414         return 0;
415 }
416
417 static struct file_operations psaux_fops = {
418         read:           read_aux,
419         write:          write_aux,
420         poll:           aux_poll,
421         open:           open_aux,
422         release:        release_aux,
423         fasync:         fasync_aux,
424 };
425
426 static struct miscdevice psaux_mouse = {
427         minor:          PSMOUSE_MINOR,
428         name:           "psaux",
429         fops:           &psaux_fops,
430 };
431
432 #endif /* CONFIG_PSMOUSE */
433
434
435 /* This function is looking at the PS2 controller and empty the two buffers */
436
437 static u8 handle_lasikbd_event(unsigned long hpa)
438 {
439         u8 status_keyb,status_mouse,scancode,id;
440         extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */
441         
442         /* Mask to get the base address of the PS/2 controller */
443         id = gsc_readb(hpa+LASI_ID) & 0x0f;
444         
445         if (id==1) 
446                 hpa -= LASI_PSAUX_OFFSET; 
447         
448         status_keyb = read_status(hpa);
449         status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
450
451         while ((status_keyb|status_mouse) & LASI_STAT_RBNE){
452            
453                 while (status_keyb & LASI_STAT_RBNE) {
454               
455                 scancode = read_input(hpa);
456
457                 /* XXX don't know if this is a valid fix, but filtering
458                  * 0xfa avoids 'unknown scancode' errors on, eg, capslock
459                  * on some keyboards.
460                  */
461                       
462                 if (scancode == AUX_REPLY_ACK) 
463                         cmd_status=0;
464                         
465                 else if (scancode == AUX_RESEND)
466                         cmd_status=1;
467                 else 
468                         handle_at_scancode(scancode); 
469               
470                 status_keyb =read_status(hpa);
471                 }
472            
473 #ifdef CONFIG_PSMOUSE
474                 while (status_mouse & LASI_STAT_RBNE) {
475                         scancode = read_input(hpa+LASI_PSAUX_OFFSET);
476                         handle_mouse_scancode(scancode);
477                         status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
478                 }
479                 status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
480 #endif /* CONFIG_PSMOUSE */
481                 status_keyb = read_status(hpa);
482         }
483
484         tasklet_schedule(&keyboard_tasklet);
485         return (status_keyb|status_mouse);
486 }
487         
488 extern struct pt_regs *kbd_pt_regs;
489
490 static void lasikbd_interrupt(int irq, void *dev, struct pt_regs *regs)
491 {
492         kbd_pt_regs = regs;
493         handle_lasikbd_event((unsigned long) dev);
494 }
495
496 extern int pckbd_translate(unsigned char, unsigned char *, char);
497 extern int pckbd_setkeycode(unsigned int, unsigned int);
498 extern int pckbd_getkeycode(unsigned int);
499
500 static struct kbd_ops gsc_ps2_kbd_ops = {
501         setkeycode:     pckbd_setkeycode,
502         getkeycode:     pckbd_getkeycode,
503         translate:      pckbd_translate,
504         leds:           lasikbd_leds,
505 #ifdef CONFIG_MAGIC_SYSRQ
506         sysrq_key:      0x54,
507         sysrq_xlate:    hp_ps2kbd_sysrq_xlate,
508 #endif
509 };
510
511
512
513 #if 1
514 /* XXX: HACK !!!
515  * remove this function and the call in hil_kbd.c 
516  * if hp_psaux.c/hp_keyb.c is converted to the input layer... */
517 int register_ps2_keybfuncs(void)
518 {
519         gsc_ps2_kbd_ops.leds = NULL;
520         register_kbd_ops(&gsc_ps2_kbd_ops);
521 }
522 EXPORT_SYMBOL(register_ps2_keybfuncs);
523 #endif
524
525
526 static int __init
527 lasi_ps2_register(struct parisc_device *dev)
528 {
529         unsigned long hpa = dev->hpa;
530         char *name;
531         int device_found = 0;
532         u8 id;
533
534         id = gsc_readb(hpa+LASI_ID) & 0x0f;
535
536         switch (id) {
537         case 0:
538                 name = "keyboard";
539                 lasikbd_hpa = hpa;      /* save "hpa" for lasikbd_leds() */
540                 break;
541         case 1:
542                 name = "psaux";
543                 break;
544         default:
545                 printk(KERN_WARNING "%s: Unknown PS/2 port (id=%d) - ignored.\n",
546                         __FUNCTION__, id );
547                 return 0;
548         }
549         
550         /* reset the PS/2 port */
551         lasi_ps2_reset(hpa);
552
553         switch (id) {
554         case 0: 
555                 device_found = init_keyb(hpa);
556                 if (device_found) register_kbd_ops(&gsc_ps2_kbd_ops);
557                 break;
558         case 1:
559 #ifdef CONFIG_PSMOUSE
560                 queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
561                 if (!queue)
562                         return -ENOMEM;
563
564                 memset(queue, 0, sizeof(*queue));
565                 queue->head = queue->tail = 0;
566                 init_waitqueue_head(&queue->proc_list);
567                 
568                 misc_register(&psaux_mouse);
569
570                 aux_write_ack(AUX_ENABLE_DEV);
571                 /* try it a second time, this will give status if the device is
572                  * available */
573                 device_found = aux_write_ack(AUX_ENABLE_DEV);
574                 break;
575 #else
576                 /* return without printing any unnecessary and misleading info */
577                 return 0;       
578 #endif
579         } /* of case */
580         
581         if (device_found) {
582         /* Here we claim only if we have a device attached */   
583                 /* allocate the irq and memory region for that device */
584                 if (!dev->irq)
585                 return -ENODEV;
586            
587                 if (request_irq(dev->irq, lasikbd_interrupt, 0, name, (void *)hpa))
588                 return -ENODEV;
589            
590                 if (!request_mem_region(hpa, LASI_STATUS + 4, name))
591                 return -ENODEV;
592         }
593         
594         printk(KERN_INFO "PS/2 %s port at 0x%08lx (irq %d) found, "
595                          "%sdevice attached.\n",
596                         name, hpa, dev->irq, device_found ? "":"no ");
597
598         return 0;
599 }
600
601 static struct parisc_device_id lasi_psaux_tbl[] = {
602         { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 },
603         { 0, } /* 0 terminated list */
604 };
605
606 MODULE_DEVICE_TABLE(parisc, lasi_psaux_tbl);
607
608 static struct parisc_driver lasi_psaux_driver = {
609         name:           "Lasi psaux",
610         id_table:       lasi_psaux_tbl,
611         probe:          lasi_ps2_register,
612 };
613
614 static int __init gsc_ps2_init(void) 
615 {
616         return register_parisc_driver(&lasi_psaux_driver);
617 }
618
619 module_init(gsc_ps2_init);