1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/config.h>
18
19#include <linux/types.h>
20#include <linux/ptrace.h>
21#include <linux/interrupt.h>
22#include <linux/sched.h>
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
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
47#define AUX_REPLY_ACK 0xFA
48#define AUX_RESEND 0xFE
49#define AUX_RECONNECT 0xAA
50
51#define LASI_PSAUX_OFFSET 0x0100
52
53#define LASI_ID 0x00
54#define LASI_RESET 0x00
55#define LASI_RCVDATA 0x04
56#define LASI_XMTDATA 0x04
57#define LASI_CONTROL 0x08
58#define LASI_STATUS 0x0C
59
60
61#define LASI_CTRL_ENBL 0x01
62#define LASI_CTRL_LPBXR 0x02
63#define LASI_CTRL_DIAG 0x20
64#define LASI_CTRL_DATDIR 0x40
65#define LASI_CTRL_CLKDIR 0x80
66
67
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
76static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
77static unsigned long lasikbd_hpa;
78
79static volatile int cmd_status;
80
81static inline u8 read_input(unsigned long hpa)
82{
83 return gsc_readb(hpa+LASI_RCVDATA);
84}
85
86static inline u8 read_control(unsigned long hpa)
87{
88 return gsc_readb(hpa+LASI_CONTROL);
89}
90
91static inline void write_control(u8 val, unsigned long hpa)
92{
93 gsc_writeb(val, hpa+LASI_CONTROL);
94}
95
96static inline u8 read_status(unsigned long hpa)
97{
98 return gsc_readb(hpa+LASI_STATUS);
99}
100
101
102
103static 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
119
120static 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
134
135static inline int aux_write_ack(u8 val)
136{
137 return write_output(val, lasikbd_hpa+LASI_PSAUX_OFFSET);
138}
139
140
141
142
143
144
145static 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
175int 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 ;
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
200static 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
221static void __init lasi_ps2_reset(unsigned long hpa)
222{
223 u8 control;
224
225
226 gsc_writeb(0xff, hpa+LASI_RESET);
227 gsc_writeb(0x0 , hpa+LASI_RESET);
228
229
230 control = read_control(hpa);
231 write_control(control | LASI_CTRL_ENBL, hpa);
232}
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248#ifdef CONFIG_PSMOUSE
249
250static struct aux_queue *queue;
251static unsigned char mouse_reply_expected;
252static int aux_count;
253
254static 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
267static 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;
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
296static inline int queue_empty(void)
297{
298 return queue->head == queue->tail;
299}
300
301static 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
317
318
319static 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;
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
346static 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);
357repeat:
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
381static int open_aux(struct inode * inode, struct file * file)
382{
383 if (aux_count++)
384 return 0;
385
386 queue->head = queue->tail = 0;
387 aux_count = 1;
388 aux_write_ack(AUX_ENABLE_DEV);
389
390 return 0;
391}
392
393
394
395static 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
405static 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
417static 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
426static struct miscdevice psaux_mouse = {
427 minor: PSMOUSE_MINOR,
428 name: "psaux",
429 fops: &psaux_fops,
430};
431
432#endif
433
434
435
436
437static u8 handle_lasikbd_event(unsigned long hpa)
438{
439 u8 status_keyb,status_mouse,scancode,id;
440 extern void handle_at_scancode(int);
441
442
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
458
459
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
481 status_keyb = read_status(hpa);
482 }
483
484 tasklet_schedule(&keyboard_tasklet);
485 return (status_keyb|status_mouse);
486}
487
488extern struct pt_regs *kbd_pt_regs;
489
490static 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
496extern int pckbd_translate(unsigned char, unsigned char *, char);
497extern int pckbd_setkeycode(unsigned int, unsigned int);
498extern int pckbd_getkeycode(unsigned int);
499
500static 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
515
516
517int register_ps2_keybfuncs(void)
518{
519 gsc_ps2_kbd_ops.leds = NULL;
520 register_kbd_ops(&gsc_ps2_kbd_ops);
521}
522EXPORT_SYMBOL(register_ps2_keybfuncs);
523#endif
524
525
526static int __init
527lasi_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;
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
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
572
573 device_found = aux_write_ack(AUX_ENABLE_DEV);
574 break;
575#else
576
577 return 0;
578#endif
579 }
580
581 if (device_found) {
582
583
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
601static struct parisc_device_id lasi_psaux_tbl[] = {
602 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 },
603 { 0, }
604};
605
606MODULE_DEVICE_TABLE(parisc, lasi_psaux_tbl);
607
608static struct parisc_driver lasi_psaux_driver = {
609 name: "Lasi psaux",
610 id_table: lasi_psaux_tbl,
611 probe: lasi_ps2_register,
612};
613
614static int __init gsc_ps2_init(void)
615{
616 return register_parisc_driver(&lasi_psaux_driver);
617}
618
619module_init(gsc_ps2_init);
620