📄 claw.c
字号:
* claw_tx * *-------------------------------------------------------------------*/static intclaw_tx(struct sk_buff *skb, struct net_device *dev){ int rc; struct claw_privbk *privptr=dev->priv; unsigned long saveflags; struct chbk *p_ch;#ifdef FUNCTRACE printk(KERN_INFO "%s:%s enter\n",dev->name,__FUNCTION__);#endif CLAW_DBF_TEXT(4,trace,"claw_tx"); p_ch=&privptr->channel[WRITE]; if (skb == NULL) { printk(KERN_WARNING "%s: null pointer passed as sk_buffer\n", dev->name); privptr->stats.tx_dropped++;#ifdef FUNCTRACE printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n", dev->name,__FUNCTION__, __LINE__);#endif CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO); return -EIO; }#ifdef IOTRACE printk(KERN_INFO "%s: variable sk_buff=\n",dev->name); dumpit((char *) skb, sizeof(struct sk_buff)); printk(KERN_INFO "%s: variable dev=\n",dev->name); dumpit((char *) dev, sizeof(struct net_device));#endif spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags); rc=claw_hw_tx( skb, dev, 1 ); spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);#ifdef FUNCTRACE printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n", dev->name, __FUNCTION__, __LINE__, rc);#endif CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc); return rc;} /* end of claw_tx *//*------------------------------------------------------------------* * pack the collect queue into an skb and return it * * If not packing just return the top skb from the queue * *------------------------------------------------------------------*/static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr){ struct sk_buff *new_skb,*held_skb; struct chbk *p_ch = &privptr->channel[WRITE]; struct claw_env *p_env = privptr->p_env; int pkt_cnt,pk_ind,so_far; new_skb = NULL; /* assume no dice */ pkt_cnt = 0; CLAW_DBF_TEXT(4,trace,"PackSKBe"); if (!skb_queue_empty(&p_ch->collect_queue)) { /* some data */ held_skb = skb_dequeue(&p_ch->collect_queue); if (held_skb) dev_kfree_skb_any(held_skb); else return NULL; if (p_env->packing != DO_PACKED) return held_skb; /* get a new SKB we will pack at least one */ new_skb = dev_alloc_skb(p_env->write_size); if (new_skb == NULL) { atomic_inc(&held_skb->users); skb_queue_head(&p_ch->collect_queue,held_skb); return NULL; } /* we have packed packet and a place to put it */ pk_ind = 1; so_far = 0; new_skb->cb[1] = 'P'; /* every skb on queue has pack header */ while ((pk_ind) && (held_skb != NULL)) { if (held_skb->len+so_far <= p_env->write_size-8) { memcpy(skb_put(new_skb,held_skb->len), held_skb->data,held_skb->len); privptr->stats.tx_packets++; so_far += held_skb->len; pkt_cnt++; dev_kfree_skb_any(held_skb); held_skb = skb_dequeue(&p_ch->collect_queue); if (held_skb) atomic_dec(&held_skb->users); } else { pk_ind = 0; atomic_inc(&held_skb->users); skb_queue_head(&p_ch->collect_queue,held_skb); } }#ifdef IOTRACE printk(KERN_INFO "%s: %s() Packed %d len %d\n", p_env->ndev->name, __FUNCTION__,pkt_cnt,new_skb->len);#endif } CLAW_DBF_TEXT(4,trace,"PackSKBx"); return new_skb;}/*-------------------------------------------------------------------* * claw_change_mtu * * * *-------------------------------------------------------------------*/static intclaw_change_mtu(struct net_device *dev, int new_mtu){ struct claw_privbk *privptr=dev->priv; int buff_size;#ifdef FUNCTRACE printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);#endif#ifdef DEBUGMSG printk(KERN_INFO "variable dev =\n"); dumpit((char *) dev, sizeof(struct net_device)); printk(KERN_INFO "variable new_mtu = %d\n", new_mtu);#endif CLAW_DBF_TEXT(4,trace,"setmtu"); buff_size = privptr->p_env->write_size; if ((new_mtu < 60) || (new_mtu > buff_size)) {#ifdef FUNCTRACE printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n", dev->name, __FUNCTION__, __LINE__);#endif return -EINVAL; } dev->mtu = new_mtu;#ifdef FUNCTRACE printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name, __FUNCTION__, __LINE__);#endif return 0;} /* end of claw_change_mtu *//*-------------------------------------------------------------------* * claw_open * * * *-------------------------------------------------------------------*/static intclaw_open(struct net_device *dev){ int rc; int i; unsigned long saveflags=0; unsigned long parm; struct claw_privbk *privptr; DECLARE_WAITQUEUE(wait, current); struct timer_list timer; struct ccwbk *p_buf;#ifdef FUNCTRACE printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);#endif CLAW_DBF_TEXT(4,trace,"open"); if (!dev | (dev->name[0] == 0x00)) { CLAW_DBF_TEXT(2,trace,"BadDev"); printk(KERN_WARNING "claw: Bad device at open failing \n"); return -ENODEV; } privptr = (struct claw_privbk *)dev->priv; /* allocate and initialize CCW blocks */ if (privptr->buffs_alloc == 0) { rc=init_ccw_bk(dev); if (rc) { printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n", dev->name, __FUNCTION__, __LINE__); CLAW_DBF_TEXT(2,trace,"openmem"); return -ENOMEM; } } privptr->system_validate_comp=0; privptr->release_pend=0; if(strncmp(privptr->p_env->api_type,WS_APPL_NAME_PACKED,6) == 0) { privptr->p_env->read_size=DEF_PACK_BUFSIZE; privptr->p_env->write_size=DEF_PACK_BUFSIZE; privptr->p_env->packing=PACKING_ASK; } else { privptr->p_env->packing=0; privptr->p_env->read_size=CLAW_FRAME_SIZE; privptr->p_env->write_size=CLAW_FRAME_SIZE; } claw_set_busy(dev); tasklet_init(&privptr->channel[READ].tasklet, claw_irq_tasklet, (unsigned long) &privptr->channel[READ]); for ( i = 0; i < 2; i++) { CLAW_DBF_TEXT_(2,trace,"opn_ch%d",i); init_waitqueue_head(&privptr->channel[i].wait); /* skb_queue_head_init(&p_ch->io_queue); */ if (i == WRITE) skb_queue_head_init( &privptr->channel[WRITE].collect_queue); privptr->channel[i].flag_a = 0; privptr->channel[i].IO_active = 0; privptr->channel[i].flag &= ~CLAW_TIMER; init_timer(&timer); timer.function = (void *)claw_timer; timer.data = (unsigned long)(&privptr->channel[i]); timer.expires = jiffies + 15*HZ; add_timer(&timer); spin_lock_irqsave(get_ccwdev_lock( privptr->channel[i].cdev), saveflags); parm = (unsigned long) &privptr->channel[i]; privptr->channel[i].claw_state = CLAW_START_HALT_IO; rc = 0; add_wait_queue(&privptr->channel[i].wait, &wait); rc = ccw_device_halt( (struct ccw_device *)privptr->channel[i].cdev,parm); set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore( get_ccwdev_lock(privptr->channel[i].cdev), saveflags); schedule(); set_current_state(TASK_RUNNING); remove_wait_queue(&privptr->channel[i].wait, &wait); if(rc != 0) ccw_check_return_code(privptr->channel[i].cdev, rc); if((privptr->channel[i].flag & CLAW_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) & CLAW_TIMER) != 0x00)) {#ifdef DEBUGMSG printk(KERN_INFO "%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 not ready\n", dev->name); CLAW_DBF_TEXT(2,trace,"notrdy"); for ( i = 0; i < 2; i++) { spin_lock_irqsave( get_ccwdev_lock(privptr->channel[i].cdev), saveflags); parm = (unsigned long) &privptr->channel[i]; privptr->channel[i].claw_state = CLAW_STOP; rc = ccw_device_halt( (struct ccw_device *)&privptr->channel[i].cdev, parm); spin_unlock_irqrestore( get_ccwdev_lock(privptr->channel[i].cdev), saveflags); if (rc != 0) { ccw_check_return_code( privptr->channel[i].cdev, rc); } } free_pages((unsigned long)privptr->p_buff_ccw, (int)pages_to_order_of_mag(privptr->p_buff_ccw_num)); if (privptr->p_env->read_size < PAGE_SIZE) { free_pages((unsigned long)privptr->p_buff_read, (int)pages_to_order_of_mag( privptr->p_buff_read_num)); } else { p_buf=privptr->p_read_active_first; while (p_buf!=NULL) { free_pages((unsigned long)p_buf->p_buffer, (int)pages_to_order_of_mag( privptr->p_buff_pages_perread )); p_buf=p_buf->next; } } if (privptr->p_env->write_size < PAGE_SIZE ) { free_pages((unsigned long)privptr->p_buff_write, (int)pages_to_order_of_mag( privptr->p_buff_write_num)); } else { p_buf=privptr->p_write_active_first; while (p_buf!=NULL) { free_pages((unsigned long)p_buf->p_buffer, (int)pages_to_order_of_mag( privptr->p_buff_pages_perwrite )); p_buf=p_buf->next; } } privptr->buffs_alloc = 0; privptr->channel[READ].flag= 0x00; privptr->channel[WRITE].flag = 0x00; privptr->p_buff_ccw=NULL; privptr->p_buff_read=NULL; privptr->p_buff_write=NULL; claw_clear_busy(dev);#ifdef FUNCTRACE printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n", dev->name,__FUNCTION__,__LINE__);#endif CLAW_DBF_TEXT(2,trace,"open EIO"); return -EIO; } /* Send SystemValidate command */ claw_clear_busy(dev);#ifdef FUNCTRACE printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n", dev->name,__FUNCTION__,__LINE__);#endif CLAW_DBF_TEXT(4,trace,"openok"); return 0;} /* end of claw_open *//*-------------------------------------------------------------------** ** claw_irq_handler ** **--------------------------------------------------------------------*/static voidclaw_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb){ struct chbk *p_ch = NULL; struct claw_privbk *privptr = NULL; struct net_device *dev = NULL; struct claw_env *p_env; struct chbk *p_ch_r=NULL;#ifdef FUNCTRACE printk(KERN_INFO "%s enter \n",__FUNCTION__);#endif CLAW_DBF_TEXT(4,trace,"clawirq"); /* Bypass all 'unsolicited interrupts' */ if (!cdev->dev.driver_data) { printk(KERN_WARNING "claw: unsolicited interrupt for device:" "%s received c-%02x d-%02x\n", cdev->dev.bus_id,irb->scsw.cstat, irb->scsw.dstat);#ifdef FUNCTRACE printk(KERN_INFO "claw: %s() " "exit on line %d\n",__FUNCTION__,__LINE__);#endif CLAW_DBF_TEXT(2,trace,"badirq"); return; } privptr = (struct claw_privbk *)cdev->dev.driver_data; /* Try to extract channel from driver data. */ if (privptr->channel[READ].cdev == cdev) p_ch = &privptr->channel[READ]; else if (privptr->channel[WRITE].cdev == cdev) p_ch = &privptr->channel[WRITE]; else { printk(KERN_WARNING "claw: Can't determine channel for " "interrupt, device %s\n", cdev->dev.bus_id); CLAW_DBF_TEXT(2,trace,"badchan"); return; } CLAW_DBF_TEXT_(4,trace,"IRQCH=%d",p_ch->flag); dev = (struct net_device *) (p_ch->ndev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -