patch-2.1.79 linux/drivers/sbus/char/pcikbd.c

Next file: linux/drivers/sbus/char/pcikbd.h
Previous file: linux/drivers/sbus/char/pcicons.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.78/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.4 1997/09/05 22:59:53 ecd Exp $
+/* $Id: pcikbd.c,v 1.12 1997/12/27 16:28:27 jj Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -8,6 +8,7 @@
  * to the original authors.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -19,6 +20,7 @@
 #include <linux/random.h>
 #include <linux/miscdevice.h>
 #include <linux/kbd_ll.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 
 #include <asm/ebus.h>
@@ -26,7 +28,6 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/keyboard.h>
 
 #include "pcikbd.h"
 #include "sunserial.h"
@@ -35,6 +36,7 @@
 static int beep_node;
 
 static unsigned long pcikbd_iobase = 0;
+static unsigned long pcibeep_iobase = 0;
 static unsigned int pcikbd_irq;
 
 /* used only by send_data - set by keyboard_interrupt */
@@ -42,12 +44,31 @@
 static volatile unsigned char acknowledge = 0;
 static volatile unsigned char resend = 0;
 
+unsigned char pckbd_read_mask = KBD_STAT_OBF;
+
+extern int pcikbd_init(void);
+extern void pci_compute_shiftstate(void);
+extern int pci_setkeycode(unsigned int, unsigned int);
+extern int pci_getkeycode(unsigned int);
+extern void pci_setledstate(struct kbd_struct *, unsigned int);
+extern unsigned char pci_getledstate(void);
+
+static __inline__ unsigned char pcikbd_inb(unsigned long port)
+{
+	return inb(port);
+}
+
+static __inline__ void pcikbd_outb(unsigned char val, unsigned long port)
+{
+	outb(val, port);
+}
+
 static inline void kb_wait(void)
 {
 	unsigned long start = jiffies;
 
 	do {
-		if(!(inb(pcikbd_iobase + KBD_STATUS_REG) & KBD_STAT_IBF))
+		if(!(pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG) & KBD_STAT_IBF))
 			return;
 	} while (jiffies - start < KBC_TIMEOUT);
 }
@@ -167,6 +188,19 @@
   0, 0, 0, 0, 0, 0, 0, 0			      /* 0x78-0x7f */
 };
 
+/* Simple translation table for the SysRq keys */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char pcikbd_sysrq_xlate[128] =
+	"\000\0331234567890-=\177\t"			/* 0x00 - 0x0f */
+	"qwertyuiop[]\r\000as"				/* 0x10 - 0x1f */
+	"dfghjkl;'`\000\\zxcv"				/* 0x20 - 0x2f */
+	"bnm,./\000*\000 \000\201\202\203\204\205"	/* 0x30 - 0x3f */
+	"\206\207\210\211\212\000\000789-456+1"		/* 0x40 - 0x4f */
+	"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+	"\r\000/";					/* 0x60 - 0x6f */
+#endif
+
 static unsigned int prev_scancode = 0;
 
 int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode)
@@ -268,25 +302,17 @@
 {
 	unsigned char status;
 
-	/*
-	 * This IRQ might be shared with the 16550A serial chip,
-	 * so we check dev_id to see if it was for us.
-	 * (See also drivers/sbus/char/su.c).
-	 */
-	if (dev_id)
-		return;
-
-	/* kbd_pt_regs = regs; */
-	status = inb(pcikbd_iobase + KBD_STATUS_REG);
+	kbd_pt_regs = regs;
+	status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
 	do {
 		unsigned char scancode;
 
-		if(status & kbd_read_mask & KBD_STAT_MOUSE_OBF)
+		if(status & pckbd_read_mask & KBD_STAT_MOUSE_OBF)
 			break;
-		scancode = inb(pcikbd_iobase + KBD_DATA_REG);
+		scancode = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
 		if((status & KBD_STAT_OBF) && do_acknowledge(scancode))
-			/* handle_scancode(scancode) */;
-		status = inb(pcikbd_iobase + KBD_STATUS_REG);
+			handle_scancode(scancode);
+		status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
 	} while(status & KBD_STAT_OBF);
 	mark_bh(KEYBOARD_BH);
 }
@@ -300,7 +326,7 @@
 		kb_wait();
 		acknowledge = resend = 0;
 		reply_expected = 1;
-		outb(data, pcikbd_iobase + KBD_DATA_REG);
+		pcikbd_outb(data, pcikbd_iobase + KBD_DATA_REG);
 		start = jiffies;
 		do {
 			if(acknowledge)
@@ -325,10 +351,10 @@
 	unsigned long start = jiffies;
 
 	do {
-		status = inb(pcikbd_iobase + KBD_STATUS_REG);
+		status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
 		if(!(status & KBD_STAT_OBF))
 			continue;
-		data = inb(pcikbd_iobase + KBD_DATA_REG);
+		data = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
 		if(status & (KBD_STAT_GTO | KBD_STAT_PERR))
 			continue;
 		return (data & 0xff);
@@ -341,18 +367,55 @@
 	int status;
 
 	do {
-		status = inb(pcikbd_iobase + KBD_STATUS_REG);
+		status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
 	} while (status & KBD_STAT_IBF);
-	outb(data, pcikbd_iobase + address);
+	pcikbd_outb(data, pcikbd_iobase + address);
+}
+
+/* Timer routine to turn off the beep after the interval expires. */
+static void pcikbd_kd_nosound(unsigned long __unused)
+{
+	outl(0, pcibeep_iobase);
+}
+
+/*
+ * Initiate a keyboard beep. If the frequency is zero, then we stop
+ * the beep. Any other frequency will start a monotone beep. The beep
+ * will be stopped by a timer after "ticks" jiffies. If ticks is 0,
+ * then we do not start a timer.
+ */
+static void pcikbd_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+	unsigned long flags;
+	static struct timer_list sound_timer = { NULL, NULL, 0, 0,
+						 pcikbd_kd_nosound };
+
+	save_flags(flags); cli();
+	del_timer(&sound_timer);
+	if (hz) {
+		outl(1, pcibeep_iobase);
+		if (ticks) {
+			sound_timer.expires = jiffies + ticks;
+			add_timer(&sound_timer);
+		}
+	} else
+		outl(0, pcibeep_iobase);
+	restore_flags(flags);
 }
 
-__initfunc(static char *do_pcikbd_hwinit(void))
+static void nop_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+}
+
+extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
+
+__initfunc(static char *do_pcikbd_init_hw(void))
 {
 	while(pcikbd_wait_for_input() != -1)
 		;
 
 	pcikbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);
-	if(pcikbd_wait_for_input() != 0xff)
+	if(pcikbd_wait_for_input() != 0x55)
 		return "Keyboard failed self test";
 
 	pcikbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);
@@ -388,23 +451,12 @@
 	return NULL; /* success */
 }
 
-__initfunc(void pcikbd_hwinit(void))
-{
-	char *msg;
-
-	disable_irq(pcikbd_irq);
-	msg = do_pcikbd_hwinit();
-	enable_irq(pcikbd_irq);
-
-	if(msg)
-		printk("8042: keyboard init failure [%s]\n", msg);
-}
-
-__initfunc(int pcikbd_probe(void))
+__initfunc(void pcikbd_init_hw(void))
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
 	struct linux_ebus_child *child;
+	char *msg;
 
 	for_all_ebusdev(edev, ebus) {
 		if(!strcmp(edev->prom_name, "8042")) {
@@ -415,29 +467,57 @@
 		}
 	}
 	printk("pcikbd_probe: no 8042 found\n");
-	return -ENODEV;
+	return;
 
 found:
 	pcikbd_iobase = child->base_address[0];
 	if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
 		printk("8042: can't get region %lx, %d\n",
 		       pcikbd_iobase, (int)sizeof(unsigned long));
