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

📄 scc.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	grp1 = scc->kiss.group;		for (k = 0; k < (Nchips * 2); k++)	{		scc2 = &SCC_Info[k];		grp2 = scc2->kiss.group;				if (scc2 == scc || !(scc2->dev && grp2))			continue;				if ((grp1 & 0x3f) == (grp2 & 0x3f))		{			if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )				return 1;						if ( (grp1 & RXGROUP) && scc2->dcd )				return 1;		}	}	return 0;}/* DWAIT and SLOTTIME expired * * fulldup == 0:  DCD is active or Rand > P-persistence: start t_busy timer *                else key trx and start txdelay * fulldup == 1:  key trx and start txdelay * fulldup == 2:  mintime expired, reset status or key trx and start txdelay */static void t_dwait(unsigned long channel){	struct scc_channel *scc = (struct scc_channel *) channel;		if (scc->stat.tx_state == TXS_WAIT)	/* maxkeyup or idle timeout */	{		if (skb_queue_len(&scc->tx_queue) == 0)	/* nothing to send */		{			scc->stat.tx_state = TXS_IDLE;			netif_wake_queue(scc->dev);	/* t_maxkeyup locked it. */			return;		}		scc->stat.tx_state = TXS_BUSY;	}	if (scc->kiss.fulldup == KISS_DUPLEX_HALF)	{		Rand = Rand * 17 + 31;				if (scc->dcd || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )		{			scc_start_defer(scc);			scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);			return ;		}	}	if ( !(scc->wreg[R5] & RTS) )	{		scc_key_trx(scc, TX_ON);		scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);	} else {		scc_start_tx_timer(scc, t_txdelay, 0);	}}/* TXDELAY expired * * kick transmission by a fake scc_txint(scc), start 'maxkeyup' watchdog. */static void t_txdelay(unsigned long channel){	struct scc_channel *scc = (struct scc_channel *) channel;	scc_start_maxkeyup(scc);	if (scc->tx_buff == NULL)	{		disable_irq(scc->irq);		scc_txint(scc);			enable_irq(scc->irq);	}}	/* TAILTIME expired * * switch off transmitter. If we were stopped by Maxkeyup restart * transmission after 'mintime' seconds */static void t_tail(unsigned long channel){	struct scc_channel *scc = (struct scc_channel *) channel;	unsigned long flags;	 	save_flags(flags); 	cli();  	del_timer(&scc->tx_wdog);	 	scc_key_trx(scc, TX_OFF); 	restore_flags(flags); 	if (scc->stat.tx_state == TXS_TIMEOUT)		/* we had a timeout? */ 	{ 		scc->stat.tx_state = TXS_WAIT; 		if (scc->kiss.mintime != TIMER_OFF)	/* try it again */ 			scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100); 		else 			scc_start_tx_timer(scc, t_dwait, 0); 		return; 	} 	 	scc->stat.tx_state = TXS_IDLE;	netif_wake_queue(scc->dev);}/* BUSY timeout * * throw away send buffers if DCD remains active too long. */static void t_busy(unsigned long channel){	struct scc_channel *scc = (struct scc_channel *) channel;	del_timer(&scc->tx_t);	netif_stop_queue(scc->dev);	/* don't pile on the wabbit! */	scc_discard_buffers(scc);	scc->stat.txerrs++;	scc->stat.tx_state = TXS_IDLE;	netif_wake_queue(scc->dev);	}/* MAXKEYUP timeout * * this is our watchdog. */static void t_maxkeyup(unsigned long channel){	struct scc_channel *scc = (struct scc_channel *) channel;	unsigned long flags;	save_flags(flags);	cli();	/* 	 * let things settle down before we start to	 * accept new data.	 */	netif_stop_queue(scc->dev);	scc_discard_buffers(scc);	del_timer(&scc->tx_t);	cl(scc, R1, TxINT_ENAB);	/* force an ABORT, but don't */	cl(scc, R15, TxUIE);		/* count it. */	OutReg(scc->ctrl, R0, RES_Tx_P);	restore_flags(flags);	scc->stat.txerrs++;	scc->stat.tx_state = TXS_TIMEOUT;	scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);}/* IDLE timeout * * in fulldup mode 2 it keys down the transmitter after 'idle' seconds * of inactivity. We will not restart transmission before 'mintime' * expires. */static void t_idle(unsigned long channel){	struct scc_channel *scc = (struct scc_channel *) channel;		del_timer(&scc->tx_wdog);	scc_key_trx(scc, TX_OFF);	if (scc->kiss.mintime != TIMER_OFF)		scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);	scc->stat.tx_state = TXS_WAIT;}static void scc_init_timer(struct scc_channel *scc){	unsigned long flags;		save_flags(flags); 	cli();		scc->stat.tx_state = TXS_IDLE;	restore_flags(flags);}/* ******************************************************************** *//* *			Set/get L1 parameters			      * *//* ******************************************************************** *//* * this will set the "hardware" parameters through KISS commands or ioctl() */#define CAST(x) (unsigned long)(x)static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg){	switch (cmd)	{		case PARAM_TXDELAY:	scc->kiss.txdelay=arg;		break;		case PARAM_PERSIST:	scc->kiss.persist=arg;		break;		case PARAM_SLOTTIME:	scc->kiss.slottime=arg;		break;		case PARAM_TXTAIL:	scc->kiss.tailtime=arg;		break;		case PARAM_FULLDUP:	scc->kiss.fulldup=arg;		break;		case PARAM_DTR:		break; /* does someone need this? */		case PARAM_GROUP:	scc->kiss.group=arg;		break;		case PARAM_IDLE:	scc->kiss.idletime=arg;		break;		case PARAM_MIN:		scc->kiss.mintime=arg;		break;		case PARAM_MAXKEY:	scc->kiss.maxkeyup=arg;		break;		case PARAM_WAIT:	scc->kiss.waittime=arg;		break;		case PARAM_MAXDEFER:	scc->kiss.maxdefer=arg;		break;		case PARAM_TX:		scc->kiss.tx_inhibit=arg;	break;		case PARAM_SOFTDCD:				scc->kiss.softdcd=arg;			if (arg)			{				or(scc, R15, SYNCIE);				cl(scc, R15, DCDIE);				start_hunt(scc);			} else {				or(scc, R15, DCDIE);				cl(scc, R15, SYNCIE);			}			break;						case PARAM_SPEED:			if (arg < 256)				scc->modem.speed=arg*100;			else				scc->modem.speed=arg;			if (scc->stat.tx_state == 0)	/* only switch baudrate on rx... ;-) */				set_speed(scc);			break;					case PARAM_RTS:				if ( !(scc->wreg[R5] & RTS) )			{				if (arg != TX_OFF)					scc_key_trx(scc, TX_ON);					scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);			} else {				if (arg == TX_OFF)				{					scc->stat.tx_state = TXS_BUSY;					scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);				}			}			break;					case PARAM_HWEVENT:			scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);			break;		default:		return -EINVAL;	}		return 0;} static unsigned long scc_get_param(struct scc_channel *scc, unsigned int cmd){	switch (cmd)	{		case PARAM_TXDELAY:	return CAST(scc->kiss.txdelay);		case PARAM_PERSIST:	return CAST(scc->kiss.persist);		case PARAM_SLOTTIME:	return CAST(scc->kiss.slottime);		case PARAM_TXTAIL:	return CAST(scc->kiss.tailtime);		case PARAM_FULLDUP:	return CAST(scc->kiss.fulldup);		case PARAM_SOFTDCD:	return CAST(scc->kiss.softdcd);		case PARAM_DTR:		return CAST((scc->wreg[R5] & DTR)? 1:0);		case PARAM_RTS:		return CAST((scc->wreg[R5] & RTS)? 1:0);		case PARAM_SPEED:	return CAST(scc->modem.speed);		case PARAM_GROUP:	return CAST(scc->kiss.group);		case PARAM_IDLE:	return CAST(scc->kiss.idletime);		case PARAM_MIN:		return CAST(scc->kiss.mintime);		case PARAM_MAXKEY:	return CAST(scc->kiss.maxkeyup);		case PARAM_WAIT:	return CAST(scc->kiss.waittime);		case PARAM_MAXDEFER:	return CAST(scc->kiss.maxdefer);		case PARAM_TX:		return CAST(scc->kiss.tx_inhibit);		default:		return NO_SUCH_PARAM;	}}#undef CAST/* ******************************************************************* *//* *			Send calibration pattern		     * *//* ******************************************************************* */static void scc_stop_calibrate(unsigned long channel){	struct scc_channel *scc = (struct scc_channel *) channel;	unsigned long flags;		save_flags(flags);	cli();	del_timer(&scc->tx_wdog);	scc_key_trx(scc, TX_OFF);	wr(scc, R6, 0);	wr(scc, R7, FLAG);	Outb(scc->ctrl,RES_EXT_INT);	/* reset ext/status interrupts */	Outb(scc->ctrl,RES_EXT_INT);	netif_wake_queue(scc->dev);	restore_flags(flags);}static voidscc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern){	unsigned long flags;		save_flags(flags);	cli();	netif_stop_queue(scc->dev);	scc_discard_buffers(scc);	del_timer(&scc->tx_wdog);	scc->tx_wdog.data = (unsigned long) scc;	scc->tx_wdog.function = scc_stop_calibrate;	scc->tx_wdog.expires = jiffies + HZ*duration;	add_timer(&scc->tx_wdog);	/* This doesn't seem to work. Why not? */		wr(scc, R6, 0);	wr(scc, R7, pattern);	/* 	 * Don't know if this works. 	 * Damn, where is my Z8530 programming manual...? 	 */	Outb(scc->ctrl,RES_EXT_INT);	/* reset ext/status interrupts */	Outb(scc->ctrl,RES_EXT_INT);	scc_key_trx(scc, TX_ON);	restore_flags(flags);}/* ******************************************************************* *//* *		Init channel structures, special HW, etc...	     * *//* ******************************************************************* *//* * Reset the Z8530s and setup special hardware */static void z8530_init(void){	struct scc_channel *scc;	int chip, k;	unsigned long flags;	char *flag;	printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);		flag=" ";	for (k = 0; k < NR_IRQS; k++)		if (Ivec[k].used) 		{			printk("%s%d", flag, k);			flag=",";		}	printk("\n");	/* reset and pre-init all chips in the system */	for (chip = 0; chip < Nchips; chip++)	{		scc=&SCC_Info[2*chip];		if (!scc->ctrl) continue;		/* Special SCC cards */		if(scc->brand & EAGLE)			/* this is an EAGLE card */			Outb(scc->special,0x08);	/* enable interrupt on the board */					if(scc->brand & (PC100 | PRIMUS))	/* this is a PC100/PRIMUS card */			Outb(scc->special,scc->option);	/* set the MODEM mode (0x22) */					/* Reset and pre-init Z8530 */		save_flags(flags);		cli();				Outb(scc->ctrl, 0);		OutReg(scc->ctrl,R9,FHWRES);		/* force hardware reset */		udelay(100);				/* give it 'a bit' more time than required */		wr(scc, R2, chip*16);			/* interrupt vector */		wr(scc, R9, VIS);			/* vector includes status */		        	restore_flags(flags);        } 	Driver_Initialized = 1;}/* * Allocate device structure, err, instance, and register driver */static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev){	struct net_device *dev;	if (dev_get(name))	{		printk(KERN_INFO "Z8530drv: device %s already exists.\n", name);		return -EEXIST;	}	if ((scc->dev = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL)		return -ENOMEM;	dev = scc->dev;	memset(dev, 0, sizeof(struct net_device));	strcpy(dev->name, name);	dev->priv = (void *) scc;	dev->init = scc_net_init;	if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0) {		kfree(dev);                return -EIO;        }	SET_MODULE_OWNER(dev);	return 0;}/* ******************************************************************** *//* *			    Network driver methods		      * *//* ******************************************************************** */static unsigned char ax25_bcast[AX25_ADDR_LEN] ={'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};static unsigned char ax25_nocall[AX25_ADDR_LEN] ={'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};/* ----> Initialize device <----- */static int scc_net_init(struct net_device *dev){	dev->tx_queue_len    = 16;	/* should be enough... */	dev->open            = scc_net_open;	dev->stop	     = scc_net_close;	dev->hard_start_xmit = scc_net_tx;	dev->hard_header     = ax25_encapsulate;	dev->rebuild_header  = ax25_rebuild_header;	dev->set_mac_address = scc_net_set_mac_address;	dev->get_stats       = scc_net_get_stats;	dev->do_ioctl        = scc_net_ioctl;	dev->tx_timeout      = NULL;	memcpy(dev->broadcast, ax25_bcast,  AX25_ADDR_LEN);	memcpy(dev->dev_addr,  ax25_nocall, AX25_ADDR_LEN); 	dev->flags      = 0;	dev->type = ARPHRD_AX25;	dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;	dev->mtu = AX25_DEF_PACLEN;	dev->addr_len = AX25_ADDR_LEN;	return 0;}/* ----> open network device <---- */static int scc_net_open(struct net_device *dev){	struct scc_channel *scc = (struct scc_channel *) dev->priv; 	if (!scc->init)		return -EINVAL;	scc->tx_buff = NULL;	skb_queue_head_init(&scc->tx_queue); 	init_channel(scc);	netif_start_queue(dev);	return 0;}/* ----> close network device <---- */static int scc_net_close(struct net_device *dev){	struct scc_channel *scc = (struct scc_channel *) dev->priv;	unsigned long flags;	netif_stop_queue(dev);	save_flags(flags); 	cli();		Outb(scc->ctrl,0);		/* Make sure pointer is written */	wr(scc,R1,0);			/* disable interrupts */	wr(scc,R3,0);	del_timer(&scc->tx_t);	del_timer(&scc->tx_wdog);	restore_flags(flags);	

⌨️ 快捷键说明

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