📄 iucv.c
字号:
spin_unlock_irqrestore (&iucv_lock, flags); if (!h) { printk(KERN_WARNING "%s: NULL handle passed by application " "or handler not found in iucv_handler_table\n", __FUNCTION__); return -EINVAL; } if (pathid == NULL) { printk(KERN_WARNING "%s: NULL pathid pointer\n", __FUNCTION__); return -EINVAL; } parm = (iparml_control *)grab_param(); parm->ipmsglim = msglim_reqstd; if (user_data) memcpy(parm->ipuser, user_data, sizeof(parm->ipuser)); if (userid) { memcpy(parm->ipvmid, userid, sizeof(parm->ipvmid)); ASCEBC(parm->ipvmid, sizeof(parm->ipvmid)); EBC_TOUPPER(parm->ipvmid, sizeof(parm->ipvmid)); } if (system_name) { memcpy(parm->iptarget, system_name, sizeof(parm->iptarget)); ASCEBC(parm->iptarget, sizeof(parm->iptarget)); EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget)); } parm->ipflags1 = (__u8)flags1; b2f0_result = b2f0(CONNECT, parm); if (b2f0_result) { release_param(parm); return b2f0_result; } add_pathid_result = iucv_add_pathid(parm->ippathid, h); *pathid = parm->ippathid; if (msglim) *msglim = parm->ipmsglim; if (flags1_out) *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0; if (add_pathid_result) { iucv_sever(parm->ippathid, no_memory); printk(KERN_WARNING "%s: add_pathid failed with rc =" " %d\n", __FUNCTION__, add_pathid_result); return(add_pathid_result); } iucv_debug("exiting"); return b2f0_result;}/** * iucv_purge: * @pathid: Path identification number * @msgid: Message ID of message to purge. * @srccls: Message class of the message to purge. * @audit: Pointer to an __u32. If not NULL, on return, information about * asynchronous errors that may have affected the normal completion * of this message ist stored at the given location. * * Cancels a message you have sent. * Returns: return code from CP */intiucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit){ iparml_purge *parm; ulong b2f0_result = 0; iucv_debug("entering"); iucv_debug("pathid = %d", pathid); parm = (iparml_purge *)grab_param(); parm->ipmsgid = msgid; parm->ippathid = pathid; parm->ipsrccls = srccls; parm->ipflags1 |= (IPSRCCLS | IPFGMID | IPFGPID); b2f0_result = b2f0(PURGE, parm); if ((b2f0_result == 0) && audit) { memcpy(audit, parm->ipaudit, sizeof(parm->ipaudit)); /* parm->ipaudit has only 3 bytes */ *audit >>= 8; } release_param(parm); iucv_debug("b2f0_result = %ld", b2f0_result); iucv_debug("exiting"); return b2f0_result;}/** * iucv_query_generic: * @want_maxconn: Flag, describing which value is to be returned. * * Helper function for iucv_query_maxconn() and iucv_query_bufsize(). * * Returns: The buffersize, if want_maxconn is 0; the maximum number of * connections, if want_maxconn is 1 or an error-code < 0 on failure. */static intiucv_query_generic(int want_maxconn){ iparml_purge *parm = (iparml_purge *)grab_param(); int bufsize, maxconn; int ccode; /** * Call b2f0 and store R0 (max buffer size), * R1 (max connections) and CC. */ asm volatile ( "LRA 1,0(%4)\n\t" "LR 0,%3\n\t" ".long 0xb2f01000\n\t" "IPM %0\n\t" "SRL %0,28\n\t" "ST 0,%1\n\t" "ST 1,%2\n\t" : "=d" (ccode), "=m" (bufsize), "=m" (maxconn) : "d" (QUERY), "a" (parm) : "0", "1", "cc" ); release_param(parm); if (ccode) return -EPERM; if (want_maxconn) return maxconn; return bufsize;}/** * iucv_query_maxconn: * * Determines the maximum number of connections thay may be established. * * Returns: Maximum number of connections that can be. */ulongiucv_query_maxconn(void){ return iucv_query_generic(1);}/** * iucv_query_bufsize: * * Determines the size of the external interrupt buffer. * * Returns: Size of external interrupt buffer. */ulongiucv_query_bufsize (void){ return iucv_query_generic(0);}/** * iucv_quiesce: * @pathid: Path identification number * @user_data: 16-byte user data * * Temporarily suspends incoming messages on an IUCV path. * You can later reactivate the path by invoking the iucv_resume function. * Returns: return code from CP */intiucv_quiesce (__u16 pathid, __u8 user_data[16]){ iparml_control *parm; ulong b2f0_result = 0; iucv_debug("entering"); iucv_debug("pathid = %d", pathid); parm = (iparml_control *)grab_param(); memcpy(parm->ipuser, user_data, sizeof(parm->ipuser)); parm->ippathid = pathid; b2f0_result = b2f0(QUIESCE, parm); release_param(parm); iucv_debug("b2f0_result = %ld", b2f0_result); iucv_debug("exiting"); return b2f0_result;}/** * iucv_receive: * @pathid: Path identification number. * @buffer: Address of buffer to receive. Must be below 2G. * @buflen: Length of buffer to receive. * @msgid: Specifies the message ID. * @trgcls: Specifies target class. * @flags1_out: Receives options for path on return. * - IPNORPY (0x10) Specifies whether a reply is required * - IPPRTY (0x20) Specifies if you want to send priority message * - IPRMDATA (0x80) Specifies the data is contained in the parameter list * @residual_buffer: Receives the address of buffer updated by the number * of bytes you have received on return. * @residual_length: On return, receives one of the following values: * - 0 If the receive buffer is the same length as * the message. * - Remaining bytes in buffer If the receive buffer is longer than the * message. * - Remaining bytes in message If the receive buffer is shorter than the * message. * * This function receives messages that are being sent to you over established * paths. * Returns: return code from CP IUCV call; If the receive buffer is shorter * than the message, always 5 * -EINVAL - buffer address is pointing to NULL */intiucv_receive (__u16 pathid, __u32 msgid, __u32 trgcls, void *buffer, ulong buflen, int *flags1_out, ulong * residual_buffer, ulong * residual_length){ iparml_db *parm; ulong b2f0_result; int moved = 0; /* number of bytes moved from parmlist to buffer */ iucv_debug("entering"); if (!buffer) return -EINVAL; parm = (iparml_db *)grab_param(); parm->ipbfadr1 = (__u32) (addr_t) buffer; parm->ipbfln1f = (__u32) ((ulong) buflen); parm->ipmsgid = msgid; parm->ippathid = pathid; parm->iptrgcls = trgcls; parm->ipflags1 = (IPFGPID | IPFGMID | IPFGMCL); b2f0_result = b2f0(RECEIVE, parm); if (b2f0_result == 0 || b2f0_result == 5) { if (flags1_out) { iucv_debug("*flags1_out = %d", *flags1_out); *flags1_out = (parm->ipflags1 & (~0x07)); iucv_debug("*flags1_out = %d", *flags1_out); } if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */ if (residual_length) *residual_length = parm->ipbfln1f; if (residual_buffer) *residual_buffer = parm->ipbfadr1; } else { moved = min_t (unsigned long, buflen, 8); memcpy ((char *) buffer, (char *) &parm->ipbfadr1, moved); if (buflen < 8) b2f0_result = 5; if (residual_length) *residual_length = abs (buflen - 8); if (residual_buffer) *residual_buffer = (ulong) (buffer + moved); } } release_param(parm); iucv_debug("exiting"); return b2f0_result;}/* * Name: iucv_receive_array * Purpose: This function receives messages that are being sent to you * over established paths. * Input: pathid - path identification number * buffer - address of array of buffers * buflen - total length of buffers * msgid - specifies the message ID. * trgcls - specifies target class * Output: * flags1_out: Options for path. * IPNORPY - 0x10 specifies whether a reply is required * IPPRTY - 0x20 specifies if you want to send priority message * IPRMDATA - 0x80 specifies the data is contained in the parameter list * residual_buffer - address points to the current list entry IUCV * is working on. * residual_length - * Contains one of the following values, if the receive buffer is: * The same length as the message, this field is zero. * Longer than the message, this field contains the number of * bytes remaining in the buffer. * Shorter than the message, this field contains the residual * count (that is, the number of bytes remaining in the * message that does not fit into the buffer. In this case * b2f0_result = 5. * Return: b2f0_result - return code from CP * (-EINVAL) - buffer address is NULL */intiucv_receive_array (__u16 pathid, __u32 msgid, __u32 trgcls, iucv_array_t * buffer, ulong buflen, int *flags1_out, ulong * residual_buffer, ulong * residual_length){ iparml_db *parm; ulong b2f0_result; int i = 0, moved = 0, need_to_move = 8, dyn_len; iucv_debug("entering"); if (!buffer) return -EINVAL; parm = (iparml_db *)grab_param(); parm->ipbfadr1 = (__u32) ((ulong) buffer); parm->ipbfln1f = (__u32) buflen; parm->ipmsgid = msgid; parm->ippathid = pathid; parm->iptrgcls = trgcls; parm->ipflags1 = (IPBUFLST | IPFGPID | IPFGMID | IPFGMCL); b2f0_result = b2f0(RECEIVE, parm); if (b2f0_result == 0 || b2f0_result == 5) { if (flags1_out) { iucv_debug("*flags1_out = %d", *flags1_out); *flags1_out = (parm->ipflags1 & (~0x07)); iucv_debug("*flags1_out = %d", *flags1_out); } if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */ if (residual_length) *residual_length = parm->ipbfln1f; if (residual_buffer) *residual_buffer = parm->ipbfadr1; } else { /* copy msg from parmlist to users array. */ while ((moved < 8) && (moved < buflen)) { dyn_len = min_t (unsigned int, (buffer + i)->length, need_to_move); memcpy ((char *)((ulong)((buffer + i)->address)), ((char *) &parm->ipbfadr1) + moved, dyn_len); moved += dyn_len; need_to_move -= dyn_len; (buffer + i)->address = (__u32) ((ulong)(__u8 *) ((ulong)(buffer + i)->address) + dyn_len); (buffer + i)->length -= dyn_len; i++; } if (need_to_move) /* buflen < 8 bytes */ b2f0_result = 5; if (residual_length) *residual_length = abs (buflen - 8); if (residual_buffer) { if (moved == 0) *residual_buffer = (ulong) buffer; else *residual_buffer = (ulong) (buffer + (i - 1)); } } } release_param(parm); iucv_debug("exiting"); return b2f0_result;}/** * iucv_reject: * @pathid: Path identification number. * @msgid: Message ID of the message to reject. * @trgcls: Target class of the message to reject. * Returns: return code from CP * * Refuses a specified message. Between the time you are notified of a * message and the time that you complete the message, the message may * be rejected. */intiucv_reject (__u16 pathid, __u32 msgid, __u32 trgcls){ iparml_db *parm; ulong b2f0_result = 0; iucv_debug("entering"); iucv_debug("pathid = %d", pathid); parm = (iparml_db *)grab_param(); parm->ippathid = pathid; parm->ipmsgid = msgid; parm->iptrgcls = trgcls; parm->ipflags1 = (IPFGMCL | IPFGMID | IPFGPID); b2f0_result = b2f0(REJECT, parm); release_param(parm); iucv_debug("b2f0_result = %ld", b2f0_result); iucv_debug("exiting"); return b2f0_result;}/* * Name: iucv_reply * Purpose: This function responds to the two-way messages that you * receive. You must identify completely the message to * which you wish to reply. ie, pathid, msgid, and trgcls. * Input: pathid - path identification number * msgid - specifies the message ID. * trgcls - specifies target class * flags1 - option for path * IPPRTY- 0x20 - specifies if you want to send priority message * buffer - address of reply buffer * buflen - length of reply buffer * Output: ipbfadr2 - Address of buffer updated by the number * of bytes you have moved. * ipbfln2f - Contains on the the following values * If the answer buffer is the same length as the reply, this field
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -