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

📄 sdlamain.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	if(card->hw.type != SDLA_S514){		disable_irq(card->hw.irq);	}	if (test_bit(SEND_CRIT, (void*)&wandev->critical)) {		return -EAGAIN;	}		switch (cmd) {	case WANPIPE_DUMP:		err = ioctl_dump(wandev->private, (void*)arg);		break;	case WANPIPE_EXEC:		err = ioctl_exec(wandev->private, (void*)arg, cmd);		break;	default:		err = -EINVAL;	} 	return err;}/****** Driver IOCTL Handlers ***********************************************//*============================================================================ * Dump adapter memory to user buffer. * o verify request structure * o copy request structure to kernel data space * o verify length/offset * o verify user buffer * o copy adapter memory image to user buffer * * Note: when dumping memory, this routine switches curent dual-port memory *	 vector, so care must be taken to avoid racing conditions. */static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump){	sdla_dump_t dump;	unsigned winsize;	unsigned long oldvec;	/* DPM window vector */	unsigned long smp_flags;	int err = 0;	if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)))		return -EFAULT;			if ((dump.magic != WANPIPE_MAGIC) ||	    (dump.offset + dump.length > card->hw.memory))		return -EINVAL;		winsize = card->hw.dpmsize;	if(card->hw.type != SDLA_S514) {		lock_adapter_irq(&card->wandev.lock, &smp_flags);		                oldvec = card->hw.vector;                while (dump.length) {			/* current offset */				                        unsigned pos = dump.offset % winsize;			/* current vector */                        unsigned long vec = dump.offset - pos;                        unsigned len = (dump.length > (winsize - pos)) ?                        	(winsize - pos) : dump.length;			/* relocate window */                        if (sdla_mapmem(&card->hw, vec) != 0) {                                err = -EIO;                                break;                        }			                        if(copy_to_user((void *)dump.ptr,                                (u8 *)card->hw.dpmbase + pos, len)){ 								unlock_adapter_irq(&card->wandev.lock, &smp_flags);				return -EFAULT;			}                        dump.length     -= len;                        dump.offset     += len;                        dump.ptr         = (char*)dump.ptr + len;                }		                sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */		unlock_adapter_irq(&card->wandev.lock, &smp_flags);        	}else {               if(copy_to_user((void *)dump.ptr,			       (u8 *)card->hw.dpmbase + dump.offset, dump.length)){			return -EFAULT;		}	}	return err;}/*============================================================================ * Execute adapter firmware command. * o verify request structure * o copy request structure to kernel data space * o call protocol-specific 'exec' function */static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int cmd){	sdla_exec_t exec;	int err=0;	if (card->exec == NULL && cmd == WANPIPE_EXEC){		return -ENODEV;	}	if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)))		return -EFAULT;	if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL))		return -EINVAL;	switch (cmd) {		case WANPIPE_EXEC:				err = card->exec(card, exec.cmd, exec.data);			break;	}		return err;}/******* Miscellaneous ******************************************************//*============================================================================ * SDLA Interrupt Service Routine. * o acknowledge SDLA hardware interrupt. * o call protocol-specific interrupt service routine, if any. */STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs){#define	card	((sdla_t*)dev_id)	if(card->hw.type == SDLA_S514) {	/* handle interrrupt on S514 */                u32 int_status;                unsigned char CPU_no = card->hw.S514_cpu_no[0];                unsigned char card_found_for_IRQ;		u8 IRQ_count = 0;		for(;;) {			read_S514_int_stat(&card->hw, &int_status);			/* check if the interrupt is for this device */ 			if(!((unsigned char)int_status &				(IRQ_CPU_A | IRQ_CPU_B)))                	        return IRQ_HANDLED;			/* if the IRQ is for both CPUs on the same adapter, */			/* then alter the interrupt status so as to handle */			/* one CPU at a time */			if(((unsigned char)int_status & (IRQ_CPU_A | IRQ_CPU_B))				== (IRQ_CPU_A | IRQ_CPU_B)) {				int_status &= (CPU_no == S514_CPU_A) ?					~IRQ_CPU_B : ~IRQ_CPU_A;			} 			card_found_for_IRQ = 0;	             	/* check to see that the CPU number for this device */			/* corresponds to the interrupt status read */                	switch (CPU_no) {                        	case S514_CPU_A:                                	if((unsigned char)int_status &						IRQ_CPU_A)                                        card_found_for_IRQ = 1;                                break;	                        case S514_CPU_B:        	                        if((unsigned char)int_status &						IRQ_CPU_B)                                        card_found_for_IRQ = 1;                                break;                	}			/* exit if the interrupt is for another CPU on the */			/* same IRQ */			if(!card_found_for_IRQ)				return IRQ_HANDLED;       	 		if (!card || 			   (card->wandev.state == WAN_UNCONFIGURED && !card->configured)){					printk(KERN_INFO						"Received IRQ %d for CPU #%c\n",						irq, CPU_no);					printk(KERN_INFO						"IRQ for unconfigured adapter\n");					S514_intack(&card->hw, int_status);					return IRQ_HANDLED;       			}	        	if (card->in_isr) {        	       		printk(KERN_INFO					"%s: interrupt re-entrancy on IRQ %d\n",                       			card->devname, card->wandev.irq);				S514_intack(&card->hw, int_status); 				return IRQ_HANDLED;       			}			spin_lock(&card->wandev.lock);			if (card->next){				spin_lock(&card->next->wandev.lock);			}					               	S514_intack(&card->hw, int_status);       			if (card->isr)				card->isr(card);			if (card->next){				spin_unlock(&card->next->wandev.lock);			}			spin_unlock(&card->wandev.lock);			/* handle a maximum of two interrupts (one for each */			/* CPU on the adapter) before returning */  			if((++ IRQ_count) == 2)				return IRQ_HANDLED;		}	}	else {			/* handle interrupt on S508 adapter */		if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured))			return IRQ_HANDLED;		if (card->in_isr) {			printk(KERN_INFO				"%s: interrupt re-entrancy on IRQ %d!\n",				card->devname, card->wandev.irq);			return IRQ_HANDLED;		}		spin_lock(&card->wandev.lock);		if (card->next){			spin_lock(&card->next->wandev.lock);		}			sdla_intack(&card->hw);		if (card->isr)			card->isr(card);				if (card->next){			spin_unlock(&card->next->wandev.lock);		}		spin_unlock(&card->wandev.lock);	}        return IRQ_HANDLED;#undef	card}/*============================================================================ * This routine is called by the protocol-specific modules when network * interface is being open.  The only reason we need this, is because we * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's * defined more than once into the same kernel module. */void wanpipe_open (sdla_t* card){	++card->open_cnt;}/*============================================================================ * This routine is called by the protocol-specific modules when network * interface is being closed.  The only reason we need this, is because we * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's * defined more than once into the same kernel module. */void wanpipe_close (sdla_t* card){	--card->open_cnt;}/*============================================================================ * Set WAN device state. */void wanpipe_set_state (sdla_t* card, int state){	if (card->wandev.state != state) {		switch (state) {		case WAN_CONNECTED:			printk (KERN_INFO "%s: link connected!\n",				card->devname);			break;		case WAN_CONNECTING:			printk (KERN_INFO "%s: link connecting...\n",				card->devname);			break;		case WAN_DISCONNECTED:			printk (KERN_INFO "%s: link disconnected!\n",				card->devname);			break;		}		card->wandev.state = state;	}	card->state_tick = jiffies;}sdla_t * wanpipe_find_card (char *name){	int cnt;	for (cnt = 0; cnt < ncards; ++ cnt) {		sdla_t* card = &card_array[cnt];		if (!strcmp(card->devname,name))			return card;	}	return NULL;}sdla_t * wanpipe_find_card_num (int num){	if (num < 1 || num > ncards)		return NULL;		num--;	return &card_array[num];}/* * @work_pointer:	work_struct to be done; * 			should already have PREPARE_WORK() or * 			  INIT_WORK() done on it by caller; */void wanpipe_queue_work (struct work_struct *work_pointer){	if (test_and_set_bit(1, (void*)&wanpipe_bh_critical))		printk(KERN_INFO "CRITICAL IN QUEUING WORK\n");	queue_work(wanpipe_wq, work_pointer);	clear_bit(1,(void*)&wanpipe_bh_critical);}void wakeup_sk_bh(struct net_device *dev){	wanpipe_common_t *chan = dev->priv;	if (test_bit(0,&chan->common_critical))		return;		if (chan->sk && chan->tx_timer){		chan->tx_timer->expires=jiffies+1;		add_timer(chan->tx_timer);	}}int change_dev_flags(struct net_device *dev, unsigned flags){	struct ifreq if_info;	mm_segment_t fs = get_fs();	int err;	memset(&if_info, 0, sizeof(if_info));	strcpy(if_info.ifr_name, dev->name);	if_info.ifr_flags = flags;		set_fs(get_ds());     /* get user space block */ 	err = devinet_ioctl(SIOCSIFFLAGS, &if_info);	set_fs(fs);	return err;}unsigned long get_ip_address(struct net_device *dev, int option){		struct in_ifaddr *ifaddr;	struct in_device *in_dev;	unsigned long addr = 0;	rcu_read_lock();	if ((in_dev = __in_dev_get_rcu(dev)) == NULL){		goto out;	}	if ((ifaddr = in_dev->ifa_list)== NULL ){		goto out;	}		switch (option){	case WAN_LOCAL_IP:		addr = ifaddr->ifa_local;		break;		case WAN_POINTOPOINT_IP:		addr = ifaddr->ifa_address;		break;		case WAN_NETMASK_IP:		addr = ifaddr->ifa_mask;		break;	case WAN_BROADCAST_IP:		addr = ifaddr->ifa_broadcast;		break;	default:		break;	}out:	rcu_read_unlock();	return addr;}	void add_gateway(sdla_t *card, struct net_device *dev){	mm_segment_t oldfs;	struct rtentry route;	int res;	memset((char*)&route,0,sizeof(struct rtentry));	((struct sockaddr_in *)		&(route.rt_dst))->sin_addr.s_addr = 0;	((struct sockaddr_in *)		&(route.rt_dst))->sin_family = AF_INET;	((struct sockaddr_in *)		&(route.rt_genmask))->sin_addr.s_addr = 0;	((struct sockaddr_in *) 		&(route.rt_genmask)) ->sin_family = AF_INET;	route.rt_flags = 0;  	route.rt_dev = dev->name;	oldfs = get_fs();	set_fs(get_ds());	res = ip_rt_ioctl(SIOCADDRT,&route);	set_fs(oldfs);	if (res == 0){		printk(KERN_INFO "%s: Gateway added for %s\n",			card->devname,dev->name);	}	return;}MODULE_LICENSE("GPL");/****** End *********************************************************/

⌨️ 快捷键说明

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