aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/defconfig1
-rw-r--r--drivers/s390/net/Kconfig7
-rw-r--r--drivers/s390/net/Makefile1
-rw-r--r--drivers/s390/net/iucv.c2540
-rw-r--r--drivers/s390/net/iucv.h849
5 files changed, 0 insertions, 3398 deletions
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 7c621b8ef683..7729ca114cc9 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -508,7 +508,6 @@ CONFIG_NET_ETHERNET=y
508# 508#
509CONFIG_LCS=m 509CONFIG_LCS=m
510CONFIG_CTC=m 510CONFIG_CTC=m
511CONFIG_IUCV=m
512# CONFIG_NETIUCV is not set 511# CONFIG_NETIUCV is not set
513# CONFIG_SMSGIUCV is not set 512# CONFIG_SMSGIUCV is not set
514# CONFIG_CLAW is not set 513# CONFIG_CLAW is not set
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 52625153a4f0..f98fa465df0a 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -22,13 +22,6 @@ config CTC
22 available. This option is also available as a module which will be 22 available. This option is also available as a module which will be
23 called ctc.ko. If you do not know what it is, it's safe to say "Y". 23 called ctc.ko. If you do not know what it is, it's safe to say "Y".
24 24
25config IUCV
26 tristate "IUCV support (VM only)"
27 help
28 Select this option if you want to use inter-user communication
29 under VM or VIF. If unsure, say "Y" to enable a fast communication
30 link between VM guests.
31
32config NETIUCV 25config NETIUCV
33 tristate "IUCV network device support (VM only)" 26 tristate "IUCV network device support (VM only)"
34 depends on IUCV && NETDEVICES 27 depends on IUCV && NETDEVICES
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 4777e36a922f..bbe3ab2e93d9 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -4,7 +4,6 @@
4 4
5ctc-objs := ctcmain.o ctcdbug.o 5ctc-objs := ctcmain.o ctcdbug.o
6 6
7obj-$(CONFIG_IUCV) += iucv.o
8obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o 7obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
9obj-$(CONFIG_SMSGIUCV) += smsgiucv.o 8obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
10obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o 9obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
deleted file mode 100644
index 229aeb5fc399..000000000000
--- a/drivers/s390/net/iucv.c
+++ /dev/null
@@ -1,2540 +0,0 @@
1/*
2 * IUCV network driver
3 *
4 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s):
6 * Original source:
7 * Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
8 * Xenia Tkatschow (xenia@us.ibm.com)
9 * 2Gb awareness and general cleanup:
10 * Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
11 *
12 * Documentation used:
13 * The original source
14 * CP Programming Service, IBM document # SC24-5760
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2, or (at your option)
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
31
32/* #define DEBUG */
33
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36
37#include <linux/spinlock.h>
38#include <linux/kernel.h>
39#include <linux/slab.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/list.h>
43#include <linux/errno.h>
44#include <linux/err.h>
45#include <linux/device.h>
46#include <asm/atomic.h>
47#include "iucv.h"
48#include <asm/io.h>
49#include <asm/s390_ext.h>
50#include <asm/ebcdic.h>
51#include <asm/smp.h>
52#include <asm/s390_rdev.h>
53
54/* FLAGS:
55 * All flags are defined in the field IPFLAGS1 of each function
56 * and can be found in CP Programming Services.
57 * IPSRCCLS - Indicates you have specified a source class
58 * IPFGMCL - Indicates you have specified a target class
59 * IPFGPID - Indicates you have specified a pathid
60 * IPFGMID - Indicates you have specified a message ID
61 * IPANSLST - Indicates that you are using an address list for
62 * reply data
63 * IPBUFLST - Indicates that you are using an address list for
64 * message data
65 */
66
67#define IPSRCCLS 0x01
68#define IPFGMCL 0x01
69#define IPFGPID 0x02
70#define IPFGMID 0x04
71#define IPANSLST 0x08
72#define IPBUFLST 0x40
73
74static int
75iucv_bus_match (struct device *dev, struct device_driver *drv)
76{
77 return 0;
78}
79
80struct bus_type iucv_bus = {
81 .name = "iucv",
82 .match = iucv_bus_match,
83};
84
85struct device *iucv_root;
86
87/* General IUCV interrupt structure */
88typedef struct {
89 __u16 ippathid;
90 __u8 res1;
91 __u8 iptype;
92 __u32 res2;
93 __u8 ipvmid[8];
94 __u8 res3[24];
95} iucv_GeneralInterrupt;
96
97static iucv_GeneralInterrupt *iucv_external_int_buffer = NULL;
98
99/* Spin Lock declaration */
100
101static DEFINE_SPINLOCK(iucv_lock);
102
103static int messagesDisabled = 0;
104
105/***************INTERRUPT HANDLING ***************/
106
107typedef struct {
108 struct list_head queue;
109 iucv_GeneralInterrupt data;
110} iucv_irqdata;
111
112static struct list_head iucv_irq_queue;
113static DEFINE_SPINLOCK(iucv_irq_queue_lock);
114
115/*
116 *Internal function prototypes
117 */
118static void iucv_tasklet_handler(unsigned long);
119static void iucv_irq_handler(__u16);
120
121static DECLARE_TASKLET(iucv_tasklet,iucv_tasklet_handler,0);
122
123/************ FUNCTION ID'S ****************************/
124
125#define ACCEPT 10
126#define CONNECT 11
127#define DECLARE_BUFFER 12
128#define PURGE 9
129#define QUERY 0
130#define QUIESCE 13
131#define RECEIVE 5
132#define REJECT 8
133#define REPLY 6
134#define RESUME 14
135#define RETRIEVE_BUFFER 2
136#define SEND 4
137#define SETMASK 16
138#define SEVER 15
139
140/**
141 * Structure: handler
142 * members: list - list management.
143 * structure: id
144 * userid - 8 char array of machine identification
145 * user_data - 16 char array for user identification
146 * mask - 24 char array used to compare the 2 previous
147 * interrupt_table - vector of interrupt functions.
148 * pgm_data - ulong, application data that is passed
149 * to the interrupt handlers
150*/
151typedef struct handler_t {
152 struct list_head list;
153 struct {
154 __u8 userid[8];
155 __u8 user_data[16];
156 __u8 mask[24];
157 } id;
158 iucv_interrupt_ops_t *interrupt_table;
159 void *pgm_data;
160} handler;
161
162/**
163 * iucv_handler_table: List of registered handlers.
164 */
165static struct list_head iucv_handler_table;
166
167/**
168 * iucv_pathid_table: an array of *handler pointing into
169 * iucv_handler_table for fast indexing by pathid;
170 */
171static handler **iucv_pathid_table;
172
173static unsigned long max_connections;
174
175/**
176 * iucv_cpuid: contains the logical cpu number of the cpu which
177 * has declared the iucv buffer by issuing DECLARE_BUFFER.
178 * If no cpu has done the initialization iucv_cpuid contains -1.
179 */
180static int iucv_cpuid = -1;
181/**
182 * register_flag: is 0 when external interrupt has not been registered
183 */
184static int register_flag;
185
186/****************FIVE 40-BYTE PARAMETER STRUCTURES******************/
187/* Data struct 1: iparml_control
188 * Used for iucv_accept
189 * iucv_connect
190 * iucv_quiesce
191 * iucv_resume
192 * iucv_sever
193 * iucv_retrieve_buffer
194 * Data struct 2: iparml_dpl (data in parameter list)
195 * Used for iucv_send_prmmsg
196 * iucv_send2way_prmmsg
197 * iucv_send2way_prmmsg_array
198 * iucv_reply_prmmsg
199 * Data struct 3: iparml_db (data in a buffer)
200 * Used for iucv_receive
201 * iucv_receive_array
202 * iucv_reject
203 * iucv_reply
204 * iucv_reply_array
205 * iucv_send
206 * iucv_send_array
207 * iucv_send2way
208 * iucv_send2way_array
209 * iucv_declare_buffer
210 * Data struct 4: iparml_purge
211 * Used for iucv_purge
212 * iucv_query
213 * Data struct 5: iparml_set_mask
214 * Used for iucv_set_mask
215 */
216
217typedef struct {
218 __u16 ippathid;
219 __u8 ipflags1;
220 __u8 iprcode;
221 __u16 ipmsglim;
222 __u16 res1;
223 __u8 ipvmid[8];
224 __u8 ipuser[16];
225 __u8 iptarget[8];
226} iparml_control;
227
228typedef struct {
229 __u16 ippathid;
230 __u8 ipflags1;
231 __u8 iprcode;
232 __u32 ipmsgid;
233 __u32 iptrgcls;
234 __u8 iprmmsg[8];
235 __u32 ipsrccls;
236 __u32 ipmsgtag;
237 __u32 ipbfadr2;
238 __u32 ipbfln2f;
239 __u32 res;
240} iparml_dpl;
241
242typedef struct {
243 __u16 ippathid;
244 __u8 ipflags1;
245 __u8 iprcode;
246 __u32 ipmsgid;
247 __u32 iptrgcls;
248 __u32 ipbfadr1;
249 __u32 ipbfln1f;
250 __u32 ipsrccls;
251 __u32 ipmsgtag;
252 __u32 ipbfadr2;
253 __u32 ipbfln2f;
254 __u32 res;
255} iparml_db;
256
257typedef struct {
258 __u16 ippathid;
259 __u8 ipflags1;
260 __u8 iprcode;
261 __u32 ipmsgid;
262 __u8 ipaudit[3];
263 __u8 res1[5];
264 __u32 res2;
265 __u32 ipsrccls;
266 __u32 ipmsgtag;
267 __u32 res3[3];
268} iparml_purge;
269
270typedef struct {
271 __u8 ipmask;
272 __u8 res1[2];
273 __u8 iprcode;
274 __u32 res2[9];
275} iparml_set_mask;
276
277typedef struct {
278 union {
279 iparml_control p_ctrl;
280 iparml_dpl p_dpl;
281 iparml_db p_db;
282 iparml_purge p_purge;
283 iparml_set_mask p_set_mask;
284 } param;
285 atomic_t in_use;
286 __u32 res;
287} __attribute__ ((aligned(8))) iucv_param;
288#define PARAM_POOL_SIZE (PAGE_SIZE / sizeof(iucv_param))
289
290static iucv_param * iucv_param_pool;
291
292MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
293MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
294MODULE_LICENSE("GPL");
295
296/*
297 * Debugging stuff
298 *******************************************************************************/
299
300
301#ifdef DEBUG
302static int debuglevel = 0;
303
304module_param(debuglevel, int, 0);
305MODULE_PARM_DESC(debuglevel,
306 "Specifies the debug level (0=off ... 3=all)");
307
308static void
309iucv_dumpit(char *title, void *buf, int len)
310{
311 int i;
312 __u8 *p = (__u8 *)buf;
313
314 if (debuglevel < 3)
315 return;
316
317 printk(KERN_DEBUG "%s\n", title);
318 printk(" ");
319 for (i = 0; i < len; i++) {
320 if (!(i % 16) && i != 0)
321 printk ("\n ");
322 else if (!(i % 4) && i != 0)
323 printk(" ");
324 printk("%02X", *p++);
325 }
326 if (len % 16)
327 printk ("\n");
328 return;
329}
330#define iucv_debug(lvl, fmt, args...) \
331do { \
332 if (debuglevel >= lvl) \
333 printk(KERN_DEBUG "%s: " fmt "\n", __FUNCTION__ , ## args); \
334} while (0)
335
336#else
337
338#define iucv_debug(lvl, fmt, args...) do { } while (0)
339#define iucv_dumpit(title, buf, len) do { } while (0)
340
341#endif
342
343/*
344 * Internal functions
345 *******************************************************************************/
346
347/**
348 * print start banner
349 */
350static void
351iucv_banner(void)
352{
353 printk(KERN_INFO "IUCV lowlevel driver initialized\n");
354}
355
356/**
357 * iucv_init - Initialization
358 *
359 * Allocates and initializes various data structures.
360 */
361static int
362iucv_init(void)
363{
364 int ret;
365
366 if (iucv_external_int_buffer)
367 return 0;
368
369 if (!MACHINE_IS_VM) {
370 printk(KERN_ERR "IUCV: IUCV connection needs VM as base\n");
371 return -EPROTONOSUPPORT;
372 }
373
374 ret = bus_register(&iucv_bus);
375 if (ret) {
376 printk(KERN_ERR "IUCV: failed to register bus.\n");
377 return ret;
378 }
379
380 iucv_root = s390_root_dev_register("iucv");
381 if (IS_ERR(iucv_root)) {
382 printk(KERN_ERR "IUCV: failed to register iucv root.\n");
383 bus_unregister(&iucv_bus);
384 return PTR_ERR(iucv_root);
385 }
386
387 /* Note: GFP_DMA used used to get memory below 2G */
388 iucv_external_int_buffer = kzalloc(sizeof(iucv_GeneralInterrupt),
389 GFP_KERNEL|GFP_DMA);
390 if (!iucv_external_int_buffer) {
391 printk(KERN_WARNING
392 "%s: Could not allocate external interrupt buffer\n",
393 __FUNCTION__);
394 s390_root_dev_unregister(iucv_root);
395 bus_unregister(&iucv_bus);
396 return -ENOMEM;
397 }
398
399 /* Initialize parameter pool */
400 iucv_param_pool = kzalloc(sizeof(iucv_param) * PARAM_POOL_SIZE,
401 GFP_KERNEL|GFP_DMA);
402 if (!iucv_param_pool) {
403 printk(KERN_WARNING "%s: Could not allocate param pool\n",
404 __FUNCTION__);
405 kfree(iucv_external_int_buffer);
406 iucv_external_int_buffer = NULL;
407 s390_root_dev_unregister(iucv_root);
408 bus_unregister(&iucv_bus);
409 return -ENOMEM;
410 }
411
412 /* Initialize irq queue */
413 INIT_LIST_HEAD(&iucv_irq_queue);
414
415 /* Initialize handler table */
416 INIT_LIST_HEAD(&iucv_handler_table);
417
418 iucv_banner();
419 return 0;
420}
421
422/**
423 * iucv_exit - De-Initialization
424 *
425 * Frees everything allocated from iucv_init.
426 */
427static int iucv_retrieve_buffer (void);
428
429static void
430iucv_exit(void)
431{
432 iucv_retrieve_buffer();
433 kfree(iucv_external_int_buffer);
434 iucv_external_int_buffer = NULL;
435 kfree(iucv_param_pool);
436 iucv_param_pool = NULL;
437 s390_root_dev_unregister(iucv_root);
438 bus_unregister(&iucv_bus);
439 printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
440}
441
442/**
443 * grab_param: - Get a parameter buffer from the pre-allocated pool.
444 *
445 * This function searches for an unused element in the pre-allocated pool
446 * of parameter buffers. If one is found, it marks it "in use" and returns
447 * a pointer to it. The calling function is responsible for releasing it
448 * when it has finished its usage.
449 *
450 * Returns: A pointer to iucv_param.
451 */
452static __inline__ iucv_param *
453grab_param(void)
454{
455 iucv_param *ptr;
456 static int hint = 0;
457
458 ptr = iucv_param_pool + hint;
459 do {
460 ptr++;
461 if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
462 ptr = iucv_param_pool;
463 } while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
464 hint = ptr - iucv_param_pool;
465
466 memset(&ptr->param, 0, sizeof(ptr->param));
467 return ptr;
468}
469
470/**
471 * release_param - Release a parameter buffer.
472 * @p: A pointer to a struct iucv_param, previously obtained by calling
473 * grab_param().
474 *
475 * This function marks the specified parameter buffer "unused".
476 */
477static __inline__ void
478release_param(void *p)
479{
480 atomic_set(&((iucv_param *)p)->in_use, 0);
481}
482
483/**
484 * iucv_add_handler: - Add a new handler
485 * @new_handler: handle that is being entered into chain.
486 *
487 * Places new handle on iucv_handler_table, if identical handler is not
488 * found.
489 *
490 * Returns: 0 on success, !0 on failure (handler already in chain).
491 */
492static int
493iucv_add_handler (handler *new)
494{
495 ulong flags;
496
497 iucv_debug(1, "entering");
498 iucv_dumpit("handler:", new, sizeof(handler));
499
500 spin_lock_irqsave (&iucv_lock, flags);
501 if (!list_empty(&iucv_handler_table)) {
502 struct list_head *lh;
503
504 /**
505 * Search list for handler with identical id. If one
506 * is found, the new handler is _not_ added.
507 */
508 list_for_each(lh, &iucv_handler_table) {
509 handler *h = list_entry(lh, handler, list);
510 if (!memcmp(&new->id, &h->id, sizeof(h->id))) {
511 iucv_debug(1, "ret 1");
512 spin_unlock_irqrestore (&iucv_lock, flags);
513 return 1;
514 }
515 }
516 }
517 /**
518 * If we get here, no handler was found.
519 */
520 INIT_LIST_HEAD(&new->list);
521 list_add(&new->list, &iucv_handler_table);
522 spin_unlock_irqrestore (&iucv_lock, flags);
523
524 iucv_debug(1, "exiting");
525 return 0;
526}
527
528/**
529 * b2f0:
530 * @code: identifier of IUCV call to CP.
531 * @parm: pointer to 40 byte iparml area passed to CP
532 *
533 * Calls CP to execute IUCV commands.
534 *
535 * Returns: return code from CP's IUCV call
536 */
537static inline ulong b2f0(__u32 code, void *parm)
538{
539 register unsigned long reg0 asm ("0");
540 register unsigned long reg1 asm ("1");
541 iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
542
543 reg0 = code;
544 reg1 = virt_to_phys(parm);
545 asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
546
547 iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
548
549 return (unsigned long)*((__u8 *)(parm + 3));
550}
551
552/*
553 * Name: iucv_add_pathid
554 * Purpose: Adds a path id to the system.
555 * Input: pathid - pathid that is going to be entered into system
556 * handle - address of handler that the pathid will be associated
557 * with.
558 * pgm_data - token passed in by application.
559 * Output: 0: successful addition of pathid
560 * - EINVAL - pathid entry is being used by another application
561 * - ENOMEM - storage allocation for a new pathid table failed
562*/
563static int
564__iucv_add_pathid(__u16 pathid, handler *handler)
565{
566
567 iucv_debug(1, "entering");
568
569 iucv_debug(1, "handler is pointing to %p", handler);
570
571 if (pathid > (max_connections - 1))
572 return -EINVAL;
573
574 if (iucv_pathid_table[pathid]) {
575 iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]);
576 printk(KERN_WARNING
577 "%s: Pathid being used, error.\n", __FUNCTION__);
578 return -EINVAL;
579 }
580 iucv_pathid_table[pathid] = handler;
581
582 iucv_debug(1, "exiting");
583 return 0;
584} /* end of add_pathid function */
585
586static int
587iucv_add_pathid(__u16 pathid, handler *handler)
588{
589 ulong flags;
590 int rc;
591
592 spin_lock_irqsave (&iucv_lock, flags);
593 rc = __iucv_add_pathid(pathid, handler);
594 spin_unlock_irqrestore (&iucv_lock, flags);
595 return rc;
596}
597
598static void
599iucv_remove_pathid(__u16 pathid)
600{
601 ulong flags;
602
603 if (pathid > (max_connections - 1))
604 return;
605
606 spin_lock_irqsave (&iucv_lock, flags);
607 iucv_pathid_table[pathid] = NULL;
608 spin_unlock_irqrestore (&iucv_lock, flags);
609}
610
611/**
612 * iucv_declare_buffer_cpuid
613 * Register at VM for subsequent IUCV operations. This is executed
614 * on the reserved CPU iucv_cpuid. Called from iucv_declare_buffer().
615 */
616static void
617iucv_declare_buffer_cpuid (void *result)
618{
619 iparml_db *parm;
620
621 parm = (iparml_db *)grab_param();
622 parm->ipbfadr1 = virt_to_phys(iucv_external_int_buffer);
623 if ((*((ulong *)result) = b2f0(DECLARE_BUFFER, parm)) == 1)
624 *((ulong *)result) = parm->iprcode;
625 release_param(parm);
626}
627
628/**
629 * iucv_retrieve_buffer_cpuid:
630 * Unregister IUCV usage at VM. This is always executed on the same
631 * cpu that registered the buffer to VM.
632 * Called from iucv_retrieve_buffer().
633 */
634static void
635iucv_retrieve_buffer_cpuid (void *cpu)
636{
637 iparml_control *parm;
638
639 parm = (iparml_control *)grab_param();
640 b2f0(RETRIEVE_BUFFER, parm);
641 release_param(parm);
642}
643
644/**
645 * Name: iucv_declare_buffer
646 * Purpose: Specifies the guests real address of an external
647 * interrupt.
648 * Input: void
649 * Output: iprcode - return code from b2f0 call
650 */
651static int
652iucv_declare_buffer (void)
653{
654 unsigned long flags;
655 ulong b2f0_result;
656
657 iucv_debug(1, "entering");
658 b2f0_result = -ENODEV;
659 spin_lock_irqsave (&iucv_lock, flags);
660 if (iucv_cpuid == -1) {
661 /* Reserve any cpu for use by iucv. */
662 iucv_cpuid = smp_get_cpu(CPU_MASK_ALL);
663 spin_unlock_irqrestore (&iucv_lock, flags);
664 smp_call_function_on(iucv_declare_buffer_cpuid,
665 &b2f0_result, 0, 1, iucv_cpuid);
666 if (b2f0_result) {
667 smp_put_cpu(iucv_cpuid);
668 iucv_cpuid = -1;
669 }
670 iucv_debug(1, "Address of EIB = %p", iucv_external_int_buffer);
671 } else {
672 spin_unlock_irqrestore (&iucv_lock, flags);
673 b2f0_result = 0;
674 }
675 iucv_debug(1, "exiting");
676 return b2f0_result;
677}
678
679/**
680 * iucv_retrieve_buffer:
681 *
682 * Terminates all use of IUCV.
683 * Returns: return code from CP
684 */
685static int
686iucv_retrieve_buffer (void)
687{
688 iucv_debug(1, "entering");
689 if (iucv_cpuid != -1) {
690 smp_call_function_on(iucv_retrieve_buffer_cpuid,
691 NULL, 0, 1, iucv_cpuid);
692 /* Release the cpu reserved by iucv_declare_buffer. */
693 smp_put_cpu(iucv_cpuid);
694 iucv_cpuid = -1;
695 }
696 iucv_debug(1, "exiting");
697 return 0;
698}
699
700/**
701 * iucv_remove_handler:
702 * @users_handler: handler to be removed
703 *
704 * Remove handler when application unregisters.
705 */
706static void
707iucv_remove_handler(handler *handler)
708{
709 unsigned long flags;
710
711 if ((!iucv_pathid_table) || (!handler))
712 return;
713
714 iucv_debug(1, "entering");
715
716 spin_lock_irqsave (&iucv_lock, flags);
717 list_del(&handler->list);
718 if (list_empty(&iucv_handler_table)) {
719 if (register_flag) {
720 unregister_external_interrupt(0x4000, iucv_irq_handler);
721 register_flag = 0;
722 }
723 }
724 spin_unlock_irqrestore (&iucv_lock, flags);
725
726 iucv_debug(1, "exiting");
727 return;
728}
729
730/**
731 * iucv_register_program:
732 * @pgmname: user identification
733 * @userid: machine identification
734 * @pgmmask: Indicates which bits in the pgmname and userid combined will be
735 * used to determine who is given control.
736 * @ops: Address of interrupt handler table.
737 * @pgm_data: Application data to be passed to interrupt handlers.
738 *
739 * Registers an application with IUCV.
740 * Returns:
741 * The address of handler, or NULL on failure.
742 * NOTE on pgmmask:
743 * If pgmname, userid and pgmmask are provided, pgmmask is entered into the
744 * handler as is.
745 * If pgmmask is NULL, the internal mask is set to all 0xff's
746 * When userid is NULL, the first 8 bytes of the internal mask are forced
747 * to 0x00.
748 * If pgmmask and userid are NULL, the first 8 bytes of the internal mask
749 * are forced to 0x00 and the last 16 bytes to 0xff.
750 */
751
752iucv_handle_t
753iucv_register_program (__u8 pgmname[16],
754 __u8 userid[8],
755 __u8 pgmmask[24],
756 iucv_interrupt_ops_t * ops, void *pgm_data)
757{
758 ulong rc = 0; /* return code from function calls */
759 handler *new_handler;
760
761 iucv_debug(1, "entering");
762
763 if (ops == NULL) {
764 /* interrupt table is not defined */
765 printk(KERN_WARNING "%s: Interrupt table is not defined, "
766 "exiting\n", __FUNCTION__);
767 return NULL;
768 }
769 if (!pgmname) {
770 printk(KERN_WARNING "%s: pgmname not provided\n", __FUNCTION__);
771 return NULL;
772 }
773
774 /* Allocate handler entry */
775 new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
776 if (new_handler == NULL) {
777 printk(KERN_WARNING "%s: storage allocation for new handler "
778 "failed.\n", __FUNCTION__);
779 return NULL;
780 }
781
782 if (!iucv_pathid_table) {
783 if (iucv_init()) {
784 kfree(new_handler);
785 return NULL;
786 }
787
788 max_connections = iucv_query_maxconn();
789 iucv_pathid_table = kcalloc(max_connections, sizeof(handler *),
790 GFP_ATOMIC);
791 if (iucv_pathid_table == NULL) {
792 printk(KERN_WARNING "%s: iucv_pathid_table storage "
793 "allocation failed\n", __FUNCTION__);
794 kfree(new_handler);
795 return NULL;
796 }
797 }
798 memset(new_handler, 0, sizeof (handler));
799 memcpy(new_handler->id.user_data, pgmname,
800 sizeof (new_handler->id.user_data));
801 if (userid) {
802 memcpy (new_handler->id.userid, userid,
803 sizeof (new_handler->id.userid));
804 ASCEBC (new_handler->id.userid,
805 sizeof (new_handler->id.userid));
806 EBC_TOUPPER (new_handler->id.userid,
807 sizeof (new_handler->id.userid));
808
809 if (pgmmask) {
810 memcpy (new_handler->id.mask, pgmmask,
811 sizeof (new_handler->id.mask));
812 } else {
813 memset (new_handler->id.mask, 0xFF,
814 sizeof (new_handler->id.mask));
815 }
816 } else {
817 if (pgmmask) {
818 memcpy (new_handler->id.mask, pgmmask,
819 sizeof (new_handler->id.mask));
820 } else {
821 memset (new_handler->id.mask, 0xFF,
822 sizeof (new_handler->id.mask));
823 }
824 memset (new_handler->id.userid, 0x00,
825 sizeof (new_handler->id.userid));
826 }
827 /* fill in the rest of handler */
828 new_handler->pgm_data = pgm_data;
829 new_handler->interrupt_table = ops;
830
831 /*
832 * Check if someone else is registered with same pgmname, userid
833 * and mask. If someone is already registered with same pgmname,
834 * userid and mask, registration will fail and NULL will be returned
835 * to the application.
836 * If identical handler not found, then handler is added to list.
837 */
838 rc = iucv_add_handler(new_handler);
839 if (rc) {
840 printk(KERN_WARNING "%s: Someone already registered with same "
841 "pgmname, userid, pgmmask\n", __FUNCTION__);
842 kfree (new_handler);
843 return NULL;
844 }
845
846 rc = iucv_declare_buffer();
847 if (rc) {
848 char *err = "Unknown";
849 iucv_remove_handler(new_handler);
850 kfree(new_handler);
851 switch(rc) {
852 case 0x03:
853 err = "Directory error";
854 break;
855 case 0x0a:
856 err = "Invalid length";
857 break;
858 case 0x13:
859 err = "Buffer already exists";
860 break;
861 case 0x3e:
862 err = "Buffer overlap";
863 break;
864 case 0x5c:
865 err = "Paging or storage error";
866 break;
867 }
868 printk(KERN_WARNING "%s: iucv_declare_buffer "
869 "returned error 0x%02lx (%s)\n", __FUNCTION__, rc, err);
870 return NULL;
871 }
872 if (!register_flag) {
873 /* request the 0x4000 external interrupt */
874 rc = register_external_interrupt (0x4000, iucv_irq_handler);
875 if (rc) {
876 iucv_remove_handler(new_handler);
877 kfree (new_handler);
878 printk(KERN_WARNING "%s: "
879 "register_external_interrupt returned %ld\n",
880 __FUNCTION__, rc);
881 return NULL;
882
883 }
884 register_flag = 1;
885 }
886 iucv_debug(1, "exiting");
887 return new_handler;
888} /* end of register function */
889
890/**
891 * iucv_unregister_program:
892 * @handle: address of handler
893 *
894 * Unregister application with IUCV.
895 * Returns:
896 * 0 on success, -EINVAL, if specified handle is invalid.
897 */
898
899int
900iucv_unregister_program (iucv_handle_t handle)
901{
902 handler *h = NULL;
903 struct list_head *lh;
904 int i;
905 ulong flags;
906
907 iucv_debug(1, "entering");
908 iucv_debug(1, "address of handler is %p", h);
909
910 /* Checking if handle is valid */
911 spin_lock_irqsave (&iucv_lock, flags);
912 list_for_each(lh, &iucv_handler_table) {
913 if ((handler *)handle == list_entry(lh, handler, list)) {
914 h = (handler *)handle;
915 break;
916 }
917 }
918 if (!h) {
919 spin_unlock_irqrestore (&iucv_lock, flags);
920 if (handle)
921 printk(KERN_WARNING
922 "%s: Handler not found in iucv_handler_table.\n",
923 __FUNCTION__);
924 else
925 printk(KERN_WARNING
926 "%s: NULL handle passed by application.\n",
927 __FUNCTION__);
928 return -EINVAL;
929 }
930
931 /**
932 * First, walk thru iucv_pathid_table and sever any pathid which is
933 * still pointing to the handler to be removed.
934 */
935 for (i = 0; i < max_connections; i++)
936 if (iucv_pathid_table[i] == h) {
937 spin_unlock_irqrestore (&iucv_lock, flags);
938 iucv_sever(i, h->id.user_data);
939 spin_lock_irqsave(&iucv_lock, flags);
940 }
941 spin_unlock_irqrestore (&iucv_lock, flags);
942
943 iucv_remove_handler(h);
944 kfree(h);
945
946 iucv_debug(1, "exiting");
947 return 0;
948}
949
950/**
951 * iucv_accept:
952 * @pathid: Path identification number
953 * @msglim_reqstd: The number of outstanding messages requested.
954 * @user_data: Data specified by the iucv_connect function.
955 * @flags1: Contains options for this path.
956 * - IPPRTY (0x20) Specifies if you want to send priority message.
957 * - IPRMDATA (0x80) Specifies whether your program can handle a message
958 * in the parameter list.
959 * - IPQUSCE (0x40) Specifies whether you want to quiesce the path being
960 * established.
961 * @handle: Address of handler.
962 * @pgm_data: Application data passed to interrupt handlers.
963 * @flags1_out: Pointer to an int. If not NULL, on return the options for
964 * the path are stored at the given location:
965 * - IPPRTY (0x20) Indicates you may send a priority message.
966 * @msglim: Pointer to an __u16. If not NULL, on return the maximum
967 * number of outstanding messages is stored at the given
968 * location.
969 *
970 * This function is issued after the user receives a Connection Pending external
971 * interrupt and now wishes to complete the IUCV communication path.
972 * Returns:
973 * return code from CP
974 */
975int
976iucv_accept(__u16 pathid, __u16 msglim_reqstd,
977 __u8 user_data[16], int flags1,
978 iucv_handle_t handle, void *pgm_data,
979 int *flags1_out, __u16 * msglim)
980{
981 ulong b2f0_result = 0;
982 ulong flags;
983 struct list_head *lh;
984 handler *h = NULL;
985 iparml_control *parm;
986
987 iucv_debug(1, "entering");
988 iucv_debug(1, "pathid = %d", pathid);
989
990 /* Checking if handle is valid */
991 spin_lock_irqsave (&iucv_lock, flags);
992 list_for_each(lh, &iucv_handler_table) {
993 if ((handler *)handle == list_entry(lh, handler, list)) {
994 h = (handler *)handle;
995 break;
996 }
997 }
998 spin_unlock_irqrestore (&iucv_lock, flags);
999
1000 if (!h) {
1001 if (handle)
1002 printk(KERN_WARNING
1003 "%s: Handler not found in iucv_handler_table.\n",
1004 __FUNCTION__);
1005 else
1006 printk(KERN_WARNING
1007 "%s: NULL handle passed by application.\n",
1008 __FUNCTION__);
1009 return -EINVAL;
1010 }
1011
1012 parm = (iparml_control *)grab_param();
1013
1014 parm->ippathid = pathid;
1015 parm->ipmsglim = msglim_reqstd;
1016 if (user_data)
1017 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
1018
1019 parm->ipflags1 = (__u8)flags1;
1020 b2f0_result = b2f0(ACCEPT, parm);
1021
1022 if (!b2f0_result) {
1023 if (msglim)
1024 *msglim = parm->ipmsglim;
1025 if (pgm_data)
1026 h->pgm_data = pgm_data;
1027 if (flags1_out)
1028 *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
1029 }
1030 release_param(parm);
1031
1032 iucv_debug(1, "exiting");
1033 return b2f0_result;
1034}
1035
1036/**
1037 * iucv_connect:
1038 * @pathid: Path identification number
1039 * @msglim_reqstd: Number of outstanding messages requested
1040 * @user_data: 16-byte user data
1041 * @userid: 8-byte of user identification
1042 * @system_name: 8-byte identifying the system name
1043 * @flags1: Specifies options for this path:
1044 * - IPPRTY (0x20) Specifies if you want to send priority message.
1045 * - IPRMDATA (0x80) Specifies whether your program can handle a message
1046 * in the parameter list.
1047 * - IPQUSCE (0x40) Specifies whether you want to quiesce the path being
1048 * established.
1049 * - IPLOCAL (0x01) Allows an application to force the partner to be on the
1050 * local system. If local is specified then target class
1051 * cannot be specified.
1052 * @flags1_out: Pointer to an int. If not NULL, on return the options for
1053 * the path are stored at the given location:
1054 * - IPPRTY (0x20) Indicates you may send a priority message.
1055 * @msglim: Pointer to an __u16. If not NULL, on return the maximum
1056 * number of outstanding messages is stored at the given
1057 * location.
1058 * @handle: Address of handler.
1059 * @pgm_data: Application data to be passed to interrupt handlers.
1060 *
1061 * This function establishes an IUCV path. Although the connect may complete
1062 * successfully, you are not able to use the path until you receive an IUCV
1063 * Connection Complete external interrupt.
1064 * Returns: return code from CP, or one of the following
1065 * - ENOMEM
1066 * - return code from iucv_declare_buffer
1067 * - EINVAL - invalid handle passed by application
1068 * - EINVAL - pathid address is NULL
1069 * - ENOMEM - pathid table storage allocation failed
1070 * - return code from internal function add_pathid
1071 */
1072int
1073iucv_connect (__u16 *pathid, __u16 msglim_reqstd,
1074 __u8 user_data[16], __u8 userid[8],
1075 __u8 system_name[8], int flags1,
1076 int *flags1_out, __u16 * msglim,
1077 iucv_handle_t handle, void *pgm_data)
1078{
1079 iparml_control *parm;
1080 iparml_control local_parm;
1081 struct list_head *lh;
1082 ulong b2f0_result = 0;
1083 ulong flags;
1084 int add_pathid_result = 0;
1085 handler *h = NULL;
1086 __u8 no_memory[16] = "NO MEMORY";
1087
1088 iucv_debug(1, "entering");
1089
1090 /* Checking if handle is valid */
1091 spin_lock_irqsave (&iucv_lock, flags);
1092 list_for_each(lh, &iucv_handler_table) {
1093 if ((handler *)handle == list_entry(lh, handler, list)) {
1094 h = (handler *)handle;
1095 break;
1096 }
1097 }
1098 spin_unlock_irqrestore (&iucv_lock, flags);
1099
1100 if (!h) {
1101 if (handle)
1102 printk(KERN_WARNING
1103 "%s: Handler not found in iucv_handler_table.\n",
1104 __FUNCTION__);
1105 else
1106 printk(KERN_WARNING
1107 "%s: NULL handle passed by application.\n",
1108 __FUNCTION__);
1109 return -EINVAL;
1110 }
1111
1112 if (pathid == NULL) {
1113 printk(KERN_WARNING "%s: NULL pathid pointer\n",
1114 __FUNCTION__);
1115 return -EINVAL;
1116 }
1117
1118 parm = (iparml_control *)grab_param();
1119
1120 parm->ipmsglim = msglim_reqstd;
1121
1122 if (user_data)
1123 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
1124
1125 if (userid) {
1126 memcpy(parm->ipvmid, userid, sizeof(parm->ipvmid));
1127 ASCEBC(parm->ipvmid, sizeof(parm->ipvmid));
1128 EBC_TOUPPER(parm->ipvmid, sizeof(parm->ipvmid));
1129 }
1130
1131 if (system_name) {
1132 memcpy(parm->iptarget, system_name, sizeof(parm->iptarget));
1133 ASCEBC(parm->iptarget, sizeof(parm->iptarget));
1134 EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
1135 }
1136
1137 /* In order to establish an IUCV connection, the procedure is:
1138 *
1139 * b2f0(CONNECT)
1140 * take the ippathid from the b2f0 call
1141 * register the handler to the ippathid
1142 *
1143 * Unfortunately, the ConnectionEstablished message gets sent after the
1144 * b2f0(CONNECT) call but before the register is handled.
1145 *
1146 * In order for this race condition to be eliminated, the IUCV Control
1147 * Interrupts must be disabled for the above procedure.
1148 *
1149 * David Kennedy <dkennedy@linuxcare.com>
1150 */
1151
1152 /* Enable everything but IUCV Control messages */
1153 iucv_setmask(~(AllInterrupts));
1154 messagesDisabled = 1;
1155
1156 spin_lock_irqsave (&iucv_lock, flags);
1157 parm->ipflags1 = (__u8)flags1;
1158 b2f0_result = b2f0(CONNECT, parm);
1159 memcpy(&local_parm, parm, sizeof(local_parm));
1160 release_param(parm);
1161 parm = &local_parm;
1162 if (!b2f0_result)
1163 add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
1164 spin_unlock_irqrestore (&iucv_lock, flags);
1165
1166 if (b2f0_result) {
1167 iucv_setmask(~0);
1168 messagesDisabled = 0;
1169 return b2f0_result;
1170 }
1171
1172 *pathid = parm->ippathid;
1173
1174 /* Enable everything again */
1175 iucv_setmask(IUCVControlInterruptsFlag);
1176
1177 if (msglim)
1178 *msglim = parm->ipmsglim;
1179 if (flags1_out)
1180 *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
1181
1182 if (add_pathid_result) {
1183 iucv_sever(*pathid, no_memory);
1184 printk(KERN_WARNING "%s: add_pathid failed with rc ="
1185 " %d\n", __FUNCTION__, add_pathid_result);
1186 return(add_pathid_result);
1187 }
1188
1189 iucv_debug(1, "exiting");
1190 return b2f0_result;
1191}
1192
1193/**
1194 * iucv_purge:
1195 * @pathid: Path identification number
1196 * @msgid: Message ID of message to purge.
1197 * @srccls: Message class of the message to purge.
1198 * @audit: Pointer to an __u32. If not NULL, on return, information about
1199 * asynchronous errors that may have affected the normal completion
1200 * of this message ist stored at the given location.
1201 *
1202 * Cancels a message you have sent.
1203 * Returns: return code from CP
1204 */
1205int
1206iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
1207{
1208 iparml_purge *parm;
1209 ulong b2f0_result = 0;
1210
1211 iucv_debug(1, "entering");
1212 iucv_debug(1, "pathid = %d", pathid);
1213
1214 parm = (iparml_purge *)grab_param();
1215
1216 parm->ipmsgid = msgid;
1217 parm->ippathid = pathid;
1218 parm->ipsrccls = srccls;
1219 parm->ipflags1 |= (IPSRCCLS | IPFGMID | IPFGPID);
1220 b2f0_result = b2f0(PURGE, parm);
1221
1222 if (!b2f0_result && audit) {
1223 memcpy(audit, parm->ipaudit, sizeof(parm->ipaudit));
1224 /* parm->ipaudit has only 3 bytes */
1225 *audit >>= 8;
1226 }
1227
1228 release_param(parm);
1229
1230 iucv_debug(1, "b2f0_result = %ld", b2f0_result);
1231 iucv_debug(1, "exiting");
1232 return b2f0_result;
1233}
1234
1235/**
1236 * iucv_query_generic:
1237 * @want_maxconn: Flag, describing which value is to be returned.
1238 *
1239 * Helper function for iucv_query_maxconn() and iucv_query_bufsize().
1240 *
1241 * Returns: The buffersize, if want_maxconn is 0; the maximum number of
1242 * connections, if want_maxconn is 1 or an error-code < 0 on failure.
1243 */
1244static int
1245iucv_query_generic(int want_maxconn)
1246{
1247 register unsigned long reg0 asm ("0");
1248 register unsigned long reg1 asm ("1");
1249 iparml_purge *parm = (iparml_purge *)grab_param();
1250 int bufsize, maxconn;
1251 int ccode;
1252
1253 /**
1254 * Call b2f0 and store R0 (max buffer size),
1255 * R1 (max connections) and CC.
1256 */
1257 reg0 = QUERY;
1258 reg1 = virt_to_phys(parm);
1259 asm volatile(
1260 " .long 0xb2f01000\n"
1261 " ipm %0\n"
1262 " srl %0,28\n"
1263 : "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
1264 bufsize = reg0;
1265 maxconn = reg1;
1266 release_param(parm);
1267
1268 if (ccode)
1269 return -EPERM;
1270 if (want_maxconn)
1271 return maxconn;
1272 return bufsize;
1273}
1274
1275/**
1276 * iucv_query_maxconn:
1277 *
1278 * Determines the maximum number of connections thay may be established.
1279 *
1280 * Returns: Maximum number of connections that can be.
1281 */
1282ulong
1283iucv_query_maxconn(void)
1284{
1285 return iucv_query_generic(1);
1286}
1287
1288/**
1289 * iucv_query_bufsize:
1290 *
1291 * Determines the size of the external interrupt buffer.
1292 *
1293 * Returns: Size of external interrupt buffer.
1294 */
1295ulong
1296iucv_query_bufsize (void)
1297{
1298 return iucv_query_generic(0);
1299}
1300
1301/**
1302 * iucv_quiesce:
1303 * @pathid: Path identification number
1304 * @user_data: 16-byte user data
1305 *
1306 * Temporarily suspends incoming messages on an IUCV path.
1307 * You can later reactivate the path by invoking the iucv_resume function.
1308 * Returns: return code from CP
1309 */
1310int
1311iucv_quiesce (__u16 pathid, __u8 user_data[16])
1312{
1313 iparml_control *parm;
1314 ulong b2f0_result = 0;
1315
1316 iucv_debug(1, "entering");
1317 iucv_debug(1, "pathid = %d", pathid);
1318
1319 parm = (iparml_control *)grab_param();
1320
1321 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
1322 parm->ippathid = pathid;
1323
1324 b2f0_result = b2f0(QUIESCE, parm);
1325 release_param(parm);
1326
1327 iucv_debug(1, "b2f0_result = %ld", b2f0_result);
1328 iucv_debug(1, "exiting");
1329
1330 return b2f0_result;
1331}
1332
1333/**
1334 * iucv_receive:
1335 * @pathid: Path identification number.
1336 * @buffer: Address of buffer to receive. Must be below 2G.
1337 * @buflen: Length of buffer to receive.
1338 * @msgid: Specifies the message ID.
1339 * @trgcls: Specifies target class.
1340 * @flags1_out: Receives options for path on return.
1341 * - IPNORPY (0x10) Specifies whether a reply is required
1342 * - IPPRTY (0x20) Specifies if you want to send priority message
1343 * - IPRMDATA (0x80) Specifies the data is contained in the parameter list
1344 * @residual_buffer: Receives the address of buffer updated by the number
1345 * of bytes you have received on return.
1346 * @residual_length: On return, receives one of the following values:
1347 * - 0 If the receive buffer is the same length as
1348 * the message.
1349 * - Remaining bytes in buffer If the receive buffer is longer than the
1350 * message.
1351 * - Remaining bytes in message If the receive buffer is shorter than the
1352 * message.
1353 *
1354 * This function receives messages that are being sent to you over established
1355 * paths.
1356 * Returns: return code from CP IUCV call; If the receive buffer is shorter
1357 * than the message, always 5
1358 * -EINVAL - buffer address is pointing to NULL
1359 */
1360int
1361iucv_receive (__u16 pathid, __u32 msgid, __u32 trgcls,
1362 void *buffer, ulong buflen,
1363 int *flags1_out, ulong * residual_buffer, ulong * residual_length)
1364{
1365 iparml_db *parm;
1366 ulong b2f0_result;
1367 int moved = 0; /* number of bytes moved from parmlist to buffer */
1368
1369 iucv_debug(2, "entering");
1370
1371 if (!buffer)
1372 return -EINVAL;
1373
1374 parm = (iparml_db *)grab_param();
1375
1376 parm->ipbfadr1 = (__u32) (addr_t) buffer;
1377 parm->ipbfln1f = (__u32) ((ulong) buflen);
1378 parm->ipmsgid = msgid;
1379 parm->ippathid = pathid;
1380 parm->iptrgcls = trgcls;
1381 parm->ipflags1 = (IPFGPID | IPFGMID | IPFGMCL);
1382
1383 b2f0_result = b2f0(RECEIVE, parm);
1384
1385 if (!b2f0_result || b2f0_result == 5) {
1386 if (flags1_out) {
1387 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1388 *flags1_out = (parm->ipflags1 & (~0x07));
1389 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1390 }
1391
1392 if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */
1393 if (residual_length)
1394 *residual_length = parm->ipbfln1f;
1395
1396 if (residual_buffer)
1397 *residual_buffer = parm->ipbfadr1;
1398 } else {
1399 moved = min_t (unsigned long, buflen, 8);
1400
1401 memcpy ((char *) buffer,
1402 (char *) &parm->ipbfadr1, moved);
1403
1404 if (buflen < 8)
1405 b2f0_result = 5;
1406
1407 if (residual_length)
1408 *residual_length = abs (buflen - 8);
1409
1410 if (residual_buffer)
1411 *residual_buffer = (ulong) (buffer + moved);
1412 }
1413 }
1414 release_param(parm);
1415
1416 iucv_debug(2, "exiting");
1417 return b2f0_result;
1418}
1419
1420/*
1421 * Name: iucv_receive_array
1422 * Purpose: This function receives messages that are being sent to you
1423 * over established paths.
1424 * Input: pathid - path identification number
1425 * buffer - address of array of buffers
1426 * buflen - total length of buffers
1427 * msgid - specifies the message ID.
1428 * trgcls - specifies target class
1429 * Output:
1430 * flags1_out: Options for path.
1431 * IPNORPY - 0x10 specifies whether a reply is required
1432 * IPPRTY - 0x20 specifies if you want to send priority message
1433 * IPRMDATA - 0x80 specifies the data is contained in the parameter list
1434 * residual_buffer - address points to the current list entry IUCV
1435 * is working on.
1436 * residual_length -
1437 * Contains one of the following values, if the receive buffer is:
1438 * The same length as the message, this field is zero.
1439 * Longer than the message, this field contains the number of
1440 * bytes remaining in the buffer.
1441 * Shorter than the message, this field contains the residual
1442 * count (that is, the number of bytes remaining in the
1443 * message that does not fit into the buffer. In this case
1444 * b2f0_result = 5.
1445 * Return: b2f0_result - return code from CP
1446 * (-EINVAL) - buffer address is NULL
1447 */
1448int
1449iucv_receive_array (__u16 pathid,
1450 __u32 msgid, __u32 trgcls,
1451 iucv_array_t * buffer, ulong buflen,
1452 int *flags1_out,
1453 ulong * residual_buffer, ulong * residual_length)
1454{
1455 iparml_db *parm;
1456 ulong b2f0_result;
1457 int i = 0, moved = 0, need_to_move = 8, dyn_len;
1458
1459 iucv_debug(2, "entering");
1460
1461 if (!buffer)
1462 return -EINVAL;
1463
1464 parm = (iparml_db *)grab_param();
1465
1466 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1467 parm->ipbfln1f = (__u32) buflen;
1468 parm->ipmsgid = msgid;
1469 parm->ippathid = pathid;
1470 parm->iptrgcls = trgcls;
1471 parm->ipflags1 = (IPBUFLST | IPFGPID | IPFGMID | IPFGMCL);
1472
1473 b2f0_result = b2f0(RECEIVE, parm);
1474
1475 if (!b2f0_result || b2f0_result == 5) {
1476
1477 if (flags1_out) {
1478 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1479 *flags1_out = (parm->ipflags1 & (~0x07));
1480 iucv_debug(2, "*flags1_out = %d", *flags1_out);
1481 }
1482
1483 if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */
1484
1485 if (residual_length)
1486 *residual_length = parm->ipbfln1f;
1487
1488 if (residual_buffer)
1489 *residual_buffer = parm->ipbfadr1;
1490
1491 } else {
1492 /* copy msg from parmlist to users array. */
1493
1494 while ((moved < 8) && (moved < buflen)) {
1495 dyn_len =
1496 min_t (unsigned int,
1497 (buffer + i)->length, need_to_move);
1498
1499 memcpy ((char *)((ulong)((buffer + i)->address)),
1500 ((char *) &parm->ipbfadr1) + moved,
1501 dyn_len);
1502
1503 moved += dyn_len;
1504 need_to_move -= dyn_len;
1505
1506 (buffer + i)->address =
1507 (__u32)
1508 ((ulong)(__u8 *) ((ulong)(buffer + i)->address)
1509 + dyn_len);
1510
1511 (buffer + i)->length -= dyn_len;
1512 i++;
1513 }
1514
1515 if (need_to_move) /* buflen < 8 bytes */
1516 b2f0_result = 5;
1517
1518 if (residual_length)
1519 *residual_length = abs (buflen - 8);
1520
1521 if (residual_buffer) {
1522 if (!moved)
1523 *residual_buffer = (ulong) buffer;
1524 else
1525 *residual_buffer =
1526 (ulong) (buffer + (i - 1));
1527 }
1528
1529 }
1530 }
1531 release_param(parm);
1532
1533 iucv_debug(2, "exiting");
1534 return b2f0_result;
1535}
1536
1537/**
1538 * iucv_reject:
1539 * @pathid: Path identification number.
1540 * @msgid: Message ID of the message to reject.
1541 * @trgcls: Target class of the message to reject.
1542 * Returns: return code from CP
1543 *
1544 * Refuses a specified message. Between the time you are notified of a
1545 * message and the time that you complete the message, the message may
1546 * be rejected.
1547 */
1548int
1549iucv_reject (__u16 pathid, __u32 msgid, __u32 trgcls)
1550{
1551 iparml_db *parm;
1552 ulong b2f0_result = 0;
1553
1554 iucv_debug(1, "entering");
1555 iucv_debug(1, "pathid = %d", pathid);
1556
1557 parm = (iparml_db *)grab_param();
1558
1559 parm->ippathid = pathid;
1560 parm->ipmsgid = msgid;
1561 parm->iptrgcls = trgcls;
1562 parm->ipflags1 = (IPFGMCL | IPFGMID | IPFGPID);
1563
1564 b2f0_result = b2f0(REJECT, parm);
1565 release_param(parm);
1566
1567 iucv_debug(1, "b2f0_result = %ld", b2f0_result);
1568 iucv_debug(1, "exiting");
1569
1570 return b2f0_result;
1571}
1572
1573/*
1574 * Name: iucv_reply
1575 * Purpose: This function responds to the two-way messages that you
1576 * receive. You must identify completely the message to
1577 * which you wish to reply. ie, pathid, msgid, and trgcls.
1578 * Input: pathid - path identification number
1579 * msgid - specifies the message ID.
1580 * trgcls - specifies target class
1581 * flags1 - option for path
1582 * IPPRTY- 0x20 - specifies if you want to send priority message
1583 * buffer - address of reply buffer
1584 * buflen - length of reply buffer
1585 * Output: ipbfadr2 - Address of buffer updated by the number
1586 * of bytes you have moved.
1587 * ipbfln2f - Contains one of the following values:
1588 * If the answer buffer is the same length as the reply, this field
1589 * contains zero.
1590 * If the answer buffer is longer than the reply, this field contains
1591 * the number of bytes remaining in the buffer.
1592 * If the answer buffer is shorter than the reply, this field contains
1593 * a residual count (that is, the number of bytes remianing in the
1594 * reply that does not fit into the buffer. In this
1595 * case b2f0_result = 5.
1596 * Return: b2f0_result - return code from CP
1597 * (-EINVAL) - buffer address is NULL
1598 */
1599int
1600iucv_reply (__u16 pathid,
1601 __u32 msgid, __u32 trgcls,
1602 int flags1,
1603 void *buffer, ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
1604{
1605 iparml_db *parm;
1606 ulong b2f0_result;
1607
1608 iucv_debug(2, "entering");
1609
1610 if (!buffer)
1611 return -EINVAL;
1612
1613 parm = (iparml_db *)grab_param();
1614
1615 parm->ipbfadr2 = (__u32) ((ulong) buffer);
1616 parm->ipbfln2f = (__u32) buflen; /* length of message */
1617 parm->ippathid = pathid;
1618 parm->ipmsgid = msgid;
1619 parm->iptrgcls = trgcls;
1620 parm->ipflags1 = (__u8) flags1; /* priority message */
1621
1622 b2f0_result = b2f0(REPLY, parm);
1623
1624 if ((!b2f0_result) || (b2f0_result == 5)) {
1625 if (ipbfadr2)
1626 *ipbfadr2 = parm->ipbfadr2;
1627 if (ipbfln2f)
1628 *ipbfln2f = parm->ipbfln2f;
1629 }
1630 release_param(parm);
1631
1632 iucv_debug(2, "exiting");
1633
1634 return b2f0_result;
1635}
1636
1637/*
1638 * Name: iucv_reply_array
1639 * Purpose: This function responds to the two-way messages that you
1640 * receive. You must identify completely the message to
1641 * which you wish to reply. ie, pathid, msgid, and trgcls.
1642 * The array identifies a list of addresses and lengths of
1643 * discontiguous buffers that contains the reply data.
1644 * Input: pathid - path identification number
1645 * msgid - specifies the message ID.
1646 * trgcls - specifies target class
1647 * flags1 - option for path
1648 * IPPRTY- specifies if you want to send priority message
1649 * buffer - address of array of reply buffers
1650 * buflen - total length of reply buffers
1651 * Output: ipbfadr2 - Address of buffer which IUCV is currently working on.
1652 * ipbfln2f - Contains one of the following values:
1653 * If the answer buffer is the same length as the reply, this field
1654 * contains zero.
1655 * If the answer buffer is longer than the reply, this field contains
1656 * the number of bytes remaining in the buffer.
1657 * If the answer buffer is shorter than the reply, this field contains
1658 * a residual count (that is, the number of bytes remianing in the
1659 * reply that does not fit into the buffer. In this
1660 * case b2f0_result = 5.
1661 * Return: b2f0_result - return code from CP
1662 * (-EINVAL) - buffer address is NULL
1663*/
1664int
1665iucv_reply_array (__u16 pathid,
1666 __u32 msgid, __u32 trgcls,
1667 int flags1,
1668 iucv_array_t * buffer,
1669 ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
1670{
1671 iparml_db *parm;
1672 ulong b2f0_result;
1673
1674 iucv_debug(2, "entering");
1675
1676 if (!buffer)
1677 return -EINVAL;
1678
1679 parm = (iparml_db *)grab_param();
1680
1681 parm->ipbfadr2 = (__u32) ((ulong) buffer);
1682 parm->ipbfln2f = buflen; /* length of message */
1683 parm->ippathid = pathid;
1684 parm->ipmsgid = msgid;
1685 parm->iptrgcls = trgcls;
1686 parm->ipflags1 = (IPANSLST | flags1);
1687
1688 b2f0_result = b2f0(REPLY, parm);
1689
1690 if ((!b2f0_result) || (b2f0_result == 5)) {
1691
1692 if (ipbfadr2)
1693 *ipbfadr2 = parm->ipbfadr2;
1694 if (ipbfln2f)
1695 *ipbfln2f = parm->ipbfln2f;
1696 }
1697 release_param(parm);
1698
1699 iucv_debug(2, "exiting");
1700
1701 return b2f0_result;
1702}
1703
1704/*
1705 * Name: iucv_reply_prmmsg
1706 * Purpose: This function responds to the two-way messages that you
1707 * receive. You must identify completely the message to
1708 * which you wish to reply. ie, pathid, msgid, and trgcls.
1709 * Prmmsg signifies the data is moved into the
1710 * parameter list.
1711 * Input: pathid - path identification number
1712 * msgid - specifies the message ID.
1713 * trgcls - specifies target class
1714 * flags1 - option for path
1715 * IPPRTY- specifies if you want to send priority message
1716 * prmmsg - 8-bytes of data to be placed into the parameter
1717 * list.
1718 * Output: NA
1719 * Return: b2f0_result - return code from CP
1720*/
1721int
1722iucv_reply_prmmsg (__u16 pathid,
1723 __u32 msgid, __u32 trgcls, int flags1, __u8 prmmsg[8])
1724{
1725 iparml_dpl *parm;
1726 ulong b2f0_result;
1727
1728 iucv_debug(2, "entering");
1729
1730 parm = (iparml_dpl *)grab_param();
1731
1732 parm->ippathid = pathid;
1733 parm->ipmsgid = msgid;
1734 parm->iptrgcls = trgcls;
1735 memcpy(parm->iprmmsg, prmmsg, sizeof (parm->iprmmsg));
1736 parm->ipflags1 = (IPRMDATA | flags1);
1737
1738 b2f0_result = b2f0(REPLY, parm);
1739 release_param(parm);
1740
1741 iucv_debug(2, "exiting");
1742
1743 return b2f0_result;
1744}
1745
1746/**
1747 * iucv_resume:
1748 * @pathid: Path identification number
1749 * @user_data: 16-byte of user data
1750 *
1751 * This function restores communication over a quiesced path.
1752 * Returns: return code from CP
1753 */
1754int
1755iucv_resume (__u16 pathid, __u8 user_data[16])
1756{
1757 iparml_control *parm;
1758 ulong b2f0_result = 0;
1759
1760 iucv_debug(1, "entering");
1761 iucv_debug(1, "pathid = %d", pathid);
1762
1763 parm = (iparml_control *)grab_param();
1764
1765 memcpy (parm->ipuser, user_data, sizeof (*user_data));
1766 parm->ippathid = pathid;
1767
1768 b2f0_result = b2f0(RESUME, parm);
1769 release_param(parm);
1770
1771 iucv_debug(1, "exiting");
1772
1773 return b2f0_result;
1774}
1775
1776/*
1777 * Name: iucv_send
1778 * Purpose: sends messages
1779 * Input: pathid - ushort, pathid
1780 * msgid - ulong *, id of message returned to caller
1781 * trgcls - ulong, target message class
1782 * srccls - ulong, source message class
1783 * msgtag - ulong, message tag
1784 * flags1 - Contains options for this path.
1785 * IPPRTY - Ox20 - specifies if you want to send a priority message.
1786 * buffer - pointer to buffer
1787 * buflen - ulong, length of buffer
1788 * Output: b2f0_result - return code from b2f0 call
1789 * msgid - returns message id
1790 */
1791int
1792iucv_send (__u16 pathid, __u32 * msgid,
1793 __u32 trgcls, __u32 srccls,
1794 __u32 msgtag, int flags1, void *buffer, ulong buflen)
1795{
1796 iparml_db *parm;
1797 ulong b2f0_result;
1798
1799 iucv_debug(2, "entering");
1800
1801 if (!buffer)
1802 return -EINVAL;
1803
1804 parm = (iparml_db *)grab_param();
1805
1806 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1807 parm->ippathid = pathid;
1808 parm->iptrgcls = trgcls;
1809 parm->ipbfln1f = (__u32) buflen; /* length of message */
1810 parm->ipsrccls = srccls;
1811 parm->ipmsgtag = msgtag;
1812 parm->ipflags1 = (IPNORPY | flags1); /* one way priority message */
1813
1814 b2f0_result = b2f0(SEND, parm);
1815
1816 if ((!b2f0_result) && (msgid))
1817 *msgid = parm->ipmsgid;
1818 release_param(parm);
1819
1820 iucv_debug(2, "exiting");
1821
1822 return b2f0_result;
1823}
1824
1825/*
1826 * Name: iucv_send_array
1827 * Purpose: This function transmits data to another application.
1828 * The contents of buffer is the address of the array of
1829 * addresses and lengths of discontiguous buffers that hold
1830 * the message text. This is a one-way message and the
1831 * receiver will not reply to the message.
1832 * Input: pathid - path identification number
1833 * trgcls - specifies target class
1834 * srccls - specifies the source message class
1835 * msgtag - specifies a tag to be associated witht the message
1836 * flags1 - option for path
1837 * IPPRTY- specifies if you want to send priority message
1838 * buffer - address of array of send buffers
1839 * buflen - total length of send buffers
1840 * Output: msgid - specifies the message ID.
1841 * Return: b2f0_result - return code from CP
1842 * (-EINVAL) - buffer address is NULL
1843 */
1844int
1845iucv_send_array (__u16 pathid,
1846 __u32 * msgid,
1847 __u32 trgcls,
1848 __u32 srccls,
1849 __u32 msgtag, int flags1, iucv_array_t * buffer, ulong buflen)
1850{
1851 iparml_db *parm;
1852 ulong b2f0_result;
1853
1854 iucv_debug(2, "entering");
1855
1856 if (!buffer)
1857 return -EINVAL;
1858
1859 parm = (iparml_db *)grab_param();
1860
1861 parm->ippathid = pathid;
1862 parm->iptrgcls = trgcls;
1863 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1864 parm->ipbfln1f = (__u32) buflen; /* length of message */
1865 parm->ipsrccls = srccls;
1866 parm->ipmsgtag = msgtag;
1867 parm->ipflags1 = (IPNORPY | IPBUFLST | flags1);
1868 b2f0_result = b2f0(SEND, parm);
1869
1870 if ((!b2f0_result) && (msgid))
1871 *msgid = parm->ipmsgid;
1872 release_param(parm);
1873
1874 iucv_debug(2, "exiting");
1875 return b2f0_result;
1876}
1877
1878/*
1879 * Name: iucv_send_prmmsg
1880 * Purpose: This function transmits data to another application.
1881 * Prmmsg specifies that the 8-bytes of data are to be moved
1882 * into the parameter list. This is a one-way message and the
1883 * receiver will not reply to the message.
1884 * Input: pathid - path identification number
1885 * trgcls - specifies target class
1886 * srccls - specifies the source message class
1887 * msgtag - specifies a tag to be associated with the message
1888 * flags1 - option for path
1889 * IPPRTY- specifies if you want to send priority message
1890 * prmmsg - 8-bytes of data to be placed into parameter list
1891 * Output: msgid - specifies the message ID.
1892 * Return: b2f0_result - return code from CP
1893*/
1894int
1895iucv_send_prmmsg (__u16 pathid,
1896 __u32 * msgid,
1897 __u32 trgcls,
1898 __u32 srccls, __u32 msgtag, int flags1, __u8 prmmsg[8])
1899{
1900 iparml_dpl *parm;
1901 ulong b2f0_result;
1902
1903 iucv_debug(2, "entering");
1904
1905 parm = (iparml_dpl *)grab_param();
1906
1907 parm->ippathid = pathid;
1908 parm->iptrgcls = trgcls;
1909 parm->ipsrccls = srccls;
1910 parm->ipmsgtag = msgtag;
1911 parm->ipflags1 = (IPRMDATA | IPNORPY | flags1);
1912 memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
1913
1914 b2f0_result = b2f0(SEND, parm);
1915
1916 if ((!b2f0_result) && (msgid))
1917 *msgid = parm->ipmsgid;
1918 release_param(parm);
1919
1920 iucv_debug(2, "exiting");
1921
1922 return b2f0_result;
1923}
1924
1925/*
1926 * Name: iucv_send2way
1927 * Purpose: This function transmits data to another application.
1928 * Data to be transmitted is in a buffer. The receiver
1929 * of the send is expected to reply to the message and
1930 * a buffer is provided into which IUCV moves the reply
1931 * to this message.
1932 * Input: pathid - path identification number
1933 * trgcls - specifies target class
1934 * srccls - specifies the source message class
1935 * msgtag - specifies a tag associated with the message
1936 * flags1 - option for path
1937 * IPPRTY- specifies if you want to send priority message
1938 * buffer - address of send buffer
1939 * buflen - length of send buffer
1940 * ansbuf - address of buffer to reply with
1941 * anslen - length of buffer to reply with
1942 * Output: msgid - specifies the message ID.
1943 * Return: b2f0_result - return code from CP
1944 * (-EINVAL) - buffer or ansbuf address is NULL
1945 */
1946int
1947iucv_send2way (__u16 pathid,
1948 __u32 * msgid,
1949 __u32 trgcls,
1950 __u32 srccls,
1951 __u32 msgtag,
1952 int flags1,
1953 void *buffer, ulong buflen, void *ansbuf, ulong anslen)
1954{
1955 iparml_db *parm;
1956 ulong b2f0_result;
1957
1958 iucv_debug(2, "entering");
1959
1960 if (!buffer || !ansbuf)
1961 return -EINVAL;
1962
1963 parm = (iparml_db *)grab_param();
1964
1965 parm->ippathid = pathid;
1966 parm->iptrgcls = trgcls;
1967 parm->ipbfadr1 = (__u32) ((ulong) buffer);
1968 parm->ipbfln1f = (__u32) buflen; /* length of message */
1969 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
1970 parm->ipbfln2f = (__u32) anslen;
1971 parm->ipsrccls = srccls;
1972 parm->ipmsgtag = msgtag;
1973 parm->ipflags1 = flags1; /* priority message */
1974
1975 b2f0_result = b2f0(SEND, parm);
1976
1977 if ((!b2f0_result) && (msgid))
1978 *msgid = parm->ipmsgid;
1979 release_param(parm);
1980
1981 iucv_debug(2, "exiting");
1982
1983 return b2f0_result;
1984}
1985
1986/*
1987 * Name: iucv_send2way_array
1988 * Purpose: This function transmits data to another application.
1989 * The contents of buffer is the address of the array of
1990 * addresses and lengths of discontiguous buffers that hold
1991 * the message text. The receiver of the send is expected to
1992 * reply to the message and a buffer is provided into which
1993 * IUCV moves the reply to this message.
1994 * Input: pathid - path identification number
1995 * trgcls - specifies target class
1996 * srccls - specifies the source message class
1997 * msgtag - spcifies a tag to be associated with the message
1998 * flags1 - option for path
1999 * IPPRTY- specifies if you want to send priority message
2000 * buffer - address of array of send buffers
2001 * buflen - total length of send buffers
2002 * ansbuf - address of buffer to reply with
2003 * anslen - length of buffer to reply with
2004 * Output: msgid - specifies the message ID.
2005 * Return: b2f0_result - return code from CP
2006 * (-EINVAL) - buffer address is NULL
2007 */
2008int
2009iucv_send2way_array (__u16 pathid,
2010 __u32 * msgid,
2011 __u32 trgcls,
2012 __u32 srccls,
2013 __u32 msgtag,
2014 int flags1,
2015 iucv_array_t * buffer,
2016 ulong buflen, iucv_array_t * ansbuf, ulong anslen)
2017{
2018 iparml_db *parm;
2019 ulong b2f0_result;
2020
2021 iucv_debug(2, "entering");
2022
2023 if (!buffer || !ansbuf)
2024 return -EINVAL;
2025
2026 parm = (iparml_db *)grab_param();
2027
2028 parm->ippathid = pathid;
2029 parm->iptrgcls = trgcls;
2030 parm->ipbfadr1 = (__u32) ((ulong) buffer);
2031 parm->ipbfln1f = (__u32) buflen; /* length of message */
2032 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
2033 parm->ipbfln2f = (__u32) anslen;
2034 parm->ipsrccls = srccls;
2035 parm->ipmsgtag = msgtag;
2036 parm->ipflags1 = (IPBUFLST | IPANSLST | flags1);
2037 b2f0_result = b2f0(SEND, parm);
2038 if ((!b2f0_result) && (msgid))
2039 *msgid = parm->ipmsgid;
2040 release_param(parm);
2041
2042 iucv_debug(2, "exiting");
2043 return b2f0_result;
2044}
2045
2046/*
2047 * Name: iucv_send2way_prmmsg
2048 * Purpose: This function transmits data to another application.
2049 * Prmmsg specifies that the 8-bytes of data are to be moved
2050 * into the parameter list. This is a two-way message and the
2051 * receiver of the message is expected to reply. A buffer
2052 * is provided into which IUCV moves the reply to this
2053 * message.
2054 * Input: pathid - path identification number
2055 * trgcls - specifies target class
2056 * srccls - specifies the source message class
2057 * msgtag - specifies a tag to be associated with the message
2058 * flags1 - option for path
2059 * IPPRTY- specifies if you want to send priority message
2060 * prmmsg - 8-bytes of data to be placed in parameter list
2061 * ansbuf - address of buffer to reply with
2062 * anslen - length of buffer to reply with
2063 * Output: msgid - specifies the message ID.
2064 * Return: b2f0_result - return code from CP
2065 * (-EINVAL) - buffer address is NULL
2066*/
2067int
2068iucv_send2way_prmmsg (__u16 pathid,
2069 __u32 * msgid,
2070 __u32 trgcls,
2071 __u32 srccls,
2072 __u32 msgtag,
2073 ulong flags1, __u8 prmmsg[8], void *ansbuf, ulong anslen)
2074{
2075 iparml_dpl *parm;
2076 ulong b2f0_result;
2077
2078 iucv_debug(2, "entering");
2079
2080 if (!ansbuf)
2081 return -EINVAL;
2082
2083 parm = (iparml_dpl *)grab_param();
2084
2085 parm->ippathid = pathid;
2086 parm->iptrgcls = trgcls;
2087 parm->ipsrccls = srccls;
2088 parm->ipmsgtag = msgtag;
2089 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
2090 parm->ipbfln2f = (__u32) anslen;
2091 parm->ipflags1 = (IPRMDATA | flags1); /* message in prmlist */
2092 memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
2093
2094 b2f0_result = b2f0(SEND, parm);
2095
2096 if ((!b2f0_result) && (msgid))
2097 *msgid = parm->ipmsgid;
2098 release_param(parm);
2099
2100 iucv_debug(2, "exiting");
2101
2102 return b2f0_result;
2103}
2104
2105/*
2106 * Name: iucv_send2way_prmmsg_array
2107 * Purpose: This function transmits data to another application.
2108 * Prmmsg specifies that the 8-bytes of data are to be moved
2109 * into the parameter list. This is a two-way message and the
2110 * receiver of the message is expected to reply. A buffer
2111 * is provided into which IUCV moves the reply to this
2112 * message. The contents of ansbuf is the address of the
2113 * array of addresses and lengths of discontiguous buffers
2114 * that contain the reply.
2115 * Input: pathid - path identification number
2116 * trgcls - specifies target class
2117 * srccls - specifies the source message class
2118 * msgtag - specifies a tag to be associated with the message
2119 * flags1 - option for path
2120 * IPPRTY- specifies if you want to send priority message
2121 * prmmsg - 8-bytes of data to be placed into the parameter list
2122 * ansbuf - address of buffer to reply with
2123 * anslen - length of buffer to reply with
2124 * Output: msgid - specifies the message ID.
2125 * Return: b2f0_result - return code from CP
2126 * (-EINVAL) - ansbuf address is NULL
2127 */
2128int
2129iucv_send2way_prmmsg_array (__u16 pathid,
2130 __u32 * msgid,
2131 __u32 trgcls,
2132 __u32 srccls,
2133 __u32 msgtag,
2134 int flags1,
2135 __u8 prmmsg[8],
2136 iucv_array_t * ansbuf, ulong anslen)
2137{
2138 iparml_dpl *parm;
2139 ulong b2f0_result;
2140
2141 iucv_debug(2, "entering");
2142
2143 if (!ansbuf)
2144 return -EINVAL;
2145
2146 parm = (iparml_dpl *)grab_param();
2147
2148 parm->ippathid = pathid;
2149 parm->iptrgcls = trgcls;
2150 parm->ipsrccls = srccls;
2151 parm->ipmsgtag = msgtag;
2152 parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
2153 parm->ipbfln2f = (__u32) anslen;
2154 parm->ipflags1 = (IPRMDATA | IPANSLST | flags1);
2155 memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
2156 b2f0_result = b2f0(SEND, parm);
2157 if ((!b2f0_result) && (msgid))
2158 *msgid = parm->ipmsgid;
2159 release_param(parm);
2160
2161 iucv_debug(2, "exiting");
2162 return b2f0_result;
2163}
2164
2165void
2166iucv_setmask_cpuid (void *result)
2167{
2168 iparml_set_mask *parm;
2169
2170 iucv_debug(1, "entering");
2171 parm = (iparml_set_mask *)grab_param();
2172 parm->ipmask = *((__u8*)result);
2173 *((ulong *)result) = b2f0(SETMASK, parm);
2174 release_param(parm);
2175
2176 iucv_debug(1, "b2f0_result = %ld", *((ulong *)result));
2177 iucv_debug(1, "exiting");
2178}
2179
2180/*
2181 * Name: iucv_setmask
2182 * Purpose: This function enables or disables the following IUCV
2183 * external interruptions: Nonpriority and priority message
2184 * interrupts, nonpriority and priority reply interrupts.
2185 * Input: SetMaskFlag - options for interrupts
2186 * 0x80 - Nonpriority_MessagePendingInterruptsFlag
2187 * 0x40 - Priority_MessagePendingInterruptsFlag
2188 * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
2189 * 0x10 - Priority_MessageCompletionInterruptsFlag
2190 * 0x08 - IUCVControlInterruptsFlag
2191 * Output: NA
2192 * Return: b2f0_result - return code from CP
2193*/
2194int
2195iucv_setmask (int SetMaskFlag)
2196{
2197 union {
2198 ulong result;
2199 __u8 param;
2200 } u;
2201 int cpu;
2202
2203 u.param = SetMaskFlag;
2204 cpu = get_cpu();
2205 smp_call_function_on(iucv_setmask_cpuid, &u, 0, 1, iucv_cpuid);
2206 put_cpu();
2207
2208 return u.result;
2209}
2210
2211/**
2212 * iucv_sever:
2213 * @pathid: Path identification number
2214 * @user_data: 16-byte of user data
2215 *
2216 * This function terminates an iucv path.
2217 * Returns: return code from CP
2218 */
2219int
2220iucv_sever(__u16 pathid, __u8 user_data[16])
2221{
2222 iparml_control *parm;
2223 ulong b2f0_result = 0;
2224
2225 iucv_debug(1, "entering");
2226 parm = (iparml_control *)grab_param();
2227
2228 memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
2229 parm->ippathid = pathid;
2230
2231 b2f0_result = b2f0(SEVER, parm);
2232
2233 if (!b2f0_result)
2234 iucv_remove_pathid(pathid);
2235 release_param(parm);
2236
2237 iucv_debug(1, "exiting");
2238 return b2f0_result;
2239}
2240
2241/*
2242 * Interrupt Handlers
2243 *******************************************************************************/
2244
2245/**
2246 * iucv_irq_handler:
2247 * @regs: Current registers
2248 * @code: irq code
2249 *
2250 * Handles external interrupts coming in from CP.
2251 * Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
2252 */
2253static void
2254iucv_irq_handler(__u16 code)
2255{
2256 iucv_irqdata *irqdata;
2257
2258 irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC);
2259 if (!irqdata) {
2260 printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
2261 return;
2262 }
2263
2264 memcpy(&irqdata->data, iucv_external_int_buffer,
2265 sizeof(iucv_GeneralInterrupt));
2266
2267 spin_lock(&iucv_irq_queue_lock);
2268 list_add_tail(&irqdata->queue, &iucv_irq_queue);
2269 spin_unlock(&iucv_irq_queue_lock);
2270
2271 tasklet_schedule(&iucv_tasklet);
2272}
2273
2274/**
2275 * iucv_do_int:
2276 * @int_buf: Pointer to copy of external interrupt buffer
2277 *
2278 * The workhorse for handling interrupts queued by iucv_irq_handler().
2279 * This function is called from the bottom half iucv_tasklet_handler().
2280 */
2281static void
2282iucv_do_int(iucv_GeneralInterrupt * int_buf)
2283{
2284 handler *h = NULL;
2285 struct list_head *lh;
2286 ulong flags;
2287 iucv_interrupt_ops_t *interrupt = NULL; /* interrupt addresses */
2288 __u8 temp_buff1[24], temp_buff2[24]; /* masked handler id. */
2289 int rc = 0, j = 0;
2290 __u8 no_listener[16] = "NO LISTENER";
2291
2292 iucv_debug(2, "entering, pathid %d, type %02X",
2293 int_buf->ippathid, int_buf->iptype);
2294 iucv_dumpit("External Interrupt Buffer:",
2295 int_buf, sizeof(iucv_GeneralInterrupt));
2296
2297 ASCEBC (no_listener, 16);
2298
2299 if (int_buf->iptype != 01) {
2300 if ((int_buf->ippathid) > (max_connections - 1)) {
2301 printk(KERN_WARNING "%s: Got interrupt with pathid %d"
2302 " > max_connections (%ld)\n", __FUNCTION__,
2303 int_buf->ippathid, max_connections - 1);
2304 } else {
2305 h = iucv_pathid_table[int_buf->ippathid];
2306 interrupt = h->interrupt_table;
2307 iucv_dumpit("Handler:", h, sizeof(handler));
2308 }
2309 }
2310
2311 /* end of if statement */
2312 switch (int_buf->iptype) {
2313 case 0x01: /* connection pending */
2314 if (messagesDisabled) {
2315 iucv_setmask(~0);
2316 messagesDisabled = 0;
2317 }
2318 spin_lock_irqsave(&iucv_lock, flags);
2319 list_for_each(lh, &iucv_handler_table) {
2320 h = list_entry(lh, handler, list);
2321 memcpy(temp_buff1, &(int_buf->ipvmid), 24);
2322 memcpy(temp_buff2, &(h->id.userid), 24);
2323 for (j = 0; j < 24; j++) {
2324 temp_buff1[j] &= (h->id.mask)[j];
2325 temp_buff2[j] &= (h->id.mask)[j];
2326 }
2327
2328 iucv_dumpit("temp_buff1:",
2329 temp_buff1, sizeof(temp_buff1));
2330 iucv_dumpit("temp_buff2",
2331 temp_buff2, sizeof(temp_buff2));
2332
2333 if (!memcmp (temp_buff1, temp_buff2, 24)) {
2334
2335 iucv_debug(2,
2336 "found a matching handler");
2337 break;
2338 } else
2339 h = NULL;
2340 }
2341 spin_unlock_irqrestore (&iucv_lock, flags);
2342 if (h) {
2343 /* ADD PATH TO PATHID TABLE */
2344 rc = iucv_add_pathid(int_buf->ippathid, h);
2345 if (rc) {
2346 iucv_sever (int_buf->ippathid,
2347 no_listener);
2348 iucv_debug(1,
2349 "add_pathid failed, rc = %d",
2350 rc);
2351 } else {
2352 interrupt = h->interrupt_table;
2353 if (interrupt->ConnectionPending) {
2354 EBCASC (int_buf->ipvmid, 8);
2355 interrupt->ConnectionPending(
2356 (iucv_ConnectionPending *)int_buf,
2357 h->pgm_data);
2358 } else
2359 iucv_sever(int_buf->ippathid,
2360 no_listener);
2361 }
2362 } else
2363 iucv_sever(int_buf->ippathid, no_listener);
2364 break;
2365
2366 case 0x02: /*connection complete */
2367 if (messagesDisabled) {
2368 iucv_setmask(~0);
2369 messagesDisabled = 0;
2370 }
2371 if (h) {
2372 if (interrupt->ConnectionComplete)
2373 {
2374 interrupt->ConnectionComplete(
2375 (iucv_ConnectionComplete *)int_buf,
2376 h->pgm_data);
2377 }
2378 else
2379 iucv_debug(1,
2380 "ConnectionComplete not called");
2381 } else
2382 iucv_sever(int_buf->ippathid, no_listener);
2383 break;
2384
2385 case 0x03: /* connection severed */
2386 if (messagesDisabled) {
2387 iucv_setmask(~0);
2388 messagesDisabled = 0;
2389 }
2390 if (h) {
2391 if (interrupt->ConnectionSevered)
2392 interrupt->ConnectionSevered(
2393 (iucv_ConnectionSevered *)int_buf,
2394 h->pgm_data);
2395
2396 else
2397 iucv_sever (int_buf->ippathid, no_listener);
2398 } else
2399 iucv_sever(int_buf->ippathid, no_listener);
2400 break;
2401
2402 case 0x04: /* connection quiesced */
2403 if (messagesDisabled) {
2404 iucv_setmask(~0);
2405 messagesDisabled = 0;
2406 }
2407 if (h) {
2408 if (interrupt->ConnectionQuiesced)
2409 interrupt->ConnectionQuiesced(
2410 (iucv_ConnectionQuiesced *)int_buf,
2411 h->pgm_data);
2412 else
2413 iucv_debug(1,
2414 "ConnectionQuiesced not called");
2415 }
2416 break;
2417
2418 case 0x05: /* connection resumed */
2419 if (messagesDisabled) {
2420 iucv_setmask(~0);
2421 messagesDisabled = 0;
2422 }
2423 if (h) {
2424 if (interrupt->ConnectionResumed)
2425 interrupt->ConnectionResumed(
2426 (iucv_ConnectionResumed *)int_buf,
2427 h->pgm_data);
2428 else
2429 iucv_debug(1,
2430 "ConnectionResumed not called");
2431 }
2432 break;
2433
2434 case 0x06: /* priority message complete */
2435 case 0x07: /* nonpriority message complete */
2436 if (h) {
2437 if (interrupt->MessageComplete)
2438 interrupt->MessageComplete(
2439 (iucv_MessageComplete *)int_buf,
2440 h->pgm_data);
2441 else
2442 iucv_debug(2,
2443 "MessageComplete not called");
2444 }
2445 break;
2446
2447 case 0x08: /* priority message pending */
2448 case 0x09: /* nonpriority message pending */
2449 if (h) {
2450 if (interrupt->MessagePending)
2451 interrupt->MessagePending(
2452 (iucv_MessagePending *) int_buf,
2453 h->pgm_data);
2454 else
2455 iucv_debug(2,
2456 "MessagePending not called");
2457 }
2458 break;
2459 default: /* unknown iucv type */
2460 printk(KERN_WARNING "%s: unknown iucv interrupt\n",
2461 __FUNCTION__);
2462 break;
2463 } /* end switch */
2464
2465 iucv_debug(2, "exiting pathid %d, type %02X",
2466 int_buf->ippathid, int_buf->iptype);
2467
2468 return;
2469}
2470
2471/**
2472 * iucv_tasklet_handler:
2473 *
2474 * This function loops over the queue of irq buffers and runs iucv_do_int()
2475 * on every queue element.
2476 */
2477static void
2478iucv_tasklet_handler(unsigned long ignored)
2479{
2480 struct list_head head;
2481 struct list_head *next;
2482 ulong flags;
2483
2484 spin_lock_irqsave(&iucv_irq_queue_lock, flags);
2485 list_add(&head, &iucv_irq_queue);
2486 list_del_init(&iucv_irq_queue);
2487 spin_unlock_irqrestore (&iucv_irq_queue_lock, flags);
2488
2489 next = head.next;
2490 while (next != &head) {
2491 iucv_irqdata *p = list_entry(next, iucv_irqdata, queue);
2492
2493 next = next->next;
2494 iucv_do_int(&p->data);
2495 kfree(p);
2496 }
2497
2498 return;
2499}
2500
2501subsys_initcall(iucv_init);
2502module_exit(iucv_exit);
2503
2504/**
2505 * Export all public stuff
2506 */
2507EXPORT_SYMBOL (iucv_bus);
2508EXPORT_SYMBOL (iucv_root);
2509EXPORT_SYMBOL (iucv_accept);
2510EXPORT_SYMBOL (iucv_connect);
2511#if 0
2512EXPORT_SYMBOL (iucv_purge);
2513EXPORT_SYMBOL (iucv_query_maxconn);
2514EXPORT_SYMBOL (iucv_query_bufsize);
2515EXPORT_SYMBOL (iucv_quiesce);
2516#endif
2517EXPORT_SYMBOL (iucv_receive);
2518#if 0
2519EXPORT_SYMBOL (iucv_receive_array);
2520#endif
2521EXPORT_SYMBOL (iucv_reject);
2522#if 0
2523EXPORT_SYMBOL (iucv_reply);
2524EXPORT_SYMBOL (iucv_reply_array);
2525EXPORT_SYMBOL (iucv_resume);
2526#endif
2527EXPORT_SYMBOL (iucv_reply_prmmsg);
2528EXPORT_SYMBOL (iucv_send);
2529EXPORT_SYMBOL (iucv_send2way);
2530EXPORT_SYMBOL (iucv_send2way_array);
2531EXPORT_SYMBOL (iucv_send2way_prmmsg);
2532EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
2533#if 0
2534EXPORT_SYMBOL (iucv_send_array);
2535EXPORT_SYMBOL (iucv_send_prmmsg);
2536EXPORT_SYMBOL (iucv_setmask);
2537#endif
2538EXPORT_SYMBOL (iucv_sever);
2539EXPORT_SYMBOL (iucv_register_program);
2540EXPORT_SYMBOL (iucv_unregister_program);
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
deleted file mode 100644
index 5b6b1b7241c9..000000000000
--- a/drivers/s390/net/iucv.h
+++ /dev/null
@@ -1,849 +0,0 @@
1/*
2 * drivers/s390/net/iucv.h
3 * IUCV base support.
4 *
5 * S390 version
6 * Copyright (C) 2000 IBM Corporation
7 * Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
8 * Xenia Tkatschow (xenia@us.ibm.com)
9 *
10 *
11 * Functionality:
12 * To explore any of the IUCV functions, one must first register
13 * their program using iucv_register_program(). Once your program has
14 * successfully completed a register, it can exploit the other functions.
15 * For furthur reference on all IUCV functionality, refer to the
16 * CP Programming Services book, also available on the web
17 * thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
18 *
19 * Definition of Return Codes
20 * -All positive return codes including zero are reflected back
21 * from CP except for iucv_register_program. The definition of each
22 * return code can be found in CP Programming Services book.
23 * Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
24 * - Return Code of:
25 * (-EINVAL) Invalid value
26 * (-ENOMEM) storage allocation failed
27 * pgmask defined in iucv_register_program will be set depending on input
28 * paramters.
29 *
30 */
31
32#include <linux/types.h>
33#include <asm/debug.h>
34
35/**
36 * Debug Facility stuff
37 */
38#define IUCV_DBF_SETUP_NAME "iucv_setup"
39#define IUCV_DBF_SETUP_LEN 32
40#define IUCV_DBF_SETUP_PAGES 2
41#define IUCV_DBF_SETUP_NR_AREAS 1
42#define IUCV_DBF_SETUP_LEVEL 3
43
44#define IUCV_DBF_DATA_NAME "iucv_data"
45#define IUCV_DBF_DATA_LEN 128
46#define IUCV_DBF_DATA_PAGES 2
47#define IUCV_DBF_DATA_NR_AREAS 1
48#define IUCV_DBF_DATA_LEVEL 2
49
50#define IUCV_DBF_TRACE_NAME "iucv_trace"
51#define IUCV_DBF_TRACE_LEN 16
52#define IUCV_DBF_TRACE_PAGES 4
53#define IUCV_DBF_TRACE_NR_AREAS 1
54#define IUCV_DBF_TRACE_LEVEL 3
55
56#define IUCV_DBF_TEXT(name,level,text) \
57 do { \
58 debug_text_event(iucv_dbf_##name,level,text); \
59 } while (0)
60
61#define IUCV_DBF_HEX(name,level,addr,len) \
62 do { \
63 debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
64 } while (0)
65
66DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
67
68#define IUCV_DBF_TEXT_(name,level,text...) \
69 do { \
70 char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf); \
71 sprintf(iucv_dbf_txt_buf, text); \
72 debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
73 put_cpu_var(iucv_dbf_txt_buf); \
74 } while (0)
75
76#define IUCV_DBF_SPRINTF(name,level,text...) \
77 do { \
78 debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
79 debug_sprintf_event(iucv_dbf_trace, level, text ); \
80 } while (0)
81
82/**
83 * some more debug stuff
84 */
85#define IUCV_HEXDUMP16(importance,header,ptr) \
86PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
87 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
88 *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
89 *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
90 *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
91 *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
92 *(((char*)ptr)+12),*(((char*)ptr)+13), \
93 *(((char*)ptr)+14),*(((char*)ptr)+15)); \
94PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
95 "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
96 *(((char*)ptr)+16),*(((char*)ptr)+17), \
97 *(((char*)ptr)+18),*(((char*)ptr)+19), \
98 *(((char*)ptr)+20),*(((char*)ptr)+21), \
99 *(((char*)ptr)+22),*(((char*)ptr)+23), \
100 *(((char*)ptr)+24),*(((char*)ptr)+25), \
101 *(((char*)ptr)+26),*(((char*)ptr)+27), \
102 *(((char*)ptr)+28),*(((char*)ptr)+29), \
103 *(((char*)ptr)+30),*(((char*)ptr)+31));
104
105static inline void
106iucv_hex_dump(unsigned char *buf, size_t len)
107{
108 size_t i;
109
110 for (i = 0; i < len; i++) {
111 if (i && !(i % 16))
112 printk("\n");
113 printk("%02x ", *(buf + i));
114 }
115 printk("\n");
116}
117/**
118 * end of debug stuff
119 */
120
121#define uchar unsigned char
122#define ushort unsigned short
123#define ulong unsigned long
124#define iucv_handle_t void *
125
126/* flags1:
127 * All flags are defined in the field IPFLAGS1 of each function
128 * and can be found in CP Programming Services.
129 * IPLOCAL - Indicates the connect can only be satisfied on the
130 * local system
131 * IPPRTY - Indicates a priority message
132 * IPQUSCE - Indicates you do not want to receive messages on a
133 * path until an iucv_resume is issued
134 * IPRMDATA - Indicates that the message is in the parameter list
135 */
136#define IPLOCAL 0x01
137#define IPPRTY 0x20
138#define IPQUSCE 0x40
139#define IPRMDATA 0x80
140
141/* flags1_out:
142 * All flags are defined in the output field of IPFLAGS1 for each function
143 * and can be found in CP Programming Services.
144 * IPNORPY - Specifies this is a one-way message and no reply is expected.
145 * IPPRTY - Indicates a priority message is permitted. Defined in flags1.
146 */
147#define IPNORPY 0x10
148
149#define Nonpriority_MessagePendingInterruptsFlag 0x80
150#define Priority_MessagePendingInterruptsFlag 0x40
151#define Nonpriority_MessageCompletionInterruptsFlag 0x20
152#define Priority_MessageCompletionInterruptsFlag 0x10
153#define IUCVControlInterruptsFlag 0x08
154#define AllInterrupts 0xf8
155/*
156 * Mapping of external interrupt buffers should be used with the corresponding
157 * interrupt types.
158 * Names: iucv_ConnectionPending -> connection pending
159 * iucv_ConnectionComplete -> connection complete
160 * iucv_ConnectionSevered -> connection severed
161 * iucv_ConnectionQuiesced -> connection quiesced
162 * iucv_ConnectionResumed -> connection resumed
163 * iucv_MessagePending -> message pending
164 * iucv_MessageComplete -> message complete
165 */
166typedef struct {
167 u16 ippathid;
168 uchar ipflags1;
169 uchar iptype;
170 u16 ipmsglim;
171 u16 res1;
172 uchar ipvmid[8];
173 uchar ipuser[16];
174 u32 res3;
175 uchar ippollfg;
176 uchar res4[3];
177} iucv_ConnectionPending;
178
179typedef struct {
180 u16 ippathid;
181 uchar ipflags1;
182 uchar iptype;
183 u16 ipmsglim;
184 u16 res1;
185 uchar res2[8];
186 uchar ipuser[16];
187 u32 res3;
188 uchar ippollfg;
189 uchar res4[3];
190} iucv_ConnectionComplete;
191
192typedef struct {
193 u16 ippathid;
194 uchar res1;
195 uchar iptype;
196 u32 res2;
197 uchar res3[8];
198 uchar ipuser[16];
199 u32 res4;
200 uchar ippollfg;
201 uchar res5[3];
202} iucv_ConnectionSevered;
203
204typedef struct {
205 u16 ippathid;
206 uchar res1;
207 uchar iptype;
208 u32 res2;
209 uchar res3[8];
210 uchar ipuser[16];
211 u32 res4;
212 uchar ippollfg;
213 uchar res5[3];
214} iucv_ConnectionQuiesced;
215
216typedef struct {
217 u16 ippathid;
218 uchar res1;
219 uchar iptype;
220 u32 res2;
221 uchar res3[8];
222 uchar ipuser[16];
223 u32 res4;
224 uchar ippollfg;
225 uchar res5[3];
226} iucv_ConnectionResumed;
227
228typedef struct {
229 u16 ippathid;
230 uchar ipflags1;
231 uchar iptype;
232 u32 ipmsgid;
233 u32 iptrgcls;
234 union u2 {
235 u32 iprmmsg1_u32;
236 uchar iprmmsg1[4];
237 } ln1msg1;
238 union u1 {
239 u32 ipbfln1f;
240 uchar iprmmsg2[4];
241 } ln1msg2;
242 u32 res1[3];
243 u32 ipbfln2f;
244 uchar ippollfg;
245 uchar res2[3];
246} iucv_MessagePending;
247
248typedef struct {
249 u16 ippathid;
250 uchar ipflags1;
251 uchar iptype;
252 u32 ipmsgid;
253 u32 ipaudit;
254 uchar iprmmsg[8];
255 u32 ipsrccls;
256 u32 ipmsgtag;
257 u32 res;
258 u32 ipbfln2f;
259 uchar ippollfg;
260 uchar res2[3];
261} iucv_MessageComplete;
262
263/*
264 * iucv_interrupt_ops_t: Is a vector of functions that handle
265 * IUCV interrupts.
266 * Parameter list:
267 * eib - is a pointer to a 40-byte area described
268 * with one of the structures above.
269 * pgm_data - this data is strictly for the
270 * interrupt handler that is passed by
271 * the application. This may be an address
272 * or token.
273*/
274typedef struct {
275 void (*ConnectionPending) (iucv_ConnectionPending * eib,
276 void *pgm_data);
277 void (*ConnectionComplete) (iucv_ConnectionComplete * eib,
278 void *pgm_data);
279 void (*ConnectionSevered) (iucv_ConnectionSevered * eib,
280 void *pgm_data);
281 void (*ConnectionQuiesced) (iucv_ConnectionQuiesced * eib,
282 void *pgm_data);
283 void (*ConnectionResumed) (iucv_ConnectionResumed * eib,
284 void *pgm_data);
285 void (*MessagePending) (iucv_MessagePending * eib, void *pgm_data);
286 void (*MessageComplete) (iucv_MessageComplete * eib, void *pgm_data);
287} iucv_interrupt_ops_t;
288
289/*
290 *iucv_array_t : Defines buffer array.
291 * Inside the array may be 31- bit addresses and 31-bit lengths.
292*/
293typedef struct {
294 u32 address;
295 u32 length;
296} iucv_array_t __attribute__ ((aligned (8)));
297
298extern struct bus_type iucv_bus;
299extern struct device *iucv_root;
300
301/* -prototypes- */
302/*
303 * Name: iucv_register_program
304 * Purpose: Registers an application with IUCV
305 * Input: prmname - user identification
306 * userid - machine identification
307 * pgmmask - indicates which bits in the prmname and userid combined will be
308 * used to determine who is given control
309 * ops - address of vector of interrupt handlers
310 * pgm_data- application data passed to interrupt handlers
311 * Output: NA
312 * Return: address of handler
313 * (0) - Error occurred, registration not completed.
314 * NOTE: Exact cause of failure will be recorded in syslog.
315*/
316iucv_handle_t iucv_register_program (uchar pgmname[16],
317 uchar userid[8],
318 uchar pgmmask[24],
319 iucv_interrupt_ops_t * ops,
320 void *pgm_data);
321
322/*
323 * Name: iucv_unregister_program
324 * Purpose: Unregister application with IUCV
325 * Input: address of handler
326 * Output: NA
327 * Return: (0) - Normal return
328 * (-EINVAL) - Internal error, wild pointer
329*/
330int iucv_unregister_program (iucv_handle_t handle);
331
332/*
333 * Name: iucv_accept
334 * Purpose: This function is issued after the user receives a Connection Pending external
335 * interrupt and now wishes to complete the IUCV communication path.
336 * Input: pathid - u16 , Path identification number
337 * msglim_reqstd - u16, The number of outstanding messages requested.
338 * user_data - uchar[16], Data specified by the iucv_connect function.
339 * flags1 - int, Contains options for this path.
340 * -IPPRTY - 0x20- Specifies if you want to send priority message.
341 * -IPRMDATA - 0x80, Specifies whether your program can handle a message
342 * in the parameter list.
343 * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
344 * established.
345 * handle - iucv_handle_t, Address of handler.
346 * pgm_data - void *, Application data passed to interrupt handlers.
347 * flags1_out - int * Contains information about the path
348 * - IPPRTY - 0x20, Indicates you may send priority messages.
349 * msglim - *u16, Number of outstanding messages.
350 * Output: return code from CP IUCV call.
351*/
352
353int iucv_accept (u16 pathid,
354 u16 msglim_reqstd,
355 uchar user_data[16],
356 int flags1,
357 iucv_handle_t handle,
358 void *pgm_data, int *flags1_out, u16 * msglim);
359
360/*
361 * Name: iucv_connect
362 * Purpose: This function establishes an IUCV path. Although the connect may complete
363 * successfully, you are not able to use the path until you receive an IUCV
364 * Connection Complete external interrupt.
365 * Input: pathid - u16 *, Path identification number
366 * msglim_reqstd - u16, Number of outstanding messages requested
367 * user_data - uchar[16], 16-byte user data
368 * userid - uchar[8], User identification
369 * system_name - uchar[8], 8-byte identifying the system name
370 * flags1 - int, Contains options for this path.
371 * -IPPRTY - 0x20, Specifies if you want to send priority message.
372 * -IPRMDATA - 0x80, Specifies whether your program can handle a message
373 * in the parameter list.
374 * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
375 * established.
376 * -IPLOCAL - 0X01, Allows an application to force the partner to be on
377 * the local system. If local is specified then target class cannot be
378 * specified.
379 * flags1_out - int * Contains information about the path
380 * - IPPRTY - 0x20, Indicates you may send priority messages.
381 * msglim - * u16, Number of outstanding messages
382 * handle - iucv_handle_t, Address of handler
383 * pgm_data - void *, Application data passed to interrupt handlers
384 * Output: return code from CP IUCV call
385 * rc - return code from iucv_declare_buffer
386 * -EINVAL - Invalid handle passed by application
387 * -EINVAL - Pathid address is NULL
388 * add_pathid_result - Return code from internal function add_pathid
389*/
390int
391 iucv_connect (u16 * pathid,
392 u16 msglim_reqstd,
393 uchar user_data[16],
394 uchar userid[8],
395 uchar system_name[8],
396 int flags1,
397 int *flags1_out,
398 u16 * msglim, iucv_handle_t handle, void *pgm_data);
399
400/*
401 * Name: iucv_purge
402 * Purpose: This function cancels a message that you have sent.
403 * Input: pathid - Path identification number.
404 * msgid - Specifies the message ID of the message to be purged.
405 * srccls - Specifies the source message class.
406 * Output: audit - Contains information about asynchronous error
407 * that may have affected the normal completion
408 * of this message.
409 * Return: Return code from CP IUCV call.
410*/
411int iucv_purge (u16 pathid, u32 msgid, u32 srccls, __u32 *audit);
412/*
413 * Name: iucv_query_maxconn
414 * Purpose: This function determines the maximum number of communication paths you
415 * may establish.
416 * Return: maxconn - ulong, Maximum number of connection the virtual machine may
417 * establish.
418*/
419ulong iucv_query_maxconn (void);
420
421/*
422 * Name: iucv_query_bufsize
423 * Purpose: This function determines how large an external interrupt
424 * buffer IUCV requires to store information.
425 * Return: bufsize - ulong, Size of external interrupt buffer.
426 */
427ulong iucv_query_bufsize (void);
428
429/*
430 * Name: iucv_quiesce
431 * Purpose: This function temporarily suspends incoming messages on an
432 * IUCV path. You can later reactivate the path by invoking
433 * the iucv_resume function.
434 * Input: pathid - Path identification number
435 * user_data - 16-bytes of user data
436 * Output: NA
437 * Return: Return code from CP IUCV call.
438*/
439int iucv_quiesce (u16 pathid, uchar user_data[16]);
440
441/*
442 * Name: iucv_receive
443 * Purpose: This function receives messages that are being sent to you
444 * over established paths. Data will be returned in buffer for length of
445 * buflen.
446 * Input:
447 * pathid - Path identification number.
448 * buffer - Address of buffer to receive.
449 * buflen - Length of buffer to receive.
450 * msgid - Specifies the message ID.
451 * trgcls - Specifies target class.
452 * Output:
453 * flags1_out: int *, Contains information about this path.
454 * IPNORPY - 0x10 Specifies this is a one-way message and no reply is
455 * expected.
456 * IPPRTY - 0x20 Specifies if you want to send priority message.
457 * IPRMDATA - 0x80 specifies the data is contained in the parameter list
458 * residual_buffer - address of buffer updated by the number
459 * of bytes you have received.
460 * residual_length -
461 * Contains one of the following values, if the receive buffer is:
462 * The same length as the message, this field is zero.
463 * Longer than the message, this field contains the number of
464 * bytes remaining in the buffer.
465 * Shorter than the message, this field contains the residual
466 * count (that is, the number of bytes remaining in the
467 * message that does not fit into the buffer. In this
468 * case b2f0_result = 5.
469 * Return: Return code from CP IUCV call.
470 * (-EINVAL) - buffer address is pointing to NULL
471*/
472int iucv_receive (u16 pathid,
473 u32 msgid,
474 u32 trgcls,
475 void *buffer,
476 ulong buflen,
477 int *flags1_out,
478 ulong * residual_buffer, ulong * residual_length);
479
480 /*
481 * Name: iucv_receive_array
482 * Purpose: This function receives messages that are being sent to you
483 * over established paths. Data will be returned in first buffer for
484 * length of first buffer.
485 * Input: pathid - Path identification number.
486 * msgid - specifies the message ID.
487 * trgcls - Specifies target class.
488 * buffer - Address of array of buffers.
489 * buflen - Total length of buffers.
490 * Output:
491 * flags1_out: int *, Contains information about this path.
492 * IPNORPY - 0x10 Specifies this is a one-way message and no reply is
493 * expected.
494 * IPPRTY - 0x20 Specifies if you want to send priority message.
495 * IPRMDATA - 0x80 specifies the data is contained in the parameter list
496 * residual_buffer - address points to the current list entry IUCV
497 * is working on.
498 * residual_length -
499 * Contains one of the following values, if the receive buffer is:
500 * The same length as the message, this field is zero.
501 * Longer than the message, this field contains the number of
502 * bytes remaining in the buffer.
503 * Shorter than the message, this field contains the residual
504 * count (that is, the number of bytes remaining in the
505 * message that does not fit into the buffer. In this
506 * case b2f0_result = 5.
507 * Return: Return code from CP IUCV call.
508 * (-EINVAL) - Buffer address is NULL.
509 */
510int iucv_receive_array (u16 pathid,
511 u32 msgid,
512 u32 trgcls,
513 iucv_array_t * buffer,
514 ulong buflen,
515 int *flags1_out,
516 ulong * residual_buffer, ulong * residual_length);
517
518/*
519 * Name: iucv_reject
520 * Purpose: The reject function refuses a specified message. Between the
521 * time you are notified of a message and the time that you
522 * complete the message, the message may be rejected.
523 * Input: pathid - Path identification number.
524 * msgid - Specifies the message ID.
525 * trgcls - Specifies target class.
526 * Output: NA
527 * Return: Return code from CP IUCV call.
528*/
529int iucv_reject (u16 pathid, u32 msgid, u32 trgcls);
530
531/*
532 * Name: iucv_reply
533 * Purpose: This function responds to the two-way messages that you
534 * receive. You must identify completely the message to
535 * which you wish to reply. ie, pathid, msgid, and trgcls.
536 * Input: pathid - Path identification number.
537 * msgid - Specifies the message ID.
538 * trgcls - Specifies target class.
539 * flags1 - Option for path.
540 * IPPRTY- 0x20, Specifies if you want to send priority message.
541 * buffer - Address of reply buffer.
542 * buflen - Length of reply buffer.
543 * Output: residual_buffer - Address of buffer updated by the number
544 * of bytes you have moved.
545 * residual_length - Contains one of the following values:
546 * If the answer buffer is the same length as the reply, this field
547 * contains zero.
548 * If the answer buffer is longer than the reply, this field contains
549 * the number of bytes remaining in the buffer.
550 * If the answer buffer is shorter than the reply, this field contains
551 * a residual count (that is, the number of bytes remianing in the
552 * reply that does not fit into the buffer. In this
553 * case b2f0_result = 5.
554 * Return: Return code from CP IUCV call.
555 * (-EINVAL) - Buffer address is NULL.
556*/
557int iucv_reply (u16 pathid,
558 u32 msgid,
559 u32 trgcls,
560 int flags1,
561 void *buffer, ulong buflen, ulong * residual_buffer,
562 ulong * residual_length);
563
564/*
565 * Name: iucv_reply_array
566 * Purpose: This function responds to the two-way messages that you
567 * receive. You must identify completely the message to
568 * which you wish to reply. ie, pathid, msgid, and trgcls.
569 * The array identifies a list of addresses and lengths of
570 * discontiguous buffers that contains the reply data.
571 * Input: pathid - Path identification number
572 * msgid - Specifies the message ID.
573 * trgcls - Specifies target class.
574 * flags1 - Option for path.
575 * IPPRTY- 0x20, Specifies if you want to send priority message.
576 * buffer - Address of array of reply buffers.
577 * buflen - Total length of reply buffers.
578 * Output: residual_buffer - Address of buffer which IUCV is currently working on.
579 * residual_length - Contains one of the following values:
580 * If the answer buffer is the same length as the reply, this field
581 * contains zero.
582 * If the answer buffer is longer than the reply, this field contains
583 * the number of bytes remaining in the buffer.
584 * If the answer buffer is shorter than the reply, this field contains
585 * a residual count (that is, the number of bytes remianing in the
586 * reply that does not fit into the buffer. In this
587 * case b2f0_result = 5.
588 * Return: Return code from CP IUCV call.
589 * (-EINVAL) - Buffer address is NULL.
590*/
591int iucv_reply_array (u16 pathid,
592 u32 msgid,
593 u32 trgcls,
594 int flags1,
595 iucv_array_t * buffer,
596 ulong buflen, ulong * residual_address,
597 ulong * residual_length);
598
599/*
600 * Name: iucv_reply_prmmsg
601 * Purpose: This function responds to the two-way messages that you
602 * receive. You must identify completely the message to
603 * which you wish to reply. ie, pathid, msgid, and trgcls.
604 * Prmmsg signifies the data is moved into the
605 * parameter list.
606 * Input: pathid - Path identification number.
607 * msgid - Specifies the message ID.
608 * trgcls - Specifies target class.
609 * flags1 - Option for path.
610 * IPPRTY- 0x20 Specifies if you want to send priority message.
611 * prmmsg - 8-bytes of data to be placed into the parameter.
612 * list.
613 * Output: NA
614 * Return: Return code from CP IUCV call.
615*/
616int iucv_reply_prmmsg (u16 pathid,
617 u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8]);
618
619/*
620 * Name: iucv_resume
621 * Purpose: This function restores communications over a quiesced path
622 * Input: pathid - Path identification number.
623 * user_data - 16-bytes of user data.
624 * Output: NA
625 * Return: Return code from CP IUCV call.
626*/
627int iucv_resume (u16 pathid, uchar user_data[16]);
628
629/*
630 * Name: iucv_send
631 * Purpose: This function transmits data to another application.
632 * Data to be transmitted is in a buffer and this is a
633 * one-way message and the receiver will not reply to the
634 * message.
635 * Input: pathid - Path identification number.
636 * trgcls - Specifies target class.
637 * srccls - Specifies the source message class.
638 * msgtag - Specifies a tag to be associated with the message.
639 * flags1 - Option for path.
640 * IPPRTY- 0x20 Specifies if you want to send priority message.
641 * buffer - Address of send buffer.
642 * buflen - Length of send buffer.
643 * Output: msgid - Specifies the message ID.
644 * Return: Return code from CP IUCV call.
645 * (-EINVAL) - Buffer address is NULL.
646*/
647int iucv_send (u16 pathid,
648 u32 * msgid,
649 u32 trgcls,
650 u32 srccls, u32 msgtag, int flags1, void *buffer, ulong buflen);
651
652/*
653 * Name: iucv_send_array
654 * Purpose: This function transmits data to another application.
655 * The contents of buffer is the address of the array of
656 * addresses and lengths of discontiguous buffers that hold
657 * the message text. This is a one-way message and the
658 * receiver will not reply to the message.
659 * Input: pathid - Path identification number.
660 * trgcls - Specifies target class.
661 * srccls - Specifies the source message class.
662 * msgtag - Specifies a tag to be associated witht the message.
663 * flags1 - Option for path.
664 * IPPRTY- specifies if you want to send priority message.
665 * buffer - Address of array of send buffers.
666 * buflen - Total length of send buffers.
667 * Output: msgid - Specifies the message ID.
668 * Return: Return code from CP IUCV call.
669 * (-EINVAL) - Buffer address is NULL.
670*/
671int iucv_send_array (u16 pathid,
672 u32 * msgid,
673 u32 trgcls,
674 u32 srccls,
675 u32 msgtag,
676 int flags1, iucv_array_t * buffer, ulong buflen);
677
678/*
679 * Name: iucv_send_prmmsg
680 * Purpose: This function transmits data to another application.
681 * Prmmsg specifies that the 8-bytes of data are to be moved
682 * into the parameter list. This is a one-way message and the
683 * receiver will not reply to the message.
684 * Input: pathid - Path identification number.
685 * trgcls - Specifies target class.
686 * srccls - Specifies the source message class.
687 * msgtag - Specifies a tag to be associated with the message.
688 * flags1 - Option for path.
689 * IPPRTY- 0x20 specifies if you want to send priority message.
690 * prmmsg - 8-bytes of data to be placed into parameter list.
691 * Output: msgid - Specifies the message ID.
692 * Return: Return code from CP IUCV call.
693*/
694int iucv_send_prmmsg (u16 pathid,
695 u32 * msgid,
696 u32 trgcls,
697 u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8]);
698
699/*
700 * Name: iucv_send2way
701 * Purpose: This function transmits data to another application.
702 * Data to be transmitted is in a buffer. The receiver
703 * of the send is expected to reply to the message and
704 * a buffer is provided into which IUCV moves the reply
705 * to this message.
706 * Input: pathid - Path identification number.
707 * trgcls - Specifies target class.
708 * srccls - Specifies the source message class.
709 * msgtag - Specifies a tag associated with the message.
710 * flags1 - Option for path.
711 * IPPRTY- 0x20 Specifies if you want to send priority message.
712 * buffer - Address of send buffer.
713 * buflen - Length of send buffer.
714 * ansbuf - Address of buffer into which IUCV moves the reply of
715 * this message.
716 * anslen - Address of length of buffer.
717 * Output: msgid - Specifies the message ID.
718 * Return: Return code from CP IUCV call.
719 * (-EINVAL) - Buffer or ansbuf address is NULL.
720*/
721int iucv_send2way (u16 pathid,
722 u32 * msgid,
723 u32 trgcls,
724 u32 srccls,
725 u32 msgtag,
726 int flags1,
727 void *buffer, ulong buflen, void *ansbuf, ulong anslen);
728
729/*
730 * Name: iucv_send2way_array
731 * Purpose: This function transmits data to another application.
732 * The contents of buffer is the address of the array of
733 * addresses and lengths of discontiguous buffers that hold
734 * the message text. The receiver of the send is expected to
735 * reply to the message and a buffer is provided into which
736 * IUCV moves the reply to this message.
737 * Input: pathid - Path identification number.
738 * trgcls - Specifies target class.
739 * srccls - Specifies the source message class.
740 * msgtag - Specifies a tag to be associated with the message.
741 * flags1 - Option for path.
742 * IPPRTY- 0x20 Specifies if you want to send priority message.
743 * buffer - Sddress of array of send buffers.
744 * buflen - Total length of send buffers.
745 * ansbuf - Address of array of buffer into which IUCV moves the reply
746 * of this message.
747 * anslen - Address of length reply buffers.
748 * Output: msgid - Specifies the message ID.
749 * Return: Return code from CP IUCV call.
750 * (-EINVAL) - Buffer address is NULL.
751*/
752int iucv_send2way_array (u16 pathid,
753 u32 * msgid,
754 u32 trgcls,
755 u32 srccls,
756 u32 msgtag,
757 int flags1,
758 iucv_array_t * buffer,
759 ulong buflen, iucv_array_t * ansbuf, ulong anslen);
760
761/*
762 * Name: iucv_send2way_prmmsg
763 * Purpose: This function transmits data to another application.
764 * Prmmsg specifies that the 8-bytes of data are to be moved
765 * into the parameter list. This is a two-way message and the
766 * receiver of the message is expected to reply. A buffer
767 * is provided into which IUCV moves the reply to this
768 * message.
769 * Input: pathid - Rath identification number.
770 * trgcls - Specifies target class.
771 * srccls - Specifies the source message class.
772 * msgtag - Specifies a tag to be associated with the message.
773 * flags1 - Option for path.
774 * IPPRTY- 0x20 Specifies if you want to send priority message.
775 * prmmsg - 8-bytes of data to be placed in parameter list.
776 * ansbuf - Address of buffer into which IUCV moves the reply of
777 * this message.
778 * anslen - Address of length of buffer.
779 * Output: msgid - Specifies the message ID.
780 * Return: Return code from CP IUCV call.
781 * (-EINVAL) - Buffer address is NULL.
782*/
783int iucv_send2way_prmmsg (u16 pathid,
784 u32 * msgid,
785 u32 trgcls,
786 u32 srccls,
787 u32 msgtag,
788 ulong flags1,
789 uchar prmmsg[8], void *ansbuf, ulong anslen);
790
791/*
792 * Name: iucv_send2way_prmmsg_array
793 * Purpose: This function transmits data to another application.
794 * Prmmsg specifies that the 8-bytes of data are to be moved
795 * into the parameter list. This is a two-way message and the
796 * receiver of the message is expected to reply. A buffer
797 * is provided into which IUCV moves the reply to this
798 * message. The contents of ansbuf is the address of the
799 * array of addresses and lengths of discontiguous buffers
800 * that contain the reply.
801 * Input: pathid - Path identification number.
802 * trgcls - Specifies target class.
803 * srccls - Specifies the source message class.
804 * msgtag - Specifies a tag to be associated with the message.
805 * flags1 - Option for path.
806 * IPPRTY- 0x20 specifies if you want to send priority message.
807 * prmmsg - 8-bytes of data to be placed into the parameter list.
808 * ansbuf - Address of array of buffer into which IUCV moves the reply
809 * of this message.
810 * anslen - Address of length of reply buffers.
811 * Output: msgid - Specifies the message ID.
812 * Return: Return code from CP IUCV call.
813 * (-EINVAL) - Ansbuf address is NULL.
814*/
815int iucv_send2way_prmmsg_array (u16 pathid,
816 u32 * msgid,
817 u32 trgcls,
818 u32 srccls,
819 u32 msgtag,
820 int flags1,
821 uchar prmmsg[8],
822 iucv_array_t * ansbuf, ulong anslen);
823
824/*
825 * Name: iucv_setmask
826 * Purpose: This function enables or disables the following IUCV
827 * external interruptions: Nonpriority and priority message
828 * interrupts, nonpriority and priority reply interrupts.
829 * Input: SetMaskFlag - options for interrupts
830 * 0x80 - Nonpriority_MessagePendingInterruptsFlag
831 * 0x40 - Priority_MessagePendingInterruptsFlag
832 * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
833 * 0x10 - Priority_MessageCompletionInterruptsFlag
834 * 0x08 - IUCVControlInterruptsFlag
835 * Output: NA
836 * Return: Return code from CP IUCV call.
837*/
838int iucv_setmask (int SetMaskFlag);
839
840/*
841 * Name: iucv_sever
842 * Purpose: This function terminates an IUCV path.
843 * Input: pathid - Path identification number.
844 * user_data - 16-bytes of user data.
845 * Output: NA
846 * Return: Return code from CP IUCV call.
847 * (-EINVAL) - Interal error, wild pointer.
848*/
849int iucv_sever (u16 pathid, uchar user_data[16]);