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

📄 ctcmain.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			ch_event_names, NR_CH_STATES, NR_CH_EVENTS,			ch_fsm, CH_FSM_LEN, GFP_KERNEL);	if (ch->fsm == NULL) {		printk(KERN_WARNING		       "ctc: Could not create FSM in add_channel\n");		kfree(ch);		return -1;	}	fsm_newstate(ch->fsm, CH_STATE_IDLE);	if ((ch->devstat = (devstat_t*)kmalloc(sizeof(devstat_t), GFP_KERNEL))	    == NULL) {		printk(KERN_WARNING "ctc: Out of memory in add_channel\n");		kfree_fsm(ch->fsm);		kfree(ch);		return -1;	}	memset(ch->devstat, 0, sizeof(devstat_t));	while (*c && ((*c)->devno < devno))		c = &(*c)->next;	if ((*c)->devno == devno) {		printk(KERN_DEBUG		       "ctc: add_channel: device %04x already in list, "		       "using old entry\n", (*c)->devno);		kfree(ch->devstat);		kfree_fsm(ch->fsm);		kfree(ch);		return 0;	}	fsm_settimer(ch->fsm, &ch->timer);	skb_queue_head_init(&ch->io_queue);	skb_queue_head_init(&ch->collect_queue);	ch->next = *c;	*c = ch;	return 0;}#ifndef CTC_CHANDEV/** * scan for all channels and create an entry in the channels list * for every supported channel. */static void channel_scan(void){	static int      print_result = 1;	int	        irq;	int             nr_escon = 0;	int             nr_ctca  = 0;	s390_dev_info_t di;	for (irq = 0; irq < NR_IRQS; irq++) {		if (get_dev_info_by_irq(irq, &di) == 0) {			if ((di.status == DEVSTAT_NOT_OPER) ||			    (di.status == DEVSTAT_DEVICE_OWNED))				continue;			switch (channel_type(&di.sid_data)) {				case channel_type_ctca:					/* CTC/A */					if (!add_channel(irq, di.devno,							 channel_type_ctca))						nr_ctca++;					break;				case channel_type_escon:					/* ESCON */					if (!add_channel(irq, di.devno,							 channel_type_escon))						nr_escon++;					break;			default:			}		}	}	if (print_result) {		if (nr_escon + nr_ctca)			printk(KERN_INFO			       "ctc: %d CTC/A channel%s and %d ESCON "			       "channel%s found.\n",			       nr_ctca, (nr_ctca == 1) ? "s" : "",			       nr_escon, (nr_escon == 1) ? "s" : "");		else			printk(KERN_INFO "ctc: No channel devices found.\n");	}	print_result = 0;}#endif/** * Release a specific channel in the channel list. * * @param ch Pointer to channel struct to be released. */static void channel_free(channel *ch){	ch->flags &= ~CHANNEL_FLAGS_INUSE;	fsm_newstate(ch->fsm, CH_STATE_IDLE);}/** * Remove a specific channel in the channel list. * * @param ch Pointer to channel struct to be released. */static void channel_remove(channel *ch){	channel **c = &channels;	if (ch == NULL)		return;#ifndef CTC_CHANDEV	if (ch->flags & CHANNEL_FLAGS_INUSE)		FREE_IRQ(ch->irq, ch->devstat);#endif	channel_free(ch);	while (*c) {		if (*c == ch) {			*c = ch->next;			fsm_deltimer(&ch->timer);			kfree_fsm(ch->fsm);			clear_normalized_cda(&ch->ccw[4]);			if (ch->trans_skb != NULL) {				clear_normalized_cda(&ch->ccw[1]);				dev_kfree_skb(ch->trans_skb);			}			kfree(ch->ccw);			return;		}		c = &((*c)->next);	}}/** * Get a specific channel from the channel list. * * @param type Type of channel we are interested in. * @param devno Device number of channel we are interested in. * @param direction Direction we want to use this channel for. * * @return Pointer to a channel or NULL if no matching channel available. */static channel *channel_get(channel_type_t type, int devno, int direction){	channel *ch = channels;#ifdef DEBUG	printk(KERN_DEBUG	       "ctc: %s(): searching for ch with devno %d and type %d\n",	       __FUNCTION__, devno, type);#endif	while (ch && ((ch->devno != devno) || (ch->type != type))) {#ifdef DEBUG		printk(KERN_DEBUG		       "ctc: %s(): ch=0x%p (devno=%d, type=%d\n",		       __FUNCTION__, ch, ch->devno, ch->type);#endif		ch = ch->next;	}#ifdef DEBUG	printk(KERN_DEBUG	       "ctc: %s(): ch=0x%pq (devno=%d, type=%d\n",	       __FUNCTION__, ch, ch->devno, ch->type);#endif	if (!ch) {		printk(KERN_WARNING "ctc: %s(): channel with devno %d "		       "and type %d not found in channel list\n",	       __FUNCTION__, devno, type);	}	else {		if (ch->flags & CHANNEL_FLAGS_INUSE)			ch = NULL;		else {			ch->flags |= CHANNEL_FLAGS_INUSE;			ch->flags &= ~CHANNEL_FLAGS_RWMASK;			ch->flags |= (direction == WRITE)				? CHANNEL_FLAGS_WRITE:CHANNEL_FLAGS_READ;			fsm_newstate(ch->fsm, CH_STATE_STOPPED);		}	}	return ch;}#ifndef CTC_CHANDEV/** * Get the next free channel from the channel list * * @param type Type of channel we are interested in. * @param direction Direction we want to use this channel for. * * @return Pointer to a channel or NULL if no matching channel available. */static channel *channel_get_next(channel_type_t type, int direction){	channel *ch = channels;	while (ch && (ch->type != type || (ch->flags & CHANNEL_FLAGS_INUSE)))		ch = ch->next;	if (ch) {		ch->flags |= CHANNEL_FLAGS_INUSE;		ch->flags &= ~CHANNEL_FLAGS_RWMASK;		ch->flags |= (direction == WRITE)			? CHANNEL_FLAGS_WRITE:CHANNEL_FLAGS_READ;		fsm_newstate(ch->fsm, CH_STATE_STOPPED);	}	return ch;}#endif/** * Return the channel type by name. * * @param name Name of network interface. * * @return Type class of channel to be used for that interface. */static channel_type_t inline extract_channel_media(char *name){	channel_type_t ret = channel_type_unknown;	if (name != NULL) {		if (strncmp(name, "ctc", 3) == 0)			ret = channel_type_ctca;		if (strncmp(name, "escon", 5) == 0)			ret = channel_type_escon;	}	return ret;}/** * Find a channel in the list by its IRQ. * * @param irq IRQ to search for. * * @return Pointer to channel or NULL if no matching channel found. */static channel *find_channel_by_irq(int irq){	channel *ch = channels;	while (ch && (ch->irq != irq))		ch = ch->next;	return ch;}/** * Main IRQ handler. * * @param irq     The IRQ to handle. * @param intparm IRQ params. * @param regs    CPU registers. */static void ctc_irq_handler (int irq, void *intparm, struct pt_regs *regs){	devstat_t  *devstat = (devstat_t *)intparm;	channel    *ch = (channel *)devstat->intparm;	net_device *dev;	/**	 * Check for unsolicited interrupts.	 * If intparm is NULL, then loop over all our known	 * channels and try matching the irq number.	 */	if (ch == NULL) {		if ((ch = find_channel_by_irq(irq)) == NULL) {			printk(KERN_WARNING			       "ctc: Got unsolicited irq: %04x c-%02x d-%02x"			       "f-%02x\n", devstat->devno, devstat->cstat,			       devstat->dstat, devstat->flag);			goto done;		}	}	dev = (net_device *)(ch->netdev);	if (dev == NULL) {		printk(KERN_CRIT		       "ctc: ctc_irq_handler dev = NULL irq=%d, ch=0x%p\n",		       irq, ch);		goto done;	}	if (intparm == NULL)		printk(KERN_DEBUG "%s: Channel %04x found by IRQ %d\n",		       dev->name, ch->devno, irq);#ifdef DEBUG	printk(KERN_DEBUG	       "%s: interrupt for device: %04x received c-%02x d-%02x "	       "f-%02x\n", dev->name, devstat->devno, devstat->cstat,	       devstat->dstat, devstat->flag);#endif	/* Check for good subchannel return code, otherwise error message */	if (devstat->cstat) {		fsm_event(ch->fsm, CH_EVENT_SC_UNKNOWN, ch);		printk(KERN_WARNING		       "%s: subchannel check for device: %04x - %02x %02x "		       "%02x\n", dev->name, ch->devno, devstat->cstat,		       devstat->dstat, devstat->flag);		goto done;	}	/* Check the reason-code of a unit check */	if (devstat->dstat & DEV_STAT_UNIT_CHECK) {		ccw_unit_check(ch, devstat->ii.sense.data[0]);		goto done;	}	if (devstat->dstat & DEV_STAT_BUSY) {		if (devstat->dstat & DEV_STAT_ATTENTION)			fsm_event(ch->fsm, CH_EVENT_ATTNBUSY, ch);		else			fsm_event(ch->fsm, CH_EVENT_BUSY, ch);		goto done;	}	if (devstat->dstat & DEV_STAT_ATTENTION) {		fsm_event(ch->fsm, CH_EVENT_ATTN, ch);		goto done;	}	if (devstat->flag & DEVSTAT_FINAL_STATUS)		fsm_event(ch->fsm, CH_EVENT_FINSTAT, ch);	else		fsm_event(ch->fsm, CH_EVENT_IRQ, ch); done:}/** * Actions for interface - statemachine. *****************************************************************************//** * Startup channels by sending CH_EVENT_START to each channel. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static void dev_action_start(fsm_instance *fi, int event, void *arg){	net_device *dev = (net_device *)arg;	ctc_priv   *privptr = dev->priv;	int        direction;	fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);	for (direction = READ; direction <= WRITE; direction++) {		channel *ch = privptr->channel[direction];		fsm_event(ch->fsm, CH_EVENT_START, ch);	}}/** * Shutdown channels by sending CH_EVENT_STOP to each channel. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static void dev_action_stop(fsm_instance *fi, int event, void *arg){	net_device *dev = (net_device *)arg;	ctc_priv   *privptr = dev->priv;	int        direction;	fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);	for (direction = READ; direction <= WRITE; direction++) {		channel *ch = privptr->channel[direction];		fsm_event(ch->fsm, CH_EVENT_STOP, ch);	}}/** * Called from channel statemachine * when a channel is up and running. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static void dev_action_chup(fsm_instance *fi, int event, void *arg){	net_device *dev = (net_device *)arg;	ctc_priv   *privptr = dev->priv;	switch (fsm_getstate(fi)) {		case DEV_STATE_STARTWAIT_RXTX:			if (event == DEV_EVENT_RXUP)				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);			else				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);			break;		case DEV_STATE_STARTWAIT_RX:			if (event == DEV_EVENT_RXUP) {				fsm_newstate(fi, DEV_STATE_RUNNING);				printk(KERN_INFO				       "%s: connected with remote side\n",				       dev->name);				if (privptr->protocol == CTC_PROTO_LINUX_TTY)					ctc_tty_setcarrier(dev, 1);				ctc_clear_busy(dev);			}			break;		case DEV_STATE_STARTWAIT_TX:			if (event == DEV_EVENT_TXUP) {				fsm_newstate(fi, DEV_STATE_RUNNING);				printk(KERN_INFO				       "%s: connected with remote side\n",				       dev->name);				if (privptr->protocol == CTC_PROTO_LINUX_TTY)					ctc_tty_setcarrier(dev, 1);				ctc_clear_busy(dev);			}			break;		case DEV_STATE_STOPWAIT_TX:			if (event == DEV_EVENT_RXUP)				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);			break;		case DEV_STATE_STOPWAIT_RX:			if (event == DEV_EVENT_TXUP)				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);			break;	}}/** * Called from channel statemachine * when a channel has been shutdown. * * @param fi    An instance of an interface statemachine. * @param event The event, just happened. * @param arg   Generic pointer, casted from net_device * upon call. */static void dev_action_chdown(fsm_instance *fi, int event, void *arg){	net_device *dev = (net_device *)arg;	ctc_priv   *privptr = dev->priv;	switch (fsm_getstate(fi)) {		case DEV_STATE_RUNNING:			if (privptr->protocol == CTC_PROTO_LINUX_TTY)				ctc_tty_setcarrier(dev, 0);			if (event == DEV_EVENT_TXDOWN)				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);			else				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);			break;		case DEV_STATE_STARTWAIT_RX:			if (event == DEV_EVENT_TXDOWN)				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);			break;		case DEV_STATE_STARTWAIT_TX:			if (event == DEV_EVENT_RXDOWN)				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);			break;		case DEV_STATE_STOPWAIT_RXTX:			if (event == DEV_EVENT_TXDOWN)				fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);			else				fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);			break;		case DEV_STATE_STOPWAIT_RX:			if (event == DEV_EVENT_RXDOWN)				fsm_newstate(fi, DEV_STATE_STOPPED);			break;		case DEV_STATE_STOPWAIT_TX:			if (event == DEV_EVENT_TXDOWN)				fsm_newstate(fi, DEV_STATE_STOPPED);			break;	}}static const fsm_node dev_fsm[] = {	{ DEV_STATE_STOPPED,        DEV_EVENT_START,   dev_action_start  },	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_START,   dev_action_start  },	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RXDOWN,  dev_action_chdown },	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_TXDOWN,  dev_action_chdown },	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_START,   dev_action_start  },	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXUP,    dev_action_chup   },	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_TXUP,    dev_action_chup   },	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXDOWN,  dev_action_chdown },	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_START,   dev_action_start  },	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RXUP,    dev_action_chup   },	{ DEV_STATE_STOPWA

⌨️ 快捷键说明

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