📄 ctc.c
字号:
#ifdef DEBUG printk(KERN_DEBUG "%s: bh routine - state-%02x\n" ,dev->name, ctc->state);#endif while (ctc->proc_anchor != NULL) { lp = &ctc->proc_anchor->block->data; while ((__u8 *) lp < (__u8 *) &ctc->proc_anchor->block->length + ctc->proc_anchor->block->length) { data_len = lp->length - PACKET_HEADER_LENGTH; skb = dev_alloc_skb(data_len); if (skb) { memcpy(skb_put(skb, data_len),&lp->data, data_len); skb->mac.raw = skb->data; skb->dev = dev; skb->protocol = htons(ETH_P_IP); skb->ip_summed = CHECKSUM_UNNECESSARY; /* no UC happened!!! */ netif_rx(skb); privptr->stats.rx_packets++; } else { privptr->stats.rx_dropped++; printk(KERN_WARNING "%s: is low on memory\n",dev->name); } (__u8 *)lp += lp->length; } s390irq_spin_lock_irqsave(ctc->irq, saveflags); ctc_buffer_swap(&ctc->proc_anchor, &ctc->free_anchor); if (test_and_set_bit(0, (void *)&ctc->IO_active) == 0) {#ifdef DEBUG printk(KERN_DEBUG "%s: HOT READ started in bh routine\n" ,dev->name);#endif ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); parm = (__u32) ctc; rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); if (rc != 0) ccw_check_return_code(dev, rc); } s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); } clear_bit(CTC_BH_ACTIVE, (void *)&ctc->flag_a); return;} static void ctc_read_retry (struct channel *ctc){ int rc = 0; __u32 parm; __u8 flags = 0x00; __u32 saveflags; net_device *dev; dev = (net_device *) ctc->dev; #ifdef DEBUG printk(KERN_DEBUG "%s: read retry - state-%02x\n" ,dev->name, ctc->state);#endif s390irq_spin_lock_irqsave(ctc->irq, saveflags); ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); parm = (__u32) ctc; rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); if (rc != 0) ccw_check_return_code(dev, rc); return;} static void ctc_write_retry (struct channel *ctc){ int rc = 0; __u32 parm; __u8 flags = 0x00; __u32 saveflags; net_device *dev; dev = (net_device *) ctc->dev; #ifdef DEBUG printk(KERN_DEBUG "%s: write retry - state-%02x\n" ,dev->name, ctc->state);#endif s390irq_spin_lock_irqsave(ctc->irq, saveflags); ctc->ccw[1].count = 0; ctc->ccw[1].cda = (char *)virt_to_phys(ctc->proc_anchor->block); parm = (__u32) ctc; rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); if (rc != 0) ccw_check_return_code(dev, rc); return;} /* * ctc_open * */static int ctc_open(net_device *dev){ int rc; int i; int j; __u8 flags = 0x00; __u32 saveflags; __u32 parm; struct ctc_priv *privptr; DECLARE_WAITQUEUE(wait, current); struct timer_list timer; ctc_set_busy(dev); privptr = (struct ctc_priv *) (dev->priv); privptr->channel[READ].flag = 0x00; privptr->channel[WRITE].flag = CTC_WRITE; for (i = 0; i < 2; i++) { for (j = 0; j < CTC_BLOCKS; j++) { rc = ctc_buffer_alloc(&privptr->channel[i]); if (rc != 0) return -ENOMEM; } init_waitqueue_head(&privptr->channel[i].wait); INIT_LIST_HEAD(&privptr->channel[i].tq.list); privptr->channel[i].tq.sync = 0; privptr->channel[i].tq.routine = (void *)(void *)ctc_irq_bh; privptr->channel[i].tq.data = &privptr->channel[i]; privptr->channel[i].dev = dev; privptr->channel[i].flag_a = 0; privptr->channel[i].IO_active = 0; privptr->channel[i].ccw[0].cmd_code = CCW_CMD_PREPARE; privptr->channel[i].ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC; privptr->channel[i].ccw[0].count = 0; privptr->channel[i].ccw[0].cda = NULL; if (i == READ) { privptr->channel[i].ccw[1].cmd_code = CCW_CMD_READ; privptr->channel[i].ccw[1].flags = CCW_FLAG_SLI; privptr->channel[i].ccw[1].count = 0xffff; /* MAX size */ privptr->channel[i].ccw[1].cda = NULL; } else { privptr->channel[i].ccw[1].cmd_code = CCW_CMD_WRITE; privptr->channel[i].ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC; privptr->channel[i].ccw[1].count = 0; privptr->channel[i].ccw[1].cda = NULL; } privptr->channel[i].ccw[2].cmd_code = CCW_CMD_NOOP; /* jointed CE+DE */ privptr->channel[i].ccw[2].flags = CCW_FLAG_SLI; privptr->channel[i].ccw[2].count = 0; privptr->channel[i].ccw[2].cda = NULL; privptr->channel[i].flag &= ~CTC_TIMER; init_timer(&timer); timer.function = (void *)ctc_timer; timer.data = (__u32)&privptr->channel[i]; timer.expires = jiffies + 150*HZ; /* time to connect with the remote side */ add_timer(&timer); s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); parm = (unsigned long) &privptr->channel[i]; privptr->channel[i].state = CTC_START_HALT_IO; rc = halt_IO(privptr->channel[i].irq, parm, flags); add_wait_queue(&privptr->channel[i].wait, &wait); current->state = TASK_INTERRUPTIBLE; s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); schedule(); remove_wait_queue(&privptr->channel[i].wait, &wait); if(rc != 0) ccw_check_return_code(dev, rc); if((privptr->channel[i].flag & CTC_TIMER) == 0x00) del_timer(&timer); } if ((((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) || (((privptr->channel[READ].flag | privptr->channel[WRITE].flag) & CTC_TIMER) != 0x00)) {#ifdef DEBUG printk(KERN_DEBUG "%s: channel problems during open - read: %02x - write: %02x\n", dev->name, privptr->channel[READ].last_dstat, privptr->channel[WRITE].last_dstat);#endif printk(KERN_INFO "%s: remote side is currently not ready\n", dev->name); for (i = 0; i < 2; i++) { s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); parm = (unsigned long) &privptr->channel[i]; privptr->channel[i].state = CTC_STOP; rc = halt_IO(privptr->channel[i].irq, parm, flags); s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); if (rc != 0) ccw_check_return_code(dev, rc); for (j = 0; j < CTC_BLOCKS; j++) ctc_buffer_free(&privptr->channel[i]); } return -EIO; } printk(KERN_INFO "%s: connected with remote side\n",dev->name); ctc_clear_busy(dev); return 0;}static void ctc_timer (struct channel *ctc){#ifdef DEBUG net_device *dev; dev = (net_device *) ctc->dev; printk(KERN_DEBUG "%s: timer return\n" ,dev->name);#endif ctc->flag |= CTC_TIMER; wake_up(&ctc->wait); return;} /* * ctc_release * */static int ctc_release(net_device *dev){ int rc; int i; int j; __u8 flags = 0x00; __u32 saveflags; __u32 parm; struct ctc_priv *privptr; DECLARE_WAITQUEUE(wait, current); privptr = (struct ctc_priv *) dev->priv; ctc_protect_busy_irqsave(dev,saveflags); ctc_setbit_busy(TB_STOP,dev); ctc_unprotect_busy_irqrestore(dev,flags); for (i = 0; i < 2; i++) { s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); privptr->channel[i].state = CTC_STOP; parm = (__u32) &privptr->channel[i]; rc = halt_IO (privptr->channel[i].irq, parm, flags ); add_wait_queue(&privptr->channel[i].wait, &wait); current->state = TASK_INTERRUPTIBLE; s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); schedule(); remove_wait_queue(&privptr->channel[i].wait, &wait); if (rc != 0) { ccw_check_return_code(dev, rc); } for (j = 0; j < CTC_BLOCKS; j++) { ctc_buffer_swap(&privptr->channel[i].proc_anchor, &privptr->channel[i].free_anchor); ctc_buffer_free(&privptr->channel[i]); } } if (((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { printk(KERN_WARNING "%s: channel problems during close - read: %02x - write: %02x\n", dev->name, privptr->channel[READ].last_dstat, privptr->channel[WRITE].last_dstat); return -EIO; } return 0;} /* * ctc_tx * * */static int ctc_tx(struct sk_buff *skb, net_device *dev){ int rc=0,rc2; __u32 parm; __u8 flags = 0x00; __u32 saveflags; struct ctc_priv *privptr; struct packet *lp; privptr = (struct ctc_priv *) (dev->priv); if (skb == NULL) { printk(KERN_WARNING "%s: NULL pointer as sk_buffer passed\n", dev->name); privptr->stats.tx_dropped++; return -EIO; } s390irq_spin_lock_irqsave(privptr->channel[WRITE].irq, saveflags); if (ctc_check_busy(dev)) { rc=-EBUSY; goto Done; } if (ctc_test_and_setbit_busy(TB_TX,dev)) { /* set transmission to busy */ rc=-EBUSY; goto Done; } if (65535 - privptr->channel[WRITE].free_anchor->block->length - PACKET_HEADER_LENGTH <= skb->len + PACKET_HEADER_LENGTH + 2) {#ifdef DEBUG printk(KERN_DEBUG "%s: early swap\n", dev->name);#endif ctc_buffer_swap(&privptr->channel[WRITE].free_anchor, &privptr->channel[WRITE].proc_anchor); if (privptr->channel[WRITE].free_anchor == NULL){ ctc_setbit_busy(TB_NOBUFFER,dev); rc=-EBUSY; goto Done2; } } if (privptr->channel[WRITE].free_anchor->block->length == 0) { privptr->channel[WRITE].free_anchor->block->length = BLOCK_HEADER_LENGTH; privptr->channel[WRITE].free_anchor->packets = 0; } (__u8 *)lp = (__u8 *) &privptr->channel[WRITE].free_anchor->block->length + privptr->channel[WRITE].free_anchor->block->length; privptr->channel[WRITE].free_anchor->block->length += skb->len + PACKET_HEADER_LENGTH; lp->length = skb->len + PACKET_HEADER_LENGTH; lp->type = 0x0800; lp->unused = 0; memcpy(&lp->data, skb->data, skb->len); (__u8 *) lp += lp->length; lp->length = 0; dev_kfree_skb(skb); privptr->channel[WRITE].free_anchor->packets++; if (test_and_set_bit(0, (void *)&privptr->channel[WRITE].IO_active) == 0) { ctc_buffer_swap(&privptr->channel[WRITE].free_anchor,&privptr->channel[WRITE].proc_anchor); privptr->channel[WRITE].ccw[1].count = privptr->channel[WRITE].proc_anchor->block->length; privptr->channel[WRITE].ccw[1].cda = (char *)virt_to_phys(privptr->channel[WRITE].proc_anchor->block); parm = (__u32) &privptr->channel[WRITE]; rc2 = do_IO (privptr->channel[WRITE].irq, &privptr->channel[WRITE].ccw[0], parm, 0xff, flags ); if (rc2 != 0) ccw_check_return_code(dev, rc2); dev->trans_start = jiffies; } if (privptr->channel[WRITE].free_anchor == NULL) ctc_setbit_busy(TB_NOBUFFER,dev);Done2: ctc_clearbit_busy(TB_TX,dev);Done: s390irq_spin_unlock_irqrestore(privptr->channel[WRITE].irq, saveflags); return(rc);} /* * ctc_change_mtu * * S/390 can handle MTU sizes from 576 to 32760 for VM, VSE * 576 to 65527 for OS/390 * */static int ctc_change_mtu(net_device *dev, int new_mtu){ if ((new_mtu < 576) || (new_mtu > 65528)) return -EINVAL; dev->mtu = new_mtu; return 0;}/* * ctc_stats * */struct net_device_stats *ctc_stats(net_device *dev){ struct ctc_priv *privptr; privptr = dev->priv; return &privptr->stats;} /* Module code goes here *//* free_irq(privptr->channel[i].irq, privptr->channel[i].devstat); kfree(privptr->channel[i].devstat); *//* --- This is the END my friend --- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -