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

📄 sktr.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	tp->timer.expires = jiffies + 2*HZ;	add_timer(&tp->timer);	if(tp->AdapterOpenFlag || tp->ReOpenInProgress)		return;	tp->ReOpenInProgress = 1;	sktr_open_adapter(dev);	return;}/* * The typical workload of the driver: Handle the network interface interrupts. */static void sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct device *dev = dev_id;	struct net_local *tp;	int ioaddr;	unsigned short irq_type;	if(dev == NULL)	{		printk("%s: irq %d for unknown device.\n", dev->name, irq);		return;	}	dev->interrupt = 1;	ioaddr = dev->base_addr;	tp = (struct net_local *)dev->priv;	irq_type = inw(ioaddr + SIFSTS);	while(irq_type & STS_SYSTEM_IRQ)	{		irq_type &= STS_IRQ_MASK;		if(!sktr_chk_ssb(tp, irq_type))		{			printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);			break;		}		switch(irq_type)		{			case STS_IRQ_RECEIVE_STATUS:				sktr_reset_interrupt(dev);				sktr_rcv_status_irq(dev);				break;			case STS_IRQ_TRANSMIT_STATUS:				/* Check if TRANSMIT.HALT command is complete */				if(tp->ssb.Parm[0] & COMMAND_COMPLETE)				{					tp->TransmitCommandActive = 0;					tp->TransmitHaltScheduled = 0;					/* Issue a new transmit command. */					sktr_exec_cmd(dev, OC_TRANSMIT);				}				sktr_reset_interrupt(dev);				sktr_tx_status_irq(dev);				break;			case STS_IRQ_COMMAND_STATUS:				/* The SSB contains status of last command				 * other than receive/transmit.				 */				sktr_cmd_status_irq(dev);				break;			case STS_IRQ_SCB_CLEAR:				/* The SCB is free for another command. */				tp->ScbInUse = 0;				sktr_chk_outstanding_cmds(dev);				break;			case STS_IRQ_RING_STATUS:				sktr_ring_status_irq(dev);				break;			case STS_IRQ_ADAPTER_CHECK:				sktr_chk_irq(dev);				break;			default:				printk(KERN_INFO "Unknown Token Ring IRQ\n");				break;		}		/* Reset system interrupt if not already done. */		if(irq_type != STS_IRQ_TRANSMIT_STATUS			&& irq_type != STS_IRQ_RECEIVE_STATUS)		{			sktr_reset_interrupt(dev);		}		irq_type = inw(ioaddr + SIFSTS);	}	dev->interrupt = 0;	return;}/* *  Reset the INTERRUPT SYSTEM bit and issue SSB CLEAR command. */static void sktr_reset_interrupt(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	SSB *ssb = &tp->ssb;	/*	 * [Workaround for "Data Late"]	 * Set all fields of the SSB to well-defined values so we can	 * check if the adapter has written the SSB.	 */	ssb->STS	= (unsigned short) -1;	ssb->Parm[0] 	= (unsigned short) -1;	ssb->Parm[1] 	= (unsigned short) -1;	ssb->Parm[2] 	= (unsigned short) -1;	/* Free SSB by issuing SSB_CLEAR command after reading IRQ code	 * and clear STS_SYSTEM_IRQ bit: enable adapter for further interrupts.	 */	sktr_exec_sifcmd(dev, CMD_SSB_CLEAR | CMD_CLEAR_SYSTEM_IRQ);	return;}/* * Check if the SSB has actually been written by the adapter. */static unsigned char sktr_chk_ssb(struct net_local *tp, unsigned short IrqType){	SSB *ssb = &tp->ssb;	/* The address of the SSB. */	/* C 0 1 2 INTERRUPT CODE	 * - - - - --------------	 * 1 1 1 1 TRANSMIT STATUS	 * 1 1 1 1 RECEIVE STATUS	 * 1 ? ? 0 COMMAND STATUS	 * 0 0 0 0 SCB CLEAR	 * 1 1 0 0 RING STATUS	 * 0 0 0 0 ADAPTER CHECK	 *	 * 0 = SSB field not affected by interrupt	 * 1 = SSB field is affected by interrupt	 *	 * C = SSB ADDRESS +0: COMMAND	 * 0 = SSB ADDRESS +2: STATUS 0	 * 1 = SSB ADDRESS +4: STATUS 1	 * 2 = SSB ADDRESS +6: STATUS 2	 */	/* Check if this interrupt does use the SSB. */	if(IrqType != STS_IRQ_TRANSMIT_STATUS		&& IrqType != STS_IRQ_RECEIVE_STATUS		&& IrqType != STS_IRQ_COMMAND_STATUS		&& IrqType != STS_IRQ_RING_STATUS)	{		return (1);	/* SSB not involved. */	}	/* Note: All fields of the SSB have been set to all ones (-1) after it	 * has last been used by the software (see DriverIsr()).	 *	 * Check if the affected SSB fields are still unchanged.	 */	if(ssb->STS == (unsigned short) -1)		return (0);	/* Command field not yet available. */	if(IrqType == STS_IRQ_COMMAND_STATUS)		return (1);	/* Status fields not always affected. */	if(ssb->Parm[0] == (unsigned short) -1)		return (0);	/* Status 1 field not yet available. */	if(IrqType == STS_IRQ_RING_STATUS)		return (1);	/* Status 2 & 3 fields not affected. */	/* Note: At this point, the interrupt is either TRANSMIT or RECEIVE. */	if(ssb->Parm[1] == (unsigned short) -1)		return (0);	/* Status 2 field not yet available. */	if(ssb->Parm[2] == (unsigned short) -1)		return (0);	/* Status 3 field not yet available. */	return (1);	/* All SSB fields have been written by the adapter. */}/* * Evaluates the command results status in the SSB status field. */static void sktr_cmd_status_irq(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	unsigned short ssb_cmd, ssb_parm_0;	unsigned short ssb_parm_1;	char *open_err = "Open error -";	char *code_err = "Open code -";	/* Copy the ssb values to local variables */	ssb_cmd    = tp->ssb.STS;	ssb_parm_0 = tp->ssb.Parm[0];	ssb_parm_1 = tp->ssb.Parm[1];	if(ssb_cmd == OPEN)	{		tp->Sleeping = 0;		if(!tp->ReOpenInProgress)	    		wake_up_interruptible(&tp->wait_for_tok_int);		tp->OpenCommandIssued = 0;		tp->ScbInUse = 0;		if((ssb_parm_0 & 0x00FF) == GOOD_COMPLETION)		{			/* Success, the adapter is open. */			tp->LobeWireFaultLogged	= 0;			tp->AdapterOpenFlag 	= 1;			tp->AdapterVirtOpenFlag = 1;			tp->TransmitCommandActive = 0;			sktr_exec_cmd(dev, OC_TRANSMIT);			sktr_exec_cmd(dev, OC_RECEIVE);			if(tp->ReOpenInProgress)				tp->ReOpenInProgress = 0;			return;		}		else 	/* The adapter did not open. */		{	    		if(ssb_parm_0 & NODE_ADDR_ERROR)				printk(KERN_INFO "%s: Node address error\n",					dev->name);	    		if(ssb_parm_0 & LIST_SIZE_ERROR)				printk(KERN_INFO "%s: List size error\n",					dev->name);	    		if(ssb_parm_0 & BUF_SIZE_ERROR)				printk(KERN_INFO "%s: Buffer size error\n",					dev->name);	    		if(ssb_parm_0 & TX_BUF_COUNT_ERROR)				printk(KERN_INFO "%s: Tx buffer count error\n",					dev->name);	    		if(ssb_parm_0 & INVALID_OPEN_OPTION)				printk(KERN_INFO "%s: Invalid open option\n",					dev->name);	    		if(ssb_parm_0 & OPEN_ERROR)			{				/* Show the open phase. */				switch(ssb_parm_0 & OPEN_PHASES_MASK)				{					case LOBE_MEDIA_TEST:						if(!tp->LobeWireFaultLogged)						{							tp->LobeWireFaultLogged = 1;							printk(KERN_INFO "%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);		    				}						tp->ReOpenInProgress	= 1;						tp->AdapterOpenFlag 	= 0;						tp->AdapterVirtOpenFlag = 1;						sktr_open_adapter(dev);						return;					case PHYSICAL_INSERTION:						printk(KERN_INFO "%s: %s Physical insertion.\n", dev->name, open_err);						break;					case ADDRESS_VERIFICATION:						printk(KERN_INFO "%s: %s Address verification.\n", dev->name, open_err);						break;					case PARTICIPATION_IN_RING_POLL:						printk(KERN_INFO "%s: %s Participation in ring poll.\n", dev->name, open_err);						break;					case REQUEST_INITIALISATION:						printk(KERN_INFO "%s: %s Request initialisation.\n", dev->name, open_err);						break;					case FULLDUPLEX_CHECK:						printk(KERN_INFO "%s: %s Full duplex check.\n", dev->name, open_err);						break;					default:						printk(KERN_INFO "%s: %s Unknown open phase\n", dev->name, open_err);						break;				}				/* Show the open errors. */				switch(ssb_parm_0 & OPEN_ERROR_CODES_MASK)				{					case OPEN_FUNCTION_FAILURE:						printk(KERN_INFO "%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);						tp->LastOpenStatus =							OPEN_FUNCTION_FAILURE;						break;					case OPEN_SIGNAL_LOSS:						printk(KERN_INFO "%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);						tp->LastOpenStatus =							OPEN_SIGNAL_LOSS;						break;					case OPEN_TIMEOUT:						printk(KERN_INFO "%s: %s OPEN_TIMEOUT\n", dev->name, code_err);						tp->LastOpenStatus =							OPEN_TIMEOUT;						break;					case OPEN_RING_FAILURE:						printk(KERN_INFO "%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);						tp->LastOpenStatus =							OPEN_RING_FAILURE;						break;					case OPEN_RING_BEACONING:						printk(KERN_INFO "%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);						tp->LastOpenStatus =							OPEN_RING_BEACONING;						break;					case OPEN_DUPLICATE_NODEADDR:						printk(KERN_INFO "%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);						tp->LastOpenStatus =							OPEN_DUPLICATE_NODEADDR;						break;					case OPEN_REQUEST_INIT:						printk(KERN_INFO "%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);						tp->LastOpenStatus =							OPEN_REQUEST_INIT;						break;					case OPEN_REMOVE_RECEIVED:						printk(KERN_INFO "%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);						tp->LastOpenStatus =							OPEN_REMOVE_RECEIVED;						break;					case OPEN_FULLDUPLEX_SET:						printk(KERN_INFO "%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);						tp->LastOpenStatus =							OPEN_FULLDUPLEX_SET;						break;					default:						printk(KERN_INFO "%s: %s Unknown open err code", dev->name, code_err);						tp->LastOpenStatus =							OPEN_FUNCTION_FAILURE;						break;				}			}			tp->AdapterOpenFlag 	= 0;			tp->AdapterVirtOpenFlag = 0;			return;		}	}	else	{		if(ssb_cmd != READ_ERROR_LOG)			return;		/* Add values from the error log table to the MAC		 * statistics counters and update the errorlogtable		 * memory.		 */		tp->MacStat.line_errors += tp->errorlogtable.Line_Error;		tp->MacStat.burst_errors += tp->errorlogtable.Burst_Error;		tp->MacStat.A_C_errors += tp->errorlogtable.ARI_FCI_Error;		tp->MacStat.lost_frames += tp->errorlogtable.Lost_Frame_Error;		tp->MacStat.recv_congest_count += tp->errorlogtable.Rx_Congest_Error;		tp->MacStat.rx_errors += tp->errorlogtable.Rx_Congest_Error;		tp->MacStat.frame_copied_errors += tp->errorlogtable.Frame_Copied_Error;		tp->MacStat.token_errors += tp->errorlogtable.Token_Error;		tp->MacStat.dummy1 += tp->errorlogtable.DMA_Bus_Error;		tp->MacStat.dummy1 += tp->errorlogtable.DMA_Parity_Error;		tp->MacStat.abort_delimiters += tp->errorlogtable.AbortDelimeters;		tp->MacStat.frequency_errors += tp->errorlogtable.Frequency_Error;		tp->MacStat.internal_errors += tp->errorlogtable.Internal_Error;	}	return;}/* * The inverse routine to sktr_open(). */static int sktr_close(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	dev->tbusy = 1;	dev->start = 0;	del_timer(&tp->timer);	/* Flush the Tx and disable Rx here. */	tp->HaltInProgress 	= 1;	sktr_exec_cmd(dev, OC_CLOSE);	tp->timer.expires	= jiffies + 1*HZ;	tp->timer.function 	= sktr_timer_end_wait;	tp->timer.data 		= (unsigned long)dev;	add_timer(&tp->timer);	sktr_enable_interrupts(dev);	tp->Sleeping = 1;	interruptible_sleep_on(&tp->wait_for_tok_int);	tp->TransmitCommandActive = 0;    	del_timer(&tp->timer);	sktr_disable_interrupts(dev);   	if(dev->dma > 0) 	{		unsigned long flags=claim_dma_lock();		disable_dma(dev->dma);		release_dma_lock(flags);	}		outw(0xFF00, dev->base_addr + SIFCMD);	if(dev->dma > 0)		outb(0xff, dev->base_addr + POSREG);#ifdef MODULE	MOD_DEC_USE_COUNT;#endif	sktr_cancel_tx_queue(tp);	return (0);}/* * Get the current statistics. This may be called with the card open * or closed. */static struct enet_statistics *sktr_get_stats(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	return ((struct enet_statistics *)&tp->MacStat);}/* * Set or clear the multicast filter for this adapter. */static void sktr_set_multicast_list(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	unsigned int OpenOptions;	OpenOptions = tp->ocpl.OPENOptions &		~(PASS_ADAPTER_MAC_FRAMES		| PASS_ATTENTION_FRAMES		| PASS_BEACON_MAC_FRAMES		| COPY_ALL_MAC_FRAMES		| COPY_ALL_NON_MAC_FRAMES);	if(dev->flags & IFF_PROMISC)		/* Enable promiscuous mode */		OpenOptions |= COPY_ALL_NON_MAC_FRAMES | COPY_ALL_MAC_FRAMES;	else	{		if(dev->flags & IFF_ALLMULTI)			/* || dev->mc_count > HW_MAX_ADDRS) */		{			/* Disable promiscuous mode, use normal mode. */		}		else		{			if(dev->mc_count)			{				/* Walk the address list, and load the filter */			}		}	}	tp->ocpl.OPENOptions = OpenOptions;	sktr_exec_cmd(dev, OC_MODIFY_OPEN_PARMS);	return;}/* * Wait for some time (microseconds) */static void sktr_wait(unsigned long time){	long tmp;	tmp = jiffies + time/(1000000/HZ);	do {  		current->state 		= TASK_INTERRUPTIBLE;		tmp = schedule_timeout(tmp);	} while(time_after(tmp, jiffies));	return;}/* * Write a command value to the SIFCMD register */static void sktr_exec_sifcmd(struct device *dev, unsigned int WriteValue){

⌨️ 快捷键说明

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