📄 iucv.c
字号:
* Name: iucv_send2way_prmmsg * Purpose: This function transmits data to another application. * Prmmsg specifies that the 8-bytes of data are to be moved * into the parameter list. This is a two-way message and the * receiver of the message is expected to reply. A buffer * is provided into which IUCV moves the reply to this * message. * Input: pathid - path identification number * trgcls - specifies target class * srccls - specifies the source message class * msgtag - specifies a tag to be associated with the message * flags1 - option for path * IPPRTY- specifies if you want to send priority message * prmmsg - 8-bytes of data to be placed in parameter list * ansbuf - address of buffer to reply with * anslen - length of buffer to reply with * Output: msgid - specifies the message ID. * Return: b2f0_result - return code from CP * (-EINVAL) - buffer address is NULL*/intiucv_send2way_prmmsg (__u16 pathid, __u32 * msgid, __u32 trgcls, __u32 srccls, __u32 msgtag, ulong flags1, __u8 prmmsg[8], void *ansbuf, ulong anslen){ iparml_dpl *parm; ulong b2f0_result; iucv_debug("entering"); if (!ansbuf) return -EINVAL; parm = (iparml_dpl *)grab_param(); parm->ippathid = pathid; parm->iptrgcls = trgcls; parm->ipsrccls = srccls; parm->ipmsgtag = msgtag; parm->ipbfadr2 = (__u32) ((ulong) ansbuf); parm->ipbfln2f = (__u32) anslen; parm->ipflags1 = (IPRMDATA | flags1); /* message in prmlist */ memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg)); b2f0_result = b2f0(SEND, parm); if ((b2f0_result == 0) && (msgid)) *msgid = parm->ipmsgid; release_param(parm); iucv_debug("exiting"); return b2f0_result;}/* * Name: iucv_send2way_prmmsg_array * Purpose: This function transmits data to another application. * Prmmsg specifies that the 8-bytes of data are to be moved * into the parameter list. This is a two-way message and the * receiver of the message is expected to reply. A buffer * is provided into which IUCV moves the reply to this * message. The contents of ansbuf is the address of the * array of addresses and lengths of discontiguous buffers * that contain the reply. * Input: pathid - path identification number * trgcls - specifies target class * srccls - specifies the source message class * msgtag - specifies a tag to be associated with the message * flags1 - option for path * IPPRTY- specifies if you want to send priority message * prmmsg - 8-bytes of data to be placed into the parameter list * ansbuf - address of buffer to reply with * anslen - length of buffer to reply with * Output: msgid - specifies the message ID. * Return: b2f0_result - return code from CP * (-EINVAL) - ansbuf address is NULL */intiucv_send2way_prmmsg_array (__u16 pathid, __u32 * msgid, __u32 trgcls, __u32 srccls, __u32 msgtag, int flags1, __u8 prmmsg[8], iucv_array_t * ansbuf, ulong anslen){ iparml_dpl *parm; ulong b2f0_result; iucv_debug("entering"); if (!ansbuf) return -EINVAL; parm = (iparml_dpl *)grab_param(); parm->ippathid = pathid; parm->iptrgcls = trgcls; parm->ipsrccls = srccls; parm->ipmsgtag = msgtag; parm->ipbfadr2 = (__u32) ((ulong) ansbuf); parm->ipbfln2f = (__u32) anslen; parm->ipflags1 = (IPRMDATA | IPANSLST | flags1); memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg)); b2f0_result = b2f0(SEND, parm); if ((b2f0_result == 0) && (msgid)) *msgid = parm->ipmsgid; release_param(parm); iucv_debug("exiting"); return b2f0_result;}/* * Name: iucv_setmask * Purpose: This function enables or disables the following IUCV * external interruptions: Nonpriority and priority message * interrupts, nonpriority and priority reply interrupts. * Input: SetMaskFlag - options for interrupts * 0x80 - Nonpriority_MessagePendingInterruptsFlag * 0x40 - Priority_MessagePendingInterruptsFlag * 0x20 - Nonpriority_MessageCompletionInterruptsFlag * 0x10 - Priority_MessageCompletionInterruptsFlag * Output: NA * Return: b2f0_result - return code from CP*/intiucv_setmask (int SetMaskFlag){ iparml_set_mask *parm; ulong b2f0_result = 0; iucv_debug("entering"); parm = (iparml_set_mask *)grab_param(); parm->ipmask = (__u8)SetMaskFlag; b2f0_result = b2f0(SETMASK, parm); release_param(parm); iucv_debug("b2f0_result = %ld", b2f0_result); iucv_debug("exiting"); return b2f0_result;}/** * iucv_sever: * @pathid: Path identification number * @user_data: 16-byte of user data * * This function terminates an iucv path. * Returns: return code from CP */intiucv_sever(__u16 pathid, __u8 user_data[16]){ iparml_control *parm; ulong b2f0_result = 0; iucv_debug("entering"); parm = (iparml_control *)grab_param(); memcpy(parm->ipuser, user_data, sizeof(parm->ipuser)); parm->ippathid = pathid; b2f0_result = b2f0(SEVER, parm); if (!b2f0_result) iucv_remove_pathid(pathid); release_param(parm); iucv_debug("exiting"); return b2f0_result;}/* * Interrupt Handlers *******************************************************************************//** * iucv_irq_handler: * @regs: Current registers * @code: irq code * * Handles external interrupts coming in from CP. * Places the interrupt buffer on a queue and schedules iucv_bh_handler(). */static voidiucv_irq_handler(struct pt_regs *regs, __u16 code){ iucv_irqdata *irqdata; int cpu = smp_processor_id(); irq_enter(cpu, 0x4000); irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC); if (!irqdata) { printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); irq_exit(cpu, 0x4000); return; } memcpy(&irqdata->data, iucv_external_int_buffer, sizeof(iucv_GeneralInterrupt)); spin_lock(&iucv_irq_queue_lock); list_add_tail(&irqdata->queue, &iucv_irq_queue); spin_unlock(&iucv_irq_queue_lock); if (atomic_compare_and_swap (0, 1, &iucv_bh_scheduled) == 0) { queue_task (&iucv_tq, &tq_immediate); mark_bh(IMMEDIATE_BH); } irq_exit(cpu, 0x4000); return;}/** * iucv_do_int: * @int_buf: Pointer to copy of external interrupt buffer * * The workhorse for handling interrupts queued by iucv_irq_handler(). * This function is called from the bottom half iucv_bh_handler(). */static voidiucv_do_int(iucv_GeneralInterrupt * int_buf){ handler *h = NULL; struct list_head *lh; ulong flags; iucv_interrupt_ops_t *interrupt = NULL; /* interrupt addresses */ __u8 temp_buff1[24], temp_buff2[24]; /* masked handler id. */ int rc = 0, j = 0; __u8 no_listener[16] = "NO LISTENER"; iucv_debug("entering, pathid %d, type %02X", int_buf->ippathid, int_buf->iptype); iucv_debug("External Interrupt Buffer:"); iucv_dumpit(int_buf, sizeof(iucv_GeneralInterrupt)); ASCEBC (no_listener, 16); if (int_buf->iptype != 01) { if ((int_buf->ippathid) > (max_connections - 1)) { printk(KERN_WARNING "%s: Got interrupt with pathid %d" " > max_connections (%ld)\n", __FUNCTION__, int_buf->ippathid, max_connections - 1); } else { h = iucv_pathid_table[int_buf->ippathid]; interrupt = h->interrupt_table; iucv_debug("Handler:"); iucv_dumpit(h, sizeof(handler)); } } /* end of if statement */ switch (int_buf->iptype) { case 0x01: /* connection pending */ spin_lock_irqsave(&iucv_lock, flags); list_for_each(lh, &iucv_handler_table) { h = list_entry(lh, handler, list); memcpy(temp_buff1, &(int_buf->ipvmid), 24); memcpy(temp_buff2, &(h->id.userid), 24); for (j = 0; j < 24; j++) { temp_buff1[j] &= (h->id.mask)[j]; temp_buff2[j] &= (h->id.mask)[j]; } iucv_debug("temp_buff1:"); iucv_dumpit(temp_buff1, sizeof(temp_buff1)); iucv_debug("temp_buff2"); iucv_dumpit(temp_buff2, sizeof(temp_buff2)); if (memcmp (temp_buff1, temp_buff2, 24) == 0) { iucv_debug("found a matching handler"); break; } } spin_unlock_irqrestore (&iucv_lock, flags); if (h) { /* ADD PATH TO PATHID TABLE */ rc = iucv_add_pathid(int_buf->ippathid, h); if (rc) { iucv_sever (int_buf->ippathid, no_listener); iucv_debug("add_pathid failed, rc = %d", rc); } else { interrupt = h->interrupt_table; if (interrupt->ConnectionPending) { EBCASC (int_buf->ipvmid, 8); interrupt->ConnectionPending( (iucv_ConnectionPending *)int_buf, h->pgm_data); } else iucv_sever(int_buf->ippathid, no_listener); } } else iucv_sever(int_buf->ippathid, no_listener); break; case 0x02: /*connection complete */ if (h) { if (interrupt->ConnectionComplete) interrupt->ConnectionComplete( (iucv_ConnectionComplete *)int_buf, h->pgm_data); else iucv_debug("ConnectionComplete not called"); } else iucv_sever(int_buf->ippathid, no_listener); break; case 0x03: /* connection severed */ if (h) { if (interrupt->ConnectionSevered) interrupt->ConnectionSevered( (iucv_ConnectionSevered *)int_buf, h->pgm_data); else iucv_sever (int_buf->ippathid, no_listener); } else iucv_sever(int_buf->ippathid, no_listener); break; case 0x04: /* connection quiesced */ if (h) { if (interrupt->ConnectionQuiesced) interrupt->ConnectionQuiesced( (iucv_ConnectionQuiesced *)int_buf, h->pgm_data); else iucv_debug("ConnectionQuiesced not called"); } break; case 0x05: /* connection resumed */ if (h) { if (interrupt->ConnectionResumed) interrupt->ConnectionResumed( (iucv_ConnectionResumed *)int_buf, h->pgm_data); else iucv_debug("ConnectionResumed not called"); } break; case 0x06: /* priority message complete */ case 0x07: /* nonpriority message complete */ if (h) { if (interrupt->MessageComplete) interrupt->MessageComplete( (iucv_MessageComplete *)int_buf, h->pgm_data); else iucv_debug("MessageComplete not called"); } break; case 0x08: /* priority message pending */ case 0x09: /* nonpriority message pending */ if (h) { if (interrupt->MessagePending) interrupt->MessagePending( (iucv_MessagePending *) int_buf, h->pgm_data); else iucv_debug("MessagePending not called"); } break; default: /* unknown iucv type */ printk(KERN_WARNING "%s: unknown iucv interrupt\n", __FUNCTION__); break; } /* end switch */ iucv_debug("exiting pathid %d, type %02X", int_buf->ippathid, int_buf->iptype); return;}/** * iucv_bh_handler: * * This function loops over the queue of irq buffers and runs iucv_do_int() * on every queue element. */static voidiucv_bh_handler(void){ struct list_head head; struct list_head *next; ulong flags; atomic_set(&iucv_bh_scheduled, 0); spin_lock_irqsave(&iucv_irq_queue_lock, flags); list_add(&head, &iucv_irq_queue); list_del_init(&iucv_irq_queue); spin_unlock_irqrestore (&iucv_irq_queue_lock, flags); next = head.next; while (next != &head) { iucv_irqdata *p = list_entry(next, iucv_irqdata, queue); next = next->next; iucv_do_int(&p->data); kfree(p); } return;}/** * Export all public stuff */EXPORT_SYMBOL (iucv_accept);EXPORT_SYMBOL (iucv_connect);EXPORT_SYMBOL (iucv_purge);EXPORT_SYMBOL (iucv_query_maxconn);EXPORT_SYMBOL (iucv_query_bufsize);EXPORT_SYMBOL (iucv_quiesce);EXPORT_SYMBOL (iucv_receive);EXPORT_SYMBOL (iucv_receive_array);EXPORT_SYMBOL (iucv_reject);EXPORT_SYMBOL (iucv_reply);EXPORT_SYMBOL (iucv_reply_array);EXPORT_SYMBOL (iucv_reply_prmmsg);EXPORT_SYMBOL (iucv_resume);EXPORT_SYMBOL (iucv_send);EXPORT_SYMBOL (iucv_send2way);EXPORT_SYMBOL (iucv_send2way_array);EXPORT_SYMBOL (iucv_send_array);EXPORT_SYMBOL (iucv_send2way_prmmsg);EXPORT_SYMBOL (iucv_send2way_prmmsg_array);EXPORT_SYMBOL (iucv_send_prmmsg);EXPORT_SYMBOL (iucv_setmask);EXPORT_SYMBOL (iucv_sever);EXPORT_SYMBOL (iucv_register_program);EXPORT_SYMBOL (iucv_unregister_program);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -