⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctcmain.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		ch->ccw[1].count = 0;		ch->trans_skb_data = ch->trans_skb->data;		ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;	}	return 0;}/** * Dummy NOP action for statemachines */static void fsm_action_nop(fsm_instance *fi, int event, void *arg){}/** * Actions for channel - statemachines. *****************************************************************************//** * Normal data has been send. Free the corresponding * skb (it's in io_queue), reset dev->tbusy and * revert to idle state. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_txdone(fsm_instance *fi, int event, void *arg){	channel        *ch = (channel *)arg;	net_device     *dev = ch->netdev;	ctc_priv       *privptr = dev->priv;	struct sk_buff *skb;	int            first = 1;	int            i;	struct timeval done_stamp = xtime;	unsigned long duration = 		(done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +		done_stamp.tv_usec - ch->prof.send_stamp.tv_usec;	if (duration > ch->prof.tx_time)		ch->prof.tx_time = duration;	if (ch->devstat->rescnt != 0)		printk(KERN_DEBUG "%s: TX not complete, remaining %d bytes\n",		       dev->name, ch->devstat->rescnt);		fsm_deltimer(&ch->timer);	while ((skb = skb_dequeue(&ch->io_queue))) {		privptr->stats.tx_packets++;		privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;		if (first) {			privptr->stats.tx_bytes += 2;			first = 0;		}		atomic_dec(&skb->users);		dev_kfree_skb_irq(skb);	}	spin_lock(&ch->collect_lock);	clear_normalized_cda(&ch->ccw[4]);	if (ch->collect_len > 0) {		int rc;		if (ctc_checkalloc_buffer(ch, 1)) {			spin_unlock(&ch->collect_lock);			return;		}		ch->trans_skb->tail = ch->trans_skb->data = ch->trans_skb_data;		ch->trans_skb->len = 0;		if (ch->prof.maxmulti < (ch->collect_len + 2))			ch->prof.maxmulti = ch->collect_len + 2;		if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))			ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);		*((__u16 *)skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;		i = 0;		while ((skb = skb_dequeue(&ch->collect_queue))) {			memcpy(skb_put(ch->trans_skb, skb->len), skb->data,			       skb->len);			privptr->stats.tx_packets++;			privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;			atomic_dec(&skb->users);			dev_kfree_skb_irq(skb);			i++;		}		ch->collect_len = 0;		spin_unlock(&ch->collect_lock);		ch->ccw[1].count = ch->trans_skb->len;		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);		ch->prof.send_stamp = xtime;		rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);		ch->prof.doios_multi++;		if (rc != 0) {			privptr->stats.tx_dropped += i;			privptr->stats.tx_errors += i;			fsm_deltimer(&ch->timer);			ccw_check_return_code(ch, rc);		}	} else {		spin_unlock(&ch->collect_lock);		fsm_newstate(fi, CH_STATE_TXIDLE);	}	ctc_clear_busy(dev);}/** * Initial data is sent. * Notify device statemachine that we are up and * running. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_txidle(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	fsm_deltimer(&ch->timer);	fsm_newstate(fi, CH_STATE_TXIDLE);	fsm_event(((ctc_priv *)ch->netdev->priv)->fsm, DEV_EVENT_TXUP,		  ch->netdev);}/** * Got normal data, check for sanity, queue it up, allocate new buffer * trigger bottom half, and initiate next read. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_rx(fsm_instance *fi, int event, void *arg){	channel        *ch = (channel *)arg;	net_device     *dev = ch->netdev;	ctc_priv       *privptr = dev->priv;	int            len = ch->max_bufsize - ch->devstat->rescnt;	struct sk_buff *skb = ch->trans_skb;	__u16          block_len = *((__u16*)skb->data);	int            check_len;	int            rc;	fsm_deltimer(&ch->timer);	if (len < 8) {		printk(KERN_WARNING "%s: got packet with length %d < 8\n",		       dev->name, len);		privptr->stats.rx_dropped++;		privptr->stats.rx_length_errors++;		goto again;	}	if (len > ch->max_bufsize) {		printk(KERN_WARNING "%s: got packet with length %d > %d\n",		       dev->name, len, ch->max_bufsize);		privptr->stats.rx_dropped++;		privptr->stats.rx_length_errors++;		goto again;	}	/**	 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.	 */	switch (ch->protocol) {		case CTC_PROTO_S390:		case CTC_PROTO_OS390:			check_len = block_len + 2;			break;		default:			check_len = block_len;			break;	}	if ((len < block_len) || (len > check_len)) {		printk(KERN_WARNING "%s: got block length %d != rx length %d\n",		       dev->name, block_len, len);#ifdef DEBUG		ctc_dump_skb(skb, 0);#endif		*((__u16*)skb->data) = len;		privptr->stats.rx_dropped++;		privptr->stats.rx_length_errors++;		goto again;	}	block_len -= 2;	if (block_len > 0) {		*((__u16*)skb->data) = block_len;		ctc_unpack_skb(ch, skb);	} again:	skb->data = skb->tail = ch->trans_skb_data;	skb->len = 0;	if (ctc_checkalloc_buffer(ch, 1))		return;	ch->ccw[1].count = ch->max_bufsize;	rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);	if (rc != 0)		ccw_check_return_code(ch, rc);}static void ch_action_rxidle(fsm_instance *fi, int event, void *arg);/** * Initialize connection by sending a __u16 of value 0. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_firstio(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	int     rc;	if (fsm_getstate(fi) == CH_STATE_TXIDLE)		printk(KERN_DEBUG "ch-%04x: remote side issued READ?, "		       "init ...\n", ch->devno);	fsm_deltimer(&ch->timer);	if (ctc_checkalloc_buffer(ch, 1))		return;	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&	    (ch->protocol == CTC_PROTO_OS390)) {		/* OS/390 resp. z/OS */		if (CHANNEL_DIRECTION(ch->flags) == READ) {			*((__u16 *)ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;			fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC,				     CH_EVENT_TIMER, ch);			ch_action_rxidle(fi, event, arg);		} else {			net_device *dev = ch->netdev;			fsm_newstate(fi, CH_STATE_TXIDLE);			fsm_event(((ctc_priv *)dev->priv)->fsm,				  DEV_EVENT_TXUP, dev);		}		return;	}	/**	 * Don磘 setup a timer for receiving the initial RX frame	 * if in compatibility mode, since VM TCP delays the initial	 * frame until it has some data to send.	 */	if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||	    (ch->protocol != CTC_PROTO_S390))		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	*((__u16 *)ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;	ch->ccw[1].count = 2; /* Transfer only length */	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)		     ? CH_STATE_RXINIT : CH_STATE_TXINIT);	rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);	if (rc != 0) {		fsm_deltimer(&ch->timer);		fsm_newstate(fi, CH_STATE_SETUPWAIT);		ccw_check_return_code(ch, rc);	}	/**	 * If in compatibility mode since we don磘 setup a timer, we	 * also signal RX channel up immediately. This enables us	 * to send packets early which in turn usually triggers some	 * reply from VM TCP which brings up the RX channel to it磗	 * final state.	 */	if ((CHANNEL_DIRECTION(ch->flags) == READ) &&	    (ch->protocol == CTC_PROTO_S390)) {		net_device *dev = ch->netdev;		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXUP, dev);	}}/** * Got initial data, check it. If OK, * notify device statemachine that we are up and * running. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_rxidle(fsm_instance *fi, int event, void *arg){	channel    *ch = (channel *)arg;	net_device *dev = ch->netdev;	__u16      buflen;	int        rc;	fsm_deltimer(&ch->timer);	buflen = *((__u16 *)ch->trans_skb->data);#ifdef DEBUG	printk(KERN_DEBUG "%s: Initial RX count %d\n", dev->name, buflen);#endif	if (buflen >= CTC_INITIAL_BLOCKLEN) {		if (ctc_checkalloc_buffer(ch, 1))			return;		ch->ccw[1].count = ch->max_bufsize;		fsm_newstate(fi, CH_STATE_RXIDLE);		rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);		if (rc != 0) {			fsm_newstate(fi, CH_STATE_RXINIT);			ccw_check_return_code(ch, rc);		} else			fsm_event(((ctc_priv *)dev->priv)->fsm,				  DEV_EVENT_RXUP, dev);	} else {		printk(KERN_DEBUG "%s: Initial RX count %d not %d\n",		       dev->name, buflen, CTC_INITIAL_BLOCKLEN);		ch_action_firstio(fi, event, arg);	}}/** * Set channel into extended mode. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_setmode(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	int     rc;	unsigned long saveflags;	fsm_deltimer(&ch->timer);	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	fsm_newstate(fi, CH_STATE_SETUPWAIT);	if (event == CH_EVENT_TIMER)		s390irq_spin_lock_irqsave(ch->irq, saveflags);	rc = do_IO(ch->irq, &ch->ccw[6], (intparm_t)ch, 0xff, 0);	if (event == CH_EVENT_TIMER)		s390irq_spin_unlock_irqrestore(ch->irq, saveflags);	if (rc != 0) {		fsm_deltimer(&ch->timer);		fsm_newstate(fi, CH_STATE_STARTWAIT);		ccw_check_return_code(ch, rc);	} else		ch->retry = 0;}/** * Setup channel. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_start(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	unsigned long saveflags;	int     rc;	net_device *dev;	if (ch == NULL) {		printk(KERN_WARNING "ch_action_start ch=NULL\n");		return;	}	if (ch->netdev == NULL) {		printk(KERN_WARNING "ch_action_start dev=NULL, irq=%d\n",		       ch->irq);		return;	}	dev = ch->netdev;#ifdef DEBUG	printk(KERN_DEBUG "%s: %s channel start\n", dev->name,	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");#endif	if (ch->trans_skb != NULL) {		clear_normalized_cda(&ch->ccw[1]);		dev_kfree_skb(ch->trans_skb);		ch->trans_skb = NULL;	}	if (CHANNEL_DIRECTION(ch->flags) == READ) {		ch->ccw[1].cmd_code = CCW_CMD_READ;		ch->ccw[1].flags    = CCW_FLAG_SLI;		ch->ccw[1].count    = 0;	} else {		ch->ccw[1].cmd_code = CCW_CMD_WRITE;		ch->ccw[1].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;		ch->ccw[1].count    = 0;	}	if (ctc_checkalloc_buffer(ch, 0))		printk(KERN_NOTICE		       "%s: Could not allocate %s trans_skb, delaying "		       "allocation until first transfer\n",		       dev->name, 		       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");#if LINUX_VERSION_CODE >= 0x020400	INIT_LIST_HEAD(&ch->tq.list);#else	ch->tq.next = NULL;#endif	ch->tq.sync    = 0;	ch->tq.routine = (void *)(void *)ctc_bh;	ch->tq.data    = ch;	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;	ch->ccw[0].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;	ch->ccw[0].count    = 0;	ch->ccw[0].cda	    = 0;	ch->ccw[2].cmd_code = CCW_CMD_NOOP;	 /* jointed CE + DE */	ch->ccw[2].flags    = CCW_FLAG_SLI;	ch->ccw[2].count    = 0;	ch->ccw[2].cda	    = 0;	memcpy(&ch->ccw[3], &ch->ccw[0], sizeof(ccw1_t) * 3);	ch->ccw[4].cda	    = 0;	ch->ccw[4].flags    &= ~CCW_FLAG_IDA;	fsm_newstate(fi, CH_STATE_STARTWAIT);	fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);	s390irq_spin_lock_irqsave(ch->irq, saveflags);	rc = halt_IO(ch->irq, (intparm_t)ch, 0);	s390irq_spin_unlock_irqrestore(ch->irq, saveflags);	if (rc != 0) {		fsm_deltimer(&ch->timer);		ccw_check_return_code(ch, rc);	}#ifdef DEBUG	printk(KERN_DEBUG "ctc: %s(): leaving\n", __FUNCTION__);#endif}/** * Shutdown a channel. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_haltio(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	unsigned long saveflags;	int     rc;	int     oldstate;	fsm_deltimer(&ch->timer);	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	if (event == CH_EVENT_STOP)		s390irq_spin_lock_irqsave(ch->irq, saveflags);	oldstate = fsm_getstate(fi);	fsm_newstate(fi, CH_STATE_TERM);	rc = halt_IO (ch->irq, (intparm_t)ch, 0);	if (event == CH_EVENT_STOP)		s390irq_spin_unlock_irqrestore(ch->irq, saveflags);	if (rc != 0) {		fsm_deltimer(&ch->timer);		fsm_newstate(fi, oldstate);		ccw_check_return_code(ch, rc);	}}/** * A channel has successfully been halted. * Cleanup it's queue and notify interface statemachine. * * @param fi    An instance of a channel statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from channel * upon call. */static void ch_action_stopped(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	net_device *dev = ch->netdev;	fsm_deltimer(&ch->timer);	fsm_newstate(fi, CH_STATE_STOPPED);	if (ch->trans_skb != NULL) {		clear_normalized_cda(&ch->ccw[1]);		dev_kfree_skb(ch->trans_skb);		ch->trans_skb = NULL;	}	if (CHANNEL_DIRECTION(ch->flags) == READ) {		skb_queue_purge(&ch->io_queue);		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);	} else {		ctc_purge_skb_queue(&ch->io_queue);		spin_lock(&ch->collect_lock);		ctc_purge_skb_queue(&ch->collect_queue);		ch->collect_len = 0;		spin_unlock(&ch->collect_lock);		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -