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

📄 sdlamain.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		err = wpf_init(card, conf);		break;#endif#ifdef	CONFIG_WANPIPE_PPP	case SFID_PPP502:	case SFID_PPP508:		err = wpp_init(card, conf);		break;#endif	default:		printk(KERN_ERR "%s: this firmware is not supported!\n",			wandev->name)		;		err = -EINVAL;	}	if (err)	{		sdla_down(&card->hw);		free_irq(irq, card);		return err;	}  	/* Reserve I/O region and schedule background task *//*	printk(KERN_INFO "about to request\n");*/	request_region(card->hw.port, card->hw.io_range, wandev->name);/*	printk(KERN_INFO "request done\n");*/	if (++active == 1)		queue_task(&sdla_tq, &tq_scheduler);			wandev->critical = 0;	return 0;}/*============================================================================ * Shut down WAN link driver.  * o shut down adapter hardware * o release system resources. * * This function is called by the router when device is being unregistered or * when it handles ROUTER_DOWN IOCTL. */static int shutdown (wan_device_t* wandev){	sdla_t* card;	/* sanity checks */	if ((wandev == NULL) || (wandev->private == NULL))		return -EFAULT;			if (wandev->state == WAN_UNCONFIGURED)		return 0;			/* If wee are in a critical section we lose */	if (test_and_set_bit(0, (void*)&wandev->critical))		return -EAGAIN;			card = wandev->private;	wandev->state = WAN_UNCONFIGURED;	if (--active == 0)		schedule();	/* stop background thread */	/*	printk(KERN_INFO "active now %d\n", active);	printk(KERN_INFO "About to call sdla_down\n");*/	sdla_down(&card->hw);/*	printk(KERN_INFO "sdla_down done\n");	printk(KERN_INFO "About to call free_irq\n");*/	free_irq(wandev->irq, card);/*	printk(KERN_INFO "free_irq done\n");	printk(KERN_INFO "About to call release_region\n");*/	release_region(card->hw.port, card->hw.io_range);/*	printk(KERN_INFO "release_region done\n");*/	wandev->critical = 0;	return 0;}/*============================================================================ * Driver I/O control.  * o verify arguments * o perform requested action * * This function is called when router handles one of the reserved user * IOCTLs.  Note that 'arg' stil points to user address space. */static int ioctl (wan_device_t* wandev, unsigned cmd, unsigned long arg){	int err;	/* sanity checks */	if ((wandev == NULL) || (wandev->private == NULL))		return -EFAULT	;	if (wandev->state == WAN_UNCONFIGURED)		return -ENODEV	;	if (test_and_set_bit(0, (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);		break;	default:		err = -EINVAL;	}	wandev->critical = 0;	return err;}/****** Driver IOCTL Hanlers ************************************************//*============================================================================ * 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 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;	save_flags(flags);        cli();				/* >>> critical section start <<< */	oldvec = card->hw.vector;	while (dump.length)	{		unsigned pos = dump.offset % winsize;	/* current offset */		unsigned long vec = dump.offset - pos;	/* current vector */		unsigned len = (dump.length > (winsize - pos)) ?			(winsize - pos) : dump.length		;		if (sdla_mapmem(&card->hw, vec) != 0)	/* relocate window */		{			err = -EIO;			break;		}		/* FIXME::: COPY TO KERNEL BUFFER FIRST ?? */		sti();	/* Not ideal but tough we have to do this */		if(copy_to_user((void *)dump.ptr,			(u8 *)card->hw.dpmbase + pos, len))				return -EFAULT;		cli();		dump.length     -= len;		dump.offset     += len;		(char*)dump.ptr += len;	}	sdla_mapmem(&card->hw, oldvec);	/* restore DPM window position */	restore_flags(flags);		/* >>> critical section end <<< */	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){	sdla_exec_t exec;	if (card->exec == NULL)		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;	return card->exec(card, exec.cmd, exec.data);}/******* Miscellaneous ******************************************************//*============================================================================ * SDLA Interrupt Service Routine. * o acknowledge SDLA hardware interrupt. * o call protocol-specific interrupt service routine, if any. */STATIC void sdla_isr (int irq, void* dev_id, struct pt_regs *regs){#define	card	((sdla_t*)dev_id)	if (!card || (card->wandev.state == WAN_UNCONFIGURED))		return	;	if (card->in_isr)	{		printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",			card->devname, card->wandev.irq)		;		return;	}	sdla_intack(&card->hw);	if (card->isr) 		card->isr(card);#undef	card}/*============================================================================ * SDLA polling routine. * This routine simulates kernel thread to perform various housekeeping job. * * o for each configured device call its poll() routine * o if there is at least one active card, then reschedule itself once again */STATIC void sdla_poll (void* data){	int i;	for (i = 0; i < ncards; ++i)	{		sdla_t* card = &card_array[i];		if ((card->wandev.state != WAN_UNCONFIGURED) && card->poll &&		    !card->wandev.critical)		{			card->poll(card);		}	}	if (active)		queue_task(&sdla_tq, &tq_scheduler);}/*============================================================================ * 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;	MOD_INC_USE_COUNT;}/*============================================================================ * 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;	MOD_DEC_USE_COUNT;}/*============================================================================ * Set WAN device state. */void wanpipe_set_state (sdla_t* card, int state){	unsigned long flags;	save_flags(flags);	cli();	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;	restore_flags(flags);}/****** End *****************************************************************/

⌨️ 快捷键说明

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