-		return -ENODEV;
+		return;
 	}
 	request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
 
 	pcikbd_irq = child->irqs[0];
 	if (request_irq(pcikbd_irq, &pcikbd_interrupt,
-			SA_SHIRQ, "keyboard", NULL)) {
+			SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
 		printk("8042: cannot register IRQ %x\n", pcikbd_irq);
-		return -ENODEV;
+		return;
 	}
 
 	printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, pcikbd_irq);
 
-	/* pcikbd_init(); */
-	kbd_read_mask = KBD_STAT_OBF;
-	return 0;
+	kd_mksound = nop_kd_mksound;
+	for_all_ebusdev(edev, ebus) {
+		if(!strcmp(edev->prom_name, "beeper"))
+			break;
+	}
+
+	/*
+	 * XXX: my 3.1.3 PROM does not give me the beeper node for the audio
+	 *      auxio register, though I know it is there... (ecd)
+	 */
+	if (!edev)
+		pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;
+	else
+		pcibeep_iobase = edev->base_address[0];
+
+	if (check_region(pcibeep_iobase, sizeof(unsigned int))) {
+		printk("8042: can't get region %lx, %d\n",
+		       pcibeep_iobase, (int)sizeof(unsigned int));
+	} else {
+		request_region(pcibeep_iobase, sizeof(unsigned int), "speaker");
+		kd_mksound = pcikbd_kd_mksound;
+		printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,
+		       edev ? "" : " (forced)");
+	}
+
+	disable_irq(pcikbd_irq);
+	msg = do_pcikbd_init_hw();
+	enable_irq(pcikbd_irq);
+
+	if(msg)
+		printk("8042: keyboard init failure [%s]\n", msg);
 }
 
 
@@ -451,8 +531,6 @@
 static unsigned long pcimouse_iobase = 0;
 static unsigned int pcimouse_irq;
 
-#define PSMOUSE_MINOR      1		/* Minor device # for this mouse */
-
 #define AUX_BUF_SIZE	2048
 
 struct aux_queue {
@@ -468,6 +546,16 @@
 static int aux_count = 0;
 static int aux_present = 0;
 
+static __inline__ unsigned char pcimouse_inb(unsigned long port)
+{
+	return inb(port);
+}
+
+static __inline__ void pcimouse_outb(unsigned char val, unsigned long port)
+{
+	outb(val, port);
+}
+
 /*
  *	Shared subroutines
  */
@@ -491,11 +579,11 @@
 	return queue->head == queue->tail;
 }
 
-static int fasync_aux(struct inode *inode, struct file *filp, int on)
+static int aux_fasync(struct file *filp, int on)
 {
 	int retval;
 
-	retval = fasync_helper(inode, filp, on, &queue->fasync);
+	retval = fasync_helper(filp, on, &queue->fasync);
 	if (retval < 0)
 		return retval;
 	return 0;
@@ -521,11 +609,11 @@
 {
 	int retries=0;
 
-	while ((inb(pcimouse_iobase + KBD_STATUS_REG) &
+	while ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) &
 		(KBD_STAT_IBF | KBD_STAT_OBF)) && retries < MAX_RETRIES) {
- 		if ((inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF)
+ 		if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF)
 		    == AUX_STAT_OBF)
-			inb(pcimouse_iobase + KBD_DATA_REG);
+			pcimouse_inb(pcimouse_iobase + KBD_DATA_REG);
 		current->state = TASK_INTERRUPTIBLE;
 		current->timeout = jiffies + (5*HZ + 99) / 100;
 		schedule();
@@ -541,9 +629,10 @@
 static void aux_write_dev(int val)
 {
 	poll_aux_status();
-	outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);/* Write magic cookie */
+	pcimouse_outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);/* Write magic cookie */
 	poll_aux_status();
