diff --recursive -c pl11/linux/config.in linux/config.in
*** pl11/linux/config.in	Fri Jul 30 22:26:39 1993
--- linux/config.in	Fri Aug  6 19:50:51 1993
***************
*** 53,59 ****
--- 53,62 ----
  *
  bool 'Keyboard meta-key sends ESC-prefix' CONFIG_KBD_META y
  bool 'Logitech busmouse support' CONFIG_BUSMOUSE n
+ bool 'QuickPort mouse support' CONFIG_QUICKPORT_MOUSE y
+ if [ "$CONFIG_QUICKPORT_MOUSE" = "n" ]
  bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE y
+ fi
  bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
  bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
  bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION y
diff --recursive -c pl11/linux/kernel/chr_drv/mouse.c linux/kernel/chr_drv/mouse.c
*** pl11/linux/kernel/chr_drv/mouse.c	Wed Feb 17 19:25:55 1993
--- linux/kernel/chr_drv/mouse.c	Fri Aug  6 19:40:21 1993
***************
*** 12,17 ****
--- 12,19 ----
   *
   * Made things a lot mode modular - easy to compile in just one or two
   * of the mouse drivers, as they are now completely independent. Linus.
+  *
+  * Added a few #ifdefs for QuickPort mouse. Johan Myreen - 05Aug93
   */
  
  #include <linux/fs.h>
***************
*** 44,50 ****
  	                file->f_op = &bus_mouse_fops;
  	                break;
  #endif
! #ifdef CONFIG_PSMOUSE
  		case PSMOUSE_MINOR:
  	                file->f_op = &psaux_fops;
  	                break;
--- 46,52 ----
  	                file->f_op = &bus_mouse_fops;
  	                break;
  #endif
! #if defined CONFIG_PSMOUSE || defined CONFIG_QUICKPORT_MOUSE
  		case PSMOUSE_MINOR:
  	                file->f_op = &psaux_fops;
  	                break;
***************
*** 82,88 ****
  #ifdef CONFIG_BUSMOUSE
  	kmem_start = bus_mouse_init(kmem_start);
  #endif
! #ifdef CONFIG_PSMOUSE
  	kmem_start = psaux_init(kmem_start);
  #endif
  #ifdef CONFIG_MS_BUSMOUSE
--- 84,90 ----
  #ifdef CONFIG_BUSMOUSE
  	kmem_start = bus_mouse_init(kmem_start);
  #endif
! #if defined CONFIG_PSMOUSE || defined CONFIG_QUICKPORT_MOUSE
  	kmem_start = psaux_init(kmem_start);
  #endif
  #ifdef CONFIG_MS_BUSMOUSE
diff --recursive -c pl11/linux/kernel/chr_drv/psaux.c linux/kernel/chr_drv/psaux.c
*** pl11/linux/kernel/chr_drv/psaux.c	Fri Jul  2 21:54:23 1993
--- linux/kernel/chr_drv/psaux.c	Wed Aug  4 22:11:47 1993
***************
*** 14,19 ****
--- 14,21 ----
   *   to perform the hardware initialization formerly done in setup.S by
   *   the BIOS.  Mouse characteristic setup is now included.
   *
+  * Modified by Johan Myreen (jem@cs.hut.fi) 04Aug93
+  *   to include support for QuickPort mouse.
   */
  
  #include <linux/timer.h>
***************
*** 26,31 ****
--- 28,35 ----
  #include <asm/segment.h>
  #include <asm/system.h>
  
+ #include <linux/config.h>
+ 
  /* aux controller ports */
  #define AUX_INPUT_PORT	0x60		/* Aux device output buffer */
  #define AUX_OUTPUT_PORT	0x60		/* Aux device input buffer */
***************
*** 59,64 ****
--- 63,84 ----
  #define AUX_IRQ		12
  #define AUX_BUF_SIZE	2048
  
