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

📄 eepro.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
	return dev->irq;}static int eepro_open(struct net_device *dev){	unsigned short temp_reg, old8, old9;	int irqMask;	int i, ioaddr = dev->base_addr;	struct eepro_local *lp = (struct eepro_local *)dev->priv;	if (net_debug > 3)		printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);	irqMask = read_eeprom(ioaddr,7,dev);	if (lp->eepro == LAN595FX_10ISA) {		if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n"); 	}	else if (irqMask == ee_FX_INT2IRQ) /* INT to IRQ Mask */		{			lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); 		}	else if ((dev->dev_addr[0] == SA_ADDR0 &&			dev->dev_addr[1] == SA_ADDR1 &&			dev->dev_addr[2] == SA_ADDR2))		{ 			lp->eepro = 1;			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n"); 		}  /* Yes, an Intel EtherExpress Pro/10 */	else lp->eepro = 0; /* No, it is a generic 82585 lan card */	/* Get the interrupt vector for the 82595 */		if (dev->irq < 2 && eepro_grab_irq(dev) == 0) {		printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);		return -EAGAIN;	}			if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) {		printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);		return -EAGAIN;	}	#ifdef irq2dev_map	if  (((irq2dev_map[dev->irq] != 0)		|| (irq2dev_map[dev->irq] = dev) == 0) && 		(irq2dev_map[dev->irq]!=dev)) {		/* printk("%s: IRQ map wrong\n", dev->name); */		return -EAGAIN;	}#endif	/* Initialize the 82595. */	eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */	temp_reg = inb(ioaddr + eeprom_reg);	lp->stepping = temp_reg >> 5;	/* Get the stepping number of the 595 */		if (net_debug > 3)		printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping);	if (temp_reg & 0x10) /* Check the TurnOff Enable bit */		outb(temp_reg & 0xef, ioaddr + eeprom_reg);	for (i=0; i < 6; i++) 		outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); 				temp_reg = inb(ioaddr + REG1);    /* Setup Transmit Chaining */	outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */		| RCV_Discard_BadFrame, ioaddr + REG1);  	temp_reg = inb(ioaddr + REG2); /* Match broadcast */	outb(temp_reg | 0x14, ioaddr + REG2);	temp_reg = inb(ioaddr + REG3);	outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */	/* Set the receiving mode */	eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */	/* Set the interrupt vector */		temp_reg = inb(ioaddr + INT_NO_REG);	if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA)		outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); 	temp_reg = inb(ioaddr + INT_NO_REG);	if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA)		outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);	if (net_debug > 3)		printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);	/* Initialize the RCV and XMT upper and lower limits */	outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); 	outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); 	outb(XMT_LOWER_LIMIT, ioaddr + xmt_lower_limit_reg);	outb(XMT_UPPER_LIMIT, ioaddr + xmt_upper_limit_reg);	/* Enable the interrupt line. */	eepro_en_intline(ioaddr);	/* Switch back to Bank 0 */	eepro_sw2bank0(ioaddr);	/* Let RX and TX events to interrupt */	eepro_en_int(ioaddr);	/* clear all interrupts */	eepro_clear_int(ioaddr);	/* Initialize RCV */	outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); 	lp->rx_start = (RCV_LOWER_LIMIT << 8) ;	outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); 	/* Initialize XMT */	outw(XMT_LOWER_LIMIT << 8, ioaddr + xmt_bar); 	/* Check for the i82595TX and i82595FX */	old8 = inb(ioaddr + 8);	outb(~old8, ioaddr + 8);	if ((temp_reg = inb(ioaddr + 8)) == old8) {		if (net_debug > 3)			printk(KERN_DEBUG "i82595 detected!\n");		lp->version = LAN595;	}	else {		lp->version = LAN595TX;		outb(old8, ioaddr + 8);		old9 = inb(ioaddr + 9);		/*outb(~old9, ioaddr + 9);		if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) {*/				if (irqMask==ee_FX_INT2IRQ) {			enum iftype { AUI=0, BNC=1, TPE=2 };			if (net_debug > 3) {				printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);				printk(KERN_DEBUG "i82595FX detected!\n");			}			lp->version = LAN595FX;			outb(old9, ioaddr + 9);			if (dev->if_port != TPE) {	/* Hopefully, this will fix the							problem of using Pentiums and							pro/10 w/ BNC. */				eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */				temp_reg = inb(ioaddr + REG13);				/* disable the full duplex mode since it is not				applicable with the 10Base2 cable. */				outb(temp_reg & ~(FDX | A_N_ENABLE), REG13);				eepro_sw2bank0(ioaddr); /* be CAREFUL, BANK 0 now */			}		}		else if (net_debug > 3) {			printk(KERN_DEBUG "temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));			printk(KERN_DEBUG "i82595TX detected!\n");		}	}		eepro_sel_reset(ioaddr);	lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8;	lp->tx_last = 0;	netif_start_queue(dev);		if (net_debug > 3)		printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);	/* enabling rx */	eepro_en_rx(ioaddr);	return 0;}static void eepro_tx_timeout (struct net_device *dev){	struct eepro_local *lp = (struct eepro_local *) dev->priv;	int ioaddr = dev->base_addr;	/* if (net_debug > 1) */	printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name,		"network cable problem");	/* This is not a duplicate. One message for the console, 	   one for the the log file  */	printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,		"network cable problem");	eepro_complete_selreset(ioaddr);}static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev){	struct eepro_local *lp = (struct eepro_local *)dev->priv;	unsigned long flags;		if (net_debug > 5)		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);		netif_stop_queue (dev);	spin_lock_irqsave(&lp->lock, flags);	{		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;		unsigned char *buf = skb->data;		lp->stats.tx_bytes+=skb->len;		hardware_send_packet(dev, buf, length);		dev->trans_start = jiffies;	}	dev_kfree_skb (skb);	/* You might need to clean up and record Tx statistics here. */	/* lp->stats.tx_aborted_errors++; */	if (net_debug > 5)		printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);	spin_unlock_irqrestore(&lp->lock, flags);		return 0;}/*	The typical workload of the driver:	Handle the network interface interrupts. */static voideepro_interrupt(int irq, void *dev_id, struct pt_regs * regs){	struct net_device *dev =  (struct net_device *)dev_id;	                      /* (struct net_device *)(irq2dev_map[irq]);*/	struct eepro_local *lp = (struct eepro_local *)dev->priv;	int ioaddr, status, boguscount = 20;	if (dev == NULL) {                printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);                return;        }        spin_lock(&lp->lock);	if (net_debug > 5)		printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);		ioaddr = dev->base_addr;	while (((status = inb(ioaddr + STATUS_REG)) & 0x06) && (boguscount--))	{		switch (status & (RX_INT | TX_INT)) {			case (RX_INT | TX_INT):				eepro_ack_rxtx(ioaddr);				break;			case RX_INT:				eepro_ack_rx(ioaddr);				break;			case TX_INT:				eepro_ack_tx(ioaddr);				break;		}		if (status & RX_INT) {			if (net_debug > 4)				printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);			/* Get the received packets */			eepro_rx(dev);		}		if (status & TX_INT) {			if (net_debug > 4) 				printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);			/* Process the status of transmitted packets */			eepro_transmit_interrupt(dev);		}	}	if (net_debug > 5)		printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);	spin_unlock(&lp->lock);	return;}static int eepro_close(struct net_device *dev){	struct eepro_local *lp = (struct eepro_local *)dev->priv;	int ioaddr = dev->base_addr;	short temp_reg;	netif_stop_queue(dev);	eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */	/* Disable the physical interrupt line. */	temp_reg = inb(ioaddr + REG1);	outb(temp_reg & 0x7f, ioaddr + REG1); 	eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */	/* Flush the Tx and disable Rx. */	outb(STOP_RCV_CMD, ioaddr); 	lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8);	lp->tx_last = 0;	/* Mask all the interrupts. */	eepro_dis_int(ioaddr);	/* clear all interrupts */	eepro_clear_int(ioaddr);	/* Reset the 82595 */	eepro_reset(ioaddr);	/* release the interrupt */	free_irq(dev->irq, dev);#ifdef irq2dev_map	irq2dev_map[dev->irq] = 0;#endif	/* Update the statistics here. What statistics? */	return 0;}/* Get the current statistics.	This may be called with the card open or   closed. */static struct net_device_stats *eepro_get_stats(struct net_device *dev){	struct eepro_local *lp = (struct eepro_local *)dev->priv;	return &lp->stats;}/* Set or clear the multicast filter for this adaptor. */static voidset_multicast_list(struct net_device *dev){	struct eepro_local *lp = (struct eepro_local *)dev->priv;	short ioaddr = dev->base_addr;	unsigned short mode;	struct dev_mc_list *dmi=dev->mc_list;	if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) 	{		/*		 *	We must make the kernel realise we had to move		 *	into promisc mode or we start all out war on		 *	the cable. If it was a promisc request the		 *	flag is already set. If not we assert it.		 */		dev->flags|=IFF_PROMISC;				eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */		mode = inb(ioaddr + REG2);		outb(mode | PRMSC_Mode, ioaddr + REG2);			mode = inb(ioaddr + REG3);		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */		printk("%s: promiscuous mode enabled.\n", dev->name);	}		else if (dev->mc_count==0 ) 	{		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */		mode = inb(ioaddr + REG2);		outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */		mode = inb(ioaddr + REG3);		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */	}		else 	{		unsigned short status, *eaddrs;		int i, boguscount = 0;				/* Disable RX and TX interrupts.  Necessary to avoid		   corruption of the HOST_ADDRESS_REG by interrupt		   service routines. */		eepro_dis_int(ioaddr);		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */		mode = inb(ioaddr + REG2);		outb(mode | Multi_IA, ioaddr + REG2);			mode = inb(ioaddr + REG3);		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */		outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG);		outw(MC_SETUP, ioaddr + IO_PORT);		outw(0, ioaddr + IO_PORT);		outw(0, ioaddr + IO_PORT);		outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);				for (i = 0; i < dev->mc_count; i++) 		{			eaddrs=(unsigned short *)dmi->dmi_addr;			dmi=dmi->next;			outw(*eaddrs++, ioaddr + IO_PORT);			outw(*eaddrs++, ioaddr + IO_PORT);			outw(*eaddrs++, ioaddr + IO_PORT);		}				eaddrs = (unsigned short *) dev->dev_addr;		outw(eaddrs[0], ioaddr + IO_PORT);		outw(eaddrs[1], ioaddr + IO_PORT);		outw(eaddrs[2], ioaddr + IO_PORT);		outw(lp->tx_end, ioaddr + xmt_bar);		outb(MC_SETUP, ioaddr);		/* Update the transmit queue */		i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);				if (lp->tx_start != lp->tx_end) 		{			/* update the next address and the chain bit in the 			   last packet */			outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);			outw(i, ioaddr + IO_PORT);			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);			status = inw(ioaddr + IO_PORT);			outw(status | CHAIN_BIT, ioaddr + IO_PORT);			lp->tx_end = i ;		}		else {			lp->tx_start = lp->tx_end = i ;		}		/* Acknowledge that the MC setup is done */		do { /* We should be doing this in the eepro_interrupt()! */			SLOW_DOWN;			SLOW_DOWN;			if (inb(ioaddr + STATUS_REG) & 0x08) 			{				i = inb(ioaddr);				outb(0x08, ioaddr + STATUS_REG);				

⌨️ 快捷键说明

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