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

📄 rtl8139.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
			pcibios_read_config_dword(pci_bus, pci_device_fn,									  PCI_BASE_ADDRESS_0, &pci_ioaddr);			ioaddr = pci_ioaddr & ~3;			irq = pci_irq_line;#endif		}		if ((pci_tbl[chip_idx].flags & PCI_USES_IO) &&			check_region(ioaddr, pci_tbl[chip_idx].io_size))			continue;		/* Activate the card: fix for brain-damaged Win98 BIOSes. */		pcibios_read_config_word(pci_bus, pci_device_fn,								 PCI_COMMAND, &pci_command);		new_command = pci_command | (pci_tbl[chip_idx].flags & 7);		if (pci_command != new_command) {#if 0			printk(KERN_INFO "  The PCI BIOS has not enabled the"				   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",				   pci_bus, pci_device_fn, pci_command, new_command);#else			/* enhance message outs , DennisK */                        printk(KERN_INFO "rtl8139:PCI BIOS has not enabled the"                                   " device at %x/%x! \n\t updating PCI command %4.4x->%4.4x.\n",                                   pci_bus, pci_device_fn, pci_command, new_command);#endif			pcibios_write_config_word(pci_bus, pci_device_fn,									  PCI_COMMAND, new_command);		}		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,									   irq, chip_idx, cards_found);		if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {			u8 pci_latency;			pcibios_read_config_byte(pci_bus, pci_device_fn,									 PCI_LATENCY_TIMER, &pci_latency);			if (pci_latency < 32) {				printk(KERN_NOTICE "  PCI latency timer (CFLT) is "					   "unreasonably low at %d.  Setting to 64 clocks.\n",					   pci_latency);				pcibios_write_config_byte(pci_bus, pci_device_fn,										  PCI_LATENCY_TIMER, 64);			}		}		dev = 0;		cards_found++;	}	return cards_found ? 0 : -ENODEV;}static inline u16 swap_bytes16(u16 source){	return ((source<<8) & 0xff00 ) | ((source >> 8) & 0x00ff) ;  }static struct device *rtl8129_probe1(int pci_bus, int pci_devfn,									 struct device *dev, long ioaddr,									 int irq, int chip_idx, int found_cnt){	static int did_version = 0;			/* Already printed version info. */	struct rtl8129_private *tp;	int i, option = found_cnt < MAX_UNITS ? options[found_cnt] : 0;	if (rtl8129_debug > 0  &&  did_version++ == 0)		printk(KERN_INFO "%s", version);	dev = init_etherdev(dev, 0);	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",		   dev->name, pci_tbl[chip_idx].name, ioaddr, irq);	/* Bring the chip out of low-power mode. */	outb(0x00, ioaddr + Config1);	{#if defined(__powerpc__)   		/* big endian */		int chip_code;		int addr_len;		chip_code = swap_bytes16(read_eeprom(ioaddr, 0, 8));		if(chip_code == 0x8129)  addr_len=8; 		else			 addr_len=6;  /* for 8139 */#else		/* little endian */		int addr_len = read_eeprom(ioaddr, 0, 8) == 0x8129 ? 8 : 6; #endif		for (i = 0; i < 3; i++)			((u16 *)(dev->dev_addr))[i] = 				swap_bytes16(read_eeprom(ioaddr, i+7, addr_len));	}	for (i = 0; i < 5; i++)		printk("%2.2x:", dev->dev_addr[i]);	printk("%2.2x.\n", dev->dev_addr[i]);	/* We do a request_region() to register /proc/ioports info. */	request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);	dev->base_addr = ioaddr;	dev->irq = irq;	/* Some data structures must be quadword aligned. */	tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);	memset(tp, 0, sizeof(*tp));	dev->priv = tp;	tp->next_module = root_rtl8129_dev;	root_rtl8129_dev = dev;	tp->chip_id = chip_idx;	tp->pci_bus = pci_bus;	tp->pci_devfn = pci_devfn;	/* Find the connected MII xcvrs.	   Doing this in open() would allow detecting external xcvrs later, but	   takes too much time. */	if (rtl_cap_tbl[chip_idx] & HAS_MII_XCVR) {		int phy, phy_idx;		for (phy = 0, phy_idx = 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;				printk(KERN_INFO "%s: MII transceiver found at address %d.\n",					   dev->name, phy);			}		}		if (phy_idx == 0) {			printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "				   "transceiver.\n",				   dev->name);			tp->phys[0] = -1;		}	} else		tp->phys[0] = 32;	/* Put the chip into low-power mode. */	outb(0xC0, ioaddr + Cfg9346);#if 0 /* ebony */	outb(0x03, ioaddr + Config1);#else	outb(0x8C, ioaddr + Config1);#endif#if 0 /* ebony */	outb('H', ioaddr + HltClk);		/* 'R' would leave the clock running. */#endif#if 0printk("chip_idx = %d\n", chip_idx); /* ebony */printk("tp->phys[0] = %d\n", tp->phys[0]); /* ebony */#endif	/* The lower four bits are the media type. */	if (option > 0) {		tp->full_duplex = (option & 0x200) ? 1 : 0;		tp->default_port = option & 15;		if (tp->default_port)			tp->medialock = 1;	}	if (found_cnt < MAX_UNITS  &&  full_duplex[found_cnt] > 0)		tp->full_duplex = full_duplex[found_cnt];	if (tp->full_duplex) {		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);		mdio_write(dev, tp->phys[0], 4, 0x141);		tp->duplex_lock = 1;	}	/* The Rtl8129-specific entries in the device structure. */	dev->open = &rtl8129_open;	dev->hard_start_xmit = &rtl8129_start_xmit;	dev->stop = &rtl8129_close;	dev->get_stats = &rtl8129_get_stats;	dev->set_multicast_list = &set_rx_mode;	dev->do_ioctl = &mii_ioctl;	return dev;}/* 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()	inl(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 read_eeprom(long ioaddr, int location, int addr_len){	int i;	unsigned retval = 0;	long ee_addr = ioaddr + Cfg9346;	int read_cmd = location | (EE_READ_CMD << addr_len);	outb(EE_ENB & ~EE_CS, ee_addr);	outb(EE_ENB, ee_addr);	/* Shift the read command bits out. */	for (i = 4 + addr_len; i >= 0; i--) {		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;		outb(EE_ENB | dataval, ee_addr);		eeprom_delay();		outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);		eeprom_delay();	}	outb(EE_ENB, ee_addr);	eeprom_delay();	for (i = 16; i > 0; i--) {		outb(EE_ENB | EE_SHIFT_CLK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0);		outb(EE_ENB, ee_addr);		eeprom_delay();	}	/* Terminate the EEPROM access. */	outb(~EE_CS, ee_addr);	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)#define mdio_delay()	inb(mdio_addr)static char mii_2_8139_map[8] = {MII_BMCR, MII_BMSR, 0, 0, NWayAdvert,								 NWayLPAR, NWayExpansion, 0 };/* Syncronize the MII management interface by shifting 32 one bits out. */static void mdio_sync(long mdio_addr){	int i;	for (i = 32; i >= 0; i--) {		outb(MDIO_WRITE1, mdio_addr);		mdio_delay();		outb(MDIO_WRITE1 | MDIO_CLK, mdio_addr);		mdio_delay();	}	return;}static int mdio_read(struct device *dev, int phy_id, int location){	long mdio_addr = dev->base_addr + MII_SMI;	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;	int retval = 0;	int i;	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */		return location < 8 && mii_2_8139_map[location] ?			inw(dev->base_addr + mii_2_8139_map[location]) : 0;	}	mdio_sync(mdio_addr);	/* Shift the read command bits out. */	for (i = 15; i >= 0; i--) {		int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;		outb(MDIO_DIR | dataval, mdio_addr);		mdio_delay();		outb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr);		mdio_delay();	}	/* Read the two transition, 16 data, and wire-idle bits. */	for (i = 19; i > 0; i--) {		outb(0, mdio_addr);		mdio_delay();		retval = (retval << 1) | ((inb(mdio_addr) & MDIO_DATA_IN) ? 1 : 0);		outb(MDIO_CLK, mdio_addr);		mdio_delay();	}	return (retval>>1) & 0xffff;}static void mdio_write(struct device *dev, int phy_id, int location, int value){	long mdio_addr = dev->base_addr + MII_SMI;	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;	int i;	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */		if (location < 8  &&  mii_2_8139_map[location])			outw(value, dev->base_addr + mii_2_8139_map[location]);		return;	}	mdio_sync(mdio_addr);	/* Shift the command bits out. */	for (i = 31; i >= 0; i--) {		int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;		outb(dataval, mdio_addr);		mdio_delay();		outb(dataval | MDIO_CLK, mdio_addr);		mdio_delay();	}	/* Clear out extra bits. */	for (i = 2; i > 0; i--) {		outb(0, mdio_addr);		mdio_delay();		outb(MDIO_CLK, mdio_addr);		mdio_delay();	}	return;}static intrtl8129_open(struct device *dev){	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;	long ioaddr = dev->base_addr;	int i;	/* Soft reset the chip. */	outb(CmdReset, ioaddr + ChipCmd);	if ((i=request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev))) {		printk("rtl8139: request_irq: failed irq=%d,errno=%d\n", dev->irq,i);		return -EAGAIN;	}	MOD_INC_USE_COUNT;	tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL);	tp->rx_ring = kmalloc(RX_BUF_LEN + 16, GFP_KERNEL);	if (tp->tx_bufs == NULL ||  tp->rx_ring == NULL) {		if (tp->tx_bufs)			kfree(tp->tx_bufs);		if (rtl8129_debug > 0)			printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n",				   dev->name, RX_BUF_LEN);		return -ENOMEM;	}	rtl8129_init_ring(dev);	/* Check that the chip has finished the reset. */	for (i = 1000; i > 0; i--)		if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)			break;	for (i = 0; i < 6; i++)		outb(dev->dev_addr[i], ioaddr + MAC0 + i);	/* Must enable Tx/Rx before setting transfer thresholds! */	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);	outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),		 ioaddr + RxConfig);	outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig);	tp->tx_flag = (TX_FIFO_THRESH<<11) & 0x003f0000;	tp->full_duplex = tp->duplex_lock;	if (tp->phys[0] >= 0  ||  (rtl_cap_tbl[tp->chip_id] & 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;		if (rtl8129_debug > 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);	}	outb(0xC0, ioaddr + Cfg9346);	outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);	outb(0x00, ioaddr + Cfg9346);	outl(virt_to_bus(tp->rx_ring), ioaddr + RxBuf);	/* Start the chip's Tx and Rx process. */	outl(0, ioaddr + RxMissed);	set_rx_mode(dev);	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);	dev->tbusy = 0;	dev->interrupt = 0;	dev->start = 1;	/* Enable all known interrupts by setting the interrupt mask. */

⌨️ 快捷键说明

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