patch-2.4.8 linux/drivers/s390/net/iucv.c

Next file: linux/drivers/s390/net/iucv.h
Previous file: linux/drivers/s390/net/fsm.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.7/linux/drivers/s390/net/iucv.c linux/drivers/s390/net/iucv.c
@@ -1,15 +1,30 @@
-/*
- *  drivers/s390/net/iucv.c
+/*                                                                                             
+ *   drivers/s390/net/iucv.c
  *    Support for VM IUCV functions for use by other part of the
  *    kernel or loadable modules.
  *
  *  S390 version
  *    Copyright (C) 2000 IBM Corporation
- *    Author(s): Xenia Tkatschow (xenia@us.ibm.com)
- *               Alan Altmark (Alan_Altmark@us.ibm.com)
- */
-
+ *    Author(s): Alan Altmark (Alan_Altmark@us.ibm.com)
+ *               Xenia Tkatschow (xenia@us.ibm.com)
+ * Functionality:                                                    
+ * To explore any of the IUCV functions, one must first register     
+ * their program using iucv_register(). Once your program has        
+ * successfully completed a register, it can use the other functions.
+ * For furthur reference on all IUCV functionality, refer to the     
+ * CP Programming Services book, also available on the web            
+ * thru www.ibm.com/s390/vm/pubs , manual # SC24-5760.               
+ *                                                                    
+ *      Definition of Return Codes                                    
+ *      -All positive return codes including zero are reflected back 
+ *       from CP and the definition can be found in CP Programming    
+ *       Services book.                  
+ *      - (-ENOMEM) Out of memory
+ *      - (-EINVAL) Invalid value                             
+*/
+/* #define DEBUG 1 */
 #include <linux/module.h>
+#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
@@ -20,25 +35,67 @@
 #include <asm/atomic.h>
 #include "iucv.h"
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/s390_ext.h>
 #include <asm/ebcdic.h>
 
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#ifdef DEBUG
+#undef KERN_INFO
 #undef KERN_DEBUG
+#define KERN_INFO KERN_EMERG
 #define KERN_DEBUG KERN_EMERG
-//#define DEBUG3
-//#define DEBUG         /* Turns Printk's on                         */
-//#define DEBUG2        /* This prints the parameter list before and */
-		      /* after the b2f0 call to cp                 */
+#endif
+
 #undef NULL
 #define NULL 0
-#define ADDED_STOR 64		/* ADDITIONAL STORAGE FOR PATHID @'S */
-ulong declare_flag = 0;
+
+#define PRRTY_PRMTD    0x01	/* priority permitted */
+#define RPY_RQRD       0x01	/* reply required */
+#define ADDED_STOR  64		/* ADDITIONAL STORAGE FOR PATHID @'S */
+#define BUFFER_SIZE 40		/* Size of 31-bit iparml */
+
+/* FLAGS:
+ * All flags are defined in the field IPFLAGS1 of each function
+ * and can be found in CP Programming Services.
+ * IPSRCCLS - Indicates you have specified a source class
+ * IPFGMCL  - Indicates you have specified a target class
+ * IPFGPID  - Indicates you have specified a pathid
+ * IPFGMID  - Indicates you have specified a message ID
+ * IPANSLST - Indicates that you are using an address list for
+ *            reply data
+ * IPBUFLST - Indicates that you are using an address list for
+ *            message data
+ */
+
+#define IPSRCCLS 	0x01
+#define IPFGMCL         0x01
+#define IPFGPID         0x02
+#define IPFGMID         0x04
+#define IPANSLST        0x08
+#define IPBUFLST        0x40
+
 static uchar iucv_external_int_buffer[40];
+
+/* Spin Lock declaration */
 struct tq_struct short_task;	/* automatically initialized to zero */
-static iucv_interrupt_ops_t my_ops;
-spinlock_t lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t iucv_lock = SPIN_LOCK_UNLOCKED;
 
-static void do_int (iucv_ConnectionPending *);
+/* General IUCV interrupt structure */
+typedef struct {
+	u16 ippathid;
+	uchar res1;
+	uchar iptype;
+	u32 res2;
+	uchar ipvmid[8];
+	uchar res3[24];
+} iucv_GeneralInterrupt;
 
 /***************INTERRUPT HANDLING DEFINITIONS***************/
 typedef struct _iucv_packet {
@@ -46,1984 +103,2323 @@
 	uchar data[40];
 } iucv_packet;
 struct tq_struct short_task;
+
 static spinlock_t iucv_packets_lock = SPIN_LOCK_UNLOCKED;
+
 iucv_packet *iucv_packets_head, *iucv_packets_tail;
 
 static atomic_t bh_scheduled = ATOMIC_INIT (0);
+
+/* 
+ *Internal function prototypes 
+ */
+
+static ulong iucv_vmsize (void);
+
+int iucv_declare_buffer (void);
+
+int iucv_retrieve_buffer (void);
+
+static int iucv_add_pathid (u16 pathid, iucv_handle_t handle, void *pgm_data);
+
+static void iucv_remove_pathid (u16 pathid);
+
 void bottom_half_interrupt (void);
 
+static void do_int (iucv_GeneralInterrupt *);
+
+inline void top_half_interrupt (struct pt_regs *regs, __u16 code);
 /************FUNCTION ID'S****************************/
-#define accept          10
-#define connect         11
-#define declare_buffer  12
-#define purge           9
-#define query           0
-#define quiesc          13
-#define receive         5
-#define reject          8
-#define reply           6
-#define resume          14
-#define retrieve_buffer 2
-#define send            4
-#define setmask         16
-#define sever           15
-
-/*****************************************************************/
-/*  Structure: handler                                           */
-/*  members: next - is a pointer to next handler on chain        */
-/*           prev - is a pointer to prev handler on chain        */
-/*           vmid - 8 char array of machine identification       */
-/*           user_data - 16 char array for user identification   */
-/*           mask - 24 char array used to compare the 2 previous */
-/*           interrupt_table - functions for interrupts          */
-/*           start - pointer to start of block of pointers to    */
-/*                   handler_table_entries                       */
-/*           end - pointer to end of block of pointers to        */
-/*                 handler_table_entries                         */
-/*           size - ulong, size of block                         */
-/*           pgm_data - ulong, program data                      */
-/* NOTE: Keep vmid and user_data together in this order          */
-/*****************************************************************/
+
+#define ACCEPT          10
+#define CONNECT         11
+#define DECLARE_BUFFER  12
+#define PURGE           9
+#define QUERY           0
+#define QUIESCE         13
+#define RECEIVE         5
+#define REJECT          8
+#define REPLY           6
+#define RESUME          14
+#define RETRIEVE_BUFFER 2
+#define SEND            4
+#define SETMASK         16
+#define SEVER           15
+
+/*                                                               
+ * Structure: handler                                            
+ * members: next - is a pointer to next handler on chain         
+ *          prev - is a pointer to prev handler on chain         
+ *          structure: id                                        
+ *             vmid - 8 char array of machine identification     
+ *             user_data - 16 char array for user identification 
+ *             mask - 24 char array used to compare the 2 previous  
+ *          interrupt_table - vector of interrupt functions.     
+ *          pathid_head - pointer to start of user_pathid_table  
+ *          pathid_tail - pointer to end of user_pathid_table    
+ *          entries -  ulong, size of user_pathid_table          
+ *          pgm_data -  ulong, application data that is passed   
+ *                      to the interrupt handlers                
+*/
 typedef struct {
 	ulong *next;
 	ulong *prev;
-	uchar vmid[8];
-	uchar user_data[16];
-	uchar mask[24];
+	struct {
+		uchar userid[8];
+		uchar user_data[16];
+		uchar mask[24];
+	} id;
 	iucv_interrupt_ops_t *interrupt_table;
-	ulong *start;
-	ulong *end;
-	ulong size;
-	ulong pgm_data;
+	ulong *pathid_head;
+	ulong *pathid_tail;
+	ulong entries;
+	void *pgm_data;
 } handler;
 
-/*******************************************************************/
-/* Structure: handler_table_entry                                  */
-/* members: addrs - pointer to a handler                           */
-/*          pathid - ushort containing path identification         */
-/*          pgm_data - ulong, program data                         */
-/*******************************************************************/
+/*                                                         
+ * Structure: handler_table_entry                          
+ * members: addrs - pointer to a handler                   
+ *          pathid - ushort containing path identification 
+ *          pgm_data - ulong, application data that is     
+ *                     passed to the interrupt handlers    
+ *          ops - pointer to iucv interrupt vector         
+ */
+
 typedef struct {
 	handler *addrs;
-	ushort pathid;
-	ulong pgm_data;
+	u16 pathid;
+	void *pgm_data;
+	iucv_interrupt_ops_t *ops;
 } handler_table_entry;
 
-/* main_table: array of pointers to handler_tables         */
-static handler_table_entry *main_table[128];
-/* handler_anchor: points to first handler on chain        */
-static handler *handler_anchor;
-
-/****************FIVE  STRUCTURES************************************/
-/* Data struct 1: iparml_control                                    */
-/*                Used for iucv_accept                              */
-/*                         iucv_connect                             */
-/*                         iucv_quiesce                             */
-/*                         iucv_resume                              */
-/*                         iucv_sever                               */
-/*                         iucv_retrieve_buffer                     */
-/* Data struct 2: iparml_dpl  (data in parameter list)              */
-/*                Used for iucv_send_prmmsg                         */
-/*                         iucv_send2way_prmmsg                     */
-/*                         iucv_send2way_prmmsg_array               */
-/*                         iucv_reply_prmmsg                        */
-/* Data struct 3: iparml_db    (data in a buffer)                   */
-/*                Used for iucv_receive                             */
-/*                         iucv_receive_array                       */
-/*                         iucv_receive_simple                      */
-/*                         iucv_reject                              */
-/*                         iucv_reply                               */
-/*                         iucv_reply_array                         */
-/*                         iucv_send                                */
-/*                         iucv_send_simple                         */
-/*                         iucv_send_array                          */
-/*                         iucv_send2way                            */
-/*                         iucv_send2way_array                      */
-/*                         iucv_declare_buffer                      */
-/* Data struct 4: iparml_purge                                      */
-/*                Used for iucv_purge                               */
-/*                         iucv_query                               */
-/* Data struct 5: iparml_set_mask                                   */
-/*                Used for iucv_set_mask                            */
-/********************************************************************/
+/* 
+ * Internal function prototypes 
+ */
+
+static int iucv_add_handler (handler * new_handler);
+
+static void iucv_remove_handler (handler * users_handler);
+
+/* handler_anchor: points to first handler on chain */
+/* handler_tail: points to last handler on chain */
+/* handler_table_anchor: points to beginning of handler_table_entries*/
+
+static handler *handler_anchor = NULL;
+
+static handler *handler_tail = NULL;
+
+static handler_table_entry *handler_table_anchor = NULL;
+
+/* declare_flag: is 0 when iucv_declare_buffer has not been called */
+
+static ulong declare_flag = 0;
+
+/****************FIVE 40-BYTE PARAMETER STRUCTURES******************/
+/* Data struct 1: iparml_control                                      
+ * Used for iucv_accept                                               
+ *          iucv_connect                                              
+ *          iucv_quiesce                                              
+ *          iucv_resume                                               
+ *          iucv_sever                                                
+ *          iucv_retrieve_buffer                                      
+ * Data struct 2: iparml_dpl     (data in parameter list)             
+ * Used for iucv_send_prmmsg                                          
+ *          iucv_send2way_prmmsg                                      
+ *          iucv_send2way_prmmsg_array                                
+ *          iucv_reply_prmmsg                                         
+ * Data struct 3: iparml_db       (data in a buffer)                  
+ * Used for iucv_receive                                              
+ *          iucv_receive_array                                        
+ *          iucv_reject                                               
+ *          iucv_reply                                                
+ *          iucv_reply_array                
+ *          iucv_send                       
+ *          iucv_send_array                 
+ *          iucv_send2way                   
+ *          iucv_send2way_array             
+ *          iucv_declare_buffer             
+ * Data struct 4: iparml_purge              
+ * Used for iucv_purge                      
+ *          iucv_query                      
+ * Data struct 5: iparml_set_mask           
+ * Used for iucv_set_mask                   
+*/
+
 typedef struct {
-	ushort ippathid;
+	u16 ippathid;
 	uchar ipflags1;
 	uchar iprcode;
-	ushort ipmsglim;
-	ushort res1;
+	u16 ipmsglim;
+	u16 res1;
 	uchar ipvmid[8];
 	uchar ipuser[16];
 	uchar iptarget[8];
 } iparml_control;
 
-/******************/
 typedef struct {
-	ushort ippathid;
+	u16 ippathid;
 	uchar ipflags1;
 	uchar iprcode;
-	ulong ipmsgid;
-	ulong iptrgcls;
+	u32 ipmsgid;
+	u32 iptrgcls;
 	uchar iprmmsg[8];
-	ulong ipsrccls;
-	ulong ipmsgtag;
-	ulong ipbfadr2;
-	ulong ipbfln2f;
-	ulong res;
+	u32 ipsrccls;
+	u32 ipmsgtag;
+	u32 ipbfadr2;
+	u32 ipbfln2f;
+	u32 res;
 } iparml_dpl;
 
-/*******************/
 typedef struct {
-	ushort ippathid;
+	u16 ippathid;
 	uchar ipflags1;
 	uchar iprcode;
-	ulong ipmsgid;
-	ulong iptrgcls;
-	ulong ipbfadr1;
-	ulong ipbfln1f;
-	ulong ipsrccls;
-	ulong ipmsgtag;
-	ulong ipbfadr2;
-	ulong ipbfln2f;
-	ulong res;
+	u32 ipmsgid;
+	u32 iptrgcls;
+	u32 ipbfadr1;
+	u32 ipbfln1f;
+	u32 ipsrccls;
+	u32 ipmsgtag;
+	u32 ipbfadr2;
+	u32 ipbfln2f;
+	u32 res;
 } iparml_db;
 
-/********************/
 typedef struct {
-	ushort ippathid;
+	u16 ippathid;
 	uchar ipflags1;
 	uchar iprcode;
-	ulong ipmsgid;
-	uchar ipaudit[4];
-	uchar res1[4];
-	ulong res2;
-	ulong ipsrccls;
-	ulong ipmsgtag;
-	ulong res3[3];
+	u32 ipmsgid;
+	uchar ipaudit[3];
+	uchar res1[5];
+	u32 res2;
+	u32 ipsrccls;
+	u32 ipmsgtag;
+	u32 res3[3];
 } iparml_purge;
 
-/*******************/
 typedef struct {
 	uchar ipmask;
 	uchar res1[2];
 	uchar iprcode;
-	ulong res2[9];
+	u32 res2[9];
 } iparml_set_mask;
 
 /*********************INTERNAL FUNCTIONS*****************************/
-/********************************************************************/
-/* Name: b2f0                                                       */
-/* Purpose: this function calls cp to execute iucv commands.        */
-/* Input: code - int, identifier of iucv call to cp.                */
-/*        parm - void *, pointer to 40 byte iparml area passed to cp */
-/* Output: iprcode- return code from iucv call to cp                */
-/********************************************************************/
-/* Assembler code performing iucv call                             */
-/*******************************************************************/
-inline ulong
-b2f0 (int code, void *parm)
+
+static ulong
+iucv_vmsize (void)
+{
+	extern unsigned long memory_size;
+	return memory_size;
+}
+
+/*
+ * Name: dumpit                                                     
+ * Purpose: print to the console buffers of a given length          
+ * Input: buf - (* uchar) - pointer to buffer to be printed         
+ *        len - int - length of buffer being printed                
+ * Output: void                                                     
+ */
+
+#ifdef DEBUG
+
+static void
+iucv_dumpit (uchar * buf, int len)
 {
-	uchar *iprcode;		/* used to extract iprcode */
-#ifdef DEBUG2
 	int i;
-	uchar *prt_parm;
-	prt_parm = (uchar *) (parm);
-	printk (KERN_DEBUG "parameter list before b2f0 call\n");
-	for (i = 0; i < 40; i++)
-		printk (KERN_DEBUG "%02x ", prt_parm[i]);
-	printk (KERN_DEBUG "\n");
-#endif
-	asm volatile ("LRA   1,0(%1)\n\t"
-		      "LR    0,%0\n\t"
-		      ".long 0xb2f01000"
-		      : : "d" (code), "a" (parm) : "0", "1");
-#ifdef DEBUG2
-	printk (KERN_DEBUG "parameter list after b2f0 call\n");
-	for (i = 0; i < 40; i++)
-		printk (KERN_DEBUG "%02x ", prt_parm[i]);
-	printk (KERN_DEBUG "\n");
-#endif
-	iprcode = (uchar *) (parm + 3);
-	return (ulong) (*iprcode);
+	for (i = 0; i < len; i++) {
+		if (!(i % 16) && i != 0)
+			printk ("\n");
+		else if (!(i % 4) && i != 0)
+			printk (" ");
+		printk ("%02X", buf[i]);
+	}
+	if (len % 16)
+		printk ("\n");
+	return;
 }
 
