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

📄 8139too.c

📁 2.4内核下8139芯片网卡驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct net_device *dev;	struct rtl8139_private *tp;	u8 tmp8;	int rc, i;	u32 pio_start, pio_end, pio_flags, pio_len;	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;	u32 tmp;	DPRINTK ("ENTER\n");	assert (pdev != NULL);	assert (ioaddr_out != NULL);	*ioaddr_out = NULL;	*dev_out = NULL;	/* dev zeroed in init_etherdev */	dev = init_etherdev (NULL, sizeof (*tp));	if (dev == NULL) {		printk (KERN_ERR PFX "unable to alloc new ethernet\n");		DPRINTK ("EXIT, returning -ENOMEM\n");		return -ENOMEM;	}	SET_MODULE_OWNER(dev);	tp = dev->priv;	/* enable device (incl. PCI PM wakeup and hotplug setup) */	rc = pci_enable_device (pdev);	if (rc)		goto err_out;	pio_start = pci_resource_start (pdev, 0);	pio_end = pci_resource_end (pdev, 0);	pio_flags = pci_resource_flags (pdev, 0);	pio_len = pci_resource_len (pdev, 0);	mmio_start = pci_resource_start (pdev, 1);	mmio_end = pci_resource_end (pdev, 1);	mmio_flags = pci_resource_flags (pdev, 1);	mmio_len = pci_resource_len (pdev, 1);	/* set this immediately, we need to know before	 * we talk to the chip directly */	DPRINTK("PIO region size == 0x%02X\n", pio_len);	DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);	if (pio_len == RTL8139B_IO_SIZE)		tp->chipset = CH_8139B;	/* make sure PCI base addr 0 is PIO */	if (!(pio_flags & IORESOURCE_IO)) {		printk (KERN_ERR PFX "region #0 not a PIO resource, aborting\n");		rc = -ENODEV;		goto err_out;	}	/* make sure PCI base addr 1 is MMIO */	if (!(mmio_flags & IORESOURCE_MEM)) {		printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n");		rc = -ENODEV;		goto err_out;	}	/* check for weird/broken PCI region reporting */	if ((pio_len < RTL_MIN_IO_SIZE) ||	    (mmio_len < RTL_MIN_IO_SIZE)) {		printk (KERN_ERR PFX "Invalid PCI region size(s), aborting\n");		rc = -ENODEV;		goto err_out;	}#ifndef USE_IO_OPS	rc = pci_request_regions (pdev, dev->name);	if (rc)		goto err_out;#endif /* !USE_IO_OPS */	/* enable PCI bus-mastering */	pci_set_master (pdev);#ifdef USE_IO_OPS	ioaddr = (void *) pio_start;	printk ("%s: use pci IO map. ioaddr=0x%08lx\n", dev->name, (unsigned long)ioaddr);#else	/* ioremap MMIO region */	ioaddr = ioremap (mmio_start, mmio_len);	if (ioaddr == NULL) {		printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");		rc = -EIO;		goto err_out_free_res;	}	printk ("%s: use memory map. ioaddr=0x%08lx\n", dev->name, (unsigned long)ioaddr);#endif /* USE_IO_OPS */	/* Soft reset the chip. */	RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);	/* Check that the chip has finished the reset. */	for (i = 1000; i > 0; i--)		if ((RTL_R8 (ChipCmd) & CmdReset) == 0)			break;		else			udelay (10);	/* Bring the chip out of low-power mode. */	if (tp->chipset == CH_8139B) {		RTL_W8 (Config1, RTL_R8 (Config1) & ~(1<<4));		RTL_W8 (Config4, RTL_R8 (Config4) & ~(1<<2));	} else {		/* handle RTL8139A and RTL8139 cases */		/* XXX from becker driver. is this right?? */		RTL_W8 (Config1, 0);	}	/* make sure chip thinks PIO and MMIO are enabled */	tmp8 = RTL_R8 (Config1);	if ((tmp8 & Cfg1_PIO) == 0) {		printk (KERN_ERR PFX "PIO not enabled, Cfg1=%02X, aborting\n", tmp8);		rc = -EIO;		goto err_out_iounmap;	}	if ((tmp8 & Cfg1_MMIO) == 0) {		printk (KERN_ERR PFX "MMIO not enabled, Cfg1=%02X, aborting\n", tmp8);		rc = -EIO;		goto err_out_iounmap;	}	/* identify chip attached to board *///	tmp = RTL_R8 (ChipVersion);	tmp = RTL_R32 (TxConfig);	tmp = ( (tmp&0x7c000000) + ( (tmp&0x00C00000)<<2 ) )>>24;	for (i = ARRAY_SIZE (rtl_chip_info) - 1; i >= 0; i--)		if (tmp == rtl_chip_info[i].version) {			tp->chipset = i;			goto match;		}	/* if unknown chip, assume array element #0, original RTL-8139 in this case */	printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n",		pdev->slot_name);	printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n", pdev->slot_name, RTL_R32 (TxConfig));	tp->chipset = 0;match:#ifdef FORCE_CPlus_Mode	if(tp->chipset >= (ARRAY_SIZE (rtl_chip_info) - 2))			tp->chipset = ARRAY_SIZE (rtl_chip_info) - 1;#endif#ifdef FORCE_C_Mode	if(tp->chipset > (ARRAY_SIZE (rtl_chip_info) - 2))		tp->chipset = ARRAY_SIZE (rtl_chip_info) - 2;#endif	DPRINTK ("chipset id (%d) == index %d, '%s'\n",		tmp,		tp->chipset,		rtl_chip_info[tp->chipset].name);	DPRINTK ("EXIT, returning 0\n");	*ioaddr_out = ioaddr;	*dev_out = dev;	return 0;err_out_iounmap:	assert (ioaddr > 0);#ifndef USE_IO_OPS	iounmap (ioaddr);err_out_free_res:	pci_release_regions (pdev);#endif /* !USE_IO_OPS */err_out:	unregister_netdev (dev);	kfree (dev);	DPRINTK ("EXIT, returning %d\n", rc);	return rc;}static int __devinit rtl8139_init_one (struct pci_dev *pdev,				       const struct pci_device_id *ent){	struct net_device *dev = NULL;	struct rtl8139_private *tp;	int i, addr_len, option;	void *ioaddr = NULL;	static int board_idx = -1;	static int printed_version;	u8 tmp;		DPRINTK ("ENTER\n");	assert (pdev != NULL);	assert (ent != NULL);	board_idx++;	if (!printed_version) {		printk (KERN_INFO RTL8139_DRIVER_NAME " loaded\n");		printed_version = 1;	}	i = rtl8139_init_board (pdev, &dev, &ioaddr);	if (i < 0) {		DPRINTK ("EXIT, returning %d\n", i);		return i;	}	tp = dev->priv;	assert (ioaddr != NULL);	assert (dev != NULL);	assert (tp != NULL);	init_crc32( dev );	addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;	for (i = 0; i < 3; i++)		((u16 *) (dev->dev_addr))[i] =		    le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));	/* The Rtl8139-specific entries in the device structure. */	if( rtl_chip_info[tp->chipset].name == "RTL-8139CP" ){		dev->open = rtl8139CP_open;		dev->hard_start_xmit = rtl8139CP_start_xmit;		dev->stop = rtl8139CP_close;		dev->tx_timeout = rtl8139CP_tx_timeout;		dev->features |= NETIF_F_IP_CSUM;	/* Can checksum only TCP/UDP over IPv4. */		printk (KERN_DEBUG "%s: Identified 8139CP chip type '%s'. Support TCP/UDP checksumOffload\n",dev->name,rtl_chip_info[tp->chipset].name);	}	else{		dev->open = rtl8139_open;		dev->hard_start_xmit = rtl8139_start_xmit;		dev->stop = rtl8139_close;		dev->tx_timeout = rtl8139_tx_timeout;		printk (KERN_DEBUG "%s:  Identified 8139CP chip type '%s'\n", dev->name, rtl_chip_info[tp->chipset].name);	}	dev->get_stats = rtl8139_get_stats;	dev->set_multicast_list = rtl8139_set_rx_mode;	dev->do_ioctl = mii_ioctl;	dev->watchdog_timeo = TX_TIMEOUT;	dev->irq = pdev->irq;	dev->base_addr = (unsigned long) ioaddr;	/* dev->priv/tp zeroed and aligned in init_etherdev */	tp = dev->priv;	/* note: tp->chipset set in rtl8139_init_board */	tp->drv_flags = board_info[ent->driver_data].hw_flags;	tp->pci_dev = pdev;	tp->mmio_addr = ioaddr;	spin_lock_init (&tp->lock);	pdev->driver_data = dev;	printk (KERN_INFO "%s: %s at 0x%lx, "		"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "		"IRQ %d\n",		dev->name,		board_info[ent->driver_data].name,		dev->base_addr,		dev->dev_addr[0], dev->dev_addr[1],		dev->dev_addr[2], dev->dev_addr[3],		dev->dev_addr[4], dev->dev_addr[5],		dev->irq);//	dev->tx_queue_len=500;	/* Find the connected MII xcvrs.	   Doing this in open() would allow detecting external xcvrs later, but	   takes too much time. */	if (tp->drv_flags & HAS_MII_XCVR) {		int phy, phy_idx = 0;		for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) {			int mii_status = mdio_read(dev, phy, 1);			if (mii_status != 0xffff  &&  mii_status != 0x0000) {				tp->phys[phy_idx++] = phy;				tp->advertising = mdio_read(dev, phy, 4);				printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x "					   "advertising %4.4x.\n",					   dev->name, phy, mii_status, tp->advertising);			}		}		if (phy_idx == 0) {			printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "				   "transceiver.\n",				   dev->name);			tp->phys[0] = 32;		}	} else		tp->phys[0] = 32;	/* Put the chip into low-power mode. */	RTL_W8_F (Cfg9346, Cfg9346_Unlock);	tmp = RTL_R8 (Config1) & Config1Clear;	tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */	RTL_W8_F (Config1, tmp);	RTL_W8_F (HltClk, 'H');	/* 'R' would leave the clock running. */	/* The lower four bits are the media type. */	option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];	tp->AutoNegoAbility = option&0xF;	if (option > 0) {		tp->full_duplex = (option & 0x210) ? 1 : 0;		tp->default_port = option & 0xFF;		if (tp->default_port)			tp->medialock = 1;	}	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)		tp->full_duplex = full_duplex[board_idx];	if (tp->full_duplex) {		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);		/* Changing the MII-advertised media because might prevent		   re-connection. */		tp->duplex_lock = 1;	}	if (tp->default_port) {		printk(KERN_INFO "%s: Forcing %dMbs %s-duplex operation.\n", dev->name,			   (option & 0x0C ? 100 : 10),			   (option & 0x0A ? "full" : "half"));		mdio_write(dev, tp->phys[0], 0,				   ((option & 0x20) ? 0x2000 : 0) | 	/* 100mbps? */				   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */	}#ifdef RTL8139_PROC_DEBUG	//-----------------------------------------------------------------------------	// Add proc file system	//-----------------------------------------------------------------------------	rtl8139_init_proc(dev);#endif	//#ifdef RTL8139_PROC_DEBUG	DPRINTK ("EXIT - returning 0\n");	return 0;}static void __devexit rtl8139_remove_one (struct pci_dev *pdev){	struct net_device *dev = pdev->driver_data;	struct rtl8139_private *np;	DPRINTK ("ENTER\n");	assert (dev != NULL);	np = (struct rtl8139_private *) (dev->priv);	assert (np != NULL);#ifndef USE_IO_OPS	iounmap (np->mmio_addr);	pci_release_regions (pdev);#endif /* !USE_IO_OPS */#ifdef RTL8139_PROC_DEBUG	//-----------------------------------------------------------------------------	// Remove proc file system	//-----------------------------------------------------------------------------	rtl8139_remove_proc(dev);#endif	//#ifdef RTL8139_PROC_DEBUG	unregister_netdev (dev);	pdev->driver_data = NULL;	pci_disable_device (pdev);	DPRINTK ("EXIT\n");}/* Serial EEPROM section. *//*  EEPROM_Ctrl bits. */#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */#define EE_CS			0x08	/* EEPROM chip select. */#define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */#define EE_WRITE_0		0x00#define EE_WRITE_1		0x02#define EE_DATA_READ	0x01	/* EEPROM chip data out. */#define EE_ENB			(0x80 | EE_CS)/* Delay between EEPROM clock transitions.   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. */#define eeprom_delay()	readl(ee_addr)/* The EEPROM commands include the alway-set leading bit. */#define EE_WRITE_CMD	(5)#define EE_READ_CMD		(6)#define EE_ERASE_CMD	(7)static int __devinit read_eeprom (void *ioaddr, int location, int addr_len){	int i;	unsigned retval = 0;	void *ee_addr = ioaddr + Cfg9346;	int read_cmd = location | (EE_READ_CMD << addr_len);	DPRINTK ("ENTER\n");	writeb (EE_ENB & ~EE_CS, ee_addr);	writeb (EE_ENB, ee_addr);	eeprom_delay ();	/* Shift the read command bits out. */	for (i = 4 + addr_len; i >= 0; i--) {		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;		writeb (EE_ENB | dataval, ee_addr);		eeprom_delay ();		writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);		eeprom_delay ();	}	writeb (EE_ENB, ee_addr);	eeprom_delay ();	for (i = 16; i > 0; i--) {		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);		eeprom_delay ();		retval =		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :				     0);		writeb (EE_ENB, ee_addr);		eeprom_delay ();	}	/* Terminate the EEPROM access. */	writeb (~EE_CS, ee_addr);	eeprom_delay ();	DPRINTK ("EXIT - returning %d\n", retval);	return retval;}/* MII serial management: mostly bogus for now. *//* Read and write the MII management registers using software-generated   serial MDIO protocol.   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually   met by back-to-back PCI I/O cycles, but we insert a delay to avoid   "overclocking" issues. */#define MDIO_DIR		0x80#define MDIO_DATA_OUT	0x04#define MDIO_DATA_IN	0x02#define MDIO_CLK		0x01#define MDIO_WRITE0 (MDIO_DIR)#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)

⌨️ 快捷键说明

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