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

📄 8139too.c

📁 8139driver_in)linux2.4.x
💻 C
📖 第 1 页 / 共 5 页
字号:
	tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);	if (tp->thr_pid < 0)		printk (KERN_WARNING "%s: unable to start kernel thread\n",			dev->name);	DPRINTK ("EXIT, returning 0\n");	return 0;}/* Start the hardware at open or resume. */static void rtl8139_hw_start (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	u32 i;	u8 tmp;	DPRINTK ("ENTER\n");	/* Soft reset the chip. */	RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);	udelay (100);	/* Check that the chip has finished the reset. */	for (i = 1000; i > 0; i--)		if ((RTL_R8 (ChipCmd) & CmdReset) == 0)			break;	/* unlock Config[01234] and BMCR register writes */	RTL_W8_F (Cfg9346, Cfg9346_Unlock);	/* Restore our idea of the MAC address. */	RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));	RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));	/* Must enable Tx/Rx before setting transfer thresholds! */	RTL_W8_F (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) |			   CmdRxEnb | CmdTxEnb);	i = rtl8139_rx_config |	    (RTL_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);	RTL_W32_F (RxConfig, i);	/* Check this value: the documentation for IFG contradicts ifself. */	RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift));	tp->cur_rx = 0;	/* This is check_duplex() */	if (tp->phys[0] >= 0  ||  (tp->drv_flags & HAS_MII_XCVR)) {		u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);		if (mii_reg5 == 0xffff)			;					/* Not there */		else if ((mii_reg5 & 0x0100) == 0x0100				 || (mii_reg5 & 0x00C0) == 0x0040)			tp->full_duplex = 1;		printk(KERN_INFO"%s: Setting %s%s-duplex based on"			   " auto-negotiated partner ability %4.4x.\n", dev->name,			   mii_reg5 == 0 ? "" :			   (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",			   tp->full_duplex ? "full" : "half", mii_reg5);	}	if (tp->chipset >= CH_8139A) {		tmp = RTL_R8 (Config1) & Config1Clear;		tmp |= Cfg1_Driver_Load;		tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */		RTL_W8_F (Config1, tmp);	} else {		u8 foo = RTL_R8 (Config1) & Config1Clear;		RTL_W8 (Config1, tp->full_duplex ? (foo|0x60) : (foo|0x20));	}	if (tp->chipset >= CH_8139B) {		tmp = RTL_R8 (Config4) & ~(1<<2);		/* chip will clear Rx FIFO overflow automatically */		tmp |= (1<<7);		RTL_W8 (Config4, tmp);		/* disable magic packet scanning, which is enabled		 * when PM is enabled above (Config1) */		RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));	}	/* Lock Config[01234] and BMCR register writes */	RTL_W8_F (Cfg9346, Cfg9346_Lock);	udelay (10);	/* init Rx ring buffer DMA address */	RTL_W32_F (RxBuf, tp->rx_ring_dma);	/* init Tx buffer DMA addresses */	for (i = 0; i < NUM_TX_DESC; i++)		RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));	RTL_W32_F (RxMissed, 0);	rtl8139_set_rx_mode (dev);	/* no early-rx interrupts */	RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);	/* make sure RxTx has started */	RTL_W8_F (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) |			   CmdRxEnb | CmdTxEnb);	/* Enable all known interrupts by setting the interrupt mask. */	RTL_W16_F (IntrMask, rtl8139_intr_mask);	netif_start_queue (dev);	DPRINTK ("EXIT\n");}/* Initialize the Rx and Tx rings, along with various 'dev' bits. */static void rtl8139_init_ring (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	int i;	DPRINTK ("ENTER\n");	tp->cur_rx = 0;	tp->cur_tx = 0;	tp->dirty_tx = 0;	for (i = 0; i < NUM_TX_DESC; i++) {		tp->tx_info[i].skb = NULL;		tp->tx_info[i].mapping = 0;		tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];	}	DPRINTK ("EXIT\n");}static int rtl8139CP_open (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	int retval;	u8 diff;			//for 8139C+	u32 txPhyAddr, rxPhyAddr;	//for 8139C+#ifdef RTL8139_DEBUG	void *ioaddr = tp->mmio_addr;#endif	DPRINTK ("ENTER\n");	retval = request_irq (dev->irq, rtl8139CP_interrupt, SA_SHIRQ, dev->name, dev);	if (retval) {		DPRINTK ("EXIT, returning %d\n", retval);		return retval;	}	//////////////////////////////////////////////////////////////////////////////	tp->TxDescArrays= kmalloc(NUM_CP_TX_DESC*sizeof(struct CPlusTxDesc)+256 , GFP_KERNEL);	// Tx Desscriptor needs 256 bytes alignment;	txPhyAddr=virt_to_bus(tp->TxDescArrays);	diff=txPhyAddr-((txPhyAddr >> 8)<< 8);	diff=256-diff;	txPhyAddr +=diff;	tp->TxDescArray = (struct CPlusTxDesc *)(tp->TxDescArrays + diff);	tp->RxDescArrays= kmalloc(NUM_CP_RX_DESC*sizeof(struct CPlusRxDesc)+256 , GFP_KERNEL);	// Rx Desscriptor needs 256 bytes alignment;	rxPhyAddr=virt_to_bus(tp->RxDescArrays);	diff=rxPhyAddr-((rxPhyAddr >> 8)<< 8);	diff=256-diff;	rxPhyAddr +=diff;	tp->RxDescArray = (struct CPlusRxDesc *)(tp->RxDescArrays + diff);		if (tp->TxDescArrays == NULL || tp->RxDescArrays == NULL) {		printk(KERN_INFO"Allocate RxDescArray or TxDescArray failed\n");		free_irq(dev->irq, dev);		if (tp->TxDescArrays) kfree(tp->TxDescArrays);		if (tp->RxDescArrays) kfree(tp->RxDescArrays);		DPRINTK ("EXIT, returning -ENOMEM\n");		return -ENOMEM;	}	tp->RxBufferRings=kmalloc( CP_RX_BUF_SIZE*NUM_CP_RX_DESC, GFP_KERNEL);	if(tp->RxBufferRings==NULL){		printk(KERN_INFO"Allocate RxBufferRing failed\n");	}	//////////////////////////////////////////////////////////////////////////////	tp->full_duplex = tp->duplex_lock;	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;	tp->twistie = 1;	rtl8139CP_init_ring (dev);	rtl8139CP_hw_start (dev);	DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d"			" GP Pins %2.2x %s-duplex.\n",			dev->name, pci_resource_start (tp->pci_dev, 1),			dev->irq, RTL_R8 (MediaStatus),			tp->full_duplex ? "full" : "half");	tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);	if (tp->thr_pid < 0)		printk (KERN_WARNING "%s: unable to start kernel thread\n",			dev->name);	DPRINTK ("EXIT, returning 0\n");	return 0;}/* Start the hardware at open or resume. */static void rtl8139CP_hw_start (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	u32 i;	u8 tmp;	u16 BasicModeCtrlReg;	u8 MediaStatusReg;	DPRINTK ("ENTER\n");	/* Soft reset the chip. */	RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);	udelay (100);	/* Check that the chip has finished the reset. */	for (i = 1000; i > 0; i--)		if ((RTL_R8 (ChipCmd) & CmdReset) == 0)			break;	/* unlock Config[01234] and BMCR register writes */	RTL_W8_F (Cfg9346, Cfg9346_Unlock);	RTL_W16 (CPlusCmd, CPlusTxEnb | CPlusRxEnb | CPlusCheckSumEnb);	//C+ mode only	/* Restore our idea of the MAC address. */	RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));	RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));	/* Must enable Tx/Rx before setting transfer thresholds! */	RTL_W8 (ChipCmd,CmdRxEnb | CmdTxEnb);					//C+ mode only	RTL_W8 (CPlusEarlyTxThldReg, CPlusEarlyTxThld);			//C+ mode only	i = rtl8139_rx_config | (RTL_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);	RTL_W32_F (RxConfig, i);	/* Check this value: the documentation for IFG contradicts ifself. */	RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift)|0x03000000);	tp->CP_cur_rx = 0;/*	//////////////////////////////////////////////////////////////	RTL_W8_F (Cfg9346, Cfg9346_Unlock);	RTL_W16 (NWayAdvert, AutoNegoAbility10half | AutoNegoAbility10full | AutoNegoAbility100half | AutoNegoAbility100full);	RTL_W16_F (BasicModeCtrl, AutoNegotiationEnable|AutoNegotiationRestart);	RTL_W8_F (Cfg9346, Cfg9346_Lock);	//////////////////////////////////////////////////////////////*/	MediaStatusReg = RTL_R8(MediaStatus);	BasicModeCtrlReg = RTL_R16(BasicModeCtrl);	/* This is check_duplex() */	if (tp->phys[0] >= 0  ||  (tp->drv_flags & HAS_MII_XCVR)) {		u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);		if (mii_reg5 == 0xffff)			;					/* Not there */		else if ((mii_reg5 & 0x0100) == 0x0100				 || (mii_reg5 & 0x00C0) == 0x0040)			tp->full_duplex = 1;/*		printk(KERN_INFO"%s: Setting %s%s-duplex based on"			   " auto-negotiated partner ability %4.4x.\n", dev->name,			   mii_reg5 == 0 ? "" :			   (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",			   tp->full_duplex ? "full" : "half", mii_reg5);*/		printk(KERN_INFO"%s: Setting %s%s-duplex based on"			   " auto-negotiated partner ability %4.4x.\n", dev->name,			   (MediaStatusReg & Speed_10) ? "10mbps " : "100mbps ",			   (BasicModeCtrlReg & DuplexMode) ? "full" : "half", mii_reg5);	}	if (tp->chipset >= CH_8139A) {		tmp = RTL_R8 (Config1) & Config1Clear;		tmp |= Cfg1_Driver_Load;		tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */		RTL_W8_F (Config1, tmp);	} else {		u8 foo = RTL_R8 (Config1) & Config1Clear;		RTL_W8 (Config1, tp->full_duplex ? (foo|0x60) : (foo|0x20));	}	if (tp->chipset >= CH_8139B) {		tmp = RTL_R8 (Config4) & ~(1<<2);		/* chip will clear Rx FIFO overflow automatically */		tmp |= (1<<7);		RTL_W8 (Config4, tmp);		/* disable magic packet scanning, which is enabled		 * when PM is enabled above (Config1) */		RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));	}	RTL_W32 ( CPlusTxStartAddr, virt_to_bus(tp->TxDescArray) );	//C+ mode only	RTL_W32 ( CPlusRxStartAddr, virt_to_bus(tp->RxDescArray) );	//C+ mode only		/* Lock Config[01234] and BMCR register writes */	RTL_W8_F (Cfg9346, Cfg9346_Lock);	udelay (10);	RTL_W32_F (RxMissed, 0);	rtl8139_set_rx_mode (dev);	/* no early-rx interrupts */	RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);	/* Enable all known interrupts by setting the interrupt mask. */	RTL_W16_F (IntrMask, rtl8139_intr_mask);	netif_start_queue (dev);	DPRINTK ("EXIT\n");}/* Initialize the Rx and Tx rings, along with various 'dev' bits. */static void rtl8139CP_init_ring (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	int i;	DPRINTK ("ENTER\n");	//////////////////////////////////////////////////////////////////////////////	tp->CP_cur_rx = 0;	tp->CP_cur_tx = 0;	tp->CP_dirty_tx = 0;	memset(tp->TxDescArray, 0x0, NUM_CP_TX_DESC*sizeof(struct CPlusTxDesc));	memset(tp->RxDescArray, 0x0, NUM_CP_RX_DESC*sizeof(struct CPlusRxDesc));	for (i=0 ; i<NUM_CP_TX_DESC ; i++){		tp->Tx_skbuff[i]=NULL;	}	for (i=0; i <NUM_CP_RX_DESC; i++) {		if(i==(NUM_CP_RX_DESC-1))			tp->RxDescArray[i].status = 0xC0000000+CP_RX_BUF_SIZE;		else			tp->RxDescArray[i].status = 0x80000000+CP_RX_BUF_SIZE;		tp->RxBufferRing[i]= &(tp->RxBufferRings[i*CP_RX_BUF_SIZE]);		tp->RxDescArray[i].buf_addr=virt_to_bus(tp->RxBufferRing[i]);	}	//////////////////////////////////////////////////////////////////////////////	DPRINTK ("EXIT\n");}/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */static int next_tick = 3 * HZ;#ifndef CONFIG_8139TOO_TUNE_TWISTERstatic inline void rtl8139_tune_twister (struct net_device *dev,				  struct rtl8139_private *tp) {}#elsestatic void rtl8139_tune_twister (struct net_device *dev,				  struct rtl8139_private *tp){	int linkcase;	void *ioaddr = tp->mmio_addr;	DPRINTK ("ENTER\n");	/* This is a complicated state machine to configure the "twister" for	   impedance/echos based on the cable length.	   All of this is magic and undocumented.	 */	switch (tp->twistie) {	case 1:		if (RTL_R16 (CSCR) & CSCR_LinkOKBit) {			/* We have link beat, let us tune the twister. */			RTL_W16 (CSCR, CSCR_LinkDownOffCmd);			tp->twistie = 2;	/* Change to state 2. */			next_tick = HZ / 10;		} else {			/* Just put in some reasonable defaults for when beat returns. */			RTL_W16 (CSCR, CSCR_LinkDownCmd);			RTL_W32 (FIFOTMS, 0x20);	/* Turn on cable test mode. */			RTL_W32 (PARA78, PARA78_default);			RTL_W32 (PARA7c, PARA7c_default);			tp->twistie = 0;	/* Bail from future actions. */		}		break;	case 2:		/* Read how long it took to hear the echo. */		linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits;		if (linkcase == 0x7000)			tp->twist_row = 3;		else if (linkcase == 0x3000)			tp->twist_row = 2;		else if (linkcase == 0x1000)			tp->twist_row = 1;		else			tp->twist_row = 0;		tp->twist_col = 0;		tp->twistie = 3;	/* Change to state 2. */		next_tick = HZ / 10;		break;	case 3:		/* Put out four tuning parameters, one per 100msec. */		if (tp->twist_col == 0)			RTL_W16 (FIFOTMS, 0);		RTL_W32 (PARA7c, param[(int) tp->twist_row]			 [(int) tp->twist_col]);		next_tick = HZ / 10;		if (++tp->twist_col >= 4) {			/* For short cables we are done.			   For long cables (row == 3) check for mistune. */			tp->twistie =			    (tp->twist_row == 3) ? 4 : 0;		}		break;	case 4:		/* Special case for long cables: check for mistune. */		if ((RTL_R16 (CSCR) &		     CSCR_LinkStatusBits) == 0x7000) {			tp->twistie = 0;			break;		} else {			RTL_W32 (PARA7c, 0xfb38de03);			tp->twistie = 5;			next_tick = HZ / 10;		}		break;	case 5:		/* Retune for shorter cable (column 2). */		RTL_W32 (FIFOTMS, 0x20);		RTL_W32 (PARA78, PARA78_default);		RTL_W32 (PARA7c, PARA7c_default);		RTL_W32 (FIFOTMS, 0x00);		tp->twist_row = 2;		tp->twist_col = 0;		tp->twistie = 3;		next_tick = HZ / 10;		break;	default:		/* do nothing */		break;	}	DPRINTK ("EXIT\n");}#endif /* CONFIG_8139TOO_TUNE_TWISTER */static inline void rtl8139_thread_iter (struct net_device *dev,				 struct rtl8139_private *tp,				 void *ioaddr){	int mii_reg5;	mii_reg5 = mdio_read (dev, tp->phys[0], 5);	if (!tp->duplex_lock && mii_reg5 != 0xffff) {		int duplex = (mii_reg5 & 0x0100)		    || (mii_reg5 & 0x01C0) == 0x0040;		if (tp->full_duplex != duplex) {			tp->full_duplex = duplex;			printk (KERN_INFO

⌨️ 快捷键说明

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