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

📄 sdla.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
			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 *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);		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, (struct frad_conf *)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, (struct sdla_mem *)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;	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);	dev->base_addr = map->base_addr;	request_region(dev->base_addr, SDLA_IO_EXTENTS, dev->name);	/* 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(dev->base_addr + i) != 0xFF)			break;	if (i == SDLA_IO_EXTENTS)	{   		outb(SDLA_HALT, dev->base_addr + SDLA_REG_Z80_CONTROL);		if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x08)		{			outb(SDLA_S502E_INTACK, dev->base_addr + SDLA_REG_CONTROL);			if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x0C)			{				outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);				flp->type = SDLA_S502E;			}		}	}	if (flp->type == SDLA_UNKNOWN)	{		for(byte=inb(dev->base_addr),i=0;i<SDLA_IO_EXTENTS;i++)			if (inb(dev->base_addr + i) != byte)				break;		if (i == SDLA_IO_EXTENTS)		{			outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);			if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x30)			{				outb(SDLA_S507_ENABLE, dev->base_addr + SDLA_REG_CONTROL);				if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x32)				{					outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);					flp->type = SDLA_S507;				}			}		}	}	if (flp->type == SDLA_UNKNOWN)	{		outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);		if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x00)		{			outb(SDLA_S508_INTEN, dev->base_addr + SDLA_REG_CONTROL);			if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x10)			{				outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL);				flp->type = SDLA_S508;			}		}	}	if (flp->type == SDLA_UNKNOWN)	{		outb(SDLA_S502A_HALT, dev->base_addr + SDLA_REG_CONTROL);		if (inb(dev->base_addr + SDLA_S502_STS) == 0x40)		{			outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);			if (inb(dev->base_addr + SDLA_S502_STS) == 0x40)			{				outb(SDLA_S502A_INTEN, dev->base_addr + SDLA_REG_CONTROL);				if (inb(dev->base_addr + SDLA_S502_STS) == 0x44)				{					outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);					flp->type = SDLA_S502A;				}			}		}	}	if (flp->type == SDLA_UNKNOWN)	{		printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);		return(-ENODEV);	}	switch(dev->base_addr)	{		case 0x270:		case 0x280:		case 0x380: 		case 0x390:			if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507))				return(-EINVAL);	}	switch (map->irq)	{		case 2:			if (flp->type != SDLA_S502E)				return(-EINVAL);			break;		case 10:		case 11:		case 12:		case 15:		case 4:			if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507))				return(-EINVAL);		case 3:		case 5:		case 7:			if (flp->type == SDLA_S502A)				return(-EINVAL);			break;		default:			return(-EINVAL);	}	dev->irq = map->irq;	if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev)) 		return(-EAGAIN);	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;   	if (i == sizeof(valid_mem) / sizeof(int))	/*	 *	FIXME:	 *	BUG BUG BUG: MUST RELEASE THE IRQ WE ALLOCATED IN	 *	ALL THESE CASES	 *	 */		return(-EINVAL);	if ((flp->type == SDLA_S502A) && (((map->mem_start & 0xF000) >> 12) == 0x0E))		return(-EINVAL);	if ((flp->type != SDLA_S507) && ((map->mem_start >> 16) == 0x0B))		return(-EINVAL);	if ((flp->type == SDLA_S507) && ((map->mem_start >> 16) == 0x0D))		return(-EINVAL);	dev->mem_start = map->mem_start;	dev->mem_end = dev->mem_start + 0x2000;	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, dev->base_addr + 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, dev->base_addr + SDLA_REG_CONTROL);	flp->initialized = 1;	return(0);} static struct net_device_stats *sdla_stats(struct net_device *dev){	struct frad_local *flp;	flp = dev->priv;	return(&flp->stats);}int __init sdla_init(struct net_device *dev){	struct frad_local *flp;	/* allocate the private data structure */	flp = kmalloc(sizeof(struct frad_local), GFP_KERNEL);	if (!flp)		return(-ENOMEM);	memset(flp, 0, sizeof(struct frad_local));	dev->priv = flp;	dev->flags		= 0;	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;	dev->type		= 0xFFFF;	dev->hard_header_len = 0;	dev->addr_len		= 0;	dev->mtu		= SDLA_MAX_MTU;	dev_init_buffers(dev);   	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;	return(0);}int __init sdla_c_setup(void){	printk("%s.\n", version);	register_frad(devname);	return 0;}#ifdef MODULEstatic struct net_device sdla0 = {"sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, sdla_init};int init_module(void){	int result;	sdla_c_setup();	if ((result = register_netdev(&sdla0)) != 0)		return result;	return 0;}void cleanup_module(void){	unregister_netdev(&sdla0);	if (sdla0.priv)		kfree(sdla0.priv);	if (sdla0.irq)		free_irq(sdla0.irq, &sdla0);}#endif /* MODULE */

⌨️ 快捷键说明

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