-	outb_p(val, pcimouse_iobase + KBD_DATA_REG);		 /* Write data */
+	pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG);		 /* Write data */
+	udelay(1);
 }
 
 /*
@@ -555,8 +644,8 @@
 	aux_write_dev(val);
 	poll_aux_status();
 
-	if ((inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF)
-		return (inb(pcimouse_iobase + KBD_DATA_REG));
+	if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF)
+		return (pcimouse_inb(pcimouse_iobase + KBD_DATA_REG));
 	return 0;
 }
 
@@ -567,9 +656,9 @@
 static void aux_write_cmd(int val)
 {
 	poll_aux_status();
-	outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
+	pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
 	poll_aux_status();
-	outb(val, pcimouse_iobase + KBD_DATA_REG);
+	pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG);
 }
 
 /*
@@ -607,18 +696,10 @@
 	int head = queue->head;
 	int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
 
-	/*
-	 * This IRQ might be shared with the 16550A serial chip,
-	 * so we check dev_id to see if it was for us.
-	 * (See also drivers/sbus/char/su.c).
-	 */
-	if (dev_id)
-		return;
-
-	if ((inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) != AUX_STAT_OBF)
+	if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) != AUX_STAT_OBF)
 		return;
 
-	add_mouse_randomness(queue->buf[head] = inb(pcimouse_iobase + KBD_DATA_REG));
+	add_mouse_randomness(queue->buf[head] = pcimouse_inb(pcimouse_iobase + KBD_DATA_REG));
 	if (head != maxhead) {
 		head++;
 		head &= AUX_BUF_SIZE-1;
@@ -630,9 +711,9 @@
 	wake_up_interruptible(&queue->proc_list);
 }
 
-static int release_aux(struct inode * inode, struct file * file)
+static int aux_release(struct inode * inode, struct file * file)
 {
-	fasync_aux(inode, file, 0);
+	aux_fasync(file, 0);
 	if (--aux_count)
 		return 0;
 	aux_start_atomic();
@@ -642,7 +723,7 @@
 	poll_aux_status();
 
 	/* Disable Aux device */
-	outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
+	pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
 	poll_aux_status();
 	aux_end_atomic();
 
@@ -655,10 +736,11 @@
  * Enable auxiliary device.
  */
 
-static int open_aux(struct inode * inode, struct file * file)
+static int aux_open(struct inode * inode, struct file * file)
 {
 	if (!aux_present)
 		return -ENODEV;
+
 	aux_start_atomic();
 	if (aux_count++) {
 		aux_end_atomic();
@@ -674,7 +756,7 @@
 	MOD_INC_USE_COUNT;
 
 	poll_aux_status();
-	outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase+KBD_CNTL_REG);    /* Enable Aux */
+	pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase+KBD_CNTL_REG);    /* Enable Aux */
 	aux_write_dev(AUX_ENABLE_DEV);			    /* Enable aux device */
 	aux_write_cmd(AUX_INTS_ON);			    /* Enable controller ints */
 	poll_aux_status();
@@ -688,31 +770,31 @@
  * Write to the aux device.
  */
 
-static long write_aux(struct inode * inode, struct file * file,
-	const char * buffer, unsigned long count)
+static ssize_t aux_write(struct file * file, const char * buffer,
+			 size_t count, loff_t *ppos)
 {
-	int retval = 0;
+	ssize_t retval = 0;
 
 	if (count) {
-		int written = 0;
+		ssize_t written = 0;
 
 		aux_start_atomic();
 		do {
 			char c;
 			if (!poll_aux_status())
 				break;
-			outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);
+			pcimouse_outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);
 			if (!poll_aux_status())
 				break;
 			get_user(c, buffer++);
-			outb(c, pcimouse_iobase + KBD_DATA_REG);
+			pcimouse_outb(c, pcimouse_iobase + KBD_DATA_REG);
 			written++;
 		} while (--count);
 		aux_end_atomic();
 		retval = -EIO;
 		if (written) {
 			retval = written;
-			inode->i_mtime = CURRENT_TIME;
+			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
 		}
 	}
 
