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

📄 sktr.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	int ioaddr = dev->base_addr;	unsigned short cmd;	unsigned short SifStsValue;	unsigned long loop_counter;	WriteValue = ((WriteValue ^ CMD_SYSTEM_IRQ) | CMD_INTERRUPT_ADAPTER);	cmd = (unsigned short)WriteValue;	loop_counter = 0,5 * 800000;	do {		SifStsValue = inw(ioaddr + SIFSTS);	} while((SifStsValue & CMD_INTERRUPT_ADAPTER) && loop_counter--);	outw(cmd, ioaddr + SIFCMD);	return;}/* * Processes adapter hardware reset, halts adapter and downloads firmware, * clears the halt bit. */static int sktr_reset_adapter(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	unsigned short *fw_ptr = (unsigned short *)&sktr_code;	unsigned short count, c;	int ioaddr = dev->base_addr;	/* Hardware adapter reset */	outw(ACL_ARESET, ioaddr + SIFACL);	sktr_wait(40);	c = inw(ioaddr + SIFACL);	sktr_wait(20);	if(dev->dma == 0)	/* For PCI adapters */	{		c &= ~(ACL_SPEED4 | ACL_SPEED16);	/* Clear bits */		if(tp->DataRate == SPEED_4)			c |= ACL_SPEED4;		/* Set 4Mbps */		else			c |= ACL_SPEED16;		/* Set 16Mbps */	}	/* In case a command is pending - forget it */	tp->ScbInUse = 0;	c &= ~ACL_ARESET;		/* Clear adapter reset bit */	c |=  ACL_CPHALT;		/* Halt adapter CPU, allow download */	c &= ~ACL_PSDMAEN;		/* Clear pseudo dma bit */	outw(c, ioaddr + SIFACL);	sktr_wait(40);	/* Download firmware via DIO interface: */	do {		/* Download first address part */		outw(*fw_ptr, ioaddr + SIFADX);		fw_ptr++;		/* Download second address part */		outw(*fw_ptr, ioaddr + SIFADD);		fw_ptr++;		if((count = *fw_ptr) != 0)	/* Load loop counter */		{			fw_ptr++;	/* Download block data */			for(; count > 0; count--)			{				outw(*fw_ptr, ioaddr + SIFINC);				fw_ptr++;			}		}		else	/* Stop, if last block downloaded */		{			c = inw(ioaddr + SIFACL);			c &= (~ACL_CPHALT | ACL_SINTEN);			/* Clear CPHALT and start BUD */			outw(c, ioaddr + SIFACL);			return (1);		}	} while(count == 0);	return (-1);}/* * Starts bring up diagnostics of token ring adapter and evaluates * diagnostic results. */static int sktr_bringup_diags(struct device *dev){	int loop_cnt, retry_cnt;	unsigned short Status;	int ioaddr = dev->base_addr;	sktr_wait(HALF_SECOND);	sktr_exec_sifcmd(dev, EXEC_SOFT_RESET);	sktr_wait(HALF_SECOND);	retry_cnt = BUD_MAX_RETRIES;	/* maximal number of retrys */	do {		retry_cnt--;		if(sktr_debug > 3)			printk(KERN_INFO "BUD-Status: \n");		loop_cnt = BUD_MAX_LOOPCNT;	/* maximum: three seconds*/		do {			/* Inspect BUD results */			loop_cnt--;			sktr_wait(HALF_SECOND);			Status = inw(ioaddr + SIFSTS);			Status &= STS_MASK;			if(sktr_debug > 3)				printk(KERN_INFO " %04X \n", Status);			/* BUD successfully completed */			if(Status == STS_INITIALIZE)				return (1);		/* Unrecoverable hardware error, BUD not completed? */		} while((loop_cnt > 0) && ((Status & (STS_ERROR | STS_TEST))			!= (STS_ERROR | STS_TEST)));		/* Error preventing completion of BUD */		if(retry_cnt > 0)		{			printk(KERN_INFO "%s: Adapter Software Reset.\n", 				dev->name);			sktr_exec_sifcmd(dev, EXEC_SOFT_RESET);			sktr_wait(HALF_SECOND);		}	} while(retry_cnt > 0);	Status = inw(ioaddr + SIFSTS);	Status &= STS_ERROR_MASK;	/* Hardware error occurred! */	printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",		dev->name, Status);	return (-1);}/* * Copy initialisation data to adapter memory, beginning at address * 1:0A00; Starting DMA test and evaluating result bits. */static int sktr_init_adapter(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	const unsigned char SCB_Test[6] = {0x00, 0x00, 0xC1, 0xE2, 0xD4, 0x8B};	const unsigned char SSB_Test[8] = {0xFF, 0xFF, 0xD1, 0xD7,						0xC5, 0xD9, 0xC3, 0xD4};	void *ptr = (void *)&tp->ipb;	unsigned short *ipb_ptr = (unsigned short *)ptr;	unsigned char *cb_ptr = (unsigned char *) &tp->scb;	unsigned char *sb_ptr = (unsigned char *) &tp->ssb;	unsigned short Status;	int i, loop_cnt, retry_cnt;	int ioaddr = dev->base_addr;	/* Normalize: byte order low/high, word order high/low! (only IPB!) */	tp->ipb.SCB_Addr = SWAPW(virt_to_bus(&tp->scb));	tp->ipb.SSB_Addr = SWAPW(virt_to_bus(&tp->ssb));	/* Maximum: three initialization retries */	retry_cnt = INIT_MAX_RETRIES;	do {		retry_cnt--;		/* Transfer initialization block */		outw(0x0001, ioaddr + SIFADX);		/* To address 0001:0A00 of adapter RAM */		outw(0x0A00, ioaddr + SIFADD);		/* Write 11 words to adapter RAM */		for(i = 0; i < 11; i++)			outw(ipb_ptr[i], ioaddr + SIFINC);		/* Execute SCB adapter command */		sktr_exec_sifcmd(dev, CMD_EXECUTE);		loop_cnt = INIT_MAX_LOOPCNT;	/* Maximum: 11 seconds */		/* While remaining retries, no error and not completed */		do {			Status = 0;			loop_cnt--;			sktr_wait(HALF_SECOND);			/* Mask interesting status bits */			Status = inw(ioaddr + SIFSTS);			Status &= STS_MASK;		} while(((Status &(STS_INITIALIZE | STS_ERROR | STS_TEST)) != 0)			&& ((Status & STS_ERROR) == 0) && (loop_cnt != 0));		if((Status & (STS_INITIALIZE | STS_ERROR | STS_TEST)) == 0)		{			/* Initialization completed without error */			i = 0;			do {	/* Test if contents of SCB is valid */				if(SCB_Test[i] != *(cb_ptr + i))					/* DMA data error: wrong data in SCB */					return (-1);				i++;			} while(i < 6);			i = 0;			do {	/* Test if contents of SSB is valid */				if(SSB_Test[i] != *(sb_ptr + i))					/* DMA data error: wrong data in SSB */					return (-1);				i++;			} while (i < 8);			return (1);	/* Adapter successfully initialized */		}		else		{			if((Status & STS_ERROR) != 0)			{				/* Initialization error occurred */				Status = inw(ioaddr + SIFSTS);				Status &= STS_ERROR_MASK;				/* ShowInitialisationErrorCode(Status); */				return (-1); /* Unrecoverable error */			}			else			{				if(retry_cnt > 0)				{					/* Reset adapter and try init again */					sktr_exec_sifcmd(dev, EXEC_SOFT_RESET);					sktr_wait(HALF_SECOND);				}			}		}	} while(retry_cnt > 0);	return (-1);}/* * Check for outstanding commands in command queue and tries to execute * command immediately. Corresponding command flag in command queue is cleared. */static void sktr_chk_outstanding_cmds(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	unsigned long Addr = 0;	unsigned char i = 0;	if(tp->CMDqueue == 0)		return;		/* No command execution */	/* If SCB in use: no command */	if(tp->ScbInUse == 1)		return;	/* Check if adapter is opened, avoiding COMMAND_REJECT	 * interrupt by the adapter!	 */	if(tp->AdapterOpenFlag == 0)	{		if(tp->CMDqueue & OC_OPEN)		{			/* Execute OPEN command	*/			tp->CMDqueue ^= OC_OPEN;			/* Copy the 18 bytes of the product ID */			while((AdapterName[i] != '\0') && (i < PROD_ID_SIZE))			{				tp->ProductID[i] = AdapterName[i];				i++;			}			Addr = htonl(virt_to_bus(&tp->ocpl));			tp->scb.Parm[0] = LOWORD(Addr);			tp->scb.Parm[1] = HIWORD(Addr);			tp->scb.CMD = OPEN;		}		else			/* No OPEN command queued, but adapter closed. Note:			 * We'll try to re-open the adapter in DriverPoll()			 */			return;		/* No adapter command issued */	}	else	{		/* Adapter is open; evaluate command queue: try to execute		 * outstanding commands (depending on priority!) CLOSE		 * command queued		 */		if(tp->CMDqueue & OC_CLOSE)		{			tp->CMDqueue ^= OC_CLOSE;			tp->AdapterOpenFlag = 0;			tp->scb.Parm[0] = 0; /* Parm[0], Parm[1] are ignored */			tp->scb.Parm[1] = 0; /* but should be set to zero! */			tp->scb.CMD = CLOSE;			if(!tp->HaltInProgress)				tp->CMDqueue |= OC_OPEN; /* re-open adapter */			else				tp->CMDqueue = 0;	/* no more commands */		}		else		{			if(tp->CMDqueue & OC_RECEIVE)			{				tp->CMDqueue ^= OC_RECEIVE;				Addr = htonl(virt_to_bus(tp->RplHead));				tp->scb.Parm[0] = LOWORD(Addr);				tp->scb.Parm[1] = HIWORD(Addr);				tp->scb.CMD = RECEIVE;			}			else			{				if(tp->CMDqueue & OC_TRANSMIT_HALT)				{					/* NOTE: TRANSMIT.HALT must be checked 					 * before TRANSMIT.					 */					tp->CMDqueue ^= OC_TRANSMIT_HALT;					tp->scb.CMD = TRANSMIT_HALT;					/* Parm[0] and Parm[1] are ignored					 * but should be set to zero!					 */					tp->scb.Parm[0] = 0;					tp->scb.Parm[1] = 0;				}				else				{					if(tp->CMDqueue & OC_TRANSMIT)					{						/* NOTE: TRANSMIT must be 						 * checked after TRANSMIT.HALT						 */						if(tp->TransmitCommandActive)						{							if(!tp->TransmitHaltScheduled)							{								tp->TransmitHaltScheduled = 1;								sktr_exec_cmd(dev, OC_TRANSMIT_HALT) ;							}							tp->TransmitCommandActive = 0;							return;						}						tp->CMDqueue ^= OC_TRANSMIT;						sktr_cancel_tx_queue(tp);						Addr = htonl(virt_to_bus(tp->TplBusy));						tp->scb.Parm[0] = LOWORD(Addr);						tp->scb.Parm[1] = HIWORD(Addr);						tp->scb.CMD = TRANSMIT;						tp->TransmitCommandActive = 1;					}					else					{						if(tp->CMDqueue & OC_MODIFY_OPEN_PARMS)						{							tp->CMDqueue ^= OC_MODIFY_OPEN_PARMS;							tp->scb.Parm[0] = tp->ocpl.OPENOptions; /* new OPEN options*/							tp->scb.Parm[0] |= ENABLE_FULL_DUPLEX_SELECTION;							tp->scb.Parm[1] = 0; /* is ignored but should be zero */							tp->scb.CMD = MODIFY_OPEN_PARMS;						}						else						{							if(tp->CMDqueue & OC_SET_FUNCT_ADDR)							{								tp->CMDqueue ^= OC_SET_FUNCT_ADDR;								tp->scb.Parm[0] = LOWORD(tp->ocpl.FunctAddr);								tp->scb.Parm[1] = HIWORD(tp->ocpl.FunctAddr);								tp->scb.CMD = SET_FUNCT_ADDR;							}							else							{								if(tp->CMDqueue & OC_SET_GROUP_ADDR)								{									tp->CMDqueue ^= OC_SET_GROUP_ADDR;									tp->scb.Parm[0] = LOWORD(tp->ocpl.GroupAddr);									tp->scb.Parm[1] = HIWORD(tp->ocpl.GroupAddr);									tp->scb.CMD = SET_GROUP_ADDR;								}								else								{									if(tp->CMDqueue & OC_READ_ERROR_LOG)									{										tp->CMDqueue ^= OC_READ_ERROR_LOG;										Addr = htonl(virt_to_bus(&tp->errorlogtable));										tp->scb.Parm[0] = LOWORD(Addr);										tp->scb.Parm[1] = HIWORD(Addr);										tp->scb.CMD = READ_ERROR_LOG;									}									else									{										printk(KERN_WARNING "CheckForOutstandingCommand: unknown Command\n");										tp->CMDqueue = 0;										return;									}								}							}						}					}				}			}		}	}	tp->ScbInUse = 1;	/* Set semaphore: SCB in use. */	/* Execute SCB and generate IRQ when done. */	sktr_exec_sifcmd(dev, CMD_EXECUTE | CMD_SCB_REQUEST);	return;}/* * IRQ conditions: signal loss on the ring, transmit or receive of beacon * frames (disabled if bit 1 of OPEN option is set); report error MAC * frame transmit (disabled if bit 2 of OPEN option is set); open or short * cirquit fault on the lobe is detected; remove MAC frame received; * error counter overflow (255); opened adapter is the only station in ring. * After some of the IRQs the adapter is closed! */static void sktr_ring_status_irq(struct device *dev){	struct net_local *tp = (struct net_local *)dev->priv;	tp->CurrentRingStatus = SWAPB(tp->ssb.Parm[0]);	/* First: fill up statistics */	if(tp->ssb.Parm[0] & SIGNAL_LOSS)	{		printk(KERN_INFO "%s: Signal Loss\n", dev->name);		tp->MacStat.line_errors++;	}	/* Adapter is closed, but initialized */	if(tp->ssb.Parm[0] & LOBE_WIRE_FAULT)	{		printk(KERN_INFO "%s: Lobe Wire Fault, Reopen Adapter\n", 			dev->name);		tp->MacStat.line_errors++;	}	if(tp->ssb.Parm[0] & RING_RECOVERY)		printk(KERN_INFO "%s: Ring Recovery\n", dev->name);	/* Counter overflow: read error log */	if(tp->ssb.Parm[0] & COUNTER_OVERFLOW)	{		printk(KERN_INFO "%s: Counter Overflow\n", dev->name);		sktr_exec_cmd(dev, OC_READ_ERROR_LOG);	}	/* Adapter is closed, but initialized */	if(tp->ssb.Parm[0] & REMOVE_RECEIVED)		printk(KERN_INFO "%s: Remove Received, Reopen Adapter\n", 			dev->name);	/* Adapter is closed, but initialized */	if(tp->ssb.Parm[0] & AUTO_REMOVAL_ERROR)		printk(KERN_INFO "%s: Auto Removal Error, Reopen Adapter\n", 			dev->name);	if(tp->ssb.Parm[0] & HARD_ERROR)		printk(KERN_INFO "%s: Hard Error\n", dev->name);	if(tp->ssb.Parm[0] & SOFT_ERROR)		printk(KERN_INFO "%s: Soft Error\n", dev->name);	if(tp->ssb.Parm[0] & TRANSMIT_BEACON)		printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);	if(tp->ssb.Parm[0] & SINGLE_STATION)		printk(KERN_INFO "%s: Single Station\n", dev->name);	/* Check if adapter has been closed */	if(tp->ssb.Parm[0] & ADAPTER_CLOSED)	{		printk(KERN_INFO "%s: Adapter closed (Reopening)," 			"QueueSkb %d, CurrentRingStat %x\n",			dev->name, tp->QueueSkb, tp->CurrentRingStatus);		tp->AdapterOpenFlag = 0;		sktr_open_adapter(dev);	}	return;}/* * Issued if adapter has encountered an unrecoverable hardware * or software error. */static void sktr_chk_irq(struct device *dev){	int i;	unsigned short AdapterCheckBlock[4];	unsigned short ioaddr = dev->base_addr;	struct net_local *tp = (struct net_local *)dev->priv;	tp->AdapterOpenFlag = 0;	/* Adapter closed now */	/* Page number of adapter memory */	outw(0x0001, ioaddr + SIFADX);	/* Address offset */	outw(CHECKADDR, ioaddr + SIFADR);	/* Reading 8 byte adapter check block. */	for(i = 0; i < 4; i++)		AdapterCheckBlock[i] = inw(ioaddr + SIFINC);

⌨️ 快捷键说明

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