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

📄 sdlamain.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (err){		release_hw(card);		return err;			}  	/* Reserve I/O region and schedule background task */        if(card->hw.type != SDLA_S514 && !card->wandev.piggyback)                request_region(card->hw.port, card->hw.io_range, wandev->name);	if (++active == 1) {		MOD_INC_USE_COUNT;		if (schedule_task(&sdla_tq) == 0)			MOD_DEC_USE_COUNT;	}			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 we 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 */	/* Release Resources */	release_hw(card);        /* only free the allocated I/O range if not an S514 adapter */	if (wandev->hw_opt[0] != SDLA_S514 && !card->configured){              	release_region(card->hw.port, card->hw.io_range);	}	if (!card->configured){		memset(&card->hw, 0, sizeof(sdlahw_t));	      	if (card->next){			memset(&card->next->hw, 0, sizeof(sdlahw_t));		}	}	wandev->critical = 0;	return 0;}static void release_hw (sdla_t *card){	sdla_t *nxt_card;	/* Check if next device exists */	if (card->next){		nxt_card = card->next;		/* If next device is down then release resources */		if (nxt_card->wandev.state == WAN_UNCONFIGURED){			if (card->wandev.piggyback){				/* If this device is piggyback then use                                 * information of the master device 				 */				printk(KERN_INFO "%s: Piggyback shutting down\n",card->devname);				sdla_down(&card->next->hw);       				free_irq(card->wandev.irq, card->next);				card->configured = 0;				card->next->configured = 0;				card->wandev.piggyback = 0;			}else{				/* Master device shutting down */				printk(KERN_INFO "%s: Master shutting down\n",card->devname);				sdla_down(&card->hw);				free_irq(card->wandev.irq, card);				card->configured = 0;				card->next->configured = 0;			}		}else{			printk(KERN_INFO "%s: Device still running\n",				nxt_card->devname);			card->configured = 1;		}	}else{		printk(KERN_INFO "%s: Master shutting down\n",card->devname);		sdla_down(&card->hw);       		free_irq(card->wandev.irq, card);		card->configured = 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){	sdla_t* card;	int err;	/* sanity checks */	if ((wandev == NULL) || (wandev->private == NULL))		return -EFAULT;	if (wandev->state == WAN_UNCONFIGURED)		return -ENODEV;	card = wandev->private;	if(card->hw.type != SDLA_S514){		disable_irq(card->hw.irq);	}	if (test_and_set_bit(0, (void*)&wandev->critical)) {		if(card->hw.type != SDLA_S514){			enable_irq(card->hw.irq);		}		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;	} 	clear_bit(0, (void*)&wandev->critical);        if(card->hw.type != SDLA_S514){		enable_irq(card->hw.irq);	} 	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 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 <<< */	if(card->hw.type != SDLA_S514) {                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;                        }                        /* 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 */        }		else {		/* 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 + dump.offset, dump.length))                	return -EFAULT;               cli();	}	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->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;			/* 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;       	 		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;       			}	        	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;       			}	               	S514_intack(&card->hw, int_status);        			if (card->isr)				card->isr(card);			/* handle a maximum of two interrupts (one for each */			/* CPU on the adapter) before returning */  			if((++ IRQ_count) == 2)				return;		}	}	else {			/* handle interrupt on S508 adapter */		if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured))			return;		if (card->in_isr) {			printk(KERN_INFO				"%s: interrupt re-entrancy on IRQ %d!\n",				card->devname, card->wandev.irq);			return;		}		/* Use spin lock only for S508 */#ifdef CONFIG_SMP		spin_lock(&card->lock);#endif		sdla_intack(&card->hw);		if (card->isr)			card->isr(card);#ifdef CONFIG_SMP		spin_unlock(&card->lock);#endif	}                #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) {		MOD_INC_USE_COUNT;		if (schedule_task(&sdla_tq) == 0)	/* Surely not? */			MOD_DEC_USE_COUNT;	}	MOD_DEC_USE_COUNT;}/*============================================================================ * 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 + -