@@ -727,11 +809,11 @@
  * Put bytes from input queue to buffer.
  */
 
-static long read_aux(struct inode * inode, struct file * file,
-	char * buffer, unsigned long count)
+static ssize_t aux_read(struct file * file, char * buffer,
+		        size_t count, loff_t *ppos)
 {
 	struct wait_queue wait = { current, NULL };
-	int i = count;
+	ssize_t i = count;
 	unsigned char c;
 
 	if (queue_empty()) {
@@ -754,7 +836,7 @@
 	}
 	aux_ready = !queue_empty();
 	if (count-i) {
-		inode->i_atime = CURRENT_TIME;
+		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
 		return count-i;
 	}
 	if (signal_pending(current))
@@ -772,16 +854,16 @@
 
 struct file_operations psaux_fops = {
 	NULL,		/* seek */
-	read_aux,
-	write_aux,
+	aux_read,
+	aux_write,
 	NULL, 		/* readdir */
 	aux_poll,
 	NULL, 		/* ioctl */
 	NULL,		/* mmap */
-	open_aux,
-	release_aux,
+	aux_open,
+	aux_release,
 	NULL,
-	fasync_aux,
+	aux_fasync,
 };
 
 static struct miscdevice psaux_mouse = {
@@ -816,7 +898,7 @@
 
 	pcimouse_irq = child->irqs[0];
 	if (request_irq(pcimouse_irq, &pcimouse_interrupt,
-		        SA_SHIRQ, "mouse", NULL)) {
+		        SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) {
 		printk("8042: Cannot register IRQ %x\n", pcimouse_irq);
 		return -ENODEV;
 	}
@@ -826,7 +908,7 @@
 
 	printk("8042: PS/2 auxiliary pointing device detected.\n");
 	aux_present = 1;
-	kbd_read_mask = AUX_STAT_OBF;
+	pckbd_read_mask = AUX_STAT_OBF;
 
 	misc_register(&psaux_mouse);
 	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
@@ -834,18 +916,19 @@
 	queue->head = queue->tail = 0;
 	queue->proc_list = NULL;
 	aux_start_atomic();
-	outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG);
+	pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG);
+	aux_write_ack(AUX_RESET);
 	aux_write_ack(AUX_SET_SAMPLE);
 	aux_write_ack(100);
 	aux_write_ack(AUX_SET_RES);
 	aux_write_ack(3);
 	aux_write_ack(AUX_SET_SCALE21);
 	poll_aux_status();
-	outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
+	pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
 	poll_aux_status();
-	outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
+	pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
 	poll_aux_status();
-	outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG);
+	pcimouse_outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG);
 	poll_aux_status();
 	aux_end_atomic();
 
@@ -853,21 +936,6 @@
 }
 
 
-__initfunc(static int ps2_init(void))
-{
-	int err;
-
-	err = pcikbd_probe();
-	if (err)
-		return err;
-
-	err = pcimouse_init();
-	if (err)
-		return err;
-
-	return 0;
-}
-
 __initfunc(int ps2kbd_probe(unsigned long *memory_start))
 {
 	int pnode, enode, node, dnode;
@@ -959,6 +1027,12 @@
 	return -ENODEV;
 
 found:
-        sunserial_setinitfunc(memory_start, ps2_init);
+        sunkbd_setinitfunc(memory_start, pcimouse_init);
+        sunkbd_setinitfunc(memory_start, pcikbd_init);
+	kbd_ops.compute_shiftstate = pci_compute_shiftstate;
+	kbd_ops.setledstate = pci_setledstate;
+	kbd_ops.getledstate = pci_getledstate;
+	kbd_ops.setkeycode = pci_setkeycode;
+	kbd_ops.getkeycode = pci_getkeycode;
 	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov