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

📄 ctcmain.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
}/** * A stop command from device statemachine arrived and we are in * not operational mode. Set state to stopped. * * @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_stop(fsm_instance *fi, int event, void *arg){	fsm_newstate(fi, CH_STATE_STOPPED);}/** * A machine check for no path, not operational status or gone device has * happened. * Cleanup 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_fail(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_NOTOP);	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);	}}/** * Handle error during setup of 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_setuperr(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	net_device *dev = ch->netdev;	/**	 * Special case: Got UC_RCRESET on setmode.	 * This means that remote side isn't setup. In this case	 * simply retry after some 10 secs...	 */	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&	    ((event == CH_EVENT_UC_RCRESET) ||	     (event == CH_EVENT_UC_RSRESET)   )         ) {		fsm_newstate(fi, CH_STATE_STARTRETRY);		fsm_deltimer(&ch->timer);		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);		if (CHANNEL_DIRECTION(ch->flags) == READ) {			int rc = halt_IO (ch->irq, (intparm_t)ch, 0);			if (rc != 0)				ccw_check_return_code(ch, rc);		}		return;	}	printk(KERN_DEBUG "%s: Error %s during %s channel setup state=%s\n",	       dev->name, ch_event_names[event],	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",	       fsm_getstate_str(fi));	if (CHANNEL_DIRECTION(ch->flags) == READ) {		fsm_newstate(fi, CH_STATE_RXERR);		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);	} else {		fsm_newstate(fi, CH_STATE_TXERR);		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);	}}/** * Restart a channel after an error. * * @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_restart(fsm_instance *fi, int event, void *arg){	unsigned long saveflags;	int   oldstate;	int   rc;	channel *ch = (channel *)arg;	net_device *dev = ch->netdev;	fsm_deltimer(&ch->timer);	printk(KERN_DEBUG "%s: %s channel restart\n", dev->name,	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);	oldstate = fsm_getstate(fi);	fsm_newstate(fi, CH_STATE_STARTWAIT);	if (event == CH_EVENT_TIMER)		s390irq_spin_lock_irqsave(ch->irq, saveflags);	rc = halt_IO (ch->irq, (intparm_t)ch, 0);	if (event == CH_EVENT_TIMER)		s390irq_spin_unlock_irqrestore(ch->irq, saveflags);	if (rc != 0) {		fsm_deltimer(&ch->timer);		fsm_newstate(fi, oldstate);		ccw_check_return_code(ch, rc);	}}/** * Handle error during RX initial handshake (exchange of * 0-length block header) * * @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_rxiniterr(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	net_device *dev = ch->netdev;	if (event == CH_EVENT_TIMER) {		fsm_deltimer(&ch->timer);		printk(KERN_DEBUG "%s: Timeout during RX init handshake\n",		       dev->name);		if (ch->retry++ < 3)			ch_action_restart(fi, event, arg);		else {			fsm_newstate(fi, CH_STATE_RXERR);			fsm_event(((ctc_priv *)dev->priv)->fsm,				  DEV_EVENT_RXDOWN, dev);		}	} else		printk(KERN_WARNING "%s: Error during RX init handshake\n",		       dev->name);}/** * Notify device statemachine if we gave up initialization * of RX 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_rxinitfail(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	net_device *dev = ch->netdev;	fsm_newstate(fi, CH_STATE_RXERR);	printk(KERN_WARNING "%s: RX initialization failed\n", dev->name);	printk(KERN_WARNING "%s: RX <-> RX connection detected\n", dev->name);	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);}/** * Handle RX Unit check remote reset (remote disconnected) * * @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_rxdisc(fsm_instance *fi, int event, void *arg){	channel    *ch = (channel *)arg;	channel    *ch2;	net_device *dev = ch->netdev;	fsm_deltimer(&ch->timer);	printk(KERN_DEBUG "%s: Got remote disconnect, re-initializing ...\n",	       dev->name);	/**	 * Notify device statemachine	 */	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);	fsm_newstate(fi, CH_STATE_DTERM);	ch2 = ((ctc_priv *)dev->priv)->channel[WRITE];	fsm_newstate(ch2->fsm, CH_STATE_DTERM);	halt_IO(ch->irq, (intparm_t)ch, 0);	halt_IO(ch2->irq, (intparm_t)ch2, 0);}/** * Handle error during TX channel initialization. * * @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_txiniterr(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	net_device *dev = ch->netdev;	if (event == CH_EVENT_TIMER) {		fsm_deltimer(&ch->timer);		printk(KERN_DEBUG "%s: Timeout during TX init handshake\n",		       dev->name);		if (ch->retry++ < 3)			ch_action_restart(fi, event, arg);		else {			fsm_newstate(fi, CH_STATE_TXERR);			fsm_event(((ctc_priv *)dev->priv)->fsm,				  DEV_EVENT_TXDOWN, dev);		}	} else		printk(KERN_WARNING "%s: Error during TX init handshake\n",		       dev->name);}/** * Handle TX timeout by retrying operation. * * @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_txretry(fsm_instance *fi, int event, void *arg){	channel    *ch = (channel *)arg;	net_device *dev = ch->netdev;	unsigned long saveflags;	fsm_deltimer(&ch->timer);	if (ch->retry++ > 3) {		printk(KERN_DEBUG "%s: TX retry failed, restarting channel\n",		       dev->name);		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);		ch_action_restart(fi, event, arg);	} else {		struct sk_buff *skb;		printk(KERN_DEBUG "%s: TX retry %d\n", dev->name, ch->retry);		if ((skb = skb_peek(&ch->io_queue))) {			int rc = 0;			clear_normalized_cda(&ch->ccw[4]);			ch->ccw[4].count = skb->len;			if (set_normalized_cda(&ch->ccw[4],					       virt_to_phys(skb->data))) {				printk(KERN_DEBUG "%s: IDAL alloc failed, "				       "restarting channel\n", dev->name);				fsm_event(((ctc_priv *)dev->priv)->fsm,					  DEV_EVENT_TXDOWN, dev);				ch_action_restart(fi, event, arg);				return;			}			fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);			if (event == CH_EVENT_TIMER)				s390irq_spin_lock_irqsave(ch->irq, saveflags);			rc = do_IO(ch->irq, &ch->ccw[3], (intparm_t)ch, 0xff, 0);			if (event == CH_EVENT_TIMER)				s390irq_spin_unlock_irqrestore(ch->irq,							       saveflags);			if (rc != 0) {				fsm_deltimer(&ch->timer);				ccw_check_return_code(ch, rc);				ctc_purge_skb_queue(&ch->io_queue);			}		}	}}/** * Handle fatal errors during an I/O command. * * @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_iofatal(fsm_instance *fi, int event, void *arg){	channel *ch = (channel *)arg;	net_device *dev = ch->netdev;	fsm_deltimer(&ch->timer);	if (CHANNEL_DIRECTION(ch->flags) == READ) {		printk(KERN_DEBUG "%s: RX I/O error\n", dev->name);		fsm_newstate(fi, CH_STATE_RXERR);		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);	} else {		printk(KERN_DEBUG "%s: TX I/O error\n", dev->name);		fsm_newstate(fi, CH_STATE_TXERR);		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);	}}/** * The statemachine for a channel. */static const fsm_node ch_fsm[] = {	{ CH_STATE_STOPPED,    CH_EVENT_STOP,       fsm_action_nop       },	{ CH_STATE_STOPPED,    CH_EVENT_START,      ch_action_start      },	{ CH_STATE_STOPPED,    CH_EVENT_FINSTAT,    fsm_action_nop       },	{ CH_STATE_STOPPED,    CH_EVENT_MC_FAIL,    fsm_action_nop       },	{ CH_STATE_NOTOP,      CH_EVENT_STOP,       ch_action_stop       },	{ CH_STATE_NOTOP,      CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_NOTOP,      CH_EVENT_FINSTAT,    fsm_action_nop       },	{ CH_STATE_NOTOP,      CH_EVENT_MC_FAIL,    fsm_action_nop       },	{ CH_STATE_NOTOP,      CH_EVENT_MC_GOOD,    ch_action_start      },	{ CH_STATE_STARTWAIT,  CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_STARTWAIT,  CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_STARTWAIT,  CH_EVENT_FINSTAT,    ch_action_setmode    },	{ CH_STATE_STARTWAIT,  CH_EVENT_TIMER,      ch_action_setuperr   },	{ CH_STATE_STARTWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },	{ CH_STATE_STARTWAIT,  CH_EVENT_IO_EIO,     ch_action_iofatal    },	{ CH_STATE_STARTWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_STARTRETRY, CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_STARTRETRY, CH_EVENT_TIMER,      ch_action_setmode    },	{ CH_STATE_STARTRETRY, CH_EVENT_FINSTAT,    fsm_action_nop       },	{ CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_SETUPWAIT,  CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_SETUPWAIT,  CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_SETUPWAIT,  CH_EVENT_FINSTAT,    ch_action_firstio    },	{ CH_STATE_SETUPWAIT,  CH_EVENT_UC_RCRESET, ch_action_setuperr   },	{ CH_STATE_SETUPWAIT,  CH_EVENT_UC_RSRESET, ch_action_setuperr   },	{ CH_STATE_SETUPWAIT,  CH_EVENT_TIMER,      ch_action_setmode    },	{ CH_STATE_SETUPWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },	{ CH_STATE_SETUPWAIT,  CH_EVENT_IO_EIO,     ch_action_iofatal    },	{ CH_STATE_SETUPWAIT,  CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_RXINIT,     CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_RXINIT,     CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_RXINIT,     CH_EVENT_FINSTAT,    ch_action_rxidle     },	{ CH_STATE_RXINIT,     CH_EVENT_UC_RCRESET, ch_action_rxiniterr  },	{ CH_STATE_RXINIT,     CH_EVENT_UC_RSRESET, ch_action_rxiniterr  },	{ CH_STATE_RXINIT,     CH_EVENT_TIMER,      ch_action_rxiniterr  },	{ CH_STATE_RXINIT,     CH_EVENT_ATTNBUSY,   ch_action_rxinitfail },	{ CH_STATE_RXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },	{ CH_STATE_RXINIT,     CH_EVENT_IO_EIO,     ch_action_iofatal    },	{ CH_STATE_RXINIT,     CH_EVENT_UC_ZERO,    ch_action_firstio    },	{ CH_STATE_RXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_RXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_RXIDLE,     CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_RXIDLE,     CH_EVENT_FINSTAT,    ch_action_rx         },	{ CH_STATE_RXIDLE,     CH_EVENT_UC_RCRESET, ch_action_rxdisc     },//	{ CH_STATE_RXIDLE,     CH_EVENT_UC_RSRESET, ch_action_rxretry    },	{ CH_STATE_RXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },	{ CH_STATE_RXIDLE,     CH_EVENT_IO_EIO,     ch_action_iofatal    },	{ CH_STATE_RXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_RXIDLE,     CH_EVENT_UC_ZERO,    ch_action_rx         },	{ CH_STATE_TXINIT,     CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_TXINIT,     CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_TXINIT,     CH_EVENT_FINSTAT,    ch_action_txidle     },	{ CH_STATE_TXINIT,     CH_EVENT_UC_RCRESET, ch_action_txiniterr  },	{ CH_STATE_TXINIT,     CH_EVENT_UC_RSRESET, ch_action_txiniterr  },	{ CH_STATE_TXINIT,     CH_EVENT_TIMER,      ch_action_txiniterr  },	{ CH_STATE_TXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },	{ CH_STATE_TXINIT,     CH_EVENT_IO_EIO,     ch_action_iofatal    },	{ CH_STATE_TXINIT,     CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_TXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_TXIDLE,     CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_TXIDLE,     CH_EVENT_FINSTAT,    ch_action_firstio    },	{ CH_STATE_TXIDLE,     CH_EVENT_UC_RCRESET, fsm_action_nop       },	{ CH_STATE_TXIDLE,     CH_EVENT_UC_RSRESET, fsm_action_nop       },	{ CH_STATE_TXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },	{ CH_STATE_TXIDLE,     CH_EVENT_IO_EIO,     ch_action_iofatal    },	{ CH_STATE_TXIDLE,     CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_TERM,       CH_EVENT_STOP,       fsm_action_nop       },	{ CH_STATE_TERM,       CH_EVENT_START,      ch_action_restart    },	{ CH_STATE_TERM,       CH_EVENT_FINSTAT,    ch_action_stopped    },	{ CH_STATE_TERM,       CH_EVENT_UC_RCRESET, fsm_action_nop       },	{ CH_STATE_TERM,       CH_EVENT_UC_RSRESET, fsm_action_nop       },	{ CH_STATE_TERM,       CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_DTERM,      CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_DTERM,      CH_EVENT_START,      ch_action_restart    },	{ CH_STATE_DTERM,      CH_EVENT_FINSTAT,    ch_action_setmode    },	{ CH_STATE_DTERM,      CH_EVENT_UC_RCRESET, fsm_action_nop       },	{ CH_STATE_DTERM,      CH_EVENT_UC_RSRESET, fsm_action_nop       },	{ CH_STATE_DTERM,      CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_TX,         CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_TX,         CH_EVENT_START,      fsm_action_nop       },	{ CH_STATE_TX,         CH_EVENT_FINSTAT,    ch_action_txdone     },	{ CH_STATE_TX,         CH_EVENT_UC_RCRESET, ch_action_txretry    },	{ CH_STATE_TX,         CH_EVENT_UC_RSRESET, ch_action_txretry    },	{ CH_STATE_TX,         CH_EVENT_TIMER,      ch_action_txretry    },	{ CH_STATE_TX,         CH_EVENT_IO_ENODEV,  ch_action_iofatal    },	{ CH_STATE_TX,         CH_EVENT_IO_EIO,     ch_action_iofatal    },	{ CH_STATE_TX,         CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_RXERR,      CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_TXERR,      CH_EVENT_STOP,       ch_action_haltio     },	{ CH_STATE_TXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },	{ CH_STATE_RXERR,      CH_EVENT_MC_FAIL,    ch_action_fail       },};static const int CH_FSM_LEN = sizeof(ch_fsm) / sizeof(fsm_node);/** * Functions related to setup and device detection. *****************************************************************************//** * Add a new channel to the list of channels. * Keeps the channel list sorted. * * @param irq   The IRQ to be used by the new channel. * @param devno The device number of the new channel. * @param type  The type class of the new channel. * * @return 0 on success, !0 on error. */static int add_channel(int irq, __u16 devno, channel_type_t type){	channel **c = &channels;	channel *ch;	char name[10];	if ((ch = (channel *)kmalloc(sizeof(channel), GFP_KERNEL)) == NULL) {		printk(KERN_WARNING "ctc: Out of memory in add_channel\n");		return -1;	}	memset(ch, 0, sizeof(channel));	if ((ch->ccw = (ccw1_t *)kmalloc(sizeof(ccw1_t) * 8,					 GFP_KERNEL|GFP_DMA)) == NULL) {		kfree(ch);		printk(KERN_WARNING "ctc: Out of memory in add_channel\n");		return -1;	}	/**	 * "static" ccws are used in the following way:	 *	 * ccw[0..2] (Channel program for generic I/O):	 *           0: prepare	 *           1: read or write (depending on direction) with fixed	 *              buffer (idal allocated once when buffer is allocated)	 *           2: nop	 * ccw[3..5] (Channel program for direct write of packets)	 *           3: prepare	 *           4: write (idal allocated on every write).	 *           5: nop	 * ccw[6..7] (Channel program for initial channel setup):	 *           3: set extended mode	 *           4: nop	 *	 * ch->ccw[0..5] are initialized in ch_action_start because	 * the channel's direction is yet unknown here.	 */	ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;	ch->ccw[6].flags    = CCW_FLAG_SLI;	ch->ccw[6].count    = 0;	ch->ccw[6].cda      = 0;		ch->ccw[7].cmd_code = CCW_CMD_NOOP;	ch->ccw[7].flags    = CCW_FLAG_SLI;	ch->ccw[7].count    = 0;	ch->ccw[7].cda      = 0;	ch->irq = irq;	ch->devno = devno;	ch->type = type;	sprintf(name, "ch-%04x", devno);	ch->fsm = init_fsm(name, ch_state_names,

⌨️ 快捷键说明

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