📄 iucv.c
字号:
struct iucv_priv *privptr; char iucv_host[8] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; char vmident[16] ={0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40};#ifdef DEBUG printk( "iucv: iucv_open, device: %s\n",dev->name);#endif privptr = (struct iucv_priv *)(dev->priv); if(privptr->pathid != -1) { netif_start(dev); netif_start_queue(dev); return 0; } if ((rc = iucv_connect(privptr->command_buffer, privptr->userid, iucv_host, vmident, &iucv_used_pathid))!=0) { printk( "iucv: iucv connect failed with rc %X\n",rc); iucv_retrieve_buffer(privptr->command_buffer); return -ENODEV; } privptr->pathid = iucv_used_pathid; iucv_pathid[dev-iucv_devs]=privptr->pathid;#ifdef DEBUG printk( "iucv: iucv_connect ended with rc: %X\n",rc); printk( "iucv[%d] pathid %X \n",(int)(dev-iucv_devs),privptr->pathid);#endif netif_start(dev); netif_start_queue(dev); return 0;}/*-----------------------------------------------------------------------*//* Receive a packet: retrieve, encapsulate and pass over to upper levels *//*-----------------------------------------------------------------------*/void iucv_rx(net_device *dev, int len, unsigned char *buf){ struct sk_buff *skb; struct iucv_priv *privptr = (struct iucv_priv *)dev->priv;#ifdef DEBUG printk( "iucv: iucv_rx len: %X, device %s\n",len,dev->name); printk( "iucv rx: received orig:\n"); dumpit(buf,len);#endif /* strip iucv header now */ len = len - 2; /* short header */ buf = buf + 2; /* short header */ skb = dev_alloc_skb(len+2); /* why +2 ? alignment ? */ if (!skb) { printk( "iucv rx: low on mem, returning...\n"); return; } skb_reserve(skb, 2); /* align IP on 16B boundary*/ memcpy(skb_put(skb, len), buf, len);#ifdef DEBUG printk( "iucv rx: data before netif_rx()\n"); dumpit(buf,len);#endif /* Write metadata, and then pass to the receive level */ skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; skb->dev = dev; skb->protocol = htons(ETH_P_IP); skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it*/ privptr->stats.rx_packets++; netif_rx(skb); return;} /* end iucv_rx() *//*----------------------------*//* handle interrupts *//*----------------------------*/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() *//*-------------------------------------------*//* Transmit a packet (low level interface) *//*-------------------------------------------*/int iucv_hw_tx(char *send_buf, int len,net_device *dev){ /* This function deals with hw details. */ /* This interface strips off the ethernet header details. */ /* In other words, this function implements the iucv behaviour,*/ /* while all other procedures are rather device-independent */ struct iucv_priv *privptr; int rc, recv_len=2000; privptr = (struct iucv_priv *)(dev->priv); #ifdef DEBUG printk( "iucv: iucv_hw_tx, device %s\n",dev->name); printk( "iucv: hw_TX_data len: %X\n",len); dumpit(send_buf,len);#endif /* I am paranoid. Ain't I? */ if (len < sizeof(struct iphdr)) { printk( "iucv: Hmm... packet too short (%i octets)\n",len); return -EINVAL; } /* * build IUCV header (preceeding halfword offset) * works as follows: Each packet is preceded by the * halfword offset to the next one. * The last packet is followed by an offset of zero. * E.g., AL2(12),10-byte packet, AL2(34), 32-byte packet, AL2(0) */ memcpy(&privptr->send_buffer[2],send_buf,len+2); privptr->send_buffer[len+2] = 0; privptr->send_buffer[len+3] = 0; *((unsigned short*) &privptr->send_buffer[0]) = len + 2; #ifdef DEBUG printk( "iucv: iucv_hw_tx, device %s\n",dev->name); printk( "iucv: send len: %X\n",len+4); dumpit(privptr->send_buffer,len+4);#endif *((unsigned short*) &privptr->send_buffer[0]) = len + 2; /* Ok, now the packet is ready for transmission: send it. */ if ((rc = iucv_send(privptr->command_buffer, privptr->pathid, &privptr->send_buffer[0],len+4, privptr->recv_buf,recv_len))!=0) { printk( "iucv: send_iucv failed, rc: %X\n",rc); iucv_retrieve_buffer(privptr->command_buffer); }#ifdef DEBUG printk( "iucv: send_iucv ended, rc: %X\n",rc);#endif return rc;} /* end iucv_hw_tx() *//*------------------------------------------*//* Transmit a packet (called by the kernel) *//*------------------------------------------*/int iucv_tx(struct sk_buff *skb, net_device *dev){ int retval=0; struct iucv_priv *privptr; if (dev == NULL) { printk("iucv: NULL dev passed\n"); return 0; } privptr = (struct iucv_priv *) (dev->priv); if (skb == NULL) { printk("iucv: %s: NULL buffer passed\n", dev->name); privptr->stats.tx_errors++; return 0; }#ifdef DEBUG printk( "iucv: enter iucv_tx, using %s\n",dev->name);#endif if (netif_is_busy(dev)) /* shouldn't happen */ { privptr->stats.tx_errors++; dev_kfree_skb(skb); printk("iucv: %s: transmit access conflict ! leaving iucv_tx.\n", dev->name); } netif_stop_queue(dev); /* transmission is busy*/ dev->trans_start = jiffies; /* save the timestamp*/ /* actual deliver of data is device-specific, and not shown here */ retval = iucv_hw_tx(skb->data, skb->len, dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -