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

📄 tulip.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
		for (i = 0; i < count; i++) {			struct medialeaf *leaf = &mtable->mleaf[i];			if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */				leaf->type = 0;				leaf->media = p[0] & 0x3f;				leaf->leafdata = p;				if ((p[2] & 0x61) == 0x01)	/* Bogus, but Znyx boards do it. */					mtable->has_mii = 1;				p += 4;			} else {				leaf->type = p[1];				if (p[1] == 0x05) {					mtable->has_reset = i;					leaf->media = p[2] & 0x0f;				} else if (p[1] & 1) {					mtable->has_mii = 1;					leaf->media = 11;				} else {					mtable->has_nonmii = 1;					leaf->media = p[2] & 0x0f;					switch (leaf->media) {					case 0: new_advertise |= 0x0020; break;					case 4: new_advertise |= 0x0040; break;					case 3: new_advertise |= 0x0080; break;					case 5: new_advertise |= 0x0100; break;					case 6: new_advertise |= 0x0200; break;					}					if (p[1] == 2  &&  leaf->media == 0) {						if (p[2] & 0x40) {							u32 base15 = get_unaligned((u16*)&p[7]);							mtable->csr15dir =								(get_unaligned((u16*)&p[9])<<16) + base15;							mtable->csr15val =								(get_unaligned((u16*)&p[11])<<16) + base15;						} else {							mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;							mtable->csr15val = get_unaligned((u16*)&p[5])<<16;						}					}				}				leaf->leafdata = p + 2;				p += (p[0] & 0x3f) + 1;			}			if (tulip_debug > 1  &&  leaf->media == 11) {				unsigned char *bp = leaf->leafdata;				printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "					   "sequences %d/%d long, capabilities %2.2x %2.2x.\n",					   dev->name, bp[0], bp[1], bp[2 + bp[1]*2],					   bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);			}			printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "				   "by a %s (%d) block.\n",				   dev->name, i, medianame[leaf->media], leaf->media,				   block_name[leaf->type], leaf->type);		}		if (new_advertise)			tp->to_advertise = new_advertise;	}}/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*//*  EEPROM_Ctrl bits. */#define EE_SHIFT_CLK	0x02	/* EEPROM shift clock. */#define EE_CS			0x01	/* EEPROM chip select. */#define EE_DATA_WRITE	0x04	/* Data from the Tulip to EEPROM. */#define EE_WRITE_0		0x01#define EE_WRITE_1		0x05#define EE_DATA_READ	0x08	/* Data from the EEPROM chip. */#define EE_ENB			(0x4800 | EE_CS)/* Delay between EEPROM clock transitions.   Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.   We add a bus turn-around to insure that this remains true. */#define eeprom_delay()	inl(ee_addr)/* The EEPROM commands include the alway-set leading bit. */#define EE_READ_CMD		(6)/* Note: this routine returns extra data bits for size detection. */static int read_eeprom(long ioaddr, int location, int addr_len){	int i;	unsigned retval = 0;	long ee_addr = ioaddr + CSR9;	int read_cmd = location | (EE_READ_CMD << addr_len);	outl(EE_ENB & ~EE_CS, ee_addr);	outl(EE_ENB, ee_addr);	/* Shift the read command bits out. */	for (i = 4 + addr_len; i >= 0; i--) {		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;		outl(EE_ENB | dataval, ee_addr);		eeprom_delay();		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);	}	outl(EE_ENB, ee_addr);	for (i = 16; i > 0; i--) {		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);		outl(EE_ENB, ee_addr);		eeprom_delay();	}	/* Terminate the EEPROM access. */	outl(EE_ENB & ~EE_CS, ee_addr);	return retval;}/* MII transceiver control section.   Read and write the MII registers using software-generated serial   MDIO protocol.  See the MII specifications or DP83840A data sheet   for details. *//* 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 or future 66Mhz PCI. */#define mdio_delay() inl(mdio_addr)/* Read and write the MII registers using software-generated serial   MDIO protocol.  It is just different enough from the EEPROM protocol   to not share code.  The maxium data clock rate is 2.5 Mhz. */#define MDIO_SHIFT_CLK	0x10000#define MDIO_DATA_WRITE0 0x00000#define MDIO_DATA_WRITE1 0x20000#define MDIO_ENB		0x00000		/* Ignore the 0x02000 databook setting. */#define MDIO_ENB_IN		0x40000#define MDIO_DATA_READ	0x80000static int mdio_read(struct device *dev, int phy_id, int location){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	int i;	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;	int retval = 0;	long ioaddr = dev->base_addr;	long mdio_addr = ioaddr + CSR9;	if (tp->chip_id == LC82C168) {		int i = 1000;		outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);		inl(ioaddr + 0xA0);		inl(ioaddr + 0xA0);		while (--i > 0)			if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))				return retval & 0xffff;		return 0xffff;	}	if (tp->chip_id == COMET) {		if (phy_id == 1) {			if (location < 7)				return inl(ioaddr + 0xB4 + (location<<2));			else if (location == 17)				return inl(ioaddr + 0xD0);			else if (location >= 29 && location <= 31)				return inl(ioaddr + 0xD4 + ((location-29)<<2));		}		return 0xffff;	}	/* Establish sync by sending at least 32 logic ones. */	for (i = 32; i >= 0; i--) {		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);		mdio_delay();		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Shift the read command bits out. */	for (i = 15; i >= 0; i--) {		int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;		outl(MDIO_ENB | dataval, mdio_addr);		mdio_delay();		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Read the two transition, 16 data, and wire-idle bits. */	for (i = 19; i > 0; i--) {		outl(MDIO_ENB_IN, mdio_addr);		mdio_delay();		retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	return (retval>>1) & 0xffff;}static void mdio_write(struct device *dev, int phy_id, int location, int value){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	int i;	int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;	long ioaddr = dev->base_addr;	long mdio_addr = ioaddr + CSR9;	if (tp->chip_id == LC82C168) {		int i = 1000;		outl(cmd, ioaddr + 0xA0);		do			if ( ! (inl(ioaddr + 0xA0) & 0x80000000))				break;		while (--i > 0);		return;	}	if (tp->chip_id == COMET) {		if (phy_id != 1)			return;		if (location < 7)			outl(value, ioaddr + 0xB4 + (location<<2));		else if (location == 17)			outl(value, ioaddr + 0xD0);		else if (location >= 29 && location <= 31)			outl(value, ioaddr + 0xD4 + ((location-29)<<2));		return;	}	/* Establish sync by sending 32 logic ones. */	for (i = 32; i >= 0; i--) {		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);		mdio_delay();		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Shift the command bits out. */	for (i = 31; i >= 0; i--) {		int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;		outl(MDIO_ENB | dataval, mdio_addr);		mdio_delay();		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Clear out extra bits. */	for (i = 2; i > 0; i--) {		outl(MDIO_ENB_IN, mdio_addr);		mdio_delay();		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	return;}static inttulip_open(struct device *dev){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	long ioaddr = dev->base_addr;	int next_tick = 3*HZ;	int i;	/* Wake the chip from sleep/snooze mode. */	if (tp->flags & HAS_PWRDWN)		pcibios_write_config_dword(tp->pci_bus, tp->pci_devfn, 0x40, 0);	/* On some chip revs we must set the MII/SYM port before the reset!? */	if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii))		outl(0x00040000, ioaddr + CSR6);	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */	outl(0x00000001, ioaddr + CSR0);	if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))		return -EAGAIN;	MOD_INC_USE_COUNT;	/* Deassert reset.	   Wait the specified 50 PCI cycles after a reset by initializing	   Tx and Rx queues and the address filter list. */	outl(tp->csr0, ioaddr + CSR0);	if (tulip_debug > 1)		printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq);	tulip_init_ring(dev);#if 0	if (tp->chip_id == PNIC2) {		u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));		u32 addr_high = cpu_to_le16(get_unaligned((u16 *)(dev->dev_addr+4)));		addr_high = (dev->dev_addr[4]<<8) + (dev->dev_addr[5]<<0);		outl((dev->dev_addr[0]<<8) + dev->dev_addr[1] +			 (dev->dev_addr[2]<<24) + (dev->dev_addr[3]<<16),			 ioaddr + 0xB0);		outl(addr_high + (addr_high<<16), ioaddr + 0xB8);	}#endif	if (tp->flags & MC_HASH_ONLY) {		u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));		u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));		if (tp->chip_id == AX88140) {			outl(0, ioaddr + CSR13);			outl(addr_low,  ioaddr + CSR14);			outl(1, ioaddr + CSR13);			outl(addr_high, ioaddr + CSR14);		} else if (tp->chip_id == COMET) {			outl(addr_low,  ioaddr + 0xA4);			outl(addr_high, ioaddr + 0xA8);			outl(0, ioaddr + 0xAC);			outl(0, ioaddr + 0xB0);		}	} else {		/* This is set_rx_mode(), but without starting the transmitter. */		u16 *eaddrs = (u16 *)dev->dev_addr;		u16 *setup_frm = &tp->setup_frame[15*6];		/* 21140 bug: you must add the broadcast address. */		memset(tp->setup_frame, 0xff, sizeof(tp->setup_frame));		/* Fill the final entry of the table with our physical address. */		*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];		*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];		*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];		/* Put the setup frame on the Tx list. */		tp->tx_ring[0].length = cpu_to_le32(0x08000000 | 192);		tp->tx_ring[0].buffer1 = virt_to_le32desc(tp->setup_frame);		tp->tx_ring[0].status = cpu_to_le32(DescOwned);		tp->cur_tx++;	}	outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);	outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);	tp->saved_if_port = dev->if_port;	if (dev->if_port == 0)		dev->if_port = tp->default_port;	/* Allow selecting a default media. */	i = 0;	if (tp->mtable == NULL)		goto media_picked;	if (dev->if_port) {		int looking_for = media_cap[dev->if_port] & MediaIsMII ? 11 :			(dev->if_port == 12 ? 0 : dev->if_port);		for (i = 0; i < tp->mtable->leafcount; i++)			if (tp->mtable->mleaf[i].media == looking_for) {				printk(KERN_INFO "%s: Using user-specified media %s.\n",					   dev->name, medianame[dev->if_port]);				goto media_picked;			}	}	if ((tp->mtable->defaultmedia & 0x0800) == 0) {		int looking_for = tp->mtable->defaultmedia & 15;		for (i = 0; i < tp->mtable->leafcount; i++)			if (tp->mtable->mleaf[i].media == looking_for) {				printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",					   dev->name, medianame[looking_for]);				goto media_picked;			}	}	/* Start sensing first non-full-duplex media. */	for (i = tp->mtable->leafcount - 1;		 (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)		;media_picked:	tp->csr6 = 0;	tp->cur_index = i;	tp->nwayset = 0;	if (dev->if_port == 0  && tp->chip_id == DC21041) {		tp->nway = 1;	}	if (dev->if_port == 0  &&  tp->chip_id == DC21142) {		if (tp->mii_cnt) {			select_media(dev, 1);			if (tulip_debug > 1)				printk(KERN_INFO "%s: Using MII transceiver %d, status "					   "%4.4x.\n",					   dev->name, tp->phys[0], mdio_read(dev, tp->phys[0], 1));			outl(0x82020000, ioaddr + CSR6);			tp->csr6 = 0x820E0000;			dev->if_port = 11;			outl(0x0000, ioaddr + CSR13);			outl(0x0000, ioaddr + CSR14);		} else			t21142_start_nway(dev);	} else if (tp->chip_id == PNIC2) {		t21142_start_nway(dev);	} else if (tp->chip_id == LC82C168  &&  ! tp->medialock) {

⌨️ 快捷键说明

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