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

📄 sdla.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			return(-EINVAL);		if (data.config.flags & ~FRAD_VALID_FLAGS)			return(-EINVAL);		if ((data.config.kbaud < 0) || 			 ((data.config.kbaud > 128) && (flp->type != SDLA_S508)))			return(-EINVAL);		if (data.config.clocking & ~(FRAD_CLOCK_INT | SDLA_S508_PORT_RS232))			return(-EINVAL);		if ((data.config.mtu < 0) || (data.config.mtu > SDLA_MAX_MTU))			return(-EINVAL);		if ((data.config.T391 < 5) || (data.config.T391 > 30))			return(-EINVAL);		if ((data.config.T392 < 5) || (data.config.T392 > 30))			return(-EINVAL);		if ((data.config.N391 < 1) || (data.config.N391 > 255))			return(-EINVAL);		if ((data.config.N392 < 1) || (data.config.N392 > 10))			return(-EINVAL);		if ((data.config.N393 < 1) || (data.config.N393 > 10))			return(-EINVAL);		memcpy(&flp->config, &data.config, sizeof(struct frad_conf));		flp->config.flags |= SDLA_DIRECT_RECV;		if (flp->type == SDLA_S508)			flp->config.flags |= SDLA_TX70_RX30;		if (dev->mtu != flp->config.mtu)		{			/* this is required to change the MTU */			dev->mtu = flp->config.mtu;			for(i=0;i<CONFIG_DLCI_MAX;i++)				if (flp->master[i])					flp->master[i]->mtu = flp->config.mtu;		}		flp->config.mtu += sizeof(struct frhdr);		/* off to the races! */		if (!flp->configured)			sdla_start(dev);		flp->configured = 1;	}	else	{		/* no sense reading if the CPU isn't started */		if (netif_running(dev))		{			size = sizeof(data);			if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)				return(-EIO);		}		else			if (flp->configured)				memcpy(&data.config, &flp->config, sizeof(struct frad_conf));			else				memset(&data.config, 0, sizeof(struct frad_conf));		memcpy(&flp->config, &data.config, sizeof(struct frad_conf));		data.config.flags &= FRAD_VALID_FLAGS;		data.config.mtu -= data.config.mtu > sizeof(struct frhdr) ? sizeof(struct frhdr) : data.config.mtu;		return copy_to_user(conf, &data.config, sizeof(struct frad_conf))?-EFAULT:0;	}	return(0);}static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int read){	struct sdla_mem mem;	char	*temp;	if(copy_from_user(&mem, info, sizeof(mem)))		return -EFAULT;			if (read)	{			temp = kmalloc(mem.len, GFP_KERNEL);		if (!temp)			return(-ENOMEM);		memset(temp, 0, mem.len);		sdla_read(dev, mem.addr, temp, mem.len);		if(copy_to_user(mem.data, temp, mem.len))		{			kfree(temp);			return -EFAULT;		}		kfree(temp);	}	else	{		temp = kmalloc(mem.len, GFP_KERNEL);		if (!temp)			return(-ENOMEM);		if(copy_from_user(temp, mem.data, mem.len))		{			kfree(temp);			return -EFAULT;		}		sdla_write(dev, mem.addr, temp, mem.len);		kfree(temp);	}	return(0);}static int sdla_reconfig(struct net_device *dev){	struct frad_local *flp;	struct conf_data  data;	int               i, len;	flp = dev->priv;	len = 0;	for(i=0;i<CONFIG_DLCI_MAX;i++)		if (flp->dlci[i])			data.dlci[len++] = flp->dlci[i];	len *= 2;	memcpy(&data, &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);	sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);	return(0);}static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	struct frad_local *flp;	if(!capable(CAP_NET_ADMIN))		return -EPERM;			flp = dev->priv;	if (!flp->initialized)		return(-EINVAL);	switch (cmd)	{		case FRAD_GET_CONF:		case FRAD_SET_CONF:			return(sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF));		case SDLA_IDENTIFY:			ifr->ifr_flags = flp->type;			break;		case SDLA_CPUSPEED:			return(sdla_cpuspeed(dev, ifr)); /* ==========================================================NOTE:  This is rather a useless action right now, as the       current driver does not support protocols other than       FR.  However, Sangoma has modules for a number of       other protocols in the works.============================================================*/		case SDLA_PROTOCOL:			if (flp->configured)				return(-EALREADY);			switch (ifr->ifr_flags)			{				case ARPHRD_FRAD:					dev->type = ifr->ifr_flags;					break;				default:					return(-ENOPROTOOPT);			}			break;		case SDLA_CLEARMEM:			sdla_clear(dev);			break;		case SDLA_WRITEMEM:		case SDLA_READMEM:			return(sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM));		case SDLA_START:			sdla_start(dev);			break;		case SDLA_STOP:			sdla_stop(dev);			break;		default:			return(-EOPNOTSUPP);	}	return(0);}int sdla_change_mtu(struct net_device *dev, int new_mtu){	struct frad_local *flp;	flp = dev->priv;	if (netif_running(dev))		return(-EBUSY);	/* for now, you can't change the MTU! */	return(-EOPNOTSUPP);}int sdla_set_config(struct net_device *dev, struct ifmap *map){	struct frad_local *flp;	int               i;	char              byte;	unsigned base;	int err = -EINVAL;	flp = dev->priv;	if (flp->initialized)		return(-EINVAL);	for(i=0;i < sizeof(valid_port) / sizeof (int) ; i++)		if (valid_port[i] == map->base_addr)			break;   	if (i == sizeof(valid_port) / sizeof(int))		return(-EINVAL);	if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){		printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr);		return(-EINVAL);	}	base = map->base_addr;	/* test for card types, S502A, S502E, S507, S508                 */	/* these tests shut down the card completely, so clear the state */	flp->type = SDLA_UNKNOWN;	flp->state = 0;   	for(i=1;i<SDLA_IO_EXTENTS;i++)		if (inb(base + i) != 0xFF)			break;	if (i == SDLA_IO_EXTENTS) {   		outb(SDLA_HALT, base + SDLA_REG_Z80_CONTROL);		if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x08) {			outb(SDLA_S502E_INTACK, base + SDLA_REG_CONTROL);			if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x0C) {				outb(SDLA_HALT, base + SDLA_REG_CONTROL);				flp->type = SDLA_S502E;				goto got_type;			}		}	}	for(byte=inb(base),i=0;i<SDLA_IO_EXTENTS;i++)		if (inb(base + i) != byte)			break;	if (i == SDLA_IO_EXTENTS) {		outb(SDLA_HALT, base + SDLA_REG_CONTROL);		if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x30) {			outb(SDLA_S507_ENABLE, base + SDLA_REG_CONTROL);			if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x32) {				outb(SDLA_HALT, base + SDLA_REG_CONTROL);				flp->type = SDLA_S507;				goto got_type;			}		}	}	outb(SDLA_HALT, base + SDLA_REG_CONTROL);	if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x00) {		outb(SDLA_S508_INTEN, base + SDLA_REG_CONTROL);		if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x10) {			outb(SDLA_HALT, base + SDLA_REG_CONTROL);			flp->type = SDLA_S508;			goto got_type;		}	}	outb(SDLA_S502A_HALT, base + SDLA_REG_CONTROL);	if (inb(base + SDLA_S502_STS) == 0x40) {		outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);		if (inb(base + SDLA_S502_STS) == 0x40) {			outb(SDLA_S502A_INTEN, base + SDLA_REG_CONTROL);			if (inb(base + SDLA_S502_STS) == 0x44) {				outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);				flp->type = SDLA_S502A;				goto got_type;			}		}	}	printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);	err = -ENODEV;	goto fail;got_type:	switch(base) {		case 0x270:		case 0x280:		case 0x380: 		case 0x390:			if (flp->type != SDLA_S508 && flp->type != SDLA_S507)				goto fail;	}	switch (map->irq) {		case 2:			if (flp->type != SDLA_S502E)				goto fail;			break;		case 10:		case 11:		case 12:		case 15:		case 4:			if (flp->type != SDLA_S508 && flp->type != SDLA_S507)				goto fail;			break;		case 3:		case 5:		case 7:			if (flp->type == SDLA_S502A)				goto fail;			break;		default:			goto fail;	}	err = -EAGAIN;	if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev)) 		goto fail;	if (flp->type == SDLA_S507) {		switch(dev->irq) {			case 3:				flp->state = SDLA_S507_IRQ3;				break;			case 4:				flp->state = SDLA_S507_IRQ4;				break;			case 5:				flp->state = SDLA_S507_IRQ5;				break;			case 7:				flp->state = SDLA_S507_IRQ7;				break;			case 10:				flp->state = SDLA_S507_IRQ10;				break;			case 11:				flp->state = SDLA_S507_IRQ11;				break;			case 12:				flp->state = SDLA_S507_IRQ12;				break;			case 15:				flp->state = SDLA_S507_IRQ15;				break;		}	}	for(i=0;i < sizeof(valid_mem) / sizeof (int) ; i++)		if (valid_mem[i] == map->mem_start)			break;   	err = -EINVAL;	if (i == sizeof(valid_mem) / sizeof(int))		goto fail2;	if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)		goto fail2;	if (flp->type != SDLA_S507 && map->mem_start >> 16 == 0x0B)		goto fail2;	if (flp->type == SDLA_S507 && map->mem_start >> 16 == 0x0D)		goto fail2;	byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0;	byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0));	switch(flp->type) {		case SDLA_S502A:		case SDLA_S502E:			switch (map->mem_start >> 16) {				case 0x0A:					byte |= SDLA_S502_SEG_A;					break;				case 0x0C:					byte |= SDLA_S502_SEG_C;					break;				case 0x0D:					byte |= SDLA_S502_SEG_D;					break;				case 0x0E:					byte |= SDLA_S502_SEG_E;					break;			}			break;		case SDLA_S507:			switch (map->mem_start >> 16) {				case 0x0A:					byte |= SDLA_S507_SEG_A;					break;				case 0x0B:					byte |= SDLA_S507_SEG_B;					break;				case 0x0C:					byte |= SDLA_S507_SEG_C;					break;				case 0x0E:					byte |= SDLA_S507_SEG_E;					break;			}			break;		case SDLA_S508:			switch (map->mem_start >> 16) {				case 0x0A:					byte |= SDLA_S508_SEG_A;					break;				case 0x0C:					byte |= SDLA_S508_SEG_C;					break;				case 0x0D:					byte |= SDLA_S508_SEG_D;					break;				case 0x0E:					byte |= SDLA_S508_SEG_E;					break;			}			break;	}	/* set the memory bits, and enable access */	outb(byte, base + SDLA_REG_PC_WINDOW);	switch(flp->type)	{		case SDLA_S502E:			flp->state = SDLA_S502E_ENABLE;			break;		case SDLA_S507:			flp->state |= SDLA_MEMEN;			break;		case SDLA_S508:			flp->state = SDLA_MEMEN;			break;	}	outb(flp->state, base + SDLA_REG_CONTROL);	dev->irq = map->irq;	dev->base_addr = base;	dev->mem_start = map->mem_start;	dev->mem_end = dev->mem_start + 0x2000;	flp->initialized = 1;	return 0;fail2:	free_irq(map->irq, dev);fail:	release_region(base, SDLA_IO_EXTENTS);	return err;} static struct net_device_stats *sdla_stats(struct net_device *dev){	struct frad_local *flp;	flp = dev->priv;	return(&flp->stats);}static void setup_sdla(struct net_device *dev){	struct frad_local *flp = dev->priv;	netdev_boot_setup_check(dev);	SET_MODULE_OWNER(dev);	dev->flags		= 0;	dev->type		= 0xFFFF;	dev->hard_header_len	= 0;	dev->addr_len		= 0;	dev->mtu		= SDLA_MAX_MTU;	dev->open		= sdla_open;	dev->stop		= sdla_close;	dev->do_ioctl		= sdla_ioctl;	dev->set_config		= sdla_set_config;	dev->get_stats		= sdla_stats;	dev->hard_start_xmit	= sdla_transmit;	dev->change_mtu		= sdla_change_mtu;	flp->activate		= sdla_activate;	flp->deactivate		= sdla_deactivate;	flp->assoc		= sdla_assoc;	flp->deassoc		= sdla_deassoc;	flp->dlci_conf		= sdla_dlci_conf;	init_timer(&flp->timer);	flp->timer.expires	= 1;	flp->timer.data		= (unsigned long) dev;	flp->timer.function	= sdla_poll;}static struct net_device *sdla;static int __init init_sdla(void){	int err;	printk("%s.\n", version);	sdla = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla);	if (!sdla) 		return -ENOMEM;	err = register_netdev(sdla);	if (err) 		free_netdev(sdla);	return err;}static void __exit exit_sdla(void){	struct frad_local *flp = sdla->priv;	unregister_netdev(sdla);	if (flp->initialized) {		free_irq(sdla->irq, sdla);		release_region(sdla->base_addr, SDLA_IO_EXTENTS);	}	del_timer_sync(&flp->timer);	free_netdev(sdla);}MODULE_LICENSE("GPL");module_init(init_sdla);module_exit(exit_sdla);

⌨️ 快捷键说明

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