+ /* QuickPort definitions */
+ 
+ #define QP_DATA         0x310		/* Data Port I/O Address */
+ #define QP_STATUS       0x311		/* Status Port I/O Address */
+ 
+ #define QP_DEV_IDLE     0x01	        /* Device Idle */
+ #define QP_RX_FULL      0x02		/* Device Char received */
+ #define QP_TX_IDLE      0x04		/* Device XMIT Idle */
+ #define QP_RESET        0x08		/* Device Reset */
+ #define QP_INTS_ON      0x10		/* Device Interrupt On */
+ #define QP_ERROR_FLAG   0x20		/* Device Error */
+ #define QP_CLEAR        0x40		/* Device Clear */
+ #define QP_ENABLE       0x80		/* Device Enable */
+ 
+ #define QP_IRQ          12
+ 
  extern unsigned char aux_device_present;
  
  struct aux_queue {
***************
*** 72,79 ****
  static int aux_ready = 0;
  static int aux_busy = 0;
  static int aux_present = 0;
! 
! static int poll_status(void);
  
  /*
   * Write to aux device
--- 92,105 ----
  static int aux_ready = 0;
  static int aux_busy = 0;
  static int aux_present = 0;
! static int qp_present = 0;
! static int qp_busy = 0;
! static int qp_data = QP_DATA;
! static int qp_status = QP_STATUS;
! 
! static int poll_aux_status(void);
! static int poll_qp_status(void);
! static int probe_qp(void);
  
  /*
   * Write to aux device
***************
*** 80,88 ****
   */
  static void aux_write_dev(int val)
  {
! 	poll_status();
  	outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);	/* write magic cookie */
! 	poll_status();
  	outb_p(val,AUX_OUTPUT_PORT);		/* write data */
  	
  }
--- 106,114 ----
   */
  static void aux_write_dev(int val)
  {
! 	poll_aux_status();
  	outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);	/* write magic cookie */
! 	poll_aux_status();
  	outb_p(val,AUX_OUTPUT_PORT);		/* write data */
  	
  }
***************
*** 110,118 ****
  
  static void aux_write_cmd(int val)
  {
! 	poll_status();
  	outb_p(AUX_CMD_WRITE,AUX_COMMAND);
! 	poll_status();
  	outb_p(val,AUX_OUTPUT_PORT);
  }
  
--- 136,144 ----
  
  static void aux_write_cmd(int val)
  {
! 	poll_aux_status();
  	outb_p(AUX_CMD_WRITE,AUX_COMMAND);
! 	poll_aux_status();
  	outb_p(val,AUX_OUTPUT_PORT);
  }
  
***************
*** 157,168 ****
  	wake_up_interruptible(&queue->proc_list);
  }
  
  
  static void release_aux(struct inode * inode, struct file * file)
  {
! 	poll_status();
  	aux_write_dev(AUX_DISABLE_DEV);		/* disable aux device */
! 	poll_status();
  	outb_p(AUX_DISABLE,AUX_COMMAND);      	/* Disable Aux device */
  	aux_write_cmd(AUX_INTS_OFF);		/* disable controller ints */
  	free_irq(AUX_IRQ);
--- 183,214 ----
  	wake_up_interruptible(&queue->proc_list);
  }
  
+ /*
+  * Interrupt handler for the QuickPort. A character
+  * is waiting in the 82C710.
+  */
+ 
+ static void qp_interrupt(int cpl)
+ {
+ 	int head = queue->head;
+ 	int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
+ 
+ 	queue->buf[head] = inb(qp_data);
+ 	if (head != maxhead) {
+ 		head++;
+ 		head &= AUX_BUF_SIZE-1;
+ 	}
+ 	queue->head = head;
+ 	aux_ready = 1;
+ 	wake_up_interruptible(&queue->proc_list);
+ }
+ 
  
  static void release_aux(struct inode * inode, struct file * file)
  {
! 	poll_aux_status();
  	aux_write_dev(AUX_DISABLE_DEV);		/* disable aux device */
! 	poll_aux_status();
  	outb_p(AUX_DISABLE,AUX_COMMAND);      	/* Disable Aux device */
  	aux_write_cmd(AUX_INTS_OFF);		/* disable controller ints */
  	free_irq(AUX_IRQ);
***************
*** 169,174 ****
--- 215,233 ----
  	aux_busy = 0;
  }
  
+ static void release_qp(struct inode * inode, struct file * file)
+ {
+ 	unsigned char status;
+ 
+ 	if (!poll_qp_status())
+ 	        printk("Warning: QuickPort device busy in release_qp()\n");
+ 	status = inb_p(qp_status);
+ 	outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
+ 	if (!poll_qp_status())
+ 	        printk("Warning: QuickPort device busy in release_qp()\n");
+ 	free_irq(QP_IRQ);
+ 	qp_busy = 0;
+ }
  
  /*
   * Install interrupt handler.
***************
*** 181,187 ****
  		return -EINVAL;
  	if (aux_busy)
  		return -EBUSY;
! 	if (!poll_status())
  		return -EBUSY;
  	aux_busy = 1;
  	queue->head = queue->tail = 0;  /* Flush input queue */
--- 240,246 ----
  		return -EINVAL;
  	if (aux_busy)
  		return -EBUSY;
! 	if (!poll_aux_status())
  		return -EBUSY;
  	aux_busy = 1;
  	queue->head = queue->tail = 0;  /* Flush input queue */
***************
*** 189,199 ****
  		return -EBUSY;
  	aux_write_dev(AUX_ENABLE_DEV);		/* enable aux device */
  	aux_write_cmd(AUX_INTS_ON);		/* enable controller ints */
! 	poll_status();
  	outb_p(AUX_ENABLE,AUX_COMMAND);		/* Enable Aux */
  	return 0;
  }
  
  
  /*
   * Write to the aux device.
--- 248,298 ----
  		return -EBUSY;
  	aux_write_dev(AUX_ENABLE_DEV);		/* enable aux device */
  	aux_write_cmd(AUX_INTS_ON);		/* enable controller ints */
! 	poll_aux_status();
  	outb_p(AUX_ENABLE,AUX_COMMAND);		/* Enable Aux */
  	return 0;
  }
  
+ /*
+  * Install interrupt handler.
+  * Enable the device, enable interrupts. Set qp_busy
+  * (allow only one opener at a time.)
+  */
+ 
+ static int open_qp(struct inode * inode, struct file * file)
+ {
+         unsigned char status;
+ 
+ 	if (!qp_present)
+ 		return -EINVAL;
+ 
+ 	if (qp_busy)
+ 		return -EBUSY;
+ 
+ 	if (request_irq(QP_IRQ, qp_interrupt))
+ 		return -EBUSY;
+ 
+ 	qp_busy = 1;
+ 
+ 	status = inb_p(qp_status);
+ 	status |= (QP_ENABLE|QP_RESET);
+ 	outb_p(status, qp_status);
+ 	status &= ~(QP_RESET);
+ 	outb_p(status, qp_status);
+ 
+ 	queue->head = queue->tail = 0;          /* Flush input queue */
+ 	status |= QP_INTS_ON;
+ 	outb_p(status, qp_status);              /* Enable interrupts */
+ 
+ 	while (!poll_qp_status()) {
+ 	        printk("Error: QuickPort device busy in open_qp()\n");
+ 		return -EBUSY;
+         }
+ 
+ 	outb_p(AUX_ENABLE_DEV, qp_data);	/* Wake up mouse */
+ 
+ 	return 0;
+ }
  
  /*
   * Write to the aux device.
***************
*** 204,213 ****
  	int i = count;
  
  	while (i--) {
! 		if (!poll_status())
  			return -EIO;
  		outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
! 		if (!poll_status())
  			return -EIO;
  		outb_p(get_fs_byte(buffer++),AUX_OUTPUT_PORT);
  	}
--- 303,312 ----
  	int i = count;
  
  	while (i--) {
! 		if (!poll_aux_status())
  			return -EIO;
  		outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
! 		if (!poll_aux_status())
  			return -EIO;
  		outb_p(get_fs_byte(buffer++),AUX_OUTPUT_PORT);
  	}
***************
*** 217,222 ****
--- 316,339 ----
  
  
  /*
+  * Write to the QuickPort device.
+  */
+ 
+ static int write_qp(struct inode * inode, struct file * file, char * buffer, int count)
+ {
+ 	int i = count;
+ 
+ 	while (i--) {
+ 		if (!poll_qp_status())
+ 			return -EIO;
+ 		outb_p(get_fs_byte(buffer++), qp_data);
+ 	}
+ 	inode->i_mtime = CURRENT_TIME;
+ 	return count;
+ }
+ 
+ 
+ /*
   * Put bytes from input queue to buffer.
   */
  
***************
*** 279,303 ****
  };
  
  
  unsigned long psaux_init(unsigned long kmem_start)
  {
! 	if (aux_device_present != 0xaa) {
! 		return kmem_start;
  	}
- 	printk("PS/2 type pointing device detected and installed.\n");
  	queue = (struct aux_queue *) kmem_start;
  	kmem_start += sizeof (struct aux_queue);
  	queue->head = queue->tail = 0;
  	queue->proc_list = NULL;
! 	aux_present = 1;
! 	poll_status();
! 	outb_p(AUX_DISABLE,AUX_COMMAND);      	/* Disable Aux device */
! 	aux_write_cmd(AUX_INTS_OFF);		/* disable controller ints */
  	return kmem_start;
  }
  
! 
! static int poll_status(void)
  {
  	int retries=0;
  
--- 396,442 ----
  };
  
  
+ /*
+  * Initialize driver. First check for QuickPort device; if found
+  * forget about the Aux port and use the QuickPort functions.
+  */
+ 
  unsigned long psaux_init(unsigned long kmem_start)
  {
!         int qp_found;
! 
! #ifdef CONFIG_QUICKPORT_MOUSE
! 	printk("Probing QuickPort device.\n");
!         if (qp_found = probe_qp()) {
! 	        printk("QuickPort pointing device detected -- driver installed.\n");
! 		printk("QuickPort address = %x (should be 0x310)\n", qp_data);
! 		qp_present = 1;
! 		psaux_fops.write = write_qp;
! 		psaux_fops.open = open_qp;
! 		psaux_fops.release = release_qp;
! 		poll_qp_status();
! 	} else
! #endif
! 	if (aux_device_present == 0xaa) {
! 	        printk("PS/2 type pointing device detected -- driver installed.\n");
!          	aux_present = 1;
! 	        poll_aux_status();
! 	} else {
! 	        printk("**** No mouse, no nothing... ****\n");
! 		return kmem_start;              /* No mouse at all */
  	}
  	queue = (struct aux_queue *) kmem_start;
  	kmem_start += sizeof (struct aux_queue);
  	queue->head = queue->tail = 0;
  	queue->proc_list = NULL;
! 	if (!qp_found) {
!         	outb_p(AUX_DISABLE,AUX_COMMAND);   /* Disable Aux device */
! 	        aux_write_cmd(AUX_INTS_OFF);    /* disable controller ints */
! 	}
  	return kmem_start;
  }
  
! static int poll_aux_status(void)
  {
  	int retries=0;
  
***************
*** 310,312 ****
--- 449,504 ----
  	}
  	return !(retries==MAX_RETRIES);
  }
+ 
+ /*
+  * Wait for device to send output char and flush any input char.
+  */
+ 
+ static int poll_qp_status(void)
+ {
+ 	int retries=0;
+ 
+ 	while ((inb(qp_status)&(QP_RX_FULL|QP_TX_IDLE|QP_DEV_IDLE))
+ 	               != (QP_DEV_IDLE|QP_TX_IDLE)
+ 	               && retries++ < MAX_RETRIES) {
+ 
+ 	        if (inb_p(qp_status)&(QP_RX_FULL))
+ 		        inb_p(qp_data);
+ 		current->state = TASK_INTERRUPTIBLE;
+ 		current->timeout = jiffies + 5;
+ 		schedule();
+ 	}
+ 	return !(retries==MAX_RETRIES);
+ }
+ 
+ /*
+  * Function to read register in 82C710.
+  */
+ 
+ static inline unsigned char read_710(unsigned char index)
+ {
+         outb_p(index, 0x390);			/* Write index */
+ 	return inb_p(0x391);			/* Read the data */
+ }
+ 
+ /*
+  * See if we can find a QuickPort device. Read mouse address.
+  */
+ 
+ static int probe_qp(void)
+ {
+         outb_p(0x55, 0x2fa);			/* Any value except 9, ff or 36 */
+ 	outb_p(0xaa, 0x3fa);			/* Inverse of 55 */
+ 	outb_p(0x36, 0x3fa);			/* Address the chip */
+ 	outb_p(0xe4, 0x3fa);			/* 390/4; 390 = config address */
+ 	outb_p(0x1b, 0x2fa);			/* Inverse of e4 */
+ 	if (read_710(0x0f) != 0xe4)		/* Config address found? */
+ 	  return 0;				/* No: no 82C710 here */
+ 	qp_data = read_710(0x0d)*4;		/* Get mouse I/O address */
+ 	qp_status = qp_data+1;
+ 	outb_p(0x0f, 0x390);
+ 	outb_p(0x0f, 0x391);			/* Close config mode */
+ 	return 1;
+ }
+ 	
+ 
