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

📄 sdla.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	flp = slave->priv;	for(i=0;i<CONFIG_DLCI_MAX;i++)	{		if (!flp->master[i])			break;		if (abs(flp->dlci[i]) == *(short *)(master->dev_addr))			return(-EADDRINUSE);	} 	if (i == CONFIG_DLCI_MAX)		return(-EMLINK);  /* #### Alan: Comments on this ?? */	flp->master[i] = master;	flp->dlci[i] = -*(short *)(master->dev_addr);	master->mtu = slave->mtu;	if (netif_running(slave)) {		if (flp->config.station == FRAD_STATION_CPE)			sdla_reconfig(slave);		else			sdla_cmd(slave, SDLA_ADD_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);	}	return(0);}int sdla_deassoc(struct net_device *slave, struct net_device *master){	struct frad_local *flp;	int               i;	flp = slave->priv;	for(i=0;i<CONFIG_DLCI_MAX;i++)		if (flp->master[i] == master)			break;	if (i == CONFIG_DLCI_MAX)		return(-ENODEV);	flp->master[i] = NULL;	flp->dlci[i] = 0;	if (netif_running(slave)) {		if (flp->config.station == FRAD_STATION_CPE)			sdla_reconfig(slave);		else			sdla_cmd(slave, SDLA_DELETE_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);	}	return(0);}int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get){	struct frad_local *flp;	struct dlci_local *dlp;	int               i;	short             len, ret;	flp = slave->priv;	for(i=0;i<CONFIG_DLCI_MAX;i++)		if (flp->master[i] == master)			break;	if (i == CONFIG_DLCI_MAX)		return(-ENODEV);	dlp = master->priv;	ret = SDLA_RET_OK;	len = sizeof(struct dlci_conf);	if (netif_running(slave)) {		if (get)			ret = sdla_cmd(slave, SDLA_READ_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0,  			            NULL, 0, &dlp->config, &len);		else			ret = sdla_cmd(slave, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0,  			            &dlp->config, sizeof(struct dlci_conf) - 4 * sizeof(short), NULL, NULL);	}	return(ret == SDLA_RET_OK ? 0 : -EIO);}/************************** * * now for the Linux driver  * **************************//* NOTE: the DLCI driver deals with freeing the SKB!! */static int sdla_transmit(struct sk_buff *skb, struct net_device *dev){	struct frad_local *flp;	int               ret, addr, accept, i;	short             size;	unsigned long     flags;	struct buf_entry  *pbuf;	flp = dev->priv;	ret = 0;	accept = 1;	netif_stop_queue(dev);	/*	 * stupid GateD insists on setting up the multicast router thru us	 * and we're ill equipped to handle a non Frame Relay packet at this	 * time!	 */	accept = 1;	switch (dev->type)	{		case ARPHRD_FRAD:			if (skb->dev->type != ARPHRD_DLCI)			{				printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);				accept = 0;			}			break;		default:			printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);			accept = 0;			break;	}	if (accept)	{		/* this is frame specific, but till there's a PPP module, it's the default */		switch (flp->type)		{			case SDLA_S502A:			case SDLA_S502E:				ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);				break;				case SDLA_S508:				size = sizeof(addr);				ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);				if (ret == SDLA_RET_OK)				{					spin_lock_irqsave(&sdla_lock, flags);					SDLA_WINDOW(dev, addr);					pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));					__sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);					SDLA_WINDOW(dev, addr);					pbuf->opp_flag = 1;					spin_unlock_irqrestore(&sdla_lock, flags);				}				break;		}		switch (ret)		{			case SDLA_RET_OK:				flp->stats.tx_packets++;				ret = DLCI_RET_OK;				break;			case SDLA_RET_CIR_OVERFLOW:			case SDLA_RET_BUF_OVERSIZE:			case SDLA_RET_NO_BUFS:				flp->stats.tx_dropped++;				ret = DLCI_RET_DROP;				break;			default:				flp->stats.tx_errors++;				ret = DLCI_RET_ERR;				break;		}	}	netif_wake_queue(dev);	for(i=0;i<CONFIG_DLCI_MAX;i++)	{		if(flp->master[i]!=NULL)			netif_wake_queue(flp->master[i]);	}			return(ret);}static void sdla_receive(struct net_device *dev){	struct net_device	  *master;	struct frad_local *flp;	struct dlci_local *dlp;	struct sk_buff	 *skb;	struct sdla_cmd	*cmd;	struct buf_info	*pbufi;	struct buf_entry  *pbuf;	unsigned long	  flags;	int               i=0, received, success, addr, buf_base, buf_top;	short             dlci, len, len2, split;	flp = dev->priv;	success = 1;	received = addr = buf_top = buf_base = 0;	len = dlci = 0;	skb = NULL;	master = NULL;	cmd = NULL;	pbufi = NULL;	pbuf = NULL;	spin_lock_irqsave(&sdla_lock, flags);	switch (flp->type)	{		case SDLA_S502A:		case SDLA_S502E:			cmd = (void *) (dev->mem_start + (SDLA_502_RCV_BUF & SDLA_ADDR_MASK));			SDLA_WINDOW(dev, SDLA_502_RCV_BUF);			success = cmd->opp_flag;			if (!success)				break;			dlci = cmd->dlci;			len = cmd->length;			break;		case SDLA_S508:			pbufi = (void *) (dev->mem_start + (SDLA_508_RXBUF_INFO & SDLA_ADDR_MASK));			SDLA_WINDOW(dev, SDLA_508_RXBUF_INFO);			pbuf = (void *) (dev->mem_start + ((pbufi->rse_base + flp->buffer * sizeof(struct buf_entry)) & SDLA_ADDR_MASK));			success = pbuf->opp_flag;			if (!success)				break;			buf_top = pbufi->buf_top;			buf_base = pbufi->buf_base;			dlci = pbuf->dlci;			len = pbuf->length;			addr = pbuf->buf_addr;			break;	}	/* common code, find the DLCI and get the SKB */	if (success)	{		for (i=0;i<CONFIG_DLCI_MAX;i++)			if (flp->dlci[i] == dlci)				break;		if (i == CONFIG_DLCI_MAX)		{			printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci);			flp->stats.rx_errors++;			success = 0;		}	}	if (success)	{		master = flp->master[i];		skb = dev_alloc_skb(len + sizeof(struct frhdr));		if (skb == NULL) 		{			printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);			flp->stats.rx_dropped++; 			success = 0;		}		else			skb_reserve(skb, sizeof(struct frhdr));	}	/* pick up the data */	switch (flp->type)	{		case SDLA_S502A:		case SDLA_S502E:			if (success)				__sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len);			SDLA_WINDOW(dev, SDLA_502_RCV_BUF);			cmd->opp_flag = 0;			break;		case SDLA_S508:			if (success)			{				/* is this buffer split off the end of the internal ring buffer */				split = addr + len > buf_top + 1 ? len - (buf_top - addr + 1) : 0;				len2 = len - split;				__sdla_read(dev, addr, skb_put(skb, len2), len2);				if (split)					__sdla_read(dev, buf_base, skb_put(skb, split), split);			}			/* increment the buffer we're looking at */			SDLA_WINDOW(dev, SDLA_508_RXBUF_INFO);			flp->buffer = (flp->buffer + 1) % pbufi->rse_num;			pbuf->opp_flag = 0;			break;	}	if (success)	{		flp->stats.rx_packets++;		dlp = master->priv;		(*dlp->receive)(skb, master);	}	spin_unlock_irqrestore(&sdla_lock, flags);}static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs){	struct net_device     *dev;	struct frad_local *flp;	char              byte;	dev = dev_id;	if (dev == NULL)	{		printk(KERN_WARNING "sdla_isr(): irq %d for unknown device.\n", irq);		return IRQ_NONE;	}	flp = dev->priv;	if (!flp->initialized)	{		printk(KERN_WARNING "%s: irq %d for uninitialized device.\n", dev->name, irq);		return IRQ_NONE;	}	byte = sdla_byte(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE);	switch (byte)	{		case SDLA_INTR_RX:			sdla_receive(dev);			break;		/* the command will get an error return, which is processed above */		case SDLA_INTR_MODEM:		case SDLA_INTR_STATUS:			sdla_cmd(dev, SDLA_READ_DLC_STATUS, 0, 0, NULL, 0, NULL, NULL);			break;		case SDLA_INTR_TX:		case SDLA_INTR_COMPLETE:		case SDLA_INTR_TIMER:			printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte);			break;	}	/* the S502E requires a manual acknowledgement of the interrupt */ 	if (flp->type == SDLA_S502E)	{		flp->state &= ~SDLA_S502E_INTACK;		outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);		flp->state |= SDLA_S502E_INTACK;		outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);	}	/* this clears the byte, informing the Z80 we're done */	byte = 0;	sdla_write(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));	return IRQ_HANDLED;}static void sdla_poll(unsigned long device){	struct net_device	  *dev;	struct frad_local *flp;	dev = (struct net_device *) device;	flp = dev->priv;	if (sdla_byte(dev, SDLA_502_RCV_BUF))		sdla_receive(dev);	flp->timer.expires = 1;	add_timer(&flp->timer);}static int sdla_close(struct net_device *dev){	struct frad_local *flp;	struct intr_info  intr;	int               len, i;	short             dlcis[CONFIG_DLCI_MAX];	flp = dev->priv;	len = 0;	for(i=0;i<CONFIG_DLCI_MAX;i++)		if (flp->dlci[i])			dlcis[len++] = abs(flp->dlci[i]);	len *= 2;	if (flp->config.station == FRAD_STATION_NODE)	{		for(i=0;i<CONFIG_DLCI_MAX;i++)			if (flp->dlci[i] > 0) 				sdla_cmd(dev, SDLA_DEACTIVATE_DLCI, 0, 0, dlcis, len, NULL, NULL);		sdla_cmd(dev, SDLA_DELETE_DLCI, 0, 0, &flp->dlci[i], sizeof(flp->dlci[i]), NULL, NULL);	}	memset(&intr, 0, sizeof(intr));	/* let's start up the reception */	switch(flp->type)	{		case SDLA_S502A:			del_timer(&flp->timer); 			break;		case SDLA_S502E:			sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(char) + sizeof(short), NULL, NULL);			flp->state &= ~SDLA_S502E_INTACK;			outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);			break;		case SDLA_S507:			break;		case SDLA_S508:			sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(struct intr_info), NULL, NULL);			flp->state &= ~SDLA_S508_INTEN;			outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);			break;	}	sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);	netif_stop_queue(dev);		return(0);}struct conf_data {	struct frad_conf config;	short            dlci[CONFIG_DLCI_MAX];};static int sdla_open(struct net_device *dev){	struct frad_local *flp;	struct dlci_local *dlp;	struct conf_data  data;	struct intr_info  intr;	int               len, i;	char              byte;	flp = dev->priv;	if (!flp->initialized)		return(-EPERM);	if (!flp->configured)		return(-EPERM);	/* time to send in the configuration */	len = 0;	for(i=0;i<CONFIG_DLCI_MAX;i++)		if (flp->dlci[i])			data.dlci[len++] = abs(flp->dlci[i]);	len *= 2;	memcpy(&data.config, &flp->config, sizeof(struct frad_conf));	len += sizeof(struct frad_conf);	sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);	sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL);	if (flp->type == SDLA_S508)		flp->buffer = 0;	sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);	/* let's start up the reception */	memset(&intr, 0, sizeof(intr));	switch(flp->type)	{		case SDLA_S502A:			flp->timer.expires = 1;			add_timer(&flp->timer);			break;		case SDLA_S502E:			flp->state |= SDLA_S502E_ENABLE;			outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);			flp->state |= SDLA_S502E_INTACK;			outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);			byte = 0;			sdla_write(dev, SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));			intr.flags = SDLA_INTR_RX | SDLA_INTR_STATUS | SDLA_INTR_MODEM;			sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(char) + sizeof(short), NULL, NULL);			break;		case SDLA_S507:			break;		case SDLA_S508:			flp->state |= SDLA_S508_INTEN;			outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);			byte = 0;			sdla_write(dev, SDLA_508_IRQ_INTERFACE, &byte, sizeof(byte));			intr.flags = SDLA_INTR_RX | SDLA_INTR_STATUS | SDLA_INTR_MODEM;			intr.irq = dev->irq;			sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(struct intr_info), NULL, NULL);			break;	}	if (flp->config.station == FRAD_STATION_CPE)	{		byte = SDLA_ICS_STATUS_ENQ;		sdla_cmd(dev, SDLA_ISSUE_IN_CHANNEL_SIGNAL, 0, 0, &byte, sizeof(byte), NULL, NULL);	}	else	{		sdla_cmd(dev, SDLA_ADD_DLCI, 0, 0, data.dlci, len - sizeof(struct frad_conf), NULL, NULL);		for(i=0;i<CONFIG_DLCI_MAX;i++)			if (flp->dlci[i] > 0)				sdla_cmd(dev, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], 2*sizeof(flp->dlci[i]), NULL, NULL);	}	/* configure any specific DLCI settings */	for(i=0;i<CONFIG_DLCI_MAX;i++)		if (flp->dlci[i])		{			dlp = flp->master[i]->priv;			if (dlp->configured)				sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf), NULL, NULL);		}	netif_start_queue(dev);		return(0);}static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, int get){	struct frad_local *flp;	struct conf_data  data;	int               i;	short             size;	if (dev->type == 0xFFFF)		return(-EUNATCH);	flp = dev->priv;	if (!get)	{		if (netif_running(dev))			return(-EBUSY);		if(copy_from_user(&data.config, conf, sizeof(struct frad_conf)))			return -EFAULT;		if (data.config.station & ~FRAD_STATION_NODE)

⌨️ 快捷键说明

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