-/**************************************************************/
-/* Name: iucv_retrieve_buffer                                 */
-/* Purpose: terminates all use of iucv                        */
-/* Input: void                                                */
-/* Output: Return code from CP                                */
-/**************************************************************/
-int
-iucv_retrieve_buffer (void)
+#else
+static void
+iucv_dumpit (uchar * buf, int len)
 {
-	iparml_control parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_retrieve_buffer\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	b2f0_result = b2f0 (retrieve_buffer, &parm);
-	if (b2f0_result == NULL)
-		declare_flag = 0;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_retrieve_buffer\n");
-#endif
-	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_declare_buffer                                  */
-/* Purpose: specifies the guests real address of an external  */
-/*          interrupt.                                        */
-/* Input: bfr - pointer to  buffer                            */
-/* Output: iprcode - return code from b2f0 call               */
-/* Note : See output options for b2f0 call                    */
-/**************************************************************/
+#endif
+
+/*
+ * Name iucv_add_handler
+ * Purpose: Place new handle on handler_anchor chain, if identical handler is not
+ *	    found. Handlers are ordered with largest mask integer value first.
+ * Input: new_handler - handle that is being entered into chain
+ * Return: int
+ *	   0 - handler added
+ *	   1 - identical handler found, handler not added to chain
+*/
 int
-iucv_declare_buffer (uchar * bfr)
+iucv_add_handler (handler * new_handler)
 {
-	iparml_db parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "Entering iucv_declare_buffer\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	parm.ipbfadr1 = virt_to_phys (bfr);
-	b2f0_result = b2f0 (declare_buffer, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "Address of EIB = %p\n", bfr);
-	printk (KERN_DEBUG "Exiting iucv_declare_buffer\n");
-#endif
-	return b2f0_result;
+	handler *R = new_handler;
+	int rc = 1, comp = 0;	/* return code (rc = 1 not added) or (rc = 0 added) */
+	ulong flags;
+	pr_debug ("iucv_add_handler: entering\n");
+	iucv_dumpit ((uchar *) new_handler, sizeof (handler));
+	spin_lock_irqsave (&iucv_lock, flags);
+	if (handler_anchor == NULL) {
+		/* add to beginning of chain */
+		handler_anchor = handler_tail = new_handler;
+		rc = 0;
+	} else
+		for (R = handler_anchor; R != NULL; R = (handler *) R->next) {
+			comp = memcmp ((void *) &(new_handler->id),
+				       (void *) &(R->id), sizeof (R->id));
+			pr_debug ("comp = %d\n", comp);
+			if (comp == 0)	/* identicle handler found */
+				break;	/* break out of for loop */
+			else if (comp > 0) {	/* new_handler > R */
+				pr_debug
+				    ("iucv_add_handler: Found a place to add,"
+				     "R is\n");
+				iucv_dumpit ((uchar *) R, sizeof (handler));
+				if ((R->prev != NULL)) {
+					/* add to middle of chain */
+					pr_debug
+					    ("iucv_add_handler: added to middle\n");
+					new_handler->prev = R->prev;
+					new_handler->next = (ulong *) R;
+					((handler *) (R->prev))->next =
+					    (ulong *) new_handler;
+					R->prev = (ulong *) new_handler;
+					rc = 0;
+					break;	/* break out of FOR loop */
+				} else {	/* R->prev == NULL */
+					/* add to start of chain;  */
+					pr_debug ("iucv_add_handler:"
+						  "added to beginning\n");
+					R->prev = (ulong *) new_handler;
+					new_handler->next = (ulong *) R;
+					handler_anchor = new_handler;
+					rc = 0;
+					break;	/* break out of FOR loop */
+				}
+			}	/* end of else if */
+		}		/* end of for loop */
+	if (R == NULL) {
+		/* add to end of chain */
+		pr_debug ("iucv_add_handler: added to end\n");
+		handler_tail->next = (ulong *) new_handler;
+		new_handler->prev = (ulong *) handler_tail;
+		handler_tail = new_handler;
+		rc = 0;
+	}
+	spin_unlock_irqrestore (&iucv_lock, flags);
+
+	pr_debug ("Current Chain of handlers is\n");
+	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
+		iucv_dumpit ((uchar *) R, (int) sizeof (handler));
+
+	pr_debug ("iucv_add_handler: exiting\n");
+	return rc;
+}
+
+/* 
+ * Name: iucv_remove_handler
+ * Purpose: Remove handler when application unregisters.
+ * Input: users_handler - handler to be removed
+ * Output: void
+*/
+void
+iucv_remove_handler (handler * users_handler)
+{
+	handler *R;		/* used for Debugging */
+	pr_debug ("iucv_remove_handler: entering\n");
+	if ((users_handler->next != NULL) & (users_handler->prev != NULL)) {
+		/* remove from middle of chain */
+		((handler *) (users_handler->next))->prev =
+		    (ulong *) users_handler->prev;
+		((handler *) (users_handler->prev))->next =
+		    (ulong *) users_handler->next;
+	} else if ((users_handler->next != NULL) &
+		   (users_handler->prev == NULL)) {
+		/* remove from start of chain */
+		((handler *) (users_handler->next))->prev = NULL;
+		handler_anchor = (handler *) users_handler->next;
+	} else if ((users_handler->next == NULL) &
+		   (users_handler->prev != NULL)) {
+		/* remove from end of chain */
+		((handler *) (users_handler->prev))->next = NULL;
+		handler_tail = (handler *) users_handler->prev;
+	} else {
+		handler_anchor = NULL;
+		handler_tail = NULL;
+	}
+
+	pr_debug ("Current Chain of handlers is\n");
+	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
+		iucv_dumpit ((uchar *) R, (int) sizeof (handler));
+
+	pr_debug ("iucv_remove_handler: exiting\n");
+	return;
+}
+
+/*
+ * Name: b2f0
+ * Purpose: This function calls CP to execute IUCV commands.
+ * Input: code -  identifier of IUCV call to CP.
+ *        parm -  pointer to 40 byte iparml area
+ *               passed to CP
+ * Output: iprcode- return code from CP's IUCV call
+ * NOTE: Assembler code performing IUCV call
+*/
+inline ulong
+b2f0 (u32 code, void *parm)
+{
+	uchar *iprcode;
+	pr_debug ("iparml before b2f0 call\n");
+	iucv_dumpit ((uchar *) parm, (int) BUFFER_SIZE);
+	asm volatile ("LRA   1,0(%1)\n\t"
+		      "LR    0,%0\n\t"
+		      ".long 0xb2f01000"::"d" (code), "a" (parm):"0", "1");
+	pr_debug ("iparml after b2f0 call\n");
+	iucv_dumpit ((uchar *) parm, (int) BUFFER_SIZE);
+	iprcode = (uchar *) (parm + 3);
+	return (ulong) (*iprcode);
 }
 
-/**************************************************************/
-/* Name: add_pathid                                           */
-/* Purpose: adds a path id to the system                      */
-/* Input: pathid - ushort, pathid to enter system             */
-/*        handle - iucv_handle_t, address of handler to add to */
-/*        pgm_data - ulong, pathid identifier.                */
-/* Output: 0: successful addition of pathid                   */
-/**************************************************************/
+/*
+ * Name: iucv_add_pathid                                            
+ * Purpose: Adds a path id to the system.                       
+ * Input: pathid -  pathid that is going to be entered into system              
+ *        handle -  address of handler that the pathid will be associated
+ *		   with.
+ *        pgm_data - token passed in by application.                
+ * Output: 0: successful addition of pathid
+ *	   - EINVAL - pathid entry is being used by another application
+ *	   - ENOMEM - storage allocation for a new pathid table failed      
+*/
 int
-add_pathid (ushort pathid, iucv_handle_t handle, ulong pgm_data)
+iucv_add_pathid (u16 pathid, iucv_handle_t handle, void *pgm_data)
 {
-	ulong index1, index2;	/* index1 into main_table */
 	ulong add_flag = 0;
 	ulong old_size = 0, new_size = 0;
+	ulong flags;
 	uchar *to, *from;	/* pointer for copying the table */
-	handler_table_entry *P = 0;	/*P is a pointer to H_T_E */
-	handler *Q = 0;		/*Q is a pointer to handler */
-	ulong *X = 0;		/*Points to array of pointers */
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering add_pathid\n");
-#endif
-	Q = (handler *) handle;	/* Q points to a handler    */
-	/*
-	 * main_table has 128 entries.
-	 * 128*512 = 65536 maximum number of pathid's allowed
-	 */
-	index1 = ((ulong) pathid) / 512;
-	index2 = ((ulong) pathid) % 512;
-#ifdef DEBUG
-	printk (KERN_DEBUG "index1 = %d\n ", (int) index1);
-	printk (KERN_DEBUG "index2 = %d\n ", (int) index2);
-	printk (KERN_DEBUG "Q is pointing to %p ", Q);
-#endif
-	spin_lock (&lock);
-	/*
-	 * If NULL then handler table does not exist and need to get storage
-	 *  and have main_table[index1] point to it
-	 * If allocating storage failed, return
-	 */
-	if (main_table[index1] == NULL) {
-		main_table[index1] = (handler_table_entry *) kmalloc
-		    (512 * sizeof (handler_table_entry), GFP_KERNEL);
-		if (main_table[index1] == NULL) {
-			spin_unlock (&lock);
-			return -ENOBUFS;
-		}
-		memset (main_table[index1], 0,
-			512 * sizeof (handler_table_entry));
-#ifdef DEBUG
-		printk (KERN_DEBUG "address of table H_T is %p \n",
-			main_table[index1]);
-#endif
-	}
+	handler_table_entry *P = 0;	/*P is a pointer to the users H_T_E */
+	handler *users_handler = 0;
+	ulong *X = 0;		/* Points to array of pointers to H-T_E */
+
+	pr_debug ("iucv_add_pathid: entering\n");
+
+	users_handler = (handler *) handle;
+
+	pr_debug ("iucv_add_pathid: users_handler is pointing to %p ",
+		  users_handler);
+
+	spin_lock_irqsave (&iucv_lock, flags);
+
 	/*
-	 * P points to a handler table entry (H_T_E) in which all entries in
+	 * P points to the users handler table entry (H_T_E) in which all entries in
 	 * that structure should be NULL. If they're not NULL, then there
-	 * is a bad pointer and it will return(-2) immediately, otherwise
+	 * is a bad pointer and it will return(-EINVAL) immediately, otherwise users
 	 * data will be entered into H_T_E.
 	 */
-	P = main_table[index1];
-	if ((P + index2)->addrs) {
-#ifdef DEBUG
-		printk (KERN_DEBUG "main_table[index1] = %p \n",
-			main_table[index1]);
-		printk (KERN_DEBUG "P+index2 = %p \n", P + index2);
-		printk (KERN_DEBUG "(P+index2)->addrs is %p \n",
-			(P + index2)->addrs);
-#endif
-		spin_unlock (&lock);
-		printk (KERN_DEBUG "bad pointer1\n");
-		return (-2);
+
+	P = handler_table_anchor + pathid;	/* index into users handler table */
+
+	pr_debug ("handler_table_anchor is %p\n", handler_table_anchor);
+	pr_debug ("P=handler_table_anchor+pathid = %p\n", P);
+
+	if (P->addrs) {
+		pr_debug ("iucv_add_pathid: P = %p \n", P);
+		pr_debug ("iucv_add_pathid: P->addrs is %p \n", P->addrs);
+		spin_unlock_irqrestore (&iucv_lock, flags);
+		/* This message should be sent to syslog */
+		printk (KERN_WARNING "iucv_add_pathid: Pathid being used,"
+			"error.\n");
+		return (-EINVAL);
 	}
-	(P + index2)->addrs = handle;
+
+	P->addrs = handle;
+	P->pathid = pathid;
+
 	/*
-	 * checking if address of handle is valid, if it's not valid,
-	 * unlock the lock and return(-2) immediately.
+	 * pgm_data provided in iucv_register may be overwritten on a connect, accept. 
 	 */
-	if ((P + index2)->addrs == NULL) {
-		spin_unlock (&lock);
-		printk (KERN_DEBUG "bad pointer2\n");
-		return (-2);
-	}
-	(P + index2)->pathid = pathid;
+
 	if (pgm_data)
-		(P + index2)->pgm_data = pgm_data;
+		P->pgm_data = pgm_data;
 	else
-		(P + index2)->pgm_data = Q->pgm_data;
+		P->pgm_data = users_handler->pgm_data;
+
+	/*
+	 * Address of pathid's iucv_interrupt_ops is taken from the associated handler
+	 * and added here for quicker access to the interrupt tables during interrupt
+	 * handling.
+	 */
+
+	P->ops = (P->addrs)->interrupt_table;
+
+	pr_debug ("Complete users H_T_E is\n");
+	iucv_dumpit ((uchar *) P, sizeof (handler_table_entry));
+
 	/*
 	 * Step thru the table of addresses of pathid's to find the first
 	 * available entry (NULL). If an entry is found, add the pathid,
 	 * unlock and exit. If an available entry is not found, allocate a
-	 * new, larger table, copy over the old table and deallocate the
-	 * old table and add the pathid.
+	 * new, larger table, copy over the old table to the new table. De-allocate the
+	 * old table and enter the new pathid.
 	 */
-#ifdef DEBUG
-	printk (KERN_DEBUG "address of handle is %p\n", handle);
-	printk (KERN_DEBUG "&(Q->start) is %p\n", &(Q->start));
-	printk (KERN_DEBUG "&(Q->end) is %p\n", &(Q->end));
-	printk (KERN_DEBUG "start of pathid table is %p\n", (Q->start));
-	printk (KERN_DEBUG "end of pathid table is %p\n", (Q->end));
-	for (X = (Q->start); X < (Q->end); X++)
-		printk (KERN_DEBUG "X = %p ", X);
-	printk (KERN_DEBUG "\n");
-#endif
-	for (X = (Q->start); X < (Q->end); X++) {
+
+	pr_debug ("iucv_add_pathid: address of handle is %p\n", handle);
+	pr_debug ("iucv_add_pathid: &(users_handler->pathid_head) is %p\n",
+		  &(users_handler->pathid_head));
+	pr_debug ("iucv_add_pathid: &(users_handler->pathid_tail) is %p\n",
+		  &(users_handler->pathid_tail));
+	pr_debug ("iucv_add_pathid: start of pathid table is %p\n",
+		  (users_handler->pathid_head));
+	pr_debug ("iucv_add_pathid: end of pathid table is %p\n",
+		  (users_handler->pathid_tail));
+	iucv_dumpit ((uchar *) users_handler->pathid_head,
+		     (int) (users_handler->pathid_tail -
+			    users_handler->pathid_head));
+
+	for (X = (users_handler->pathid_head);
+	     X <
+	     (users_handler->pathid_head +
+	      users_handler->entries * sizeof (ulong)); X++)
 		if (*X == NULL) {
-#ifdef DEBUG
-			printk (KERN_DEBUG "adding pathid, %p = P+index2\n",
-				(P + index2));
-#endif
-			*X = (ulong) (P + index2);
+			pr_debug ("adding pathid, %p = P\n", P);
+			*X = (ulong) P;
 			add_flag = 1;
+			break;	/* breaks out of for loop */
 		}
-		if (add_flag == 1)
-			break;
-	}
-	if (add_flag == 0) {	/* element not added to list */
-		X = Q->start;
-		old_size = Q->size;
-		new_size = old_size + ADDED_STOR;	/* size of new table */
-		from = (uchar *) (Q->start);	/* address of old table */
-		(*Q).start = kmalloc (new_size * sizeof (ulong), GFP_KERNEL);
-		if ((Q->start) == NULL) {
-			spin_unlock (&lock);
-			return -ENOBUFS;
+
+	pr_debug ("Addresses of HTE's are\n");
+	iucv_dumpit ((uchar *) users_handler->pathid_head,
+		     users_handler->entries * sizeof (ulong));
+
+	if (add_flag == 0) {	/* element not added to list: must get a new table */
+		X = users_handler->pathid_head;
+		old_size = users_handler->entries;
+		new_size = old_size + ADDED_STOR;	/*number of entries of new table */
+		from = (uchar *) (users_handler->pathid_head);	/*address of old table */
+		users_handler->pathid_head =
+		    kmalloc (new_size * sizeof (ulong), GFP_ATOMIC);
+
+		if (users_handler->pathid_head == NULL) {
+			users_handler->pathid_head = X;	/*setting old condition */
+			spin_unlock_irqrestore (&iucv_lock, flags);
+			printk (KERN_WARNING
+				"iucv_add_pathid: storage allocation"
+				"failed for new pathid table \n ");
+			memset (P, 0, sizeof (handler_table_entry));
+			return -ENOMEM;
 		}
-		memset ((*Q).start, 0, new_size * sizeof (ulong));
-		to = (uchar *) (Q->start);	/* address of new table */
+
+		memset (users_handler->pathid_head, 0,
+			new_size * sizeof (ulong));
+		to = (uchar *) (users_handler->pathid_head);	/* address of new table */
 		/* copy old table to new  */
 		memcpy (to, from, old_size * (sizeof (ulong)));
-#ifdef DEBUG
-		printk (KERN_DEBUG "Getting a new pathid table\n");
-		printk (KERN_DEBUG "to is %p \n", to);
-		printk (KERN_DEBUG "from is %p \n", from);
-#endif
-		Q->size = new_size;	/* storing new size of table */
-		Q->end = (Q->start) + (Q->size);
-		X = Q->start + old_size;	/* next blank in table */
-		*X = (ulong) (P + index2);	/* adding element to new table */
-#ifdef DEBUG
-		printk (KERN_DEBUG "Q->size is %u \n", (int) (Q->size));
-		printk (KERN_DEBUG "Q->end is %p \n", Q->end);
-		printk (KERN_DEBUG "Q->start is %p \n", Q->start);
-		printk (KERN_DEBUG "X is %p \n", X);
-		printk (KERN_DEBUG "*X is %u \n", (int) (*X));
-#endif
+
+		pr_debug ("iucv: add_pathid: Getting a new pathid table\n");
+		pr_debug ("iucv: add_pathid: to is %p \n", to);
+		pr_debug ("iucv: add_pathid: from is %p \n", from);
+
+		users_handler->entries = new_size;	/* storing new size of table */
+		users_handler->pathid_tail =
+		    (users_handler->pathid_head) + (users_handler->entries);
+		X = users_handler->pathid_head + old_size;
+		*X = (ulong) P;	/* adding element to new table */
+
+		pr_debug ("iucv: add_pathid: users_handler->entries is %u \n",
+			  (int) (users_handler->entries));
+		pr_debug
+		    ("iucv: add_pathid: users_handler->pathid_tail is %p\n",
+		     users_handler->pathid_tail);
+		pr_debug ("users_handler->pathid_head is %p \n",
+			  users_handler->pathid_head);
+		pr_debug ("iucv: add_pathid: X is %p \n", X);
+		pr_debug ("iucv: add_pathid: *X is %u \n", (int) (*X));
+		pr_debug ("Addresses of HTE's after getting new table is\n");
+		iucv_dumpit ((uchar *) users_handler->pathid_head,
+			     users_handler->entries * sizeof (ulong));
+		pr_debug ("New handler is\n");
+		iucv_dumpit ((uchar *) users_handler, sizeof (handler));
+
 		kfree (from);	/* free old table */
 	}
-	spin_unlock (&lock);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting add_pathid\n");
-#endif
+	spin_unlock_irqrestore (&iucv_lock, flags);
+	pr_debug ("iucv_dd_pathid: exiting\n");
 	return (0);
 }				/* end of add_pathid function */
 
-/***********************EXTERNAL FUNCTIONS***************************/
-/**************************************************************/
-/* Name: iucv_query                                           */
-/* Purpose: determines how large an external interrupt buffer */
-/*          IUCV requires to store information                */
-/* Input : bufsize - ulong: size of interrupt buffer          */
-/*         - filled in by function and returned to caller     */
-/*         conmax  - ulong: maximum number of connections that */
-/*           can be outstanding for this VM                   */
-/*         - filled in by function and returned to caller     */
-/* Output: void                                               */
-/**************************************************************/
-void
-iucv_query (ulong * bufsize, ulong * conmax)
-{
-	iparml_purge parm;	/* DOESN'T MATTER WHICH IPARML IS USED    */
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_purge\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	/*
-	 * Assembler instruction calling b2f0  and storing R0 and R1
-	 */
-	asm volatile ("LRA   1,0(%3)\n\t"
-		      "LR    0,%2\n\t"
-		      ".long 0xb2f01000\n\t"
-		      "ST    0,%0\n\t"
-		      "ST    1,%1\n\t":"=m" (*bufsize),
-		      "=m" (*conmax):"d" (query), "a" (&parm):"0", "1");
-	return;
-}
-
-/**************************************************************/
-/* Name: iucv_purge                                           */
-/* Purpose: cancels a message you have sent                   */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong, mid of message                      */
-/*        srccls - ulong, sourse message class                */
-/*        audit  - uchar[4], info about ansync. error condit. */
-/*                 filled in by function and passed back      */
-/* Output: void                                               */
-/* NOTE: pathid is required, flag is always turned on         */
-/**************************************************************/
+/*
+ * Name: iucv_declare_buffer                                    
+ * Purpose: Specifies the guests real address of an external  
+ *          interrupt.                                        
+ * Input: void                             
+ * Output: iprcode - return code from b2f0 call               
+*/
 int
-iucv_purge (ulong msgid, ushort pathid, ulong srccls, uchar audit[4])
+iucv_declare_buffer (void)
 {
-	iparml_purge parm;
+	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_purge\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	parm.ipmsgid = msgid;
-	parm.ippathid = pathid;
-	parm.ipsrccls = srccls;
-	parm.ipflags1 |= specify_pathid;	/* pathid id flag */
-	if (parm.ipmsgid)
-		parm.ipflags1 |= specify_msgid;
-	if (parm.ipsrccls)
-		parm.ipflags1 |= source_class;
-	b2f0_result = b2f0 (purge, &parm);
-	if (b2f0_result != NULL)
-		return b2f0_result;
-	memcpy (audit, parm.ipaudit, 4);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_purge\n");
-#endif
+	pr_debug ("iucv_declare_buffer: entering\n");
+	memset (&parm, 0, sizeof (parm));
+	parm.ipbfadr1 = virt_to_phys ((uchar *) iucv_external_int_buffer);
+	b2f0_result = b2f0 (DECLARE_BUFFER, &parm);
+	pr_debug ("iucv_declare_buffer: Address of EIB = %p\n",
+		  iucv_external_int_buffer);
+	pr_debug ("iucv_declare_buffer: exiting\n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_quiesce                                         */
-/* Purpose: temporarily suspends incoming messages            */
-/* Input: pathid - ushort, pathid                             */
-/*        user_data - uchar[16], user id                      */
-/* Output: iprcode - return code from b2f0 call               */
-/* NOTE: see b2f0 output list                                 */
-/**************************************************************/
+/*
+ * Name: iucv_retrieve_buffer
+ * Purpose: Terminates all use of IUCV.
+ * Input: void
+ * Output:
+ *      b2f0_result: return code from CP
+*/
 int
-iucv_quiesce (ushort pathid, uchar user_data[16])
+iucv_retrieve_buffer (void)
 {
 	iparml_control parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_quiesce\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	memcpy (parm.ipuser, user_data, 16);
-	parm.ippathid = pathid;
-	b2f0_result = b2f0 (quiesc, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_quiesce\n");
-#endif
+	ulong b2f0_result = 0;
+	pr_debug ("iucv_retrieve_buffer: entering\n");
+	memset (&parm, 0, sizeof (parm));
+	b2f0_result = b2f0 (RETRIEVE_BUFFER, &parm);
+	if (b2f0_result == NULL) {
+		kfree (handler_table_anchor);
+		handler_table_anchor = NULL;
+		declare_flag = 0;
+	}
+	pr_debug ("iucv_retrieve_buffer: exiting\n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_resume                                          */
-/* Purpose: restores communication over a quiesced path       */
-/* Input: pathid - ushort, pathid                             */
-/*        user_data - uchar[16], user id                      */
-/* Output: iprcode - return code from b2f0 call               */
-/* NOTE: see b2f0 output list                                 */
-/**************************************************************/
-int
-iucv_resume (ushort pathid, uchar user_data[16])
-{
-	iparml_control parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_resume\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	memcpy (parm.ipuser, user_data, 16);
-	parm.ippathid = pathid;
-	b2f0_result = b2f0 (resume, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_resume\n");
-#endif
-	return b2f0_result;
-}
+/*
+ * Name: iucv_register_program
+ * Purpose: Registers an application with IUCV.   
+ * Input: prmname - user identification
+ *        userid  - machine identification
+ *        pgmmask - indicates which bits in the prmname and userid combined will be used
+ *	   to determine who is given control
+ *        ops - address of vector of interrupt handlers
+ *        pgm_data- application data passed to interrupt handlers
+ * Output: NA
+ * Return: type: iucv_handle_t
+ *          address of handler
+ *         (0) - registration failed
+ *	       - Machine size > 2GB
+ *	       - new_handler kmalloc failed
+ * 	       - pgmname was not provided
+ *	       - pathid_table kmalloc failed
+ *             - application with identical pgmname, userid, and pgmmask is registered
+ * 	       - iucv_declare_buffer failed
+ * NOTE: pgmmask
+ *	When pgmname, userid, pgmmask is provided, mask is entered into the handler
+ *	as is.
+ *	When pgmname, userid is provided, pgmmask is all 0xff's
+ *	When pgmname, pgmmask is provided, the first 8 bytes = 0x00 and the last 16
+ *      bytes are as provided by pgmmask. 
+ *	When pgmname is provided is provided, the first 8 bytes = 0x00 and the last
+ *	16 bytes are 0xff.   
+*/
 
-/**************************************************************/
-/* Name: iucv_reject                                          */
-/* Purpose: rejects a message                                 */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong, mid of message                      */
-/*        trgcls - ulong, target message class                */
-/* Output: iprcode - return code from b2f0 call               */
-/* NOTE: pathid is required field, flag always turned on      */
-/*       RESTRICTION: target class cannot be zero             */
-/* NOTE: see b2f0 output list                                 */
-/**************************************************************/
-int
-iucv_reject (ushort pathid, ulong msgid, ulong trgcls)
+iucv_handle_t
+iucv_register_program (uchar pgmname[16],
+		       uchar userid[8],
+		       uchar pgmmask[24],
+		       iucv_interrupt_ops_t * ops, void *pgm_data)
 {
-	iparml_db parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_reject\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	parm.ipmsgid = msgid;
-	parm.ippathid = pathid;
-	parm.iptrgcls = trgcls;
-	parm.ipflags1 |= specify_pathid;	/* flag for pathid */
-	if (parm.ipmsgid)
-		parm.ipflags1 |= specify_msgid;
-	if (parm.iptrgcls)
-		parm.ipflags1 |= target_class;
-	b2f0_result = b2f0 (reject, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_reject\n");
-#endif
-	return b2f0_result;
-}
+	ulong rc = 0;		/* return code from function calls */
+	ulong machine_size = 0;	/* size of virtual machine */
+	static u32 maxconn1;
+	handler *new_handler = NULL;
+
+	pr_debug ("iucv_register_program:entering\n");
+
+	if (ops == NULL) {
+		/* interrupt table is not defined */
+		printk (KERN_WARNING "iucv_register_program:"
+			"Interrupt table is not defined, exiting\n");
+		return NULL;
+	}
 
-/**************************************************************/
-/* Name: iucv_setmask                                         */
-/* Purpose: enables or disables certain iucv external interr. */
-/* Input: non_priority_interrupts - uchar                     */
-/*        priority_interrupts - uchar                         */
-/*        non_priority_completion_interrupts - uchar          */
-/*        priority_completion_interrupts) - uchar             */
-/* Output: iprcode - return code from b2f0 call               */
-/* NOTE: see b2f0 output list                                 */
-/**************************************************************/
-int
-iucv_setmask (uchar non_priority_interrupts,
-	      uchar priority_interrupts,
-	      uchar non_priority_completion_interrupts,
-	      uchar priority_completion_interrupts)
-{
-	iparml_set_mask parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_setmask\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	if (non_priority_interrupts)
-		parm.ipmask |= 0x80;
-	if (priority_interrupts)
-		parm.ipmask |= 0x40;
-	if (non_priority_completion_interrupts)
-		parm.ipmask |= 0x20;
-	if (priority_completion_interrupts)
-		parm.ipmask |= 0x10;
-	b2f0_result = b2f0 (setmask, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_setmask\n");
-#endif
-	return b2f0_result;
-}
+	if (declare_flag == 0) {
+		/* check size of virtual machine */
+		if ((machine_size = iucv_vmsize ()) > 0x100000000) {	/* 2GB */
+			printk (KERN_WARNING "iucv_register_progam: Virtual"
+				"storage = %lx hex," "exiting\n", machine_size);
+			return NULL;
+		}
 
-/**************************************************************/
-/* Name: iucv_sever                                           */
-/* Purpose: terminates an iucv path to another machine        */
-/* Input: pathid - ushort, pathid                             */
-/*        user_data - uchar[16], user id                      */
-/* Output: iprcode - return code from b2f0 call               */
-/* NOTE: see b2f0 output list                                 */
-/**************************************************************/
-int
-iucv_sever (ushort pathid, uchar user_data[16])
-{
-	ulong index1, index2;
-	ulong b2f0_result;
-	handler_table_entry *P = 0;
-	handler *Q = 0;
-	ulong *X;
-	iparml_control parm;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_sever\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	memcpy (parm.ipuser, user_data, 16);
-	parm.ippathid = pathid;
-	b2f0_result = b2f0 (sever, &parm);
-	if (b2f0_result)
-		return b2f0_result;
-	index1 = ((ulong) pathid) / 512;
-	index2 = ((ulong) pathid) % 512;
-	spin_lock (&lock);
-	P = main_table[index1];
-	if (((P + index2)->addrs) == NULL) {	/* called from interrupt code */
-		spin_unlock (&lock);
-		return (-2);	/* bad pointer */
-	}
-	Q = (*(P + index2)).addrs;
-#ifdef DEBUG
-	printk (KERN_DEBUG "pathid is %d\n", pathid);
-	printk (KERN_DEBUG "index1 is %d\n", (int) index1);
-	printk (KERN_DEBUG "index2 is %d\n", (int) index2);
-	printk (KERN_DEBUG "H_T_E is %p\n", P);
-	printk (KERN_DEBUG "address of handler is %p\n", Q);
-	for (X = ((*Q).start); X < ((*Q).end); X++)
-		printk (KERN_DEBUG " %x ", (int) (*X));
-	printk (KERN_DEBUG "\n above is pathid table\n");
-#endif
-/********************************************************************/
-/* Searching the pathid address table for matching address, once    */
-/* found, NULL the field. Then Null the H_T_E fields.               */
-/********************************************************************/
-	for (X = ((*Q).start); X < ((*Q).end); X++)
-		if (*X == (ulong) (P + index2)) {
-#ifdef DEBUG
-			printk (KERN_DEBUG "found a path to sever\n");
-			printk (KERN_DEBUG "severing %d \n", (int) (*X));
-#endif
-			*X = NULL;
-			(*(P + index2)).addrs = NULL;	/*clearing the fields */
-			(*(P + index2)).pathid = 0;
-			(*(P + index2)).pgm_data = 0;
+		pr_debug ("machine_size is %lx\n", machine_size);
+
+		maxconn1 = iucv_query_maxconn ();
+		handler_table_anchor = kmalloc (maxconn1 * sizeof
+						(handler_table_entry),
+						GFP_KERNEL);
+
+		if (handler_table_anchor == NULL) {
+			printk (KERN_WARNING "iucv_register_program:"
+				"handler_table_anchor"
+				"storage allocation failed\n");
+			return NULL;
 		}
-	spin_unlock (&lock);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_sever\n");
-#endif
-	return b2f0_result;
-}
 
-/**************************************************************/
-/* Name: iucv_receive                                         */
-/* Purpose: receives incoming message                         */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - *ulong, mid of message                     */
-/*        trgcls - *ulong, target message class               */
-/*        buffer - pointer of buffer                          */
-/*        buflen - length of buffer                           */
-/*        adds_curr_buffer - pointer to updated buffer address*/
-/*                           to write to                      */
-/*        adds_curr_length - pointer to updated length in     */
-/*                           buffer available to write to     */
-/*        reply_required - uchar *, flag                      */
-/*        priority_msg - uchar *, flag                        */
-/* Output: iprcode - return code from b2f0 call               */
-/* NOTE: pathid must be specified, flag being turned on       */
-/* RESTRICTIONS: target class CANNOT be zero because the code */
-/* checks for a non-NULL value to turn flag on, therefore if  */
-/* target class = zero, flag will not be turned on.           */
-/**************************************************************/
-int
-iucv_receive (ushort pathid, ulong * msgid, ulong * trgcls,
-	      void *buffer, ulong buflen,
-	      uchar * reply_required,
-	      uchar * priority_msg,
-	      ulong * adds_curr_buffer, ulong * adds_curr_length)
-{
-	iparml_db parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_receive\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	parm.ipmsgid = *msgid;
+		memset (handler_table_anchor, 0,
+			maxconn1 * sizeof (handler_table_entry));
+
+	}
+	/* Allocate handler table */
+	new_handler = (handler *) kmalloc (sizeof (handler), GFP_KERNEL);
+	if (new_handler == NULL) {
+		printk (KERN_WARNING "iucv_register_program: storage allocation"
+			"for new handler failed. \n ");
+		return NULL;
+	}
+	memset (new_handler, 0, sizeof (handler));
+	if (pgmname) {
+		memcpy (new_handler->id.user_data, pgmname,
+			sizeof (new_handler->id.user_data));
+		if (userid) {
+			memcpy (new_handler->id.userid, userid,
+				sizeof (new_handler->id.userid));
+			ASCEBC (new_handler->id.userid,
+				sizeof (new_handler->id.userid));
+			EBC_TOUPPER (new_handler->id.userid,
+				     sizeof (new_handler->id.userid));
+
+			if (pgmmask) {
+				memcpy (new_handler->id.mask, pgmmask,
+					sizeof (new_handler->id.mask));
+			} else {
+				memset (new_handler->id.mask, 0xFF,
+					sizeof (new_handler->id.mask));
+			}
+		} else {
+			if (pgmmask) {
+				memcpy (new_handler->id.mask, pgmmask,
+					sizeof (new_handler->id.mask));
+			} else {
+				memset (new_handler->id.mask, 0xFF,
+					sizeof (new_handler->id.mask));
+			}
+			memset (new_handler->id.mask, 0x00,
+				sizeof (new_handler->id.userid));
+		}
+	} else {
+		kfree (new_handler);
+		printk (KERN_WARNING "iucv_register_program: pgmname not"
+			"provided\n");
+		return NULL;
+	}
+	/* fill in the rest of handler */
+	new_handler->pgm_data = pgm_data;
+	new_handler->interrupt_table = ops;
+	new_handler->entries = ADDED_STOR;
+	/* Allocate storage for pathid table */
+	new_handler->pathid_head =
+	    kmalloc (new_handler->entries * sizeof (ulong), GFP_KERNEL);
+	if (new_handler->pathid_head == NULL) {
+		printk (KERN_WARNING "iucv_register_program: storage allocation"
+			"failed\n");
+		kfree (new_handler);
+		return NULL;
+	}
+
+	memset (new_handler->pathid_head, 0,
+		new_handler->entries * sizeof (ulong));
+	new_handler->pathid_tail =
+	    new_handler->pathid_head + new_handler->entries;
+	/* 
+	 * Check if someone else is registered with same pgmname, userid, and mask. 
+	 * If someone is already registered with same pgmname, userid, and mask 
+	 * registration will fail and NULL will be returned to the application. 
+	 * If identical handler not found, then handler is added to list.
+	 */
+	rc = iucv_add_handler (new_handler);
+	if (rc) {
+		printk (KERN_WARNING "iucv_register_program: Someone already"
+			"registered with same pgmname, userid, pgmmask\n");
+		kfree (new_handler->pathid_head);
+		kfree (new_handler);
+		return NULL;
+	}
+
+	if (declare_flag == 0) {
+		rc = iucv_declare_buffer ();
+		if (rc) {
+			kfree (handler_table_anchor);
+			kfree (new_handler->pathid_head);
+			kfree (new_handler);
+			handler_table_anchor = NULL;
+			printk (KERN_WARNING "iucv_register_program: rc from"
+				"iucv_declare_buffer is:% ld \n ", rc);
+			return NULL;
+		}
+		/* request the 0x4000 external interrupt */
+		rc = register_external_interrupt (0x4000, top_half_interrupt);
+		if (rc) {
+			iucv_retrieve_buffer ();
+			kfree (new_handler->pathid_head);
+			kfree (new_handler);
+			printk (KERN_WARNING "iucv_register_program: rc from"
+				"register_external_interrupt is:% ld \n ", rc);
+			return NULL;
+
+		}
+		declare_flag = 1;
+	}
+	pr_debug ("iucv_register_program: exiting\n");
+	return new_handler;
+}				/* end of register function */
+
+/*
+ * Name: iucv_unregister_program
+ * Purpose: Unregister application with IUCV.
+ * Input: handle address of handler
+ * Output: NA
+ * Return: (0) - Normal return
+ *         (-EINVAL)- Matching handler was not found
+*/
+
+int
+iucv_unregister_program (iucv_handle_t handle)
+{
+	handler *users_handler = 0, *R;
+	handler_table_entry *H_T_E = 0;
+	ulong *S = 0;		/*points to the beginning of block of h_t_e's */
+	ulong flags;
+	u16 pathid_sever = 0;
+	pr_debug ("iucv_unregister_program: entering\n");
+	pr_debug ("iucv_unregister_program: address of handle is %p\n", handle);
+	spin_lock_irqsave (&iucv_lock, flags);
+	users_handler = (handler *) handle;
+	/* 
+	 * Checking if handle is still registered: if yes, continue
+	 *  if not registered, return.
+	 */
+	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
+		if (users_handler == R) {
+			pr_debug ("iucv_unregister_program: found a matching"
+				  "handler\n");
+			break;
+		}
+	if (!R) {
+		pr_debug ("You are not registered\n");
+		spin_unlock_irqrestore (&iucv_lock, flags);
+		return (0);
+	}
+	S = users_handler->pathid_head;
+	while (S < (users_handler->pathid_tail)) {	/* index thru table */
+		if (*S) {
+			H_T_E = (handler_table_entry *) (*S);
+
+			pr_debug ("iucv_unregister_program: pointer to H_T_E is"
+				  "%p\n", H_T_E);
+			pr_debug
+			    ("iucv_unregister_program: address of handle in"
+			     "H_T_E is %p", (H_T_E->addrs));
+			pathid_sever = H_T_E->pathid;
+			spin_unlock_irqrestore (&iucv_lock, flags);
+			iucv_sever (pathid_sever, users_handler->id.user_data);
+			spin_lock_irqsave (&iucv_lock, flags);
+		}
+
+		S++;		/* index by address */
+	}
+
+	kfree (users_handler->pathid_head);
+	iucv_remove_handler (users_handler);
+	spin_unlock_irqrestore (&iucv_lock, flags);
+	kfree (handle);
+	pr_debug ("iucv_unregister_program: exiting\n");
+	return 0;
+}
+
+/*
+ * Name: iucv_accept
+ * Purpose: This function is issued after the user receives a Connection Pending external
+ *          interrupt and now wishes to complete the IUCV communication path.
+ * Input:  pathid - u16 , path identification number   
+ *         msglim_reqstd - u16, The number of outstanding messages requested.
+ *         user_data - uchar[16], Data specified by the iucv_connect function.
+ *	   flags1 - int, Contains options for this path.
+ *           -IPPRTY - 0x20- Specifies if you want to send priority message.
+ *           -IPRMDATA - 0x80, Specifies whether your program can handle a message
+ *            	in  the parameter list.
+ *           -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
+ *		established.
+ *         handle - iucv_handle_t, Address of handler.
+ *         pgm_data - ulong, Application data passed to interrupt handlers.
+ *	   flags1_out - int *, Options for path.
+ *           IPPRTY - 0x20 - Indicates you may send a priority message.
+ *         priority_permitted -uchar *, Indicates you may send priority messages.
+ *         msglim - *u16, Number of outstanding messages.
+ * Output: b2f0_result - return code from CP
+*/
+int
+iucv_accept (u16 pathid, u16 msglim_reqstd,
+	     uchar user_data[16], int flags1,
+	     iucv_handle_t handle, void *pgm_data,
+	     int *flags1_out, u16 * msglim)
+{
+	iparml_control parm;
+	ulong b2f0_result = 0;
+	ulong flags;
+	handler *R = NULL;
+	pr_debug ("iucv_accept: entering \n");
+	pr_debug ("iucv_accept: pathid = %d\n", pathid);
+
+	/* Checking if handle is valid  */
+	spin_lock_irqsave (&iucv_lock, flags);
+
+	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
+		if (R == handle)
+			break;
+
+	spin_unlock_irqrestore (&iucv_lock, flags);
+	if (R == NULL) {
+		printk (KERN_WARNING "iucv_connect: NULL handle passed by"
+			"application\n");
+		return -EINVAL;
+	}
+
+	memset (&parm, 0, sizeof (parm));
 	parm.ippathid = pathid;
-	parm.iptrgcls = *trgcls;
-	parm.ipflags1 |= specify_pathid;	/* turning pathid flag */
-	if (parm.ipmsgid)
-		parm.ipflags1 |= 0x05;
-	if (parm.iptrgcls)
-		parm.ipflags1 |= target_class;
-	parm.ipbfadr1 = (ulong) buffer;
-	parm.ipbfln1f = buflen;
-	b2f0_result = b2f0 (receive, &parm);
+	parm.ipmsglim = msglim_reqstd;
+	if (user_data)
+		memcpy (parm.ipuser, user_data, sizeof (parm.ipuser));
+	parm.ipflags1 = (uchar) flags1;
+	b2f0_result = b2f0 (ACCEPT, &parm);
+
+	if (b2f0_result == 0) {
+		if (pgm_data)
+			(handler_table_anchor + pathid)->pgm_data = pgm_data;
+		if (parm.ipflags1 & IPPRTY)
+			if (flags1_out) {
+				pr_debug ("*flags1_out = %d\n", *flags1_out);
+				*flags1_out = 0;
+				*flags1_out |= IPPRTY;
+				pr_debug (" *flags1_out = %d\n", *flags1_out);
+			}
+	}
+
+	pr_debug ("iucv_accept: exiting\n");
+	return b2f0_result;
+}
+
+/*
+ * Name: iucv_connect                                         
+ * Purpose: This function establishes an IUCV path. Although the connect may complete
+ *	    successfully, you are not able to use the path until you receive an IUCV 
+ *          Connection Complete external interrupt.            
+ * Input: pathid - u16 *, path identification number          
+ *        msglim_reqstd - u16, number of outstanding messages requested       
+ *        user_data - uchar[16], 16-byte user data                    
+ *        userid - uchar[8], 8-byte of user identification                        
+ *        system_name - uchar[8], 8-byte identifying the system name 
+ *        flags1 - int, Contains options for this path.
+ *          -IPPRTY - 0x20- Specifies if you want to send priority message.
+ *          -IPRMDATA - 0x80, Specifies whether your program can handle a message
+ *               in  the parameter list.
+ *          -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
+ *              established.
+ *          -IPLOCAL - 0X01, allows an application to force the partner to be on the
+ *              local system. If local is specified then target class cannot be
+ *              specified.  
+ *         flags1_out - int *, Options for path. 
+ *           IPPRTY - 0x20 - Indicates you may send a priority message.
+ *        msglim - * u16, number of outstanding messages
+ *        handle - iucv_handle_t, address of handler                         
+ *        pgm_data - *void, application data passed to interrupt handlers                  
+ * Output: b2f0_result - return code from CP
+ *         -ENOMEM
+ *         rc - return code from iucv_declare_buffer
+ *         -EINVAL - invalid handle passed by application 
+ *         -EINVAL - pathid address is NULL 
+ *	   -ENOMEM - pathid table storage allocation failed
+ *         add_pathid_result - return code from internal function add_pathid             
+*/
+int
+iucv_connect (u16 * pathid, u16 msglim_reqstd,
+	      uchar user_data[16], uchar userid[8],
+	      uchar system_name[8], int flags1,
+	      int *flags1_out, u16 * msglim,
+	      iucv_handle_t handle, void *pgm_data)
+{
+	iparml_control parm;
+	ulong b2f0_result = 0;
+	ulong flags;
+	int add_pathid_result = 0;
+	handler *R = NULL;
+	uchar no_memory[16] = "NO MEMORY";
+
+	pr_debug ("iucv_connect: entering \n");
+
+	/* Checking if handle is valid  */
+	spin_lock_irqsave (&iucv_lock, flags);
+
+	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
+		if (R == handle)
+			break;
+
+	spin_unlock_irqrestore (&iucv_lock, flags);
+
+	if (R == NULL) {
+		printk (KERN_WARNING "iucv_connect: NULL handle passed by"
+			"application\n");
+		return -EINVAL;
+	}
+
+	if (pathid == NULL) {
+		printk (KERN_WARNING "iucv_connect: NULL pathid pointer\n");
+		return -EINVAL;
+	}
+	memset (&parm, 0, sizeof (iparml_control));
+	parm.ipmsglim = msglim_reqstd;
+
+	if (user_data)
+		memcpy (parm.ipuser, user_data, sizeof (parm.ipuser));
+
+	if (userid) {
+		memcpy (parm.ipvmid, userid, sizeof (parm.ipvmid));
+		ASCEBC (parm.ipvmid, sizeof (parm.ipvmid));
+		EBC_TOUPPER (parm.ipvmid, sizeof (parm.ipvmid));
+	}
+
+	if (system_name) {
+		memcpy (parm.iptarget, system_name, sizeof (parm.iptarget));
+		ASCEBC (parm.iptarget, sizeof (parm.iptarget));
+		EBC_TOUPPER (parm.iptarget, sizeof (parm.iptarget));
+	}
+
+	parm.ipflags1 = (uchar) flags1;
+	b2f0_result = b2f0 (CONNECT, &parm);
 	if (b2f0_result)
 		return b2f0_result;
-	if (msgid)
-		*msgid = parm.ipmsgid;
-	if (trgcls)
-		*trgcls = parm.iptrgcls;
-	if (parm.ipflags1 & prior_msg)
-		if (priority_msg)
-			*priority_msg = 0x01;	/*yes, priority msg */
-	if (!(parm.ipflags1 & 0x10))	/*& with X'10'     */
-		if (reply_required)
-			*reply_required = 0x01;	/*yes, reply required */
-	if (!(parm.ipflags1 & parm_data)) {	/*msg not in parmlist */
-		if (adds_curr_length)
-			*adds_curr_length = parm.ipbfln1f;
-		if (adds_curr_buffer)
-			*adds_curr_buffer = parm.ipbfadr1;
-	} else {
-		if ((buflen) >= 8) {
-			if (buffer)
-				memcpy ((char *) buffer,
-					(char *) parm.ipbfadr1, 8);
-			if (adds_curr_length)
-				*adds_curr_length = ((buflen) - 8);
-			if (adds_curr_buffer)
-				*adds_curr_buffer = (ulong) buffer + 8;
-		} else {
-			parm.iprcode |= 0x05;
-			b2f0_result = (ulong) parm.iprcode;
-		}
+
+	add_pathid_result = iucv_add_pathid (parm.ippathid, handle, pgm_data);
+	if (add_pathid_result) {
+
+		iucv_sever (parm.ippathid, no_memory);
+		printk (KERN_WARNING "iucv_connect: add_pathid failed with rc ="
+			"%d\n", add_pathid_result);
+		return (add_pathid_result);
 	}
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_receive\n");
-#endif
+
+	*pathid = parm.ippathid;
+
+	if (msglim)
+		*msglim = parm.ipmsglim;
+
+	if (parm.ipflags1 & IPPRTY)
+		if (flags1_out) {
+			*flags1_out = 0;
+			*flags1_out |= IPPRTY;
+		}
+
+	pr_debug ("iucv_connect: exiting\n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_receive_simple                                  */
-/* Purpose: receives fully-qualified message                  */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong, id of message                       */
-/*        trgcls - ulong, target message class                */
-/*        buffer - pointer of buffer                          */
-/*        buflen - length of buffer                           */
-/* Output: iprcode - return code from b2f0 call               */
-/**************************************************************/
+/*
+ * Name: iucv_purge                                           
+ * Purpose: Cancels a message you have sent.                   
+ * Input: pathid -   address of pathid                                  
+ *        msgid  -   address of message identification             
+ *        srccls -   address of source message class                     
+ *        audit  -  contains information about                              
+ *                 asynchronous error that may have affected                           
+ *                 the normal completion of this message.                  
+ * Output:b2f0_result - return code from CP                   
+*/
 int
-iucv_receive_simple (ushort pathid, ulong msgid, ulong trgcls,
-		     void *buffer, ulong buflen)
+iucv_purge (u16 pathid, u32 msgid, u32 srccls, uchar audit[3])
+{
+	iparml_purge parm;
+	ulong b2f0_result = 0;
+	pr_debug ("iucv_purge: entering\n");
+	pr_debug ("iucv_purge: pathid = %d \n", pathid);
+	memset (&parm, 0, sizeof (parm));
+	parm.ipmsgid = msgid;
+	parm.ippathid = pathid;
+	parm.ipsrccls = srccls;
+	parm.ipflags1 |= (IPSRCCLS | IPFGMID | IPFGPID);
+	b2f0_result = b2f0 (PURGE, &parm);
+
+	if ((b2f0_result == 0) && (audit))
+		memcpy (audit, parm.ipaudit, sizeof (parm.ipaudit));
+
+	pr_debug ("iucv_purge: b2f0_result = %ld \n", b2f0_result);
+	pr_debug ("iucv_purge: exiting\n");
+	return b2f0_result;
+}
+
+/*
+ * Name: iucv_query_maxconn                                            
+ * Purpose: Determines the maximum number of connections thay may be established.
+ * Output: maxconn - ulong: Maximum number of connections that can be.     
+*/
+ulong
+iucv_query_maxconn (void)
+{
+	iparml_purge parm;	/* DOESN'T MATTER WHICH IPARML IS USED    */
+	static u32 maxconn1, bufsize1;
+
+	pr_debug ("iucv_query_maxconn: entering\n");
+
+	memset (&parm, 0, sizeof (parm));
+
+	/* Assembler instruction calling b2f0  and storing R0 and R1 */
+	asm volatile ("LRA   1,0(%3)\n\t"
+		      "LR    0,%2\n\t"
+		      ".long 0xb2f01000\n\t"
+		      "ST    0,%0\n\t"
+		      "ST    1,%1\n\t":"=m" (bufsize1),
+		      "=m" (maxconn1):"d" (QUERY), "a" (&parm):"0", "1");
+
+	pr_debug (" bufsize1 = %d and maxconn1 = %d \n", bufsize1, maxconn1);
+	pr_debug ("iucv_query_maxconn: exiting\n");
+
+	return maxconn1;
+}
+
+/*
+ * Name: iucv_query_bufsize
+ * Purpose: Determines the size of the external interrupt buffer.
+ * Output: bufsize - ulong: Size of external interrupt buffer.
+ */
+ulong
+iucv_query_bufsize (void)
+{
+	iparml_purge parm;	/* DOESN'T MATTER WHICH IPARML IS USED    */
+	static u32 maxconn1, bufsize1;
+
+	pr_debug ("iucv_query_bufsize: entering\n");
+	pr_debug ("iucv_query_maxconn: entering\n");
+
+	memset (&parm, 0, sizeof (parm));
+
+	/* Assembler instruction calling b2f0  and storing R0 and R1 */
+	asm volatile ("LRA   1,0(%3)\n\t"
+		      "LR    0,%2\n\t"
+		      ".long 0xb2f01000\n\t"
+		      "ST    0,%0\n\t"
+		      "ST    1,%1\n\t":"=m" (bufsize1),
+		      "=m" (maxconn1):"d" (QUERY), "a" (&parm):"0", "1");
+
+	pr_debug (" bufsize1 = %d and maxconn1 = %d \n", bufsize1, maxconn1);
+	pr_debug ("iucv_query_bufsize: exiting\n");
+
+	return bufsize1;
+}
+
+/*
+ * Name: iucv_quiesce                                         
+ * Purpose: temporarily suspends incoming messages on an IUCV path.
+ *          You can later reactivate the path by invoking the iucv_resume function        
+ * Input: pathid - u16, path identification number                             
+ *        user_data - uchar[16], 16-byte user data                      
+ * Output: b2f0_result - return code from CP               
+ */
+int
+iucv_quiesce (u16 pathid, uchar user_data[16])
+{
+	iparml_control parm;
+	ulong b2f0_result = 0;
+
+	pr_debug ("iucv_quiesce: entering \n");
+	pr_debug ("iucv_quiesce: pathid = %d\n", pathid);
+
+	memset (&parm, 0, sizeof (parm));
+	memcpy (parm.ipuser, user_data, sizeof (parm.ipuser));
+	parm.ippathid = pathid;
+
+	b2f0_result = b2f0 (QUIESCE, &parm);
+
+	pr_debug ("iucv_quiesce: b2f0_result = %ld\n", b2f0_result);
+	pr_debug ("iucv_quiesce: exiting\n");
+
+	return b2f0_result;
+}
+
+/*
+ * Name: iucv_receive
+ * Purpose: This function receives messages that are being sent to you
+ *          over established paths. 
+ * Input:
+ *        pathid - path identification number
+ *        buffer - address of buffer to receive
+ *        buflen - length of buffer to receive
+ *        msgid - specifies the message ID.
+ *        trgcls - specifies target class
+ * Output:
+ *	 flags1_out: Options for path.
+ *         IPNORPY - 0x10 specifies whether a reply is required
+ *         IPPRTY - 0x20 specifies if you want to send priority message
+ *         IPRMDATA - 0x80 specifies the data is contained in the parameter list
+ *       residual_buffer - address of buffer updated by the number
+ *                         of bytes you have received.
+ *       residual_length - 
+ *		Contains one of the following values, if the receive buffer is:
+ *		 The same length as the message, this field is zero.
+ *		 Longer than the message, this field contains the number of
+ *		  bytes remaining in the buffer.
+ *		 Shorter than the message, this field contains the residual
+ *		  count (that is, the number of bytes remaining in the
+ *		  message that does not fit into the buffer. In this
+ *		  case b2f0_result = 5. 
+ * Return: b2f0_result - return code from CP IUCV call.
+ *         (-EINVAL) - buffer address is pointing to NULL
+ */
+int
+iucv_receive (u16 pathid, u32 msgid, u32 trgcls,
+	      void *buffer, ulong buflen,
+	      int *flags1_out, ulong * residual_buffer, ulong * residual_length)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-	pr_debug ("entering iucv_receive_simple\n");
+	int moved = 0;		/* number of bytes moved from parmlist to buffer */
+	pr_debug ("iucv_receive: entering\n");
+
+	if (!buffer)
+		return -EINVAL;
 
-	memset (&(parm), 0, sizeof (parm));
+	memset (&parm, 0, sizeof (parm));
+	parm.ipbfadr1 = (u32) buffer;
+	parm.ipbfln1f = (u32) ((ulong) buflen);
 	parm.ipmsgid = msgid;
 	parm.ippathid = pathid;
 	parm.iptrgcls = trgcls;
-	parm.ipflags1 = IPFGMID + IPFGPID + IPFGMCL;
-	parm.ipbfadr1 = (ulong) buffer;
-	parm.ipbfln1f = buflen;
+	parm.ipflags1 = (IPFGPID | IPFGMID | IPFGMCL);
 
-	b2f0_result = b2f0 (receive, &parm);
-	if (b2f0_result)
-		return b2f0_result;
+	b2f0_result = b2f0 (RECEIVE, &parm);
+
+	if (b2f0_result == 0 || b2f0_result == 5) {
+		if (flags1_out) {
+			pr_debug ("*flags1_out = %d\n", *flags1_out);
+			*flags1_out = (parm.ipflags1 & (~0x07));
+			pr_debug ("*flags1_out = %d\n", *flags1_out);
+		}
+
+		if (!(parm.ipflags1 & IPRMDATA)) {	/*msg not in parmlist */
+			if (residual_length)
+				*residual_length = parm.ipbfln1f;
 
-	if (parm.ipflags1 & IPRMDATA) {	/*msg in parmlist */
-		if ((buflen) >= 8)
-			memcpy ((char *) buffer, (char *) parm.ipbfadr1, 8);
-		else
-			b2f0_result = 5;
-	}
-	pr_debug ("exiting iucv_receive_simple\n");
+			if (residual_buffer)
+				*residual_buffer = parm.ipbfadr1;
+		} else {
+			moved = min (buflen, 8);
+
+			memcpy ((char *) buffer,
+				(char *) &parm.ipbfadr1, moved);
+
+			if (buflen < 8)
+				b2f0_result = 5;
+
+			if (residual_length)
+				*residual_length = abs (buflen - 8);
+
+			if (residual_buffer)
+				*residual_buffer = (ulong) (buffer + moved);
+		}
+	}
+	pr_debug ("iucv_receive: exiting \n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_receive_array                                   */
-/* Purpose: receives incoming message                         */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  -* ulong, mid of message                     */
-/*        trgcls -* ulong, target message class               */
-/*        buffer - pointer of iucv_array_t                    */
-/*        buflen - ulong , length of buffer                   */
-/*        reply_required - uchar *, flag returned to caller   */
-/*        priority_msg - uchar *, flag returned to caller     */
-/*        adds_curr_buffer - pointer to updated buffer array  */
-/*                   to write to                              */
-/*        adds_curr_length - pointer to updated length in     */
-/*                   buffer available to write to             */
-/* Output: iprcode - return code from b2f0 call               */
-/* NOTE: pathid must be specified, flag being turned on       */
-/* RESTRICTIONS: target class CANNOT be zero because the code */
-/* checks for a non-NULL value to turn flag on, therefore if  */
-/* target class = if target class = zero flag will not be     */
-/* turned on, therefore if target class is specified it cannot */
-/* be zero.                                                   */
-/**************************************************************/
-int
-iucv_receive_array (ushort pathid, ulong * msgid, ulong * trgcls,
-		    iucv_array_t * buffer, ulong * buflen,
-		    uchar * reply_required,
-		    uchar * priority_msg,
-		    ulong * adds_curr_buffer, ulong * adds_curr_length)
+/*
+ * Name: iucv_receive_array
+ * Purpose: This function receives messages that are being sent to you
+ *          over established paths. 
+ * Input: pathid - path identification number
+ *        buffer - address of array of buffers
+ *        buflen - total length of buffers
+ *        msgid - specifies the message ID.
+ *        trgcls - specifies target class
+ * Output:
+ *        flags1_out: Options for path.
+ *          IPNORPY - 0x10 specifies whether a reply is required
+ *          IPPRTY - 0x20 specifies if you want to send priority message
+ *         IPRMDATA - 0x80 specifies the data is contained in the parameter list
+ *       residual_buffer - address points to the current list entry IUCV
+ *                         is working on.
+ *       residual_length -
+ *              Contains one of the following values, if the receive buffer is:
+ *               The same length as the message, this field is zero.
+ *               Longer than the message, this field contains the number of
+ *                bytes remaining in the buffer.
+ *               Shorter than the message, this field contains the residual
+ *                count (that is, the number of bytes remaining in the
+ *                message that does not fit into the buffer. In this case
+ *		  b2f0_result = 5.
+ * Return: b2f0_result - return code from CP
+ *         (-EINVAL) - buffer address is NULL
+ */
+int
+iucv_receive_array (u16 pathid,
+		    u32 msgid, u32 trgcls,
+		    iucv_array_t * buffer, ulong buflen,
+		    int *flags1_out,
+		    ulong * residual_buffer, ulong * residual_length)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_receive_array\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	parm.ipmsgid = *msgid;
+	int i = 0, moved = 0, need_to_move = 8, dyn_len;
+	pr_debug ("iucv_receive_array: entering\n");
+
+	if (!buffer)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
+	parm.ipbfadr1 = (u32) ((ulong) buffer);
+	parm.ipbfln1f = (u32) buflen;
+	parm.ipmsgid = msgid;
 	parm.ippathid = pathid;
-	parm.iptrgcls = *trgcls;
-	parm.ipflags1 |= array;	/* using an address list  */
-	parm.ipflags1 |= specify_pathid;	/*turning on pathid flag */
-	if (parm.ipmsgid)
-		parm.ipflags1 |= 0x05;
-	if (parm.iptrgcls)
-		parm.ipflags1 |= target_class;
-	parm.ipbfadr1 = (ulong) buffer;
-	parm.ipbfln1f = *buflen;
-	b2f0_result = b2f0 (receive, &parm);
-	if (b2f0_result)
-		return b2f0_result;
-	if (msgid)
-		*msgid = parm.ipmsgid;
-	if (trgcls)
-		*trgcls = parm.iptrgcls;
-	if (parm.ipflags1 & prior_msg)
-		if (priority_msg)
-			*priority_msg = 0x01;	/*yes, priority msg */
-	if (!(parm.ipflags1 & 0x10))	/*& with X'10'     */
-		if (reply_required)
-			*reply_required = 0x01;	/*yes, reply required */
-	if (!(parm.ipflags1 & parm_data)) {	/*msg not in parmlist */
-		if (adds_curr_length)
-			*adds_curr_length = parm.ipbfln1f;
-		if (adds_curr_buffer)
-			*adds_curr_buffer = parm.ipbfadr1;
-	} else {
-		if ((buffer->length) >= 8) {
-			memcpy ((char *) buffer->address,
-				(char *) parm.ipbfadr1, 8);
-			if (adds_curr_buffer)
-				*adds_curr_buffer =
-				    (ulong) ((buffer->address) + 8);
-			if (adds_curr_length)
-				*adds_curr_length = ((buffer->length) - 8);
+	parm.iptrgcls = trgcls;
+	parm.ipflags1 = (IPBUFLST | IPFGPID | IPFGMID | IPFGMCL);
+
+	b2f0_result = b2f0 (RECEIVE, &parm);
+
+	if (b2f0_result == 0 || b2f0_result == 5) {
+
+		if (flags1_out) {
+			pr_debug ("*flags1_out = %d\n", *flags1_out);
+			*flags1_out = (parm.ipflags1 & (~0x07));
+			pr_debug ("*flags1_out = %d\n", *flags1_out);
+		}
+
+		if (!(parm.ipflags1 & IPRMDATA)) {	/*msg not in parmlist */
+
+			if (residual_length)
+				*residual_length = parm.ipbfln1f;
+
+			if (residual_buffer)
+				*residual_buffer = parm.ipbfadr1;
 
 		} else {
-			parm.iprcode |= 0x05;
-			b2f0_result = (ulong) parm.iprcode;
+			/* copy msg from parmlist to users array. */
+
+			while ((moved < 8) && (moved < buflen)) {
+				dyn_len =
+				    min ((buffer + i)->length, need_to_move);
+
+				memcpy ((char *)((ulong)((buffer + i)->address)),
+					((char *) &parm.ipbfadr1) + moved,
+					dyn_len);
+
+				moved += dyn_len;
+				need_to_move -= dyn_len;
+
+				(buffer + i)->address =
+				    	(u32)  
+				((ulong)(uchar *) ((ulong)(buffer + i)->address) 
+						+ dyn_len);
+
+				(buffer + i)->length -= dyn_len;
+				i++;
+			}
+
+			if (need_to_move)	/* buflen < 8 bytes */
+				b2f0_result = 5;
+
+			if (residual_length)
+				*residual_length = abs (buflen - 8);
+
+			if (residual_buffer) {
+				if (moved == 0)
+					*residual_buffer = (ulong) buffer;
+				else
+					*residual_buffer =
+					    (ulong) (buffer + (i - 1));
+			}
+
 		}
 	}
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_receive\n");
-#endif
+
+	pr_debug ("iucv_receive_array: exiting\n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_send                                            */
-/* Purpose: sends messages                                    */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong *, id of message returned to caller  */
-/*        trgcls - ulong, target message class                */
-/*        srccls - ulong, source message class                */
-/*        msgtag - ulong, message tag                         */
-/*        priority_msg - uchar, flag                          */
-/*        buffer - pointer to buffer                          */
-/*        buflen - ulong, length of buffer                    */
-/* Output: iprcode - return code from b2f0 call               */
-/*         msgid - returns message id                         */
-/**************************************************************/
-int
-iucv_send (ushort pathid, ulong * msgid,
-	   ulong trgcls, ulong srccls,
-	   ulong msgtag, uchar priority_msg, void *buffer, ulong buflen)
+/*
+ * Name: iucv_reject                                          
+ * Purpose: Refuses a specified message. Between the time you are notified of a 
+ *          message and the time that you complete the message, the message may
+ *          be rejected.                                 
+ * Input: pathid - u16, path identification number.                            
+ *        msgid  - u32, specifies the message ID.
+ *        trgcls - u32, specifies target class.                
+ * Output: b2f0_result - return code from CP
+ * NOTE: see b2f0 output list                                 
+*/
+int
+iucv_reject (u16 pathid, u32 msgid, u32 trgcls)
+{
+	iparml_db parm;
+	ulong b2f0_result = 0;
+
+	pr_debug ("iucv_reject: entering \n");
+	pr_debug ("iucv_reject: pathid = %d\n", pathid);
+
+	memset (&parm, 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.ipmsgid = msgid;
+	parm.iptrgcls = trgcls;
+	parm.ipflags1 = (IPFGMCL | IPFGMID | IPFGPID);
+
+	b2f0_result = b2f0 (REJECT, &parm);
+
+	pr_debug ("iucv_reject: b2f0_result = %ld\n", b2f0_result);
+	pr_debug ("iucv_reject: exiting\n");
+
+	return b2f0_result;
+}
+
+/* 
+ * Name: iucv_reply
+ * Purpose: This function responds to the two-way messages that you
+ *          receive. You must identify completely the message to
+ *          which you wish to reply. ie, pathid, msgid, and trgcls.
+ * Input: pathid - path identification number
+ *        msgid - specifies the message ID. 
+ *        trgcls - specifies target class
+ *        flags1 - option for path
+ *                 IPPRTY- 0x20 - specifies if you want to send priority message
+ *        buffer - address of reply buffer
+ *        buflen - length of reply buffer
+ * Output: ipbfadr2 - Address of buffer updated by the number
+ *                    of bytes you have moved.
+ *         ipbfln2f - Contains on the the following values
+ *              If the answer buffer is the same length as the reply, this field
+ *               contains zero.
+ *              If the answer buffer is longer than the reply, this field contains
+ *               the number of bytes remaining in the buffer.
+ *              If the answer buffer is shorter than the reply, this field contains
+ *               a residual count (that is, the number of bytes remianing in the
+ *               reply that does not fit into the buffer. In this
+ *                case b2f0_result = 5.
+ * Return: b2f0_result - return code from CP
+ *         (-EINVAL) - buffer address is NULL
+ */
+int
+iucv_reply (u16 pathid,
+	    u32 msgid, u32 trgcls,
+	    int flags1,
+	    void *buffer, ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_send\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_reply: entering\n");
+
+	if (!buffer)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
+	parm.ipbfadr2 = (u32) ((ulong) buffer);
+	parm.ipbfln2f = (u32) buflen;	/* length of message */
 	parm.ippathid = pathid;
+	parm.ipmsgid = msgid;
 	parm.iptrgcls = trgcls;
-	parm.ipbfadr1 = (ulong) buffer;
-	parm.ipbfln1f = buflen;	/* length of message */
-	parm.ipsrccls = srccls;
-	parm.ipmsgtag = msgtag;
-	parm.ipflags1 |= one_way_msg;	/* one way message */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	b2f0_result = b2f0 (send, &parm);
-	if (b2f0_result)
-		return b2f0_result;
-	if (msgid)
-		*msgid = parm.ipmsgid;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_send\n");
-#endif
+	parm.ipflags1 = (uchar) flags1;	/* priority message */
+
+	b2f0_result = b2f0 (REPLY, &parm);
+
+	if ((b2f0_result == 0) || (b2f0_result == 5)) {
+		if (ipbfadr2)
+			*ipbfadr2 = parm.ipbfadr2;
+		if (ipbfln2f)
+			*ipbfln2f = parm.ipbfln2f;
+	}
+
+	pr_debug ("iucv_reply: exiting\n");
+
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_send_array                                      */
-/* Purpose: sends messages in buffer array                    */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong *, id of message returned to caller  */
-/*        trgcls - ulong, target message class                */
-/*        srccls - ulong, source message class                */
-/*        msgtag - ulong, message tag                         */
-/*        priority_msg - uchar, flag                          */
-/*        buffer - pointer to iucv_array_t                    */
-/*        buflen - ulong, length of buffer                    */
-/* Output: iprcode - return code from b2f0 call               */
-/*         msgid - returns message id                         */
-/**************************************************************/
-int
-iucv_send_array (ushort pathid, ulong * msgid,
-		 ulong trgcls, ulong srccls,
-		 ulong msgtag, uchar priority_msg,
-		 iucv_array_t * buffer, ulong buflen)
+/*
+ * Name: iucv_reply_array
+ * Purpose: This function responds to the two-way messages that you
+ *          receive. You must identify completely the message to   
+ *          which you wish to reply. ie, pathid, msgid, and trgcls.
+ *          The array identifies a list of addresses and lengths of
+ *          discontiguous buffers that contains the reply data.
+ * Input: pathid - path identification number
+ *        msgid - specifies the message ID. 
+ *        trgcls - specifies target class 
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        buffer - address of array of reply buffers
+ *        buflen - total length of reply buffers
+ * Output: ipbfadr2 - Address of buffer which IUCV is currently working on.
+ *         ipbfln2f - Contains on the the following values
+ *              If the answer buffer is the same length as the reply, this field
+ *               contains zero.
+ *              If the answer buffer is longer than the reply, this field contains
+ *               the number of bytes remaining in the buffer.
+ *              If the answer buffer is shorter than the reply, this field contains
+ *               a residual count (that is, the number of bytes remianing in the
+ *               reply that does not fit into the buffer. In this
+ *               case b2f0_result = 5.
+ * Return: b2f0_result - return code from CP
+ *             (-EINVAL) - buffer address is NULL
+*/
+int
+iucv_reply_array (u16 pathid,
+		  u32 msgid, u32 trgcls,
+		  int flags1,
+		  iucv_array_t * buffer,
+		  ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_send_array\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_reply_array: entering\n");
+
+	if (!buffer)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
+	parm.ipbfadr2 = (u32) ((ulong) buffer);
+	parm.ipbfln2f = buflen;	/* length of message */
 	parm.ippathid = pathid;
+	parm.ipmsgid = msgid;
 	parm.iptrgcls = trgcls;
-	parm.ipbfadr1 = (ulong) buffer;
-	parm.ipbfln1f = buflen;	/* length of message */
-	parm.ipsrccls = srccls;
-	parm.ipmsgtag = msgtag;
-	parm.ipflags1 |= one_way_msg;	/* one way message */
-	parm.ipflags1 |= array;	/* one way w/ array */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	b2f0_result = b2f0 (send, &parm);
-	if (msgid)
-		*msgid = parm.ipmsgid;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_send_array\n");
-#endif
+	parm.ipflags1 = (IPANSLST | flags1);
+
+	b2f0_result = b2f0 (REPLY, &parm);
+
+	if ((b2f0_result == 0) || (b2f0_result == 5)) {
+
+		if (ipbfadr2)
+			*ipbfadr2 = parm.ipbfadr2;
+		if (ipbfln2f)
+			*ipbfln2f = parm.ipbfln2f;
+	}
+
+	pr_debug ("iucv_reply_array: exiting\n");
+
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_send_prmmsg                                     */
-/* Purpose: sends messages in parameter list                  */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong *, id of message                     */
-/*        trgcls - ulong, target message class                */
-/*        srccls - ulong, source message class                */
-/*        msgtag - ulong, message tag                         */
-/*        priority_msg - uchar, flag                          */
-/*        prmmsg - uchar[8], message being sent               */
-/* Output: iprcode - return code from b2f0 call               */
-/*         msgid - returns message id                         */
-/**************************************************************/
-int
-iucv_send_prmmsg (ushort pathid, ulong * msgid,
-		  ulong trgcls, ulong srccls,
-		  ulong msgtag, uchar priority_msg, uchar prmmsg[8])
+/*
+ * Name: iucv_reply_prmmsg
+ * Purpose: This function responds to the two-way messages that you
+ *          receive. You must identify completely the message to
+ *          which you wish to reply. ie, pathid, msgid, and trgcls.
+ *          Prmmsg signifies the data is moved into the
+ *          parameter list.
+ * Input: pathid - path identification number
+ *        msgid - specifies the message ID. 
+ *        trgcls - specifies target class
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        prmmsg - 8-bytes of data to be placed into the parameter
+ *                 list.
+ * Output: NA
+ * Return: b2f0_result - return code from CP
+*/
+int
+iucv_reply_prmmsg (u16 pathid,
+		   u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8])
 {
 	iparml_dpl parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_send_prmmsg\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_reply_prmmsg: entering\n");
+
+	memset (&parm, 0, sizeof (parm));
 	parm.ippathid = pathid;
+	parm.ipmsgid = msgid;
 	parm.iptrgcls = trgcls;
-	parm.ipsrccls = srccls;
-	parm.ipmsgtag = msgtag;
-	parm.ipflags1 |= parm_data;	/* message in prmlist */
-	parm.ipflags1 |= one_way_msg;	/* one way message */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	memcpy (parm.iprmmsg, prmmsg, 8);
-	b2f0_result = b2f0 (send, &parm);
-	if (msgid)
-		*msgid = parm.ipmsgid;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_send_prmmsg\n");
-#endif
+	memcpy (parm.iprmmsg, prmmsg, sizeof (parm.iprmmsg));
+	parm.ipflags1 = (IPRMDATA | flags1);
+
+	b2f0_result = b2f0 (REPLY, &parm);
+
+	pr_debug ("iucv_reply_prmmsg: exiting\n");
+
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_send2way                                        */
-/* Purpose: sends messages in both directions                 */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong *, id of message                     */
-/*        trgcls - ulong, target message class                */
-/*        srccls - ulong, source message class                */
-/*        msgtag - ulong, message tag                         */
-/*        priority_msg - uchar, flag                          */
-/*        buffer - pointer to buffer                          */
-/*        buflen - ulong, length of buffer                    */
-/*        ansbuf - pointer to buffer on reply                 */
-/*        anslen - length of ansbuf buffer                    */
-/* Output: iprcode - return code from b2f0 call               */
-/*         msgid - returns message id                         */
-/**************************************************************/
-int
-iucv_send2way (ushort pathid, ulong * msgid,
-	       ulong trgcls, ulong srccls,
-	       ulong msgtag, uchar priority_msg,
-	       void *buffer, ulong buflen, void *ansbuf, ulong anslen)
+/*
+ * Name: iucv_resume                                          
+ * Purpose: This function restores communication over a quiesced path.       
+ * Input: pathid - u16, path identification number                             
+ *        user_data - uchar[16], 16-byte of user data                     
+ * Output: b2f0_result - return code from CP               
+ */
+int
+iucv_resume (u16 pathid, uchar user_data[16])
+{
+	iparml_control parm;
+	ulong b2f0_result = 0;
+
+	pr_debug ("iucv_resume: entering\n");
+	pr_debug ("iucv_resume: pathid = %d\n", pathid);
+
+	memset (&parm, 0, sizeof (parm));
+	memcpy (parm.ipuser, user_data, sizeof (*user_data));
+	parm.ippathid = pathid;
+
+	b2f0_result = b2f0 (RESUME, &parm);
+
+	pr_debug ("iucv_resume: exiting \n");
+
+	return b2f0_result;
+}
+
+/*
+ * Name: iucv_send                                             
+ * Purpose: sends messages                                    
+ * Input: pathid - ushort, pathid                            
+ *        msgid  - ulong *, id of message returned to caller   
+ *        trgcls - ulong, target message class              
+ *        srccls - ulong, source message class              
+ *        msgtag - ulong, message tag                    
+ *	  flags1  - Contains options for this path.
+ *		IPPRTY - Ox20 - specifies if you want to send a priority message.
+ *        buffer - pointer to buffer                           
+ *        buflen - ulong, length of buffer                     
+ * Output: b2f0_result - return code from b2f0 call               
+ *         msgid - returns message id                         
+ */
+int
+iucv_send (u16 pathid, u32 * msgid,
+	   u32 trgcls, u32 srccls,
+	   u32 msgtag, int flags1, void *buffer, ulong buflen)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_send2way\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_send: entering\n");
+
+	if (!buffer)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
+	parm.ipbfadr1 = (u32) ((ulong) buffer);
 	parm.ippathid = pathid;
 	parm.iptrgcls = trgcls;
-	parm.ipbfadr1 = (ulong) buffer;
-	parm.ipbfln1f = buflen;	/* length of message */
-	parm.ipbfadr2 = (ulong) ansbuf;
-	parm.ipbfln2f = anslen;
+	parm.ipbfln1f = (u32) buflen;	/* length of message */
 	parm.ipsrccls = srccls;
 	parm.ipmsgtag = msgtag;
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	b2f0_result = b2f0 (send, &parm);
-	if (msgid)
+	parm.ipflags1 = (IPNORPY | flags1);	/* one way priority message */
+
+	b2f0_result = b2f0 (SEND, &parm);
+
+	if ((b2f0_result == 0) && (msgid))
 		*msgid = parm.ipmsgid;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_send2way\n");
-#endif
+
+	pr_debug ("iucv_send: exiting\n");
+
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_send2way_array                                  */
-/* Purpose: sends messages in both directions in arrays       */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong *, id of message                     */
-/*        trgcls - ulong, target message class                */
-/*        srccls - ulong, source message class                */
-/*        msgtag - ulong, message tag                         */
-/*        priority_msg - uchar, flag                          */
-/*        buffer - pointer to iucv_array_t                    */
-/*        buflen - ulong, length of buffer                    */
-/*        ansbuf - pointer to iucv_array_t on reply           */
-/*        anslen - length of ansbuf buffer                    */
-/* Output: iprcode - return code from b2f0 call               */
-/*         msgid - returns message id                         */
-/**************************************************************/
-int
-iucv_send2way_array (ushort pathid, ulong * msgid,
-		     ulong trgcls, ulong srccls,
-		     ulong msgtag, uchar priority_msg,
-		     iucv_array_t * buffer, ulong buflen,
-		     iucv_array_t * ansbuf, ulong anslen)
+/*
+ * Name: iucv_send_array
+ * Purpose: This function transmits data to another application.
+ *          The contents of buffer is the address of the array of
+ *          addresses and lengths of discontiguous buffers that hold
+ *          the message text. This is a one-way message and the
+ *          receiver will not reply to the message.
+ * Input: pathid - path identification number
+ *        trgcls - specifies target class
+ *        srccls - specifies the source message class
+ *        msgtag - specifies a tag to be associated witht the message
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        buffer - address of array of send buffers
+ *        buflen - total length of send buffers
+ * Output: msgid - specifies the message ID.
+ * Return: b2f0_result - return code from CP 
+ *         (-EINVAL) - buffer address is NULL
+ */
+int
+iucv_send_array (u16 pathid,
+		 u32 * msgid,
+		 u32 trgcls,
+		 u32 srccls,
+		 u32 msgtag, int flags1, iucv_array_t * buffer, ulong buflen)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_send2way_array\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_send_array: entering\n");
+
+	if (!buffer)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
 	parm.ippathid = pathid;
 	parm.iptrgcls = trgcls;
-	parm.ipbfadr1 = (ulong) buffer;
-	parm.ipbfln1f = buflen;	/* length of message */
-	parm.ipbfadr2 = (ulong) ansbuf;
-	parm.ipbfln2f = anslen;
+	parm.ipbfadr1 = (u32) ((ulong) buffer);
+	parm.ipbfln1f = (u32) buflen;	/* length of message */
 	parm.ipsrccls = srccls;
 	parm.ipmsgtag = msgtag;
-	parm.ipflags1 |= array;	/* send  w/ array  */
-	parm.ipflags1 |= reply_array;	/* reply w/ array  */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	b2f0_result = b2f0 (send, &parm);
-	if (msgid)
+	parm.ipflags1 = (IPNORPY | IPBUFLST | flags1);
+	b2f0_result = b2f0 (SEND, &parm);
+
+	if ((b2f0_result == 0) && (msgid))
 		*msgid = parm.ipmsgid;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_send2way_array\n");
-#endif
+	pr_debug ("iucv_send_array: exiting\n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_send2way_prmmsg                                 */
-/* Purpose: sends messages in both directions w/parameter lst */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong *, id of message                     */
-/*        trgcls - ulong, target message class                */
-/*        srccls - ulong, source message class                */
-/*        msgtag - ulong, message tag                         */
-/*        priority_msg - uchar, flag                          */
-/*        prmmsg - uchar[8], message being sent in parameter  */
-/*        ansbuf - pointer to buffer                          */
-/*        anslen - length of ansbuf buffer                    */
-/* Output: iprcode - return code from b2f0 call               */
-/*         msgid - returns message id                         */
-/**************************************************************/
-int
-iucv_send2way_prmmsg (ushort pathid, ulong * msgid,
-		      ulong trgcls, ulong srccls,
-		      ulong msgtag, uchar priority_msg,
-		      uchar prmmsg[8], void *ansbuf, ulong anslen)
+/*
+ * Name: iucv_send_prmmsg
+ * Purpose: This function transmits data to another application. 
+ *          Prmmsg specifies that the 8-bytes of data are to be moved
+ *          into the parameter list. This is a one-way message and the
+ *          receiver will not reply to the message.
+ * Input: pathid - path identification number
+ *        trgcls - specifies target class
+ *        srccls - specifies the source message class
+ *        msgtag - specifies a tag to be associated with the message
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        prmmsg - 8-bytes of data to be placed into parameter list
+ * Output: msgid - specifies the message ID.   
+ * Return: b2f0_result - return code from CP
+*/
+int
+iucv_send_prmmsg (u16 pathid,
+		  u32 * msgid,
+		  u32 trgcls,
+		  u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8])
 {
 	iparml_dpl parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_send2way_prmmsg\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_send_prmmsg: entering\n");
+
+	memset (&parm, 0, sizeof (parm));
 	parm.ippathid = pathid;
 	parm.iptrgcls = trgcls;
 	parm.ipsrccls = srccls;
 	parm.ipmsgtag = msgtag;
-	parm.ipbfadr2 = (ulong) ansbuf;
-	parm.ipbfln2f = anslen;
-	parm.ipflags1 |= parm_data;	/* message in prmlist */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	memcpy (parm.iprmmsg, prmmsg, 8);
-	b2f0_result = b2f0 (send, &parm);
-	if (msgid)
+	parm.ipflags1 = (IPRMDATA | IPNORPY | flags1);
+	memcpy (parm.iprmmsg, prmmsg, sizeof (parm.iprmmsg));
+
+	b2f0_result = b2f0 (SEND, &parm);
+
+	if ((b2f0_result == 0) && (msgid))
 		*msgid = parm.ipmsgid;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_send2way_prmmsg\n");
-#endif
+
+	pr_debug ("iucv_send_prmmsg: exiting\n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_reply                                           */
-/* Purpose: responds to the two-way messages that you receive */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong, id of message                       */
-/*        trgcls - ulong, target message class                */
-/*        priority_msg - uchar, flag                          */
-/*        buf    - pointer, address of buffer                 */
-/*        buflen - length of buffer                           */
-/* Output: iprcode - return code from b2f0 call               */
-/**************************************************************/
+/*
+ * Name: iucv_send2way
+ * Purpose: This function transmits data to another application.
+ *          Data to be transmitted is in a buffer. The receiver
+ *          of the send is expected to reply to the message and
+ *          a buffer is provided into which IUCV moves the reply 
+ *          to this message.
+ * Input: pathid - path identification number
+ *        trgcls - specifies target class
+ *        srccls - specifies the source message class
+ *        msgtag - specifies a tag associated with the message
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        buffer - address of send buffer
+ *        buflen - length of send buffer
+ *        ansbuf - address of buffer to reply with
+ *        anslen - length of buffer to reply with
+ * Output: msgid - specifies the message ID.
+ * Return: b2f0_result - return code from CP
+ *         (-EINVAL) - buffer or ansbuf address is NULL
+ */
 int
-iucv_reply (ushort pathid, ulong msgid, ulong trgcls,
-	    uchar priority_msg, void *buf, ulong buflen)
+iucv_send2way (u16 pathid,
+	       u32 * msgid,
+	       u32 trgcls,
+	       u32 srccls,
+	       u32 msgtag,
+	       int flags1,
+	       void *buffer, ulong buflen, void *ansbuf, ulong anslen)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_reply\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+	pr_debug ("iucv_send2way: entering\n");
+
+	if (!buffer || !ansbuf)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
 	parm.ippathid = pathid;
-	parm.ipmsgid = msgid;
 	parm.iptrgcls = trgcls;
-	parm.ipbfadr2 = (ulong) buf;
-	parm.ipbfln2f = buflen;	/* length of message */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	b2f0_result = b2f0 (reply, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_reply\n");
-#endif
+	parm.ipbfadr1 = (u32) ((ulong) buffer);
+	parm.ipbfln1f = (u32) buflen;	/* length of message */
+	parm.ipbfadr2 = (u32) ((ulong) ansbuf);
+	parm.ipbfln2f = (u32) anslen;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipflags1 = flags1;	/* priority message */
+
+	b2f0_result = b2f0 (SEND, &parm);
+
+	if ((b2f0_result == 0) && (msgid))
+		*msgid = parm.ipmsgid;
+
+	pr_debug ("iucv_send2way: exiting\n");
+
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_reply_array                                     */
-/* Purpose: responds to the two-way messages that you receive */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong, id of message                       */
-/*        trgcls - ulong, target message class                */
-/*        priority_msg - uchar, flag                          */
-/*        buf    - pointer, address of array                  */
-/*        buflen - length of buffer                           */
-/* Output: iprcode - return code from b2f0 call               */
-/**************************************************************/
+/*
+ * Name: iucv_send2way_array
+ * Purpose: This function transmits data to another application.
+ *          The contents of buffer is the address of the array of
+ *          addresses and lengths of discontiguous buffers that hold
+ *          the message text. The receiver of the send is expected to
+ *          reply to the message and a buffer is provided into which
+ *          IUCV moves the reply to this message.
+ * Input: pathid - path identification number
+ *        trgcls - specifies target class
+ *        srccls - specifies the source message class
+ *        msgtag - spcifies a tag to be associated with the message
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        buffer - address of array of send buffers
+ *        buflen - total length of send buffers
+ *        ansbuf - address of buffer to reply with                       
+ *        anslen - length of buffer to reply with     
+ * Output: msgid - specifies the message ID.
+ * Return: b2f0_result - return code from CP
+ *         (-EINVAL) - buffer address is NULL
+ */
 int
-iucv_reply_array (ushort pathid, ulong msgid, ulong trgcls,
-		  uchar priority_msg, iucv_array_t * buffer, ulong buflen)
+iucv_send2way_array (u16 pathid,
+		     u32 * msgid,
+		     u32 trgcls,
+		     u32 srccls,
+		     u32 msgtag,
+		     int flags1,
+		     iucv_array_t * buffer,
+		     ulong buflen, iucv_array_t * ansbuf, ulong anslen)
 {
 	iparml_db parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_reply_array\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_send2way_array: entering\n");
+
+	if (!buffer || !ansbuf)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
 	parm.ippathid = pathid;
-	parm.ipmsgid = msgid;
 	parm.iptrgcls = trgcls;
-	parm.ipbfadr2 = (ulong) buffer;
-	parm.ipbfln2f = buflen;	/* length of message */
-	parm.ipflags1 |= reply_array;	/* reply w/ array  */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	b2f0_result = b2f0 (reply, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_reply_array\n");
-#endif
+	parm.ipbfadr1 = (u32) ((ulong) buffer);
+	parm.ipbfln1f = (u32) buflen;	/* length of message */
+	parm.ipbfadr2 = (u32) ((ulong) ansbuf);
+	parm.ipbfln2f = (u32) anslen;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipflags1 = (IPBUFLST | IPANSLST | flags1);
+	b2f0_result = b2f0 (SEND, &parm);
+	if ((b2f0_result == 0) && (msgid))
+		*msgid = parm.ipmsgid;
+	pr_debug ("iucv_send2way_array: exiting\n");
+	return b2f0_result;
+}
+
+/*
+ * Name: iucv_send2way_prmmsg
+ * Purpose: This function transmits data to another application.
+ *          Prmmsg specifies that the 8-bytes of data are to be moved
+ *          into the parameter list. This is a two-way message and the
+ *          receiver of the message is expected to reply. A buffer
+ *          is provided into which IUCV moves the reply to this
+ *          message.
+ * Input: pathid - path identification number  
+ *        trgcls - specifies target class
+ *        srccls - specifies the source message class
+ *        msgtag - specifies a tag to be associated with the message
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        prmmsg - 8-bytes of data to be placed in parameter list
+ *        ansbuf - address of buffer to reply with                       
+ *        anslen - length of buffer to reply with     
+ * Output: msgid - specifies the message ID.
+ * Return: b2f0_result - return code from CP
+ *         (-EINVAL) - buffer address is NULL
+*/
+int
+iucv_send2way_prmmsg (u16 pathid,
+		      u32 * msgid,
+		      u32 trgcls,
+		      u32 srccls,
+		      u32 msgtag,
+		      ulong flags1, uchar prmmsg[8], void *ansbuf, ulong anslen)
+{
+	iparml_dpl parm;
+	ulong b2f0_result;
+	pr_debug ("iucv_send2way_prmmsg: entering\n");
+
+	if (!ansbuf)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipbfadr2 = (u32) ((ulong) ansbuf);
+	parm.ipbfln2f = (u32) anslen;
+	parm.ipflags1 = (IPRMDATA | flags1);	/* message in prmlist */
+	memcpy (parm.iprmmsg, prmmsg, sizeof (parm.iprmmsg));
+
+	b2f0_result = b2f0 (SEND, &parm);
+
+	if ((b2f0_result == 0) && (msgid))
+		*msgid = parm.ipmsgid;
+
+	pr_debug ("iucv_send2way_prmmsg: exiting\n");
+
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_reply_prmmsg                                    */
-/* Purpose: responds to the two-way messages in parameter list */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong, id of message                       */
-/*        trgcls - ulong, target message class                */
-/*        priority_msg - uchar, flag                          */
-/*        prmmsg - uchar[8], message in parameter list        */
-/* Output: iprcode - return code from b2f0 call               */
-/**************************************************************/
+/*
+ * Name: iucv_send2way_prmmsg_array
+ * Purpose: This function transmits data to another application.
+ *          Prmmsg specifies that the 8-bytes of data are to be moved
+ *          into the parameter list. This is a two-way message and the
+ *          receiver of the message is expected to reply. A buffer
+ *          is provided into which IUCV moves the reply to this
+ *          message. The contents of ansbuf is the address of the
+ *          array of addresses and lengths of discontiguous buffers
+ *          that contain the reply.
+ * Input: pathid - path identification number
+ *        trgcls - specifies target class
+ *        srccls - specifies the source message class   
+ *        msgtag - specifies a tag to be associated with the message
+ *        flags1 - option for path
+ *                 IPPRTY- specifies if you want to send priority message
+ *        prmmsg - 8-bytes of data to be placed into the parameter list
+ *        ansbuf - address of buffer to reply with                       
+ *        anslen - length of buffer to reply with     
+ * Output: msgid - specifies the message ID.
+ * Return: b2f0_result - return code from CP
+ *         (-EINVAL) - ansbuf address is NULL
+ */
 int
-iucv_reply_prmmsg (ushort pathid, ulong msgid, ulong trgcls,
-		   uchar priority_msg, uchar prmmsg[8])
+iucv_send2way_prmmsg_array (u16 pathid,
+			    u32 * msgid,
+			    u32 trgcls,
+			    u32 srccls,
+			    u32 msgtag,
+			    int flags1,
+			    uchar prmmsg[8],
+			    iucv_array_t * ansbuf, ulong anslen)
 {
 	iparml_dpl parm;
 	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_reply_prmmsg\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+
+	pr_debug ("iucv_send2way_prmmsg_array: entering\n");
+
+	if (!ansbuf)
+		return -EINVAL;
+
+	memset (&parm, 0, sizeof (parm));
 	parm.ippathid = pathid;
-	parm.ipmsgid = msgid;
 	parm.iptrgcls = trgcls;
-	memcpy (parm.iprmmsg, prmmsg, 8);
-	parm.ipflags1 |= parm_data;
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	b2f0_result = b2f0 (reply, &parm);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_reply_prmmsg\n");
-#endif
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipbfadr2 = (u32) ((ulong) ansbuf);
+	parm.ipbfln2f = (u32) anslen;
+	parm.ipflags1 = (IPRMDATA | IPANSLST | flags1);
+	memcpy (parm.iprmmsg, prmmsg, sizeof (parm.iprmmsg));
+	b2f0_result = b2f0 (SEND, &parm);
+	if ((b2f0_result == 0) && (msgid))
+		*msgid = parm.ipmsgid;
+	pr_debug ("iucv_send2way_prmmsg_array: exiting\n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_connect                                         */
-/* Purpose: establishes an IUCV path to another vm            */
-/* Input: pathid - ushort *, pathid returned to user          */
-/*        msglim - ushort, limit of outstanding messages      */
-/*        user_data - uchar[16], user data                    */
-/*        userid - uchar[8], user's id                        */
-/*        system_name - uchar[8], system identification       */
-/*        priority_requested - uchar- flag                    */
-/*        prmdata - uchar, flag prgrm can handler messages    */
-/*                  in parameter list                         */
-/*        quiesce - uchar, flag to quiesce a path being establ */
-/*        control - uchar, flag, option not used              */
-/*        local   - uchar, flag, establish connection only on */
-/*                  local system                              */
-/*        priority_permitted - uchar *, flag returned to user */
-/*        handle - address of handler                         */
-/*        pgm_data - ulong                                    */
-/* Output: iprcode - return code from b2f0 call               */
-/**************************************************************/
-int
-iucv_connect (ushort * pathid, ushort msglim, uchar user_data[16],
-	      uchar userid[8], uchar system_name[8],
-	      uchar priority_requested, uchar prmdata,
-	      uchar quiesce, uchar control,
-	      uchar local, uchar * priority_permitted,
-	      iucv_handle_t handle, ulong pgm_data)
+/*
+ * Name: iucv_setmask
+ * Purpose: This function enables or disables the following IUCV   
+ *          external interruptions: Nonpriority and priority message
+ *          interrupts, nonpriority and priority reply interrupts.
+ * Input: SetMaskFlag - options for interrupts
+ *           0x80 - Nonpriority_MessagePendingInterruptsFlag
+ *           0x40 - Priority_MessagePendingInterruptsFlag
+ *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
+ *           0x10 - Priority_MessageCompletionInterruptsFlag
+ * Output: NA
+ * Return: b2f0_result - return code from CP
+*/
+int
+iucv_setmask (int SetMaskFlag)
 {
-	iparml_control parm;
-	ulong b2f0_result;
-	int add_pathid_result, rc;
-	handler *R;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_connect\n");
-#endif
+	iparml_set_mask parm;
+	ulong b2f0_result = 0;
+	pr_debug ("iucv_setmask: entering \n");
+
 	memset (&parm, 0, sizeof (parm));
-	if (declare_flag == NULL) {
-		rc = iucv_declare_buffer (iucv_external_int_buffer);
-		if (rc) {
-			printk (KERN_DEBUG "IUCV: registration failed\n");
-#ifdef DEBUG
-			printk (KERN_DEBUG "rc from declare buffer is: %i\n",
-				rc);
-#endif
-			return rc;
-		} else
-			declare_flag = 1;
-	}
-	/* Checking if handle is valid  */
-	spin_lock (&lock);
-	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
-		if (R == handle)
-			break;
-	if (R == NULL) {
-		spin_unlock (&lock);
-#ifdef DEBUG
-		printk (KERN_DEBUG "iucv_connect: Invalid Handle\n");
-#endif
-		return (-2);
-	}
-	if (pathid == NULL) {
-		spin_unlock (&lock);
-#ifdef DEBUG
-		printk (KERN_DEBUG "iucv_connect: invalid pathid pointer\n");
-#endif
-		return (-3);
-	}
-	spin_unlock (&lock);
-	parm.ipmsglim = msglim;
-	memcpy (parm.ipuser, user_data, 16);
-	memcpy (parm.ipvmid, userid, 8);
-	memcpy (parm.iptarget, system_name, 8);
-	if (parm.iptarget)
-		ASCEBC (parm.iptarget, 8);
-	if (parm.ipvmid) {
-		ASCEBC (parm.ipvmid, 8);
-		EBC_TOUPPER(parm.ipvmid, 8);
-	}
-	if (priority_requested)
-		parm.ipflags1 |= prior_msg;
-	if (prmdata)
-		parm.ipflags1 |= parm_data;	/*data in parameter list */
-	if (quiesce)
-		parm.ipflags1 |= quiesce_msg;
-	if (control) {
-		/* do nothing at the time being  */
-		/*control not provided yet */
-	}
-	if (local)
-		parm.ipflags1 |= local_conn;	/*connect on local system */
-	b2f0_result = b2f0 (connect, &parm);
-	if (b2f0_result)
-		return b2f0_result;
-	add_pathid_result = add_pathid (parm.ippathid, handle, pgm_data);
-	if (add_pathid_result) {
-#ifdef DEBUG
-		printk (KERN_DEBUG "iucv_connect: add_pathid failed \n");
-#endif
-		return (add_pathid_result);
-	}
-	*pathid = parm.ippathid;
-	if (parm.ipflags1 & prior_msg)
-		if (priority_permitted)
-			*priority_permitted = 0x01;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_connect\n");
-#endif
+	parm.ipmask = (uchar) SetMaskFlag;
+
+	b2f0_result = b2f0 (SETMASK, &parm);
+
+	pr_debug ("iucv_setmask: b2f0_result = %ld\n", b2f0_result);
+	pr_debug ("iucv_setmask: exiting\n");
+
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_accept                                          */
-/* Purpose: completes the iucv communication path             */
-/* Input: pathid - ushort , pathid                            */
-/*        msglim - ushort, limit of outstanding messages      */
-/*        user_data - uchar[16], user data                    */
-/*        priority_requested - uchar- flag                    */
-/*        prmdata - uchar, flag prgrm can handler messages    */
-/*                  in parameter list                         */
-/*        quiesce - uchar, flag to quiesce a path being establ*/
-/*        control - uchar, flag, option not used              */
-/*        priority_permitted -uchar *, flag returned to caller*/
-/*        handle - address of handler                         */
-/*        pgm_data - ulong                                    */
-/* Output: iprcode - return code from b2f0 call               */
-/**************************************************************/
-int
-iucv_accept (ushort pathid, ushort msglim, uchar user_data[16],
-	     uchar priority_requested,
-	     uchar prmdata, uchar quiesce, uchar control,
-	     uchar * priority_permitted, iucv_handle_t handle, ulong pgm_data)
+/*
+ * Name: iucv_sever                                           
+ * Purpose: This function terminates an iucv path         
+ * Input: pathid - u16, path identification number                             
+ *        user_data - uchar[16], 16-byte of user data                     
+ * Output: b2f0_result - return code from CP          
+ *         -EINVAL - NULL address found for handler                                 
+ */
+int
+iucv_sever (u16 pathid, uchar user_data[16])
 {
-	ulong index1, index2;
-	handler_table_entry *P = 0;
 	iparml_control parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_accept\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
+	ulong b2f0_result = 0;
+	pr_debug ("iucv_sever: entering\n");
+	memset (&parm, 0, sizeof (parm));
+	memcpy (parm.ipuser, user_data, sizeof (parm.ipuser));
 	parm.ippathid = pathid;
-	parm.ipmsglim = msglim;
-	memcpy (parm.ipuser, user_data, 16);
-	if (priority_requested)
-		parm.ipflags1 |= prior_msg;
-	if (prmdata)
-		parm.ipflags1 |= parm_data;	/*data in parameter list */
-	if (quiesce)
-		parm.ipflags1 |= quiesce_msg;
-	if (control) {
-		/* do nothing at the time being  */
-		/*control not provided yet */
-	}
-	b2f0_result = b2f0 (accept, &parm);
-	if (b2f0_result)
-		return b2f0_result;
-	index1 = ((ulong) pathid) / 512;
-	index2 = ((ulong) pathid) % 512;
-	spin_lock (&lock);
-	if (pgm_data) {
-		P = main_table[index1];
-		(P + index2)->pgm_data = pgm_data;
-	}
-	spin_unlock (&lock);
-	if (parm.ipflags1 & prior_msg)
-		if (priority_permitted)
-			*priority_permitted = 0x01;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_accept\n");
-#endif
+
+	b2f0_result = b2f0 (SEVER, &parm);
+
+	if (!b2f0_result)
+		iucv_remove_pathid (pathid);
+
+	pr_debug ("iucv_sever: exiting \n");
 	return b2f0_result;
 }
 
-/**************************************************************/
-/* Name: iucv_send2way_prmmsg_array                           */
-/* Purpose: sends messages in both directions w/parameter lst */
-/* Input: pathid - ushort, pathid                             */
-/*        msgid  - ulong *, id of message returned to caller  */
-/*        trgcls - ulong, target message class                */
-/*        srccls - ulong, source message class                */
-/*        msgtag - ulong, message tag                         */
-/*        priority_msg - uchar, flag                          */
-/*        prmmsg - uchar[8], message being sent in parameter  */
-/*        ansbuf - pointer to array of buffers                */
-/*        anslen - length of ansbuf buffer                    */
-/* Output: iprcode - return code from b2f0 call               */
-/*         msgid - returns message id                         */
-/**************************************************************/
-int
-iucv_send2way_prmmsg_array (ushort pathid, ulong * msgid,
-			    ulong trgcls, ulong srccls,
-			    ulong msgtag, uchar priority_msg,
-			    uchar prmmsg[8],
-			    iucv_array_t * ansbuf, ulong anslen)
+static void
+iucv_remove_pathid (u16 pathid)
 {
-	iparml_dpl parm;
-	ulong b2f0_result;
-#ifdef DEBUG
-	printk (KERN_DEBUG "entering iucv_send2way_prmmsg\n");
-#endif
-	memset (&(parm), 0, sizeof (parm));
-	parm.ippathid = pathid;
-	parm.iptrgcls = trgcls;
-	parm.ipsrccls = srccls;
-	parm.ipmsgtag = msgtag;
-	parm.ipbfadr2 = (ulong) ansbuf;
-	parm.ipbfln2f = anslen;
-	parm.ipflags1 |= 0x88;	/* message in prmlist */
-	if (priority_msg)
-		parm.ipflags1 |= prior_msg;	/* priority message */
-	memcpy (parm.iprmmsg, prmmsg, 8);
-	b2f0_result = b2f0 (send, &parm);
-	if (msgid)
-		*msgid = parm.ipmsgid;
-#ifdef DEBUG
-	printk (KERN_DEBUG "exiting iucv_send2way_prmmsg\n");
-#endif
-	return b2f0_result;
+	handler_table_entry *users_hte = NULL;	/*users handler_table_entry */
+	handler *users_handler = NULL;
+	ulong *users_pathid = NULL;
+	ulong flags;
+	spin_lock_irqsave (&iucv_lock, flags);
+	users_hte = handler_table_anchor + (int) pathid;
+
+	if ((users_hte->addrs) == NULL) {
+		spin_unlock_irqrestore (&iucv_lock, flags);
+		return;		/* wild pointer has been found */
+	}
+
+	users_handler = users_hte->addrs;
+
+	pr_debug ("iucv_sever: pathid is %d\n", pathid);
+	pr_debug ("iucv_sever: H_T_E is %p\n", users_hte);
+	pr_debug ("iucv_sever: address of handler is %p\n", users_handler);
+	pr_debug ("iucv_sever: below is pathid table\n");
+	iucv_dumpit ((uchar *) users_handler->pathid_head,
+		     (int) users_handler->entries * sizeof (ulong));
+
+/*
+ * Searching the pathid address table for matching address, once    
+ * found, NULL the handler_table_entry field and then zero the H_T_E fields.               
+ */
+
+	for (users_pathid = (users_handler->pathid_head);
+	     users_pathid < (users_handler->pathid_tail); users_pathid++)
+
+		if (*users_pathid == (ulong) users_hte) {
+			pr_debug ("iucv_sever: found a path to remove from"
+				  "table\n");
+			pr_debug ("iucv_sever: removing %d \n",
+				  (int) (*users_pathid)); *users_pathid = NULL;
+
+			memset (users_hte, 0, sizeof (handler_table_entry));
+		}
+	spin_unlock_irqrestore (&iucv_lock, flags);
+	return;
 }
 
-/******************************************************************/
-/* Name: top_half_handler                                         */
-/* Purpose: handle minimum amount of interrupt in fastest time    */
-/*  possible and then pass interrupt to bottom half handler.      */
-/* Input: external interrupt buffer                               */
-/* Output: void                                                   */
-/******************************************************************/
+/*
+ * Interrupt Handling Functions
+ * 	top_half_interrupt
+ * 	bottom_half_interrupt
+ * 	do_int
+ */
+
+/*
+ * Name: top_half_interrupt                                         
+ * Purpose: Handles interrupts coming in from CP.  Places the interrupt on a queue and  
+ * 	    calls bottom_half_interrupt          
+ * Input: external interrupt buffer                                
+ * Output: void                                                    
+ */
 
 inline void
 top_half_interrupt (struct pt_regs *regs, __u16 code)
 {
 	iucv_packet *pkt;
-	pkt = (iucv_packet *) kmalloc
-	    (sizeof (iucv_packet), GFP_ATOMIC);
+	int cpu = smp_processor_id();
+
+	irq_enter(cpu, 0x4000);
+
+	pkt = (iucv_packet *) kmalloc (sizeof (iucv_packet), GFP_ATOMIC);
 	if (pkt == NULL) {
-		printk (KERN_DEBUG "out of memory\n");
+		printk (KERN_WARNING
+			"iucv:top_half_interrupt: out of memory\n");
+		irq_exit(cpu, 0x4000);
 		return;
 	}
-	memcpy (pkt->data, iucv_external_int_buffer, 40);
-#ifdef DEBUG3
-printk (KERN_EMERG "TH: Got INT: %08x\n", *(int *)(pkt->data+4));
-#endif
+
+	memcpy (pkt->data, iucv_external_int_buffer, BUFFER_SIZE);
+
+	pr_debug ("TH: Got INT: %08x\n", *(int *) (pkt->data + 4));
+
 	/* put new packet on the list */
 	spin_lock (&iucv_packets_lock);
 	pkt->next = NULL;
+
 	if (iucv_packets_tail != NULL)
 		iucv_packets_tail->next = pkt;
 	else
 		iucv_packets_head = pkt;
+
 	iucv_packets_tail = pkt;
 	spin_unlock (&iucv_packets_lock);
 
 	if (atomic_compare_and_swap (0, 1, &bh_scheduled) == 0) {
-#ifdef DEBUG3
-printk (KERN_EMERG "TH: Queuing BH\n");
-#endif
-		INIT_LIST_HEAD(&short_task.list);
-		short_task.sync = 0;
 		short_task.routine = (void *) bottom_half_interrupt;
 		queue_task (&short_task, &tq_immediate);
 		mark_bh (IMMEDIATE_BH);
 	}
+	irq_exit(cpu, 0x4000);
 	return;
 }
 
-/*******************************************************************/
-/* Name: bottom_half_interrupt                                     */
-/* Purpose: Handle interrupt at a more safer time                  */
-/* Input: void                                                     */
-/* Output: void                                                    */
-/*******************************************************************/
+/*
+ * Name: bottom_half_interrupt                                      
+ * Purpose: Handle interrupt at a more safer time                  
+ * Input: void                                                     
+ * Output: void                                                    
+ */
 void
 bottom_half_interrupt (void)
 {
 	iucv_packet *iucv_packet_list;
 	iucv_packet *tmp;
 	ulong flags;
-
 	atomic_set (&bh_scheduled, 0);
+
 	spin_lock_irqsave (&iucv_packets_lock, flags);
 	iucv_packet_list = iucv_packets_head;
 	iucv_packets_head = iucv_packets_tail = NULL;
 	spin_unlock_irqrestore (&iucv_packets_lock, flags);
 
 	/* now process all the request in the iucv_packet_list */
-#ifdef DEBUG3
-	printk (KERN_EMERG "BH: Process all packets\n");
-#endif
+	pr_debug ("BH: Process all packets\n");
 	while (iucv_packet_list != NULL) {
-#ifdef DEBUG3
-		printk( KERN_EMERG "BH:>  %08x\n", 
-			*(int *)(iucv_packet_list->data+4));
-#endif
-		do_int ((iucv_ConnectionPending *) iucv_packet_list->data);
-#ifdef DEBUG3
-		printk( KERN_EMERG "BH:<  %08x\n",
-			*(int *)(iucv_packet_list->data+4));
-#endif
+		pr_debug ("BH:>  %08x\n",
+			  *(int *) (iucv_packet_list->data + 4));
+
+		do_int ((iucv_GeneralInterrupt *) iucv_packet_list->data);
+
+		pr_debug ("BH:<  %08x\n",
+			  *(int *) (iucv_packet_list->data + 4));
 		tmp = iucv_packet_list;
 		iucv_packet_list = iucv_packet_list->next;
 		kfree (tmp);
 	}
-#ifdef DEBUG3
-	printk (KERN_EMERG "BH: Done\n");
-#endif
+	pr_debug ("BH: Done\n");
 	return;
 }
-/*******************************************************************/
-/* Name: do_int                                                    */
-/* Purpose: Handle interrupt in a more safe environment            */
-/* Inuput: int_buf - pointer to copy of external interrupt buffer  */
-/* Output: void                                                    */
-/*******************************************************************/
+
+/*
+ * Name: do_int                                                     
+ * Purpose: Handles the interrupts in a more safe environment             
+ * Input: int_buf - pointer to copy of external interrupt buffer  
+ * Output: void                                                     
+ */
 void
-do_int (iucv_ConnectionPending * int_buf)
+do_int (iucv_GeneralInterrupt * int_buf)
 {
-	ulong index1 = 0, index2 = 0;
-	handler_table_entry *P = 0;	/* P is a pointer */
-	handler *Q = 0, *R;	/* Q and R are pointers */
+	handler_table_entry *P = 0;
+	ulong flags;
+	handler *Q = 0, *R;
 	iucv_interrupt_ops_t *interrupt = 0;	/* interrupt addresses */
 	uchar temp_buff1[24], temp_buff2[24];	/* masked handler id. */
 	int add_pathid_result = 0, j = 0;
 	uchar no_listener[16] = "NO LISTENER";
-#ifdef DEBUG
-	int i;
-	uchar *prt_parm;
-#endif
-#ifdef DEBUG3
-	printk (KERN_DEBUG "BH:-  Entered do_int "
-	                   "pathid %d, type %02X\n",
-		int_buf->ippathid, int_buf->iptype);
-#endif
-#ifdef DEBUG
-	prt_parm = (uchar *) (int_buf);
-	printk (KERN_DEBUG "External Interrupt Buffer\n");
-	for (i = 0; i < 40; i++)
-		printk (KERN_DEBUG "%02x ", prt_parm[i]);
-	printk (KERN_DEBUG "\n");
-#endif
+
+	pr_debug ("IUCV: BHI: -  Entered do_int "
+		  "pathid %d, type %02X\n", int_buf->ippathid, int_buf->iptype);
+	pr_debug ("BHI:External Interrupt Buffer\n");
+	iucv_dumpit ((uchar *) int_buf, sizeof (iucv_GeneralInterrupt));
+
 	ASCEBC (no_listener, 16);
 	if (int_buf->iptype != 01) {
-		index1 = ((ulong) (int_buf->ippathid)) / 512;
-		index2 = ((ulong) (int_buf->ippathid)) % 512;
-		spin_lock (&lock);
-
-		P = main_table[index1];
-		Q = (P + index2)->addrs;
-		interrupt = Q->interrupt_table;	/* interrupt functions */
-		spin_unlock (&lock);
-#ifdef DEBUG
-		printk (KERN_DEBUG "Handler is: \n");
-		prt_parm = (uchar *) Q;
-		for (i = 0; i < sizeof (handler); i++)
-			printk (KERN_DEBUG " %02x ", prt_parm[i]);
-		printk (KERN_DEBUG "\n");
-#endif
-	}			/* end of if statement */
+		spin_lock_irqsave (&iucv_lock, flags);
+		P = handler_table_anchor + int_buf->ippathid;
+		Q = P->addrs;
+		interrupt = P->ops;	/* interrupt functions */
+
+		pr_debug ("iucv: do_int: Handler\n");
+		iucv_dumpit ((uchar *) Q, sizeof (handler));
+		spin_unlock_irqrestore (&iucv_lock, flags);
+	}
+	/* end of if statement */
 	switch (int_buf->iptype) {
 	case 0x01:		/* connection pending */
-		spin_lock (&lock);
+		spin_lock_irqsave (&iucv_lock, flags);
 		for (R = handler_anchor; R != NULL; R = (handler *) R->next) {
 			memcpy (temp_buff1, &(int_buf->ipvmid), 24);
-			memcpy (temp_buff2, &(R->vmid), 24);
+			memcpy (temp_buff2, &(R->id.userid), 24);
 			for (j = 0; j < 24; j++) {
-				temp_buff1[j] = (temp_buff1[j]) & (R->mask)[j];
-				temp_buff2[j] = (temp_buff2[j]) & (R->mask)[j];
+				temp_buff1[j] =
+				    (temp_buff1[j]) & (R->id.mask)[j];
+				temp_buff2[j] =
+				    (temp_buff2[j]) & (R->id.mask)[j];
 			}
-#ifdef DEBUG
-			for (i = 0; i < sizeof (temp_buff1); i++)
-				printk (KERN_DEBUG " %c ", temp_buff1[i]);
-			printk (KERN_DEBUG "\n");
-			for (i = 0; i < sizeof (temp_buff2); i++)
-				printk (KERN_DEBUG " %c ", temp_buff2[i]);
-			printk (KERN_DEBUG "\n");
-#endif
-			if (memcmp((void *) temp_buff1,
-				   (void *) temp_buff2, 24) == 0) {
-#ifdef DEBUG
-				printk (KERN_DEBUG
-					"found a matching handler\n");
-#endif
+
+			pr_debug ("iucv:do_int: temp_buff1\n");
+			iucv_dumpit (temp_buff1, sizeof (temp_buff1));
+			pr_debug ("iucv:do_int: temp_buff2\n");
+			iucv_dumpit (temp_buff2, sizeof (temp_buff2));
+
+			if (memcmp ((void *) temp_buff1,
+				    (void *) temp_buff2, 24) == 0) {
+
+				pr_debug
+				    ("iucv:do_int: found a matching handler\n");
 				break;
 			}
 		}
-		spin_unlock (&lock);
+		spin_unlock_irqrestore (&iucv_lock, flags);
+
 		if (R) {
 			/* ADD PATH TO PATHID TABLE */
-			add_pathid_result =
-			    add_pathid (int_buf->ippathid, R, R->pgm_data);
+			add_pathid_result = iucv_add_pathid (int_buf->ippathid,
+							     R, R->pgm_data);
 			if (add_pathid_result == NULL) {
 				interrupt = R->interrupt_table;
-				if ((*interrupt).ConnectionPending) {
+				if (interrupt->ConnectionPending) {
+
 					EBCASC (int_buf->ipvmid, 8);
-					
-					    ((*interrupt).
-					 ConnectionPending) (int_buf,
-							     R->pgm_data);
+
+					(interrupt->ConnectionPending)
+					    ((iucv_ConnectionPending *) int_buf,
+					     (R->pgm_data));
 				} else {
 					iucv_sever (int_buf->ippathid,
 						    no_listener);
 				}
-			} /* end if if(add_p...... */
+			} /* end of if(add_p...... */
 			else {
 				iucv_sever (int_buf->ippathid, no_listener);
-#ifdef DEBUG
-				printk (KERN_DEBUG
-					"add_pathid failed with rc = %d\n",
-					(int) add_pathid_result);
-#endif
+				pr_debug ("iucv:do_int:add_pathid failed"
+					  "with rc = %d\n",
+					  (int) add_pathid_result);
 			}
 		} else
 			iucv_sever (int_buf->ippathid, no_listener);
 		break;
+
 	case 0x02:		/*connection complete */
 		if (Q) {
-			if ((*interrupt).ConnectionComplete)
-				((*interrupt).ConnectionComplete)
-				    
-				    ((iucv_ConnectionComplete *) int_buf,
-				     (P + index2)->pgm_data);
-			else {
-#ifdef DEBUG
-				printk (KERN_DEBUG
-					"ConnectionComplete not called\n");
-				printk (KERN_DEBUG "routine@ is %p\n",
-					(*interrupt).ConnectionComplete);
-#endif
-			}
+			if (interrupt->ConnectionComplete)
+				(interrupt->ConnectionComplete)
+				    ((iucv_ConnectionComplete *) int_buf, (P->pgm_data));
+			else
+				pr_debug ("iucv:do_int:"
+					  "ConnectionComplete not called\n");
 		}
+		
 		break;
+
 	case 0x03:		/* connection severed */
 		if (Q) {
-			if ((*interrupt).ConnectionSevered)
-				((*interrupt).ConnectionSevered)
-				    
+			if (interrupt->ConnectionSevered)
+				(interrupt->ConnectionSevered)
 				    ((iucv_ConnectionSevered *) int_buf,
-				     (P + index2)->pgm_data);
+				     (P->pgm_data));
+
 			else
 				iucv_sever (int_buf->ippathid, no_listener);
 		} else
 			iucv_sever (int_buf->ippathid, no_listener);
 		break;
+
 	case 0x04:		/* connection quiesced */
 		if (Q) {
-			if ((*interrupt).ConnectionQuiesced)
-				((*interrupt).ConnectionQuiesced)
-				    
+			if (interrupt->ConnectionQuiesced)
+				(interrupt->ConnectionQuiesced)
 				    ((iucv_ConnectionQuiesced *) int_buf,
-				     (P + index2)->pgm_data);
-			else {
-#ifdef DEBUG
-				printk (KERN_DEBUG
-					"ConnectionQuiesced not called\n");
-				printk (KERN_DEBUG "routine@ is %p\n",
-					(*interrupt).ConnectionQuiesced);
-#endif
-			}
+				     (P->pgm_data));
+			else
+				pr_debug ("iucv:do_int:"
+					  "ConnectionQuiesced not called\n");
 		}
 		break;
+
 	case 0x05:		/* connection resumed */
 		if (Q) {
-			if ((*interrupt).ConnectionResumed)
-				((*interrupt).ConnectionResumed)
-				    
-				    ((iucv_ConnectionResumed *) int_buf,
-				     (P + index2)->pgm_data);
-			else {
-#ifdef DEBUG
-				printk (KERN_DEBUG
-					"ConnectionResumed not called\n");
-				printk (KERN_DEBUG "routine@ is %p\n",
-					(*interrupt).ConnectionResumed);
-#endif
-			}
+			if (interrupt->ConnectionResumed)
+				(interrupt->ConnectionResumed)
+				    ((iucv_ConnectionResumed *) int_buf, (P->pgm_data));
+			else
+				pr_debug ("iucv:do_int:"
+					  "ConnectionResumed not called\n");
 		}
 		break;
+
 	case 0x06:		/* priority message complete */
 	case 0x07:		/* nonpriority message complete */
 		if (Q) {
-			if ((*interrupt).MessageComplete)
-				((*interrupt).MessageComplete)
-				    
-				    ((iucv_MessageComplete *) int_buf,
-				     (P + index2)->pgm_data);
-			else {
-#ifdef DEBUG
-				printk (KERN_DEBUG
-					"MessageComplete not called\n");
-				printk (KERN_DEBUG "routine@ is %p\n",
-					(*interrupt).MessageComplete);
-#endif
-			}
+			if (interrupt->MessageComplete)
+				(interrupt->MessageComplete)
+				    ((iucv_MessageComplete *) int_buf, (P->pgm_data));
+			else
+				pr_debug ("iucv:do_int:"
+					  "MessageComplete not called\n");
 		}
 		break;
+
 	case 0x08:		/* priority message pending  */
 	case 0x09:		/* nonpriority message pending  */
 		if (Q) {
-			if ((*interrupt).MessagePending)
-				((*interrupt).MessagePending)
-				    
-				    ((iucv_MessagePending *) int_buf,
-				     (P + index2)->pgm_data);
-			else {
-#ifdef DEBUG
-				printk (KERN_DEBUG
-					"MessagePending not called\n");
-				printk (KERN_DEBUG "routine@ is %p\n",
-					(*interrupt).MessagePending);
-#endif
-			}
+			if (interrupt->MessagePending)
+				(interrupt->MessagePending)
+				    ((iucv_MessagePending *) int_buf, (P->pgm_data));
+			else
+				pr_debug ("iucv:do_int:"
+					  "MessagePending not called\n");
 		}
 		break;
 	default:		/* unknown iucv type */
-		printk (KERN_DEBUG "unknown iucv interrupt \n");
+		printk (KERN_WARNING "iucv:do_int: unknown iucv interrupt \n");
 		break;
 	}			/* end switch */
-#ifdef DEBUG3
-	printk (KERN_DEBUG "BH:-  Exiting do_int "
-	                   "pathid %d, type %02X\n",
-		int_buf->ippathid, int_buf->iptype);
-#endif
-	return;
-}				/* end of function call */
 
-/**************************************************************/
-/* Name: iucv_register_program                                */
-/* Purpose: registers a new handler                           */
-/* Input: pgmname- uchar[16], user id                         */
-/*        userid - uchar[8], machine id                       */
-/*        prmmask- mask                                       */
-/*        ops    - pointer to iucv_interrupt_ops buffer       */
-/* Output: new_handler - address of new handler               */
-/**************************************************************/
-iucv_handle_t
-iucv_register_program (uchar pgmname[16],
-		       uchar userid[8],
-		       uchar pgmmask[24],
-		       iucv_interrupt_ops_t * ops, ulong pgm_data)
-{
-	int rc;
-	handler *new_handler = 0;
-#ifdef DEBUG
-	int i;
-	uchar *prt_parm;
-	printk (KERN_DEBUG "enter iucv_register_program\n");
-#endif
-	my_ops = *ops;
-	/* Allocate handler table */
-	new_handler = (handler *) kmalloc (sizeof (handler), GFP_KERNEL);
-	if (new_handler == NULL) {
-#ifdef DEBUG
-		printk (KERN_DEBUG
-			"IUCV: returned NULL address for new handle \n");
-#endif
-		return NULL;
-	}
-	/* fill in handler table */
-	memcpy (new_handler->user_data, pgmname, 16);
-	memcpy (new_handler->vmid, userid, 8);
-	memcpy (new_handler->mask, pgmmask, 24);
-	new_handler->pgm_data = pgm_data;
-	/* Convert from ASCII to EBCDIC */
-	if (new_handler->vmid) {
-		ASCEBC (new_handler->vmid, 8);
-		EBC_TOUPPER(new_handler->vmid, 8);
-	}
-	/* fill in handler table */
-	new_handler->interrupt_table = ops;
-	new_handler->size = ADDED_STOR;
-	/* Allocate storage for pathid table */
-	new_handler->start = kmalloc (ADDED_STOR * sizeof (ulong), GFP_KERNEL);
-	if (new_handler->start == NULL) {
-#ifdef DEBUG
-		printk (KERN_DEBUG
-			"IUCV: returned NULL address for pathid table,"
-			" exiting\n");
-#endif
-		kfree(new_handler);
-		return NULL;
-	}
-	memset (new_handler->start, 0, ADDED_STOR * sizeof (ulong));
-	new_handler->end = (*new_handler).start + ADDED_STOR;
-	new_handler->next = 0;
-	new_handler->prev = 0;
-	/* Place handler at beginning of chain */
-	spin_lock (&lock);
-	if (handler_anchor == NULL)
-		handler_anchor = new_handler;
-	else {
-		handler_anchor->prev = (ulong *) new_handler;
-		new_handler->next = (ulong *) handler_anchor;
-		handler_anchor = new_handler;
-#ifdef DEBUG
-		printk (KERN_DEBUG "adding a another handler to list\n");
-		printk (KERN_DEBUG "handler_anchor->prev is %p \n",
-			handler_anchor->prev);
-		printk (KERN_DEBUG "new_handler->next is %p \n",
-			new_handler->next);
-		printk (KERN_DEBUG "handler_anchor is %p \n", handler_anchor);
-#endif
-	}
-	spin_unlock (&lock);
-	if (declare_flag == NULL) {
-		rc = iucv_declare_buffer (iucv_external_int_buffer);
-		if (rc == 0) {
-			declare_flag = 1;
-			/* request the 0x4000 external interrupt */
-			rc =
-			    register_external_interrupt (0x4000,
-							 top_half_interrupt);
-		} else {
-			panic ("Registration failed");
-#ifdef DEBUG
-			printk (KERN_DEBUG "rc from declare buffer is: %i\n",
-				rc);
-#endif
-		}
-	}
-#ifdef DEBUG
-	printk (KERN_DEBUG "address of handle is %p ", new_handler);
-	printk (KERN_DEBUG "size of handle is %d ", (int) (sizeof (handler)));
-	printk (KERN_DEBUG "exit iucv_register_program\n");
-	printk (KERN_DEBUG "main_table is %p \n", main_table);
-	printk (KERN_DEBUG "handler_anchor is %p \n", handler_anchor);
-	printk (KERN_DEBUG "Handler is: \n");
-	prt_parm = (uchar *) new_handler;
-	for (i = 0; i < sizeof (handler); i++)
-		printk (KERN_DEBUG " %02x ", prt_parm[i]);
-	printk (KERN_DEBUG "\n");
-#endif
-	return new_handler;	/* send buffer address back */
-}				/* end of register function */
+	pr_debug ("BH:-  Exiting do_int "
+		  "pathid %d, type %02X\n", int_buf->ippathid, int_buf->iptype);
 
-/**************************************************************/
-/* Name: iucv_unregister                                      */
-/* Purpose: remove handler from chain and sever all paths     */
-/* Input: handle - address of handler to be severed           */
-/* Output: returns 0                                          */
-/**************************************************************/
-int
-iucv_unregister (iucv_handle_t handle)
-{
-	handler *temp_next = 0, *temp_prev = 0;
-	handler *Q = 0, *R;
-	handler_table_entry *H_T_E = 0;
-	ulong *S = 0;		/*points to the beginning of block of h_t_e's*/
-#ifdef DEBUG
-	printk (KERN_DEBUG "enter iucv_unregister\n");
-	printk (KERN_DEBUG "address of handle is %p ", handle);
-	printk (KERN_DEBUG "size of handle is %u ", (int) (sizeof (handle)));
-#endif
-	spin_lock (&lock);
-	Q = (handler *) handle;
-	/*
-	 * Checking if handle is still registered: if yes, continue
-	 *  if not registered, return.
-	 */
-	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
-		if (Q == R) {
-#ifdef DEBUG
-			printk (KERN_DEBUG "found a matching handler\n");
-#endif
-			break;
-		}
-	if (!R) {
-		spin_unlock (&lock);
-		return (0);
-	}
-	S = Q->start;
-#ifdef DEBUG
-	printk (KERN_DEBUG "Q is handle? %p ", Q);
-	printk (KERN_DEBUG "Q->start is %p ", Q->start);
-	printk (KERN_DEBUG "&(Q->start) is %p ", &(Q->start));
-	printk (KERN_DEBUG "Q->end is %p ", Q->end);
-	printk (KERN_DEBUG "&(Q->end) is %p ", &(Q->end));
-#endif
-	while (S < (Q->end)) {	/* index thru table */
-		if (*S) {
-			H_T_E = (handler_table_entry *) (*S);
-#ifdef DEBUG
-			printk (KERN_DEBUG "Pointer to H_T_E is %p ", H_T_E);
-			printk (KERN_DEBUG "Address of handle in H_T_E is %p",
-				(H_T_E->addrs));
-#endif
-			if ((H_T_E->addrs) != handle) {
-				spin_unlock (&lock);
-				return (-2);	/*handler addresses don't match */
-			} else {
-				spin_unlock (&lock);
-				iucv_sever (H_T_E->pathid, Q->user_data);
-				spin_lock (&lock);
-			}
-		}
-		S++;		/* index by size of ulong */
-	}
-	kfree (Q->start);
-	temp_next = (handler *) Q->next;	/* address of next handler on list */
-	temp_prev = (handler *) Q->prev;	/* address of prev handler on list */
-	if ((temp_next != NULL) & (temp_prev != NULL)) {
-		(*temp_next).prev = (ulong *) temp_prev;
-		(*temp_prev).next = (ulong *) temp_next;
-	} else if ((temp_next != NULL) & (temp_prev == NULL)) {
-		(*temp_next).prev = NULL;
-		handler_anchor = temp_next;
-	} else if ((temp_next == NULL) & (temp_prev != NULL))
-		(*temp_prev).next = NULL;
-	else
-		handler_anchor = NULL;
-	if (handler_anchor == NULL)
-		iucv_retrieve_buffer ();
-	kfree (handle);
-	spin_unlock (&lock);
-#ifdef DEBUG
-	printk (KERN_DEBUG "exit iucv_unregister\n");
-#endif
-	return 0;
+	return;
 }
+/* end of function call */
 
 EXPORT_SYMBOL (iucv_accept);
 EXPORT_SYMBOL (iucv_connect);
 EXPORT_SYMBOL (iucv_purge);
-EXPORT_SYMBOL (iucv_query);
+EXPORT_SYMBOL (iucv_query_maxconn);
+EXPORT_SYMBOL (iucv_query_bufsize);
 EXPORT_SYMBOL (iucv_quiesce);
 EXPORT_SYMBOL (iucv_receive);
-EXPORT_SYMBOL (iucv_receive_simple);
 EXPORT_SYMBOL (iucv_receive_array);
 EXPORT_SYMBOL (iucv_reject);
 EXPORT_SYMBOL (iucv_reply);
@@ -2040,5 +2436,4 @@
 EXPORT_SYMBOL (iucv_setmask);
 EXPORT_SYMBOL (iucv_sever);
 EXPORT_SYMBOL (iucv_register_program);
-EXPORT_SYMBOL (iucv_unregister);
-
+EXPORT_SYMBOL (iucv_unregister_program);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)