static void smsg_message_pending(iucv_MessagePending *eib, void *pgm_data) { struct smsg_callback *cb; unsigned char *msg; unsigned short len; int rc; len = eib->ln1msg2.ipbfln1f; msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA); if (!msg) { iucv_reject(eib->ippathid, eib->ipmsgid, eib->iptrgcls); return; } rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls, msg, len, 0, 0, 0); if (rc == 0) { msg[len] = 0; EBCASC(msg, len); spin_lock(&smsg_list_lock); list_for_each_entry(cb, &smsg_list, list) if (strncmp(msg + 8, cb->prefix, cb->len) == 0) { cb->callback(msg + 8); break; } spin_unlock(&smsg_list_lock); }
/*----------------------------*/ void do_iucv_interrupt(void) { int rc; struct in_device *indev; struct in_ifaddr *inaddr; unsigned long len=0; net_device *dev=0; struct iucv_priv *privptr; INTERRUPT_T * extern_int_buffer; unsigned short iucv_data_len=0; unsigned short iucv_next=0; unsigned char * rcvptr; /* get own buffer: */ extern_int_buffer = (INTERRUPT_T*) iucv_ext_int_buffer; netif_enter_interrupt(dev); /* lock ! */ #ifdef DEBUG printk( "iucv: do_iucv_interrupt %x received; pathid: %02X\n", extern_int_buffer->iptype,extern_int_buffer->ippathid); printk( "iucv: extern_int_buffer:\n"); dumpit((char *)&extern_int_buffer[0],40); #endif switch (extern_int_buffer->iptype) { case 0x01: /* connection pending ext interrrupt */ #ifdef DEBUG printk( "iucv: connection pending IRQ.\n"); #endif rc = iucv_accept(glob_command_buffer, extern_int_buffer->ippathid); if (rc != 0) { printk( "iucv: iucv_accept failed with rc: %X\n",rc); iucv_retrieve_buffer(glob_command_buffer); break; } #ifdef DEBUG dumpit(&((char *)extern_int_buffer)[8],8); #endif dev = get_device_from_userid(&((char*)extern_int_buffer)[8]); privptr = (struct iucv_priv *)(dev->priv); privptr->pathid = extern_int_buffer->ippathid; #ifdef DEBUG printk( "iucv: iucv_accept ended with rc: %X\n",rc); printk( "iucv: device %s found.\n",dev->name); #endif break; case 0x02: /* connection completed ext interrrupt */ /* set own global IP address */ /* & set global routing addr */ #ifdef DEBUG printk( "connection completed.\n"); #endif if( extern_int_buffer->ipmsgtag !=0) { /* get ptr's to kernel struct with local & broadcast address */ dev = get_device_from_pathid(extern_int_buffer->ippathid); privptr = (struct iucv_priv *)(dev->priv); indev = dev->ip_ptr; inaddr = (struct in_ifaddr*) indev->ifa_list; } break; case 0x03: /* connection severed ext interrrupt */ /* we do not handle this one at this time */ #ifdef DEBUG printk( "connection severed.\n"); #endif break; case 0x04: /* connection quiesced ext interrrupt */ /* we do not handle this one at this time */ #ifdef DEBUG printk( "connection quiesced.\n"); #endif break; case 0x05: /* connection resumed ext interrrupt */ /* we do not handle this one at this time */ #ifdef DEBUG printk( "connection resumed.\n"); #endif break; case 0x06: /* priority message complete ext interrupt */ case 0x07: /* non priority message complete ext interrupt */ /* send it to iucv_rx for handling */ #ifdef DEBUG printk( "message completed.\n"); #endif if (extern_int_buffer->ipaudit ==0) /* ok case */ { #ifdef DEBUG printk( "iucv: msg complete interrupt successful, rc: %X\n", (unsigned int)extern_int_buffer->ipaudit); #endif ; } else { printk( "iucv: msg complete interrupt error, rc: %X\n", (unsigned int)extern_int_buffer->ipaudit); } /* a transmission is over: tell we are no more busy */ dev = get_device_from_pathid(extern_int_buffer->ippathid); privptr = (struct iucv_priv *)(dev->priv); privptr->stats.tx_packets++; netif_wake_queue(dev); /* transmission is no longer busy*/ break; case 0x08: /* priority message pending */ case 0x09: /* non priority message pending */ #ifdef DEBUG printk( "message pending.\n"); #endif dev = get_device_from_pathid(extern_int_buffer->ippathid); privptr = (struct iucv_priv *)(dev->priv); rcvptr = &privptr->receive_buffer[0]; /* re-set receive buffer */ memset(privptr->receive_buffer,0,privptr->receive_buffer_len); len = privptr->receive_buffer_len; /* get data now */ if (extern_int_buffer->ipflags1 & 0x80) { /* data is in the message */ #ifdef DEBUG printk( "iucv: iucv_receive data is in header!\n"); #endif memcpy(privptr->receive_buffer, (char *)extern_int_buffer->iprmmsg1, (unsigned long)(extern_int_buffer->iprmmsg2)); } else /* data is in buffer, do a receive */ { rc = iucv_receive(privptr->command_buffer,rcvptr,len); if (rc != 0 || len == 0) { printk( "iucv: iucv_receive failed with rc: %X, length: %lX\n",rc,len); iucv_retrieve_buffer(privptr->command_buffer); break; } } /* end else */ iucv_next = 0; /* get next packet offset */ iucv_data_len= *((unsigned short*)rcvptr); do{ /* until receive buffer is empty, i.e. iucv_next == 0 ! */ /* get data length: */ iucv_data_len= iucv_data_len - iucv_next; #ifdef DEBUG printk( "iucv: iucv_receive: len is %02X, last: %02X\n", iucv_data_len,iucv_next); #endif /* transmit upstairs */ iucv_rx(dev,(iucv_data_len),rcvptr); #ifdef DEBUG printk( "iucv: transaction complete now.\n"); #endif iucv_next = *((unsigned short*)rcvptr); rcvptr = rcvptr + iucv_data_len; /* get next packet offset */ iucv_data_len= *((unsigned short*)rcvptr); } while (iucv_data_len != 0); netif_start_queue(dev); /* transmission is no longer busy*/ break; default: printk( "unknown iucv interrupt \n"); break; } /* end switch */ netif_exit_interrupt(dev); /* release lock*/ #ifdef DEBUG printk( "iucv: leaving do_iucv_interrupt.\n"); #endif } /* end do_iucv_interrupt() */