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

📄 sdlamain.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
			return err;		}	        if(card->hw.type != SDLA_S514)			irq = (conf->irq == 2) ? 9 : conf->irq; /* IRQ2 -> IRQ9 */		else			irq = card->hw.irq;		/* request an interrupt vector - note that interrupts may be shared */		/* when using the S514 PCI adapter */		       		if(request_irq(irq, sdla_isr, 		      (card->hw.type == SDLA_S514) ? SA_SHIRQ : 0, 		       wandev->name, card)){			printk(KERN_INFO "%s: Can't reserve IRQ %d!\n", wandev->name, irq);			return -EINVAL;		}	}else{		printk(KERN_INFO "%s: Card Configured %lu or Piggybacking %i!\n",			wandev->name,card->configured,card->wandev.piggyback);	} 	if (!card->configured){		/* Initialize the Spin lock */		printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name);		/* Piggyback spin lock has already been initialized,		 * in check_s514/s508_conflicts() */		if (!card->wandev.piggyback){			spin_lock_init(&card->wandev.lock);		}				/* Intialize WAN device data space */		wandev->irq       = irq;		wandev->dma       = 0;		if(card->hw.type != SDLA_S514){ 			wandev->ioport = card->hw.port;		}else{			wandev->S514_cpu_no[0] = card->hw.S514_cpu_no[0];			wandev->S514_slot_no = card->hw.S514_slot_no;		}		wandev->maddr     = (unsigned long)card->hw.dpmbase;		wandev->msize     = card->hw.dpmsize;		wandev->hw_opt[0] = card->hw.type;		wandev->hw_opt[1] = card->hw.pclk;		wandev->hw_opt[2] = card->hw.memory;		wandev->hw_opt[3] = card->hw.fwid;	}	/* Protocol-specific initialization */	switch (card->hw.fwid) {	case SFID_X25_502:	case SFID_X25_508:		printk(KERN_INFO "%s: Starting X.25 Protocol Init.\n",				card->devname);		err = wpx_init(card, conf);		break;	case SFID_FR502:	case SFID_FR508:		printk(KERN_INFO "%s: Starting Frame Relay Protocol Init.\n",				card->devname);		err = wpf_init(card, conf);		break;	case SFID_PPP502:	case SFID_PPP508:		printk(KERN_INFO "%s: Starting PPP Protocol Init.\n",				card->devname);		err = wpp_init(card, conf);		break;			case SFID_CHDLC508:	case SFID_CHDLC514:		if (conf->ft1){					printk(KERN_INFO "%s: Starting FT1 CSU/DSU Config Driver.\n",				card->devname);			err = wpft1_init(card, conf);			break;					}else if (conf->config_id == WANCONFIG_MPPP){			printk(KERN_INFO "%s: Starting Multi-Port PPP Protocol Init.\n",					card->devname);			err = wsppp_init(card,conf);			break;		}else{			printk(KERN_INFO "%s: Starting CHDLC Protocol Init.\n",					card->devname);			err = wpc_init(card, conf);			break;		}	default:		printk(KERN_INFO "%s: Error, Firmware is not supported %X %X!\n",			wandev->name,card->hw.fwid,SFID_CHDLC508);		err = -EPROTONOSUPPORT;	}	if (err != 0){		if (err == -EPROTONOSUPPORT){			printk(KERN_INFO 				"%s: Error, Protocol selected has not been compiled!\n",					card->devname);			printk(KERN_INFO 				"%s:        Re-configure the kernel and re-build the modules!\n",					card->devname);		}				release_hw(card);		wandev->state = WAN_UNCONFIGURED;		return err;	}  	/* Reserve I/O region and schedule background task */        if(card->hw.type != SDLA_S514 && !card->wandev.piggyback)		if (!request_region(card->hw.port, card->hw.io_range, 				wandev->name)) {			printk(KERN_WARNING "port 0x%04x busy\n", card->hw.port);			release_hw(card);			wandev->state = WAN_UNCONFIGURED;			return -EBUSY;	  }	/* Only use the polling routine for the X25 protocol */		card->wandev.critical=0;	return 0;}/*==================================================================  * configure_s508_card *  * For a S508 adapter, check for a possible configuration error in that * we are loading an adapter in the same IO port as a previously loaded S508 * card. */ static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int *irq){	unsigned long smp_flags;	int i;		if (conf->ioport <= 0) {		printk(KERN_INFO		"%s: can't configure without I/O port address!\n",		card->wandev.name);		return -EINVAL;	}	if (conf->irq <= 0) {		printk(KERN_INFO "%s: can't configure without IRQ!\n",		card->wandev.name);		return -EINVAL;	}	if (test_bit(0,&card->configured))		return 0;	/* Check for already loaded card with the same IO port and IRQ 	 * If found, copy its hardware configuration and use its	 * resources (i.e. piggybacking)	 */		for (i = 0; i < ncards; i++) {		sdla_t *nxt_card = &card_array[i];		/* Skip the current card ptr */		if (nxt_card == card)				continue;		/* Find a card that is already configured with the		 * same IO Port */		if ((nxt_card->hw.type == SDLA_S508) &&		    (nxt_card->hw.port == conf->ioport) && 		    (nxt_card->next == NULL)){						/* We found a card the card that has same configuration			 * as us. This means, that we must setup this card in 			 * piggibacking mode. However, only CHDLC and MPPP protocol			 * support this setup */					if ((conf->config_id == WANCONFIG_CHDLC || 			     conf->config_id == WANCONFIG_MPPP) &&			    (nxt_card->wandev.config_id == WANCONFIG_CHDLC || 			     nxt_card->wandev.config_id == WANCONFIG_MPPP)){ 								*irq = nxt_card->hw.irq;				memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));							/* The master could already be running, we must				 * set this as a critical area */				lock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);				nxt_card->next = card;				card->next = nxt_card;				card->wandev.piggyback = WANOPT_YES;				/* We must initialise the piggiback spin lock here				 * since isr will try to lock card->next if it				 * exists */				spin_lock_init(&card->wandev.lock);								unlock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);				break;			}else{				/* Trying to run piggibacking with a wrong protocol */				printk(KERN_INFO "%s: ERROR: Resource busy, ioport: 0x%x\n"						 "%s:        This protocol doesn't support\n"						 "%s:        multi-port operation!\n",						 card->devname,nxt_card->hw.port,						 card->devname,card->devname);				return -EEXIST;			}		}	}		/* Make sure I/O port region is available only if we are the	 * master device.  If we are running in piggybacking mode, 	 * we will use the resources of the master card. */	if (!card->wandev.piggyback) {		struct resource *rr =			request_region(conf->ioport, SDLA_MAXIORANGE, "sdlamain");		release_region(conf->ioport, SDLA_MAXIORANGE);		if (!rr) {			printk(KERN_INFO				"%s: I/O region 0x%X - 0x%X is in use!\n",				card->wandev.name, conf->ioport,				conf->ioport + SDLA_MAXIORANGE - 1);			return -EINVAL;		}	}	return 0;}/*==================================================================  * configure_s514_card *  * For a S514 adapter, check for a possible configuration error in that * we are loading an adapter in the same slot as a previously loaded S514 * card. */ static int check_s514_conflicts(sdla_t* card,wandev_conf_t* conf, int *irq){	unsigned long smp_flags;	int i;		if (test_bit(0,&card->configured))		return 0;		/* Check for already loaded card with the same IO port and IRQ 	 * If found, copy its hardware configuration and use its	 * resources (i.e. piggybacking)	 */	for (i = 0; i < ncards; i ++) {			sdla_t* nxt_card = &card_array[i];		if(nxt_card == card)			continue;				if((nxt_card->hw.type == SDLA_S514) &&		   (nxt_card->hw.S514_slot_no == conf->PCI_slot_no) &&		   (nxt_card->hw.S514_cpu_no[0] == conf->S514_CPU_no[0])&&		   (nxt_card->next == NULL)){			if ((conf->config_id == WANCONFIG_CHDLC || 			     conf->config_id == WANCONFIG_MPPP) &&			    (nxt_card->wandev.config_id == WANCONFIG_CHDLC || 			     nxt_card->wandev.config_id == WANCONFIG_MPPP)){ 								*irq = nxt_card->hw.irq;				memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));					/* The master could already be running, we must				 * set this as a critical area */				lock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);				nxt_card->next = card;				card->next = nxt_card;				card->wandev.piggyback = WANOPT_YES;				/* We must initialise the piggiback spin lock here				 * since isr will try to lock card->next if it				 * exists */				spin_lock_init(&card->wandev.lock);				unlock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);			}else{				/* Trying to run piggibacking with a wrong protocol */				printk(KERN_INFO "%s: ERROR: Resource busy: CPU %c PCISLOT %i\n"						 "%s:        This protocol doesn't support\n"						 "%s:        multi-port operation!\n",						 card->devname,						 conf->S514_CPU_no[0],conf->PCI_slot_no,						 card->devname,card->devname);				return -EEXIST;			}		}	}	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(struct wan_device* wandev){	sdla_t *card;	int err=0;		/* sanity checks */	if ((wandev == NULL) || (wandev->private == NULL)){		return -EFAULT;	}			if (wandev->state == WAN_UNCONFIGURED){		return 0;	}	card = wandev->private;	if (card->tty_opt){		if (card->tty_open){			printk(KERN_INFO 				"%s: Shutdown Failed: TTY is still open\n",				  card->devname);			return -EBUSY;		}	}		wandev->state = WAN_UNCONFIGURED;	set_bit(PERI_CRIT,(void*)&wandev->critical);		/* In case of piggibacking, make sure that          * we never try to shutdown both devices at the same         * time, because they depend on one another */		if (card->disable_comm){		card->disable_comm(card);	}	/* 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));		}	}		clear_bit(PERI_CRIT,(void*)&wandev->critical);	return err;}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 %i\n",				nxt_card->devname,nxt_card->wandev.state);			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;	}	return;}/*============================================================================ * 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(struct wan_device* 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;

⌨️ 快捷键说明

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